ssUSD Integration Guide
This guide walks you through integrating StateSet USD (ssUSD) into your application, from basic setup to advanced features.๐ Quick Start
1. Get Your API Keys
Create Account
Sign up at dashboard.stateset.com
2. Install SDK
Copy
npm install @stateset/sdk
3. Initialize Client
Copy
import { StateSet } from '@stateset/sdk';
const stateset = new StateSet({
apiKey: process.env.STATESET_API_KEY,
network: 'mainnet' // or 'testnet' for development
});
// Test connection
const balance = await stateset.stablecoin.balance({
address: 'your_wallet_address'
});
console.log('ssUSD Balance:', balance.amount);
๐ณ Common Use Cases
E-Commerce Payments
Accept ssUSD payments with instant settlement and no chargebacks:Copy
// Create payment request
async function createPayment(amount, orderId) {
const payment = await stateset.payments.create({
amount: amount,
currency: 'ssusd',
metadata: {
order_id: orderId,
customer_email: '[email protected]'
},
webhook_url: 'https://yoursite.com/webhooks/payment'
});
return payment.payment_address;
}
// Verify payment received
async function verifyPayment(paymentId) {
const payment = await stateset.payments.get(paymentId);
if (payment.status === 'completed') {
// Process order fulfillment
await fulfillOrder(payment.metadata.order_id);
}
}
Payroll & Disbursements
Send bulk payments efficiently:Copy
// Batch payroll payments
async function processPayroll(employees) {
const transfers = employees.map(emp => ({
to: emp.wallet_address,
amount: emp.salary_ssusd,
memo: `Payroll ${new Date().toISOString().slice(0, 7)}`
}));
const batch = await stateset.stablecoin.batchTransfer({
transfers,
idempotency_key: `payroll_${Date.now()}`
});
// Send notifications
for (const result of batch.results) {
if (result.success) {
await notifyEmployee(result.to, result.transaction_hash);
}
}
return batch;
}
Treasury Management
Hold and manage corporate ssUSD reserves:Copy
// Corporate treasury dashboard
class TreasuryManager {
async getOverview() {
const [balance, reserves, transactions] = await Promise.all([
stateset.stablecoin.balance({ address: this.treasuryAddress }),
stateset.stablecoin.reserves(),
stateset.stablecoin.transactions({
address: this.treasuryAddress,
limit: 100
})
]);
return {
current_balance: balance.amount,
reserve_backing: reserves.total_usd,
recent_activity: transactions,
health_score: this.calculateHealthScore(balance, transactions)
};
}
async optimizeYield(amount) {
// Check available yield opportunities
const opportunities = await stateset.finance.yieldOpportunities({
asset: 'ssusd',
amount: amount,
risk_level: 'low'
});
// Deploy to best opportunity
if (opportunities[0].apy > 0.03) { // 3% APY threshold
return await stateset.finance.deployCapital({
opportunity_id: opportunities[0].id,
amount: amount
});
}
}
}
๐ Security Best Practices
API Key Management
Never expose your secret API key in client-side code or public repositories!
Copy
// โ WRONG - Never do this
const stateset = new StateSet({
apiKey: 'sk_live_your_actual_key_here' // Hardcoded key (never do this)
});
// โ
CORRECT - Use environment variables
const stateset = new StateSet({
apiKey: process.env.STATESET_API_KEY
});
// โ
CORRECT - Use restricted keys for client-side
const publicClient = new StateSet({
apiKey: process.env.STATESET_PUBLIC_KEY // pk_ prefix
});
Transaction Security
Implement proper validation and limits:Copy
class SecureTransferService {
constructor() {
this.dailyLimit = 100000; // $100k daily limit
this.perTxLimit = 10000; // $10k per transaction
}
async transfer(to, amount, memo) {
// Validate amount
if (amount > this.perTxLimit) {
throw new Error('Transaction exceeds limit');
}
// Check daily volume
const dailyVolume = await this.getDailyVolume();
if (dailyVolume + amount > this.dailyLimit) {
throw new Error('Daily limit exceeded');
}
// Validate recipient
if (!this.isValidAddress(to)) {
throw new Error('Invalid recipient address');
}
// Execute with idempotency
return await stateset.stablecoin.transfer({
to,
amount,
memo,
idempotency_key: `transfer_${Date.now()}_${to}`
});
}
}
๐ Monitoring & Analytics
Real-Time Balance Monitoring
Copy
// WebSocket subscription for balance updates
const ws = stateset.subscriptions.connect();
ws.subscribe('balance.updated', async (event) => {
console.log('New balance:', event.balance);
// Alert on large changes
if (Math.abs(event.change) > 10000) {
await sendAlert({
type: 'large_balance_change',
amount: event.change,
new_balance: event.balance
});
}
});
// Historical balance tracking
async function getBalanceHistory(days = 30) {
const history = [];
const now = Date.now();
for (let i = 0; i < days; i++) {
const timestamp = now - (i * 24 * 60 * 60 * 1000);
const balance = await stateset.stablecoin.balance({
address: treasuryAddress,
at_timestamp: timestamp
});
history.push({
date: new Date(timestamp).toISOString().slice(0, 10),
balance: balance.amount
});
}
return history;
}
Transaction Analytics
Copy
// Analyze transaction patterns
async function analyzeTransactions(address, period = '30d') {
const transactions = await stateset.stablecoin.transactions({
address,
period,
limit: 1000
});
const analytics = {
total_volume: 0,
transaction_count: transactions.length,
average_size: 0,
largest_transaction: 0,
counterparties: new Set(),
daily_pattern: {}
};
transactions.forEach(tx => {
analytics.total_volume += tx.amount;
analytics.largest_transaction = Math.max(
analytics.largest_transaction,
tx.amount
);
analytics.counterparties.add(
tx.from === address ? tx.to : tx.from
);
const date = new Date(tx.timestamp).toISOString().slice(0, 10);
analytics.daily_pattern[date] =
(analytics.daily_pattern[date] || 0) + tx.amount;
});
analytics.average_size =
analytics.total_volume / analytics.transaction_count;
analytics.unique_counterparties = analytics.counterparties.size;
return analytics;
}
๐ Multi-Chain Integration
Bridge to Other Chains
Copy
// Bridge ssUSD to Base
async function bridgeToBase(amount) {
const bridge = await stateset.bridge.create({
from_chain: 'stateset',
to_chain: 'base',
asset: 'ssusd',
amount: amount,
recipient: baseAddress
});
// Monitor bridge progress
const status = await stateset.bridge.track(bridge.id);
console.log('Bridge status:', status);
return bridge;
}
// Cross-chain balance aggregation
async function getTotalBalance(addresses) {
const balances = await Promise.all([
stateset.stablecoin.balance({
address: addresses.stateset,
chain: 'stateset'
}),
stateset.stablecoin.balance({
address: addresses.base,
chain: 'base'
}),
stateset.stablecoin.balance({
address: addresses.solana,
chain: 'solana'
})
]);
return balances.reduce((sum, b) => sum + b.amount, 0);
}
๐งช Testing
Test Mode
Use test mode for development:Copy
const testClient = new StateSet({
apiKey: process.env.STATESET_TEST_KEY,
network: 'testnet'
});
// Get test ssUSD
async function getTestFunds() {
const faucet = await testClient.faucet.request({
asset: 'ssusd',
amount: 10000, // $10k test ssUSD
address: testAddress
});
return faucet;
}
Integration Tests
Copy
describe('ssUSD Integration', () => {
it('should transfer funds successfully', async () => {
const initialBalance = await getBalance(senderAddress);
const transfer = await stateset.stablecoin.transfer({
to: recipientAddress,
amount: '100.00'
});
expect(transfer.status).toBe('completed');
const finalBalance = await getBalance(senderAddress);
expect(finalBalance).toBe(initialBalance - 100);
});
it('should handle insufficient funds', async () => {
await expect(
stateset.stablecoin.transfer({
to: recipientAddress,
amount: '1000000.00' // More than balance
})
).rejects.toThrow('Insufficient funds');
});
});
๐จ Error Handling
Common Errors and Solutions
Copy
try {
const transfer = await stateset.stablecoin.transfer({...});
} catch (error) {
switch(error.code) {
case 'insufficient_funds':
// Handle low balance
console.error('Not enough ssUSD');
break;
case 'invalid_address':
// Handle bad recipient
console.error('Check recipient address format');
break;
case 'compliance_block':
// Handle compliance issues
console.error('Transaction blocked for compliance');
await handleComplianceBlock(error.details);
break;
case 'rate_limit':
// Handle rate limiting
console.error('Too many requests');
await sleep(error.retry_after * 1000);
break;
default:
console.error('Unknown error:', error);
}
}