moltspay 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -14
- package/dist/cdp/index.d.mts +1 -1
- package/dist/cdp/index.d.ts +1 -1
- package/dist/cdp/index.js +53 -30368
- package/dist/cdp/index.js.map +1 -1
- package/dist/cdp/index.mjs +37 -30360
- package/dist/cdp/index.mjs.map +1 -1
- package/dist/cdp-DeohBe1o.d.ts +66 -0
- package/dist/cdp-p_eHuQpb.d.mts +66 -0
- package/dist/chains/index.d.mts +1 -1
- package/dist/chains/index.d.ts +1 -1
- package/dist/chains/index.js +29 -0
- package/dist/chains/index.js.map +1 -1
- package/dist/chains/index.mjs +29 -0
- package/dist/chains/index.mjs.map +1 -1
- package/dist/cli/index.js +863 -109
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +867 -109
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/index.d.mts +25 -2
- package/dist/client/index.d.ts +25 -2
- package/dist/client/index.js +195 -12
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +185 -12
- package/dist/client/index.mjs.map +1 -1
- package/dist/facilitators/index.d.mts +15 -53
- package/dist/facilitators/index.d.ts +15 -53
- package/dist/facilitators/index.js +234 -1
- package/dist/facilitators/index.js.map +1 -1
- package/dist/facilitators/index.mjs +233 -1
- package/dist/facilitators/index.mjs.map +1 -1
- package/dist/{index-DgJPZMBG.d.mts → index-On9ZaGDW.d.mts} +1 -1
- package/dist/{index-DgJPZMBG.d.ts → index-On9ZaGDW.d.ts} +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +718 -30584
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +711 -30587
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +17 -0
- package/dist/server/index.d.ts +17 -0
- package/dist/server/index.js +443 -5
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +443 -5
- package/dist/server/index.mjs.map +1 -1
- package/dist/verify/index.d.mts +1 -1
- package/dist/verify/index.d.ts +1 -1
- package/dist/verify/index.js +29 -0
- package/dist/verify/index.js.map +1 -1
- package/dist/verify/index.mjs +29 -0
- package/dist/verify/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +1 -1
- package/dist/wallet/index.d.ts +1 -1
- package/dist/wallet/index.js +29 -0
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +29 -0
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +5 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/index.ts","../../src/facilitators/interface.ts","../../src/facilitators/cdp.ts","../../src/facilitators/registry.ts"],"sourcesContent":["/**\n * MoltsPay Server - Payment infrastructure for AI Agents\n * \n * Now uses pluggable Facilitator abstraction for payment verification/settlement.\n * \n * Environment variables (from ~/.moltspay/.env or process.env):\n * USE_MAINNET=true - Use Base mainnet (requires CDP keys)\n * CDP_API_KEY_ID=xxx - Coinbase Developer Platform API key ID\n * CDP_API_KEY_SECRET=xxx - CDP API key secret\n * \n * Usage:\n * const server = new MoltsPayServer('./moltspay.services.json');\n * server.skill('text-to-video', async (params) => { ... });\n * server.listen(3000);\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { createServer, IncomingMessage, ServerResponse } from 'http';\nimport * as path from 'path';\nimport {\n FacilitatorRegistry,\n FacilitatorSelection,\n X402PaymentPayload,\n X402PaymentRequirements,\n} from '../facilitators/index.js';\nimport {\n ServicesManifest,\n ServiceConfig,\n SkillFunction,\n RegisteredSkill,\n MoltsPayServerOptions,\n} from './types.js';\n\nexport * from './types.js';\n\n// x402 constants\nconst X402_VERSION = 2;\nconst PAYMENT_REQUIRED_HEADER = 'x-payment-required';\nconst PAYMENT_HEADER = 'x-payment';\nconst PAYMENT_RESPONSE_HEADER = 'x-payment-response';\n\n// Token contract addresses by network\nconst TOKEN_ADDRESSES: Record<string, Record<string, string>> = {\n 'eip155:8453': {\n USDC: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n USDT: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',\n },\n 'eip155:84532': {\n USDC: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n USDT: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Same as USDC on testnet\n },\n 'eip155:137': {\n USDC: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n USDT: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',\n },\n};\n\n// Chain name to network ID mapping\nconst CHAIN_TO_NETWORK: Record<string, string> = {\n 'base': 'eip155:8453',\n 'base_sepolia': 'eip155:84532',\n 'polygon': 'eip155:137',\n};\n\n// EIP-712 domain info for tokens (per network)\n// Different networks may have different domain names for the same token\nconst TOKEN_DOMAINS: Record<string, Record<string, { name: string; version: string }>> = {\n // Base mainnet\n 'eip155:8453': {\n USDC: { name: 'USD Coin', version: '2' },\n USDT: { name: 'Tether USD', version: '2' },\n },\n // Base Sepolia testnet - USDC uses 'USDC' not 'USD Coin'\n 'eip155:84532': {\n USDC: { name: 'USDC', version: '2' },\n USDT: { name: 'USDC', version: '2' }, // Same contract as USDC on testnet\n },\n // Polygon mainnet\n 'eip155:137': {\n USDC: { name: 'USD Coin', version: '2' },\n USDT: { name: '(PoS) Tether USD', version: '2' },\n },\n};\n\n// Helper to get token domain for a network\nfunction getTokenDomain(network: string, token: string): { name: string; version: string } {\n const networkDomains = TOKEN_DOMAINS[network] || TOKEN_DOMAINS['eip155:8453']; // fallback to base mainnet\n return networkDomains[token] || { name: 'USD Coin', version: '2' };\n}\n\n// Helper to get accepted currencies with backward compatibility\nfunction getAcceptedCurrencies(config: ServiceConfig): string[] {\n return config.acceptedCurrencies ?? [config.currency];\n}\n\n/**\n * Load environment from .env files\n */\nfunction loadEnvFile(): void {\n const envPaths = [\n path.join(process.cwd(), '.env'),\n path.join(process.env.HOME || '', '.moltspay', '.env'),\n ];\n \n for (const envPath of envPaths) {\n if (existsSync(envPath)) {\n try {\n const content = readFileSync(envPath, 'utf-8');\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n if (!process.env[key]) {\n process.env[key] = value;\n }\n }\n console.log(`[MoltsPay] Loaded config from ${envPath}`);\n break;\n } catch {\n // Ignore errors\n }\n }\n }\n}\n\n/**\n * Extended server options with facilitator config\n */\nexport interface MoltsPayServerOptionsExtended extends MoltsPayServerOptions {\n /** Facilitator selection configuration */\n facilitators?: FacilitatorSelection;\n}\n\nexport class MoltsPayServer {\n private manifest: ServicesManifest;\n private skills: Map<string, RegisteredSkill> = new Map();\n private options: MoltsPayServerOptionsExtended;\n private registry: FacilitatorRegistry;\n private networkId: string;\n private useMainnet: boolean;\n\n constructor(servicesPath: string, options: MoltsPayServerOptionsExtended = {}) {\n // Load env files FIRST (before reading USE_MAINNET)\n loadEnvFile();\n \n // Load services manifest\n const content = readFileSync(servicesPath, 'utf-8');\n this.manifest = JSON.parse(content) as ServicesManifest;\n \n this.options = {\n port: options.port || 3000,\n host: options.host || '0.0.0.0',\n ...options,\n };\n\n // Determine default network from env (fallback only)\n // NOTE: Chain is auto-detected from client payment header (payment.network)\n // USE_MAINNET is only used as fallback when payment header omits network\n // Recommended: configure \"chains\" array in manifest instead\n this.useMainnet = process.env.USE_MAINNET?.toLowerCase() === 'true';\n this.networkId = this.useMainnet ? 'eip155:8453' : 'eip155:84532';\n\n // Create facilitator registry with config (env vars take precedence)\n const facilitatorConfig: FacilitatorSelection = options.facilitators || {\n primary: process.env.FACILITATOR_PRIMARY || 'cdp',\n fallback: process.env.FACILITATOR_FALLBACK?.split(',').filter(Boolean),\n strategy: (process.env.FACILITATOR_STRATEGY as any) || 'failover',\n config: {\n cdp: { useMainnet: this.useMainnet },\n },\n };\n this.registry = new FacilitatorRegistry(facilitatorConfig);\n\n // Get primary facilitator for logging\n const primaryFacilitator = this.registry.get(facilitatorConfig.primary);\n \n console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);\n console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);\n console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);\n \n // Log configured chains\n const chains = this.manifest.provider.chains;\n if (chains && chains.length > 0) {\n const chainNames = chains.map(c => c.chain || c.network).join(', ');\n console.log(`[MoltsPay] Chains: ${chainNames} (multi-chain enabled)`);\n } else {\n const networkName = this.useMainnet ? 'Base mainnet' : 'Base Sepolia (testnet)';\n console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);\n }\n \n console.log(`[MoltsPay] Facilitator: ${primaryFacilitator.displayName} (${facilitatorConfig.strategy || 'failover'})`);\n console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);\n }\n\n /**\n * Register a skill handler for a service\n */\n skill(serviceId: string, handler: SkillFunction): this {\n const config = this.manifest.services.find(s => s.id === serviceId);\n if (!config) {\n throw new Error(`Service '${serviceId}' not found in manifest`);\n }\n this.skills.set(serviceId, { id: serviceId, config, handler });\n return this;\n }\n\n /**\n * Get all configured chains for this provider\n * Returns array of { network, wallet, tokens } for each chain\n */\n private getProviderChains(): Array<{ network: string; wallet: string; tokens: string[] }> {\n const provider = this.manifest.provider;\n \n // If chains array is defined, use it\n // Supports both string array [\"base\", \"polygon\"] and object array [{chain, wallet, tokens}]\n if (provider.chains && provider.chains.length > 0) {\n return provider.chains.map(c => {\n const chainName = typeof c === 'string' ? c : c.chain;\n return {\n network: CHAIN_TO_NETWORK[chainName] || 'eip155:8453',\n wallet: (typeof c === 'object' ? c.wallet : null) || provider.wallet,\n tokens: (typeof c === 'object' ? c.tokens : null) || ['USDC'],\n };\n });\n }\n \n // Fallback to single chain (backward compat)\n const chain = provider.chain || 'base';\n const network = CHAIN_TO_NETWORK[chain] || this.networkId;\n return [{\n network,\n wallet: provider.wallet,\n tokens: ['USDC'],\n }];\n }\n\n /**\n * Get wallet address for a specific network\n */\n private getWalletForNetwork(network: string): string {\n const chains = this.getProviderChains();\n const chain = chains.find(c => c.network === network);\n return chain?.wallet || this.manifest.provider.wallet;\n }\n\n /**\n * Check if a network is accepted by this provider\n */\n private isNetworkAccepted(network: string): boolean {\n const chains = this.getProviderChains();\n return chains.some(c => c.network === network);\n }\n\n /**\n * Start HTTP server\n */\n listen(port?: number): void {\n const p = port || this.options.port || 3000;\n const host = this.options.host || '0.0.0.0';\n\n const server = createServer((req, res) => this.handleRequest(req, res));\n server.listen(p, host, () => {\n console.log(`[MoltsPay] Server listening on http://${host}:${p}`);\n console.log(`[MoltsPay] Endpoints:`);\n console.log(` GET /services - List available services`);\n console.log(` POST /execute - Execute service (x402 payment)`);\n console.log(` POST /proxy - Proxy payment for external services`);\n console.log(` GET /health - Health check (incl. facilitators)`);\n });\n }\n\n /**\n * Handle incoming request\n */\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // CORS\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Payment');\n res.setHeader('Access-Control-Expose-Headers', 'X-Payment-Required, X-Payment-Response');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n try {\n const url = new URL(req.url || '/', `http://${req.headers.host}`);\n \n if (url.pathname === '/services' && req.method === 'GET') {\n return this.handleGetServices(res);\n }\n\n // Standard discovery endpoint\n if (url.pathname === '/.well-known/agent-services.json' && req.method === 'GET') {\n return this.handleAgentServicesDiscovery(res);\n }\n\n if (url.pathname === '/health' && req.method === 'GET') {\n return await this.handleHealthCheck(res);\n }\n\n if (url.pathname === '/execute' && req.method === 'POST') {\n const body = await this.readBody(req);\n const paymentHeader = req.headers[PAYMENT_HEADER] as string | undefined;\n return await this.handleExecute(body, paymentHeader, res);\n }\n\n if (url.pathname === '/proxy' && req.method === 'POST') {\n // Check IP whitelist\n const clientIP = (req.headers['x-real-ip'] as string) || \n (req.headers['x-forwarded-for'] as string)?.split(',')[0]?.trim() ||\n req.socket.remoteAddress || '';\n if (!this.isProxyAllowed(clientIP)) {\n return this.sendJson(res, 403, { error: 'Forbidden: IP not allowed' });\n }\n const body = await this.readBody(req);\n const paymentHeader = req.headers[PAYMENT_HEADER] as string | undefined;\n return await this.handleProxy(body, paymentHeader, res);\n }\n\n // Not found\n this.sendJson(res, 404, { error: 'Not found' });\n } catch (err: any) {\n console.error('[MoltsPay] Error:', err);\n this.sendJson(res, 500, { error: err.message || 'Internal error' });\n }\n }\n\n /**\n * GET /.well-known/agent-services.json - Standard discovery endpoint\n */\n private handleAgentServicesDiscovery(res: ServerResponse): void {\n const services = this.manifest.services.map(s => ({\n id: s.id,\n name: s.name,\n description: s.description,\n price: s.price,\n currency: s.currency,\n acceptedCurrencies: getAcceptedCurrencies(s),\n input: s.input,\n output: s.output,\n available: this.skills.has(s.id),\n }));\n\n this.sendJson(res, 200, {\n version: '1.0',\n provider: {\n name: this.manifest.provider.name,\n description: this.manifest.provider.description,\n wallet: this.manifest.provider.wallet,\n chain: this.manifest.provider.chain || 'base',\n },\n services,\n endpoints: {\n services: '/services',\n execute: '/execute',\n health: '/health',\n },\n payment: {\n protocol: 'x402',\n version: X402_VERSION,\n network: this.networkId,\n schemes: ['exact'],\n mainnet: this.useMainnet,\n },\n });\n }\n\n /**\n * GET /services - List available services\n */\n private handleGetServices(res: ServerResponse): void {\n const services = this.manifest.services.map(s => ({\n id: s.id,\n name: s.name,\n description: s.description,\n price: s.price,\n currency: s.currency,\n acceptedCurrencies: getAcceptedCurrencies(s),\n input: s.input,\n output: s.output,\n available: this.skills.has(s.id),\n }));\n\n const selection = this.registry.getSelection();\n \n this.sendJson(res, 200, {\n provider: this.manifest.provider,\n services,\n x402: {\n version: X402_VERSION,\n network: this.networkId,\n schemes: ['exact'],\n facilitators: {\n primary: selection.primary,\n fallback: selection.fallback,\n strategy: selection.strategy,\n },\n mainnet: this.useMainnet,\n },\n });\n }\n\n /**\n * GET /health - Health check endpoint\n */\n private async handleHealthCheck(res: ServerResponse): Promise<void> {\n const facilitatorHealth = await this.registry.healthCheckAll();\n \n const allHealthy = Object.values(facilitatorHealth).every(h => h.healthy);\n \n this.sendJson(res, allHealthy ? 200 : 503, {\n status: allHealthy ? 'healthy' : 'degraded',\n network: this.networkId,\n facilitators: facilitatorHealth,\n services: this.manifest.services.length,\n registered: this.skills.size,\n });\n }\n\n /**\n * POST /execute - Execute service with x402 payment\n */\n private async handleExecute(\n body: any,\n paymentHeader: string | undefined,\n res: ServerResponse\n ): Promise<void> {\n const { service, params } = body;\n\n if (!service) {\n return this.sendJson(res, 400, { error: 'Missing service' });\n }\n\n const skill = this.skills.get(service);\n if (!skill) {\n return this.sendJson(res, 404, { error: `Service '${service}' not found or not registered` });\n }\n\n // Validate required params\n for (const [key, field] of Object.entries(skill.config.input)) {\n if (field.required && (!params || params[key] === undefined)) {\n return this.sendJson(res, 400, { error: `Missing required param: ${key}` });\n }\n }\n\n // If no payment header, return 402 with payment requirements\n if (!paymentHeader) {\n return this.sendPaymentRequired(skill.config, res);\n }\n\n // Parse payment payload\n let payment: X402PaymentPayload;\n try {\n const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');\n payment = JSON.parse(decoded);\n } catch {\n return this.sendJson(res, 400, { error: 'Invalid X-Payment header' });\n }\n\n // Validate basic payment fields\n const validation = this.validatePayment(payment, skill.config);\n if (!validation.valid) {\n return this.sendJson(res, 402, { error: validation.error });\n }\n\n // Detect which token is being used\n const paymentToken = this.detectPaymentToken(payment);\n if (paymentToken && !this.isTokenAccepted(skill.config, paymentToken)) {\n const accepted = getAcceptedCurrencies(skill.config);\n return this.sendJson(res, 402, { \n error: `Token ${paymentToken} not accepted. Accepted: ${accepted.join(', ')}` \n });\n }\n\n // Auto-detect chain from payment header (key insight: client specifies chain via --chain flag)\n // payment.network contains \"eip155:8453\" (base) or \"eip155:84532\" (base_sepolia) etc.\n // This allows provider to serve both mainnet and testnet without separate configuration\n const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;\n const paymentWallet = this.getWalletForNetwork(paymentNetwork);\n\n // Build requirements for facilitator using the detected token and network\n const requirements = this.buildPaymentRequirements(skill.config, paymentNetwork, paymentWallet, paymentToken);\n\n // Verify payment with facilitator (via registry)\n console.log(`[MoltsPay] Verifying payment on ${paymentNetwork}...`);\n const verifyResult = await this.registry.verify(payment, requirements);\n if (!verifyResult.valid) {\n return this.sendJson(res, 402, { \n error: `Payment verification failed: ${verifyResult.error}`,\n facilitator: verifyResult.facilitator,\n });\n }\n console.log(`[MoltsPay] Verified by ${verifyResult.facilitator}`);\n\n // Execute skill FIRST (pay-for-success) with timeout\n const timeoutSeconds = parseInt(process.env.SKILL_TIMEOUT_SECONDS || '1200');\n console.log(`[MoltsPay] Executing skill: ${service} (timeout: ${timeoutSeconds}s)`);\n let result: any;\n try {\n result = await Promise.race([\n skill.handler(params || {}),\n new Promise((_, reject) => \n setTimeout(() => reject(new Error(`Skill timeout after ${timeoutSeconds}s`)), timeoutSeconds * 1000)\n )\n ]);\n } catch (err: any) {\n console.error('[MoltsPay] Skill execution failed:', err.message);\n return this.sendJson(res, 500, {\n error: 'Service execution failed',\n message: err.message,\n });\n }\n\n // Skill succeeded - now settle payment with facilitator\n console.log(`[MoltsPay] Skill succeeded, settling payment...`);\n let settlement: any = null;\n try {\n settlement = await this.registry.settle(payment, requirements);\n console.log(`[MoltsPay] Payment settled by ${settlement.facilitator}: ${settlement.transaction || 'pending'}`);\n } catch (err: any) {\n console.error('[MoltsPay] Settlement failed:', err.message);\n }\n\n // Build response\n const responseHeaders: Record<string, string> = {};\n if (settlement?.success) {\n const responsePayload = {\n success: true,\n transaction: settlement.transaction,\n network: payment.network || payment.accepted?.network,\n facilitator: settlement.facilitator,\n };\n responseHeaders[PAYMENT_RESPONSE_HEADER] = Buffer.from(\n JSON.stringify(responsePayload)\n ).toString('base64');\n }\n\n this.sendJson(res, 200, {\n success: true,\n result,\n payment: settlement?.success \n ? { transaction: settlement.transaction, status: 'settled', facilitator: settlement.facilitator }\n : { status: 'pending' },\n }, responseHeaders);\n }\n\n /**\n * Return 402 with x402 payment requirements (v2 format)\n * Includes requirements for all chains and all accepted currencies\n */\n private sendPaymentRequired(config: ServiceConfig, res: ServerResponse): void {\n const acceptedTokens = getAcceptedCurrencies(config);\n const providerChains = this.getProviderChains();\n \n // Build requirements for each chain x token combination\n const accepts: X402PaymentRequirements[] = [];\n for (const chainConfig of providerChains) {\n for (const token of acceptedTokens) {\n // Only add if this chain supports this token\n if (chainConfig.tokens.includes(token)) {\n accepts.push(this.buildPaymentRequirements(config, chainConfig.network, chainConfig.wallet, token));\n }\n }\n }\n\n // Get list of accepted chains for response\n const acceptedChains = providerChains.map(c => {\n // Convert network ID to chain name for readability\n if (c.network === 'eip155:8453') return 'base';\n if (c.network === 'eip155:137') return 'polygon';\n return c.network;\n });\n\n const paymentRequired = {\n x402Version: X402_VERSION,\n accepts,\n acceptedCurrencies: acceptedTokens,\n acceptedChains,\n resource: {\n url: `/execute?service=${config.id}`,\n description: `${config.name} - $${config.price} ${config.currency}`,\n mimeType: 'application/json',\n },\n };\n\n const encoded = Buffer.from(JSON.stringify(paymentRequired)).toString('base64');\n\n res.writeHead(402, {\n 'Content-Type': 'application/json',\n [PAYMENT_REQUIRED_HEADER]: encoded,\n });\n res.end(JSON.stringify({\n error: 'Payment required',\n message: `Service requires $${config.price} ${config.currency}`,\n acceptedCurrencies: acceptedTokens,\n acceptedChains,\n x402: paymentRequired,\n }, null, 2));\n }\n\n /**\n * Basic payment validation\n */\n private validatePayment(\n payment: X402PaymentPayload,\n config: ServiceConfig\n ): { valid: boolean; error?: string } {\n if (payment.x402Version !== X402_VERSION) {\n return { valid: false, error: `Unsupported x402 version: ${payment.x402Version}` };\n }\n\n const scheme = payment.accepted?.scheme || payment.scheme;\n const network = payment.accepted?.network || payment.network || this.networkId;\n\n if (scheme !== 'exact') {\n return { valid: false, error: `Unsupported scheme: ${scheme}` };\n }\n\n // Check if payment network is one of our accepted networks\n if (!this.isNetworkAccepted(network)) {\n const acceptedChains = this.getProviderChains().map(c => c.network).join(', ');\n return { valid: false, error: `Network not accepted: ${network}. Accepted: ${acceptedChains}` };\n }\n\n return { valid: true };\n }\n\n /**\n * Build payment requirements for facilitator\n * Now supports multi-chain: takes network and wallet as parameters\n */\n private buildPaymentRequirements(\n config: ServiceConfig, \n network?: string, \n wallet?: string,\n token?: string\n ): X402PaymentRequirements {\n const amountInUnits = Math.floor(config.price * 1e6).toString();\n const acceptedTokens = getAcceptedCurrencies(config);\n \n // Use specified values or defaults\n const selectedNetwork = network || this.networkId;\n const selectedWallet = wallet || this.manifest.provider.wallet;\n const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];\n \n const tokenAddresses = TOKEN_ADDRESSES[selectedNetwork] || {};\n const tokenAddress = tokenAddresses[selectedToken];\n const tokenDomain = getTokenDomain(selectedNetwork, selectedToken);\n\n return {\n scheme: 'exact',\n network: selectedNetwork,\n asset: tokenAddress,\n amount: amountInUnits,\n payTo: selectedWallet,\n maxTimeoutSeconds: 300,\n extra: tokenDomain,\n };\n }\n\n /**\n * Detect which token is being used in the payment\n * Checks across all supported networks\n */\n private detectPaymentToken(payment: X402PaymentPayload): string | undefined {\n const asset = payment.accepted?.asset || (payment.payload as any)?.asset;\n if (!asset) return undefined;\n\n // Get payment network to check correct token addresses\n const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;\n const tokenAddresses = TOKEN_ADDRESSES[paymentNetwork] || {};\n \n for (const [symbol, address] of Object.entries(tokenAddresses)) {\n if (address && (address as string).toLowerCase() === asset.toLowerCase()) {\n return symbol;\n }\n }\n return undefined;\n }\n\n /**\n * Check if payment token is accepted for service\n */\n private isTokenAccepted(config: ServiceConfig, token: string): boolean {\n const accepted = getAcceptedCurrencies(config);\n return accepted.includes(token);\n }\n\n private async readBody(req: IncomingMessage): Promise<any> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', chunk => body += chunk);\n req.on('end', () => {\n try {\n resolve(body ? JSON.parse(body) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n }\n\n private sendJson(\n res: ServerResponse, \n status: number, \n data: any,\n extraHeaders?: Record<string, string>\n ): void {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (extraHeaders) {\n Object.assign(headers, extraHeaders);\n }\n res.writeHead(status, headers);\n res.end(JSON.stringify(data, null, 2));\n }\n\n /**\n * Check if IP is allowed for /proxy endpoint\n */\n private isProxyAllowed(clientIP: string): boolean {\n const allowedIPs = process.env.PROXY_ALLOWED_IPS?.split(',').map(ip => ip.trim()) || [];\n \n // If no whitelist configured, deny all (secure by default)\n if (allowedIPs.length === 0) {\n console.log(`[MoltsPay] /proxy denied: no PROXY_ALLOWED_IPS configured`);\n return false;\n }\n \n // Normalize IPv6 localhost\n const normalizedIP = clientIP === '::1' ? '127.0.0.1' : clientIP.replace('::ffff:', '');\n \n const allowed = allowedIPs.includes(normalizedIP) || allowedIPs.includes(clientIP);\n if (!allowed) {\n console.log(`[MoltsPay] /proxy denied for IP: ${clientIP} (normalized: ${normalizedIP})`);\n }\n return allowed;\n }\n\n /**\n * POST /proxy - Handle payment for external services (moltspay-creators)\n * \n * This endpoint allows other services to delegate x402 payment handling.\n * It does NOT execute any skill - just handles payment verification/settlement.\n * \n * Request body:\n * { wallet, amount, currency, chain, memo, serviceId, description }\n * \n * Without X-Payment header: returns 402 with payment requirements\n * With X-Payment header: verifies payment and returns result\n */\n private async handleProxy(\n body: any,\n paymentHeader: string | undefined,\n res: ServerResponse\n ): Promise<void> {\n const { wallet, amount, currency, chain, memo, serviceId, description } = body;\n\n // Validate required fields\n if (!wallet || !amount) {\n return this.sendJson(res, 400, { error: 'Missing required fields: wallet, amount' });\n }\n\n // Validate wallet format\n if (!/^0x[a-fA-F0-9]{40}$/.test(wallet)) {\n return this.sendJson(res, 400, { error: 'Invalid wallet address format' });\n }\n\n // Validate amount\n const amountNum = parseFloat(amount);\n if (isNaN(amountNum) || amountNum <= 0) {\n return this.sendJson(res, 400, { error: 'Invalid amount' });\n }\n \n // Validate chain if provided\n const supportedChains = ['base', 'polygon', 'base_sepolia'];\n if (chain && !supportedChains.includes(chain)) {\n return this.sendJson(res, 400, { error: `Unsupported chain: ${chain}. Supported: ${supportedChains.join(', ')}` });\n }\n\n // Build a synthetic service config for payment\n const proxyConfig: ServiceConfig = {\n id: serviceId || 'proxy',\n name: description || 'Proxy Payment',\n description: description || '',\n price: amountNum,\n currency: currency || 'USDC',\n function: '', // Not used\n input: {},\n output: {},\n };\n\n // Build payment requirements with the provided wallet and chain\n const requirements = this.buildProxyPaymentRequirements(proxyConfig, wallet, currency, chain);\n\n // If no payment header, return 402 with payment requirements\n if (!paymentHeader) {\n return this.sendProxyPaymentRequired(proxyConfig, wallet, memo, chain, res);\n }\n\n // Parse payment payload\n let payment: X402PaymentPayload;\n try {\n const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');\n payment = JSON.parse(decoded);\n } catch {\n return this.sendJson(res, 400, { error: 'Invalid X-Payment header' });\n }\n\n // Validate basic payment fields\n if (payment.x402Version !== X402_VERSION) {\n return this.sendJson(res, 402, { error: `Unsupported x402 version: ${payment.x402Version}` });\n }\n\n const scheme = payment.accepted?.scheme || payment.scheme;\n const network = payment.accepted?.network || payment.network;\n\n if (scheme !== 'exact') {\n return this.sendJson(res, 402, { error: `Unsupported scheme: ${scheme}` });\n }\n\n // Validate network matches requested chain (or default to provider's network)\n const expectedNetwork = chain ? (CHAIN_TO_NETWORK[chain] || this.networkId) : this.networkId;\n if (network !== expectedNetwork) {\n return this.sendJson(res, 402, { error: `Network mismatch: expected ${expectedNetwork}, got ${network}` });\n }\n\n // Verify payment with facilitator\n console.log(`[MoltsPay] /proxy: Verifying payment for ${wallet}...`);\n const verifyResult = await this.registry.verify(payment, requirements);\n if (!verifyResult.valid) {\n return this.sendJson(res, 402, { \n success: false,\n error: `Payment verification failed: ${verifyResult.error}`,\n facilitator: verifyResult.facilitator,\n });\n }\n console.log(`[MoltsPay] /proxy: Verified by ${verifyResult.facilitator}`);\n\n // Check if execution requested\n const { execute, service, params } = body;\n \n // If execute requested, run skill BEFORE settling (pay on success)\n if (execute && service) {\n console.log(`[MoltsPay] /proxy: Executing skill first (pay on success): ${service}`);\n const skill = this.skills.get(service);\n if (!skill) {\n // Service not found - don't settle, return error\n console.log(`[MoltsPay] /proxy: Service not found: ${service} - NOT settling`);\n return this.sendJson(res, 404, {\n success: false,\n paymentSettled: false,\n error: `Service not found: ${service}`,\n });\n }\n\n // Execute skill first (with timeout)\n const timeoutSeconds = parseInt(process.env.SKILL_TIMEOUT_SECONDS || '1200');\n let result: any;\n try {\n result = await Promise.race([\n skill.handler(params || {}),\n new Promise((_, reject) => \n setTimeout(() => reject(new Error(`Skill timeout after ${timeoutSeconds}s`)), timeoutSeconds * 1000)\n )\n ]);\n console.log(`[MoltsPay] /proxy: Skill succeeded, now settling payment...`);\n } catch (err: any) {\n // Skill failed or timeout - don't settle, client keeps their money\n console.error(`[MoltsPay] /proxy: Skill failed: ${err.message} - NOT settling`);\n return this.sendJson(res, 500, {\n success: false,\n paymentSettled: false,\n error: `Service execution failed: ${err.message}`,\n });\n }\n\n // Skill succeeded - now settle payment\n let settlement: any = null;\n try {\n settlement = await this.registry.settle(payment, requirements);\n console.log(`[MoltsPay] /proxy: Payment settled by ${settlement.facilitator}: ${settlement.transaction || 'pending'}`);\n } catch (err: any) {\n console.error('[MoltsPay] /proxy: Settlement failed:', err.message);\n // Skill succeeded but settlement failed - return result anyway with warning\n return this.sendJson(res, 200, {\n success: true,\n verified: true,\n settled: false,\n settlementError: err.message,\n from: (payment.payload as any)?.authorization?.from, // Buyer's wallet address\n paidTo: wallet,\n amount: amountNum,\n currency: currency || 'USDC',\n memo,\n result,\n });\n }\n\n return this.sendJson(res, 200, {\n success: true,\n verified: true,\n settled: settlement?.success || false,\n txHash: settlement?.transaction,\n from: (payment.payload as any)?.authorization?.from, // Buyer's wallet address\n paidTo: wallet,\n amount: amountNum,\n currency: currency || 'USDC',\n facilitator: settlement?.facilitator,\n memo,\n result,\n });\n }\n\n // No execution requested - settle immediately (payment-only mode)\n console.log(`[MoltsPay] /proxy: Settling payment (no execution)...`);\n let settlement: any = null;\n try {\n settlement = await this.registry.settle(payment, requirements);\n console.log(`[MoltsPay] /proxy: Payment settled by ${settlement.facilitator}: ${settlement.transaction || 'pending'}`);\n } catch (err: any) {\n console.error('[MoltsPay] /proxy: Settlement failed:', err.message);\n return this.sendJson(res, 500, {\n success: false,\n error: `Settlement failed: ${err.message}`,\n });\n }\n\n // Return success (payment only, no execution)\n this.sendJson(res, 200, {\n success: true,\n verified: true,\n settled: settlement?.success || false,\n txHash: settlement?.transaction,\n from: (payment.payload as any)?.authorization?.from, // Buyer's wallet address\n paidTo: wallet,\n amount: amountNum,\n currency: currency || 'USDC',\n facilitator: settlement?.facilitator,\n memo,\n });\n }\n\n /**\n * Build payment requirements for proxy endpoint (uses provided wallet)\n */\n private buildProxyPaymentRequirements(config: ServiceConfig, wallet: string, token?: string, chain?: string): X402PaymentRequirements {\n const amountInUnits = Math.floor(config.price * 1e6).toString();\n const acceptedTokens = getAcceptedCurrencies(config);\n \n // Determine network from chain parameter or use default\n const networkId = chain ? (CHAIN_TO_NETWORK[chain] || this.networkId) : this.networkId;\n \n // Use specified token or default to first accepted\n const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];\n const tokenAddresses = TOKEN_ADDRESSES[networkId] || TOKEN_ADDRESSES[this.networkId] || {};\n const tokenAddress = tokenAddresses[selectedToken];\n const tokenDomain = getTokenDomain(networkId, selectedToken);\n\n return {\n scheme: 'exact',\n network: networkId,\n asset: tokenAddress,\n amount: amountInUnits,\n payTo: wallet, // Use provided wallet, not manifest\n maxTimeoutSeconds: 300,\n extra: tokenDomain,\n };\n }\n\n /**\n * Return 402 with x402 payment requirements for proxy endpoint\n */\n private sendProxyPaymentRequired(\n config: ServiceConfig, \n wallet: string,\n memo: string | undefined,\n chain: string | undefined,\n res: ServerResponse\n ): void {\n const requirements = this.buildProxyPaymentRequirements(config, wallet, config.currency, chain);\n\n const paymentRequired = {\n x402Version: X402_VERSION,\n accepts: [requirements],\n resource: {\n url: `/proxy`,\n description: `${config.name} - $${config.price} ${config.currency}`,\n mimeType: 'application/json',\n memo,\n },\n };\n\n const encoded = Buffer.from(JSON.stringify(paymentRequired)).toString('base64');\n\n res.writeHead(402, {\n 'Content-Type': 'application/json',\n [PAYMENT_REQUIRED_HEADER]: encoded,\n });\n res.end(JSON.stringify({\n error: 'Payment required',\n message: `Payment requires $${config.price} ${config.currency}`,\n x402: paymentRequired,\n }, null, 2));\n }\n}\n","/**\n * Facilitator Interface\n * \n * A facilitator is a service that handles x402 payment verification and settlement.\n * This abstraction allows MoltsPay to support multiple facilitators.\n * \n * @see https://www.x402.org/ecosystem?category=facilitators\n */\n\n/**\n * x402 Payment Payload (from client)\n */\nexport interface X402PaymentPayload {\n x402Version: number;\n scheme?: string;\n network?: string;\n accepted?: {\n scheme: string;\n network: string;\n asset: string;\n amount: string;\n payTo: string;\n maxTimeoutSeconds: number;\n extra?: Record<string, unknown>;\n };\n payload: unknown;\n}\n\n/**\n * x402 Payment Requirements (server specifies what it accepts)\n */\nexport interface X402PaymentRequirements {\n scheme: string;\n network: string;\n asset: string;\n amount: string;\n payTo: string;\n maxTimeoutSeconds: number;\n extra?: Record<string, unknown>;\n}\n\n/**\n * Result of payment verification\n */\nexport interface VerifyResult {\n valid: boolean;\n error?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * Result of payment settlement\n */\nexport interface SettleResult {\n success: boolean;\n transaction?: string;\n error?: string;\n status?: string;\n}\n\n/**\n * Facilitator health check result\n */\nexport interface HealthCheckResult {\n healthy: boolean;\n latencyMs?: number;\n error?: string;\n}\n\n/**\n * Facilitator fee information (for selection strategies)\n */\nexport interface FacilitatorFee {\n perTx: number;\n currency: string;\n freeQuota?: number;\n}\n\n/**\n * Facilitator configuration\n */\nexport interface FacilitatorConfig {\n /** Facilitator endpoint URL */\n endpoint?: string;\n /** API key (if required) */\n apiKey?: string;\n /** API secret (if required) */\n apiSecret?: string;\n /** Additional config specific to facilitator */\n [key: string]: unknown;\n}\n\n/**\n * Facilitator Interface\n * \n * All facilitators must implement this interface.\n */\nexport interface Facilitator {\n /** Unique identifier for this facilitator */\n readonly name: string;\n \n /** Human-readable display name */\n readonly displayName: string;\n \n /** Supported networks (e.g., [\"eip155:8453\", \"eip155:84532\"]) */\n readonly supportedNetworks: string[];\n \n /**\n * Check if facilitator is available and responsive\n */\n healthCheck(): Promise<HealthCheckResult>;\n \n /**\n * Verify a payment signature without executing it\n * \n * @param paymentPayload - The x402 payment payload from client\n * @param requirements - The payment requirements from server\n */\n verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult>;\n \n /**\n * Settle a payment on-chain\n * \n * @param paymentPayload - The x402 payment payload from client\n * @param requirements - The payment requirements from server\n */\n settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult>;\n \n /**\n * Get current fee information (optional, for selection strategies)\n */\n getFee?(): Promise<FacilitatorFee>;\n \n /**\n * Check if this facilitator supports a given network\n */\n supportsNetwork(network: string): boolean;\n}\n\n/**\n * Base class with common functionality\n */\nexport abstract class BaseFacilitator implements Facilitator {\n abstract readonly name: string;\n abstract readonly displayName: string;\n abstract readonly supportedNetworks: string[];\n \n abstract healthCheck(): Promise<HealthCheckResult>;\n abstract verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult>;\n abstract settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult>;\n \n supportsNetwork(network: string): boolean {\n return this.supportedNetworks.includes(network);\n }\n}\n","/**\n * CDP Facilitator\n * \n * Coinbase Developer Platform x402 facilitator implementation.\n * Auto-detects mainnet vs testnet from chain ID in request.\n * \n * Supported networks:\n * - Base mainnet (eip155:8453)\n * - Polygon mainnet (eip155:137)\n * - Base Sepolia testnet (eip155:84532)\n * \n * @see https://docs.cdp.coinbase.com/x402/core-concepts/facilitator\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport * as path from 'path';\nimport {\n BaseFacilitator,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n FacilitatorFee,\n FacilitatorConfig,\n} from './interface.js';\n\n// x402 protocol version\nconst X402_VERSION = 2;\n\n// CDP Facilitator URL (handles both mainnet and testnet)\nconst CDP_URL = 'https://api.cdp.coinbase.com/platform/v2/x402';\n\n// Testnet chain IDs (for logging/info only - CDP auto-detects from network field)\nconst TESTNET_CHAIN_IDS = [84532]; // Base Sepolia\n\nexport interface CDPFacilitatorConfig extends FacilitatorConfig {\n /** CDP API Key ID (required) */\n apiKeyId?: string;\n /** CDP API Key Secret (required) */\n apiKeySecret?: string;\n}\n\n/**\n * Load environment from .env files\n */\nfunction loadEnvFile(): void {\n const envPaths = [\n path.join(process.cwd(), '.env'),\n path.join(process.env.HOME || '', '.moltspay', '.env'),\n ];\n \n for (const envPath of envPaths) {\n if (existsSync(envPath)) {\n try {\n const content = readFileSync(envPath, 'utf-8');\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n if (!process.env[key]) {\n process.env[key] = value;\n }\n }\n break;\n } catch {\n // Ignore errors\n }\n }\n }\n}\n\n/**\n * CDP (Coinbase Developer Platform) Facilitator\n * \n * Handles payment verification and settlement via Coinbase's x402 facilitator.\n */\nexport class CDPFacilitator extends BaseFacilitator {\n readonly name = 'cdp';\n readonly displayName = 'Coinbase CDP';\n readonly supportedNetworks: string[];\n \n private endpoint: string;\n private apiKeyId?: string;\n private apiKeySecret?: string;\n \n constructor(config: CDPFacilitatorConfig = {}) {\n super();\n \n // Load env files for credentials\n loadEnvFile();\n \n // Get credentials (required for CDP)\n this.apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;\n this.apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;\n \n // Single endpoint handles both mainnet and testnet (auto-detected from chain ID in request)\n this.endpoint = CDP_URL;\n \n // All supported networks - CDP handles both mainnet and testnet\n this.supportedNetworks = [\n 'eip155:8453', // Base mainnet\n 'eip155:137', // Polygon mainnet\n 'eip155:84532', // Base Sepolia (testnet)\n ];\n \n // Warn if missing credentials\n if (!this.apiKeyId || !this.apiKeySecret) {\n console.warn('[CDPFacilitator] WARNING: Missing CDP credentials!');\n console.warn('[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET in ~/.moltspay/.env');\n }\n }\n \n /**\n * Get auth headers for CDP API requests\n */\n private async getAuthHeaders(\n method: string,\n urlPath: string,\n body?: unknown\n ): Promise<Record<string, string>> {\n if (!this.apiKeyId || !this.apiKeySecret) {\n throw new Error('CDP credentials required. Set CDP_API_KEY_ID and CDP_API_KEY_SECRET');\n }\n \n try {\n const { getAuthHeaders } = await import('@coinbase/cdp-sdk/auth');\n \n return await getAuthHeaders({\n apiKeyId: this.apiKeyId,\n apiKeySecret: this.apiKeySecret,\n requestMethod: method,\n requestHost: 'api.cdp.coinbase.com',\n requestPath: urlPath,\n requestBody: body,\n });\n } catch (err: any) {\n throw new Error(`Failed to generate CDP auth: ${err.message}`);\n }\n }\n \n /**\n * Health check - verify facilitator is reachable\n */\n async healthCheck(): Promise<HealthCheckResult> {\n const start = Date.now();\n \n try {\n // For testnet, just check if x402.org responds\n // For mainnet, we could hit a health endpoint or just check DNS\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5000);\n \n const response = await fetch(this.endpoint.replace('/x402', ''), {\n method: 'HEAD',\n signal: controller.signal,\n }).catch(() => null);\n \n clearTimeout(timeout);\n \n const latencyMs = Date.now() - start;\n \n return {\n healthy: response !== null,\n latencyMs,\n };\n } catch (err: any) {\n return {\n healthy: false,\n error: err.message,\n latencyMs: Date.now() - start,\n };\n }\n }\n \n /**\n * Verify payment signature with facilitator\n */\n async verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult> {\n try {\n const requestBody = {\n x402Version: X402_VERSION,\n paymentPayload,\n paymentRequirements: requirements,\n };\n \n console.log('[CDP Verify] Payload:', JSON.stringify(paymentPayload, null, 2));\n \n const authHeaders = await this.getAuthHeaders(\n 'POST',\n '/platform/v2/x402/verify',\n requestBody\n );\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...authHeaders,\n };\n \n const response = await fetch(`${this.endpoint}/verify`, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n });\n \n const result = await response.json() as any;\n console.log('[CDP Verify] Response:', response.status, JSON.stringify(result));\n \n if (!response.ok || !result.isValid) {\n return {\n valid: false,\n error: result.invalidReason || result.error || 'Verification failed',\n details: result,\n };\n }\n \n return { valid: true, details: result };\n } catch (err: any) {\n return {\n valid: false,\n error: `Facilitator error: ${err.message}`,\n };\n }\n }\n \n /**\n * Settle payment on-chain via facilitator\n */\n async settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult> {\n try {\n const requestBody = {\n x402Version: X402_VERSION,\n paymentPayload,\n paymentRequirements: requirements,\n };\n \n const authHeaders = await this.getAuthHeaders(\n 'POST',\n '/platform/v2/x402/settle',\n requestBody\n );\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...authHeaders,\n };\n \n const response = await fetch(`${this.endpoint}/settle`, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n });\n \n const result = await response.json() as any;\n \n if (!response.ok || !result.success) {\n return {\n success: false,\n error: result.error || result.errorReason || 'Settlement failed',\n };\n }\n \n return {\n success: true,\n transaction: result.transaction,\n status: result.status || 'settled',\n };\n } catch (err: any) {\n return {\n success: false,\n error: `Settlement error: ${err.message}`,\n };\n }\n }\n \n /**\n * Get CDP fee information\n */\n async getFee(): Promise<FacilitatorFee> {\n // CDP pricing: 1000 free/month, then $0.001/tx\n return {\n perTx: 0.001,\n currency: 'USD',\n freeQuota: 1000,\n };\n }\n \n /**\n * Check if a chain ID is testnet\n */\n static isTestnet(chainId: number): boolean {\n return TESTNET_CHAIN_IDS.includes(chainId);\n }\n \n /**\n * Get configuration summary (for logging)\n */\n getConfigSummary(): string {\n const hasCredentials = !!(this.apiKeyId && this.apiKeySecret);\n const networks = this.supportedNetworks.join(', ');\n return `CDP Facilitator (networks: ${networks}, credentials: ${hasCredentials ? 'yes' : 'no'})`;\n }\n}\n","/**\n * Facilitator Registry\n * \n * Central registry for all available facilitators.\n * Supports selection strategies for failover, load balancing, etc.\n */\n\nimport {\n Facilitator,\n FacilitatorConfig,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n} from './interface.js';\nimport { CDPFacilitator, CDPFacilitatorConfig } from './cdp.js';\n\n/**\n * Selection strategy for choosing facilitators\n */\nexport type SelectionStrategy = \n | 'failover' // Use primary, switch to fallback on failure\n | 'cheapest' // Use facilitator with lowest fees\n | 'fastest' // Use first responder\n | 'random' // Random selection (load balancing)\n | 'roundrobin'; // Rotate through facilitators\n\n/**\n * Facilitator selection configuration\n */\nexport interface FacilitatorSelection {\n /** Primary facilitator to use */\n primary: string;\n /** Fallback facilitators (in order of preference) */\n fallback?: string[];\n /** Selection strategy */\n strategy?: SelectionStrategy;\n /** Per-facilitator config overrides */\n config?: Record<string, FacilitatorConfig>;\n}\n\n/**\n * Factory function type for creating facilitators\n */\ntype FacilitatorFactory = (config?: FacilitatorConfig) => Facilitator;\n\n/**\n * Facilitator Registry\n * \n * Manages available facilitators and provides selection logic.\n */\nexport class FacilitatorRegistry {\n private factories: Map<string, FacilitatorFactory> = new Map();\n private instances: Map<string, Facilitator> = new Map();\n private selection: FacilitatorSelection;\n private roundRobinIndex = 0;\n \n constructor(selection?: FacilitatorSelection) {\n // Register built-in facilitators\n this.registerFactory('cdp', (config) => new CDPFacilitator(config as CDPFacilitatorConfig));\n \n // Default selection\n this.selection = selection || { primary: 'cdp', strategy: 'failover' };\n }\n \n /**\n * Register a new facilitator factory\n */\n registerFactory(name: string, factory: FacilitatorFactory): void {\n this.factories.set(name, factory);\n }\n \n /**\n * Get or create a facilitator instance\n */\n get(name: string, config?: FacilitatorConfig): Facilitator {\n // Check cache first\n if (this.instances.has(name)) {\n return this.instances.get(name)!;\n }\n \n // Look up factory\n const factory = this.factories.get(name);\n if (!factory) {\n throw new Error(`Unknown facilitator: ${name}. Available: ${Array.from(this.factories.keys()).join(', ')}`);\n }\n \n // Merge config from selection\n const mergedConfig = {\n ...this.selection.config?.[name],\n ...config,\n };\n \n // Create and cache instance\n const instance = factory(mergedConfig);\n this.instances.set(name, instance);\n return instance;\n }\n \n /**\n * Get all configured facilitator names\n */\n getConfiguredNames(): string[] {\n const names = [this.selection.primary];\n if (this.selection.fallback) {\n names.push(...this.selection.fallback);\n }\n return names;\n }\n \n /**\n * Get list of facilitators based on selection strategy\n */\n private async getOrderedFacilitators(network: string): Promise<Facilitator[]> {\n const names = this.getConfiguredNames();\n const facilitators: Facilitator[] = [];\n \n for (const name of names) {\n try {\n const f = this.get(name);\n if (f.supportsNetwork(network)) {\n facilitators.push(f);\n }\n } catch (err) {\n console.warn(`[Registry] Failed to get facilitator ${name}:`, err);\n }\n }\n \n if (facilitators.length === 0) {\n throw new Error(`No facilitators available for network: ${network}`);\n }\n \n // Apply strategy\n switch (this.selection.strategy) {\n case 'random':\n return this.shuffle(facilitators);\n \n case 'roundrobin':\n this.roundRobinIndex = (this.roundRobinIndex + 1) % facilitators.length;\n return [\n ...facilitators.slice(this.roundRobinIndex),\n ...facilitators.slice(0, this.roundRobinIndex),\n ];\n \n case 'cheapest':\n return this.sortByCheapest(facilitators);\n \n case 'fastest':\n return this.sortByFastest(facilitators);\n \n case 'failover':\n default:\n return facilitators;\n }\n }\n \n private shuffle<T>(array: T[]): T[] {\n const result = [...array];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [result[i], result[j]] = [result[j], result[i]];\n }\n return result;\n }\n \n private async sortByCheapest(facilitators: Facilitator[]): Promise<Facilitator[]> {\n const withFees = await Promise.all(\n facilitators.map(async (f) => {\n try {\n const fee = await f.getFee?.();\n return { facilitator: f, perTx: fee?.perTx ?? Infinity };\n } catch {\n return { facilitator: f, perTx: Infinity };\n }\n })\n );\n withFees.sort((a, b) => a.perTx - b.perTx);\n return withFees.map(w => w.facilitator);\n }\n \n private async sortByFastest(facilitators: Facilitator[]): Promise<Facilitator[]> {\n const withLatency = await Promise.all(\n facilitators.map(async (f) => {\n try {\n const health = await f.healthCheck();\n return { facilitator: f, latency: health.latencyMs ?? Infinity };\n } catch {\n return { facilitator: f, latency: Infinity };\n }\n })\n );\n withLatency.sort((a, b) => a.latency - b.latency);\n return withLatency.map(w => w.facilitator);\n }\n \n /**\n * Verify payment using configured facilitators\n */\n async verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult & { facilitator: string }> {\n const network = paymentPayload.accepted?.network || paymentPayload.network || requirements.network;\n const facilitators = await this.getOrderedFacilitators(network);\n \n let lastError: string | undefined;\n \n for (const f of facilitators) {\n try {\n console.log(`[Registry] Trying ${f.name} for verify...`);\n const result = await f.verify(paymentPayload, requirements);\n \n if (result.valid) {\n console.log(`[Registry] ${f.name} verify succeeded`);\n return { ...result, facilitator: f.name };\n }\n \n lastError = result.error;\n console.log(`[Registry] ${f.name} verify failed: ${result.error}`);\n \n // For failover strategy, only try next if it's a network/server error\n if (this.selection.strategy === 'failover' && !this.isTransientError(result.error)) {\n // Permanent error (e.g., invalid signature) - don't try others\n break;\n }\n } catch (err: any) {\n lastError = err.message;\n console.error(`[Registry] ${f.name} error:`, err.message);\n }\n }\n \n return {\n valid: false,\n error: lastError || 'All facilitators failed',\n facilitator: 'none',\n };\n }\n \n /**\n * Settle payment using configured facilitators\n */\n async settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult & { facilitator: string }> {\n const network = paymentPayload.accepted?.network || paymentPayload.network || requirements.network;\n const facilitators = await this.getOrderedFacilitators(network);\n \n let lastError: string | undefined;\n \n for (const f of facilitators) {\n try {\n console.log(`[Registry] Trying ${f.name} for settle...`);\n const result = await f.settle(paymentPayload, requirements);\n \n if (result.success) {\n console.log(`[Registry] ${f.name} settle succeeded: ${result.transaction}`);\n return { ...result, facilitator: f.name };\n }\n \n lastError = result.error;\n console.log(`[Registry] ${f.name} settle failed: ${result.error}`);\n } catch (err: any) {\n lastError = err.message;\n console.error(`[Registry] ${f.name} error:`, err.message);\n }\n }\n \n return {\n success: false,\n error: lastError || 'All facilitators failed',\n facilitator: 'none',\n };\n }\n \n /**\n * Check health of all configured facilitators\n */\n async healthCheckAll(): Promise<Record<string, HealthCheckResult>> {\n const results: Record<string, HealthCheckResult> = {};\n \n for (const name of this.getConfiguredNames()) {\n try {\n const f = this.get(name);\n results[name] = await f.healthCheck();\n } catch (err: any) {\n results[name] = { healthy: false, error: err.message };\n }\n }\n \n return results;\n }\n \n /**\n * Check if an error is transient (network/server issue) vs permanent (bad request)\n */\n private isTransientError(error?: string): boolean {\n if (!error) return true;\n const transientPatterns = [\n /timeout/i,\n /network/i,\n /connection/i,\n /ECONNREFUSED/i,\n /ETIMEDOUT/i,\n /503/,\n /502/,\n /500/,\n ];\n return transientPatterns.some(p => p.test(error));\n }\n \n /**\n * Update selection configuration\n */\n setSelection(selection: FacilitatorSelection): void {\n this.selection = selection;\n // Clear cached instances to pick up new config\n this.instances.clear();\n }\n \n /**\n * Get current selection configuration\n */\n getSelection(): FacilitatorSelection {\n return { ...this.selection };\n }\n}\n\n// Default registry instance\nlet defaultRegistry: FacilitatorRegistry | null = null;\n\n/**\n * Get the default facilitator registry\n */\nexport function getDefaultRegistry(): FacilitatorRegistry {\n if (!defaultRegistry) {\n defaultRegistry = new FacilitatorRegistry();\n }\n return defaultRegistry;\n}\n\n/**\n * Create a new registry with custom selection\n */\nexport function createRegistry(selection?: FacilitatorSelection): FacilitatorRegistry {\n return new FacilitatorRegistry(selection);\n}\n"],"mappings":";AAgBA,SAAS,gBAAAA,eAAc,cAAAC,mBAAkB;AACzC,SAAS,oBAAqD;AAC9D,YAAYC,WAAU;;;ACkIf,IAAe,kBAAf,MAAsD;AAAA,EAe3D,gBAAgB,SAA0B;AACxC,WAAO,KAAK,kBAAkB,SAAS,OAAO;AAAA,EAChD;AACF;;;ACxJA,SAAS,cAAc,kBAAkB;AACzC,YAAY,UAAU;AAatB,IAAM,eAAe;AAGrB,IAAM,UAAU;AAGhB,IAAM,oBAAoB,CAAC,KAAK;AAYhC,SAAS,cAAoB;AAC3B,QAAM,WAAW;AAAA,IACV,UAAK,QAAQ,IAAI,GAAG,MAAM;AAAA,IAC1B,UAAK,QAAQ,IAAI,QAAQ,IAAI,aAAa,MAAM;AAAA,EACvD;AAEA,aAAW,WAAW,UAAU;AAC9B,QAAI,WAAW,OAAO,GAAG;AACvB,UAAI;AACF,cAAM,UAAU,aAAa,SAAS,OAAO;AAC7C,mBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,gBAAM,UAAU,KAAK,KAAK;AAC1B,cAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG;AACzC,gBAAM,UAAU,QAAQ,QAAQ,GAAG;AACnC,cAAI,YAAY,GAAI;AACpB,gBAAM,MAAM,QAAQ,MAAM,GAAG,OAAO,EAAE,KAAK;AAC3C,cAAI,QAAQ,QAAQ,MAAM,UAAU,CAAC,EAAE,KAAK;AAC5C,cAAK,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAC3C,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAAI;AAClD,oBAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,UAC3B;AACA,cAAI,CAAC,QAAQ,IAAI,GAAG,GAAG;AACrB,oBAAQ,IAAI,GAAG,IAAI;AAAA,UACrB;AAAA,QACF;AACA;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAOO,IAAM,iBAAN,cAA6B,gBAAgB;AAAA,EACzC,OAAO;AAAA,EACP,cAAc;AAAA,EACd;AAAA,EAED;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,SAA+B,CAAC,GAAG;AAC7C,UAAM;AAGN,gBAAY;AAGZ,SAAK,WAAW,OAAO,YAAY,QAAQ,IAAI;AAC/C,SAAK,eAAe,OAAO,gBAAgB,QAAQ,IAAI;AAGvD,SAAK,WAAW;AAGhB,SAAK,oBAAoB;AAAA,MACvB;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,IACF;AAGA,QAAI,CAAC,KAAK,YAAY,CAAC,KAAK,cAAc;AACxC,cAAQ,KAAK,oDAAoD;AACjE,cAAQ,KAAK,gFAAgF;AAAA,IAC/F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,eACZ,QACA,SACA,MACiC;AACjC,QAAI,CAAC,KAAK,YAAY,CAAC,KAAK,cAAc;AACxC,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACvF;AAEA,QAAI;AACF,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,wBAAwB;AAEhE,aAAO,MAAM,eAAe;AAAA,QAC1B,UAAU,KAAK;AAAA,QACf,cAAc,KAAK;AAAA,QACnB,eAAe;AAAA,QACf,aAAa;AAAA,QACb,aAAa;AAAA,QACb,aAAa;AAAA,MACf,CAAC;AAAA,IACH,SAAS,KAAU;AACjB,YAAM,IAAI,MAAM,gCAAgC,IAAI,OAAO,EAAE;AAAA,IAC/D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAA0C;AAC9C,UAAM,QAAQ,KAAK,IAAI;AAEvB,QAAI;AAGF,YAAM,aAAa,IAAI,gBAAgB;AACvC,YAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,GAAI;AAEzD,YAAM,WAAW,MAAM,MAAM,KAAK,SAAS,QAAQ,SAAS,EAAE,GAAG;AAAA,QAC/D,QAAQ;AAAA,QACR,QAAQ,WAAW;AAAA,MACrB,CAAC,EAAE,MAAM,MAAM,IAAI;AAEnB,mBAAa,OAAO;AAEpB,YAAM,YAAY,KAAK,IAAI,IAAI;AAE/B,aAAO;AAAA,QACL,SAAS,aAAa;AAAA,QACtB;AAAA,MACF;AAAA,IACF,SAAS,KAAU;AACjB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,IAAI;AAAA,QACX,WAAW,KAAK,IAAI,IAAI;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OACJ,gBACA,cACuB;AACvB,QAAI;AACF,YAAM,cAAc;AAAA,QAClB,aAAa;AAAA,QACb;AAAA,QACA,qBAAqB;AAAA,MACvB;AAEA,cAAQ,IAAI,yBAAyB,KAAK,UAAU,gBAAgB,MAAM,CAAC,CAAC;AAE5E,YAAM,cAAc,MAAM,KAAK;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,UAAkC;AAAA,QACtC,gBAAgB;AAAA,QAChB,GAAG;AAAA,MACL;AAEA,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,QAAQ,WAAW;AAAA,QACtD,QAAQ;AAAA,QACR;AAAA,QACA,MAAM,KAAK,UAAU,WAAW;AAAA,MAClC,CAAC;AAED,YAAM,SAAS,MAAM,SAAS,KAAK;AACnC,cAAQ,IAAI,0BAA0B,SAAS,QAAQ,KAAK,UAAU,MAAM,CAAC;AAE7E,UAAI,CAAC,SAAS,MAAM,CAAC,OAAO,SAAS;AACnC,eAAO;AAAA,UACL,OAAO;AAAA,UACP,OAAO,OAAO,iBAAiB,OAAO,SAAS;AAAA,UAC/C,SAAS;AAAA,QACX;AAAA,MACF;AAEA,aAAO,EAAE,OAAO,MAAM,SAAS,OAAO;AAAA,IACxC,SAAS,KAAU;AACjB,aAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,sBAAsB,IAAI,OAAO;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OACJ,gBACA,cACuB;AACvB,QAAI;AACF,YAAM,cAAc;AAAA,QAClB,aAAa;AAAA,QACb;AAAA,QACA,qBAAqB;AAAA,MACvB;AAEA,YAAM,cAAc,MAAM,KAAK;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,UAAkC;AAAA,QACtC,gBAAgB;AAAA,QAChB,GAAG;AAAA,MACL;AAEA,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,QAAQ,WAAW;AAAA,QACtD,QAAQ;AAAA,QACR;AAAA,QACA,MAAM,KAAK,UAAU,WAAW;AAAA,MAClC,CAAC;AAED,YAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,UAAI,CAAC,SAAS,MAAM,CAAC,OAAO,SAAS;AACnC,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,OAAO,SAAS,OAAO,eAAe;AAAA,QAC/C;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa,OAAO;AAAA,QACpB,QAAQ,OAAO,UAAU;AAAA,MAC3B;AAAA,IACF,SAAS,KAAU;AACjB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,qBAAqB,IAAI,OAAO;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAkC;AAEtC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAAU,SAA0B;AACzC,WAAO,kBAAkB,SAAS,OAAO;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,mBAA2B;AACzB,UAAM,iBAAiB,CAAC,EAAE,KAAK,YAAY,KAAK;AAChD,UAAM,WAAW,KAAK,kBAAkB,KAAK,IAAI;AACjD,WAAO,8BAA8B,QAAQ,kBAAkB,iBAAiB,QAAQ,IAAI;AAAA,EAC9F;AACF;;;ACvQO,IAAM,sBAAN,MAA0B;AAAA,EACvB,YAA6C,oBAAI,IAAI;AAAA,EACrD,YAAsC,oBAAI,IAAI;AAAA,EAC9C;AAAA,EACA,kBAAkB;AAAA,EAE1B,YAAY,WAAkC;AAE5C,SAAK,gBAAgB,OAAO,CAAC,WAAW,IAAI,eAAe,MAA8B,CAAC;AAG1F,SAAK,YAAY,aAAa,EAAE,SAAS,OAAO,UAAU,WAAW;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,MAAc,SAAmC;AAC/D,SAAK,UAAU,IAAI,MAAM,OAAO;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,MAAc,QAAyC;AAEzD,QAAI,KAAK,UAAU,IAAI,IAAI,GAAG;AAC5B,aAAO,KAAK,UAAU,IAAI,IAAI;AAAA,IAChC;AAGA,UAAM,UAAU,KAAK,UAAU,IAAI,IAAI;AACvC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,wBAAwB,IAAI,gBAAgB,MAAM,KAAK,KAAK,UAAU,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,IAC5G;AAGA,UAAM,eAAe;AAAA,MACnB,GAAG,KAAK,UAAU,SAAS,IAAI;AAAA,MAC/B,GAAG;AAAA,IACL;AAGA,UAAM,WAAW,QAAQ,YAAY;AACrC,SAAK,UAAU,IAAI,MAAM,QAAQ;AACjC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,qBAA+B;AAC7B,UAAM,QAAQ,CAAC,KAAK,UAAU,OAAO;AACrC,QAAI,KAAK,UAAU,UAAU;AAC3B,YAAM,KAAK,GAAG,KAAK,UAAU,QAAQ;AAAA,IACvC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,uBAAuB,SAAyC;AAC5E,UAAM,QAAQ,KAAK,mBAAmB;AACtC,UAAM,eAA8B,CAAC;AAErC,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,cAAM,IAAI,KAAK,IAAI,IAAI;AACvB,YAAI,EAAE,gBAAgB,OAAO,GAAG;AAC9B,uBAAa,KAAK,CAAC;AAAA,QACrB;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,KAAK,wCAAwC,IAAI,KAAK,GAAG;AAAA,MACnE;AAAA,IACF;AAEA,QAAI,aAAa,WAAW,GAAG;AAC7B,YAAM,IAAI,MAAM,0CAA0C,OAAO,EAAE;AAAA,IACrE;AAGA,YAAQ,KAAK,UAAU,UAAU;AAAA,MAC/B,KAAK;AACH,eAAO,KAAK,QAAQ,YAAY;AAAA,MAElC,KAAK;AACH,aAAK,mBAAmB,KAAK,kBAAkB,KAAK,aAAa;AACjE,eAAO;AAAA,UACL,GAAG,aAAa,MAAM,KAAK,eAAe;AAAA,UAC1C,GAAG,aAAa,MAAM,GAAG,KAAK,eAAe;AAAA,QAC/C;AAAA,MAEF,KAAK;AACH,eAAO,KAAK,eAAe,YAAY;AAAA,MAEzC,KAAK;AACH,eAAO,KAAK,cAAc,YAAY;AAAA,MAExC,KAAK;AAAA,MACL;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,QAAW,OAAiB;AAClC,UAAM,SAAS,CAAC,GAAG,KAAK;AACxB,aAAS,IAAI,OAAO,SAAS,GAAG,IAAI,GAAG,KAAK;AAC1C,YAAM,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE;AAC5C,OAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AAAA,IAChD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,eAAe,cAAqD;AAChF,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,aAAa,IAAI,OAAO,MAAM;AAC5B,YAAI;AACF,gBAAM,MAAM,MAAM,EAAE,SAAS;AAC7B,iBAAO,EAAE,aAAa,GAAG,OAAO,KAAK,SAAS,SAAS;AAAA,QACzD,QAAQ;AACN,iBAAO,EAAE,aAAa,GAAG,OAAO,SAAS;AAAA,QAC3C;AAAA,MACF,CAAC;AAAA,IACH;AACA,aAAS,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACzC,WAAO,SAAS,IAAI,OAAK,EAAE,WAAW;AAAA,EACxC;AAAA,EAEA,MAAc,cAAc,cAAqD;AAC/E,UAAM,cAAc,MAAM,QAAQ;AAAA,MAChC,aAAa,IAAI,OAAO,MAAM;AAC5B,YAAI;AACF,gBAAM,SAAS,MAAM,EAAE,YAAY;AACnC,iBAAO,EAAE,aAAa,GAAG,SAAS,OAAO,aAAa,SAAS;AAAA,QACjE,QAAQ;AACN,iBAAO,EAAE,aAAa,GAAG,SAAS,SAAS;AAAA,QAC7C;AAAA,MACF,CAAC;AAAA,IACH;AACA,gBAAY,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AAChD,WAAO,YAAY,IAAI,OAAK,EAAE,WAAW;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OACJ,gBACA,cACiD;AACjD,UAAM,UAAU,eAAe,UAAU,WAAW,eAAe,WAAW,aAAa;AAC3F,UAAM,eAAe,MAAM,KAAK,uBAAuB,OAAO;AAE9D,QAAI;AAEJ,eAAW,KAAK,cAAc;AAC5B,UAAI;AACF,gBAAQ,IAAI,qBAAqB,EAAE,IAAI,gBAAgB;AACvD,cAAM,SAAS,MAAM,EAAE,OAAO,gBAAgB,YAAY;AAE1D,YAAI,OAAO,OAAO;AAChB,kBAAQ,IAAI,cAAc,EAAE,IAAI,mBAAmB;AACnD,iBAAO,EAAE,GAAG,QAAQ,aAAa,EAAE,KAAK;AAAA,QAC1C;AAEA,oBAAY,OAAO;AACnB,gBAAQ,IAAI,cAAc,EAAE,IAAI,mBAAmB,OAAO,KAAK,EAAE;AAGjE,YAAI,KAAK,UAAU,aAAa,cAAc,CAAC,KAAK,iBAAiB,OAAO,KAAK,GAAG;AAElF;AAAA,QACF;AAAA,MACF,SAAS,KAAU;AACjB,oBAAY,IAAI;AAChB,gBAAQ,MAAM,cAAc,EAAE,IAAI,WAAW,IAAI,OAAO;AAAA,MAC1D;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,aAAa;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OACJ,gBACA,cACiD;AACjD,UAAM,UAAU,eAAe,UAAU,WAAW,eAAe,WAAW,aAAa;AAC3F,UAAM,eAAe,MAAM,KAAK,uBAAuB,OAAO;AAE9D,QAAI;AAEJ,eAAW,KAAK,cAAc;AAC5B,UAAI;AACF,gBAAQ,IAAI,qBAAqB,EAAE,IAAI,gBAAgB;AACvD,cAAM,SAAS,MAAM,EAAE,OAAO,gBAAgB,YAAY;AAE1D,YAAI,OAAO,SAAS;AAClB,kBAAQ,IAAI,cAAc,EAAE,IAAI,sBAAsB,OAAO,WAAW,EAAE;AAC1E,iBAAO,EAAE,GAAG,QAAQ,aAAa,EAAE,KAAK;AAAA,QAC1C;AAEA,oBAAY,OAAO;AACnB,gBAAQ,IAAI,cAAc,EAAE,IAAI,mBAAmB,OAAO,KAAK,EAAE;AAAA,MACnE,SAAS,KAAU;AACjB,oBAAY,IAAI;AAChB,gBAAQ,MAAM,cAAc,EAAE,IAAI,WAAW,IAAI,OAAO;AAAA,MAC1D;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,aAAa;AAAA,MACpB,aAAa;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAA6D;AACjE,UAAM,UAA6C,CAAC;AAEpD,eAAW,QAAQ,KAAK,mBAAmB,GAAG;AAC5C,UAAI;AACF,cAAM,IAAI,KAAK,IAAI,IAAI;AACvB,gBAAQ,IAAI,IAAI,MAAM,EAAE,YAAY;AAAA,MACtC,SAAS,KAAU;AACjB,gBAAQ,IAAI,IAAI,EAAE,SAAS,OAAO,OAAO,IAAI,QAAQ;AAAA,MACvD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,OAAyB;AAChD,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,oBAAoB;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,kBAAkB,KAAK,OAAK,EAAE,KAAK,KAAK,CAAC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,WAAuC;AAClD,SAAK,YAAY;AAEjB,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,eAAqC;AACnC,WAAO,EAAE,GAAG,KAAK,UAAU;AAAA,EAC7B;AACF;;;AHnSA,IAAMC,gBAAe;AACrB,IAAM,0BAA0B;AAChC,IAAM,iBAAiB;AACvB,IAAM,0BAA0B;AAGhC,IAAM,kBAA0D;AAAA,EAC9D,eAAe;AAAA,IACb,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EACA,gBAAgB;AAAA,IACd,MAAM;AAAA,IACN,MAAM;AAAA;AAAA,EACR;AAAA,EACA,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACF;AAGA,IAAM,mBAA2C;AAAA,EAC/C,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,WAAW;AACb;AAIA,IAAM,gBAAmF;AAAA;AAAA,EAEvF,eAAe;AAAA,IACb,MAAM,EAAE,MAAM,YAAY,SAAS,IAAI;AAAA,IACvC,MAAM,EAAE,MAAM,cAAc,SAAS,IAAI;AAAA,EAC3C;AAAA;AAAA,EAEA,gBAAgB;AAAA,IACd,MAAM,EAAE,MAAM,QAAQ,SAAS,IAAI;AAAA,IACnC,MAAM,EAAE,MAAM,QAAQ,SAAS,IAAI;AAAA;AAAA,EACrC;AAAA;AAAA,EAEA,cAAc;AAAA,IACZ,MAAM,EAAE,MAAM,YAAY,SAAS,IAAI;AAAA,IACvC,MAAM,EAAE,MAAM,oBAAoB,SAAS,IAAI;AAAA,EACjD;AACF;AAGA,SAAS,eAAe,SAAiB,OAAkD;AACzF,QAAM,iBAAiB,cAAc,OAAO,KAAK,cAAc,aAAa;AAC5E,SAAO,eAAe,KAAK,KAAK,EAAE,MAAM,YAAY,SAAS,IAAI;AACnE;AAGA,SAAS,sBAAsB,QAAiC;AAC9D,SAAO,OAAO,sBAAsB,CAAC,OAAO,QAAQ;AACtD;AAKA,SAASC,eAAoB;AAC3B,QAAM,WAAW;AAAA,IACV,WAAK,QAAQ,IAAI,GAAG,MAAM;AAAA,IAC1B,WAAK,QAAQ,IAAI,QAAQ,IAAI,aAAa,MAAM;AAAA,EACvD;AAEA,aAAW,WAAW,UAAU;AAC9B,QAAIC,YAAW,OAAO,GAAG;AACvB,UAAI;AACF,cAAM,UAAUC,cAAa,SAAS,OAAO;AAC7C,mBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,gBAAM,UAAU,KAAK,KAAK;AAC1B,cAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG;AACzC,gBAAM,UAAU,QAAQ,QAAQ,GAAG;AACnC,cAAI,YAAY,GAAI;AACpB,gBAAM,MAAM,QAAQ,MAAM,GAAG,OAAO,EAAE,KAAK;AAC3C,cAAI,QAAQ,QAAQ,MAAM,UAAU,CAAC,EAAE,KAAK;AAC5C,cAAK,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAC3C,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAAI;AAClD,oBAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,UAC3B;AACA,cAAI,CAAC,QAAQ,IAAI,GAAG,GAAG;AACrB,oBAAQ,IAAI,GAAG,IAAI;AAAA,UACrB;AAAA,QACF;AACA,gBAAQ,IAAI,iCAAiC,OAAO,EAAE;AACtD;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAUO,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EACA,SAAuC,oBAAI,IAAI;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,cAAsB,UAAyC,CAAC,GAAG;AAE7E,IAAAF,aAAY;AAGZ,UAAM,UAAUE,cAAa,cAAc,OAAO;AAClD,SAAK,WAAW,KAAK,MAAM,OAAO;AAElC,SAAK,UAAU;AAAA,MACb,MAAM,QAAQ,QAAQ;AAAA,MACtB,MAAM,QAAQ,QAAQ;AAAA,MACtB,GAAG;AAAA,IACL;AAMA,SAAK,aAAa,QAAQ,IAAI,aAAa,YAAY,MAAM;AAC7D,SAAK,YAAY,KAAK,aAAa,gBAAgB;AAGnD,UAAM,oBAA0C,QAAQ,gBAAgB;AAAA,MACtE,SAAS,QAAQ,IAAI,uBAAuB;AAAA,MAC5C,UAAU,QAAQ,IAAI,sBAAsB,MAAM,GAAG,EAAE,OAAO,OAAO;AAAA,MACrE,UAAW,QAAQ,IAAI,wBAAgC;AAAA,MACvD,QAAQ;AAAA,QACN,KAAK,EAAE,YAAY,KAAK,WAAW;AAAA,MACrC;AAAA,IACF;AACA,SAAK,WAAW,IAAI,oBAAoB,iBAAiB;AAGzD,UAAM,qBAAqB,KAAK,SAAS,IAAI,kBAAkB,OAAO;AAEtE,YAAQ,IAAI,qBAAqB,KAAK,SAAS,SAAS,MAAM,kBAAkB,YAAY,EAAE;AAC9F,YAAQ,IAAI,wBAAwB,KAAK,SAAS,SAAS,IAAI,EAAE;AACjE,YAAQ,IAAI,8BAA8B,KAAK,SAAS,SAAS,MAAM,EAAE;AAGzE,UAAM,SAAS,KAAK,SAAS,SAAS;AACtC,QAAI,UAAU,OAAO,SAAS,GAAG;AAC/B,YAAM,aAAa,OAAO,IAAI,OAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,IAAI;AAClE,cAAQ,IAAI,sBAAsB,UAAU,wBAAwB;AAAA,IACtE,OAAO;AACL,YAAM,cAAc,KAAK,aAAa,iBAAiB;AACvD,cAAQ,IAAI,uBAAuB,KAAK,SAAS,KAAK,WAAW,GAAG;AAAA,IACtE;AAEA,YAAQ,IAAI,2BAA2B,mBAAmB,WAAW,KAAK,kBAAkB,YAAY,UAAU,GAAG;AACrH,YAAQ,IAAI,gEAAgE;AAAA,EAC9E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAmB,SAA8B;AACrD,UAAM,SAAS,KAAK,SAAS,SAAS,KAAK,OAAK,EAAE,OAAO,SAAS;AAClE,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,YAAY,SAAS,yBAAyB;AAAA,IAChE;AACA,SAAK,OAAO,IAAI,WAAW,EAAE,IAAI,WAAW,QAAQ,QAAQ,CAAC;AAC7D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAkF;AACxF,UAAM,WAAW,KAAK,SAAS;AAI/B,QAAI,SAAS,UAAU,SAAS,OAAO,SAAS,GAAG;AACjD,aAAO,SAAS,OAAO,IAAI,OAAK;AAC9B,cAAM,YAAY,OAAO,MAAM,WAAW,IAAI,EAAE;AAChD,eAAO;AAAA,UACL,SAAS,iBAAiB,SAAS,KAAK;AAAA,UACxC,SAAS,OAAO,MAAM,WAAW,EAAE,SAAS,SAAS,SAAS;AAAA,UAC9D,SAAS,OAAO,MAAM,WAAW,EAAE,SAAS,SAAS,CAAC,MAAM;AAAA,QAC9D;AAAA,MACF,CAAC;AAAA,IACH;AAGA,UAAM,QAAQ,SAAS,SAAS;AAChC,UAAM,UAAU,iBAAiB,KAAK,KAAK,KAAK;AAChD,WAAO,CAAC;AAAA,MACN;AAAA,MACA,QAAQ,SAAS;AAAA,MACjB,QAAQ,CAAC,MAAM;AAAA,IACjB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,SAAyB;AACnD,UAAM,SAAS,KAAK,kBAAkB;AACtC,UAAM,QAAQ,OAAO,KAAK,OAAK,EAAE,YAAY,OAAO;AACpD,WAAO,OAAO,UAAU,KAAK,SAAS,SAAS;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,SAA0B;AAClD,UAAM,SAAS,KAAK,kBAAkB;AACtC,WAAO,OAAO,KAAK,OAAK,EAAE,YAAY,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,MAAqB;AAC1B,UAAM,IAAI,QAAQ,KAAK,QAAQ,QAAQ;AACvC,UAAM,OAAO,KAAK,QAAQ,QAAQ;AAElC,UAAM,SAAS,aAAa,CAAC,KAAK,QAAQ,KAAK,cAAc,KAAK,GAAG,CAAC;AACtE,WAAO,OAAO,GAAG,MAAM,MAAM;AAC3B,cAAQ,IAAI,yCAAyC,IAAI,IAAI,CAAC,EAAE;AAChE,cAAQ,IAAI,uBAAuB;AACnC,cAAQ,IAAI,gDAAgD;AAC5D,cAAQ,IAAI,uDAAuD;AACnE,cAAQ,IAAI,4DAA4D;AACxE,cAAQ,IAAI,0DAA0D;AAAA,IACxE,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAc,KAAsB,KAAoC;AAEpF,QAAI,UAAU,+BAA+B,GAAG;AAChD,QAAI,UAAU,gCAAgC,oBAAoB;AAClE,QAAI,UAAU,gCAAgC,yBAAyB;AACvE,QAAI,UAAU,iCAAiC,wCAAwC;AAEvF,QAAI,IAAI,WAAW,WAAW;AAC5B,UAAI,UAAU,GAAG;AACjB,UAAI,IAAI;AACR;AAAA,IACF;AAEA,QAAI;AACF,YAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,IAAI,QAAQ,IAAI,EAAE;AAEhE,UAAI,IAAI,aAAa,eAAe,IAAI,WAAW,OAAO;AACxD,eAAO,KAAK,kBAAkB,GAAG;AAAA,MACnC;AAGA,UAAI,IAAI,aAAa,sCAAsC,IAAI,WAAW,OAAO;AAC/E,eAAO,KAAK,6BAA6B,GAAG;AAAA,MAC9C;AAEA,UAAI,IAAI,aAAa,aAAa,IAAI,WAAW,OAAO;AACtD,eAAO,MAAM,KAAK,kBAAkB,GAAG;AAAA,MACzC;AAEA,UAAI,IAAI,aAAa,cAAc,IAAI,WAAW,QAAQ;AACxD,cAAM,OAAO,MAAM,KAAK,SAAS,GAAG;AACpC,cAAM,gBAAgB,IAAI,QAAQ,cAAc;AAChD,eAAO,MAAM,KAAK,cAAc,MAAM,eAAe,GAAG;AAAA,MAC1D;AAEA,UAAI,IAAI,aAAa,YAAY,IAAI,WAAW,QAAQ;AAEtD,cAAM,WAAY,IAAI,QAAQ,WAAW,KACvB,IAAI,QAAQ,iBAAiB,GAAc,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,KAChE,IAAI,OAAO,iBAAiB;AAC7C,YAAI,CAAC,KAAK,eAAe,QAAQ,GAAG;AAClC,iBAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,4BAA4B,CAAC;AAAA,QACvE;AACA,cAAM,OAAO,MAAM,KAAK,SAAS,GAAG;AACpC,cAAM,gBAAgB,IAAI,QAAQ,cAAc;AAChD,eAAO,MAAM,KAAK,YAAY,MAAM,eAAe,GAAG;AAAA,MACxD;AAGA,WAAK,SAAS,KAAK,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,IAChD,SAAS,KAAU;AACjB,cAAQ,MAAM,qBAAqB,GAAG;AACtC,WAAK,SAAS,KAAK,KAAK,EAAE,OAAO,IAAI,WAAW,iBAAiB,CAAC;AAAA,IACpE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,6BAA6B,KAA2B;AAC9D,UAAM,WAAW,KAAK,SAAS,SAAS,IAAI,QAAM;AAAA,MAChD,IAAI,EAAE;AAAA,MACN,MAAM,EAAE;AAAA,MACR,aAAa,EAAE;AAAA,MACf,OAAO,EAAE;AAAA,MACT,UAAU,EAAE;AAAA,MACZ,oBAAoB,sBAAsB,CAAC;AAAA,MAC3C,OAAO,EAAE;AAAA,MACT,QAAQ,EAAE;AAAA,MACV,WAAW,KAAK,OAAO,IAAI,EAAE,EAAE;AAAA,IACjC,EAAE;AAEF,SAAK,SAAS,KAAK,KAAK;AAAA,MACtB,SAAS;AAAA,MACT,UAAU;AAAA,QACR,MAAM,KAAK,SAAS,SAAS;AAAA,QAC7B,aAAa,KAAK,SAAS,SAAS;AAAA,QACpC,QAAQ,KAAK,SAAS,SAAS;AAAA,QAC/B,OAAO,KAAK,SAAS,SAAS,SAAS;AAAA,MACzC;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT,UAAU;AAAA,QACV,SAAS;AAAA,QACT,QAAQ;AAAA,MACV;AAAA,MACA,SAAS;AAAA,QACP,UAAU;AAAA,QACV,SAASH;AAAA,QACT,SAAS,KAAK;AAAA,QACd,SAAS,CAAC,OAAO;AAAA,QACjB,SAAS,KAAK;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,KAA2B;AACnD,UAAM,WAAW,KAAK,SAAS,SAAS,IAAI,QAAM;AAAA,MAChD,IAAI,EAAE;AAAA,MACN,MAAM,EAAE;AAAA,MACR,aAAa,EAAE;AAAA,MACf,OAAO,EAAE;AAAA,MACT,UAAU,EAAE;AAAA,MACZ,oBAAoB,sBAAsB,CAAC;AAAA,MAC3C,OAAO,EAAE;AAAA,MACT,QAAQ,EAAE;AAAA,MACV,WAAW,KAAK,OAAO,IAAI,EAAE,EAAE;AAAA,IACjC,EAAE;AAEF,UAAM,YAAY,KAAK,SAAS,aAAa;AAE7C,SAAK,SAAS,KAAK,KAAK;AAAA,MACtB,UAAU,KAAK,SAAS;AAAA,MACxB;AAAA,MACA,MAAM;AAAA,QACJ,SAASA;AAAA,QACT,SAAS,KAAK;AAAA,QACd,SAAS,CAAC,OAAO;AAAA,QACjB,cAAc;AAAA,UACZ,SAAS,UAAU;AAAA,UACnB,UAAU,UAAU;AAAA,UACpB,UAAU,UAAU;AAAA,QACtB;AAAA,QACA,SAAS,KAAK;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,kBAAkB,KAAoC;AAClE,UAAM,oBAAoB,MAAM,KAAK,SAAS,eAAe;AAE7D,UAAM,aAAa,OAAO,OAAO,iBAAiB,EAAE,MAAM,OAAK,EAAE,OAAO;AAExE,SAAK,SAAS,KAAK,aAAa,MAAM,KAAK;AAAA,MACzC,QAAQ,aAAa,YAAY;AAAA,MACjC,SAAS,KAAK;AAAA,MACd,cAAc;AAAA,MACd,UAAU,KAAK,SAAS,SAAS;AAAA,MACjC,YAAY,KAAK,OAAO;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cACZ,MACA,eACA,KACe;AACf,UAAM,EAAE,SAAS,OAAO,IAAI;AAE5B,QAAI,CAAC,SAAS;AACZ,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAAA,IAC7D;AAEA,UAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,QAAI,CAAC,OAAO;AACV,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,YAAY,OAAO,gCAAgC,CAAC;AAAA,IAC9F;AAGA,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,OAAO,KAAK,GAAG;AAC7D,UAAI,MAAM,aAAa,CAAC,UAAU,OAAO,GAAG,MAAM,SAAY;AAC5D,eAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,2BAA2B,GAAG,GAAG,CAAC;AAAA,MAC5E;AAAA,IACF;AAGA,QAAI,CAAC,eAAe;AAClB,aAAO,KAAK,oBAAoB,MAAM,QAAQ,GAAG;AAAA,IACnD;AAGA,QAAI;AACJ,QAAI;AACF,YAAM,UAAU,OAAO,KAAK,eAAe,QAAQ,EAAE,SAAS,OAAO;AACrE,gBAAU,KAAK,MAAM,OAAO;AAAA,IAC9B,QAAQ;AACN,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,2BAA2B,CAAC;AAAA,IACtE;AAGA,UAAM,aAAa,KAAK,gBAAgB,SAAS,MAAM,MAAM;AAC7D,QAAI,CAAC,WAAW,OAAO;AACrB,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,WAAW,MAAM,CAAC;AAAA,IAC5D;AAGA,UAAM,eAAe,KAAK,mBAAmB,OAAO;AACpD,QAAI,gBAAgB,CAAC,KAAK,gBAAgB,MAAM,QAAQ,YAAY,GAAG;AACrE,YAAM,WAAW,sBAAsB,MAAM,MAAM;AACnD,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,OAAO,SAAS,YAAY,4BAA4B,SAAS,KAAK,IAAI,CAAC;AAAA,MAC7E,CAAC;AAAA,IACH;AAKA,UAAM,iBAAiB,QAAQ,UAAU,WAAW,QAAQ,WAAW,KAAK;AAC5E,UAAM,gBAAgB,KAAK,oBAAoB,cAAc;AAG7D,UAAM,eAAe,KAAK,yBAAyB,MAAM,QAAQ,gBAAgB,eAAe,YAAY;AAG5G,YAAQ,IAAI,mCAAmC,cAAc,KAAK;AAClE,UAAM,eAAe,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AACrE,QAAI,CAAC,aAAa,OAAO;AACvB,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,OAAO,gCAAgC,aAAa,KAAK;AAAA,QACzD,aAAa,aAAa;AAAA,MAC5B,CAAC;AAAA,IACH;AACA,YAAQ,IAAI,0BAA0B,aAAa,WAAW,EAAE;AAGhE,UAAM,iBAAiB,SAAS,QAAQ,IAAI,yBAAyB,MAAM;AAC3E,YAAQ,IAAI,+BAA+B,OAAO,cAAc,cAAc,IAAI;AAClF,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,QAAQ,KAAK;AAAA,QAC1B,MAAM,QAAQ,UAAU,CAAC,CAAC;AAAA,QAC1B,IAAI;AAAA,UAAQ,CAAC,GAAG,WACd,WAAW,MAAM,OAAO,IAAI,MAAM,uBAAuB,cAAc,GAAG,CAAC,GAAG,iBAAiB,GAAI;AAAA,QACrG;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAU;AACjB,cAAQ,MAAM,sCAAsC,IAAI,OAAO;AAC/D,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,OAAO;AAAA,QACP,SAAS,IAAI;AAAA,MACf,CAAC;AAAA,IACH;AAGA,YAAQ,IAAI,iDAAiD;AAC7D,QAAI,aAAkB;AACtB,QAAI;AACF,mBAAa,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AAC7D,cAAQ,IAAI,iCAAiC,WAAW,WAAW,KAAK,WAAW,eAAe,SAAS,EAAE;AAAA,IAC/G,SAAS,KAAU;AACjB,cAAQ,MAAM,iCAAiC,IAAI,OAAO;AAAA,IAC5D;AAGA,UAAM,kBAA0C,CAAC;AACjD,QAAI,YAAY,SAAS;AACvB,YAAM,kBAAkB;AAAA,QACtB,SAAS;AAAA,QACT,aAAa,WAAW;AAAA,QACxB,SAAS,QAAQ,WAAW,QAAQ,UAAU;AAAA,QAC9C,aAAa,WAAW;AAAA,MAC1B;AACA,sBAAgB,uBAAuB,IAAI,OAAO;AAAA,QAChD,KAAK,UAAU,eAAe;AAAA,MAChC,EAAE,SAAS,QAAQ;AAAA,IACrB;AAEA,SAAK,SAAS,KAAK,KAAK;AAAA,MACtB,SAAS;AAAA,MACT;AAAA,MACA,SAAS,YAAY,UACjB,EAAE,aAAa,WAAW,aAAa,QAAQ,WAAW,aAAa,WAAW,YAAY,IAC9F,EAAE,QAAQ,UAAU;AAAA,IAC1B,GAAG,eAAe;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAoB,QAAuB,KAA2B;AAC5E,UAAM,iBAAiB,sBAAsB,MAAM;AACnD,UAAM,iBAAiB,KAAK,kBAAkB;AAG9C,UAAM,UAAqC,CAAC;AAC5C,eAAW,eAAe,gBAAgB;AACxC,iBAAW,SAAS,gBAAgB;AAElC,YAAI,YAAY,OAAO,SAAS,KAAK,GAAG;AACtC,kBAAQ,KAAK,KAAK,yBAAyB,QAAQ,YAAY,SAAS,YAAY,QAAQ,KAAK,CAAC;AAAA,QACpG;AAAA,MACF;AAAA,IACF;AAGA,UAAM,iBAAiB,eAAe,IAAI,OAAK;AAE7C,UAAI,EAAE,YAAY,cAAe,QAAO;AACxC,UAAI,EAAE,YAAY,aAAc,QAAO;AACvC,aAAO,EAAE;AAAA,IACX,CAAC;AAED,UAAM,kBAAkB;AAAA,MACtB,aAAaA;AAAA,MACb;AAAA,MACA,oBAAoB;AAAA,MACpB;AAAA,MACA,UAAU;AAAA,QACR,KAAK,oBAAoB,OAAO,EAAE;AAAA,QAClC,aAAa,GAAG,OAAO,IAAI,OAAO,OAAO,KAAK,IAAI,OAAO,QAAQ;AAAA,QACjE,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,UAAU,OAAO,KAAK,KAAK,UAAU,eAAe,CAAC,EAAE,SAAS,QAAQ;AAE9E,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,CAAC,uBAAuB,GAAG;AAAA,IAC7B,CAAC;AACD,QAAI,IAAI,KAAK,UAAU;AAAA,MACrB,OAAO;AAAA,MACP,SAAS,qBAAqB,OAAO,KAAK,IAAI,OAAO,QAAQ;AAAA,MAC7D,oBAAoB;AAAA,MACpB;AAAA,MACA,MAAM;AAAA,IACR,GAAG,MAAM,CAAC,CAAC;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKQ,gBACN,SACA,QACoC;AACpC,QAAI,QAAQ,gBAAgBA,eAAc;AACxC,aAAO,EAAE,OAAO,OAAO,OAAO,6BAA6B,QAAQ,WAAW,GAAG;AAAA,IACnF;AAEA,UAAM,SAAS,QAAQ,UAAU,UAAU,QAAQ;AACnD,UAAM,UAAU,QAAQ,UAAU,WAAW,QAAQ,WAAW,KAAK;AAErE,QAAI,WAAW,SAAS;AACtB,aAAO,EAAE,OAAO,OAAO,OAAO,uBAAuB,MAAM,GAAG;AAAA,IAChE;AAGA,QAAI,CAAC,KAAK,kBAAkB,OAAO,GAAG;AACpC,YAAM,iBAAiB,KAAK,kBAAkB,EAAE,IAAI,OAAK,EAAE,OAAO,EAAE,KAAK,IAAI;AAC7E,aAAO,EAAE,OAAO,OAAO,OAAO,yBAAyB,OAAO,eAAe,cAAc,GAAG;AAAA,IAChG;AAEA,WAAO,EAAE,OAAO,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,yBACN,QACA,SACA,QACA,OACyB;AACzB,UAAM,gBAAgB,KAAK,MAAM,OAAO,QAAQ,GAAG,EAAE,SAAS;AAC9D,UAAM,iBAAiB,sBAAsB,MAAM;AAGnD,UAAM,kBAAkB,WAAW,KAAK;AACxC,UAAM,iBAAiB,UAAU,KAAK,SAAS,SAAS;AACxD,UAAM,gBAAgB,SAAS,eAAe,SAAS,KAAK,IAAI,QAAQ,eAAe,CAAC;AAExF,UAAM,iBAAiB,gBAAgB,eAAe,KAAK,CAAC;AAC5D,UAAM,eAAe,eAAe,aAAa;AACjD,UAAM,cAAc,eAAe,iBAAiB,aAAa;AAEjE,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,mBAAmB;AAAA,MACnB,OAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,SAAiD;AAC1E,UAAM,QAAQ,QAAQ,UAAU,SAAU,QAAQ,SAAiB;AACnE,QAAI,CAAC,MAAO,QAAO;AAGnB,UAAM,iBAAiB,QAAQ,UAAU,WAAW,QAAQ,WAAW,KAAK;AAC5E,UAAM,iBAAiB,gBAAgB,cAAc,KAAK,CAAC;AAE3D,eAAW,CAAC,QAAQ,OAAO,KAAK,OAAO,QAAQ,cAAc,GAAG;AAC9D,UAAI,WAAY,QAAmB,YAAY,MAAM,MAAM,YAAY,GAAG;AACxE,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,QAAuB,OAAwB;AACrE,UAAM,WAAW,sBAAsB,MAAM;AAC7C,WAAO,SAAS,SAAS,KAAK;AAAA,EAChC;AAAA,EAEA,MAAc,SAAS,KAAoC;AACzD,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,OAAO;AACX,UAAI,GAAG,QAAQ,WAAS,QAAQ,KAAK;AACrC,UAAI,GAAG,OAAO,MAAM;AAClB,YAAI;AACF,kBAAQ,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC;AAAA,QACtC,QAAQ;AACN,iBAAO,IAAI,MAAM,cAAc,CAAC;AAAA,QAClC;AAAA,MACF,CAAC;AACD,UAAI,GAAG,SAAS,MAAM;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEQ,SACN,KACA,QACA,MACA,cACM;AACN,UAAM,UAAkC,EAAE,gBAAgB,mBAAmB;AAC7E,QAAI,cAAc;AAChB,aAAO,OAAO,SAAS,YAAY;AAAA,IACrC;AACA,QAAI,UAAU,QAAQ,OAAO;AAC7B,QAAI,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,UAA2B;AAChD,UAAM,aAAa,QAAQ,IAAI,mBAAmB,MAAM,GAAG,EAAE,IAAI,QAAM,GAAG,KAAK,CAAC,KAAK,CAAC;AAGtF,QAAI,WAAW,WAAW,GAAG;AAC3B,cAAQ,IAAI,2DAA2D;AACvE,aAAO;AAAA,IACT;AAGA,UAAM,eAAe,aAAa,QAAQ,cAAc,SAAS,QAAQ,WAAW,EAAE;AAEtF,UAAM,UAAU,WAAW,SAAS,YAAY,KAAK,WAAW,SAAS,QAAQ;AACjF,QAAI,CAAC,SAAS;AACZ,cAAQ,IAAI,oCAAoC,QAAQ,iBAAiB,YAAY,GAAG;AAAA,IAC1F;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAc,YACZ,MACA,eACA,KACe;AACf,UAAM,EAAE,QAAQ,QAAQ,UAAU,OAAO,MAAM,WAAW,YAAY,IAAI;AAG1E,QAAI,CAAC,UAAU,CAAC,QAAQ;AACtB,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,0CAA0C,CAAC;AAAA,IACrF;AAGA,QAAI,CAAC,sBAAsB,KAAK,MAAM,GAAG;AACvC,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,gCAAgC,CAAC;AAAA,IAC3E;AAGA,UAAM,YAAY,WAAW,MAAM;AACnC,QAAI,MAAM,SAAS,KAAK,aAAa,GAAG;AACtC,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,iBAAiB,CAAC;AAAA,IAC5D;AAGA,UAAM,kBAAkB,CAAC,QAAQ,WAAW,cAAc;AAC1D,QAAI,SAAS,CAAC,gBAAgB,SAAS,KAAK,GAAG;AAC7C,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,sBAAsB,KAAK,gBAAgB,gBAAgB,KAAK,IAAI,CAAC,GAAG,CAAC;AAAA,IACnH;AAGA,UAAM,cAA6B;AAAA,MACjC,IAAI,aAAa;AAAA,MACjB,MAAM,eAAe;AAAA,MACrB,aAAa,eAAe;AAAA,MAC5B,OAAO;AAAA,MACP,UAAU,YAAY;AAAA,MACtB,UAAU;AAAA;AAAA,MACV,OAAO,CAAC;AAAA,MACR,QAAQ,CAAC;AAAA,IACX;AAGA,UAAM,eAAe,KAAK,8BAA8B,aAAa,QAAQ,UAAU,KAAK;AAG5F,QAAI,CAAC,eAAe;AAClB,aAAO,KAAK,yBAAyB,aAAa,QAAQ,MAAM,OAAO,GAAG;AAAA,IAC5E;AAGA,QAAI;AACJ,QAAI;AACF,YAAM,UAAU,OAAO,KAAK,eAAe,QAAQ,EAAE,SAAS,OAAO;AACrE,gBAAU,KAAK,MAAM,OAAO;AAAA,IAC9B,QAAQ;AACN,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,2BAA2B,CAAC;AAAA,IACtE;AAGA,QAAI,QAAQ,gBAAgBA,eAAc;AACxC,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,6BAA6B,QAAQ,WAAW,GAAG,CAAC;AAAA,IAC9F;AAEA,UAAM,SAAS,QAAQ,UAAU,UAAU,QAAQ;AACnD,UAAM,UAAU,QAAQ,UAAU,WAAW,QAAQ;AAErD,QAAI,WAAW,SAAS;AACtB,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,uBAAuB,MAAM,GAAG,CAAC;AAAA,IAC3E;AAGA,UAAM,kBAAkB,QAAS,iBAAiB,KAAK,KAAK,KAAK,YAAa,KAAK;AACnF,QAAI,YAAY,iBAAiB;AAC/B,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,8BAA8B,eAAe,SAAS,OAAO,GAAG,CAAC;AAAA,IAC3G;AAGA,YAAQ,IAAI,4CAA4C,MAAM,KAAK;AACnE,UAAM,eAAe,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AACrE,QAAI,CAAC,aAAa,OAAO;AACvB,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,SAAS;AAAA,QACT,OAAO,gCAAgC,aAAa,KAAK;AAAA,QACzD,aAAa,aAAa;AAAA,MAC5B,CAAC;AAAA,IACH;AACA,YAAQ,IAAI,kCAAkC,aAAa,WAAW,EAAE;AAGxE,UAAM,EAAE,SAAS,SAAS,OAAO,IAAI;AAGrC,QAAI,WAAW,SAAS;AACtB,cAAQ,IAAI,8DAA8D,OAAO,EAAE;AACnF,YAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,UAAI,CAAC,OAAO;AAEV,gBAAQ,IAAI,yCAAyC,OAAO,iBAAiB;AAC7E,eAAO,KAAK,SAAS,KAAK,KAAK;AAAA,UAC7B,SAAS;AAAA,UACT,gBAAgB;AAAA,UAChB,OAAO,sBAAsB,OAAO;AAAA,QACtC,CAAC;AAAA,MACH;AAGA,YAAM,iBAAiB,SAAS,QAAQ,IAAI,yBAAyB,MAAM;AAC3E,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,QAAQ,KAAK;AAAA,UAC1B,MAAM,QAAQ,UAAU,CAAC,CAAC;AAAA,UAC1B,IAAI;AAAA,YAAQ,CAAC,GAAG,WACd,WAAW,MAAM,OAAO,IAAI,MAAM,uBAAuB,cAAc,GAAG,CAAC,GAAG,iBAAiB,GAAI;AAAA,UACrG;AAAA,QACF,CAAC;AACD,gBAAQ,IAAI,6DAA6D;AAAA,MAC3E,SAAS,KAAU;AAEjB,gBAAQ,MAAM,oCAAoC,IAAI,OAAO,iBAAiB;AAC9E,eAAO,KAAK,SAAS,KAAK,KAAK;AAAA,UAC7B,SAAS;AAAA,UACT,gBAAgB;AAAA,UAChB,OAAO,6BAA6B,IAAI,OAAO;AAAA,QACjD,CAAC;AAAA,MACH;AAGA,UAAII,cAAkB;AACtB,UAAI;AACF,QAAAA,cAAa,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AAC7D,gBAAQ,IAAI,yCAAyCA,YAAW,WAAW,KAAKA,YAAW,eAAe,SAAS,EAAE;AAAA,MACvH,SAAS,KAAU;AACjB,gBAAQ,MAAM,yCAAyC,IAAI,OAAO;AAElE,eAAO,KAAK,SAAS,KAAK,KAAK;AAAA,UAC7B,SAAS;AAAA,UACT,UAAU;AAAA,UACV,SAAS;AAAA,UACT,iBAAiB,IAAI;AAAA,UACrB,MAAO,QAAQ,SAAiB,eAAe;AAAA;AAAA,UAC/C,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,UAAU,YAAY;AAAA,UACtB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAEA,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,SAAS;AAAA,QACT,UAAU;AAAA,QACV,SAASA,aAAY,WAAW;AAAA,QAChC,QAAQA,aAAY;AAAA,QACpB,MAAO,QAAQ,SAAiB,eAAe;AAAA;AAAA,QAC/C,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU,YAAY;AAAA,QACtB,aAAaA,aAAY;AAAA,QACzB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAGA,YAAQ,IAAI,uDAAuD;AACnE,QAAI,aAAkB;AACtB,QAAI;AACF,mBAAa,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AAC7D,cAAQ,IAAI,yCAAyC,WAAW,WAAW,KAAK,WAAW,eAAe,SAAS,EAAE;AAAA,IACvH,SAAS,KAAU;AACjB,cAAQ,MAAM,yCAAyC,IAAI,OAAO;AAClE,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,SAAS;AAAA,QACT,OAAO,sBAAsB,IAAI,OAAO;AAAA,MAC1C,CAAC;AAAA,IACH;AAGA,SAAK,SAAS,KAAK,KAAK;AAAA,MACtB,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS,YAAY,WAAW;AAAA,MAChC,QAAQ,YAAY;AAAA,MACpB,MAAO,QAAQ,SAAiB,eAAe;AAAA;AAAA,MAC/C,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU,YAAY;AAAA,MACtB,aAAa,YAAY;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,8BAA8B,QAAuB,QAAgB,OAAgB,OAAyC;AACpI,UAAM,gBAAgB,KAAK,MAAM,OAAO,QAAQ,GAAG,EAAE,SAAS;AAC9D,UAAM,iBAAiB,sBAAsB,MAAM;AAGnD,UAAM,YAAY,QAAS,iBAAiB,KAAK,KAAK,KAAK,YAAa,KAAK;AAG7E,UAAM,gBAAgB,SAAS,eAAe,SAAS,KAAK,IAAI,QAAQ,eAAe,CAAC;AACxF,UAAM,iBAAiB,gBAAgB,SAAS,KAAK,gBAAgB,KAAK,SAAS,KAAK,CAAC;AACzF,UAAM,eAAe,eAAe,aAAa;AACjD,UAAM,cAAc,eAAe,WAAW,aAAa;AAE3D,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA;AAAA,MACP,mBAAmB;AAAA,MACnB,OAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,yBACN,QACA,QACA,MACA,OACA,KACM;AACN,UAAM,eAAe,KAAK,8BAA8B,QAAQ,QAAQ,OAAO,UAAU,KAAK;AAE9F,UAAM,kBAAkB;AAAA,MACtB,aAAaJ;AAAA,MACb,SAAS,CAAC,YAAY;AAAA,MACtB,UAAU;AAAA,QACR,KAAK;AAAA,QACL,aAAa,GAAG,OAAO,IAAI,OAAO,OAAO,KAAK,IAAI,OAAO,QAAQ;AAAA,QACjE,UAAU;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,OAAO,KAAK,KAAK,UAAU,eAAe,CAAC,EAAE,SAAS,QAAQ;AAE9E,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,CAAC,uBAAuB,GAAG;AAAA,IAC7B,CAAC;AACD,QAAI,IAAI,KAAK,UAAU;AAAA,MACrB,OAAO;AAAA,MACP,SAAS,qBAAqB,OAAO,KAAK,IAAI,OAAO,QAAQ;AAAA,MAC7D,MAAM;AAAA,IACR,GAAG,MAAM,CAAC,CAAC;AAAA,EACb;AACF;","names":["readFileSync","existsSync","path","X402_VERSION","loadEnvFile","existsSync","readFileSync","settlement"]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/index.ts","../../src/facilitators/interface.ts","../../src/facilitators/cdp.ts","../../src/chains/index.ts","../../src/facilitators/tempo.ts","../../src/facilitators/registry.ts"],"sourcesContent":["/**\n * MoltsPay Server - Payment infrastructure for AI Agents\n * \n * Now uses pluggable Facilitator abstraction for payment verification/settlement.\n * \n * Environment variables (from ~/.moltspay/.env or process.env):\n * USE_MAINNET=true - Use Base mainnet (requires CDP keys)\n * CDP_API_KEY_ID=xxx - Coinbase Developer Platform API key ID\n * CDP_API_KEY_SECRET=xxx - CDP API key secret\n * \n * Usage:\n * const server = new MoltsPayServer('./moltspay.services.json');\n * server.skill('text-to-video', async (params) => { ... });\n * server.listen(3000);\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { createServer, IncomingMessage, ServerResponse } from 'http';\nimport * as path from 'path';\nimport {\n FacilitatorRegistry,\n FacilitatorSelection,\n X402PaymentPayload,\n X402PaymentRequirements,\n} from '../facilitators/index.js';\nimport {\n ServicesManifest,\n ServiceConfig,\n SkillFunction,\n RegisteredSkill,\n MoltsPayServerOptions,\n} from './types.js';\n\nexport * from './types.js';\n\n// x402 constants\nconst X402_VERSION = 2;\nconst PAYMENT_REQUIRED_HEADER = 'x-payment-required';\nconst PAYMENT_HEADER = 'x-payment';\nconst PAYMENT_RESPONSE_HEADER = 'x-payment-response';\n\n// MPP (Machine Payments Protocol) constants\nconst MPP_AUTH_HEADER = 'authorization';\nconst MPP_WWW_AUTH_HEADER = 'www-authenticate';\nconst MPP_RECEIPT_HEADER = 'payment-receipt';\n\n// Token contract addresses by network\nconst TOKEN_ADDRESSES: Record<string, Record<string, string>> = {\n 'eip155:8453': {\n USDC: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n USDT: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',\n },\n 'eip155:84532': {\n USDC: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n USDT: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Same as USDC on testnet\n },\n 'eip155:137': {\n USDC: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n USDT: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',\n },\n 'eip155:42431': {\n // Tempo Moderato testnet - TIP-20 stablecoins\n USDC: '0x20c0000000000000000000000000000000000000', // pathUSD\n USDT: '0x20c0000000000000000000000000000000000001', // alphaUSD\n },\n};\n\n// Chain name to network ID mapping\nconst CHAIN_TO_NETWORK: Record<string, string> = {\n 'base': 'eip155:8453',\n 'base_sepolia': 'eip155:84532',\n 'polygon': 'eip155:137',\n 'tempo_moderato': 'eip155:42431',\n};\n\n// EIP-712 domain info for tokens (per network)\n// Different networks may have different domain names for the same token\nconst TOKEN_DOMAINS: Record<string, Record<string, { name: string; version: string }>> = {\n // Base mainnet\n 'eip155:8453': {\n USDC: { name: 'USD Coin', version: '2' },\n USDT: { name: 'Tether USD', version: '2' },\n },\n // Base Sepolia testnet - USDC uses 'USDC' not 'USD Coin'\n 'eip155:84532': {\n USDC: { name: 'USDC', version: '2' },\n USDT: { name: 'USDC', version: '2' }, // Same contract as USDC on testnet\n },\n // Polygon mainnet\n 'eip155:137': {\n USDC: { name: 'USD Coin', version: '2' },\n USDT: { name: '(PoS) Tether USD', version: '2' },\n },\n // Tempo Moderato testnet - TIP-20 stablecoins\n 'eip155:42431': {\n USDC: { name: 'pathUSD', version: '1' },\n USDT: { name: 'alphaUSD', version: '1' },\n },\n};\n\n// Helper to get token domain for a network\nfunction getTokenDomain(network: string, token: string): { name: string; version: string } {\n const networkDomains = TOKEN_DOMAINS[network] || TOKEN_DOMAINS['eip155:8453']; // fallback to base mainnet\n return networkDomains[token] || { name: 'USD Coin', version: '2' };\n}\n\n// Helper to get accepted currencies with backward compatibility\nfunction getAcceptedCurrencies(config: ServiceConfig): string[] {\n return config.acceptedCurrencies ?? [config.currency];\n}\n\n/**\n * Load environment from .env files\n */\nfunction loadEnvFile(): void {\n const envPaths = [\n path.join(process.cwd(), '.env'),\n path.join(process.env.HOME || '', '.moltspay', '.env'),\n ];\n \n for (const envPath of envPaths) {\n if (existsSync(envPath)) {\n try {\n const content = readFileSync(envPath, 'utf-8');\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n if (!process.env[key]) {\n process.env[key] = value;\n }\n }\n console.log(`[MoltsPay] Loaded config from ${envPath}`);\n break;\n } catch {\n // Ignore errors\n }\n }\n }\n}\n\n/**\n * Extended server options with facilitator config\n */\nexport interface MoltsPayServerOptionsExtended extends MoltsPayServerOptions {\n /** Facilitator selection configuration */\n facilitators?: FacilitatorSelection;\n}\n\nexport class MoltsPayServer {\n private manifest: ServicesManifest;\n private skills: Map<string, RegisteredSkill> = new Map();\n private options: MoltsPayServerOptionsExtended;\n private registry: FacilitatorRegistry;\n private networkId: string;\n private useMainnet: boolean;\n\n constructor(servicesPath: string, options: MoltsPayServerOptionsExtended = {}) {\n // Load env files FIRST (before reading USE_MAINNET)\n loadEnvFile();\n \n // Load services manifest\n const content = readFileSync(servicesPath, 'utf-8');\n this.manifest = JSON.parse(content) as ServicesManifest;\n \n this.options = {\n port: options.port || 3000,\n host: options.host || '0.0.0.0',\n ...options,\n };\n\n // Determine default network from env (fallback only)\n // NOTE: Chain is auto-detected from client payment header (payment.network)\n // USE_MAINNET is only used as fallback when payment header omits network\n // Recommended: configure \"chains\" array in manifest instead\n this.useMainnet = process.env.USE_MAINNET?.toLowerCase() === 'true';\n this.networkId = this.useMainnet ? 'eip155:8453' : 'eip155:84532';\n\n // Create facilitator registry with config (env vars take precedence)\n // Always include 'tempo' in fallback for Tempo testnet support\n const defaultFallback = ['tempo'];\n const envFallback = process.env.FACILITATOR_FALLBACK?.split(',').filter(Boolean);\n const facilitatorConfig: FacilitatorSelection = options.facilitators || {\n primary: process.env.FACILITATOR_PRIMARY || 'cdp',\n fallback: envFallback || defaultFallback,\n strategy: (process.env.FACILITATOR_STRATEGY as any) || 'failover',\n config: {\n cdp: { useMainnet: this.useMainnet },\n },\n };\n this.registry = new FacilitatorRegistry(facilitatorConfig);\n\n // Get primary facilitator for logging\n const primaryFacilitator = this.registry.get(facilitatorConfig.primary);\n \n console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);\n console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);\n console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);\n \n // Log configured chains\n const chains = this.manifest.provider.chains;\n if (chains && chains.length > 0) {\n const chainNames = chains.map(c => c.chain || c.network).join(', ');\n console.log(`[MoltsPay] Chains: ${chainNames} (multi-chain enabled)`);\n } else {\n const networkName = this.useMainnet ? 'Base mainnet' : 'Base Sepolia (testnet)';\n console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);\n }\n \n console.log(`[MoltsPay] Facilitator: ${primaryFacilitator.displayName} (${facilitatorConfig.strategy || 'failover'})`);\n console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);\n }\n\n /**\n * Register a skill handler for a service\n */\n skill(serviceId: string, handler: SkillFunction): this {\n const config = this.manifest.services.find(s => s.id === serviceId);\n if (!config) {\n throw new Error(`Service '${serviceId}' not found in manifest`);\n }\n this.skills.set(serviceId, { id: serviceId, config, handler });\n return this;\n }\n\n /**\n * Get all configured chains for this provider\n * Returns array of { network, wallet, tokens } for each chain\n */\n private getProviderChains(): Array<{ network: string; wallet: string; tokens: string[] }> {\n const provider = this.manifest.provider;\n \n // If chains array is defined, use it\n // Supports both string array [\"base\", \"polygon\"] and object array [{chain, wallet, tokens}]\n if (provider.chains && provider.chains.length > 0) {\n return provider.chains.map(c => {\n const chainName = typeof c === 'string' ? c : c.chain;\n return {\n network: CHAIN_TO_NETWORK[chainName] || 'eip155:8453',\n wallet: (typeof c === 'object' ? c.wallet : null) || provider.wallet,\n tokens: (typeof c === 'object' ? c.tokens : null) || ['USDC'],\n };\n });\n }\n \n // Fallback to single chain (backward compat)\n const chain = provider.chain || 'base';\n const network = CHAIN_TO_NETWORK[chain] || this.networkId;\n return [{\n network,\n wallet: provider.wallet,\n tokens: ['USDC'],\n }];\n }\n\n /**\n * Get wallet address for a specific network\n */\n private getWalletForNetwork(network: string): string {\n const chains = this.getProviderChains();\n const chain = chains.find(c => c.network === network);\n return chain?.wallet || this.manifest.provider.wallet;\n }\n\n /**\n * Check if a network is accepted by this provider\n */\n private isNetworkAccepted(network: string): boolean {\n const chains = this.getProviderChains();\n return chains.some(c => c.network === network);\n }\n\n /**\n * Start HTTP server\n */\n listen(port?: number): void {\n const p = port || this.options.port || 3000;\n const host = this.options.host || '0.0.0.0';\n\n const server = createServer((req, res) => this.handleRequest(req, res));\n server.listen(p, host, () => {\n console.log(`[MoltsPay] Server listening on http://${host}:${p}`);\n console.log(`[MoltsPay] Endpoints:`);\n console.log(` GET /services - List available services`);\n console.log(` POST /execute - Execute service (x402 payment)`);\n console.log(` POST /proxy - Proxy payment for external services`);\n console.log(` GET /health - Health check (incl. facilitators)`);\n });\n }\n\n /**\n * Handle incoming request\n */\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // CORS\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Payment, Authorization');\n res.setHeader('Access-Control-Expose-Headers', 'X-Payment-Required, X-Payment-Response, WWW-Authenticate, Payment-Receipt');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n try {\n const url = new URL(req.url || '/', `http://${req.headers.host}`);\n \n if (url.pathname === '/services' && req.method === 'GET') {\n return this.handleGetServices(res);\n }\n\n // Standard discovery endpoint\n if (url.pathname === '/.well-known/agent-services.json' && req.method === 'GET') {\n return this.handleAgentServicesDiscovery(res);\n }\n\n if (url.pathname === '/health' && req.method === 'GET') {\n return await this.handleHealthCheck(res);\n }\n\n if (url.pathname === '/execute' && req.method === 'POST') {\n const body = await this.readBody(req);\n const paymentHeader = req.headers[PAYMENT_HEADER] as string | undefined;\n return await this.handleExecute(body, paymentHeader, res);\n }\n\n if (url.pathname === '/proxy' && req.method === 'POST') {\n // Check IP whitelist\n const clientIP = (req.headers['x-real-ip'] as string) || \n (req.headers['x-forwarded-for'] as string)?.split(',')[0]?.trim() ||\n req.socket.remoteAddress || '';\n if (!this.isProxyAllowed(clientIP)) {\n return this.sendJson(res, 403, { error: 'Forbidden: IP not allowed' });\n }\n const body = await this.readBody(req);\n const paymentHeader = req.headers[PAYMENT_HEADER] as string | undefined;\n return await this.handleProxy(body, paymentHeader, res);\n }\n\n // MPP Protocol: Handle service-specific endpoints like /text-to-video, /ping\n // Check if URL matches a registered service ID\n const servicePath = url.pathname.replace(/^\\//, ''); // Remove leading slash\n const skill = this.skills.get(servicePath);\n if (skill && (req.method === 'POST' || req.method === 'GET')) {\n const body = req.method === 'POST' ? await this.readBody(req) : {};\n const authHeader = req.headers[MPP_AUTH_HEADER] as string | undefined;\n const x402Header = req.headers[PAYMENT_HEADER] as string | undefined;\n return await this.handleMPPRequest(skill, body, authHeader, x402Header, res);\n }\n\n // Not found\n this.sendJson(res, 404, { error: 'Not found' });\n } catch (err: any) {\n console.error('[MoltsPay] Error:', err);\n this.sendJson(res, 500, { error: err.message || 'Internal error' });\n }\n }\n\n /**\n * GET /.well-known/agent-services.json - Standard discovery endpoint\n */\n private handleAgentServicesDiscovery(res: ServerResponse): void {\n const services = this.manifest.services.map(s => ({\n id: s.id,\n name: s.name,\n description: s.description,\n price: s.price,\n currency: s.currency,\n acceptedCurrencies: getAcceptedCurrencies(s),\n input: s.input,\n output: s.output,\n available: this.skills.has(s.id),\n }));\n\n this.sendJson(res, 200, {\n version: '1.0',\n provider: {\n name: this.manifest.provider.name,\n description: this.manifest.provider.description,\n wallet: this.manifest.provider.wallet,\n chain: this.manifest.provider.chain || 'base',\n },\n services,\n endpoints: {\n services: '/services',\n execute: '/execute',\n health: '/health',\n },\n payment: {\n protocol: 'x402',\n version: X402_VERSION,\n network: this.networkId,\n schemes: ['exact'],\n mainnet: this.useMainnet,\n },\n });\n }\n\n /**\n * GET /services - List available services\n */\n private handleGetServices(res: ServerResponse): void {\n const services = this.manifest.services.map(s => ({\n id: s.id,\n name: s.name,\n description: s.description,\n price: s.price,\n currency: s.currency,\n acceptedCurrencies: getAcceptedCurrencies(s),\n input: s.input,\n output: s.output,\n available: this.skills.has(s.id),\n }));\n\n const selection = this.registry.getSelection();\n \n this.sendJson(res, 200, {\n provider: this.manifest.provider,\n services,\n x402: {\n version: X402_VERSION,\n network: this.networkId,\n schemes: ['exact'],\n facilitators: {\n primary: selection.primary,\n fallback: selection.fallback,\n strategy: selection.strategy,\n },\n mainnet: this.useMainnet,\n },\n });\n }\n\n /**\n * GET /health - Health check endpoint\n */\n private async handleHealthCheck(res: ServerResponse): Promise<void> {\n const facilitatorHealth = await this.registry.healthCheckAll();\n \n const allHealthy = Object.values(facilitatorHealth).every(h => h.healthy);\n \n this.sendJson(res, allHealthy ? 200 : 503, {\n status: allHealthy ? 'healthy' : 'degraded',\n network: this.networkId,\n facilitators: facilitatorHealth,\n services: this.manifest.services.length,\n registered: this.skills.size,\n });\n }\n\n /**\n * POST /execute - Execute service with x402 payment\n */\n private async handleExecute(\n body: any,\n paymentHeader: string | undefined,\n res: ServerResponse\n ): Promise<void> {\n const { service, params } = body;\n\n if (!service) {\n return this.sendJson(res, 400, { error: 'Missing service' });\n }\n\n const skill = this.skills.get(service);\n if (!skill) {\n return this.sendJson(res, 404, { error: `Service '${service}' not found or not registered` });\n }\n\n // Validate required params\n for (const [key, field] of Object.entries(skill.config.input)) {\n if (field.required && (!params || params[key] === undefined)) {\n return this.sendJson(res, 400, { error: `Missing required param: ${key}` });\n }\n }\n\n // If no payment header, return 402 with payment requirements\n if (!paymentHeader) {\n return this.sendPaymentRequired(skill.config, res);\n }\n\n // Parse payment payload\n let payment: X402PaymentPayload;\n try {\n const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');\n payment = JSON.parse(decoded);\n } catch {\n return this.sendJson(res, 400, { error: 'Invalid X-Payment header' });\n }\n\n // Validate basic payment fields\n const validation = this.validatePayment(payment, skill.config);\n if (!validation.valid) {\n return this.sendJson(res, 402, { error: validation.error });\n }\n\n // Detect which token is being used\n const paymentToken = this.detectPaymentToken(payment);\n if (paymentToken && !this.isTokenAccepted(skill.config, paymentToken)) {\n const accepted = getAcceptedCurrencies(skill.config);\n return this.sendJson(res, 402, { \n error: `Token ${paymentToken} not accepted. Accepted: ${accepted.join(', ')}` \n });\n }\n\n // Auto-detect chain from payment header (key insight: client specifies chain via --chain flag)\n // payment.network contains \"eip155:8453\" (base) or \"eip155:84532\" (base_sepolia) etc.\n // This allows provider to serve both mainnet and testnet without separate configuration\n const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;\n const paymentWallet = this.getWalletForNetwork(paymentNetwork);\n\n // Build requirements for facilitator using the detected token and network\n const requirements = this.buildPaymentRequirements(skill.config, paymentNetwork, paymentWallet, paymentToken);\n\n // Verify payment with facilitator (via registry)\n console.log(`[MoltsPay] Verifying payment on ${paymentNetwork}...`);\n const verifyResult = await this.registry.verify(payment, requirements);\n if (!verifyResult.valid) {\n return this.sendJson(res, 402, { \n error: `Payment verification failed: ${verifyResult.error}`,\n facilitator: verifyResult.facilitator,\n });\n }\n console.log(`[MoltsPay] Verified by ${verifyResult.facilitator}`);\n\n // Execute skill FIRST (pay-for-success) with timeout\n const timeoutSeconds = parseInt(process.env.SKILL_TIMEOUT_SECONDS || '1200');\n console.log(`[MoltsPay] Executing skill: ${service} (timeout: ${timeoutSeconds}s)`);\n let result: any;\n try {\n result = await Promise.race([\n skill.handler(params || {}),\n new Promise((_, reject) => \n setTimeout(() => reject(new Error(`Skill timeout after ${timeoutSeconds}s`)), timeoutSeconds * 1000)\n )\n ]);\n } catch (err: any) {\n console.error('[MoltsPay] Skill execution failed:', err.message);\n return this.sendJson(res, 500, {\n error: 'Service execution failed',\n message: err.message,\n });\n }\n\n // Skill succeeded - now settle payment with facilitator\n console.log(`[MoltsPay] Skill succeeded, settling payment...`);\n let settlement: any = null;\n try {\n settlement = await this.registry.settle(payment, requirements);\n console.log(`[MoltsPay] Payment settled by ${settlement.facilitator}: ${settlement.transaction || 'pending'}`);\n } catch (err: any) {\n console.error('[MoltsPay] Settlement failed:', err.message);\n }\n\n // Build response\n const responseHeaders: Record<string, string> = {};\n if (settlement?.success) {\n const responsePayload = {\n success: true,\n transaction: settlement.transaction,\n network: payment.network || payment.accepted?.network,\n facilitator: settlement.facilitator,\n };\n responseHeaders[PAYMENT_RESPONSE_HEADER] = Buffer.from(\n JSON.stringify(responsePayload)\n ).toString('base64');\n }\n\n this.sendJson(res, 200, {\n success: true,\n result,\n payment: settlement?.success \n ? { transaction: settlement.transaction, status: 'settled', facilitator: settlement.facilitator }\n : { status: 'pending' },\n }, responseHeaders);\n }\n\n /**\n * Handle MPP (Machine Payments Protocol) request\n * Supports both x402 and MPP protocols on service endpoints\n */\n private async handleMPPRequest(\n skill: RegisteredSkill,\n body: any,\n authHeader: string | undefined,\n x402Header: string | undefined,\n res: ServerResponse\n ): Promise<void> {\n const config = skill.config;\n const params = body || {};\n\n // Check for x402 payment header first (backward compatibility)\n if (x402Header) {\n return await this.handleExecute({ service: config.id, params }, x402Header, res);\n }\n\n // Check for MPP payment credential\n if (authHeader && authHeader.toLowerCase().startsWith('payment ')) {\n return await this.handleMPPPayment(skill, params, authHeader, res);\n }\n\n // No payment provided - return 402 with both x402 and MPP headers\n return this.sendMPPPaymentRequired(config, res);\n }\n\n /**\n * Handle MPP payment verification and service execution\n */\n private async handleMPPPayment(\n skill: RegisteredSkill,\n params: any,\n authHeader: string,\n res: ServerResponse\n ): Promise<void> {\n const config = skill.config;\n\n // Parse MPP credential: \"Payment <base64>\"\n const credentialMatch = authHeader.match(/Payment\\s+(.+)/i);\n if (!credentialMatch) {\n return this.sendJson(res, 400, { error: 'Invalid Authorization header format' });\n }\n\n let mppCredential: {\n challenge: {\n id: string;\n realm: string;\n method: string;\n intent: string;\n request: any;\n };\n payload: {\n hash?: string;\n signature?: string;\n type: 'hash' | 'transaction';\n };\n source?: string;\n };\n \n try {\n // mppx uses base64url encoding without padding\n const base64 = credentialMatch[1].replace(/-/g, '+').replace(/_/g, '/');\n const decoded = Buffer.from(base64, 'base64').toString('utf-8');\n mppCredential = JSON.parse(decoded);\n } catch (err) {\n console.error('[MoltsPay] Failed to parse MPP credential:', err);\n return this.sendJson(res, 400, { error: 'Invalid payment credential encoding' });\n }\n\n // Extract transaction hash from payload\n let txHash: string | undefined;\n if (mppCredential.payload?.type === 'hash' && mppCredential.payload?.hash) {\n txHash = mppCredential.payload.hash;\n } else if (mppCredential.payload?.type === 'transaction') {\n // For 'transaction' type, server would need to submit the signed tx\n // For now, we only support 'hash' type (push mode)\n return this.sendJson(res, 400, { \n error: 'Transaction type not supported. Please use push mode (hash type).' \n });\n }\n\n if (!txHash) {\n return this.sendJson(res, 400, { error: 'Missing transaction hash in credential' });\n }\n\n // Extract chainId from challenge or source\n let chainId = mppCredential.challenge?.request?.methodDetails?.chainId;\n if (!chainId && mppCredential.source) {\n const chainMatch = mppCredential.source.match(/eip155:(\\d+)/);\n if (chainMatch) chainId = parseInt(chainMatch[1], 10);\n }\n chainId = chainId || 42431; // Default to Tempo Moderato\n\n // Determine network from chainId\n const network = `eip155:${chainId}`;\n\n if (!this.isNetworkAccepted(network)) {\n return this.sendJson(res, 402, { \n error: `Network not accepted: ${network}` \n });\n }\n\n // Build requirements for verification\n const requirements = this.buildPaymentRequirements(\n config,\n network,\n this.getWalletForNetwork(network),\n 'USDC'\n );\n\n // Create x402-compatible payload for facilitator\n const paymentPayload: X402PaymentPayload = {\n x402Version: X402_VERSION,\n scheme: 'exact',\n network,\n payload: {\n txHash,\n chainId,\n },\n };\n\n console.log(`[MoltsPay] Verifying MPP payment: txHash=${txHash}, chainId=${chainId}`);\n\n // Verify payment using facilitator registry\n const verification = await this.registry.verify(paymentPayload, requirements);\n \n if (!verification.valid) {\n return this.sendJson(res, 402, { \n error: `Payment verification failed: ${verification.error}` \n });\n }\n\n console.log(`[MoltsPay] Payment verified! Executing service: ${config.id}`);\n\n // Execute the skill\n let result: any;\n try {\n result = await skill.handler(params);\n } catch (err: any) {\n console.error(`[MoltsPay] Skill execution error:`, err);\n return this.sendJson(res, 500, { \n error: `Service execution failed: ${err.message}` \n });\n }\n\n // Build receipt\n const receipt = {\n success: true,\n txHash,\n network,\n facilitator: verification.facilitator,\n };\n const receiptEncoded = Buffer.from(JSON.stringify(receipt)).toString('base64');\n\n // Return success with MPP receipt header\n res.writeHead(200, {\n 'Content-Type': 'application/json',\n [MPP_RECEIPT_HEADER]: receiptEncoded,\n });\n res.end(JSON.stringify({\n success: true,\n result,\n payment: {\n txHash,\n status: 'verified',\n facilitator: verification.facilitator,\n },\n }, null, 2));\n }\n\n /**\n * Return 402 with both x402 and MPP payment requirements\n */\n private sendMPPPaymentRequired(config: ServiceConfig, res: ServerResponse): void {\n const acceptedTokens = getAcceptedCurrencies(config);\n const providerChains = this.getProviderChains();\n \n // === x402 format (existing) ===\n const accepts: X402PaymentRequirements[] = [];\n for (const chainConfig of providerChains) {\n for (const token of acceptedTokens) {\n if (chainConfig.tokens.includes(token)) {\n accepts.push(this.buildPaymentRequirements(config, chainConfig.network, chainConfig.wallet, token));\n }\n }\n }\n\n const x402PaymentRequired = {\n x402Version: X402_VERSION,\n accepts,\n acceptedCurrencies: acceptedTokens,\n resource: {\n url: `/${config.id}`,\n description: `${config.name} - $${config.price} ${config.currency}`,\n },\n };\n const x402Encoded = Buffer.from(JSON.stringify(x402PaymentRequired)).toString('base64');\n\n // === MPP format ===\n // Find Tempo chain if available\n const tempoChain = providerChains.find(c => c.network === 'eip155:42431');\n \n let mppWwwAuth = '';\n if (tempoChain) {\n const challengeId = this.generateChallengeId();\n const amountInUnits = Math.floor(config.price * 1e6).toString();\n const tokenAddress = TOKEN_ADDRESSES['eip155:42431']?.USDC || '0x20c0000000000000000000000000000000000000';\n \n const mppRequest = {\n amount: amountInUnits,\n currency: tokenAddress,\n methodDetails: {\n chainId: 42431,\n feePayer: true,\n },\n recipient: tempoChain.wallet,\n };\n const mppRequestEncoded = Buffer.from(JSON.stringify(mppRequest)).toString('base64');\n \n const expiresAt = new Date(Date.now() + 5 * 60 * 1000).toISOString();\n \n mppWwwAuth = `Payment id=\"${challengeId}\", realm=\"${this.manifest.provider.name}\", method=\"tempo\", intent=\"charge\", request=\"${mppRequestEncoded}\", description=\"${config.name}\", expires=\"${expiresAt}\"`;\n }\n\n // Build response headers\n const headers: Record<string, string> = {\n 'Content-Type': 'application/problem+json',\n [PAYMENT_REQUIRED_HEADER]: x402Encoded,\n };\n \n if (mppWwwAuth) {\n headers[MPP_WWW_AUTH_HEADER] = mppWwwAuth;\n }\n\n res.writeHead(402, headers);\n res.end(JSON.stringify({\n type: 'https://paymentauth.org/problems/payment-required',\n title: 'Payment Required',\n status: 402,\n detail: `Payment is required (${config.name}).`,\n service: config.id,\n price: config.price,\n currency: config.currency,\n acceptedCurrencies: acceptedTokens,\n }, null, 2));\n }\n\n /**\n * Generate a unique challenge ID for MPP\n */\n private generateChallengeId(): string {\n const bytes = new Uint8Array(24);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n return Buffer.from(bytes).toString('base64url');\n }\n\n /**\n * Return 402 with x402 payment requirements (v2 format)\n * Includes requirements for all chains and all accepted currencies\n */\n private sendPaymentRequired(config: ServiceConfig, res: ServerResponse): void {\n const acceptedTokens = getAcceptedCurrencies(config);\n const providerChains = this.getProviderChains();\n \n // Build requirements for each chain x token combination\n const accepts: X402PaymentRequirements[] = [];\n for (const chainConfig of providerChains) {\n for (const token of acceptedTokens) {\n // Only add if this chain supports this token\n if (chainConfig.tokens.includes(token)) {\n accepts.push(this.buildPaymentRequirements(config, chainConfig.network, chainConfig.wallet, token));\n }\n }\n }\n\n // Get list of accepted chains for response\n const acceptedChains = providerChains.map(c => {\n // Convert network ID to chain name for readability\n if (c.network === 'eip155:8453') return 'base';\n if (c.network === 'eip155:137') return 'polygon';\n return c.network;\n });\n\n const paymentRequired = {\n x402Version: X402_VERSION,\n accepts,\n acceptedCurrencies: acceptedTokens,\n acceptedChains,\n resource: {\n url: `/execute?service=${config.id}`,\n description: `${config.name} - $${config.price} ${config.currency}`,\n mimeType: 'application/json',\n },\n };\n\n const encoded = Buffer.from(JSON.stringify(paymentRequired)).toString('base64');\n\n res.writeHead(402, {\n 'Content-Type': 'application/json',\n [PAYMENT_REQUIRED_HEADER]: encoded,\n });\n res.end(JSON.stringify({\n error: 'Payment required',\n message: `Service requires $${config.price} ${config.currency}`,\n acceptedCurrencies: acceptedTokens,\n acceptedChains,\n x402: paymentRequired,\n }, null, 2));\n }\n\n /**\n * Basic payment validation\n */\n private validatePayment(\n payment: X402PaymentPayload,\n config: ServiceConfig\n ): { valid: boolean; error?: string } {\n if (payment.x402Version !== X402_VERSION) {\n return { valid: false, error: `Unsupported x402 version: ${payment.x402Version}` };\n }\n\n const scheme = payment.accepted?.scheme || payment.scheme;\n const network = payment.accepted?.network || payment.network || this.networkId;\n\n if (scheme !== 'exact') {\n return { valid: false, error: `Unsupported scheme: ${scheme}` };\n }\n\n // Check if payment network is one of our accepted networks\n if (!this.isNetworkAccepted(network)) {\n const acceptedChains = this.getProviderChains().map(c => c.network).join(', ');\n return { valid: false, error: `Network not accepted: ${network}. Accepted: ${acceptedChains}` };\n }\n\n return { valid: true };\n }\n\n /**\n * Build payment requirements for facilitator\n * Now supports multi-chain: takes network and wallet as parameters\n */\n private buildPaymentRequirements(\n config: ServiceConfig, \n network?: string, \n wallet?: string,\n token?: string\n ): X402PaymentRequirements {\n const amountInUnits = Math.floor(config.price * 1e6).toString();\n const acceptedTokens = getAcceptedCurrencies(config);\n \n // Use specified values or defaults\n const selectedNetwork = network || this.networkId;\n const selectedWallet = wallet || this.manifest.provider.wallet;\n const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];\n \n const tokenAddresses = TOKEN_ADDRESSES[selectedNetwork] || {};\n const tokenAddress = tokenAddresses[selectedToken];\n const tokenDomain = getTokenDomain(selectedNetwork, selectedToken);\n\n return {\n scheme: 'exact',\n network: selectedNetwork,\n asset: tokenAddress,\n amount: amountInUnits,\n payTo: selectedWallet,\n maxTimeoutSeconds: 300,\n extra: tokenDomain,\n };\n }\n\n /**\n * Detect which token is being used in the payment\n * Checks across all supported networks\n */\n private detectPaymentToken(payment: X402PaymentPayload): string | undefined {\n const asset = payment.accepted?.asset || (payment.payload as any)?.asset;\n if (!asset) return undefined;\n\n // Get payment network to check correct token addresses\n const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;\n const tokenAddresses = TOKEN_ADDRESSES[paymentNetwork] || {};\n \n for (const [symbol, address] of Object.entries(tokenAddresses)) {\n if (address && (address as string).toLowerCase() === asset.toLowerCase()) {\n return symbol;\n }\n }\n return undefined;\n }\n\n /**\n * Check if payment token is accepted for service\n */\n private isTokenAccepted(config: ServiceConfig, token: string): boolean {\n const accepted = getAcceptedCurrencies(config);\n return accepted.includes(token);\n }\n\n private async readBody(req: IncomingMessage): Promise<any> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', chunk => body += chunk);\n req.on('end', () => {\n try {\n resolve(body ? JSON.parse(body) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n }\n\n private sendJson(\n res: ServerResponse, \n status: number, \n data: any,\n extraHeaders?: Record<string, string>\n ): void {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (extraHeaders) {\n Object.assign(headers, extraHeaders);\n }\n res.writeHead(status, headers);\n res.end(JSON.stringify(data, null, 2));\n }\n\n /**\n * Check if IP is allowed for /proxy endpoint\n */\n private isProxyAllowed(clientIP: string): boolean {\n const allowedIPs = process.env.PROXY_ALLOWED_IPS?.split(',').map(ip => ip.trim()) || [];\n \n // If no whitelist configured, deny all (secure by default)\n if (allowedIPs.length === 0) {\n console.log(`[MoltsPay] /proxy denied: no PROXY_ALLOWED_IPS configured`);\n return false;\n }\n \n // Normalize IPv6 localhost\n const normalizedIP = clientIP === '::1' ? '127.0.0.1' : clientIP.replace('::ffff:', '');\n \n const allowed = allowedIPs.includes(normalizedIP) || allowedIPs.includes(clientIP);\n if (!allowed) {\n console.log(`[MoltsPay] /proxy denied for IP: ${clientIP} (normalized: ${normalizedIP})`);\n }\n return allowed;\n }\n\n /**\n * POST /proxy - Handle payment for external services (moltspay-creators)\n * \n * This endpoint allows other services to delegate x402 payment handling.\n * It does NOT execute any skill - just handles payment verification/settlement.\n * \n * Request body:\n * { wallet, amount, currency, chain, memo, serviceId, description }\n * \n * Without X-Payment header: returns 402 with payment requirements\n * With X-Payment header: verifies payment and returns result\n */\n private async handleProxy(\n body: any,\n paymentHeader: string | undefined,\n res: ServerResponse\n ): Promise<void> {\n const { wallet, amount, currency, chain, memo, serviceId, description } = body;\n\n // Validate required fields\n if (!wallet || !amount) {\n return this.sendJson(res, 400, { error: 'Missing required fields: wallet, amount' });\n }\n\n // Validate wallet format\n if (!/^0x[a-fA-F0-9]{40}$/.test(wallet)) {\n return this.sendJson(res, 400, { error: 'Invalid wallet address format' });\n }\n\n // Validate amount\n const amountNum = parseFloat(amount);\n if (isNaN(amountNum) || amountNum <= 0) {\n return this.sendJson(res, 400, { error: 'Invalid amount' });\n }\n \n // Validate chain if provided\n const supportedChains = ['base', 'polygon', 'base_sepolia'];\n if (chain && !supportedChains.includes(chain)) {\n return this.sendJson(res, 400, { error: `Unsupported chain: ${chain}. Supported: ${supportedChains.join(', ')}` });\n }\n\n // Build a synthetic service config for payment\n const proxyConfig: ServiceConfig = {\n id: serviceId || 'proxy',\n name: description || 'Proxy Payment',\n description: description || '',\n price: amountNum,\n currency: currency || 'USDC',\n function: '', // Not used\n input: {},\n output: {},\n };\n\n // Build payment requirements with the provided wallet and chain\n const requirements = this.buildProxyPaymentRequirements(proxyConfig, wallet, currency, chain);\n\n // If no payment header, return 402 with payment requirements\n if (!paymentHeader) {\n return this.sendProxyPaymentRequired(proxyConfig, wallet, memo, chain, res);\n }\n\n // Parse payment payload\n let payment: X402PaymentPayload;\n try {\n const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');\n payment = JSON.parse(decoded);\n } catch {\n return this.sendJson(res, 400, { error: 'Invalid X-Payment header' });\n }\n\n // Validate basic payment fields\n if (payment.x402Version !== X402_VERSION) {\n return this.sendJson(res, 402, { error: `Unsupported x402 version: ${payment.x402Version}` });\n }\n\n const scheme = payment.accepted?.scheme || payment.scheme;\n const network = payment.accepted?.network || payment.network;\n\n if (scheme !== 'exact') {\n return this.sendJson(res, 402, { error: `Unsupported scheme: ${scheme}` });\n }\n\n // Validate network matches requested chain (or default to provider's network)\n const expectedNetwork = chain ? (CHAIN_TO_NETWORK[chain] || this.networkId) : this.networkId;\n if (network !== expectedNetwork) {\n return this.sendJson(res, 402, { error: `Network mismatch: expected ${expectedNetwork}, got ${network}` });\n }\n\n // Verify payment with facilitator\n console.log(`[MoltsPay] /proxy: Verifying payment for ${wallet}...`);\n const verifyResult = await this.registry.verify(payment, requirements);\n if (!verifyResult.valid) {\n return this.sendJson(res, 402, { \n success: false,\n error: `Payment verification failed: ${verifyResult.error}`,\n facilitator: verifyResult.facilitator,\n });\n }\n console.log(`[MoltsPay] /proxy: Verified by ${verifyResult.facilitator}`);\n\n // Check if execution requested\n const { execute, service, params } = body;\n \n // If execute requested, run skill BEFORE settling (pay on success)\n if (execute && service) {\n console.log(`[MoltsPay] /proxy: Executing skill first (pay on success): ${service}`);\n const skill = this.skills.get(service);\n if (!skill) {\n // Service not found - don't settle, return error\n console.log(`[MoltsPay] /proxy: Service not found: ${service} - NOT settling`);\n return this.sendJson(res, 404, {\n success: false,\n paymentSettled: false,\n error: `Service not found: ${service}`,\n });\n }\n\n // Execute skill first (with timeout)\n const timeoutSeconds = parseInt(process.env.SKILL_TIMEOUT_SECONDS || '1200');\n let result: any;\n try {\n result = await Promise.race([\n skill.handler(params || {}),\n new Promise((_, reject) => \n setTimeout(() => reject(new Error(`Skill timeout after ${timeoutSeconds}s`)), timeoutSeconds * 1000)\n )\n ]);\n console.log(`[MoltsPay] /proxy: Skill succeeded, now settling payment...`);\n } catch (err: any) {\n // Skill failed or timeout - don't settle, client keeps their money\n console.error(`[MoltsPay] /proxy: Skill failed: ${err.message} - NOT settling`);\n return this.sendJson(res, 500, {\n success: false,\n paymentSettled: false,\n error: `Service execution failed: ${err.message}`,\n });\n }\n\n // Skill succeeded - now settle payment\n let settlement: any = null;\n try {\n settlement = await this.registry.settle(payment, requirements);\n console.log(`[MoltsPay] /proxy: Payment settled by ${settlement.facilitator}: ${settlement.transaction || 'pending'}`);\n } catch (err: any) {\n console.error('[MoltsPay] /proxy: Settlement failed:', err.message);\n // Skill succeeded but settlement failed - return result anyway with warning\n return this.sendJson(res, 200, {\n success: true,\n verified: true,\n settled: false,\n settlementError: err.message,\n from: (payment.payload as any)?.authorization?.from, // Buyer's wallet address\n paidTo: wallet,\n amount: amountNum,\n currency: currency || 'USDC',\n memo,\n result,\n });\n }\n\n return this.sendJson(res, 200, {\n success: true,\n verified: true,\n settled: settlement?.success || false,\n txHash: settlement?.transaction,\n from: (payment.payload as any)?.authorization?.from, // Buyer's wallet address\n paidTo: wallet,\n amount: amountNum,\n currency: currency || 'USDC',\n facilitator: settlement?.facilitator,\n memo,\n result,\n });\n }\n\n // No execution requested - settle immediately (payment-only mode)\n console.log(`[MoltsPay] /proxy: Settling payment (no execution)...`);\n let settlement: any = null;\n try {\n settlement = await this.registry.settle(payment, requirements);\n console.log(`[MoltsPay] /proxy: Payment settled by ${settlement.facilitator}: ${settlement.transaction || 'pending'}`);\n } catch (err: any) {\n console.error('[MoltsPay] /proxy: Settlement failed:', err.message);\n return this.sendJson(res, 500, {\n success: false,\n error: `Settlement failed: ${err.message}`,\n });\n }\n\n // Return success (payment only, no execution)\n this.sendJson(res, 200, {\n success: true,\n verified: true,\n settled: settlement?.success || false,\n txHash: settlement?.transaction,\n from: (payment.payload as any)?.authorization?.from, // Buyer's wallet address\n paidTo: wallet,\n amount: amountNum,\n currency: currency || 'USDC',\n facilitator: settlement?.facilitator,\n memo,\n });\n }\n\n /**\n * Build payment requirements for proxy endpoint (uses provided wallet)\n */\n private buildProxyPaymentRequirements(config: ServiceConfig, wallet: string, token?: string, chain?: string): X402PaymentRequirements {\n const amountInUnits = Math.floor(config.price * 1e6).toString();\n const acceptedTokens = getAcceptedCurrencies(config);\n \n // Determine network from chain parameter or use default\n const networkId = chain ? (CHAIN_TO_NETWORK[chain] || this.networkId) : this.networkId;\n \n // Use specified token or default to first accepted\n const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];\n const tokenAddresses = TOKEN_ADDRESSES[networkId] || TOKEN_ADDRESSES[this.networkId] || {};\n const tokenAddress = tokenAddresses[selectedToken];\n const tokenDomain = getTokenDomain(networkId, selectedToken);\n\n return {\n scheme: 'exact',\n network: networkId,\n asset: tokenAddress,\n amount: amountInUnits,\n payTo: wallet, // Use provided wallet, not manifest\n maxTimeoutSeconds: 300,\n extra: tokenDomain,\n };\n }\n\n /**\n * Return 402 with x402 payment requirements for proxy endpoint\n */\n private sendProxyPaymentRequired(\n config: ServiceConfig, \n wallet: string,\n memo: string | undefined,\n chain: string | undefined,\n res: ServerResponse\n ): void {\n const requirements = this.buildProxyPaymentRequirements(config, wallet, config.currency, chain);\n\n const paymentRequired = {\n x402Version: X402_VERSION,\n accepts: [requirements],\n resource: {\n url: `/proxy`,\n description: `${config.name} - $${config.price} ${config.currency}`,\n mimeType: 'application/json',\n memo,\n },\n };\n\n const encoded = Buffer.from(JSON.stringify(paymentRequired)).toString('base64');\n\n res.writeHead(402, {\n 'Content-Type': 'application/json',\n [PAYMENT_REQUIRED_HEADER]: encoded,\n });\n res.end(JSON.stringify({\n error: 'Payment required',\n message: `Payment requires $${config.price} ${config.currency}`,\n x402: paymentRequired,\n }, null, 2));\n }\n}\n","/**\n * Facilitator Interface\n * \n * A facilitator is a service that handles x402 payment verification and settlement.\n * This abstraction allows MoltsPay to support multiple facilitators.\n * \n * @see https://www.x402.org/ecosystem?category=facilitators\n */\n\n/**\n * x402 Payment Payload (from client)\n */\nexport interface X402PaymentPayload {\n x402Version: number;\n scheme?: string;\n network?: string;\n accepted?: {\n scheme: string;\n network: string;\n asset: string;\n amount: string;\n payTo: string;\n maxTimeoutSeconds: number;\n extra?: Record<string, unknown>;\n };\n payload: unknown;\n}\n\n/**\n * x402 Payment Requirements (server specifies what it accepts)\n */\nexport interface X402PaymentRequirements {\n scheme: string;\n network: string;\n asset: string;\n amount: string;\n payTo: string;\n maxTimeoutSeconds: number;\n extra?: Record<string, unknown>;\n}\n\n/**\n * Result of payment verification\n */\nexport interface VerifyResult {\n valid: boolean;\n error?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * Result of payment settlement\n */\nexport interface SettleResult {\n success: boolean;\n transaction?: string;\n error?: string;\n status?: string;\n}\n\n/**\n * Facilitator health check result\n */\nexport interface HealthCheckResult {\n healthy: boolean;\n latencyMs?: number;\n error?: string;\n}\n\n/**\n * Facilitator fee information (for selection strategies)\n */\nexport interface FacilitatorFee {\n perTx: number;\n currency: string;\n freeQuota?: number;\n}\n\n/**\n * Facilitator configuration\n */\nexport interface FacilitatorConfig {\n /** Facilitator endpoint URL */\n endpoint?: string;\n /** API key (if required) */\n apiKey?: string;\n /** API secret (if required) */\n apiSecret?: string;\n /** Additional config specific to facilitator */\n [key: string]: unknown;\n}\n\n/**\n * Facilitator Interface\n * \n * All facilitators must implement this interface.\n */\nexport interface Facilitator {\n /** Unique identifier for this facilitator */\n readonly name: string;\n \n /** Human-readable display name */\n readonly displayName: string;\n \n /** Supported networks (e.g., [\"eip155:8453\", \"eip155:84532\"]) */\n readonly supportedNetworks: string[];\n \n /**\n * Check if facilitator is available and responsive\n */\n healthCheck(): Promise<HealthCheckResult>;\n \n /**\n * Verify a payment signature without executing it\n * \n * @param paymentPayload - The x402 payment payload from client\n * @param requirements - The payment requirements from server\n */\n verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult>;\n \n /**\n * Settle a payment on-chain\n * \n * @param paymentPayload - The x402 payment payload from client\n * @param requirements - The payment requirements from server\n */\n settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult>;\n \n /**\n * Get current fee information (optional, for selection strategies)\n */\n getFee?(): Promise<FacilitatorFee>;\n \n /**\n * Check if this facilitator supports a given network\n */\n supportsNetwork(network: string): boolean;\n}\n\n/**\n * Base class with common functionality\n */\nexport abstract class BaseFacilitator implements Facilitator {\n abstract readonly name: string;\n abstract readonly displayName: string;\n abstract readonly supportedNetworks: string[];\n \n abstract healthCheck(): Promise<HealthCheckResult>;\n abstract verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult>;\n abstract settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult>;\n \n supportsNetwork(network: string): boolean {\n return this.supportedNetworks.includes(network);\n }\n}\n","/**\n * CDP Facilitator\n * \n * Coinbase Developer Platform x402 facilitator implementation.\n * Auto-detects mainnet vs testnet from chain ID in request.\n * \n * Supported networks:\n * - Base mainnet (eip155:8453)\n * - Polygon mainnet (eip155:137)\n * - Base Sepolia testnet (eip155:84532)\n * \n * @see https://docs.cdp.coinbase.com/x402/core-concepts/facilitator\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport * as path from 'path';\nimport {\n BaseFacilitator,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n FacilitatorFee,\n FacilitatorConfig,\n} from './interface.js';\n\n// x402 protocol version\nconst X402_VERSION = 2;\n\n// CDP Facilitator URL (handles both mainnet and testnet)\nconst CDP_URL = 'https://api.cdp.coinbase.com/platform/v2/x402';\n\n// Testnet chain IDs (for logging/info only - CDP auto-detects from network field)\nconst TESTNET_CHAIN_IDS = [84532]; // Base Sepolia\n\nexport interface CDPFacilitatorConfig extends FacilitatorConfig {\n /** CDP API Key ID (required) */\n apiKeyId?: string;\n /** CDP API Key Secret (required) */\n apiKeySecret?: string;\n}\n\n/**\n * Load environment from .env files\n */\nfunction loadEnvFile(): void {\n const envPaths = [\n path.join(process.cwd(), '.env'),\n path.join(process.env.HOME || '', '.moltspay', '.env'),\n ];\n \n for (const envPath of envPaths) {\n if (existsSync(envPath)) {\n try {\n const content = readFileSync(envPath, 'utf-8');\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eqIndex = trimmed.indexOf('=');\n if (eqIndex === -1) continue;\n const key = trimmed.slice(0, eqIndex).trim();\n let value = trimmed.slice(eqIndex + 1).trim();\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n if (!process.env[key]) {\n process.env[key] = value;\n }\n }\n break;\n } catch {\n // Ignore errors\n }\n }\n }\n}\n\n/**\n * CDP (Coinbase Developer Platform) Facilitator\n * \n * Handles payment verification and settlement via Coinbase's x402 facilitator.\n */\nexport class CDPFacilitator extends BaseFacilitator {\n readonly name = 'cdp';\n readonly displayName = 'Coinbase CDP';\n readonly supportedNetworks: string[];\n \n private endpoint: string;\n private apiKeyId?: string;\n private apiKeySecret?: string;\n \n constructor(config: CDPFacilitatorConfig = {}) {\n super();\n \n // Load env files for credentials\n loadEnvFile();\n \n // Get credentials (required for CDP)\n this.apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;\n this.apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;\n \n // Single endpoint handles both mainnet and testnet (auto-detected from chain ID in request)\n this.endpoint = CDP_URL;\n \n // All supported networks - CDP handles both mainnet and testnet\n this.supportedNetworks = [\n 'eip155:8453', // Base mainnet\n 'eip155:137', // Polygon mainnet\n 'eip155:84532', // Base Sepolia (testnet)\n ];\n \n // Warn if missing credentials\n if (!this.apiKeyId || !this.apiKeySecret) {\n console.warn('[CDPFacilitator] WARNING: Missing CDP credentials!');\n console.warn('[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET in ~/.moltspay/.env');\n }\n }\n \n /**\n * Get auth headers for CDP API requests\n */\n private async getAuthHeaders(\n method: string,\n urlPath: string,\n body?: unknown\n ): Promise<Record<string, string>> {\n if (!this.apiKeyId || !this.apiKeySecret) {\n throw new Error('CDP credentials required. Set CDP_API_KEY_ID and CDP_API_KEY_SECRET');\n }\n \n try {\n const { getAuthHeaders } = await import('@coinbase/cdp-sdk/auth');\n \n return await getAuthHeaders({\n apiKeyId: this.apiKeyId,\n apiKeySecret: this.apiKeySecret,\n requestMethod: method,\n requestHost: 'api.cdp.coinbase.com',\n requestPath: urlPath,\n requestBody: body,\n });\n } catch (err: any) {\n throw new Error(`Failed to generate CDP auth: ${err.message}`);\n }\n }\n \n /**\n * Health check - verify facilitator is reachable\n */\n async healthCheck(): Promise<HealthCheckResult> {\n const start = Date.now();\n \n try {\n // For testnet, just check if x402.org responds\n // For mainnet, we could hit a health endpoint or just check DNS\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5000);\n \n const response = await fetch(this.endpoint.replace('/x402', ''), {\n method: 'HEAD',\n signal: controller.signal,\n }).catch(() => null);\n \n clearTimeout(timeout);\n \n const latencyMs = Date.now() - start;\n \n return {\n healthy: response !== null,\n latencyMs,\n };\n } catch (err: any) {\n return {\n healthy: false,\n error: err.message,\n latencyMs: Date.now() - start,\n };\n }\n }\n \n /**\n * Verify payment signature with facilitator\n */\n async verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult> {\n try {\n const requestBody = {\n x402Version: X402_VERSION,\n paymentPayload,\n paymentRequirements: requirements,\n };\n \n console.log('[CDP Verify] Payload:', JSON.stringify(paymentPayload, null, 2));\n \n const authHeaders = await this.getAuthHeaders(\n 'POST',\n '/platform/v2/x402/verify',\n requestBody\n );\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...authHeaders,\n };\n \n const response = await fetch(`${this.endpoint}/verify`, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n });\n \n const result = await response.json() as any;\n console.log('[CDP Verify] Response:', response.status, JSON.stringify(result));\n \n if (!response.ok || !result.isValid) {\n return {\n valid: false,\n error: result.invalidReason || result.error || 'Verification failed',\n details: result,\n };\n }\n \n return { valid: true, details: result };\n } catch (err: any) {\n return {\n valid: false,\n error: `Facilitator error: ${err.message}`,\n };\n }\n }\n \n /**\n * Settle payment on-chain via facilitator\n */\n async settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult> {\n try {\n const requestBody = {\n x402Version: X402_VERSION,\n paymentPayload,\n paymentRequirements: requirements,\n };\n \n const authHeaders = await this.getAuthHeaders(\n 'POST',\n '/platform/v2/x402/settle',\n requestBody\n );\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...authHeaders,\n };\n \n const response = await fetch(`${this.endpoint}/settle`, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n });\n \n const result = await response.json() as any;\n \n if (!response.ok || !result.success) {\n return {\n success: false,\n error: result.error || result.errorReason || 'Settlement failed',\n };\n }\n \n return {\n success: true,\n transaction: result.transaction,\n status: result.status || 'settled',\n };\n } catch (err: any) {\n return {\n success: false,\n error: `Settlement error: ${err.message}`,\n };\n }\n }\n \n /**\n * Get CDP fee information\n */\n async getFee(): Promise<FacilitatorFee> {\n // CDP pricing: 1000 free/month, then $0.001/tx\n return {\n perTx: 0.001,\n currency: 'USD',\n freeQuota: 1000,\n };\n }\n \n /**\n * Check if a chain ID is testnet\n */\n static isTestnet(chainId: number): boolean {\n return TESTNET_CHAIN_IDS.includes(chainId);\n }\n \n /**\n * Get configuration summary (for logging)\n */\n getConfigSummary(): string {\n const hasCredentials = !!(this.apiKeyId && this.apiKeySecret);\n const networks = this.supportedNetworks.join(', ');\n return `CDP Facilitator (networks: ${networks}, credentials: ${hasCredentials ? 'yes' : 'no'})`;\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName, TokenSymbol } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n tokens: {\n USDC: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin', // EIP-712 domain name\n },\n USDT: {\n address: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // deprecated, for backward compat\n explorer: 'https://basescan.org/address/',\n explorerTx: 'https://basescan.org/tx/',\n avgBlockTime: 2,\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n rpc: 'https://polygon-bor-rpc.publicnode.com',\n tokens: {\n USDC: {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: '(PoS) Tether USD', // Polygon uses this name\n },\n },\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n // ============ Testnet ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n tokens: {\n USDC: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USDC', // Testnet USDC uses 'USDC' not 'USD Coin'\n },\n USDT: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Same as USDC on testnet (no official USDT)\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'USDC', // Uses same contract as USDC\n },\n },\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n // ============ Tempo Testnet (Moderato) ============\n tempo_moderato: {\n name: 'Tempo Moderato',\n chainId: 42431,\n rpc: 'https://rpc.moderato.tempo.xyz',\n tokens: {\n // TIP-20 stablecoins on Tempo testnet (from mppx SDK)\n // Note: Tempo uses USD as native gas token, not ETH\n USDC: {\n address: '0x20c0000000000000000000000000000000000000', // pathUSD - primary testnet stablecoin\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'pathUSD',\n },\n USDT: {\n address: '0x20c0000000000000000000000000000000000001', // alphaUSD\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'alphaUSD',\n },\n },\n usdc: '0x20c0000000000000000000000000000000000000',\n explorer: 'https://explore.testnet.tempo.xyz/address/',\n explorerTx: 'https://explore.testnet.tempo.xyz/tx/',\n avgBlockTime: 0.5, // ~500ms finality\n },\n};\n\n/**\n * Get token address for a chain\n */\nexport function getTokenAddress(chainName: ChainName, token: TokenSymbol): string {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n const tokenConfig = chain.tokens[token];\n if (!tokenConfig) {\n throw new Error(`Token ${token} not supported on ${chainName}`);\n }\n return tokenConfig.address;\n}\n\n/**\n * Get token config for a chain\n */\nexport function getTokenConfig(chainName: ChainName, token: TokenSymbol) {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n return chain.tokens[token];\n}\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * List all supported chains\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * Get chain config by chainId\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI (minimal, only required methods)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName, TokenSymbol };\n","/**\n * Tempo Testnet Facilitator\n * \n * Verifies payments on Tempo Moderato testnet by checking transaction receipts.\n * Unlike CDP facilitator, this directly verifies on-chain without a third-party service.\n */\n\nimport {\n BaseFacilitator,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n} from './interface.js';\nimport { CHAINS } from '../chains/index.js';\n\n// TIP-20 Transfer event signature\nconst TRANSFER_EVENT_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';\n\ninterface TempoPaymentPayload {\n txHash: string;\n chainId: number;\n}\n\n/**\n * Tempo Testnet Facilitator\n * \n * Verifies TIP-20 token transfers on Tempo Moderato (chainId 42431).\n */\nexport class TempoFacilitator extends BaseFacilitator {\n readonly name = 'tempo';\n readonly displayName = 'Tempo Testnet';\n readonly supportedNetworks = ['eip155:42431']; // Tempo Moderato\n\n private rpcUrl: string;\n\n constructor() {\n super();\n this.rpcUrl = CHAINS.tempo_moderato.rpc;\n }\n\n async healthCheck(): Promise<HealthCheckResult> {\n const start = Date.now();\n try {\n const response = await fetch(this.rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_chainId',\n params: [],\n id: 1,\n }),\n });\n \n const data = await response.json() as { result: string };\n const chainId = parseInt(data.result, 16);\n \n if (chainId !== 42431) {\n return { healthy: false, error: `Wrong chainId: ${chainId}` };\n }\n \n return { healthy: true, latencyMs: Date.now() - start };\n } catch (error) {\n return { healthy: false, error: String(error) };\n }\n }\n\n async verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult> {\n try {\n // Extract Tempo-specific payload\n const tempoPayload = paymentPayload.payload as TempoPaymentPayload;\n \n if (!tempoPayload?.txHash) {\n return { valid: false, error: 'Missing txHash in payment payload' };\n }\n\n // Get transaction receipt\n const receipt = await this.getTransactionReceipt(tempoPayload.txHash);\n \n if (!receipt) {\n return { valid: false, error: 'Transaction not found' };\n }\n\n if (receipt.status !== '0x1') {\n return { valid: false, error: 'Transaction failed' };\n }\n\n // Find Transfer event\n const transferLog = receipt.logs.find((log: any) => \n log.topics[0] === TRANSFER_EVENT_TOPIC\n );\n\n if (!transferLog) {\n return { valid: false, error: 'No Transfer event found' };\n }\n\n // Verify recipient (topic[2] is 'to' address, padded to 32 bytes)\n const toAddress = '0x' + transferLog.topics[2].slice(26).toLowerCase();\n const expectedTo = requirements.payTo.toLowerCase();\n \n if (toAddress !== expectedTo) {\n return { \n valid: false, \n error: `Wrong recipient: ${toAddress}, expected ${expectedTo}` \n };\n }\n\n // Verify amount (data field contains the amount)\n const amount = BigInt(transferLog.data);\n const expectedAmount = BigInt(requirements.amount);\n \n if (amount < expectedAmount) {\n return { \n valid: false, \n error: `Insufficient amount: ${amount}, expected ${expectedAmount}` \n };\n }\n\n // Verify token address\n const tokenAddress = transferLog.address.toLowerCase();\n const expectedToken = requirements.asset.toLowerCase();\n \n if (tokenAddress !== expectedToken) {\n return { \n valid: false, \n error: `Wrong token: ${tokenAddress}, expected ${expectedToken}` \n };\n }\n\n return { \n valid: true, \n details: {\n txHash: tempoPayload.txHash,\n from: '0x' + transferLog.topics[1].slice(26),\n to: toAddress,\n amount: amount.toString(),\n token: tokenAddress,\n }\n };\n } catch (error) {\n return { valid: false, error: `Verification failed: ${error}` };\n }\n }\n\n async settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult> {\n // For Tempo, the client already executed the transaction\n // We just verify and report success\n const verifyResult = await this.verify(paymentPayload, requirements);\n \n if (!verifyResult.valid) {\n return { success: false, error: verifyResult.error };\n }\n\n const tempoPayload = paymentPayload.payload as TempoPaymentPayload;\n \n return { \n success: true, \n transaction: tempoPayload.txHash,\n status: 'settled'\n };\n }\n\n private async getTransactionReceipt(txHash: string): Promise<any> {\n const response = await fetch(this.rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_getTransactionReceipt',\n params: [txHash],\n id: 1,\n }),\n });\n\n const data = await response.json() as { result: any };\n return data.result;\n }\n}\n","/**\n * Facilitator Registry\n * \n * Central registry for all available facilitators.\n * Supports selection strategies for failover, load balancing, etc.\n */\n\nimport {\n Facilitator,\n FacilitatorConfig,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n} from './interface.js';\nimport { CDPFacilitator, CDPFacilitatorConfig } from './cdp.js';\nimport { TempoFacilitator } from './tempo.js';\n\n/**\n * Selection strategy for choosing facilitators\n */\nexport type SelectionStrategy = \n | 'failover' // Use primary, switch to fallback on failure\n | 'cheapest' // Use facilitator with lowest fees\n | 'fastest' // Use first responder\n | 'random' // Random selection (load balancing)\n | 'roundrobin'; // Rotate through facilitators\n\n/**\n * Facilitator selection configuration\n */\nexport interface FacilitatorSelection {\n /** Primary facilitator to use */\n primary: string;\n /** Fallback facilitators (in order of preference) */\n fallback?: string[];\n /** Selection strategy */\n strategy?: SelectionStrategy;\n /** Per-facilitator config overrides */\n config?: Record<string, FacilitatorConfig>;\n}\n\n/**\n * Factory function type for creating facilitators\n */\ntype FacilitatorFactory = (config?: FacilitatorConfig) => Facilitator;\n\n/**\n * Facilitator Registry\n * \n * Manages available facilitators and provides selection logic.\n */\nexport class FacilitatorRegistry {\n private factories: Map<string, FacilitatorFactory> = new Map();\n private instances: Map<string, Facilitator> = new Map();\n private selection: FacilitatorSelection;\n private roundRobinIndex = 0;\n \n constructor(selection?: FacilitatorSelection) {\n // Register built-in facilitators\n this.registerFactory('cdp', (config) => new CDPFacilitator(config as CDPFacilitatorConfig));\n this.registerFactory('tempo', () => new TempoFacilitator());\n \n // Default selection\n this.selection = selection || { primary: 'cdp', fallback: ['tempo'], strategy: 'failover' };\n }\n \n /**\n * Register a new facilitator factory\n */\n registerFactory(name: string, factory: FacilitatorFactory): void {\n this.factories.set(name, factory);\n }\n \n /**\n * Get or create a facilitator instance\n */\n get(name: string, config?: FacilitatorConfig): Facilitator {\n // Check cache first\n if (this.instances.has(name)) {\n return this.instances.get(name)!;\n }\n \n // Look up factory\n const factory = this.factories.get(name);\n if (!factory) {\n throw new Error(`Unknown facilitator: ${name}. Available: ${Array.from(this.factories.keys()).join(', ')}`);\n }\n \n // Merge config from selection\n const mergedConfig = {\n ...this.selection.config?.[name],\n ...config,\n };\n \n // Create and cache instance\n const instance = factory(mergedConfig);\n this.instances.set(name, instance);\n return instance;\n }\n \n /**\n * Get all configured facilitator names\n */\n getConfiguredNames(): string[] {\n const names = [this.selection.primary];\n if (this.selection.fallback) {\n names.push(...this.selection.fallback);\n }\n return names;\n }\n \n /**\n * Get list of facilitators based on selection strategy\n */\n private async getOrderedFacilitators(network: string): Promise<Facilitator[]> {\n const names = this.getConfiguredNames();\n const facilitators: Facilitator[] = [];\n \n for (const name of names) {\n try {\n const f = this.get(name);\n if (f.supportsNetwork(network)) {\n facilitators.push(f);\n }\n } catch (err) {\n console.warn(`[Registry] Failed to get facilitator ${name}:`, err);\n }\n }\n \n if (facilitators.length === 0) {\n throw new Error(`No facilitators available for network: ${network}`);\n }\n \n // Apply strategy\n switch (this.selection.strategy) {\n case 'random':\n return this.shuffle(facilitators);\n \n case 'roundrobin':\n this.roundRobinIndex = (this.roundRobinIndex + 1) % facilitators.length;\n return [\n ...facilitators.slice(this.roundRobinIndex),\n ...facilitators.slice(0, this.roundRobinIndex),\n ];\n \n case 'cheapest':\n return this.sortByCheapest(facilitators);\n \n case 'fastest':\n return this.sortByFastest(facilitators);\n \n case 'failover':\n default:\n return facilitators;\n }\n }\n \n private shuffle<T>(array: T[]): T[] {\n const result = [...array];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [result[i], result[j]] = [result[j], result[i]];\n }\n return result;\n }\n \n private async sortByCheapest(facilitators: Facilitator[]): Promise<Facilitator[]> {\n const withFees = await Promise.all(\n facilitators.map(async (f) => {\n try {\n const fee = await f.getFee?.();\n return { facilitator: f, perTx: fee?.perTx ?? Infinity };\n } catch {\n return { facilitator: f, perTx: Infinity };\n }\n })\n );\n withFees.sort((a, b) => a.perTx - b.perTx);\n return withFees.map(w => w.facilitator);\n }\n \n private async sortByFastest(facilitators: Facilitator[]): Promise<Facilitator[]> {\n const withLatency = await Promise.all(\n facilitators.map(async (f) => {\n try {\n const health = await f.healthCheck();\n return { facilitator: f, latency: health.latencyMs ?? Infinity };\n } catch {\n return { facilitator: f, latency: Infinity };\n }\n })\n );\n withLatency.sort((a, b) => a.latency - b.latency);\n return withLatency.map(w => w.facilitator);\n }\n \n /**\n * Verify payment using configured facilitators\n */\n async verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult & { facilitator: string }> {\n const network = paymentPayload.accepted?.network || paymentPayload.network || requirements.network;\n const facilitators = await this.getOrderedFacilitators(network);\n \n let lastError: string | undefined;\n \n for (const f of facilitators) {\n try {\n console.log(`[Registry] Trying ${f.name} for verify...`);\n const result = await f.verify(paymentPayload, requirements);\n \n if (result.valid) {\n console.log(`[Registry] ${f.name} verify succeeded`);\n return { ...result, facilitator: f.name };\n }\n \n lastError = result.error;\n console.log(`[Registry] ${f.name} verify failed: ${result.error}`);\n \n // For failover strategy, only try next if it's a network/server error\n if (this.selection.strategy === 'failover' && !this.isTransientError(result.error)) {\n // Permanent error (e.g., invalid signature) - don't try others\n break;\n }\n } catch (err: any) {\n lastError = err.message;\n console.error(`[Registry] ${f.name} error:`, err.message);\n }\n }\n \n return {\n valid: false,\n error: lastError || 'All facilitators failed',\n facilitator: 'none',\n };\n }\n \n /**\n * Settle payment using configured facilitators\n */\n async settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult & { facilitator: string }> {\n const network = paymentPayload.accepted?.network || paymentPayload.network || requirements.network;\n const facilitators = await this.getOrderedFacilitators(network);\n \n let lastError: string | undefined;\n \n for (const f of facilitators) {\n try {\n console.log(`[Registry] Trying ${f.name} for settle...`);\n const result = await f.settle(paymentPayload, requirements);\n \n if (result.success) {\n console.log(`[Registry] ${f.name} settle succeeded: ${result.transaction}`);\n return { ...result, facilitator: f.name };\n }\n \n lastError = result.error;\n console.log(`[Registry] ${f.name} settle failed: ${result.error}`);\n } catch (err: any) {\n lastError = err.message;\n console.error(`[Registry] ${f.name} error:`, err.message);\n }\n }\n \n return {\n success: false,\n error: lastError || 'All facilitators failed',\n facilitator: 'none',\n };\n }\n \n /**\n * Check health of all configured facilitators\n */\n async healthCheckAll(): Promise<Record<string, HealthCheckResult>> {\n const results: Record<string, HealthCheckResult> = {};\n \n for (const name of this.getConfiguredNames()) {\n try {\n const f = this.get(name);\n results[name] = await f.healthCheck();\n } catch (err: any) {\n results[name] = { healthy: false, error: err.message };\n }\n }\n \n return results;\n }\n \n /**\n * Check if an error is transient (network/server issue) vs permanent (bad request)\n */\n private isTransientError(error?: string): boolean {\n if (!error) return true;\n const transientPatterns = [\n /timeout/i,\n /network/i,\n /connection/i,\n /ECONNREFUSED/i,\n /ETIMEDOUT/i,\n /503/,\n /502/,\n /500/,\n ];\n return transientPatterns.some(p => p.test(error));\n }\n \n /**\n * Update selection configuration\n */\n setSelection(selection: FacilitatorSelection): void {\n this.selection = selection;\n // Clear cached instances to pick up new config\n this.instances.clear();\n }\n \n /**\n * Get current selection configuration\n */\n getSelection(): FacilitatorSelection {\n return { ...this.selection };\n }\n}\n\n// Default registry instance\nlet defaultRegistry: FacilitatorRegistry | null = null;\n\n/**\n * Get the default facilitator registry\n */\nexport function getDefaultRegistry(): FacilitatorRegistry {\n if (!defaultRegistry) {\n defaultRegistry = new FacilitatorRegistry();\n }\n return defaultRegistry;\n}\n\n/**\n * Create a new registry with custom selection\n */\nexport function createRegistry(selection?: FacilitatorSelection): FacilitatorRegistry {\n return new FacilitatorRegistry(selection);\n}\n"],"mappings":"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","names":["readFileSync","existsSync","path","X402_VERSION","loadEnvFile","existsSync","readFileSync","settlement"]}
|
package/dist/verify/index.d.mts
CHANGED
package/dist/verify/index.d.ts
CHANGED
package/dist/verify/index.js
CHANGED
|
@@ -105,6 +105,35 @@ var CHAINS = {
|
|
|
105
105
|
explorer: "https://sepolia.basescan.org/address/",
|
|
106
106
|
explorerTx: "https://sepolia.basescan.org/tx/",
|
|
107
107
|
avgBlockTime: 2
|
|
108
|
+
},
|
|
109
|
+
// ============ Tempo Testnet (Moderato) ============
|
|
110
|
+
tempo_moderato: {
|
|
111
|
+
name: "Tempo Moderato",
|
|
112
|
+
chainId: 42431,
|
|
113
|
+
rpc: "https://rpc.moderato.tempo.xyz",
|
|
114
|
+
tokens: {
|
|
115
|
+
// TIP-20 stablecoins on Tempo testnet (from mppx SDK)
|
|
116
|
+
// Note: Tempo uses USD as native gas token, not ETH
|
|
117
|
+
USDC: {
|
|
118
|
+
address: "0x20c0000000000000000000000000000000000000",
|
|
119
|
+
// pathUSD - primary testnet stablecoin
|
|
120
|
+
decimals: 6,
|
|
121
|
+
symbol: "USDC",
|
|
122
|
+
eip712Name: "pathUSD"
|
|
123
|
+
},
|
|
124
|
+
USDT: {
|
|
125
|
+
address: "0x20c0000000000000000000000000000000000001",
|
|
126
|
+
// alphaUSD
|
|
127
|
+
decimals: 6,
|
|
128
|
+
symbol: "USDT",
|
|
129
|
+
eip712Name: "alphaUSD"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
usdc: "0x20c0000000000000000000000000000000000000",
|
|
133
|
+
explorer: "https://explore.testnet.tempo.xyz/address/",
|
|
134
|
+
explorerTx: "https://explore.testnet.tempo.xyz/tx/",
|
|
135
|
+
avgBlockTime: 0.5
|
|
136
|
+
// ~500ms finality
|
|
108
137
|
}
|
|
109
138
|
};
|
|
110
139
|
function getChain(name) {
|