Cryptocurrency Payment
About
This skill enables developers to integrate direct peer-to-peer cryptocurrency payments into applications, handling wallet interactions, payment processing, and blockchain confirmations. Use it when you need to accept crypto payments without intermediaries, supporting direct transfers, payment processors, and smart contracts. It provides the core logic for generating payment requests, monitoring transactions, and confirming settlements on-chain.
Quick Install
Claude Code
Recommended/plugin add https://github.com/majiayu000/claude-skill-registrygit clone https://github.com/majiayu000/claude-skill-registry.git ~/.claude/skills/Cryptocurrency PaymentCopy and paste this command in Claude Code to install this skill
Documentation
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 (
35-blockchain-web3/wallet-connection/) - User wallets - Smart Contracts (
35-blockchain-web3/smart-contracts/) - Contract payments - Payment Gateways (
30-ecommerce/payment-gateways/) - Payment patterns
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
Resources
GitHub Repository
Related Skills
sglang
MetaSGLang is a high-performance LLM serving framework that specializes in fast, structured generation for JSON, regex, and agentic workflows using its RadixAttention prefix caching. It delivers significantly faster inference, especially for tasks with repeated prefixes, making it ideal for complex, structured outputs and multi-turn conversations. Choose SGLang over alternatives like vLLM when you need constrained decoding or are building applications with extensive prefix sharing.
evaluating-llms-harness
TestingThis Claude Skill runs the lm-evaluation-harness to benchmark LLMs across 60+ standardized academic tasks like MMLU and GSM8K. It's designed for developers to compare model quality, track training progress, or report academic results. The tool supports various backends including HuggingFace and vLLM models.
langchain
MetaLangChain is a framework for building LLM applications using agents, chains, and RAG pipelines. It supports multiple LLM providers, offers 500+ integrations, and includes features like tool calling and memory management. Use it for rapid prototyping and deploying production systems like chatbots, autonomous agents, and question-answering services.
llamaguard
OtherLlamaGuard is Meta's 7-8B parameter model for moderating LLM inputs and outputs across six safety categories like violence and hate speech. It offers 94-95% accuracy and can be deployed using vLLM, Hugging Face, or Amazon SageMaker. Use this skill to easily integrate content filtering and safety guardrails into your AI applications.
