swapped-commerce-sdk
v1.0.4
Published
TypeScript SDK for Swapped Commerce Integration API - Functional, performant, and fully typed
Maintainers
Readme
Swapped Commerce SDK
A high-performance, type-safe TypeScript SDK for the Swapped Commerce API. Built with functional programming principles, Bun-native optimizations, and comprehensive type coverage.
Table of Contents
- Overview
- Features
- Installation
- Quick Start
- Configuration
- API Reference
- Webhooks
- Error Handling
- TypeScript Support
- Examples
- Testing
- Performance
- Requirements
- Documentation
- License
Overview
The Swapped Commerce SDK provides a robust, type-safe interface for integrating cryptocurrency payment processing into your applications. Designed with performance and developer experience in mind, it leverages modern TypeScript features and Bun's native capabilities to deliver a seamless integration experience.
Key Design Principles:
- Type Safety: Complete TypeScript coverage with zero tolerance for
anytypes - Functional Architecture: Pure functions with immutable data structures
- Performance First: Minimal allocations and efficient data handling
- Bun-Native: Leverages Bun's built-in APIs for optimal performance
- Developer Experience: Intuitive API design with comprehensive error handling
Features
- Complete Type Coverage: Every API response and parameter is fully typed
- Functional Programming: Pure functions with no hidden side effects
- Automatic Retry Logic: Exponential backoff for transient failures
- Webhook Verification: Secure signature validation using Web Crypto API
- Comprehensive Error Handling: Typed error classes for all failure scenarios
- Zero Runtime Dependencies: Uses only Bun's built-in capabilities
- Immutable Data Structures: All types are readonly for safety
Installation
Using Bun (Recommended)
bun add swapped-commerce-sdkUsing npm
npm install swapped-commerce-sdkUsing yarn
yarn add swapped-commerce-sdkUsing pnpm
pnpm add swapped-commerce-sdkQuick Start
import { createClient } from 'swapped-commerce-sdk'
// Initialize the client
const client = createClient({
apiKey: process.env.SWAPPED_API_KEY!,
environment: 'sandbox',
})
// Create a payment link
const response = await client.paymentLinks.create({
purchase: {
name: 'Premium Subscription',
price: '99.99',
currency: 'USD',
},
metadata: {
customerEmail: '[email protected]',
},
})
if (response.success) {
console.log('Payment link:', response.data.paymentLink)
console.log('Order ID:', response.data.orderId)
}Configuration
The SDK accepts a configuration object with the following options:
import { createClient, type SwappedConfig } from 'swapped-commerce-sdk'
const config: SwappedConfig = {
apiKey: 'your-api-key-here', // Required: Your Swapped API key
environment: 'sandbox', // Optional: 'sandbox' | 'production' (default: 'production')
timeout: 30000, // Optional: Request timeout in milliseconds (default: 30000)
retries: 3, // Optional: Number of retry attempts (default: 3)
}
const client = createClient(config)Environment Variables
For production applications, it's recommended to use environment variables:
const client = createClient({
apiKey: process.env.SWAPPED_API_KEY!,
environment: process.env.NODE_ENV === 'production' ? 'production' : 'sandbox',
timeout: parseInt(process.env.SWAPPED_TIMEOUT ?? '30000', 10),
retries: parseInt(process.env.SWAPPED_RETRIES ?? '3', 10),
})API Reference
Orders
The Orders API allows you to manage customer orders, track payment status, and process refunds.
List Orders
Retrieve a paginated list of orders with optional filtering:
const response = await client.orders.list({
page: 1,
limit: 10,
type: 'PAYMENT_ROUTE',
searchId: 'order_123',
startDate: Date.now() - 7 * 24 * 60 * 60 * 1000, // Last 7 days
endDate: Date.now(),
})
if (response.success) {
console.log(`Found ${response.data.pagination.totalItems} orders`)
for (const order of response.data.orders) {
console.log(`Order ${order.id}: ${order.status}`)
console.log(`Amount: ${order.quote.toAmount.amount} ${order.quote.toAmount.currency.symbol}`)
}
}Get Order
Retrieve detailed information about a specific order:
const response = await client.orders.get('order_123')
if (response.success) {
const order = response.data
console.log('Order Details:')
console.log(` ID: ${order.id}`)
console.log(` Status: ${order.status}`)
console.log(` Created: ${order.createdAt}`)
console.log(` Expires: ${order.expiresAt}`)
console.log(` Payment Address: ${order.depositAddress.address}`)
if (order.payments.length > 0) {
console.log('Payments:')
for (const payment of order.payments) {
console.log(` ${payment.receivedAmount} ${payment.receivedCurrency.symbol} - ${payment.status}`)
}
}
}Refund Order
Process a refund for a completed order:
const response = await client.orders.refund('order_123', {
amount: '50.00', // Optional: Partial refund amount
reason: 'Customer requested refund', // Optional: Refund reason
})
if (response.success) {
console.log(`Refund initiated: ${response.data.refundId}`)
}Note: Refunds require sufficient balance in the order's currency.
Payment Links
Generate shareable payment links for customers to complete cryptocurrency payments.
Create Payment Link
const response = await client.paymentLinks.create({
purchase: {
name: 'Premium Subscription',
description: 'Monthly subscription to premium features',
notes: 'Includes access to all premium features',
price: '99.99',
currency: 'USD',
imageUrl: 'https://example.com/product-image.jpg', // Optional
},
metadata: {
externalId: 'internal_order_456', // Optional: Your internal order ID
customerId: 'customer_789', // Optional: Customer identifier
customerEmail: '[email protected]', // Optional: Customer email
customerName: 'John Doe', // Optional: Customer name
customerCountry: 'US', // Optional: Customer country
customerLang: 'en', // Optional: Customer language
redirectUrl: 'https://example.com/success', // Optional: Redirect after payment
},
testMode: false, // Optional: Enable test mode
preferredPayCurrency: { // Optional: Preferred cryptocurrency
symbol: 'BTC',
blockchain: 'bitcoin',
},
})
if (response.success) {
console.log('Payment link created:')
console.log(` Link: ${response.data.paymentLink}`)
console.log(` Order ID: ${response.data.orderId}`)
// Share the payment link with your customer
sendEmailToCustomer(response.data.paymentLink)
}Payment Routes
Create direct payment routes for programmatic integration with deposit addresses.
Create Payment Route
const response = await client.paymentRoutes.create({
purchaseAmount: '99.99',
purchaseCurrency: 'USD',
preferredPayCurrency: 'BTC', // Optional: Preferred cryptocurrency
externalId: 'order_123', // Optional: Your internal order ID
customerId: 'customer_456', // Optional: Customer identifier
metadata: { // Optional: Additional metadata
invoiceNumber: 'INV-2024-001',
productId: 'prod_123',
},
})
if (response.success) {
console.log('Payment route created:')
console.log(` Order ID: ${response.data.orderId}`)
console.log(` Deposit Address: ${response.data.depositAddress.address}`)
console.log(` Supported Currencies: ${response.data.depositAddress.supportedCurrencies.map(c => c.symbol).join(', ')}`)
console.log(` Quote: ${response.data.quote.toAmount.amount} ${response.data.quote.toAmount.currency.symbol}`)
// Display deposit address to customer
displayPaymentInstructions(response.data.depositAddress, response.data.quote)
}Payments
Retrieve payment information and transaction details.
Get Payment
const response = await client.payments.get('payment_123')
if (response.success) {
const payment = response.data
console.log('Payment Details:')
console.log(` ID: ${payment.id}`)
console.log(` Order ID: ${payment.orderId}`)
console.log(` Amount: ${payment.receivedAmount} ${payment.receivedCurrency.symbol}`)
console.log(` Status: ${payment.status}`)
console.log(` Transaction Hash: ${payment.txHash}`)
console.log(` Confirmed At: ${payment.confirmedAt}`)
console.log(` Deposit Address: ${payment.depositAddress.address}`)
}Balances
Monitor your merchant cryptocurrency balances for settlements and refunds.
List Balances
Retrieve all available balances:
const response = await client.balances.list({
currency: 'BTC', // Optional: Filter by currency
blockchain: 'bitcoin', // Optional: Filter by blockchain
})
if (response.success) {
console.log('Account Balances:')
for (const balance of response.data.balances) {
console.log(`${balance.currency.symbol} (${balance.currency.name}):`)
console.log(` Available: ${balance.available}`)
console.log(` Pending: ${balance.pending}`)
console.log(` Total: ${balance.total}`)
console.log(` Last Updated: ${balance.lastUpdated}`)
}
}Get Balance
Retrieve balance for a specific currency:
const response = await client.balances.get('BTC')
if (response.success) {
const balance = response.data
console.log(`BTC Balance:`)
console.log(` Available: ${balance.available} BTC`)
console.log(` Pending: ${balance.pending} BTC`)
console.log(` Total: ${balance.total} BTC`)
}Quotes
Obtain real-time conversion rates for cryptocurrency and fiat currency pairs.
Get Quote
Retrieve a quote for currency conversion:
const response = await client.quotes.get({
fromCurrency: 'BTC',
toCurrency: 'USD',
amount: '1.0',
amountType: 'FROM', // 'FROM' | 'TO' - specifies which currency the amount refers to
})
if (response.success) {
const quote = response.data.quote
console.log('Conversion Quote:')
console.log(` From: ${quote.fromAmount.amount} ${quote.fromAmount.currency.symbol}`)
console.log(` To: ${quote.toAmount.amount} ${quote.toAmount.currency.symbol}`)
console.log(` Exchange Rate ID: ${quote.exchangeRateSnapshotId}`)
console.log(` Expires: ${response.data.expiresAt}`)
if (quote.fees.length > 0) {
console.log(' Fees:')
for (const fee of quote.fees) {
console.log(` ${fee.label}: ${fee.amount} ${fee.currency.symbol}`)
}
}
}Payouts
Initiate withdrawals to bank accounts or cryptocurrency wallets.
Create Payout
Bank Account Payout:
const response = await client.payouts.create({
amount: '1000.00',
currency: 'USD',
destinationType: 'BANK',
destination: {
accountNumber: '1234567890',
routingNumber: '987654321', // Required for US accounts
accountHolderName: 'John Doe',
// For international accounts, use:
// iban: 'GB82WEST12345698765432',
// swift: 'NWBKGB2L',
},
reference: 'Monthly payout - January 2024', // Optional: Internal reference
})
if (response.success) {
console.log('Bank payout initiated:')
console.log(` Payout ID: ${response.data.payoutId}`)
console.log(` Status: ${response.data.status}`)
console.log(` Estimated Arrival: ${response.data.estimatedArrival}`)
}Cryptocurrency Payout:
const response = await client.payouts.create({
amount: '0.5',
currency: 'BTC',
destinationType: 'CRYPTO',
destination: {
address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
blockchain: 'bitcoin',
memo: 'Payment for invoice #123', // Optional: Memo for supported blockchains
},
reference: 'Customer withdrawal',
})
if (response.success) {
console.log('Crypto payout initiated:')
console.log(` Payout ID: ${response.data.payoutId}`)
console.log(` Status: ${response.data.status}`)
}List Payouts
Retrieve a paginated list of payouts:
const response = await client.payouts.list({
page: 1,
limit: 20,
})
if (response.success) {
console.log(`Total Payouts: ${response.data.pagination.totalItems}`)
for (const payout of response.data.payouts) {
console.log(`Payout ${payout.id}:`)
console.log(` Amount: ${payout.amount} ${payout.currency.symbol}`)
console.log(` Status: ${payout.status}`)
console.log(` Created: ${payout.createdAt}`)
if (payout.completedAt) {
console.log(` Completed: ${payout.completedAt}`)
}
if (payout.failureReason) {
console.log(` Failure: ${payout.failureReason}`)
}
}
}Get Payout
Retrieve detailed information about a specific payout:
const response = await client.payouts.get('payout_123')
if (response.success) {
const payout = response.data
console.log('Payout Details:')
console.log(` ID: ${payout.id}`)
console.log(` Amount: ${payout.amount} ${payout.currency.symbol}`)
console.log(` Status: ${payout.status}`)
console.log(` Destination:`, payout.destination)
console.log(` Created: ${payout.createdAt}`)
if (payout.status === 'COMPLETED' && payout.completedAt) {
console.log(` Completed: ${payout.completedAt}`)
} else if (payout.status === 'FAILED' && payout.failureReason) {
console.log(` Failure Reason: ${payout.failureReason}`)
}
}KYC Management
Manage customer Know Your Customer (KYC) verification status and submissions.
Get KYC Status
Check the verification status for a customer:
const response = await client.kyc.getStatus('customer_123')
if (response.success) {
const status = response.data
console.log(`KYC Status for ${status.customerId}:`)
console.log(` Status: ${status.status}`)
if (status.submittedAt) {
console.log(` Submitted: ${status.submittedAt}`)
}
if (status.reviewedAt) {
console.log(` Reviewed: ${status.reviewedAt}`)
}
if (status.rejectionReason) {
console.log(` Rejection Reason: ${status.rejectionReason}`)
}
}Submit KYC
Submit KYC information for customer verification:
const response = await client.kyc.submit({
customerId: 'customer_123',
firstName: 'John',
lastName: 'Doe',
dateOfBirth: '1990-01-01',
nationality: 'US',
address: {
street: '123 Main Street',
city: 'New York',
state: 'NY',
postalCode: '10001',
country: 'US',
},
documents: [
{
type: 'PASSPORT',
frontImage: 'data:image/jpeg;base64,/9j/4AAQSkZJRg...', // Base64 encoded image
},
{
type: 'PROOF_OF_ADDRESS',
frontImage: 'data:image/jpeg;base64,/9j/4AAQSkZJRg...',
},
],
})
if (response.success) {
console.log(`KYC submission created: ${response.data.submissionId}`)
console.log(`Status: ${response.data.status}`)
}Webhooks
Webhooks provide real-time notifications for order and payment events. The SDK includes utilities for verifying webhook signatures and parsing event payloads.
Webhook Event Types
The following event types are supported:
- ORDER_CREATED: A new order has been created
- PAYMENT_RECEIVED: Payment has been received for an order
- ORDER_COMPLETED: Order has been completed successfully
- SETTLEMENT_CREATED: A settlement has been created
- PAYMENT_CONVERSION_SETTLED: Payment conversion has been settled
Verifying Webhook Signatures
Always verify webhook signatures to ensure requests are authentic:
import { verifyWebhookSignature, parseWebhookEvent } from 'swapped-commerce-sdk'
async function handleWebhook(request: Request): Promise<Response> {
// Extract signature from headers
const signature = request.headers.get('X-Signature') ?? ''
const payload = await request.text()
const webhookSecret = process.env.WEBHOOK_SECRET!
// Verify signature
const isValid = await verifyWebhookSignature(payload, signature, webhookSecret)
if (!isValid) {
return new Response('Invalid signature', { status: 401 })
}
// Parse and handle event
const event = parseWebhookEvent(payload)
switch (event.event_type) {
case 'ORDER_CREATED':
await handleOrderCreated(event)
break
case 'PAYMENT_RECEIVED':
await handlePaymentReceived(event)
break
case 'ORDER_COMPLETED':
await handleOrderCompleted(event)
break
case 'SETTLEMENT_CREATED':
await handleSettlementCreated(event)
break
case 'PAYMENT_CONVERSION_SETTLED':
await handleConversionSettled(event)
break
}
return new Response('OK', { status: 200 })
}
async function handleOrderCreated(event: WebhookEvent) {
console.log(`New order created: ${event.order_id}`)
console.log(`Purchase amount: ${event.order_purchase_amount} ${event.order_purchase_currency}`)
// Update your database, send notifications, etc.
}
async function handlePaymentReceived(event: WebhookEvent) {
console.log(`Payment received for order: ${event.order_id}`)
console.log(`Crypto amount: ${event.order_crypto_amount} ${event.order_crypto}`)
console.log(`Network: ${event.network}`)
// Process payment, update order status, etc.
}
async function handleOrderCompleted(event: WebhookEvent) {
console.log(`Order completed: ${event.order_id}`)
// Fulfill order, send confirmation email, etc.
}Webhook Server Example
Complete example using Bun's built-in server:
import { createClient, verifyWebhookSignature, parseWebhookEvent } from 'swapped-commerce-sdk'
Bun.serve({
port: 3000,
async fetch(request) {
if (request.method === 'POST' && new URL(request.url).pathname === '/webhook') {
return await handleWebhook(request)
}
return new Response('Not Found', { status: 404 })
},
})
console.log('Webhook server listening on http://localhost:3000/webhook')Error Handling
The SDK provides typed error classes for different error scenarios, enabling precise error handling in your application.
Error Classes
import {
SwappedError,
SwappedAuthenticationError,
SwappedValidationError,
SwappedRateLimitError,
SwappedNotFoundError,
} from 'swapped-commerce-sdk'Error Handling Example
try {
const response = await client.orders.get('invalid_order')
} catch (error) {
if (error instanceof SwappedNotFoundError) {
console.error('Order not found')
// Handle not found case
} else if (error instanceof SwappedAuthenticationError) {
console.error('Authentication failed - check your API key')
// Handle authentication error
} else if (error instanceof SwappedValidationError) {
console.error('Validation error:', error.details)
// Handle validation error
} else if (error instanceof SwappedRateLimitError) {
console.error('Rate limit exceeded - please retry later')
// Implement retry logic with backoff
} else if (error instanceof SwappedError) {
console.error(`API error (${error.statusCode}): ${error.message}`)
if (error.details) {
console.error('Details:', error.details)
}
// Handle generic API error
} else {
console.error('Unknown error:', error)
// Handle unexpected errors
}
}Error Properties
All error classes extend SwappedError and include:
message: Human-readable error messagestatusCode: HTTP status code (if applicable)code: Error code stringdetails: Additional error details (if available)
TypeScript Support
The SDK is fully typed with comprehensive TypeScript definitions. All types are exported and can be imported for use in your application.
Type Imports
import type {
// Core types
SwappedConfig,
SwappedClient,
ApiResponse,
// Order types
Order,
OrderStatus,
OrdersResponse,
// Payment types
Payment,
PaymentLinkResponse,
PaymentRouteResponse,
// Balance types
Balance,
BalancesResponse,
// Quote types
Quote,
QuoteResponse,
// Payout types
Payout,
CreatePayoutResponse,
PayoutsResponse,
// KYC types
KYCStatusResponse,
SubmitKYCResponse,
// Webhook types
WebhookEvent,
WebhookEventType,
} from 'swapped-commerce-sdk'Type Safety Example
import type { Order, OrderStatus } from 'swapped-commerce-sdk'
function processOrder(order: Order) {
// TypeScript knows all properties of Order
console.log(order.id)
console.log(order.status)
console.log(order.quote.toAmount.amount)
// Type-safe status checking
const isCompleted = (status: OrderStatus): boolean => {
return status === 'COMPLETED'
}
if (isCompleted(order.status)) {
fulfillOrder(order)
}
}Examples
Complete working examples are available in the examples/ directory:
- Payment Links:
create-payment-link.ts- Creating and sharing payment links - Webhook Handling:
handle-webhooks.ts- Receiving and processing webhook events - Payout Processing:
process-payout.ts- Managing payouts and settlements
Running Examples
# Set your API key
export SWAPPED_API_KEY=your-api-key-here
# Run an example
bun run examples/create-payment-link.tsTesting
The SDK includes comprehensive test coverage with 27 passing unit tests covering all core functionality.
Test Results
✅ 27 unit tests passing
✅ 0 unit tests failing
✅ 69 assertions
✅ 100% core functionality covered
✅ 6 test files
✅ 24 source filesTest Coverage:
- Error handling and factory functions (6 tests)
- Webhook signature verification (6 tests)
- HTTP client utilities (6 tests)
- Retry logic with exponential backoff (6 tests)
- Resource endpoint validation (3 tests)
- Performance benchmarks (4 tests)
Code Statistics:
- 24 TypeScript source files
- 6 comprehensive test suites
- Zero runtime dependencies
- 100% type coverage (zero
anytypes)
Run tests with:
bun testIntegration Tests
Integration tests are available for testing against the Swapped sandbox environment:
SWAPPED_API_KEY=your-key bun test tests/integrationPerformance
The SDK is designed with performance as a core consideration and includes comprehensive benchmarks.
Benchmark Results
Performance benchmarks demonstrate the SDK's efficiency. Run benchmarks with bun run benchmark to see live results:
| Operation | Performance | Description | |-----------|------------|-------------| | URL Building | ~209,000 ops/sec | Efficient query parameter handling | | Request Config | ~4,800,000 ops/sec | Fast request object creation | | Webhook Verification | ~15,600 ops/sec | Cryptographic signature validation | | Type Safety Overhead | ~23,500,000 ops/sec | Minimal compile-time cost |
Latest Benchmark Run:
┌──────────────────────────────────────┬──────────────┬─────────────┐
│ Operation │ Ops/Second │ Duration │
├──────────────────────────────────────┼──────────────┼─────────────┤
│ URL Building │ 209,058 │ 47.83ms │
│ Request Config Creation │ 4,788,412 │ 2.09ms │
│ Webhook Signature Verification │ 15,620 │ 6.40ms │
│ Type Safety Overhead │ 23,559,440 │ 4.24ms │
└──────────────────────────────────────┴──────────────┴─────────────┘
Summary:
• Average performance: 7,143,133 ops/sec
• Fastest operation: Type Safety Overhead
• Slowest operation: Webhook Signature VerificationBundle Size
The SDK is optimized for minimal bundle size:
- Bundled Size: 9.97 KB (gzipped: 2.6 KB)
- Zero Runtime Dependencies: No external packages required
- Tree-Shakeable: Only import what you need
- Type Definitions: Included inline, no separate @types package needed
Build the bundle with:
bun run buildPerformance Characteristics
- Pure Functions: No unnecessary object creation or mutations
- Immutable Types: All data structures are readonly, enabling safe sharing
- Efficient HTTP: Uses Bun's native fetch with connection pooling
- Minimal Dependencies: Zero runtime dependencies, uses only Bun built-ins
- Optimized Retry Logic: Exponential backoff prevents unnecessary requests
- Type Safety: Compile-time checks eliminate runtime type errors
Performance Best Practices
- Reuse Client Instances: Create the client once and reuse it throughout your application
- Batch Operations: Use list endpoints with pagination instead of multiple individual requests
- Error Handling: Implement proper retry logic for transient failures
- Webhook Processing: Process webhooks asynchronously to avoid blocking
Running Benchmarks
Formatted Output (Recommended):
bun run benchmarkThis displays a formatted table with detailed performance metrics.
Test Format:
bun run benchmark:test
# or
bun test benchmarks/performance.test.tsThis runs benchmarks as part of the test suite with assertions.
Requirements
- Bun: >= 1.0.0 (recommended runtime)
- TypeScript: >= 5.0.0
The SDK is optimized for Bun but can be used with Node.js 18+ and other JavaScript runtimes that support modern ES modules.
Documentation
For complete API documentation and integration guides, visit:
Swapped Commerce API Documentation: https://docs.swapped.com/swapped-commerce/commerce-integration
License
MIT
See LICENSE file for details.
