Skip to Content
🚀 {xpay✦} is building the future of x402 payments - Join the developer beta →
Developer ResourcesAdvanced Integration Patterns

Advanced Integration Patterns

Real-world integration patterns for complex Xpay deployments, based on production experience and customer use cases.

Production-Tested: These patterns are based on real customer deployments and have been battle-tested in production environments.

Multi-Tenant Agent Management

SaaS Application Pattern

For SaaS applications serving multiple customers, each with their own agents:

import { SmartProxy } from '@xpaysh/agent-kit' class MultiTenantAgentManager { private smartProxies: Map<string, SmartProxy> = new Map() constructor(private config: { defaultLimits: AgentLimits tierConfigs: Record<string, TierConfig> }) {} async initializeTenant(tenantId: string, tier: string = 'basic') { const tierConfig = this.config.tierConfigs[tier] const smartProxy = new SmartProxy({ endpoint: `https://smart-proxy-${tenantId}.xpay.sh`, apiKey: process.env.XPAY_API_KEY!, // Tenant-specific configuration defaultLimits: { dailyLimit: tierConfig.dailyLimit, perCallLimit: tierConfig.perCallLimit, monthlyLimit: tierConfig.monthlyLimit }, // Isolated webhook endpoints webhookEndpoint: `https://api.yourapp.com/webhooks/xpay/${tenantId}`, // Tenant-specific caching cachePrefix: `tenant:${tenantId}` }) this.smartProxies.set(tenantId, smartProxy) return smartProxy } async createAgentForTenant( tenantId: string, userId: string, agentConfig: Partial<AgentConfig> ): Promise<Agent> { const smartProxy = this.getSmartProxyForTenant(tenantId) const tier = await this.getTenantTier(tenantId) const tierLimits = this.config.tierConfigs[tier] // Apply tenant-specific limits and branding const agent = await smartProxy.createAgent({ ...agentConfig, id: `${tenantId}-${agentConfig.id}`, userId: `${tenantId}-${userId}`, customerId: tenantId, // Apply tier limits dailyLimit: Math.min(agentConfig.dailyLimit || Infinity, tierLimits.dailyLimit), perCallLimit: Math.min(agentConfig.perCallLimit || Infinity, tierLimits.perCallLimit), monthlyLimit: Math.min(agentConfig.monthlyLimit || Infinity, tierLimits.monthlyLimit), // Tenant-specific metadata metadata: { tenant: tenantId, tier: tier, createdBy: userId } }) // Track tenant usage await this.trackTenantUsage(tenantId, 'agent_created') return agent } async getAgentsForTenant(tenantId: string, userId?: string): Promise<Agent[]> { const smartProxy = this.getSmartProxyForTenant(tenantId) const agents = await smartProxy.listAgents({ search: userId ? `${tenantId}-${userId}` : tenantId }) return agents.agents } private getSmartProxyForTenant(tenantId: string): SmartProxy { const smartProxy = this.smartProxies.get(tenantId) if (!smartProxy) { throw new Error(`Tenant ${tenantId} not initialized`) } return smartProxy } private async getTenantTier(tenantId: string): Promise<string> { // Query your database for tenant subscription tier const tenant = await db.query('SELECT tier FROM tenants WHERE id = $1', [tenantId]) return tenant.rows[0]?.tier || 'basic' } private async trackTenantUsage(tenantId: string, event: string) { // Track usage for billing/analytics await analytics.track({ event, tenantId, timestamp: new Date() }) } } // Usage in your SaaS application const agentManager = new MultiTenantAgentManager({ defaultLimits: { dailyLimit: 10, perCallLimit: 0.50, monthlyLimit: 200 }, tierConfigs: { basic: { dailyLimit: 25, perCallLimit: 1, monthlyLimit: 500 }, professional: { dailyLimit: 100, perCallLimit: 5, monthlyLimit: 2000 }, enterprise: { dailyLimit: 1000, perCallLimit: 20, monthlyLimit: 20000 } } }) // Initialize tenant when they sign up app.post('/api/tenants/:tenantId/initialize', async (req, res) => { const { tenantId } = req.params const { tier } = req.body await agentManager.initializeTenant(tenantId, tier) res.json({ success: true }) }) // Create agent for tenant user app.post('/api/tenants/:tenantId/agents', async (req, res) => { const { tenantId } = req.params const { userId, agentConfig } = req.body const agent = await agentManager.createAgentForTenant(tenantId, userId, agentConfig) res.json(agent) })

Custom Webhook Processing

Complex Event Handling

Handle multiple event types with sophisticated business logic:

import crypto from 'crypto' import { EventEmitter } from 'events' class XpayWebhookProcessor extends EventEmitter { private processors: Map<string, EventProcessor> = new Map() constructor(private config: { secret: string retryAttempts: number retryDelay: number }) { super() this.setupEventProcessors() } private setupEventProcessors() { // Agent spending warning this.processors.set('agent.spending.warning', new AgentSpendingProcessor()) // Payment confirmation with business logic this.processors.set('transaction.confirmed', new PaymentConfirmationProcessor()) // Fraud detection this.processors.set('agent.unusual_pattern', new FraudDetectionProcessor()) // Customer lifecycle this.processors.set('customer.first_payment', new CustomerOnboardingProcessor()) } async processWebhook(req: express.Request, res: express.Response) { try { // Verify webhook signature const signature = req.headers['x-xpay-signature'] as string const payload = JSON.stringify(req.body) if (!this.verifySignature(payload, signature)) { return res.status(401).json({ error: 'Invalid signature' }) } const { event, data, timestamp } = req.body // Check for replay attacks if (this.isReplayAttack(timestamp)) { return res.status(400).json({ error: 'Request too old' }) } // Process event with appropriate handler const processor = this.processors.get(event) if (processor) { await processor.process(data, event) this.emit('webhook.processed', { event, data }) } else { console.warn(`Unknown webhook event: ${event}`) } res.status(200).json({ received: true }) } catch (error) { console.error('Webhook processing error:', error) res.status(500).json({ error: 'Processing failed' }) // Queue for retry await this.queueForRetry(req.body) } } private verifySignature(payload: string, signature: string): boolean { const expectedSignature = crypto .createHmac('sha256', this.config.secret) .update(payload) .digest('hex') return crypto.timingSafeEqual( Buffer.from(`sha256=${expectedSignature}`), Buffer.from(signature) ) } private isReplayAttack(timestamp: number): boolean { const now = Date.now() const eventTime = new Date(timestamp).getTime() const maxAge = 5 * 60 * 1000 // 5 minutes return (now - eventTime) > maxAge } private async queueForRetry(webhookData: any) { // Use a queue system like Bull or SQS for retry logic await retryQueue.add('webhook-retry', webhookData, { attempts: this.config.retryAttempts, backoff: { type: 'exponential', settings: { delay: this.config.retryDelay } } }) } } // Event processor implementations class AgentSpendingProcessor implements EventProcessor { async process(data: any, event: string) { const { agentId, percentUsed, dailyLimit, currentSpent } = data if (percentUsed >= 90) { // Critical alert - near limit await this.sendCriticalAlert(agentId, percentUsed) // Auto-pause if configured const agent = await getAgent(agentId) if (agent.autoShutoff?.enabled && percentUsed >= agent.autoShutoff.threshold * 100) { await pauseAgent(agentId) } } else if (percentUsed >= 80) { // Warning alert await this.sendWarningAlert(agentId, percentUsed) } // Update internal metrics await updateAgentMetrics(agentId, { lastSpendingWarning: new Date(), percentUsed, currentSpent }) } private async sendCriticalAlert(agentId: string, percentUsed: number) { await notifications.send({ type: 'critical', channel: 'slack', message: `🚨 Agent ${agentId} at ${percentUsed}% of daily limit`, actions: [ { label: 'Pause Agent', action: 'pause_agent', agentId }, { label: 'Increase Limit', action: 'increase_limit', agentId } ] }) } private async sendWarningAlert(agentId: string, percentUsed: number) { await notifications.send({ type: 'warning', channel: 'email', message: `Agent ${agentId} at ${percentUsed}% of daily limit`, template: 'spending_warning' }) } } class PaymentConfirmationProcessor implements EventProcessor { async process(data: any, event: string) { const { transactionId, agentId, amount, endpointId } = data try { // Update transaction status await updateTransactionStatus(transactionId, 'confirmed') // Update agent spending totals await incrementAgentSpending(agentId, amount) // Update endpoint revenue (if applicable) if (endpointId) { await incrementEndpointRevenue(endpointId, amount) } // Trigger business logic await this.processBusinessLogic(data) // Analytics tracking await analytics.track('payment_confirmed', { agentId, amount, endpointId, transactionId }) } catch (error) { console.error('Payment confirmation processing failed:', error) throw error } } private async processBusinessLogic(data: any) { const { agentId, amount, metadata } = data // Check for milestone achievements const agentStats = await getAgentStats(agentId) if (agentStats.totalSpent >= 100 && !agentStats.milestonePaid) { // Agent reached $100 milestone await this.triggerMilestone(agentId, 100) } // Dynamic limit adjustments based on usage pattern if (agentStats.successRate > 0.95 && agentStats.totalCalls > 50) { await this.considerLimitIncrease(agentId) } } private async triggerMilestone(agentId: string, milestone: number) { await db.query(` UPDATE agents SET milestone_paid = $1, updated_at = NOW() WHERE id = $2 `, [milestone, agentId]) // Send congratulations await notifications.send({ type: 'milestone', message: `🎉 Agent ${agentId} reached $${milestone} in total spending!` }) } private async considerLimitIncrease(agentId: string) { // AI-powered limit optimization based on usage patterns const recommendation = await aiOptimizer.recommendLimits(agentId) if (recommendation.confidence > 0.8) { await notifications.send({ type: 'optimization', message: `Consider increasing limits for agent ${agentId}`, recommendation }) } } }

Batch Transaction Processing

High-Volume Payment Processing

Handle thousands of transactions efficiently:

interface BatchProcessor { processBatch(transactions: PendingTransaction[]): Promise<BatchResult> } class XpayBatchProcessor implements BatchProcessor { private readonly BATCH_SIZE = 100 private readonly CONCURRENT_BATCHES = 5 constructor( private smartProxy: SmartProxy, private config: { retryAttempts: number retryDelay: number successThreshold: number } ) {} async processBatch(transactions: PendingTransaction[]): Promise<BatchResult> { const startTime = Date.now() const results: TransactionResult[] = [] // Split into smaller batches for processing const batches = this.chunkArray(transactions, this.BATCH_SIZE) // Process batches concurrently with limit const batchPromises = batches.map((batch, index) => this.processSingleBatch(batch, index) ) const batchResults = await this.executeWithConcurrencyLimit( batchPromises, this.CONCURRENT_BATCHES ) // Aggregate results for (const batchResult of batchResults) { results.push(...batchResult.results) } const summary = this.calculateSummary(results, startTime) // Handle failed transactions if (summary.failedCount > 0) { await this.handleFailedTransactions( results.filter(r => !r.success) ) } return { summary, results, processedAt: new Date() } } private async processSingleBatch( transactions: PendingTransaction[], batchIndex: number ): Promise<{ results: TransactionResult[] }> { const results: TransactionResult[] = [] console.log(`Processing batch ${batchIndex} with ${transactions.length} transactions`) // Prepare batch request for Xpay const batchRequest = transactions.map(tx => ({ agentId: tx.agentId, url: tx.endpoint, options: { method: 'POST', headers: tx.headers, body: JSON.stringify(tx.payload) }, metadata: { transactionId: tx.id, batchIndex, timestamp: Date.now() } })) try { // Execute batch request const batchResults = await this.smartProxy.batchRequests(batchRequest) // Process individual results for (let i = 0; i < batchResults.length; i++) { const result = batchResults[i] const transaction = transactions[i] if (result.success) { results.push({ transactionId: transaction.id, success: true, cost: result.cost, response: result.response, processingTime: Date.now() - transaction.createdAt }) // Update transaction in database await this.updateTransactionStatus(transaction.id, 'confirmed', result.cost) } else { results.push({ transactionId: transaction.id, success: false, error: result.error, retryable: this.isRetryableError(result.error) }) // Mark for retry if appropriate if (this.isRetryableError(result.error)) { await this.scheduleRetry(transaction) } else { await this.updateTransactionStatus(transaction.id, 'failed', 0) } } } } catch (error) { console.error(`Batch ${batchIndex} failed:`, error) // Mark all transactions as failed with retry for (const transaction of transactions) { results.push({ transactionId: transaction.id, success: false, error: error.message, retryable: true }) await this.scheduleRetry(transaction) } } return { results } } private async executeWithConcurrencyLimit<T>( promises: Promise<T>[], limit: number ): Promise<T[]> { const results: T[] = [] for (let i = 0; i < promises.length; i += limit) { const batch = promises.slice(i, i + limit) const batchResults = await Promise.allSettled(batch) for (const result of batchResults) { if (result.status === 'fulfilled') { results.push(result.value) } else { console.error('Batch promise failed:', result.reason) throw result.reason } } } return results } private calculateSummary(results: TransactionResult[], startTime: number): BatchSummary { const successCount = results.filter(r => r.success).length const failedCount = results.filter(r => !r.success).length const totalCost = results .filter(r => r.success) .reduce((sum, r) => sum + (r.cost || 0), 0) return { totalTransactions: results.length, successCount, failedCount, successRate: successCount / results.length, totalCost, processingTime: Date.now() - startTime, averageTransactionTime: results .filter(r => r.success && r.processingTime) .reduce((sum, r) => sum + r.processingTime!, 0) / successCount } } private async handleFailedTransactions(failed: TransactionResult[]) { const retryable = failed.filter(f => f.retryable) const permanent = failed.filter(f => !f.retryable) if (retryable.length > 0) { console.log(`Scheduling ${retryable.length} transactions for retry`) // These will be picked up by the retry processor } if (permanent.length > 0) { console.log(`${permanent.length} transactions permanently failed`) // Notify administrators of permanent failures await notifications.send({ type: 'error', message: `${permanent.length} transactions permanently failed`, details: permanent.map(f => ({ id: f.transactionId, error: f.error })) }) } } private chunkArray<T>(array: T[], size: number): T[][] { const chunks: T[][] = [] for (let i = 0; i < array.length; i += size) { chunks.push(array.slice(i, i + size)) } return chunks } private isRetryableError(error: any): boolean { if (!error) return false const retryableCodes = [ 'NETWORK_ERROR', 'TIMEOUT', 'RATE_LIMITED', 'SERVICE_UNAVAILABLE', 'TEMPORARY_FAILURE' ] return retryableCodes.includes(error.code) || (error.status >= 500 && error.status < 600) } private async scheduleRetry(transaction: PendingTransaction) { await retryQueue.add('transaction-retry', transaction, { attempts: this.config.retryAttempts, backoff: { type: 'exponential', settings: { delay: this.config.retryDelay } } }) } private async updateTransactionStatus( transactionId: string, status: string, cost: number ) { await db.query(` UPDATE transactions SET status = $1, amount = $2, updated_at = NOW() WHERE id = $3 `, [status, cost, transactionId]) } } // Usage example const batchProcessor = new XpayBatchProcessor(smartProxy, { retryAttempts: 3, retryDelay: 1000, successThreshold: 0.95 }) // Process pending transactions every minute setInterval(async () => { const pendingTransactions = await getPendingTransactions(1000) // Get up to 1000 pending if (pendingTransactions.length > 0) { const result = await batchProcessor.processBatch(pendingTransactions) console.log(`Batch completed: ${result.summary.successCount}/${result.summary.totalTransactions} successful`) if (result.summary.successRate < 0.95) { // Alert if success rate is too low await notifications.send({ type: 'warning', message: `Low batch success rate: ${result.summary.successRate * 100}%` }) } } }, 60000) // Run every minute

Custom Analytics and Reporting

Advanced Analytics Pipeline

Build sophisticated analytics for agent performance and revenue optimization:

class XpayAnalyticsEngine { private metricsCollector: MetricsCollector private dataProcessor: DataProcessor private reportGenerator: ReportGenerator constructor( private smartProxy: SmartProxy, private config: AnalyticsConfig ) { this.metricsCollector = new MetricsCollector(smartProxy) this.dataProcessor = new DataProcessor() this.reportGenerator = new ReportGenerator() } async generateCustomerReport(customerId: string, timeframe: string): Promise<CustomerReport> { // Collect raw data const rawData = await this.metricsCollector.collectCustomerData(customerId, timeframe) // Process and analyze const processedData = await this.dataProcessor.processCustomerData(rawData) // Generate insights const insights = await this.generateCustomerInsights(processedData) // Create report return this.reportGenerator.generateCustomerReport({ customerId, timeframe, data: processedData, insights }) } async generateRevenueOptimizationReport(endpointId: string): Promise<OptimizationReport> { const data = await this.metricsCollector.collectEndpointData(endpointId, '30d') // Analyze pricing elasticity const elasticity = await this.analyzePriceElasticity(data) // Predict optimal pricing const optimalPricing = await this.predictOptimalPricing(data, elasticity) // A/B testing recommendations const testingRecommendations = await this.generateTestingRecommendations(optimalPricing) return { endpointId, currentMetrics: data.summary, elasticity, optimalPricing, testingRecommendations, projectedIncrease: this.calculateProjectedIncrease(data, optimalPricing) } } async predictAgentBehavior(agentId: string): Promise<BehaviorPrediction> { // Collect historical data const history = await this.metricsCollector.collectAgentHistory(agentId, '90d') // Machine learning prediction const prediction = await this.mlPredictor.predict({ features: this.extractFeatures(history), model: 'agent_behavior_v2' }) return { agentId, predictions: { nextDaySpending: prediction.nextDaySpending, monthlySpending: prediction.monthlySpending, riskScore: prediction.riskScore, optimalLimits: prediction.optimalLimits }, confidence: prediction.confidence, recommendations: this.generateBehaviorRecommendations(prediction) } } private async generateCustomerInsights(data: ProcessedCustomerData): Promise<CustomerInsights> { const insights: CustomerInsights = { spendingTrends: [], anomalies: [], opportunities: [], risks: [] } // Spending trend analysis if (data.spendingGrowthRate > 0.2) { insights.spendingTrends.push({ type: 'growth', description: `Spending increased by ${(data.spendingGrowthRate * 100).toFixed(1)}%`, impact: 'positive' }) } // Anomaly detection for (const anomaly of data.anomalies) { if (anomaly.severity > 0.7) { insights.anomalies.push({ type: anomaly.type, description: anomaly.description, severity: anomaly.severity, recommendedAction: anomaly.recommendedAction }) } } // Optimization opportunities if (data.efficiencyScore < 0.8) { insights.opportunities.push({ type: 'efficiency', description: 'Agent efficiency could be improved', potentialSavings: data.projectedSavings, actionItems: [ 'Review agent configurations', 'Optimize API call patterns', 'Consider batch processing' ] }) } // Risk assessment if (data.riskScore > 0.6) { insights.risks.push({ type: 'spending', description: 'High risk of budget overrun', probability: data.riskScore, mitigation: [ 'Reduce daily limits', 'Enable auto-shutoff', 'Increase monitoring frequency' ] }) } return insights } private async analyzePriceElasticity(data: EndpointData): Promise<PriceElasticity> { // Analyze how demand changes with price const pricePoints = data.historicalPricing const demandData = data.usageByPrice // Calculate elasticity coefficient const elasticity = this.calculateElasticity(pricePoints, demandData) return { coefficient: elasticity, interpretation: this.interpretElasticity(elasticity), confidenceInterval: this.calculateConfidenceInterval(pricePoints, demandData), recommendations: this.generateElasticityRecommendations(elasticity) } } private async predictOptimalPricing( data: EndpointData, elasticity: PriceElasticity ): Promise<OptimalPricing> { // Use revenue maximization algorithm const revenueFunction = (price: number) => { const demand = this.predictDemand(price, elasticity) return price * demand } // Find optimal price point const optimalPrice = this.findOptimalPrice(revenueFunction, data.currentPrice) return { currentPrice: data.currentPrice, optimalPrice, projectedRevenue: revenueFunction(optimalPrice), confidence: this.calculatePricingConfidence(data, elasticity), priceRange: { min: optimalPrice * 0.9, max: optimalPrice * 1.1 } } } // Helper methods for calculations private calculateElasticity(pricePoints: number[], demandData: number[]): number { // Simplified elasticity calculation const priceChanges = pricePoints.slice(1).map((price, i) => (price - pricePoints[i]) / pricePoints[i] ) const demandChanges = demandData.slice(1).map((demand, i) => (demand - demandData[i]) / demandData[i] ) // Calculate average elasticity const elasticities = demandChanges.map((demandChange, i) => demandChange / priceChanges[i] ) return elasticities.reduce((sum, e) => sum + e, 0) / elasticities.length } private interpretElasticity(elasticity: number): string { if (elasticity < -1) return 'elastic' if (elasticity > -1 && elasticity < 0) return 'inelastic' return 'unit_elastic' } private findOptimalPrice(revenueFunction: (price: number) => number, currentPrice: number): number { // Simple optimization using golden section search let a = currentPrice * 0.5 let b = currentPrice * 2 const phi = (1 + Math.sqrt(5)) / 2 // Golden section search iterations for (let i = 0; i < 20; i++) { const c = b - (b - a) / phi const d = a + (b - a) / phi if (revenueFunction(c) > revenueFunction(d)) { b = d } else { a = c } } return (a + b) / 2 } } // Usage example const analytics = new XpayAnalyticsEngine(smartProxy, { enableMachineLearning: true, dataRetentionDays: 365, reportingFrequency: 'daily' }) // Generate daily reports cron.schedule('0 6 * * *', async () => { const customers = await getActiveCustomers() for (const customer of customers) { const report = await analytics.generateCustomerReport(customer.id, '24h') if (report.insights.risks.length > 0) { await notifications.send({ type: 'risk_alert', customerId: customer.id, risks: report.insights.risks }) } } }) // Weekly optimization reports cron.schedule('0 9 * * 1', async () => { const endpoints = await getActiveEndpoints() for (const endpoint of endpoints) { const optimization = await analytics.generateRevenueOptimizationReport(endpoint.id) if (optimization.projectedIncrease > 0.1) { await notifications.send({ type: 'optimization_opportunity', endpointId: endpoint.id, opportunity: optimization }) } } })

Integration Testing Patterns

Comprehensive Testing Strategy

import { describe, it, beforeEach, afterEach, expect } from '@jest/globals' import { SmartProxy } from '@xpaysh/agent-kit' describe('Xpay Integration Tests', () => { let smartProxy: SmartProxy let testAgent: Agent beforeEach(async () => { // Initialize test smart proxy smartProxy = new SmartProxy({ endpoint: process.env.XPAY_TEST_ENDPOINT!, apiKey: process.env.XPAY_TEST_API_KEY!, // Test-specific configuration timeout: 5000, retries: 1 }) // Create test agent testAgent = await smartProxy.createAgent({ id: `test-agent-${Date.now()}`, name: 'Test Agent', walletAddress: process.env.TEST_WALLET_ADDRESS!, dailyLimit: 10, perCallLimit: 1 }) }) afterEach(async () => { // Cleanup if (testAgent) { await smartProxy.deleteAgent(testAgent.id) } }) describe('Agent Lifecycle', () => { it('should create agent with proper configuration', async () => { expect(testAgent.id).toBeTruthy() expect(testAgent.dailyLimit).toBe(10) expect(testAgent.status).toBe('active') }) it('should update agent limits', async () => { const updated = await smartProxy.updateAgent(testAgent.id, { dailyLimit: 20, perCallLimit: 2 }) expect(updated.dailyLimit).toBe(20) expect(updated.perCallLimit).toBe(2) }) it('should pause and resume agent', async () => { await smartProxy.pauseAgent(testAgent.id) let agent = await smartProxy.getAgent(testAgent.id) expect(agent.status).toBe('paused') await smartProxy.resumeAgent(testAgent.id) agent = await smartProxy.getAgent(testAgent.id) expect(agent.status).toBe('active') }) }) describe('Payment Processing', () => { it('should process successful payment', async () => { const response = await smartProxy.protectedFetch('https://api.example.com/test', { agentId: testAgent.id, method: 'POST', body: JSON.stringify({ test: true }) }) expect(response.ok).toBe(true) // Verify agent spending updated const updatedAgent = await smartProxy.getAgent(testAgent.id) expect(updatedAgent.totalSpent).toBeGreaterThan(0) expect(updatedAgent.totalCalls).toBe(1) }) it('should reject payment when limit exceeded', async () => { // Set very low limit await smartProxy.updateAgent(testAgent.id, { perCallLimit: 0.001 }) await expect( smartProxy.protectedFetch('https://api.example.com/expensive', { agentId: testAgent.id, method: 'POST' }) ).rejects.toThrow('Spending limit exceeded') }) it('should handle batch requests correctly', async () => { const requests = Array.from({ length: 5 }, (_, i) => ({ agentId: testAgent.id, url: `https://api.example.com/test/${i}`, options: { method: 'GET' } })) const results = await smartProxy.batchRequests(requests) expect(results).toHaveLength(5) expect(results.every(r => r.success)).toBe(true) // Verify total spending const updatedAgent = await smartProxy.getAgent(testAgent.id) expect(updatedAgent.totalCalls).toBe(5) }) }) describe('Error Handling', () => { it('should handle network timeouts gracefully', async () => { // Mock timeout scenario jest.setTimeout(10000) await expect( smartProxy.protectedFetch('https://httpstat.us/200?sleep=8000', { agentId: testAgent.id, timeout: 2000 }) ).rejects.toThrow('timeout') }) it('should retry failed requests', async () => { const retrySmartProxy = new SmartProxy({ endpoint: process.env.XPAY_TEST_ENDPOINT!, apiKey: process.env.XPAY_TEST_API_KEY!, retries: 3, retryDelay: 100 }) // Mock intermittent failure let attempts = 0 const mockFetch = jest.fn().mockImplementation(() => { attempts++ if (attempts < 3) { throw new Error('Temporary failure') } return Promise.resolve(new Response('Success')) }) // Test retry mechanism const response = await retrySmartProxy.protectedFetch('https://api.example.com/retry', { agentId: testAgent.id }) expect(response.ok).toBe(true) expect(attempts).toBe(3) }) }) describe('Analytics and Monitoring', () => { it('should track spending analytics correctly', async () => { // Make several test requests for (let i = 0; i < 3; i++) { await smartProxy.protectedFetch('https://api.example.com/analytics', { agentId: testAgent.id }) } const analytics = await smartProxy.getSpendingAnalytics({ agentIds: [testAgent.id], timeframe: '1h' }) expect(analytics.totalCalls).toBe(3) expect(analytics.totalSpent).toBeGreaterThan(0) expect(analytics.breakdown).toHaveLength(1) }) it('should retrieve transaction history', async () => { // Make a test transaction await smartProxy.protectedFetch('https://api.example.com/history', { agentId: testAgent.id }) const history = await smartProxy.getTransactionHistory({ agentIds: [testAgent.id], limit: 10 }) expect(history.transactions).toHaveLength(1) expect(history.transactions[0].agentId).toBe(testAgent.id) expect(history.transactions[0].status).toBe('confirmed') }) }) }) // Load testing utilities export class LoadTestRunner { constructor(private smartProxy: SmartProxy) {} async runLoadTest(config: LoadTestConfig): Promise<LoadTestResults> { const startTime = Date.now() const results: RequestResult[] = [] // Create test agents const agents = await Promise.all( Array.from({ length: config.agentCount }, (_, i) => this.smartProxy.createAgent({ id: `load-test-agent-${i}`, name: `Load Test Agent ${i}`, walletAddress: process.env.TEST_WALLET_ADDRESS!, dailyLimit: 100, perCallLimit: 5 }) ) ) try { // Generate load const promises: Promise<RequestResult>[] = [] for (let i = 0; i < config.totalRequests; i++) { const agent = agents[i % agents.length] const delay = (i / config.requestsPerSecond) * 1000 promises.push( new Promise(resolve => { setTimeout(async () => { const requestStart = Date.now() try { await this.smartProxy.protectedFetch(config.targetUrl, { agentId: agent.id }) resolve({ success: true, duration: Date.now() - requestStart, agentId: agent.id }) } catch (error) { resolve({ success: false, duration: Date.now() - requestStart, agentId: agent.id, error: error.message }) } }, delay) }) ) } const requestResults = await Promise.all(promises) results.push(...requestResults) } finally { // Cleanup test agents await Promise.all( agents.map(agent => this.smartProxy.deleteAgent(agent.id)) ) } return this.analyzeResults(results, Date.now() - startTime) } private analyzeResults(results: RequestResult[], totalTime: number): LoadTestResults { const successful = results.filter(r => r.success) const failed = results.filter(r => !r.success) const durations = successful.map(r => r.duration) durations.sort((a, b) => a - b) return { totalRequests: results.length, successfulRequests: successful.length, failedRequests: failed.length, successRate: successful.length / results.length, totalTime, requestsPerSecond: results.length / (totalTime / 1000), averageResponseTime: durations.reduce((sum, d) => sum + d, 0) / durations.length, medianResponseTime: durations[Math.floor(durations.length / 2)], p95ResponseTime: durations[Math.floor(durations.length * 0.95)], p99ResponseTime: durations[Math.floor(durations.length * 0.99)], errors: failed.reduce((acc, f) => { acc[f.error!] = (acc[f.error!] || 0) + 1 return acc }, {} as Record<string, number>) } } }

These advanced integration patterns provide production-ready solutions for complex Xpay deployments. They cover multi-tenancy, webhook processing, batch operations, analytics, and comprehensive testing strategies that scale with your application needs.

Last updated on: