Claude-skill-registry Cryptocurrency Payment
Enabling direct peer-to-peer cryptocurrency transactions without intermediaries, including direct wallet payments, payment processors, transaction monitoring, and blockchain confirmation.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/cryptocurrency-payment" ~/.claude/skills/majiayu000-claude-skill-registry-cryptocurrency-payment && rm -rf "$T"
manifest:
skills/data/cryptocurrency-payment/SKILL.mdsource content
Cryptocurrency Payment
Current Level: Advanced
Domain: Blockchain / Payments
Overview
Cryptocurrency payments enable direct peer-to-peer transactions without intermediaries. This guide covers direct wallet payments, payment processors, and transaction monitoring for accepting crypto payments in applications.
Crypto Payment Concepts
Customer → Payment Request → Wallet → Blockchain → Confirmation → Order Complete
Payment Methods:
- Direct Wallet - Customer sends crypto directly
- Payment Processor - Third-party handles payments
- Smart Contract - Automated payment handling
Direct Wallet Payments
// services/crypto-payment.service.ts import { ethers } from 'ethers'; export class CryptoPaymentService { constructor( private provider: ethers.providers.Provider, private merchantAddress: string ) {} async createPaymentRequest( amount: string, currency: 'ETH' | 'USDC' | 'DAI' ): Promise<PaymentRequest> { const paymentId = this.generatePaymentId(); const expiresAt = Date.now() + 15 * 60 * 1000; // 15 minutes return { paymentId, merchantAddress: this.merchantAddress, amount, currency, expiresAt, status: 'pending' }; } async monitorPayment( paymentId: string, expectedAmount: string ): Promise<PaymentStatus> { const filter = { address: this.merchantAddress, topics: [] }; return new Promise((resolve) => { this.provider.on(filter, async (log) => { const tx = await this.provider.getTransaction(log.transactionHash); if (tx.to === this.merchantAddress) { const receivedAmount = ethers.utils.formatEther(tx.value); if (receivedAmount === expectedAmount) { resolve({ paymentId, status: 'confirmed', transactionHash: tx.hash, amount: receivedAmount }); } } }); }); } async verifyPayment( transactionHash: string, expectedAmount: string ): Promise<boolean> { const receipt = await this.provider.getTransactionReceipt(transactionHash); if (!receipt || receipt.status !== 1) { return false; } const tx = await this.provider.getTransaction(transactionHash); const receivedAmount = ethers.utils.formatEther(tx.value); return ( tx.to === this.merchantAddress && receivedAmount === expectedAmount && receipt.confirmations >= 3 ); } private generatePaymentId(): string { return `pay_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } } interface PaymentRequest { paymentId: string; merchantAddress: string; amount: string; currency: string; expiresAt: number; status: 'pending' | 'confirmed' | 'expired'; } interface PaymentStatus { paymentId: string; status: string; transactionHash: string; amount: string; }
Payment Processors
Coinbase Commerce
// services/coinbase-commerce.service.ts import axios from 'axios'; export class CoinbaseCommerceService { private apiKey = process.env.COINBASE_COMMERCE_API_KEY!; private baseUrl = 'https://api.commerce.coinbase.com'; async createCharge(data: CreateChargeDto): Promise<Charge> { const response = await axios.post( `${this.baseUrl}/charges`, { name: data.name, description: data.description, pricing_type: 'fixed_price', local_price: { amount: data.amount, currency: data.currency }, metadata: data.metadata }, { headers: { 'X-CC-Api-Key': this.apiKey, 'X-CC-Version': '2018-03-22' } } ); return response.data.data; } async getCharge(chargeId: string): Promise<Charge> { const response = await axios.get( `${this.baseUrl}/charges/${chargeId}`, { headers: { 'X-CC-Api-Key': this.apiKey, 'X-CC-Version': '2018-03-22' } } ); return response.data.data; } async listCharges(): Promise<Charge[]> { const response = await axios.get( `${this.baseUrl}/charges`, { headers: { 'X-CC-Api-Key': this.apiKey, 'X-CC-Version': '2018-03-22' } } ); return response.data.data; } verifyWebhook(signature: string, payload: string): boolean { const crypto = require('crypto'); const webhookSecret = process.env.COINBASE_WEBHOOK_SECRET!; const expectedSignature = crypto .createHmac('sha256', webhookSecret) .update(payload) .digest('hex'); return signature === expectedSignature; } } interface CreateChargeDto { name: string; description: string; amount: string; currency: string; metadata?: Record<string, any>; } interface Charge { id: string; code: string; name: string; description: string; hosted_url: string; pricing: { local: { amount: string; currency: string }; bitcoin?: { amount: string; currency: string }; ethereum?: { amount: string; currency: string }; }; payments: Payment[]; timeline: TimelineEvent[]; } interface Payment { network: string; transaction_id: string; status: string; value: { local: { amount: string; currency: string }; crypto: { amount: string; currency: string }; }; } interface TimelineEvent { time: string; status: string; }
NOWPayments
// services/nowpayments.service.ts export class NOWPaymentsService { private apiKey = process.env.NOWPAYMENTS_API_KEY!; private baseUrl = 'https://api.nowpayments.io/v1'; async createPayment(data: CreatePaymentDto): Promise<Payment> { const response = await axios.post( `${this.baseUrl}/payment`, { price_amount: data.amount, price_currency: data.currency, pay_currency: data.payCurrency, order_id: data.orderId, order_description: data.description, ipn_callback_url: data.callbackUrl }, { headers: { 'x-api-key': this.apiKey } } ); return response.data; } async getPaymentStatus(paymentId: string): Promise<PaymentStatus> { const response = await axios.get( `${this.baseUrl}/payment/${paymentId}`, { headers: { 'x-api-key': this.apiKey } } ); return response.data; } async getAvailableCurrencies(): Promise<string[]> { const response = await axios.get( `${this.baseUrl}/currencies`, { headers: { 'x-api-key': this.apiKey } } ); return response.data.currencies; } async getEstimatedPrice( amount: number, fromCurrency: string, toCurrency: string ): Promise<EstimatedPrice> { const response = await axios.get( `${this.baseUrl}/estimate`, { params: { amount, currency_from: fromCurrency, currency_to: toCurrency }, headers: { 'x-api-key': this.apiKey } } ); return response.data; } } interface CreatePaymentDto { amount: number; currency: string; payCurrency: string; orderId: string; description: string; callbackUrl: string; } interface EstimatedPrice { currency_from: string; currency_to: string; estimated_amount: string; }
Transaction Monitoring
// services/transaction-monitor.service.ts export class TransactionMonitorService { private provider: ethers.providers.Provider; constructor(provider: ethers.providers.Provider) { this.provider = provider; } async waitForConfirmations( txHash: string, confirmations: number = 3 ): Promise<ethers.providers.TransactionReceipt> { const receipt = await this.provider.waitForTransaction(txHash, confirmations); return receipt; } async getTransactionStatus(txHash: string): Promise<TransactionStatus> { const [tx, receipt] = await Promise.all([ this.provider.getTransaction(txHash), this.provider.getTransactionReceipt(txHash) ]); if (!receipt) { return { status: 'pending', confirmations: 0 }; } const currentBlock = await this.provider.getBlockNumber(); const confirmations = currentBlock - receipt.blockNumber + 1; return { status: receipt.status === 1 ? 'confirmed' : 'failed', confirmations, blockNumber: receipt.blockNumber, gasUsed: receipt.gasUsed.toString() }; } monitorAddress( address: string, callback: (tx: ethers.providers.TransactionResponse) => void ): () => void { const filter = { address, topics: [] }; const listener = async (log: ethers.providers.Log) => { const tx = await this.provider.getTransaction(log.transactionHash); if (tx.to === address) { callback(tx); } }; this.provider.on(filter, listener); return () => { this.provider.off(filter, listener); }; } } interface TransactionStatus { status: 'pending' | 'confirmed' | 'failed'; confirmations: number; blockNumber?: number; gasUsed?: string; }
Payment Confirmation
// services/payment-confirmation.service.ts export class PaymentConfirmationService { async confirmPayment( transactionHash: string, expectedAmount: string, expectedRecipient: string ): Promise<ConfirmationResult> { const provider = new ethers.providers.InfuraProvider('mainnet'); // Wait for confirmations const receipt = await provider.waitForTransaction(transactionHash, 3); if (receipt.status !== 1) { return { confirmed: false, reason: 'Transaction failed' }; } // Verify transaction details const tx = await provider.getTransaction(transactionHash); if (tx.to?.toLowerCase() !== expectedRecipient.toLowerCase()) { return { confirmed: false, reason: 'Incorrect recipient' }; } const receivedAmount = ethers.utils.formatEther(tx.value); if (receivedAmount !== expectedAmount) { return { confirmed: false, reason: 'Incorrect amount' }; } return { confirmed: true, transactionHash, amount: receivedAmount, confirmations: receipt.confirmations }; } } interface ConfirmationResult { confirmed: boolean; reason?: string; transactionHash?: string; amount?: string; confirmations?: number; }
Multi-Currency Support
// services/multi-currency.service.ts export class MultiCurrencyService { private supportedCurrencies = ['ETH', 'BTC', 'USDC', 'USDT', 'DAI']; async getExchangeRate(from: string, to: string): Promise<number> { // Use CoinGecko API const response = await fetch( `https://api.coingecko.com/api/v3/simple/price?ids=${from}&vs_currencies=${to}` ); const data = await response.json(); return data[from.toLowerCase()][to.toLowerCase()]; } async convertAmount( amount: number, from: string, to: string ): Promise<number> { const rate = await this.getExchangeRate(from, to); return amount * rate; } async getPriceInCrypto( usdAmount: number, cryptocurrency: string ): Promise<string> { const cryptoAmount = await this.convertAmount(usdAmount, 'usd', cryptocurrency); return cryptoAmount.toFixed(8); } }
Webhook Handling
// pages/api/webhooks/coinbase.ts import type { NextApiRequest, NextApiResponse } from 'next'; import crypto from 'crypto'; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }); } // Verify webhook signature const signature = req.headers['x-cc-webhook-signature'] as string; const payload = JSON.stringify(req.body); if (!verifySignature(signature, payload)) { return res.status(401).json({ error: 'Invalid signature' }); } const event = req.body; // Handle different event types switch (event.type) { case 'charge:confirmed': await handleChargeConfirmed(event.data); break; case 'charge:failed': await handleChargeFailed(event.data); break; case 'charge:pending': await handleChargePending(event.data); break; } res.json({ success: true }); } function verifySignature(signature: string, payload: string): boolean { const webhookSecret = process.env.COINBASE_WEBHOOK_SECRET!; const expectedSignature = crypto .createHmac('sha256', webhookSecret) .update(payload) .digest('hex'); return signature === expectedSignature; } async function handleChargeConfirmed(data: any): Promise<void> { // Update order status await db.order.update({ where: { id: data.metadata.order_id }, data: { status: 'paid', transactionHash: data.payments[0].transaction_id } }); // Send confirmation email await emailService.sendOrderConfirmation(data.metadata.order_id); } async function handleChargeFailed(data: any): Promise<void> { await db.order.update({ where: { id: data.metadata.order_id }, data: { status: 'payment_failed' } }); } async function handleChargePending(data: any): Promise<void> { await db.order.update({ where: { id: data.metadata.order_id }, data: { status: 'payment_pending' } }); }
Quick Start
Payment Request
interface PaymentRequest { orderId: string amount: number // in crypto (e.g., 0.01 ETH) currency: 'ETH' | 'BTC' | 'USDT' recipientAddress: string } async function createPaymentRequest(request: PaymentRequest) { const payment = await db.payments.create({ data: { orderId: request.orderId, amount: request.amount, currency: request.currency, recipientAddress: request.recipientAddress, status: 'pending', expiresAt: addMinutes(new Date(), 15) // 15 min expiry } }) return { address: request.recipientAddress, amount: request.amount, currency: request.currency, qrCode: generateQRCode(`${request.currency}:${request.recipientAddress}?amount=${request.amount}`) } }
Transaction Monitoring
async function monitorTransaction(txHash: string) { const provider = new ethers.providers.JsonRpcProvider(RPC_URL) // Wait for confirmations const receipt = await provider.waitForTransaction(txHash, 3) // 3 confirmations if (receipt.status === 1) { await updatePaymentStatus(txHash, 'confirmed') } else { await updatePaymentStatus(txHash, 'failed') } }
Production Checklist
- Wallet Integration: Support multiple wallets
- Payment Processing: Payment processor or direct wallet
- Transaction Monitoring: Monitor blockchain transactions
- Confirmations: Wait for multiple confirmations
- Amount Verification: Verify exact payment amount
- Address Verification: Verify recipient address
- Expiry: Payment request expiry
- Refunds: Refund process
- Security: Secure private keys
- Testing: Test on testnets first
- Compliance: Follow local regulations
- Documentation: Document payment flow
Anti-patterns
❌ Don't: No Confirmations
// ❌ Bad - Accept after 1 confirmation const receipt = await provider.waitForTransaction(txHash, 1) await completeOrder(orderId) // Too risky!
// ✅ Good - Wait for multiple confirmations const receipt = await provider.waitForTransaction(txHash, 3) // 3 confirmations await completeOrder(orderId) // Safer
❌ Don't: Store Private Keys
// ❌ Bad - Store private keys const wallet = new ethers.Wallet('0x...private-key...') // Exposed!
// ✅ Good - Use payment processor // Or hardware wallet // Never store private keys in code
Integration Points
- Wallet Connection (
) - User wallets35-blockchain-web3/wallet-connection/ - Smart Contracts (
) - Contract payments35-blockchain-web3/smart-contracts/ - Payment Gateways (
) - Payment patterns30-ecommerce/payment-gateways/
Further Reading
Best Practices
- Confirmations - Wait for multiple confirmations
- Amount Verification - Verify exact payment amount
- Address Verification - Verify recipient address
- Webhook Security - Verify webhook signatures
- Timeout Handling - Set payment expiration times
- Multi-Currency - Support multiple cryptocurrencies
- Price Updates - Update crypto prices regularly
- Refunds - Implement refund mechanism
- Testing - Test on testnets first
- Compliance - Follow local regulations