moltspay 1.5.0 → 2.0.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.
Files changed (55) hide show
  1. package/README.md +143 -0
  2. package/dist/cdp/index.js.map +1 -1
  3. package/dist/cdp/index.mjs.map +1 -1
  4. package/dist/{cdp-DeohBe1o.d.ts → cdp-B5PhDUTC.d.ts} +1 -1
  5. package/dist/{cdp-p_eHuQpb.d.mts → cdp-D-5Hg3y_.d.mts} +1 -1
  6. package/dist/chains/index.d.mts +37 -1
  7. package/dist/chains/index.d.ts +37 -1
  8. package/dist/chains/index.js +22 -0
  9. package/dist/chains/index.js.map +1 -1
  10. package/dist/chains/index.mjs +19 -0
  11. package/dist/chains/index.mjs.map +1 -1
  12. package/dist/cli/index.js +1941 -204
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/cli/index.mjs +1938 -201
  15. package/dist/cli/index.mjs.map +1 -1
  16. package/dist/client/index.d.mts +46 -0
  17. package/dist/client/index.d.ts +46 -0
  18. package/dist/client/index.js +1059 -118
  19. package/dist/client/index.js.map +1 -1
  20. package/dist/client/index.mjs +1055 -116
  21. package/dist/client/index.mjs.map +1 -1
  22. package/dist/client/web/index.d.mts +434 -0
  23. package/dist/client/web/index.mjs +1300 -0
  24. package/dist/client/web/index.mjs.map +1 -0
  25. package/dist/facilitators/index.d.mts +185 -6
  26. package/dist/facilitators/index.d.ts +185 -6
  27. package/dist/facilitators/index.js +497 -13
  28. package/dist/facilitators/index.js.map +1 -1
  29. package/dist/facilitators/index.mjs +492 -13
  30. package/dist/facilitators/index.mjs.map +1 -1
  31. package/dist/index.d.mts +77 -2
  32. package/dist/index.d.ts +77 -2
  33. package/dist/index.js +1865 -172
  34. package/dist/index.js.map +1 -1
  35. package/dist/index.mjs +1854 -167
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/mcp/index.js +1062 -123
  38. package/dist/mcp/index.js.map +1 -1
  39. package/dist/mcp/index.mjs +1059 -120
  40. package/dist/mcp/index.mjs.map +1 -1
  41. package/dist/{registry-OsEO2dOu.d.mts → registry-DIo0WNoO.d.mts} +8 -1
  42. package/dist/{registry-OsEO2dOu.d.ts → registry-DIo0WNoO.d.ts} +8 -1
  43. package/dist/server/index.d.mts +137 -2
  44. package/dist/server/index.d.ts +137 -2
  45. package/dist/server/index.js +757 -30
  46. package/dist/server/index.js.map +1 -1
  47. package/dist/server/index.mjs +757 -30
  48. package/dist/server/index.mjs.map +1 -1
  49. package/dist/verify/index.js.map +1 -1
  50. package/dist/verify/index.mjs.map +1 -1
  51. package/dist/wallet/index.js.map +1 -1
  52. package/dist/wallet/index.mjs.map +1 -1
  53. package/package.json +15 -2
  54. package/schemas/moltspay.services.schema.json +100 -6
  55. package/scripts/postinstall.js +91 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../node_modules/tsup/assets/cjs_shims.js","../../src/cli/index.ts","../../src/client/index.ts","../../src/chains/index.ts","../../src/wallet/solana.ts","../../src/chains/solana.ts","../../src/facilitators/solana.ts","../../src/facilitators/interface.ts","../../src/client/types.ts","../../src/server/index.ts","../../src/facilitators/index.ts","../../src/facilitators/cdp.ts","../../src/facilitators/tempo.ts","../../src/facilitators/bnb.ts","../../src/facilitators/registry.ts","../../src/server/types.ts","../../src/onramp/index.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","#!/usr/bin/env node\n\n/**\n * MoltsPay CLI\n * \n * Commands:\n * npx moltspay init - Create wallet, set limits\n * npx moltspay config - Update settings\n * npx moltspay fund <amount> - Fund wallet via Coinbase (US only)\n * npx moltspay status - Show wallet and balance\n * npx moltspay services <url> - List services from provider\n * npx moltspay start <manifest> - Start server from services.json\n */\n\n// Polyfill crypto for Node.js 18\nimport { webcrypto } from 'crypto';\nif (!globalThis.crypto) {\n (globalThis as any).crypto = webcrypto;\n}\n\nimport { Command } from 'commander';\nimport { homedir } from 'os';\nimport { join, dirname, resolve } from 'path';\nimport { existsSync, writeFileSync, readFileSync, unlinkSync, mkdirSync } from 'fs';\nimport { spawn } from 'child_process';\nimport { ethers } from 'ethers';\nimport { MoltsPayClient } from '../client/index.js';\nimport { MoltsPayServer } from '../server/index.js';\nimport { printQRCode } from '../onramp/index.js';\nimport { CHAINS } from '../chains/index.js';\nimport { SOLANA_CHAINS, getSolanaExplorerUrl, getSolanaTxExplorerUrl, isSolanaChain } from '../chains/solana.js';\nimport { \n loadSolanaWallet, \n createSolanaWallet, \n getSolanaAddress, \n getSolanaBalances,\n solanaWalletExists,\n isValidSolanaAddress,\n} from '../wallet/solana.js';\nimport type { ChainName } from '../types/index.js';\nimport * as readline from 'readline';\n\n// Read version from package.json at runtime\nfunction getVersion(): string {\n // Try to find package.json in common locations\n const locations = [\n join(__dirname, '../../package.json'),\n join(__dirname, '../package.json'),\n join(process.cwd(), 'node_modules/moltspay/package.json'),\n ];\n for (const loc of locations) {\n try {\n if (existsSync(loc)) {\n const pkg = JSON.parse(readFileSync(loc, 'utf-8'));\n if (pkg.name === 'moltspay') return pkg.version;\n }\n } catch { /* ignore */ }\n }\n return '0.0.0'; // fallback\n}\n\n// Server wallet for BNB gas sponsorship (loaded from env)\nconst BNB_SPONSOR_KEY = process.env.MOLTSPAY_BNB_SPONSOR_KEY;\n// Server wallet address that will call transferFrom (for pay-for-success)\nconst BNB_SPENDER_ADDRESS = process.env.MOLTSPAY_BNB_SPENDER || '0xEBB45208D806A0c73F9673E0c5713FF720DD6b79';\n\nconst ERC20_APPROVE_ABI = [\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n];\n\n/**\n * Set up BNB chain approvals for pay-for-success flow\n * This allows the server to call transferFrom after service succeeds\n */\nasync function setupBNBApprovals(\n client: MoltsPayClient, \n chain: 'bnb' | 'bnb_testnet',\n spenderAddress: string,\n sponsorGas: boolean = false\n): Promise<void> {\n const chainConfig = CHAINS[chain];\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n \n // Get wallet from client\n const wallet = client.getWallet();\n if (!wallet) {\n console.log(' ❌ No wallet found');\n return;\n }\n const signer = wallet.connect(provider);\n \n console.log(` Spender: ${spenderAddress}`);\n \n // Check BNB balance for gas\n let bnbBalance = await provider.getBalance(wallet.address);\n const minGasRequired = ethers.parseEther('0.0005'); // ~0.0002 per approval × 2 + buffer\n \n if (bnbBalance < minGasRequired) {\n if (sponsorGas && BNB_SPONSOR_KEY) {\n console.log(' ⏳ Sponsoring BNB gas for approvals...');\n try {\n const sponsorWallet = new ethers.Wallet(BNB_SPONSOR_KEY, provider);\n const tx = await sponsorWallet.sendTransaction({\n to: wallet.address,\n value: ethers.parseEther('0.001'),\n });\n await tx.wait();\n console.log(` ✅ Sponsored 0.001 BNB (tx: ${tx.hash.slice(0, 10)}...)`);\n bnbBalance = await provider.getBalance(wallet.address);\n } catch (err: any) {\n console.log(` ⚠️ Gas sponsorship failed: ${err.message}`);\n console.log(` 💡 Get testnet BNB: https://testnet.bnbchain.org/faucet-smart`);\n return;\n }\n } else {\n console.log(` ⚠️ Need BNB for gas (~0.0005 BNB)`);\n console.log(` 💡 Run: npx moltspay faucet --chain bnb_testnet`);\n console.log(` Then run: npx moltspay approve --chain ${chain} --spender ${spenderAddress}`);\n return;\n }\n }\n \n // Approve USDT and USDC for the spender address\n for (const tokenSymbol of ['USDT', 'USDC'] as const) {\n const tokenConfig = chainConfig.tokens[tokenSymbol];\n const tokenContract = new ethers.Contract(tokenConfig.address, ERC20_APPROVE_ABI, signer);\n \n // Check existing allowance\n const allowance = await tokenContract.allowance(wallet.address, spenderAddress);\n if (allowance > 0n) {\n console.log(` ✅ ${tokenSymbol}: already approved for ${spenderAddress.slice(0, 10)}...`);\n continue;\n }\n \n console.log(` ⏳ Approving ${tokenSymbol}...`);\n try {\n const tx = await tokenContract.approve(spenderAddress, ethers.MaxUint256);\n await tx.wait();\n console.log(` ✅ ${tokenSymbol}: approved (tx: ${tx.hash.slice(0, 10)}...)`);\n } catch (err: any) {\n console.log(` ❌ ${tokenSymbol}: approval failed - ${err.message}`);\n }\n }\n \n console.log('');\n}\n\n/**\n * Check BNB approval status\n */\nasync function checkBNBApprovals(\n address: string,\n chain: 'bnb' | 'bnb_testnet',\n configDir: string = DEFAULT_CONFIG_DIR\n): Promise<{ usdt: boolean; usdc: boolean; spender: string | null }> {\n const chainConfig = CHAINS[chain];\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n \n // Read spender from wallet config (saved during approve command)\n let spenderAddress: string | null = null;\n try {\n const walletPath = join(configDir, 'wallet.json');\n const walletData = JSON.parse(readFileSync(walletPath, 'utf-8'));\n spenderAddress = walletData.approvals?.[chain] || null;\n } catch {\n // No saved spender\n }\n \n const result = { usdt: false, usdc: false, spender: spenderAddress };\n \n if (!spenderAddress) {\n return result; // No spender saved, can't check approvals\n }\n \n for (const tokenSymbol of ['USDT', 'USDC'] as const) {\n const tokenConfig = chainConfig.tokens[tokenSymbol];\n const tokenContract = new ethers.Contract(tokenConfig.address, ERC20_APPROVE_ABI, provider);\n const allowance = await tokenContract.allowance(address, spenderAddress);\n result[tokenSymbol.toLowerCase() as 'usdt' | 'usdc'] = allowance > 0n;\n }\n \n return result;\n}\n\nconst program = new Command();\nconst DEFAULT_CONFIG_DIR = join(homedir(), '.moltspay');\nconst PID_FILE = join(DEFAULT_CONFIG_DIR, 'server.pid');\n\n// Ensure config dir exists\nif (!existsSync(DEFAULT_CONFIG_DIR)) {\n mkdirSync(DEFAULT_CONFIG_DIR, { recursive: true });\n}\n\nfunction prompt(question: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise(resolve => {\n rl.question(question, answer => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nprogram\n .name('moltspay')\n .description('MoltsPay - Payment infrastructure for AI Agents')\n .version(getVersion());\n\n/**\n * npx moltspay init\n */\nprogram\n .command('init')\n .description('Initialize MoltsPay client (create wallet, set limits)')\n .option('--chain <chain>', 'Blockchain to use', 'base')\n .option('--max-per-tx <amount>', 'Max amount per transaction')\n .option('--max-per-day <amount>', 'Max amount per day')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n // Get chain option\n let chain = options.chain;\n \n // Validate chain\n const supportedEVMChains = ['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'bnb', 'bnb_testnet'];\n const supportedSolanaChains = ['solana', 'solana_devnet'];\n const supportedChains = [...supportedEVMChains, ...supportedSolanaChains];\n \n if (!supportedChains.includes(chain)) {\n console.error(`❌ Unknown chain: ${chain}. Supported: ${supportedChains.join(', ')}`);\n process.exit(1);\n }\n \n // Handle Solana chains separately (different wallet)\n if (supportedSolanaChains.includes(chain)) {\n console.log('\\n🟣 Solana Wallet Setup\\n');\n \n if (solanaWalletExists(options.configDir)) {\n const existingAddress = getSolanaAddress(options.configDir);\n console.log(`⚠️ Solana wallet already exists: ${existingAddress}`);\n console.log(` Config dir: ${options.configDir}`);\n return;\n }\n \n console.log('Creating Solana wallet...');\n const keypair = createSolanaWallet(options.configDir);\n const address = keypair.publicKey.toBase58();\n \n console.log(`\\n✅ Solana wallet created: ${address}`);\n console.log(`\\n📁 Config saved to: ${join(options.configDir, 'wallet-solana.json')}`);\n console.log(`\\n⚠️ IMPORTANT: Back up your wallet file!`);\n console.log(` This file contains your private key!\\n`);\n \n if (chain === 'solana_devnet') {\n console.log('💡 Get testnet tokens:');\n console.log(' npx moltspay faucet --chain solana_devnet\\n');\n } else {\n console.log(`💰 Fund your wallet with USDC on Solana to start (gasless - no SOL needed).\\n`);\n }\n \n return;\n }\n\n // For EVM chains, check if already initialized\n console.log('\\n🔐 MoltsPay Client Setup\\n');\n \n if (existsSync(join(options.configDir, 'wallet.json'))) {\n console.log('⚠️ EVM wallet already initialized. Use \"moltspay config\" to update settings.');\n console.log(` Config dir: ${options.configDir}`);\n return;\n }\n \n let maxPerTx = options.maxPerTx ? parseFloat(options.maxPerTx) : null;\n let maxPerDay = options.maxPerDay ? parseFloat(options.maxPerDay) : null;\n\n if (!maxPerTx) {\n const answer = await prompt('Max per transaction (USD) [100]: ');\n maxPerTx = answer ? parseFloat(answer) : 100;\n }\n\n if (!maxPerDay) {\n const answer = await prompt('Max per day (USD) [1000]: ');\n maxPerDay = answer ? parseFloat(answer) : 1000;\n }\n\n console.log('\\nCreating wallet...');\n\n const result = MoltsPayClient.init(options.configDir, {\n chain,\n maxPerTx,\n maxPerDay,\n });\n\n console.log(`\\n✅ Wallet created: ${result.address}`);\n console.log(`\\n📁 Config saved to: ${result.configDir}`);\n console.log(`\\n⚠️ IMPORTANT: Back up ${join(result.configDir, 'wallet.json')}`);\n console.log(` This file contains your private key!\\n`);\n\n // For BNB chains, set up approvals (requires gas sponsorship for new wallets)\n if (chain === 'bnb' || chain === 'bnb_testnet') {\n console.log('📋 Setting up BNB chain approvals...\\n');\n console.log(' ℹ️ Using default spender. For other services, run:');\n console.log(` npx moltspay approve --chain ${chain} --spender <address>\\n`);\n const client = new MoltsPayClient({ configDir: options.configDir });\n await setupBNBApprovals(client, chain, BNB_SPENDER_ADDRESS, true); // true = sponsor gas\n }\n\n console.log(`💰 Fund your wallet with USDC on ${chain} to start using services.\\n`);\n });\n\n/**\n * npx moltspay config\n */\nprogram\n .command('config')\n .description('Update MoltsPay settings')\n .option('--max-per-tx <amount>', 'Max amount per transaction')\n .option('--max-per-day <amount>', 'Max amount per day')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n\n if (!client.isInitialized) {\n console.log('❌ Not initialized. Run: npx moltspay init');\n return;\n }\n\n const currentConfig = client.getConfig();\n\n // If no options provided, show interactive mode\n if (!options.maxPerTx && !options.maxPerDay) {\n console.log('\\n📋 Current Settings:\\n');\n console.log(` Wallet: ${client.address}`);\n console.log(` Chain: ${currentConfig.chain}`);\n console.log(` Max per tx: $${currentConfig.limits.maxPerTx}`);\n console.log(` Max per day: $${currentConfig.limits.maxPerDay}`);\n console.log('');\n\n const maxPerTxAnswer = await prompt(`New max per tx (USD) [${currentConfig.limits.maxPerTx}]: `);\n const maxPerDayAnswer = await prompt(`New max per day (USD) [${currentConfig.limits.maxPerDay}]: `);\n\n if (maxPerTxAnswer) {\n client.updateConfig({ maxPerTx: parseFloat(maxPerTxAnswer) });\n console.log(`✅ Updated max per tx to $${maxPerTxAnswer}`);\n }\n\n if (maxPerDayAnswer) {\n client.updateConfig({ maxPerDay: parseFloat(maxPerDayAnswer) });\n console.log(`✅ Updated max per day to $${maxPerDayAnswer}`);\n }\n } else {\n // Non-interactive mode\n if (options.maxPerTx) {\n client.updateConfig({ maxPerTx: parseFloat(options.maxPerTx) });\n console.log(`✅ Updated max per tx to $${options.maxPerTx}`);\n }\n if (options.maxPerDay) {\n client.updateConfig({ maxPerDay: parseFloat(options.maxPerDay) });\n console.log(`✅ Updated max per day to $${options.maxPerDay}`);\n }\n }\n });\n\n/**\n * npx moltspay fund <amount>\n * \n * Fund wallet with USDC via Coinbase Pay\n * US residents only, debit card or Apple Pay\n */\nprogram\n .command('fund <amount>')\n .description('Fund wallet with USDC via Coinbase (US debit card / Apple Pay)')\n .option('--chain <chain>', 'Chain to fund (base, polygon, solana, base_sepolia, bnb, or bnb_testnet)', 'base')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (amountStr, options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n\n const amount = parseFloat(amountStr);\n if (isNaN(amount) || amount < 5) {\n console.log('❌ Minimum $5.');\n return;\n }\n\n const chain = (options.chain?.toLowerCase() || 'base') as 'base' | 'polygon' | 'base_sepolia' | 'solana' | 'bnb' | 'bnb_testnet';\n if (!['base', 'polygon', 'base_sepolia', 'solana', 'bnb', 'bnb_testnet'].includes(chain)) {\n console.log('❌ Invalid chain. Use: base, polygon, solana, base_sepolia, bnb, or bnb_testnet');\n return;\n }\n \n // Determine wallet address based on chain\n let walletAddress: string;\n if (chain === 'solana') {\n // Load Solana wallet\n const solanaWallet = loadSolanaWallet(options.configDir || DEFAULT_CONFIG_DIR);\n if (!solanaWallet) {\n console.log('❌ No Solana wallet found. Run: npx moltspay init --chain solana');\n return;\n }\n walletAddress = getSolanaAddress(options.configDir || DEFAULT_CONFIG_DIR) || '';\n if (!walletAddress) {\n console.log('❌ Could not get Solana wallet address.');\n return;\n }\n } else {\n // EVM chains use the client wallet\n if (!client.isInitialized) {\n console.log('❌ Not initialized. Run: npx moltspay init');\n return;\n }\n walletAddress = client.address!;\n }\n \n // Testnet: use faucet instead of Coinbase Pay\n if (chain === 'base_sepolia') {\n console.log('\\n🧪 Testnet Funding\\n');\n console.log(` Wallet: ${walletAddress}`);\n console.log(` Chain: Base Sepolia (testnet)\\n`);\n console.log('💡 Use the MoltsPay faucet to get free testnet USDC:\\n');\n console.log(' npx moltspay faucet\\n');\n console.log(' Or get from Circle Faucet: https://faucet.circle.com/\\n');\n return;\n }\n \n // BNB Testnet: use faucet (gives USDC + tBNB for gas)\n if (chain === 'bnb_testnet') {\n console.log('\\n🧪 BNB Testnet Funding\\n');\n console.log(` Wallet: ${walletAddress}`);\n console.log(` Chain: BNB Testnet\\n`);\n console.log('💡 Use the MoltsPay faucet to get testnet USDC + tBNB:\\n');\n console.log(' npx moltspay faucet --chain bnb_testnet\\n');\n console.log(' This gives you:\\n');\n console.log(' • 1 USDC (testnet) for payments');\n console.log(' • 0.001 tBNB for gas (first approval tx)\\n');\n return;\n }\n \n // BNB Mainnet: manual funding required (no Coinbase onramp)\n if (chain === 'bnb') {\n console.log('\\n📋 BNB Chain Funding\\n');\n console.log(` Wallet: ${walletAddress}\\n`);\n console.log(' To use MoltsPay on BNB Chain, you need:\\n');\n console.log(' 1. USDC for payments');\n console.log(' → Withdraw from Binance/exchange to your wallet address\\n');\n console.log(' 2. Small amount of BNB for gas (~0.001 BNB / ~$0.60)');\n console.log(' → First approval transaction requires gas');\n console.log(' → After approval, all payments are gasless\\n');\n console.log(' 💡 Tip: Most exchanges include BNB dust when you withdraw to BNB Chain\\n');\n console.log(' ─────────────────────────────────────────────────────────────');\n console.log(' After funding, check status: npx moltspay status\\n');\n return;\n }\n\n console.log('\\n💳 Fund your agent wallet\\n');\n console.log(` Wallet: ${walletAddress}`);\n console.log(` Chain: ${chain === 'solana' ? 'Solana' : chain}`);\n console.log(` Amount: $${amount.toFixed(2)}\\n`);\n\n try {\n // Call server API to generate onramp URL (no local CDP keys needed)\n const ONRAMP_API = process.env.MOLTSPAY_ONRAMP_API || 'https://moltspay.com/api/v1/onramp';\n \n const response = await fetch(`${ONRAMP_API}/create`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n address: walletAddress,\n amount,\n chain,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Server error' })) as { error?: string };\n throw new Error(errorData.error || `Server returned ${response.status}`);\n }\n\n const result = await response.json() as { url: string };\n const { url } = result;\n\n console.log(' Scan to pay (US debit card / Apple Pay):\\n');\n await printQRCode(url);\n console.log('\\n ⏱️ QR code expires in 5 minutes\\n');\n } catch (error) {\n console.log(`❌ ${(error as Error).message}`);\n }\n });\n\n/**\n * npx moltspay approve\n * \n * Approve a spender address for BNB chain payments (required before paying)\n */\nprogram\n .command('approve')\n .description('Approve a spender address for BNB chain payments')\n .requiredOption('--spender <address>', 'Spender address to approve (from server 402 response)')\n .option('--chain <chain>', 'BNB chain (bnb or bnb_testnet)', 'bnb_testnet')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n const chain = options.chain as 'bnb' | 'bnb_testnet';\n \n if (chain !== 'bnb' && chain !== 'bnb_testnet') {\n console.log('❌ approve command is only for BNB chains (bnb or bnb_testnet)');\n return;\n }\n \n if (!options.spender.match(/^0x[a-fA-F0-9]{40}$/)) {\n console.log('❌ Invalid spender address format');\n return;\n }\n \n const client = new MoltsPayClient({ configDir: options.configDir });\n if (!client.isInitialized) {\n console.log('❌ Wallet not initialized. Run: npx moltspay init --chain ' + chain);\n return;\n }\n \n console.log(`\\n🔐 Approving spender for ${chain}...\\n`);\n await setupBNBApprovals(client, chain, options.spender, false);\n \n // Save approved spender to wallet config for status command\n const walletPath = join(options.configDir || DEFAULT_CONFIG_DIR, 'wallet.json');\n try {\n const walletData = JSON.parse(readFileSync(walletPath, 'utf-8'));\n walletData.approvals = walletData.approvals || {};\n walletData.approvals[chain] = options.spender;\n writeFileSync(walletPath, JSON.stringify(walletData, null, 2));\n console.log(`✅ Approval complete! Spender saved for ${chain}.\\n`);\n } catch (err) {\n console.log('✅ Approval complete!\\n');\n console.log('⚠️ Could not save spender to wallet config');\n }\n });\n\n/**\n * npx moltspay faucet\n * \n * Request testnet tokens from faucets (Base Sepolia or Tempo Moderato)\n */\nprogram\n .command('faucet')\n .description('Request testnet tokens from faucet (Base Sepolia, Tempo Moderato, BNB Testnet, or Solana Devnet)')\n .option('--chain <chain>', 'Chain to get tokens on (base_sepolia, tempo_moderato, bnb_testnet, or solana_devnet)', 'base_sepolia')\n .option('--address <address>', 'Wallet address (defaults to your wallet)')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n let address = options.address;\n const chain = options.chain?.toLowerCase() || 'base_sepolia';\n\n // Validate chain\n if (!['base_sepolia', 'tempo_moderato', 'bnb_testnet', 'solana_devnet'].includes(chain)) {\n console.log('❌ Invalid chain. Use: base_sepolia, tempo_moderato, bnb_testnet, or solana_devnet');\n return;\n }\n\n // Handle Solana devnet separately\n if (chain === 'solana_devnet') {\n // Get Solana address\n if (!address) {\n address = getSolanaAddress(options.configDir);\n if (!address) {\n console.log('❌ No Solana wallet found. Run: npx moltspay init --chain solana_devnet');\n return;\n }\n }\n\n // Validate Solana address format\n if (!isValidSolanaAddress(address)) {\n console.log('❌ Invalid Solana address');\n return;\n }\n\n console.log('\\n🚰 Solana Devnet Faucet (Gasless Mode)\\n');\n console.log(` Address: ${address}\\n`);\n\n let usdcSuccess = false;\n\n // Request USDC from MoltsPay faucet API (no SOL needed - server pays fees)\n try {\n console.log(' ⏳ Requesting 1 USDC from faucet...');\n const FAUCET_API = process.env.MOLTSPAY_FAUCET_API || 'https://moltspay.com/api/v1/faucet';\n \n const response = await fetch(FAUCET_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ address, chain: 'solana_devnet' }),\n });\n\n const result = await response.json() as {\n success?: boolean;\n amount?: string;\n transaction?: string;\n explorer?: string;\n faucet_balance?: string;\n error?: string;\n hint?: string;\n retry_after?: string;\n };\n\n if (!response.ok) {\n console.log(` ⚠️ USDC faucet: ${result.error || 'Request failed'}`);\n if (result.hint) console.log(` ${result.hint}`);\n if (result.retry_after) console.log(` Retry after: ${result.retry_after}`);\n } else {\n console.log(` ✅ Received ${result.amount} USDC!`);\n console.log(` Transaction: ${result.explorer}`);\n if (result.faucet_balance) {\n console.log(` Faucet balance: ${result.faucet_balance} USDC remaining`);\n }\n usdcSuccess = true;\n }\n } catch (error: any) {\n console.log(` ⚠️ USDC faucet error: ${error.message}`);\n }\n\n console.log('');\n if (usdcSuccess) {\n console.log('💡 Check your balance:');\n console.log(' npx moltspay status\\n');\n } else {\n console.log('❌ Faucet request failed. Try again in a few minutes.\\n');\n }\n return;\n }\n\n // If no address provided, try to use initialized EVM wallet\n if (!address) {\n const client = new MoltsPayClient({ configDir: options.configDir });\n if (client.isInitialized) {\n address = client.address;\n } else {\n console.log('❌ No wallet found. Either run \"npx moltspay init\" or provide --address');\n return;\n }\n }\n\n // Validate EVM address format\n if (!address.match(/^0x[a-fA-F0-9]{40}$/)) {\n console.log('❌ Invalid Ethereum address');\n return;\n }\n\n console.log('\\n🚰 MoltsPay Testnet Faucet\\n');\n\n if (chain === 'tempo_moderato') {\n // Tempo Moderato faucet\n console.log(` Requesting testnet tokens on Tempo Moderato...`);\n console.log(` Address: ${address}\\n`);\n\n try {\n // Tempo docs faucet API - sends all 4 testnet tokens (pathUSD, AlphaUSD, BetaUSD, ThetaUSD)\n const TEMPO_FAUCET_API = 'https://docs.tempo.xyz/api/faucet';\n \n const response = await fetch(TEMPO_FAUCET_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ address }),\n });\n\n const result = await response.json() as { data?: { hash: string }[]; error?: string };\n\n if (response.ok && result.data && result.data.length > 0) {\n console.log(`✅ Received testnet tokens!\\n`);\n console.log(` Tokens: pathUSD, AlphaUSD, BetaUSD, ThetaUSD (1M each)`);\n console.log(` Transactions:`);\n for (const tx of result.data) {\n console.log(` https://explore.testnet.tempo.xyz/tx/${tx.hash}`);\n }\n console.log('\\n💡 Use these tokens to test MPP payments:');\n console.log(` npx moltspay pay <service-url> <service-id> --chain tempo_moderato\\n`);\n } else {\n console.log(`❌ ${result.error || 'Faucet request failed'}`);\n console.log('\\n Try again later or use Tempo Wallet: https://wallet.tempo.xyz\\n');\n }\n } catch (error) {\n console.log(`❌ ${(error as Error).message}`);\n console.log('\\n Try Tempo Wallet instead: https://wallet.tempo.xyz\\n');\n }\n } else if (chain === 'bnb_testnet') {\n // BNB Testnet faucet - uses unified MoltsPay faucet API\n console.log(` Requesting 1 USDC on BNB Testnet...`);\n console.log(` Address: ${address}\\n`);\n\n try {\n const FAUCET_API = process.env.MOLTSPAY_FAUCET_API || 'https://moltspay.com/api/v1/faucet';\n \n const response = await fetch(FAUCET_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ address, chain: 'bnb_testnet' }),\n });\n\n const result = await response.json() as {\n success?: boolean;\n amount?: string;\n token?: string;\n chain_name?: string;\n transaction?: string;\n explorer?: string;\n faucet_balance?: string;\n error?: string;\n hint?: string;\n retry_after?: string;\n };\n\n if (!response.ok) {\n console.log(`❌ ${result.error || 'Request failed'}`);\n if (result.hint) console.log(` ${result.hint}`);\n if (result.retry_after) console.log(` Retry after: ${result.retry_after}`);\n \n // Show manual faucet instructions as fallback\n console.log('\\n💡 Alternatively, get tokens manually:');\n console.log(` 1. Get test BNB: https://www.bnbchain.org/en/testnet-faucet`);\n console.log(` 2. Select \"Peggy Tokens\" -> USDC`);\n console.log(` 3. Enter: ${address}\\n`);\n return;\n }\n\n console.log(`✅ Received ${result.amount} ${result.token || 'USDC'} on ${result.chain_name || 'BNB Testnet'}!\\n`);\n console.log(` Transaction: ${result.explorer || `https://testnet.bscscan.com/tx/${result.transaction}`}`);\n if (result.faucet_balance) {\n console.log(` Faucet balance: ${result.faucet_balance} USDC`);\n }\n console.log('\\n💡 Now you can test BNB payments:');\n console.log(` npx moltspay pay <service-url> <service-id> --chain bnb_testnet\\n`);\n } catch (error) {\n console.log(`❌ ${(error as Error).message}`);\n console.log('\\n💡 Get tokens manually:');\n console.log(` 1. Get test BNB: https://www.bnbchain.org/en/testnet-faucet`);\n console.log(` 2. Select \"Peggy Tokens\" -> USDC`);\n console.log(` 3. Enter: ${address}\\n`);\n }\n } else {\n // Base Sepolia faucet (existing)\n console.log(` Requesting 1 USDC on Base Sepolia...`);\n console.log(` Address: ${address}\\n`);\n\n try {\n const FAUCET_API = process.env.MOLTSPAY_FAUCET_API || 'https://moltspay.com/api/v1/faucet';\n \n const response = await fetch(FAUCET_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ address, chain: 'base_sepolia' }),\n });\n\n const result = await response.json() as {\n success?: boolean;\n amount?: string;\n transaction?: string;\n explorer?: string;\n faucet_balance?: string;\n error?: string;\n hint?: string;\n retry_after?: string;\n };\n\n if (!response.ok) {\n console.log(`❌ ${result.error || 'Request failed'}`);\n if (result.hint) console.log(` ${result.hint}`);\n if (result.retry_after) console.log(` Retry after: ${result.retry_after}`);\n return;\n }\n\n console.log(`✅ Received ${result.amount} USDC!\\n`);\n console.log(` Transaction: ${result.transaction}`);\n console.log(` Explorer: ${result.explorer}`);\n console.log(` Faucet balance: ${result.faucet_balance} USDC remaining\\n`);\n console.log('💡 Use this USDC to test x402 payments:');\n console.log(` npx moltspay pay <service-url> <service-id> --chain base_sepolia\\n`);\n } catch (error) {\n console.log(`❌ ${(error as Error).message}`);\n }\n }\n });\n\n/**\n * npx moltspay status\n */\nprogram\n .command('status')\n .description('Show wallet status and balance')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n\n if (!client.isInitialized) {\n if (options.json) {\n console.log(JSON.stringify({ error: 'Not initialized' }));\n } else {\n console.log('❌ Not initialized. Run: npx moltspay init');\n }\n return;\n }\n\n const config = client.getConfig();\n \n // Get balances on all supported chains\n let allBalances: Record<string, { usdc: number; usdt: number; native: number }> = {};\n try {\n allBalances = await client.getAllBalances();\n } catch (err: any) {\n console.error('Warning: Could not fetch balances:', err.message);\n }\n\n // Check for Solana wallet\n const solanaAddress = getSolanaAddress(options.configDir);\n let solanaBalances: { devnet?: { sol: number; usdc: number }; mainnet?: { sol: number; usdc: number } } = {};\n \n if (solanaAddress) {\n try {\n solanaBalances.devnet = await getSolanaBalances(solanaAddress, 'solana_devnet');\n } catch { /* ignore */ }\n try {\n solanaBalances.mainnet = await getSolanaBalances(solanaAddress, 'solana');\n } catch { /* ignore */ }\n }\n\n if (options.json) {\n const output: any = {\n address: client.address,\n balances: allBalances,\n limits: config.limits,\n };\n if (solanaAddress) {\n output.solana = {\n address: solanaAddress,\n balances: solanaBalances,\n };\n }\n console.log(JSON.stringify(output, null, 2));\n } else {\n console.log('\\n📊 MoltsPay Wallet Status\\n');\n console.log(` Address: ${client.address}`);\n console.log('');\n console.log(' Balances:');\n for (const [chainName, balance] of Object.entries(allBalances)) {\n // Format chain label nicely\n let chainLabel: string;\n if (chainName === 'base_sepolia') {\n chainLabel = 'Base Sepolia';\n } else if (chainName === 'tempo_moderato') {\n chainLabel = 'Tempo Moderato';\n } else {\n chainLabel = chainName.charAt(0).toUpperCase() + chainName.slice(1);\n }\n \n // Tempo: show all 4 testnet tokens + native balance\n if (chainName === 'tempo_moderato' && (balance as any).tempo) {\n const tempo = (balance as any).tempo;\n // Format large native balance with scientific notation if needed\n const nativeStr = balance.native > 1e12 \n ? balance.native.toExponential(2) \n : balance.native.toFixed(2);\n console.log(` ${chainLabel}:`);\n console.log(` Native: ${nativeStr} TEMPO (for gas)`);\n console.log(` pathUSD: ${tempo.pathUSD.toFixed(2)}`);\n console.log(` alphaUSD: ${tempo.alphaUSD.toFixed(2)}`);\n console.log(` betaUSD: ${tempo.betaUSD.toFixed(2)}`);\n console.log(` thetaUSD: ${tempo.thetaUSD.toFixed(2)}`);\n } else if (chainName === 'bnb' || chainName === 'bnb_testnet') {\n // BNB chains: show balance + native BNB for gas\n const bnbBalance = balance.native;\n const bnbWarning = bnbBalance < 0.0005 ? ' ⚠️ Low gas' : '';\n console.log(` ${chainLabel.padEnd(14)} ${balance.usdc.toFixed(2)} USDC | ${balance.usdt.toFixed(2)} USDT | ${bnbBalance.toFixed(4)} BNB${bnbWarning}`);\n } else {\n // EVM chains: show USDC/USDT\n console.log(` ${chainLabel.padEnd(14)} ${balance.usdc.toFixed(2)} USDC | ${balance.usdt.toFixed(2)} USDT`);\n }\n }\n \n // Check BNB approval status\n const address = client.address!;\n let bnbApprovalStatus: { usdt: boolean; usdc: boolean; spender: string | null } | null = null;\n let bnbTestnetApprovalStatus: { usdt: boolean; usdc: boolean; spender: string | null } | null = null;\n \n try {\n if (allBalances['bnb']) {\n bnbApprovalStatus = await checkBNBApprovals(address, 'bnb', options.configDir);\n }\n if (allBalances['bnb_testnet']) {\n bnbTestnetApprovalStatus = await checkBNBApprovals(address, 'bnb_testnet', options.configDir);\n }\n } catch { /* ignore approval check errors */ }\n \n if (bnbApprovalStatus || bnbTestnetApprovalStatus) {\n console.log('');\n console.log(' BNB Approvals (pay-for-success):');\n if (bnbApprovalStatus) {\n if (!bnbApprovalStatus.spender) {\n console.log(' BNB: ⚠️ No spender configured');\n console.log(' └─ Run a payment first, or: npx moltspay approve --chain bnb --spender <address>');\n } else {\n const status = bnbApprovalStatus.usdt && bnbApprovalStatus.usdc ? '✅' : '⚠️';\n const tokens = [\n bnbApprovalStatus.usdt ? 'USDT✓' : 'USDT✗',\n bnbApprovalStatus.usdc ? 'USDC✓' : 'USDC✗',\n ].join(', ');\n console.log(` BNB: ${status} ${tokens}`);\n \n // Show warning if no approval and low BNB\n const bnbNative = allBalances['bnb']?.native || 0;\n if (!bnbApprovalStatus.usdc && !bnbApprovalStatus.usdt && bnbNative < 0.0005) {\n console.log(' ⚠️ Need ~0.001 BNB for first approval tx. Get from exchange.');\n }\n }\n }\n if (bnbTestnetApprovalStatus) {\n if (!bnbTestnetApprovalStatus.spender) {\n console.log(' BNB Testnet: ⚠️ No spender configured');\n console.log(' └─ Run a payment first, or: npx moltspay approve --chain bnb_testnet --spender <address>');\n } else {\n const status = bnbTestnetApprovalStatus.usdt && bnbTestnetApprovalStatus.usdc ? '✅' : '⚠️';\n const tokens = [\n bnbTestnetApprovalStatus.usdt ? 'USDT✓' : 'USDT✗',\n bnbTestnetApprovalStatus.usdc ? 'USDC✓' : 'USDC✗',\n ].join(', ');\n console.log(` BNB Testnet: ${status} ${tokens}`);\n \n // Show warning if no approval and low tBNB\n const tbnbNative = allBalances['bnb_testnet']?.native || 0;\n if (!bnbTestnetApprovalStatus.usdc && !bnbTestnetApprovalStatus.usdt && tbnbNative < 0.0005) {\n console.log(' ⚠️ Need tBNB for approval. Run: npx moltspay faucet --chain bnb_testnet');\n }\n }\n }\n }\n \n console.log('');\n console.log(' Spending Limits:');\n console.log(` Per Transaction: $${config.limits.maxPerTx}`);\n console.log(` Daily: $${config.limits.maxPerDay}`);\n \n // Show Solana wallet status if it exists\n const solanaAddress = getSolanaAddress(options.configDir);\n if (solanaAddress) {\n console.log('');\n console.log(' ─────────────────────────────────');\n console.log(` 🟣 Solana: ${solanaAddress}`);\n \n try {\n // Get Solana devnet balances\n const devnetBalances = await getSolanaBalances(solanaAddress, 'solana_devnet');\n console.log(` Devnet: ${devnetBalances.sol.toFixed(4)} SOL | ${devnetBalances.usdc.toFixed(2)} USDC`);\n } catch (err: any) {\n console.log(` Devnet: (unable to fetch)`);\n }\n \n try {\n // Get Solana mainnet balances\n const mainnetBalances = await getSolanaBalances(solanaAddress, 'solana');\n console.log(` Mainnet: ${mainnetBalances.sol.toFixed(4)} SOL | ${mainnetBalances.usdc.toFixed(2)} USDC`);\n } catch (err: any) {\n console.log(` Mainnet: (unable to fetch)`);\n }\n }\n \n console.log('');\n }\n });\n\n/**\n * npx moltspay list\n * \n * List transactions for the agent wallet using Blockscout APIs (free, no API key needed)\n */\nprogram\n .command('list')\n .description('List recent transactions')\n .option('--days <n>', 'Number of days to look back', '7')\n .option('--chain <chain>', 'Chain to query (base, polygon, base_sepolia, or all)', 'all')\n .option('--limit <n>', 'Max transactions to show', '20')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n\n if (!client.isInitialized) {\n console.log('❌ Not initialized. Run: npx moltspay init');\n return;\n }\n\n const days = parseInt(options.days) || 7;\n const limit = parseInt(options.limit) || 20;\n const chain = options.chain?.toLowerCase() || 'all';\n\n if (!['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'all'].includes(chain)) {\n console.log('❌ Invalid chain. Use: base, polygon, base_sepolia, tempo_moderato, or all');\n return;\n }\n\n const wallet = client.address!;\n const cutoffTime = Date.now() - (days * 24 * 60 * 60 * 1000);\n\n // Blockscout API configs (free, no API key needed)\n const explorers: Record<string, { api: string; usdc: string; name: string }> = {\n base: {\n api: 'https://base.blockscout.com/api/v2',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n name: 'Base',\n },\n polygon: {\n api: 'https://polygon.blockscout.com/api/v2',\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n name: 'Polygon',\n },\n base_sepolia: {\n api: 'https://base-sepolia.blockscout.com/api/v2',\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n name: 'Base Sepolia',\n },\n // Tempo explorer doesn't have public API yet\n tempo_moderato: {\n api: '', // No API available\n usdc: '0x20c0000000000000000000000000000000000000',\n name: 'Tempo Moderato',\n },\n };\n\n const chainsToQuery = chain === 'all' ? ['base', 'polygon', 'base_sepolia', 'tempo_moderato'] : [chain];\n\n console.log(`\\n📜 Transactions (last ${days} day${days > 1 ? 's' : ''})\\n`);\n\n interface TokenTx {\n chain: string;\n timestamp: number;\n type: string;\n amount: number;\n other: string;\n hash: string;\n token?: string; // Token name (e.g., pathUSD, alphaUSD for Tempo)\n }\n\n let allTxns: TokenTx[] = [];\n\n for (const c of chainsToQuery) {\n const explorer = explorers[c];\n \n try {\n if (c === 'tempo_moderato') {\n // Tempo: use eth_getLogs RPC instead of Blockscout API\n const tempoTokens = [\n { address: '0x20c0000000000000000000000000000000000000', name: 'pathUSD' },\n { address: '0x20c0000000000000000000000000000000000001', name: 'alphaUSD' },\n { address: '0x20c0000000000000000000000000000000000002', name: 'betaUSD' },\n { address: '0x20c0000000000000000000000000000000000003', name: 'thetaUSD' },\n ];\n \n // Transfer event topic: keccak256(\"Transfer(address,address,uint256)\")\n const transferTopic = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';\n const walletTopic = '0x000000000000000000000000' + wallet.toLowerCase().slice(2);\n \n // Get latest block with retry\n let latestBlock = 0;\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n const blockRes = await fetch('https://rpc.moderato.tempo.xyz', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', method: 'eth_blockNumber', params: [], id: 1 }),\n });\n const blockData = await blockRes.json() as { result: string };\n if (blockData.result) {\n latestBlock = parseInt(blockData.result, 16);\n break;\n }\n } catch (e) {\n if (attempt === 2) throw e;\n await new Promise(r => setTimeout(r, 500)); // Wait 500ms before retry\n }\n }\n \n if (latestBlock === 0) {\n console.log(' ⚠️ Tempo Moderato: Could not get latest block');\n continue;\n }\n \n // Tempo RPC has 100000 block limit, so we can only query ~14 hours back\n // For longer ranges, we'd need multiple queries (not implemented yet)\n const maxBlocks = 100000;\n const blocksPerDay = 172800; // at ~0.5s/block\n const requestedBlocks = blocksPerDay * days;\n const actualBlocks = Math.min(requestedBlocks, maxBlocks);\n const fromBlock = '0x' + Math.max(0, latestBlock - actualBlocks).toString(16);\n const toBlock = '0x' + latestBlock.toString(16); // Use fixed block to avoid range drift\n \n // Note: Tempo RPC has 100k block limit (~14 hours at 0.5s/block)\n if (requestedBlocks > maxBlocks) {\n console.log(` ℹ️ Tempo: querying last ~14 hours (RPC limit: 100k blocks)`);\n }\n \n for (const token of tempoTokens) {\n try {\n // Query incoming transfers (to = wallet)\n const inRes = await fetch('https://rpc.moderato.tempo.xyz', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_getLogs',\n params: [{ fromBlock, toBlock, address: token.address, topics: [transferTopic, null, walletTopic] }],\n id: 1,\n }),\n });\n const inData = await inRes.json() as { result?: Array<{ data: string; topics: string[]; transactionHash: string; blockTimestamp: string }>; error?: { message: string } };\n \n if (inData.error) {\n console.log(` ⚠️ ${token.name}: ${inData.error.message}`);\n continue;\n }\n \n if (inData.result && Array.isArray(inData.result)) {\n for (const log of inData.result) {\n const timestamp = parseInt(log.blockTimestamp, 16) * 1000;\n if (timestamp < cutoffTime) continue;\n const amount = parseInt(log.data, 16) / 1e6;\n const from = '0x' + log.topics[1].slice(26);\n allTxns.push({\n chain: c,\n timestamp,\n type: 'IN',\n amount,\n other: from,\n hash: log.transactionHash,\n token: token.name,\n });\n }\n }\n \n // Query outgoing transfers (from = wallet)\n const outRes = await fetch('https://rpc.moderato.tempo.xyz', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_getLogs',\n params: [{ fromBlock, toBlock, address: token.address, topics: [transferTopic, walletTopic, null] }],\n id: 1,\n }),\n });\n const outData = await outRes.json() as { result?: Array<{ data: string; topics: string[]; transactionHash: string; blockTimestamp: string }>; error?: { message: string } };\n \n if (outData.result && Array.isArray(outData.result)) {\n for (const log of outData.result) {\n const timestamp = parseInt(log.blockTimestamp, 16) * 1000;\n if (timestamp < cutoffTime) continue;\n const amount = parseInt(log.data, 16) / 1e6;\n const to = '0x' + log.topics[2].slice(26);\n allTxns.push({\n chain: c,\n timestamp,\n type: 'OUT',\n amount,\n other: to,\n hash: log.transactionHash,\n token: token.name,\n });\n }\n }\n } catch (tokenError) {\n // Silently continue to next token if one fails\n continue;\n }\n }\n } else {\n // Other chains: use Blockscout API\n const url = `${explorer.api}/addresses/${wallet}/token-transfers?type=ERC-20&token=${explorer.usdc}`;\n const response = await fetch(url);\n const data = await response.json() as { \n items: Array<{\n timestamp: string;\n from: { hash: string };\n to: { hash: string };\n total: { value: string; decimals: string };\n transaction_hash: string;\n }>;\n };\n\n if (data.items && Array.isArray(data.items)) {\n for (const tx of data.items) {\n const timestamp = new Date(tx.timestamp).getTime();\n if (timestamp < cutoffTime) continue;\n\n const isIncoming = tx.to.hash.toLowerCase() === wallet.toLowerCase();\n const decimals = parseInt(tx.total.decimals) || 6;\n allTxns.push({\n chain: c,\n timestamp,\n type: isIncoming ? 'IN' : 'OUT',\n amount: parseInt(tx.total.value) / Math.pow(10, decimals),\n other: isIncoming ? tx.from.hash : tx.to.hash,\n hash: tx.transaction_hash,\n });\n }\n }\n }\n } catch (error) {\n // Show error details for debugging\n const errMsg = error instanceof Error ? error.message : String(error);\n console.log(` ⚠️ ${explorer.name}: ${errMsg}`);\n }\n }\n\n // Sort by timestamp descending\n allTxns.sort((a, b) => b.timestamp - a.timestamp);\n\n // Apply limit\n allTxns = allTxns.slice(0, limit);\n\n if (allTxns.length === 0) {\n console.log(' (no transactions found)\\n');\n } else {\n for (const tx of allTxns) {\n const sign = tx.type === 'IN' ? '+' : '-';\n const color = tx.type === 'IN' ? '\\x1b[32m' : '\\x1b[31m';\n const reset = '\\x1b[0m';\n const date = new Date(tx.timestamp).toISOString().slice(5, 16).replace('T', ' ');\n let chainLabel = tx.chain.toUpperCase();\n if (tx.chain === 'tempo_moderato') chainLabel = 'TEMPO';\n else if (tx.chain === 'base_sepolia') chainLabel = 'BASE_SEPOLIA';\n const chainTag = chain === 'all' ? `[${chainLabel}] ` : '';\n \n const tokenName = tx.token || 'USDC';\n console.log(` ${color}${sign}${tx.amount.toFixed(2)} ${tokenName}${reset} | ${chainTag}${tx.type === 'IN' ? 'from' : 'to'} ${tx.other.slice(0, 10)}...${tx.other.slice(-4)} | ${date}`);\n }\n \n // Summary\n const inTotal = allTxns.filter(t => t.type === 'IN').reduce((s, t) => s + t.amount, 0);\n const outTotal = allTxns.filter(t => t.type === 'OUT').reduce((s, t) => s + t.amount, 0);\n console.log(`\\n 📊 ${allTxns.length} transaction(s) | \\x1b[32m+$${inTotal.toFixed(2)}\\x1b[0m in | \\x1b[31m-$${outTotal.toFixed(2)}\\x1b[0m out\\n`);\n }\n });\n\n/**\n * npx moltspay services <url>\n */\nprogram\n .command('services [url]')\n .description('List services from registry or a specific provider')\n .option('-q, --query <keyword>', 'Search by keyword (name, description, tags)')\n .option('--max-price <price>', 'Maximum price in USD')\n .option('--type <type>', 'Filter by type: api_service | file_download')\n .option('--tag <tag>', 'Filter by tag')\n .option('--json', 'Output as JSON')\n .action(async (url, options) => {\n const MOLTSPAY_REGISTRY = 'https://moltspay.com';\n \n try {\n let services: any;\n let isRegistry = false;\n \n if (url) {\n // Query specific provider\n const client = new MoltsPayClient();\n services = await client.getServices(url);\n } else {\n // Query MoltsPay registry with filters\n isRegistry = true;\n const params = new URLSearchParams();\n if (options.query) params.set('q', options.query);\n if (options.maxPrice) params.set('maxPrice', options.maxPrice);\n if (options.type) params.set('type', options.type);\n if (options.tag) params.set('tag', options.tag);\n \n const queryString = params.toString();\n const registryUrl = `${MOLTSPAY_REGISTRY}/registry/services${queryString ? '?' + queryString : ''}`;\n \n const res = await fetch(registryUrl);\n if (!res.ok) {\n throw new Error(`Registry request failed: ${res.status}`);\n }\n services = await res.json();\n }\n\n if (options.json) {\n console.log(JSON.stringify(services, null, 2));\n } else {\n const serviceList = services.services || [];\n \n if (isRegistry) {\n // Registry listing\n if (options.query) {\n console.log(`\\n🔍 Search: \"${options.query}\" (${serviceList.length} results)\\n`);\n } else {\n const filters = [];\n if (options.maxPrice) filters.push(`max $${options.maxPrice}`);\n if (options.type) filters.push(options.type);\n if (options.tag) filters.push(`#${options.tag}`);\n const filterStr = filters.length > 0 ? ` (${filters.join(', ')})` : '';\n console.log(`\\n🔍 MoltsPay Registry${filterStr} - ${serviceList.length} services\\n`);\n }\n \n // Table-like output for registry\n for (const svc of serviceList) {\n const name = (svc.name || svc.id).slice(0, 30).padEnd(30);\n const price = `$${svc.price}`.padEnd(8);\n const type = (svc.type || 'unknown').padEnd(14);\n const provider = `@${svc.provider?.username || 'unknown'}`;\n console.log(` ${name} ${price} ${type} ${provider}`);\n }\n \n if (serviceList.length > 0) {\n console.log(`\\n 💡 Use: moltspay pay <provider-url> <service-id>\\n`);\n }\n } else {\n // Single provider format\n if (services.provider) {\n console.log(`\\n🏪 ${services.provider.name}\\n`);\n console.log(` ${services.provider.description || ''}`);\n console.log(` Wallet: ${services.provider.wallet}`);\n \n const chains = services.provider.chains \n ? (Array.isArray(services.provider.chains) \n ? services.provider.chains.map((c: any) => typeof c === 'string' ? c : c.chain).join(', ')\n : services.provider.chains)\n : services.provider.chain || 'base';\n console.log(` Chains: ${chains}`);\n } else {\n console.log(`\\n🏪 Provider Services\\n`);\n console.log(` ${serviceList.length} services available`);\n }\n \n console.log('\\n📦 Services:\\n');\n \n for (const svc of serviceList) {\n const status = svc.available !== false ? '✅' : '❌';\n console.log(` ${status} ${svc.id || svc.name}`);\n console.log(` ${svc.name} - $${svc.price} ${svc.currency}`);\n if (svc.description) {\n console.log(` ${svc.description}`);\n }\n if (svc.provider && !services.provider) {\n console.log(` Provider: ${svc.provider.name || svc.provider.username}`);\n }\n console.log('');\n }\n }\n }\n } catch (err: any) {\n console.error('❌ Error:', err.message);\n }\n });\n\n/**\n * npx moltspay start <paths...>\n * \n * Start server from skill directories or manifest files.\n * \n * Supports:\n * - Skill directory: ./skills/video_gen/ (with moltspay.services.json + index.js)\n * - Legacy manifest: ./moltspay.services.json (with optional command field)\n * - Multiple paths: ./skills/video_gen/ ./skills/translation/\n * \n * Services with \"function\" field load from skill's index.js\n * Services with \"command\" field execute shell commands (legacy)\n */\nprogram\n .command('start <paths...>')\n .description('Start MoltsPay server from skill directories or manifest files')\n .option('-p, --port <port>', 'Port to listen on', '3000')\n .option('--host <host>', 'Host to bind', '0.0.0.0')\n .option('--facilitator <url>', 'x402 facilitator URL (default: https://x402.org/facilitator)')\n .action(async (paths, options) => {\n const port = parseInt(options.port, 10);\n const host = options.host;\n const facilitatorUrl = options.facilitator;\n\n // Support comma-separated paths\n const allPaths = paths.flatMap((p: string) => p.split(',').map(s => s.trim())).filter(Boolean);\n\n console.log(`\\n🚀 Starting MoltsPay Server (x402 protocol)\\n`);\n\n // Collect all services and handlers from all paths\n const allServices: any[] = [];\n const handlers: Map<string, (params: any) => Promise<any>> = new Map();\n let provider: any = null;\n\n for (const inputPath of allPaths) {\n const resolvedPath = resolve(inputPath);\n \n // Determine if it's a directory (skill) or file (manifest)\n let manifestPath: string;\n let skillDir: string;\n let isSkillDir = false;\n\n if (existsSync(join(resolvedPath, 'moltspay.services.json'))) {\n // It's a skill directory\n manifestPath = join(resolvedPath, 'moltspay.services.json');\n skillDir = resolvedPath;\n isSkillDir = true;\n } else if (existsSync(resolvedPath) && resolvedPath.endsWith('.json')) {\n // It's a manifest file\n manifestPath = resolvedPath;\n skillDir = dirname(resolvedPath);\n } else if (existsSync(resolvedPath)) {\n // Directory without moltspay.services.json\n console.error(`❌ No moltspay.services.json found in: ${resolvedPath}`);\n continue;\n } else {\n console.error(`❌ Path not found: ${resolvedPath}`);\n continue;\n }\n\n console.log(`📦 Loading: ${manifestPath}`);\n\n try {\n const manifestContent = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n \n // Use first provider found, or merge\n if (!provider) {\n provider = manifestContent.provider;\n }\n\n // Load skill module if it's a skill directory\n let skillModule: any = null;\n if (isSkillDir) {\n // Determine entry point: check package.json main, fallback to index.js\n let entryPoint = 'index.js';\n const pkgJsonPath = join(skillDir, 'package.json');\n if (existsSync(pkgJsonPath)) {\n try {\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));\n if (pkgJson.main) {\n entryPoint = pkgJson.main;\n }\n } catch {\n // Ignore package.json parse errors\n }\n }\n\n const modulePath = join(skillDir, entryPoint);\n if (existsSync(modulePath)) {\n try {\n skillModule = await import(modulePath);\n console.log(` ✅ Loaded module: ${modulePath}`);\n } catch (err: any) {\n console.error(` ⚠️ Failed to load module: ${err.message}`);\n }\n } else {\n console.error(` ⚠️ Entry point not found: ${modulePath}`);\n }\n }\n\n // Register each service\n for (const service of manifestContent.services) {\n allServices.push(service);\n\n // Priority: function > command\n if (service.function && skillModule) {\n // New skill-based approach: import function from index.js\n const fn = skillModule[service.function] || skillModule.default?.[service.function];\n if (fn && typeof fn === 'function') {\n handlers.set(service.id, fn);\n console.log(` ✅ ${service.id} → ${service.function}()`);\n } else {\n console.error(` ❌ Function '${service.function}' not found in index.js`);\n }\n } else if (service.command) {\n // Legacy command-based approach\n const workdir = skillDir;\n handlers.set(service.id, async (params) => {\n return new Promise((resolvePromise, reject) => {\n const proc = spawn('sh', ['-c', service.command], {\n cwd: workdir,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n\n proc.stdout.on('data', (data) => {\n stdout += data.toString();\n });\n\n proc.stderr.on('data', (data) => {\n stderr += data.toString();\n process.stderr.write(data);\n });\n\n proc.stdin.write(JSON.stringify(params));\n proc.stdin.end();\n\n proc.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Command failed (exit ${code}): ${stderr || 'Unknown error'}`));\n return;\n }\n try {\n resolvePromise(JSON.parse(stdout.trim()));\n } catch {\n resolvePromise({ output: stdout.trim() });\n }\n });\n\n proc.on('error', (err) => {\n reject(new Error(`Failed to spawn command: ${err.message}`));\n });\n });\n });\n console.log(` ✅ ${service.id} → command`);\n } else {\n console.warn(` ⚠️ ${service.id}: no function or command defined`);\n }\n }\n } catch (err: any) {\n console.error(`❌ Failed to load ${manifestPath}: ${err.message}`);\n continue;\n }\n }\n\n if (allServices.length === 0) {\n console.error('\\n❌ No services loaded. Exiting.');\n process.exit(1);\n }\n\n if (!provider) {\n console.error('\\n❌ No provider config found. Exiting.');\n process.exit(1);\n }\n\n // Create combined manifest for server\n const combinedManifest = {\n provider,\n services: allServices,\n };\n\n // Write temporary manifest for server\n const tempManifestPath = join(DEFAULT_CONFIG_DIR, 'combined-manifest.json');\n writeFileSync(tempManifestPath, JSON.stringify(combinedManifest, null, 2));\n\n console.log(`\\n📋 Combined manifest: ${allServices.length} services`);\n console.log(` Provider: ${provider.name}`);\n console.log(` Wallet: ${provider.wallet}`);\n console.log(` Port: ${port}`);\n console.log('');\n\n try {\n const server = new MoltsPayServer(tempManifestPath, { port, host, facilitatorUrl });\n\n // Register all handlers\n for (const [serviceId, handler] of handlers) {\n server.skill(serviceId, handler);\n }\n\n // Write PID file\n const pidData = { pid: process.pid, port, paths: allPaths };\n writeFileSync(PID_FILE, JSON.stringify(pidData, null, 2));\n\n // Start listening\n server.listen(port);\n\n // Cleanup function\n const cleanup = () => {\n try {\n if (existsSync(PID_FILE)) unlinkSync(PID_FILE);\n if (existsSync(tempManifestPath)) unlinkSync(tempManifestPath);\n } catch {}\n };\n\n process.on('SIGINT', () => {\n console.log('\\n\\n👋 Shutting down...');\n cleanup();\n process.exit(0);\n });\n\n process.on('SIGTERM', () => {\n console.log('\\n\\n👋 Shutting down...');\n cleanup();\n process.exit(0);\n });\n\n process.on('exit', cleanup);\n\n } catch (err: any) {\n console.error(`❌ Failed to start server: ${err.message}`);\n process.exit(1);\n }\n });\n\n/**\n * npx moltspay stop\n * \n * Stop the running MoltsPay server gracefully\n */\nprogram\n .command('stop')\n .description('Stop the running MoltsPay server')\n .action(async () => {\n if (!existsSync(PID_FILE)) {\n console.log('❌ No running server found (no PID file)');\n process.exit(1);\n }\n\n try {\n const pidData = JSON.parse(readFileSync(PID_FILE, 'utf-8'));\n const { pid, port, manifest } = pidData;\n\n console.log(`\\n🛑 Stopping MoltsPay Server\\n`);\n console.log(` PID: ${pid}`);\n console.log(` Port: ${port}`);\n console.log(` Manifest: ${manifest}`);\n console.log('');\n\n // Check if process is running\n try {\n process.kill(pid, 0); // Test if process exists\n } catch {\n console.log('⚠️ Process not running, cleaning up PID file...');\n unlinkSync(PID_FILE);\n process.exit(0);\n }\n\n // Send SIGTERM for graceful shutdown\n process.kill(pid, 'SIGTERM');\n console.log('✅ Sent SIGTERM to server');\n\n // Wait a bit and check if it stopped\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n try {\n process.kill(pid, 0);\n console.log('⚠️ Server still running, sending SIGKILL...');\n process.kill(pid, 'SIGKILL');\n } catch {\n // Process is gone, good\n }\n\n // Clean up PID file if still exists\n if (existsSync(PID_FILE)) {\n unlinkSync(PID_FILE);\n }\n\n console.log('✅ Server stopped\\n');\n\n } catch (err: any) {\n console.error(`❌ Failed to stop server: ${err.message}`);\n process.exit(1);\n }\n });\n\n/**\n * npx moltspay pay <server> <service> <params>\n * \n * Pay for a service and get the result\n * \n * --image can be a URL or local file path:\n * URL: https://example.com/image.jpg -> sends as image_url\n * File: ./image.jpg or /path/to/image.jpg -> sends as image_base64\n * \n * --token specifies which stablecoin to use (USDC or USDT)\n * --chain specifies which chain to pay on (base or polygon, default: base)\n */\nprogram\n .command('pay <server> <service> [params]')\n .description('Pay for a service and get the result')\n .option('--prompt <text>', 'Prompt for the service')\n .option('--image <path>', 'Image URL or local file path')\n .option('--data <json>', 'Raw JSON data to send (for custom input formats)')\n .option('--token <token>', 'Token to pay with (USDC or USDT)', 'USDC')\n .option('--chain <chain>', 'Chain to pay on (base, polygon, base_sepolia, tempo_moderato, solana, or solana_devnet).')\n .option('--config-dir <dir>', 'Config directory with wallet.json', DEFAULT_CONFIG_DIR)\n .option('--json', 'Output raw JSON only')\n .action(async (server, service, paramsJson, options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n\n if (!client.isInitialized) {\n console.error('❌ Wallet not initialized. Run: npx moltspay init');\n process.exit(1);\n }\n\n // Build params from JSON string or options\n let params: Record<string, any> = {};\n let useRawData = false;\n \n // --data flag: raw JSON for custom input formats (takes priority)\n if (options.data) {\n try {\n params = JSON.parse(options.data);\n useRawData = true;\n } catch {\n console.error('❌ Invalid JSON in --data flag');\n process.exit(1);\n }\n } else if (paramsJson) {\n try {\n params = JSON.parse(paramsJson);\n } catch {\n console.error('❌ Invalid JSON params');\n process.exit(1);\n }\n }\n \n // Override with CLI options (only if not using --data)\n if (!useRawData && options.prompt) params.prompt = options.prompt;\n \n // Handle --image: URL or local file\n if (options.image) {\n const imagePath = options.image;\n \n if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {\n // It's a URL\n params.image_url = imagePath;\n } else {\n // It's a local file - read and convert to base64\n const filePath = resolve(imagePath);\n \n if (!existsSync(filePath)) {\n console.error(`❌ Image file not found: ${filePath}`);\n process.exit(1);\n }\n \n const imageData = readFileSync(filePath);\n params.image_base64 = imageData.toString('base64');\n }\n }\n\n // Validate chain option (if specified)\n const supportedPayChains = ['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'bnb', 'bnb_testnet', 'solana', 'solana_devnet'];\n const chain = options.chain?.toLowerCase();\n if (chain && !supportedPayChains.includes(chain)) {\n console.error(`❌ Unknown chain: ${chain}. Supported: ${supportedPayChains.join(', ')}`);\n process.exit(1);\n }\n\n const imageDisplay = params.image_url || (params.image_base64 ? `[local file: ${options.image}]` : null);\n const token = (options.token || 'USDC').toUpperCase();\n\n // USDT requires gas - check native balance\n if (token === 'USDT') {\n const balance = await client.getBalance();\n if (balance.native < 0.0001) {\n console.log('\\n⚠️ USDT requires a small amount of ETH for gas (~$0.01)');\n console.log(` Your ETH balance: ${balance.native.toFixed(6)} ETH`);\n console.log(' Please add a tiny amount of ETH to your wallet.\\n');\n process.exit(1);\n }\n if (!options.json) {\n console.log('\\n⚠️ Note: USDT payments require gas (~$0.01 on Base)');\n }\n }\n\n if (!options.json) {\n console.log(`\\n💳 MoltsPay - Paying for service\\n`);\n console.log(` Server: ${server}`);\n console.log(` Service: ${service}`);\n if (useRawData) {\n console.log(` Data: ${JSON.stringify(params).slice(0, 50)}${JSON.stringify(params).length > 50 ? '...' : ''}`);\n } else {\n console.log(` Prompt: ${params.prompt}`);\n }\n if (imageDisplay) console.log(` Image: ${imageDisplay}`);\n console.log(` Chain: ${chain || '(auto)'}`); // Will be determined by server\n console.log(` Token: ${token}`);\n console.log(` Wallet: ${client.address}`);\n console.log('');\n }\n\n try {\n // All chains use the same pay() flow - protocol detection happens inside\n // Server's /proxy endpoint handles both x402 and MPP based on chain\n const result = await client.pay(server, service, params, { \n token: token as 'USDC' | 'USDT',\n chain,\n rawData: useRawData\n });\n \n if (options.json) {\n console.log(JSON.stringify(result));\n } else {\n console.log('✅ Success!\\n');\n console.log(JSON.stringify(result, null, 2));\n console.log('');\n }\n } catch (err: any) {\n if (options.json) {\n console.log(JSON.stringify({ error: err.message }));\n } else {\n console.error(`❌ Error: ${err.message}`);\n }\n process.exit(1);\n }\n });\n\n/**\n * npx moltspay validate <path>\n */\nprogram\n .command('validate <path>')\n .description('Validate a moltspay.services.json file against the schema')\n .action(async (inputPath) => {\n const resolvedPath = resolve(inputPath);\n \n // Find manifest file\n let manifestPath: string;\n if (existsSync(join(resolvedPath, 'moltspay.services.json'))) {\n manifestPath = join(resolvedPath, 'moltspay.services.json');\n } else if (resolvedPath.endsWith('.json') && existsSync(resolvedPath)) {\n manifestPath = resolvedPath;\n } else {\n console.error(`❌ Not found: ${resolvedPath}`);\n process.exit(1);\n }\n\n console.log(`\\n📋 Validating: ${manifestPath}\\n`);\n\n try {\n const content = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n const errors: string[] = [];\n\n // Validate provider\n if (!content.provider) {\n errors.push('Missing required field: provider');\n } else {\n if (!content.provider.name) errors.push('Missing provider.name');\n if (!content.provider.wallet) errors.push('Missing provider.wallet');\n else if (!/^0x[a-fA-F0-9]{40}$/.test(content.provider.wallet)) {\n errors.push('Invalid provider.wallet (must be Ethereum address)');\n }\n }\n\n // Validate services\n if (!content.services || !Array.isArray(content.services)) {\n errors.push('Missing required field: services (array)');\n } else if (content.services.length === 0) {\n errors.push('services array must have at least one service');\n } else {\n content.services.forEach((svc: any, i: number) => {\n const prefix = `services[${i}]`;\n if (!svc.id) errors.push(`${prefix}: missing id`);\n else if (!/^[a-z0-9-]+$/.test(svc.id)) {\n errors.push(`${prefix}: id must be lowercase with hyphens only`);\n }\n if (typeof svc.price !== 'number') errors.push(`${prefix}: missing or invalid price`);\n if (!svc.currency) errors.push(`${prefix}: missing currency`);\n if (!svc.function && !svc.command) {\n errors.push(`${prefix}: must have either \"function\" or \"command\"`);\n }\n });\n }\n\n if (errors.length > 0) {\n console.log('❌ Validation failed:\\n');\n errors.forEach(e => console.log(` • ${e}`));\n console.log('');\n process.exit(1);\n }\n\n console.log('✅ Valid!\\n');\n console.log(` Provider: ${content.provider.name}`);\n console.log(` Wallet: ${content.provider.wallet}`);\n console.log(` Services: ${content.services.length}`);\n content.services.forEach((svc: any) => {\n console.log(` - ${svc.id} ($${svc.price} ${svc.currency})`);\n });\n console.log('');\n\n } catch (err: any) {\n console.error(`❌ Parse error: ${err.message}`);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","/**\n * MoltsPay Client - Pay for AI Agent services\n * \n * Uses x402 protocol for gasless, pay-for-success payments.\n * \n * Usage:\n * const client = new MoltsPayClient(); // Loads from ~/.moltspay/\n * const services = await client.getServices('http://provider:3000');\n * const result = await client.pay('http://provider:3000', 'text-to-video', { prompt: '...' });\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, statSync, chmodSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { Wallet, ethers } from 'ethers';\nimport { getChain, type ChainName, type EvmChainName, type TokenSymbol, type ChainConfig } from '../chains/index.js';\nimport { SOLANA_CHAINS, type SolanaChainName } from '../chains/solana.js';\nimport { loadSolanaWallet, getSolanaAddress } from '../wallet/solana.js';\nimport { createSolanaPaymentTransaction } from '../facilitators/solana.js';\nimport { Connection, PublicKey, Keypair } from '@solana/web3.js';\nimport {\n ClientConfig,\n WalletData,\n ServicesResponse,\n MoltsPayClientOptions,\n} from './types.js';\n\nexport * from './types.js';\n\nexport interface PayOptions {\n /** Token to pay with (default: USDC, or auto-select based on balance) */\n token?: TokenSymbol;\n /** Auto-select token based on balance (default: false) */\n autoSelect?: boolean;\n /** Chain to pay on */\n chain?: 'base' | 'polygon' | 'base_sepolia' | 'tempo_moderato' | 'bnb' | 'bnb_testnet' | 'solana' | 'solana_devnet';\n /** Send raw data at top level instead of wrapped in { params } */\n rawData?: boolean;\n}\n\n// x402 constants\nconst X402_VERSION = 2;\nconst PAYMENT_REQUIRED_HEADER = 'x-payment-required';\nconst PAYMENT_HEADER = 'x-payment';\n\ninterface X402PaymentRequirements {\n scheme: string;\n network: string;\n // v2 fields\n amount?: string;\n asset?: string;\n payTo?: string;\n maxTimeoutSeconds?: number;\n extra?: Record<string, unknown>;\n // v1 fields (legacy)\n maxAmountRequired?: string;\n resource?: string;\n description?: string;\n}\n\ninterface EIP3009Authorization {\n from: string;\n to: string;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: string;\n}\n\nconst DEFAULT_CONFIG: ClientConfig = {\n chain: 'base',\n limits: {\n maxPerTx: 100,\n maxPerDay: 1000,\n },\n};\n\nexport class MoltsPayClient {\n private configDir: string;\n private config: ClientConfig;\n private walletData: WalletData | null = null;\n private wallet: Wallet | null = null;\n private todaySpending: number = 0;\n private lastSpendingReset: number = 0;\n\n constructor(options: MoltsPayClientOptions = {}) {\n this.configDir = options.configDir || join(homedir(), '.moltspay');\n this.config = this.loadConfig();\n this.walletData = this.loadWallet();\n this.loadSpending(); // Load persisted spending data\n \n if (this.walletData) {\n this.wallet = new Wallet(this.walletData.privateKey);\n }\n }\n\n /**\n * Check if client is initialized (has wallet)\n */\n get isInitialized(): boolean {\n return this.wallet !== null;\n }\n\n /**\n * Get wallet address\n */\n get address(): string | null {\n return this.wallet?.address || null;\n }\n\n /**\n * Get wallet instance (for direct operations like approvals)\n */\n getWallet(): Wallet | null {\n return this.wallet;\n }\n\n /**\n * Get current config\n */\n getConfig(): ClientConfig {\n return { ...this.config };\n }\n\n /**\n * Update config\n */\n updateConfig(updates: Partial<ClientConfig['limits']>): void {\n if (updates.maxPerTx !== undefined) {\n this.config.limits.maxPerTx = updates.maxPerTx;\n }\n if (updates.maxPerDay !== undefined) {\n this.config.limits.maxPerDay = updates.maxPerDay;\n }\n this.saveConfig();\n }\n\n /**\n * Get services from a provider\n */\n async getServices(serverUrl: string): Promise<ServicesResponse> {\n // Normalize URL - don't append /services if already present\n const normalizedUrl = serverUrl.replace(/\\/(services|api\\/services|registry\\/services)\\/?$/, '');\n \n // Try /services first (standard provider endpoint)\n const endpoints = ['/services', '/api/services', '/registry/services'];\n \n for (const endpoint of endpoints) {\n try {\n const res = await fetch(`${normalizedUrl}${endpoint}`);\n if (!res.ok) continue;\n \n const contentType = res.headers.get('content-type') || '';\n if (!contentType.includes('application/json')) continue;\n \n return await res.json() as ServicesResponse;\n } catch {\n continue;\n }\n }\n \n throw new Error(`Failed to get services: no valid endpoint found at ${normalizedUrl}`);\n }\n\n /**\n * Pay for a service and get the result (x402 protocol)\n * \n * This is GASLESS for the client - server pays gas to claim payment.\n * This is PAY-FOR-SUCCESS - payment only claimed if service succeeds.\n * \n * @param serverUrl - Server URL\n * @param service - Service ID\n * @param params - Service parameters\n * @param options - Payment options (token selection)\n */\n async pay(\n serverUrl: string,\n service: string,\n params: Record<string, any>,\n options: PayOptions = {}\n ): Promise<Record<string, any>> {\n if (!this.wallet || !this.walletData) {\n throw new Error('Client not initialized. Run: npx moltspay init');\n }\n\n // Step 1: Discover service endpoint\n console.log(`[MoltsPay] Requesting service: ${service}`);\n let executeUrl = `${serverUrl}/execute`; // Default fallback\n \n try {\n const services = await this.getServices(serverUrl);\n const svc = services.services?.find((s: any) => s.id === service);\n if (svc?.endpoint) {\n // Use the endpoint from service discovery (for Cloudflare Workers, etc.)\n executeUrl = `${serverUrl}${svc.endpoint}`;\n console.log(`[MoltsPay] Using service endpoint: ${svc.endpoint}`);\n }\n } catch {\n // Fall back to /execute if service discovery fails\n }\n \n // Build request body - raw mode sends data at top level, standard mode wraps in { params }\n let requestBody: any;\n if (options.rawData) {\n // Raw mode: { service, chain, ...params } - user's data at top level\n requestBody = { service, ...params };\n } else {\n // Standard mode: { service, params } - wrapped format\n requestBody = { service, params };\n }\n if (options.chain) {\n requestBody.chain = options.chain;\n }\n const initialRes = await fetch(executeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n });\n\n // If not 402, check for success or error\n if (initialRes.status !== 402) {\n const data = await initialRes.json() as any;\n if (initialRes.ok && data.result) {\n return data.result;\n }\n throw new Error(data.error || 'Unexpected response');\n }\n\n // Step 2: Detect protocol from 402 response\n // MPP uses WWW-Authenticate header, x402 uses X-Payment-Required header\n const wwwAuthHeader = initialRes.headers.get('www-authenticate');\n const paymentRequiredHeader = initialRes.headers.get(PAYMENT_REQUIRED_HEADER);\n \n // If WWW-Authenticate with Payment scheme, use MPP flow\n if (wwwAuthHeader && wwwAuthHeader.toLowerCase().includes('payment')) {\n console.log('[MoltsPay] Detected MPP protocol, using Tempo flow...');\n return await this.handleMPPPayment(executeUrl, service, params, wwwAuthHeader, options);\n }\n \n if (!paymentRequiredHeader) {\n throw new Error('Missing payment header (x-payment-required or www-authenticate)');\n }\n\n let requirements: X402PaymentRequirements[];\n try {\n const decoded = Buffer.from(paymentRequiredHeader, 'base64').toString('utf-8');\n const parsed = JSON.parse(decoded);\n \n // Handle both v1 (array) and v2 (object with accepts) formats\n if (Array.isArray(parsed)) {\n // v1 format: direct array of requirements\n requirements = parsed;\n } else if (parsed.accepts && Array.isArray(parsed.accepts)) {\n // v2 format: { x402Version: 2, accepts: [...] }\n requirements = parsed.accepts;\n } else {\n // Single requirement object\n requirements = [parsed];\n }\n } catch {\n throw new Error('Invalid x-payment-required header');\n }\n\n // Helper to convert network ID to chain name\n const networkToChainName = (network: string): string | null => {\n // Handle Solana networks\n if (network === 'solana:mainnet') return 'solana';\n if (network === 'solana:devnet') return 'solana_devnet';\n \n // Handle EVM networks\n const match = network.match(/^eip155:(\\d+)$/);\n if (!match) return null;\n const chainId = parseInt(match[1]);\n if (chainId === 8453) return 'base';\n if (chainId === 137) return 'polygon';\n if (chainId === 84532) return 'base_sepolia';\n if (chainId === 42431) return 'tempo_moderato';\n if (chainId === 56) return 'bnb';\n if (chainId === 97) return 'bnb_testnet';\n return null;\n };\n\n // Get server's accepted chains\n const serverChains = requirements\n .map(r => networkToChainName(r.network))\n .filter((c): c is string => c !== null);\n\n // Determine which chain to use\n const userSpecifiedChain = options.chain;\n let selectedChain: string;\n\n if (userSpecifiedChain) {\n // User specified --chain, validate it's accepted by server\n if (!serverChains.includes(userSpecifiedChain)) {\n throw new Error(\n `Server doesn't accept '${userSpecifiedChain}'.\\n` +\n `Server accepts: ${serverChains.join(', ')}`\n );\n }\n selectedChain = userSpecifiedChain;\n } else {\n // No --chain provided\n if (serverChains.length === 1 && serverChains[0] === 'base') {\n // Only default to base if server ONLY accepts base\n selectedChain = 'base';\n } else {\n throw new Error(\n `Server accepts: ${serverChains.join(', ')}\\n` +\n `Please specify: --chain <chain_name>`\n );\n }\n }\n\n // Handle Solana chains separately\n if (selectedChain === 'solana' || selectedChain === 'solana_devnet') {\n const solanaChain = selectedChain as SolanaChainName;\n const network = solanaChain === 'solana' ? 'solana:mainnet' : 'solana:devnet';\n const req = requirements.find(r => r.network === network);\n \n if (!req) {\n throw new Error(`Failed to find payment requirement for ${selectedChain}`);\n }\n \n return await this.handleSolanaPayment(executeUrl, service, params, req, solanaChain, options);\n }\n\n // EVM chain handling\n const chainName = selectedChain as EvmChainName;\n const chain = getChain(chainName);\n const network = `eip155:${chain.chainId}`;\n const req = requirements.find(r => r.scheme === 'exact' && r.network === network);\n\n if (!req) {\n throw new Error(`Failed to find payment requirement for ${chainName}`);\n }\n\n // Step 3: Check limits\n // v2 uses 'amount', v1 uses 'maxAmountRequired'\n const amountRaw = req.amount || req.maxAmountRequired;\n if (!amountRaw) {\n throw new Error('Missing amount in payment requirements');\n }\n const amount = Number(amountRaw) / 1e6;\n this.checkLimits(amount);\n\n // Determine which token to use\n let token: TokenSymbol = options.token || 'USDC';\n \n // Auto-select token based on balance if requested\n if (options.autoSelect) {\n const balances = await this.getBalance();\n if (balances.usdc >= amount) {\n token = 'USDC';\n } else if (balances.usdt >= amount) {\n token = 'USDT';\n } else {\n throw new Error(`Insufficient balance: need $${amount}, have ${balances.usdc} USDC / ${balances.usdt} USDT`);\n }\n }\n\n // USDT does not support gasless transfers (no EIP-2612 permit)\n // It requires on-chain approve + transfer, meaning the user pays gas\n if (token === 'USDT') {\n const balances = await this.getBalance();\n if (balances.native < 0.0001) {\n throw new Error(\n `USDT requires ETH for gas (~$0.01 on Base). ` +\n `Your ETH balance: ${balances.native.toFixed(6)} ETH. ` +\n `Please add a small amount of ETH to your wallet, or use USDC (gasless).`\n );\n }\n console.log(`[MoltsPay] ⚠️ USDT requires gas (~$0.01). Proceeding with payment...`);\n } else {\n console.log(`[MoltsPay] Signing payment: $${amount} ${token} (gasless)`);\n }\n\n // BNB chains use intent-based flow (pre-approval + intent signature)\n if (chainName === 'bnb' || chainName === 'bnb_testnet') {\n console.log(`[MoltsPay] Using BNB intent-based payment flow...`);\n const payTo = req.payTo || req.resource;\n if (!payTo) {\n throw new Error('Missing payTo address in payment requirements');\n }\n // Get spender address from server response (dynamic, not hardcoded)\n const bnbSpender = (req.extra as any)?.bnbSpender;\n if (!bnbSpender) {\n throw new Error('Server did not provide bnbSpender address. Server may not support BNB payments.');\n }\n return await this.handleBNBPayment(executeUrl, service, params, {\n to: payTo,\n amount,\n token,\n chainName,\n chain,\n spender: bnbSpender,\n }, options);\n }\n\n // Step 4: Sign EIP-3009 authorization (GASLESS - just signing)\n // payTo is the recipient address (v2 format)\n const payTo = req.payTo || req.resource; // fallback for v1 compatibility\n if (!payTo) {\n throw new Error('Missing payTo address in payment requirements');\n }\n \n // Use server's extra field for domain info (contains correct EIP-712 domain for the token on this network)\n const domainOverride = (req.extra && typeof req.extra === 'object' && req.extra.name) \n ? { name: req.extra.name as string, version: (req.extra.version as string) || '2' }\n : undefined;\n \n const authorization = await this.signEIP3009(payTo, amount, chain, token, domainOverride);\n\n // Get token-specific info for accepted field\n const tokenConfig = chain.tokens[token];\n\n // Step 5: Create x402 payment payload (v2 requires scheme, network, payload, AND accepted)\n // Use server's extra field if provided (contains correct EIP-712 domain for the token on this network)\n // Fall back to local config for backward compatibility\n const extra = (req.extra && typeof req.extra === 'object') \n ? req.extra \n : {\n name: (tokenConfig as any).eip712Name || 'USD Coin',\n version: '2',\n };\n \n const payload = {\n x402Version: X402_VERSION,\n scheme: 'exact',\n network,\n payload: authorization, // { authorization: {...}, signature: \"0x...\" }\n accepted: {\n scheme: 'exact',\n network,\n asset: tokenConfig.address,\n amount: amountRaw,\n payTo,\n maxTimeoutSeconds: req.maxTimeoutSeconds || 300,\n extra,\n },\n };\n const paymentHeader = Buffer.from(JSON.stringify(payload)).toString('base64');\n\n // Step 6: Retry with payment header\n console.log(`[MoltsPay] Sending request with payment...`);\n const paidRequestBody: any = options.rawData\n ? { service, ...params }\n : { service, params };\n if (options.chain) {\n paidRequestBody.chain = options.chain;\n }\n const paidRes = await fetch(executeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n [PAYMENT_HEADER]: paymentHeader,\n },\n body: JSON.stringify(paidRequestBody),\n });\n\n const result = await paidRes.json() as any;\n\n if (!paidRes.ok) {\n throw new Error(result.error || 'Service execution failed');\n }\n\n // Update spending tracking\n this.recordSpending(amount);\n\n console.log(`[MoltsPay] Success! Payment: ${result.payment?.status || 'claimed'}`);\n \n // Support both MoltsPay Server format ({ result: ... }) and direct response format\n return result.result || result;\n }\n\n /**\n * Handle MPP (Machine Payments Protocol) payment flow\n * Called when pay() detects WWW-Authenticate header in 402 response\n */\n private async handleMPPPayment(\n executeUrl: string,\n service: string,\n params: Record<string, any>,\n wwwAuthHeader: string,\n options: PayOptions = {}\n ): Promise<Record<string, any>> {\n // Dynamic imports for ESM-only packages\n const { privateKeyToAccount } = await import('viem/accounts');\n const { createWalletClient, createPublicClient, http } = await import('viem');\n const { tempoModerato } = await import('viem/chains');\n const { Actions } = await import('viem/tempo');\n\n // Get private key from wallet data\n const privateKey = this.walletData!.privateKey as `0x${string}`;\n const account = privateKeyToAccount(privateKey);\n\n console.log(`[MoltsPay] Using MPP protocol on Tempo`);\n console.log(`[MoltsPay] Account: ${account.address}`);\n\n // Parse WWW-Authenticate: Payment id=\"...\", method=\"tempo\", request=\"...\"\n const parseAuthParam = (header: string, key: string): string | null => {\n const match = header.match(new RegExp(`${key}=\"([^\"]+)\"`, 'i'));\n return match ? match[1] : null;\n };\n\n const challengeId = parseAuthParam(wwwAuthHeader, 'id');\n const method = parseAuthParam(wwwAuthHeader, 'method');\n const realm = parseAuthParam(wwwAuthHeader, 'realm');\n const requestB64 = parseAuthParam(wwwAuthHeader, 'request');\n\n if (method !== 'tempo') {\n throw new Error(`Unsupported payment method: ${method}`);\n }\n\n if (!requestB64) {\n throw new Error('Missing request in WWW-Authenticate');\n }\n\n // Decode payment request\n const requestJson = Buffer.from(requestB64, 'base64').toString('utf-8');\n const paymentRequest = JSON.parse(requestJson);\n \n const { amount, currency, recipient, methodDetails } = paymentRequest;\n const chainId = methodDetails?.chainId || 42431;\n const amountDisplay = Number(amount) / 1e6;\n\n console.log(`[MoltsPay] Payment: $${amountDisplay} to ${recipient}`);\n\n // Check limits\n this.checkLimits(amountDisplay);\n\n // Execute transfer on Tempo\n console.log(`[MoltsPay] Sending transaction on Tempo...`);\n\n const tempoChain = { ...tempoModerato, feeToken: currency as `0x${string}` };\n \n const publicClient = createPublicClient({\n chain: tempoChain,\n transport: http('https://rpc.moderato.tempo.xyz'),\n });\n\n const walletClient = createWalletClient({\n account,\n chain: tempoChain,\n transport: http('https://rpc.moderato.tempo.xyz'),\n });\n\n // TIP-20 transfer\n const txHash = await Actions.token.transfer(walletClient, {\n to: recipient as `0x${string}`,\n amount: BigInt(amount),\n token: currency as `0x${string}`,\n });\n\n console.log(`[MoltsPay] Transaction: ${txHash}`);\n\n // Wait for confirmation\n await publicClient.waitForTransactionReceipt({ hash: txHash });\n console.log(`[MoltsPay] Confirmed! Retrying with credential...`);\n\n // Build credential\n const credential = {\n challenge: {\n id: challengeId,\n realm,\n method: 'tempo',\n intent: 'charge',\n request: paymentRequest,\n },\n payload: { hash: txHash, type: 'hash' },\n source: `did:pkh:eip155:${chainId}:${account.address}`,\n };\n\n const credentialB64 = Buffer.from(JSON.stringify(credential))\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n // Retry with credential - respect rawData option\n const retryBody = options.rawData \n ? { service, ...params, chain: 'tempo_moderato' }\n : { service, params, chain: 'tempo_moderato' };\n \n const paidRes = await fetch(executeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Payment ${credentialB64}`,\n },\n body: JSON.stringify(retryBody),\n });\n\n const result = await paidRes.json() as any;\n\n if (!paidRes.ok) {\n throw new Error(result.error || 'Payment verification failed');\n }\n\n // Update spending tracking\n this.recordSpending(amountDisplay);\n\n console.log(`[MoltsPay] Success!`);\n return result.result || result;\n }\n\n /**\n * Handle BNB Chain payment flow (pre-approval + intent signature)\n * \n * Flow:\n * 1. Check client has approved server wallet (done via `moltspay init`)\n * 2. Sign EIP-712 payment intent (no gas, just signature)\n * 3. Send intent to server\n * 4. Server executes service\n * 5. Server calls transferFrom if successful (pay-for-success)\n */\n private async handleBNBPayment(\n executeUrl: string,\n service: string,\n params: Record<string, any>,\n paymentDetails: {\n to: string;\n amount: number;\n token: TokenSymbol;\n chainName: ChainName;\n chain: ChainConfig;\n spender: string;\n },\n options: PayOptions = {}\n ): Promise<Record<string, any>> {\n const { to, amount, token, chainName, chain, spender } = paymentDetails;\n const tokenConfig = chain.tokens[token];\n \n // Check approval status\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n const allowance = await this.checkAllowance(tokenConfig.address, spender, provider);\n const amountWeiCheck = BigInt(Math.floor(amount * (10 ** tokenConfig.decimals)));\n \n if (allowance < amountWeiCheck) {\n // Check if user has enough BNB for gas to approve\n const nativeBalance = await provider.getBalance(this.wallet!.address);\n const minGasBalance = ethers.parseEther('0.0005'); // ~0.0005 BNB minimum for approval\n \n if (nativeBalance < minGasBalance) {\n const nativeBNB = parseFloat(ethers.formatEther(nativeBalance)).toFixed(4);\n const isTestnet = chainName === 'bnb_testnet';\n \n if (isTestnet) {\n throw new Error(\n `❌ Insufficient tBNB for approval transaction\\n\\n` +\n ` Current tBNB: ${nativeBNB}\\n` +\n ` Required: ~0.001 tBNB\\n\\n` +\n ` Get testnet tokens: npx moltspay faucet --chain bnb_testnet\\n` +\n ` (Gives USDC + tBNB for gas)`\n );\n } else {\n throw new Error(\n `❌ Insufficient BNB for approval transaction\\n\\n` +\n ` Current BNB: ${nativeBNB}\\n` +\n ` Required: ~0.001 BNB (~$0.60)\\n\\n` +\n ` To get BNB:\\n` +\n ` • Withdraw from Binance/exchange to your wallet\\n` +\n ` • Most exchanges include BNB dust with withdrawals\\n\\n` +\n ` After funding, run:\\n` +\n ` npx moltspay approve --chain ${chainName} --spender ${spender}`\n );\n }\n }\n \n throw new Error(\n `Insufficient allowance for ${spender.slice(0, 10)}...\\n` +\n `Run: npx moltspay approve --chain ${chainName} --spender ${spender}`\n );\n }\n \n // Convert amount to wei (BNB uses 18 decimals)\n const amountWei = BigInt(Math.floor(amount * (10 ** tokenConfig.decimals))).toString();\n \n // Create payment intent\n const intent = {\n from: this.wallet!.address,\n to,\n amount: amountWei,\n token: tokenConfig.address,\n service,\n nonce: Date.now(), // Use timestamp as nonce for simplicity\n deadline: Date.now() + 3600000, // 1 hour\n };\n\n // EIP-712 domain\n const domain = {\n name: 'MoltsPay',\n version: '1',\n chainId: chain.chainId,\n };\n\n // EIP-712 types\n const types = {\n PaymentIntent: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n { name: 'token', type: 'address' },\n { name: 'service', type: 'string' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n };\n\n // Sign the intent\n console.log(`[MoltsPay] Signing BNB payment intent...`);\n const signature = await this.wallet!.signTypedData(domain, types, intent);\n\n // Create x402 payment payload with BNB-specific format\n const network = `eip155:${chain.chainId}`;\n const payload = {\n x402Version: 2,\n scheme: 'exact',\n network,\n payload: {\n intent: {\n ...intent,\n signature,\n },\n chainId: chain.chainId,\n },\n accepted: {\n scheme: 'exact',\n network,\n asset: tokenConfig.address,\n amount: amountWei,\n payTo: to,\n maxTimeoutSeconds: 300,\n },\n };\n\n const paymentHeader = Buffer.from(JSON.stringify(payload)).toString('base64');\n\n // Send request with payment - respect rawData option\n console.log(`[MoltsPay] Sending BNB payment request...`);\n const bnbRequestBody = options.rawData\n ? { service, ...params, chain: chainName }\n : { service, params, chain: chainName };\n const paidRes = await fetch(executeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Payment': paymentHeader,\n },\n body: JSON.stringify(bnbRequestBody),\n });\n\n const result = await paidRes.json() as any;\n\n if (!paidRes.ok) {\n throw new Error(result.error || 'BNB payment failed');\n }\n\n // Update spending tracking\n this.recordSpending(amount);\n\n console.log(`[MoltsPay] Success! BNB payment settled.`);\n return result.result || result;\n }\n\n /**\n * Handle Solana payment flow\n * \n * Solana uses SPL token transfers with pay-for-success model:\n * 1. Client creates and signs a transfer transaction\n * 2. Server submits the transaction after service completes\n */\n private async handleSolanaPayment(\n executeUrl: string,\n service: string,\n params: Record<string, any>,\n requirements: X402PaymentRequirements,\n chain: SolanaChainName,\n options: PayOptions = {}\n ): Promise<Record<string, any>> {\n // Load Solana wallet\n const solanaWallet = loadSolanaWallet(this.configDir);\n if (!solanaWallet) {\n throw new Error('No Solana wallet found. Run: npx moltspay init --chain solana_devnet');\n }\n\n const amount = Number(requirements.amount);\n const amountUSDC = amount / 1e6;\n \n // Check limits\n this.checkLimits(amountUSDC);\n\n console.log(`[MoltsPay] Creating Solana payment: $${amountUSDC} USDC`);\n\n // Validate payTo address\n if (!requirements.payTo) {\n throw new Error('Missing payTo address in payment requirements');\n }\n\n // Check for gasless mode (server pays fees)\n const solanaFeePayer = (requirements.extra as any)?.solanaFeePayer;\n const feePayerPubkey = solanaFeePayer ? new PublicKey(solanaFeePayer) : undefined;\n \n if (feePayerPubkey) {\n console.log(`[MoltsPay] Gasless mode: server pays fees`);\n }\n\n // Create the transfer transaction\n const recipientPubkey = new PublicKey(requirements.payTo);\n const transaction = await createSolanaPaymentTransaction(\n solanaWallet.publicKey,\n recipientPubkey,\n BigInt(amount),\n chain,\n feePayerPubkey // Optional fee payer for gasless mode\n );\n\n // Sign the transaction (partial sign if gasless mode)\n if (feePayerPubkey) {\n // Gasless mode: only sign for token transfer authority\n transaction.partialSign(solanaWallet);\n } else {\n // Normal mode: sign as both authority and fee payer\n transaction.sign(solanaWallet);\n }\n const signedTx = transaction.serialize({ requireAllSignatures: false }).toString('base64');\n\n console.log(`[MoltsPay] Transaction signed, sending to server...`);\n\n // Create x402 payload with Solana-specific format\n const network = chain === 'solana' ? 'solana:mainnet' : 'solana:devnet';\n const payload = {\n x402Version: 2,\n scheme: 'exact',\n network,\n payload: {\n signedTransaction: signedTx,\n sender: solanaWallet.publicKey.toBase58(),\n chain,\n },\n accepted: {\n scheme: 'exact',\n network,\n asset: requirements.asset,\n amount: requirements.amount,\n payTo: requirements.payTo,\n maxTimeoutSeconds: 300,\n },\n };\n\n const paymentHeader = Buffer.from(JSON.stringify(payload)).toString('base64');\n\n // Send request with payment - respect rawData option\n const solanaRequestBody = options.rawData\n ? { service, ...params, chain }\n : { service, params, chain };\n const paidRes = await fetch(executeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Payment': paymentHeader,\n },\n body: JSON.stringify(solanaRequestBody),\n });\n\n const result = await paidRes.json() as any;\n\n if (!paidRes.ok) {\n throw new Error(result.error || 'Solana payment failed');\n }\n\n // Update spending tracking\n this.recordSpending(amountUSDC);\n\n console.log(`[MoltsPay] Success! Solana payment settled.`);\n if (result.payment?.transaction) {\n const explorerUrl = chain === 'solana' \n ? `https://solscan.io/tx/${result.payment.transaction}`\n : `https://solscan.io/tx/${result.payment.transaction}?cluster=devnet`;\n console.log(`[MoltsPay] Transaction: ${explorerUrl}`);\n }\n\n return result.result || result;\n }\n\n /**\n * Check ERC20 allowance for a spender\n */\n private async checkAllowance(\n tokenAddress: string,\n spender: string,\n provider: ethers.JsonRpcProvider\n ): Promise<bigint> {\n const contract = new ethers.Contract(\n tokenAddress,\n ['function allowance(address owner, address spender) view returns (uint256)'],\n provider\n );\n return await contract.allowance(this.wallet!.address, spender);\n }\n\n /**\n * Sign EIP-3009 transferWithAuthorization (GASLESS)\n * This only signs - no on-chain transaction, no gas needed.\n * Supports both USDC and USDT.\n */\n private async signEIP3009(\n to: string,\n amount: number,\n chain: { chainId: number; tokens: Record<TokenSymbol, { address: string; decimals: number }> },\n token: TokenSymbol = 'USDC',\n domainOverride?: { name: string; version: string }\n ): Promise<{ authorization: EIP3009Authorization; signature: string }> {\n const validAfter = 0;\n const validBefore = Math.floor(Date.now() / 1000) + 3600; // 1 hour\n const nonce = ethers.hexlify(ethers.randomBytes(32));\n \n const tokenConfig = chain.tokens[token];\n const value = BigInt(Math.floor(amount * (10 ** tokenConfig.decimals))).toString();\n\n const authorization: EIP3009Authorization = {\n from: this.wallet!.address,\n to,\n value,\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n };\n\n // EIP-712 domain - use server's domain info if provided (handles mainnet vs testnet differences)\n // Fall back to local token config for backward compatibility\n const tokenName = domainOverride?.name || (tokenConfig as any).eip712Name || (token === 'USDC' ? 'USD Coin' : 'Tether USD');\n const tokenVersion = domainOverride?.version || '2';\n const domain = {\n name: tokenName,\n version: tokenVersion,\n chainId: chain.chainId,\n verifyingContract: tokenConfig.address,\n };\n\n // EIP-3009 types\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n const signature = await this.wallet!.signTypedData(domain, types, authorization);\n\n return { authorization, signature };\n }\n\n /**\n * Check spending limits\n */\n private checkLimits(amount: number): void {\n // Check per-tx limit\n if (amount > this.config.limits.maxPerTx) {\n throw new Error(\n `Amount $${amount} exceeds max per transaction ($${this.config.limits.maxPerTx})`\n );\n }\n\n // Reset daily spending if new day\n const today = new Date().setHours(0, 0, 0, 0);\n if (today > this.lastSpendingReset) {\n this.todaySpending = 0;\n this.lastSpendingReset = today;\n this.saveSpending(); // Persist reset\n }\n\n // Check daily limit\n if (this.todaySpending + amount > this.config.limits.maxPerDay) {\n throw new Error(\n `Would exceed daily limit ($${this.todaySpending} + $${amount} > $${this.config.limits.maxPerDay})`\n );\n }\n }\n\n /**\n * Record spending and persist to disk\n */\n private recordSpending(amount: number): void {\n this.todaySpending += amount;\n this.saveSpending();\n }\n\n // --- Config & Wallet Management ---\n\n private loadConfig(): ClientConfig {\n const configPath = join(this.configDir, 'config.json');\n if (existsSync(configPath)) {\n const content = readFileSync(configPath, 'utf-8');\n return { ...DEFAULT_CONFIG, ...JSON.parse(content) };\n }\n return { ...DEFAULT_CONFIG };\n }\n\n private saveConfig(): void {\n mkdirSync(this.configDir, { recursive: true });\n const configPath = join(this.configDir, 'config.json');\n writeFileSync(configPath, JSON.stringify(this.config, null, 2));\n }\n\n /**\n * Load spending data from disk\n */\n private loadSpending(): void {\n const spendingPath = join(this.configDir, 'spending.json');\n if (existsSync(spendingPath)) {\n try {\n const data = JSON.parse(readFileSync(spendingPath, 'utf-8'));\n const today = new Date().setHours(0, 0, 0, 0);\n \n // Only load if it's from today\n if (data.date && data.date === today) {\n this.todaySpending = data.amount || 0;\n this.lastSpendingReset = data.date;\n } else {\n // Data is from a previous day, reset\n this.todaySpending = 0;\n this.lastSpendingReset = today;\n }\n } catch {\n // Ignore parse errors, start fresh\n this.todaySpending = 0;\n this.lastSpendingReset = new Date().setHours(0, 0, 0, 0);\n }\n }\n }\n\n /**\n * Save spending data to disk\n */\n private saveSpending(): void {\n mkdirSync(this.configDir, { recursive: true });\n const spendingPath = join(this.configDir, 'spending.json');\n const data = {\n date: this.lastSpendingReset || new Date().setHours(0, 0, 0, 0),\n amount: this.todaySpending,\n updatedAt: Date.now(),\n };\n writeFileSync(spendingPath, JSON.stringify(data, null, 2));\n }\n\n private loadWallet(): WalletData | null {\n const walletPath = join(this.configDir, 'wallet.json');\n if (existsSync(walletPath)) {\n // POSIX-only: Windows reports synthesized mode bits and chmod can't\n // express NTFS ACLs, so the check is meaningless there.\n if (process.platform !== 'win32') {\n try {\n const stats = statSync(walletPath);\n const mode = stats.mode & 0o777;\n if (mode !== 0o600) {\n console.warn(`[MoltsPay] WARNING: wallet.json has insecure permissions (${mode.toString(8)})`);\n console.warn(`[MoltsPay] Fixing permissions to 0600...`);\n chmodSync(walletPath, 0o600);\n }\n } catch {\n /* ignored */\n }\n }\n\n const content = readFileSync(walletPath, 'utf-8');\n return JSON.parse(content);\n }\n return null;\n }\n\n /**\n * Initialize a new wallet (called by CLI)\n */\n static init(\n configDir: string,\n options: { chain: string; maxPerTx: number; maxPerDay: number }\n ): { address: string; configDir: string } {\n mkdirSync(configDir, { recursive: true });\n\n // Create wallet\n const wallet = Wallet.createRandom();\n const walletData: WalletData = {\n address: wallet.address,\n privateKey: wallet.privateKey,\n createdAt: Date.now(),\n };\n\n // Save wallet with secure permissions (0o600 = owner read/write only)\n const walletPath = join(configDir, 'wallet.json');\n writeFileSync(walletPath, JSON.stringify(walletData, null, 2), { mode: 0o600 });\n\n // Save config\n const config: ClientConfig = {\n chain: options.chain,\n limits: {\n maxPerTx: options.maxPerTx,\n maxPerDay: options.maxPerDay,\n },\n };\n const configPath = join(configDir, 'config.json');\n writeFileSync(configPath, JSON.stringify(config, null, 2));\n\n return { address: wallet.address, configDir };\n }\n\n /**\n * Get wallet balance (USDC, USDT, and native token) on default chain\n */\n async getBalance(): Promise<{ usdc: number; usdt: number; native: number }> {\n if (!this.wallet) {\n throw new Error('Client not initialized');\n }\n\n let chain;\n try {\n chain = getChain(this.config.chain as EvmChainName);\n } catch {\n throw new Error(`Unknown chain: ${this.config.chain}`);\n }\n\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n const tokenAbi = ['function balanceOf(address) view returns (uint256)'];\n\n // Get all balances in parallel\n const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([\n provider.getBalance(this.wallet.address),\n new ethers.Contract(chain.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),\n new ethers.Contract(chain.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address),\n ]);\n\n return {\n usdc: parseFloat(ethers.formatUnits(usdcBalance, chain.tokens.USDC.decimals)),\n usdt: parseFloat(ethers.formatUnits(usdtBalance, chain.tokens.USDT.decimals)),\n native: parseFloat(ethers.formatEther(nativeBalance)),\n };\n }\n\n /**\n * Get wallet balances on all supported chains (Base + Polygon + Tempo)\n */\n async getAllBalances(): Promise<Record<string, { usdc: number; usdt: number; native: number; tempo?: { pathUSD: number; alphaUSD: number; betaUSD: number; thetaUSD: number } }>> {\n if (!this.wallet) {\n throw new Error('Client not initialized');\n }\n\n const supportedChains: EvmChainName[] = ['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'bnb', 'bnb_testnet'];\n const tokenAbi = ['function balanceOf(address) view returns (uint256)'];\n const results: Record<string, { usdc: number; usdt: number; native: number; tempo?: { pathUSD: number; alphaUSD: number; betaUSD: number; thetaUSD: number } }> = {};\n\n // Tempo testnet token addresses\n const tempoTokens = {\n pathUSD: '0x20c0000000000000000000000000000000000000',\n alphaUSD: '0x20c0000000000000000000000000000000000001',\n betaUSD: '0x20c0000000000000000000000000000000000002',\n thetaUSD: '0x20c0000000000000000000000000000000000003',\n };\n\n // Query all chains in parallel\n await Promise.all(\n supportedChains.map(async (chainName) => {\n try {\n const chain = getChain(chainName);\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n\n if (chainName === 'tempo_moderato') {\n // Tempo: fetch all 4 testnet tokens\n const [nativeBalance, pathUSD, alphaUSD, betaUSD, thetaUSD] = await Promise.all([\n provider.getBalance(this.wallet!.address),\n new ethers.Contract(tempoTokens.pathUSD, tokenAbi, provider).balanceOf(this.wallet!.address),\n new ethers.Contract(tempoTokens.alphaUSD, tokenAbi, provider).balanceOf(this.wallet!.address),\n new ethers.Contract(tempoTokens.betaUSD, tokenAbi, provider).balanceOf(this.wallet!.address),\n new ethers.Contract(tempoTokens.thetaUSD, tokenAbi, provider).balanceOf(this.wallet!.address),\n ]);\n\n results[chainName] = {\n usdc: parseFloat(ethers.formatUnits(pathUSD, 6)), // pathUSD as default USDC\n usdt: parseFloat(ethers.formatUnits(alphaUSD, 6)), // alphaUSD as default USDT\n native: parseFloat(ethers.formatEther(nativeBalance)),\n tempo: {\n pathUSD: parseFloat(ethers.formatUnits(pathUSD, 6)),\n alphaUSD: parseFloat(ethers.formatUnits(alphaUSD, 6)),\n betaUSD: parseFloat(ethers.formatUnits(betaUSD, 6)),\n thetaUSD: parseFloat(ethers.formatUnits(thetaUSD, 6)),\n },\n };\n } else {\n // Other chains: fetch USDC and USDT\n const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([\n provider.getBalance(this.wallet!.address),\n new ethers.Contract(chain.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet!.address),\n new ethers.Contract(chain.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet!.address),\n ]);\n\n results[chainName] = {\n usdc: parseFloat(ethers.formatUnits(usdcBalance, chain.tokens.USDC.decimals)),\n usdt: parseFloat(ethers.formatUnits(usdtBalance, chain.tokens.USDT.decimals)),\n native: parseFloat(ethers.formatEther(nativeBalance)),\n };\n }\n } catch (err) {\n // If chain query fails, show zeros\n results[chainName] = { usdc: 0, usdt: 0, native: 0 };\n }\n })\n );\n\n return results;\n }\n\n /**\n * Pay for a service using MPP (Machine Payments Protocol)\n * \n * This implements the MPP flow manually for EOA wallets:\n * 1. Request service → get 402 with WWW-Authenticate\n * 2. Parse payment requirements\n * 3. Execute transfer on Tempo chain\n * 4. Retry with transaction hash as credential\n * \n * @param url - Full URL of the MPP-enabled endpoint\n * @param options - Request options (body, headers)\n * @returns Response from the service\n */\n async payWithMPP(\n url: string,\n options: {\n body?: any;\n headers?: Record<string, string>;\n } = {}\n ): Promise<any> {\n if (!this.wallet || !this.walletData) {\n throw new Error('Client not initialized. Run: npx moltspay init');\n }\n\n // Dynamic imports for ESM-only packages\n const { privateKeyToAccount } = await import('viem/accounts');\n const { createWalletClient, createPublicClient, http } = await import('viem');\n const { tempoModerato } = await import('viem/chains');\n const { Actions } = await import('viem/tempo');\n\n // Get private key from wallet data\n const privateKey = this.walletData.privateKey as `0x${string}`;\n const account = privateKeyToAccount(privateKey);\n\n console.log(`[MoltsPay] Making MPP request to: ${url}`);\n console.log(`[MoltsPay] Using account: ${account.address}`);\n\n // Step 1: Initial request to get 402 with payment requirements\n const initResponse = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n });\n\n // If not 402, handle directly\n if (initResponse.status !== 402) {\n if (initResponse.ok) {\n return initResponse.json();\n }\n const errorText = await initResponse.text();\n throw new Error(`Request failed (${initResponse.status}): ${errorText}`);\n }\n\n // Step 2: Parse WWW-Authenticate header\n const wwwAuth = initResponse.headers.get('www-authenticate');\n if (!wwwAuth || !wwwAuth.toLowerCase().includes('payment')) {\n throw new Error('No WWW-Authenticate Payment challenge in 402 response');\n }\n\n console.log(`[MoltsPay] Got 402, parsing payment challenge...`);\n\n // Parse WWW-Authenticate: Payment id=\"...\", method=\"tempo\", request=\"...\"\n const parseAuthParam = (header: string, key: string): string | null => {\n const match = header.match(new RegExp(`${key}=\"([^\"]+)\"`, 'i'));\n return match ? match[1] : null;\n };\n\n const challengeId = parseAuthParam(wwwAuth, 'id');\n const method = parseAuthParam(wwwAuth, 'method');\n const realm = parseAuthParam(wwwAuth, 'realm');\n const requestB64 = parseAuthParam(wwwAuth, 'request');\n\n if (method !== 'tempo') {\n throw new Error(`Unsupported payment method: ${method}`);\n }\n\n if (!requestB64) {\n throw new Error('Missing request in WWW-Authenticate');\n }\n\n // Decode payment request\n const requestJson = Buffer.from(requestB64, 'base64').toString('utf-8');\n const paymentRequest = JSON.parse(requestJson);\n \n console.log(`[MoltsPay] Payment request:`, paymentRequest);\n\n const { amount, currency, recipient, methodDetails } = paymentRequest;\n const chainId = methodDetails?.chainId || 42431;\n\n // Step 3: Execute transfer on Tempo\n console.log(`[MoltsPay] Executing transfer on Tempo (chainId: ${chainId})...`);\n console.log(`[MoltsPay] Amount: ${amount}, To: ${recipient}`);\n\n // Create viem client for Tempo (with feeToken for gas-free transactions)\n const tempoChain = { ...tempoModerato, feeToken: currency as `0x${string}` };\n \n const publicClient = createPublicClient({\n chain: tempoChain,\n transport: http('https://rpc.moderato.tempo.xyz'),\n });\n\n const walletClient = createWalletClient({\n account,\n chain: tempoChain,\n transport: http('https://rpc.moderato.tempo.xyz'),\n });\n\n // Use viem's Tempo Actions for TIP-20 transfer\n const txHash = await Actions.token.transfer(walletClient, {\n to: recipient as `0x${string}`,\n amount: BigInt(amount),\n token: currency as `0x${string}`,\n });\n\n console.log(`[MoltsPay] Transaction sent: ${txHash}`);\n\n // Wait for confirmation\n console.log(`[MoltsPay] Waiting for confirmation...`);\n await publicClient.waitForTransactionReceipt({ hash: txHash });\n console.log(`[MoltsPay] Transaction confirmed!`);\n\n // Step 4: Build credential and retry\n const challenge = {\n id: challengeId,\n realm,\n method: 'tempo',\n intent: 'charge',\n request: paymentRequest,\n };\n\n const credential = {\n challenge,\n payload: { hash: txHash, type: 'hash' },\n source: `did:pkh:eip155:${chainId}:${account.address}`,\n };\n\n const credentialB64 = Buffer.from(JSON.stringify(credential))\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, ''); // base64url without padding\n\n console.log(`[MoltsPay] Retrying with payment credential...`);\n\n // Retry with credential\n const paidResponse = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Payment ${credentialB64}`,\n ...options.headers,\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n });\n\n if (!paidResponse.ok) {\n const errorText = await paidResponse.text();\n throw new Error(`Payment verification failed (${paidResponse.status}): ${errorText}`);\n }\n\n console.log(`[MoltsPay] Payment verified! Service completed.`);\n return paidResponse.json();\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName, EvmChainName, TokenSymbol } from '../types/index.js';\n\nexport const CHAINS: Record<EvmChainName, 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 // ============ BNB Chain Testnet ============\n bnb_testnet: {\n name: 'BNB Testnet',\n chainId: 97,\n rpc: 'https://data-seed-prebsc-1-s1.binance.org:8545',\n tokens: {\n // Note: BNB uses 18 decimals for stablecoins (unlike Base/Polygon which use 6)\n // Using official Binance-Peg testnet tokens\n USDC: {\n address: '0x64544969ed7EBf5f083679233325356EbE738930', // Testnet USDC\n decimals: 18,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0x337610d27c682E347C9cD60BD4b3b107C9d34dDd', // Testnet USDT\n decimals: 18,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x64544969ed7EBf5f083679233325356EbE738930',\n explorer: 'https://testnet.bscscan.com/address/',\n explorerTx: 'https://testnet.bscscan.com/tx/',\n avgBlockTime: 3,\n // BNB-specific: requires approval for pay-for-success flow\n requiresApproval: true,\n },\n // ============ BNB Chain Mainnet ============\n bnb: {\n name: 'BNB Smart Chain',\n chainId: 56,\n rpc: 'https://bsc-dataseed.binance.org',\n tokens: {\n // Note: BNB uses 18 decimals for stablecoins\n USDC: {\n address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n decimals: 18,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0x55d398326f99059fF775485246999027B3197955',\n decimals: 18,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n explorer: 'https://bscscan.com/address/',\n explorerTx: 'https://bscscan.com/tx/',\n avgBlockTime: 3,\n // BNB-specific: requires approval for pay-for-success flow\n requiresApproval: true,\n },\n};\n\n/**\n * Get token address for a chain\n */\nexport function getTokenAddress(chainName: EvmChainName, 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: EvmChainName, 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: EvmChainName): 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 EVM chains\n */\nexport function listChains(): EvmChainName[] {\n return Object.keys(CHAINS) as EvmChainName[];\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, EvmChainName, TokenSymbol };\n","/**\n * Solana Wallet Management\n * \n * Separate from EVM wallets - uses ed25519 keypairs.\n * Stored in ~/.moltspay/wallet-solana.json\n */\n\nimport { Keypair, PublicKey, Connection, LAMPORTS_PER_SOL } from '@solana/web3.js';\nimport { getAssociatedTokenAddress, getAccount } from '@solana/spl-token';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport bs58 from 'bs58';\nimport { getSolanaConnection, getUSDCMint, type SolanaChainName } from '../chains/solana.js';\n\nconst DEFAULT_CONFIG_DIR = join(homedir(), '.moltspay');\nconst SOLANA_WALLET_FILE = 'wallet-solana.json';\n\nexport interface SolanaWalletData {\n publicKey: string; // Base58 encoded\n secretKey: string; // Base58 encoded (should be encrypted in production)\n createdAt: string;\n}\n\n/**\n * Get the path to the Solana wallet file\n */\nexport function getSolanaWalletPath(configDir: string = DEFAULT_CONFIG_DIR): string {\n return join(configDir, SOLANA_WALLET_FILE);\n}\n\n/**\n * Check if Solana wallet exists\n */\nexport function solanaWalletExists(configDir: string = DEFAULT_CONFIG_DIR): boolean {\n return existsSync(getSolanaWalletPath(configDir));\n}\n\n/**\n * Load existing Solana wallet\n */\nexport function loadSolanaWallet(configDir: string = DEFAULT_CONFIG_DIR): Keypair | null {\n const walletPath = getSolanaWalletPath(configDir);\n \n if (!existsSync(walletPath)) {\n return null;\n }\n \n try {\n const data: SolanaWalletData = JSON.parse(readFileSync(walletPath, 'utf-8'));\n const secretKey = bs58.decode(data.secretKey);\n return Keypair.fromSecretKey(secretKey);\n } catch (error) {\n console.error('Failed to load Solana wallet:', error);\n return null;\n }\n}\n\n/**\n * Create new Solana wallet\n */\nexport function createSolanaWallet(configDir: string = DEFAULT_CONFIG_DIR): Keypair {\n // Ensure config directory exists\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n \n const keypair = Keypair.generate();\n const data: SolanaWalletData = {\n publicKey: keypair.publicKey.toBase58(),\n secretKey: bs58.encode(keypair.secretKey),\n createdAt: new Date().toISOString(),\n };\n \n const walletPath = getSolanaWalletPath(configDir);\n writeFileSync(walletPath, JSON.stringify(data, null, 2));\n \n return keypair;\n}\n\n/**\n * Get Solana wallet address (public key as Base58)\n */\nexport function getSolanaAddress(configDir: string = DEFAULT_CONFIG_DIR): string | null {\n const wallet = loadSolanaWallet(configDir);\n return wallet?.publicKey.toBase58() || null;\n}\n\n/**\n * Get SOL balance (native token for gas)\n */\nexport async function getSolanaBalance(\n address: string,\n chain: SolanaChainName\n): Promise<number> {\n const connection = getSolanaConnection(chain);\n const pubkey = new PublicKey(address);\n \n const balance = await connection.getBalance(pubkey);\n return balance / LAMPORTS_PER_SOL;\n}\n\n/**\n * Get USDC balance on Solana\n */\nexport async function getSolanaUSDCBalance(\n address: string,\n chain: SolanaChainName\n): Promise<number> {\n const connection = getSolanaConnection(chain);\n const owner = new PublicKey(address);\n const mint = getUSDCMint(chain);\n \n try {\n const ata = await getAssociatedTokenAddress(mint, owner);\n const account = await getAccount(connection, ata);\n // USDC has 6 decimals on Solana\n return Number(account.amount) / 1e6;\n } catch (error: any) {\n // Account doesn't exist = 0 balance\n if (error.name === 'TokenAccountNotFoundError' || \n error.message?.includes('could not find account')) {\n return 0;\n }\n throw error;\n }\n}\n\n/**\n * Get all Solana balances (SOL + USDC)\n */\nexport async function getSolanaBalances(\n address: string,\n chain: SolanaChainName\n): Promise<{ sol: number; usdc: number }> {\n const [sol, usdc] = await Promise.all([\n getSolanaBalance(address, chain),\n getSolanaUSDCBalance(address, chain),\n ]);\n \n return { sol, usdc };\n}\n\n/**\n * Request SOL airdrop (devnet only)\n */\nexport async function requestSolanaAirdrop(\n address: string,\n chain: SolanaChainName,\n amount: number = 1\n): Promise<string> {\n if (chain !== 'solana_devnet') {\n throw new Error('Airdrop only available on devnet');\n }\n \n const connection = getSolanaConnection(chain);\n const pubkey = new PublicKey(address);\n \n const signature = await connection.requestAirdrop(\n pubkey,\n amount * LAMPORTS_PER_SOL\n );\n \n // Wait for confirmation\n await connection.confirmTransaction(signature, 'confirmed');\n \n return signature;\n}\n\n/**\n * Validate Solana address format\n */\nexport function isValidSolanaAddress(address: string): boolean {\n try {\n new PublicKey(address);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * Solana Chain Configuration\n * \n * Solana is NOT an EVM chain - uses different:\n * - Key format: ed25519 (EdDSA) vs secp256k1 (ECDSA)\n * - Address format: Base58 vs 0x hex\n * - Token standard: SPL vs ERC-20\n */\n\nimport { Connection, PublicKey } from '@solana/web3.js';\n\nexport interface SolanaChainConfig {\n name: string;\n cluster: 'mainnet-beta' | 'devnet' | 'testnet';\n rpc: string;\n explorer: string;\n explorerTx: string;\n tokens: {\n USDC: {\n mint: string;\n decimals: number;\n };\n };\n}\n\nexport type SolanaChainName = 'solana' | 'solana_devnet';\n\nexport const SOLANA_CHAINS: Record<SolanaChainName, SolanaChainConfig> = {\n solana: {\n name: 'Solana Mainnet',\n cluster: 'mainnet-beta',\n rpc: 'https://api.mainnet-beta.solana.com',\n explorer: 'https://solscan.io/account/',\n explorerTx: 'https://solscan.io/tx/',\n tokens: {\n USDC: {\n mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // Circle official USDC\n decimals: 6,\n },\n },\n },\n solana_devnet: {\n name: 'Solana Devnet',\n cluster: 'devnet',\n rpc: 'https://api.devnet.solana.com',\n explorer: 'https://solscan.io/account/',\n explorerTx: 'https://solscan.io/tx/',\n tokens: {\n USDC: {\n // Circle's devnet USDC (if not available, we'll deploy our own test token)\n mint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n decimals: 6,\n },\n },\n },\n};\n\n/**\n * Get Solana RPC connection\n */\nexport function getSolanaConnection(chain: SolanaChainName): Connection {\n const config = SOLANA_CHAINS[chain];\n return new Connection(config.rpc, 'confirmed');\n}\n\n/**\n * Get USDC mint public key for a Solana chain\n */\nexport function getUSDCMint(chain: SolanaChainName): PublicKey {\n return new PublicKey(SOLANA_CHAINS[chain].tokens.USDC.mint);\n}\n\n/**\n * Get Solana chain config\n */\nexport function getSolanaChain(name: SolanaChainName): SolanaChainConfig {\n const config = SOLANA_CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported Solana chain: ${name}. Supported: ${Object.keys(SOLANA_CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * Check if a chain name is a Solana chain\n */\nexport function isSolanaChain(chain: string): chain is SolanaChainName {\n return chain === 'solana' || chain === 'solana_devnet';\n}\n\n/**\n * Get explorer URL for a Solana address\n */\nexport function getSolanaExplorerUrl(chain: SolanaChainName, address: string): string {\n const config = SOLANA_CHAINS[chain];\n const clusterParam = chain === 'solana_devnet' ? '?cluster=devnet' : '';\n return `${config.explorer}${address}${clusterParam}`;\n}\n\n/**\n * Get explorer URL for a Solana transaction\n */\nexport function getSolanaTxExplorerUrl(chain: SolanaChainName, signature: string): string {\n const config = SOLANA_CHAINS[chain];\n const clusterParam = chain === 'solana_devnet' ? '?cluster=devnet' : '';\n return `${config.explorerTx}${signature}${clusterParam}`;\n}\n","/**\n * Solana Facilitator\n * \n * Pay-for-success payment settlement for Solana SPL token transfers.\n * Unlike EVM chains, Solana doesn't have a third-party facilitator - \n * we verify and settle directly on-chain.\n * \n * Flow:\n * 1. Client signs a SPL token transfer authorization\n * 2. Server receives the signed transaction\n * 3. Server verifies the signature and amount\n * 4. Server submits the transaction to settle payment\n */\n\nimport { \n Connection, \n PublicKey, \n Transaction,\n VersionedTransaction,\n sendAndConfirmTransaction,\n Keypair,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n createTransferCheckedInstruction,\n getAccount,\n createAssociatedTokenAccountInstruction,\n TOKEN_PROGRAM_ID,\n} from '@solana/spl-token';\nimport { \n BaseFacilitator, \n type X402PaymentPayload, \n type X402PaymentRequirements,\n type VerifyResult,\n type SettleResult,\n type HealthCheckResult,\n} from './interface.js';\nimport { SOLANA_CHAINS, type SolanaChainName } from '../chains/solana.js';\n\n/**\n * Solana payment payload structure\n */\nexport interface SolanaPaymentPayload {\n /** Base58 encoded signed transaction */\n signedTransaction: string;\n /** Sender's public key (Base58) */\n sender: string;\n /** Chain: solana or solana_devnet */\n chain: SolanaChainName;\n}\n\n/**\n * Solana Facilitator configuration\n */\nexport interface SolanaFacilitatorConfig {\n /** Optional fee payer keypair for gasless transactions */\n feePayerKeypair?: Keypair;\n}\n\n/**\n * Solana Facilitator for pay-for-success payments\n * \n * Supports gasless mode: if feePayerKeypair is provided, server pays tx fees\n */\nexport class SolanaFacilitator extends BaseFacilitator {\n readonly name = 'solana';\n readonly displayName = 'Solana Direct';\n readonly supportedNetworks = ['solana:mainnet', 'solana:devnet'];\n\n private connections: Map<SolanaChainName, Connection> = new Map();\n private feePayerKeypair?: Keypair;\n\n constructor(config?: SolanaFacilitatorConfig) {\n super();\n this.feePayerKeypair = config?.feePayerKeypair;\n \n // Initialize connections\n for (const [chain, config] of Object.entries(SOLANA_CHAINS)) {\n this.connections.set(\n chain as SolanaChainName, \n new Connection(config.rpc, 'confirmed')\n );\n }\n \n if (this.feePayerKeypair) {\n console.log(`[SolanaFacilitator] Gasless mode enabled. Fee payer: ${this.feePayerKeypair.publicKey.toBase58()}`);\n }\n }\n \n /**\n * Get fee payer public key (for gasless transactions)\n */\n getFeePayerPubkey(): string | null {\n return this.feePayerKeypair?.publicKey.toBase58() || null;\n }\n\n private getConnection(chain: SolanaChainName): Connection {\n const conn = this.connections.get(chain);\n if (!conn) {\n throw new Error(`No connection for chain: ${chain}`);\n }\n return conn;\n }\n\n /**\n * Convert our chain name to network identifier\n */\n static chainToNetwork(chain: SolanaChainName): string {\n return chain === 'solana' ? 'solana:mainnet' : 'solana:devnet';\n }\n\n /**\n * Convert network identifier to chain name\n */\n static networkToChain(network: string): SolanaChainName | null {\n if (network === 'solana:mainnet') return 'solana';\n if (network === 'solana:devnet') return 'solana_devnet';\n return null;\n }\n\n async healthCheck(): Promise<HealthCheckResult> {\n const start = Date.now();\n try {\n // Check devnet connection\n const conn = this.getConnection('solana_devnet');\n await conn.getSlot();\n return {\n healthy: true,\n latencyMs: Date.now() - start,\n };\n } catch (error: any) {\n return {\n healthy: false,\n error: error.message,\n };\n }\n }\n\n /**\n * Verify a Solana payment\n * \n * Checks:\n * 1. Transaction is valid and properly signed\n * 2. Transfer instruction matches expected amount and recipient\n */\n async verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult> {\n try {\n const solanaPayload = paymentPayload.payload as SolanaPaymentPayload;\n if (!solanaPayload || !solanaPayload.signedTransaction) {\n return { valid: false, error: 'Missing signed transaction' };\n }\n\n const chain = solanaPayload.chain || 'solana_devnet';\n const chainConfig = SOLANA_CHAINS[chain];\n if (!chainConfig) {\n return { valid: false, error: `Invalid chain: ${chain}` };\n }\n\n // Decode the transaction\n const txBuffer = Buffer.from(solanaPayload.signedTransaction, 'base64');\n let tx: Transaction | VersionedTransaction;\n \n try {\n // Try legacy transaction first\n tx = Transaction.from(txBuffer);\n } catch {\n // Try versioned transaction\n tx = VersionedTransaction.deserialize(txBuffer);\n }\n\n // Verify at least one signature exists (may be partial in gasless mode)\n if (tx instanceof Transaction) {\n // In gasless mode, fee payer signature is added by server\n // Client only signs for token transfer authority\n const hasAnySignature = tx.signatures.some(sig => \n sig.signature && !sig.signature.every(b => b === 0)\n );\n if (!hasAnySignature) {\n return { valid: false, error: 'Transaction not signed' };\n }\n }\n\n // Parse expected values from requirements\n const expectedAmount = BigInt(requirements.amount);\n const expectedRecipient = new PublicKey(requirements.payTo);\n\n // For now, we trust the transaction structure\n // Full verification happens at settlement time\n return {\n valid: true,\n details: {\n chain,\n sender: solanaPayload.sender,\n recipient: requirements.payTo,\n amount: requirements.amount,\n },\n };\n } catch (error: any) {\n return { valid: false, error: error.message };\n }\n }\n\n /**\n * Settle a Solana payment\n * \n * Submits the signed transaction to the network.\n * In gasless mode, adds fee payer signature before submitting.\n */\n async settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult> {\n try {\n const solanaPayload = paymentPayload.payload as SolanaPaymentPayload;\n if (!solanaPayload || !solanaPayload.signedTransaction) {\n return { success: false, error: 'Missing signed transaction' };\n }\n\n const chain = solanaPayload.chain || 'solana_devnet';\n const connection = this.getConnection(chain);\n\n // Decode the transaction\n const txBuffer = Buffer.from(solanaPayload.signedTransaction, 'base64');\n \n let txToSend: Buffer;\n \n try {\n // Try legacy transaction\n const tx = Transaction.from(txBuffer);\n \n // Check if we need to add fee payer signature (gasless mode)\n if (this.feePayerKeypair && tx.feePayer) {\n const feePayerPubkey = this.feePayerKeypair.publicKey.toBase58();\n const txFeePayer = tx.feePayer.toBase58();\n \n if (txFeePayer === feePayerPubkey) {\n // Gasless mode: add fee payer signature\n console.log(`[SolanaFacilitator] Gasless mode: adding fee payer signature`);\n tx.partialSign(this.feePayerKeypair);\n }\n }\n \n txToSend = tx.serialize();\n } catch (e: any) {\n // Fall back to versioned transaction (no gasless support for versioned yet)\n txToSend = txBuffer;\n }\n\n // Send the transaction\n const signature = await connection.sendRawTransaction(txToSend, {\n skipPreflight: false,\n preflightCommitment: 'confirmed',\n });\n\n // Wait for confirmation\n const confirmation = await connection.confirmTransaction(signature, 'confirmed');\n \n if (confirmation.value.err) {\n return {\n success: false,\n error: `Transaction failed: ${JSON.stringify(confirmation.value.err)}`,\n transaction: signature,\n };\n }\n\n return {\n success: true,\n transaction: signature,\n status: 'confirmed',\n };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n }\n\n supportsNetwork(network: string): boolean {\n return this.supportedNetworks.includes(network);\n }\n}\n\n/**\n * Create a Solana payment transaction for signing\n * \n * This is called by the client to create the transaction to sign.\n * \n * @param senderPubkey - The sender's public key (token owner)\n * @param recipientPubkey - The recipient's public key\n * @param amount - Amount in token base units\n * @param chain - Solana chain (solana or solana_devnet)\n * @param feePayerPubkey - Optional fee payer public key for gasless transactions\n */\nexport async function createSolanaPaymentTransaction(\n senderPubkey: PublicKey,\n recipientPubkey: PublicKey,\n amount: bigint,\n chain: SolanaChainName,\n feePayerPubkey?: PublicKey,\n): Promise<Transaction> {\n const chainConfig = SOLANA_CHAINS[chain];\n const connection = new Connection(chainConfig.rpc, 'confirmed');\n const mint = new PublicKey(chainConfig.tokens.USDC.mint);\n\n // Determine who pays fees (gasless mode uses server's fee payer)\n const actualFeePayer = feePayerPubkey || senderPubkey;\n\n // Get ATAs\n const senderATA = await getAssociatedTokenAddress(mint, senderPubkey);\n const recipientATA = await getAssociatedTokenAddress(mint, recipientPubkey);\n\n const transaction = new Transaction();\n\n // Check if recipient ATA exists\n try {\n await getAccount(connection, recipientATA);\n } catch {\n // Create ATA for recipient (fee payer pays rent in gasless mode)\n transaction.add(\n createAssociatedTokenAccountInstruction(\n actualFeePayer, // payer (fee payer in gasless mode)\n recipientATA, // ata to create\n recipientPubkey, // owner\n mint // mint\n )\n );\n }\n\n // Add transfer instruction\n transaction.add(\n createTransferCheckedInstruction(\n senderATA, // source\n mint, // mint\n recipientATA, // destination\n senderPubkey, // owner (sender still authorizes the transfer)\n amount, // amount\n chainConfig.tokens.USDC.decimals // decimals\n )\n );\n\n // Get recent blockhash\n const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();\n transaction.recentBlockhash = blockhash;\n transaction.feePayer = actualFeePayer;\n\n return transaction;\n}\n\nexport default SolanaFacilitator;\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 * MoltsPay Client Types\n */\n\n// Client configuration (stored in ~/.moltspay/)\nexport interface ClientConfig {\n chain: string;\n limits: {\n maxPerTx: number;\n maxPerDay: number;\n };\n}\n\n// Wallet data (stored in ~/.moltspay/wallet.json)\nexport interface WalletData {\n address: string;\n privateKey: string;\n createdAt: number;\n}\n\n// Payment response from server\nexport interface PaymentRequired {\n message: string;\n payment: {\n chargeId: string;\n service: string;\n amount: number;\n currency: string;\n wallet: string;\n chain: string;\n expiresAt: number;\n };\n}\n\n// Service info from server\nexport interface ServiceInfo {\n id: string;\n name: string;\n description?: string;\n price: number;\n currency: string;\n input: Record<string, any>;\n output: Record<string, any>;\n available: boolean;\n provider?: ProviderInfo; // For marketplace listings\n endpoint?: string; // Custom endpoint path (e.g., for Cloudflare Workers)\n}\n\n// Provider info from server\nexport interface ProviderInfo {\n name: string;\n username?: string;\n description?: string;\n wallet: string;\n chain?: string;\n chains?: string[] | { chain: string }[]; // Multi-chain support\n}\n\n// Services response from server\nexport interface ServicesResponse {\n provider?: ProviderInfo; // Optional for marketplace listings\n services: ServiceInfo[];\n}\n\n// Verify response from server\nexport interface VerifyResponse {\n status: string;\n chargeId: string;\n txHash: string;\n result: Record<string, any>;\n}\n\n// Client options\nexport interface MoltsPayClientOptions {\n configDir?: string; // Default: ~/.moltspay\n}\n","/**\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 // BNB Smart Chain mainnet\n 'eip155:56': {\n USDC: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n USDT: '0x55d398326f99059fF775485246999027B3197955',\n },\n // BNB Smart Chain testnet\n 'eip155:97': {\n USDC: '0x64544969ed7EBf5f083679233325356EbE738930',\n USDT: '0x337610d27c682E347C9cD60BD4b3b107C9d34dDd',\n },\n // Solana networks use mint addresses (SPL tokens)\n 'solana:mainnet': {\n USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // Circle USDC\n },\n 'solana:devnet': {\n USDC: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU', // Devnet USDC\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 'bnb': 'eip155:56',\n 'bnb_testnet': 'eip155:97',\n 'solana': 'solana:mainnet',\n 'solana_devnet': 'solana:devnet',\n};\n\n// Helper to check if a network is Solana\nfunction isSolanaNetwork(network: string): boolean {\n return network.startsWith('solana:');\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 // BNB Smart Chain mainnet\n 'eip155:56': {\n USDC: { name: 'USD Coin', version: '1' },\n USDT: { name: 'Tether USD', version: '1' },\n },\n // BNB Smart Chain testnet\n 'eip155:97': {\n USDC: { name: 'USD Coin', version: '1' },\n USDT: { name: 'Tether USD', 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', 'bnb', and 'solana' in fallback for multi-chain support\n const defaultFallback = ['tempo', 'bnb', 'solana'];\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 // Helper to get the right wallet for a chain\n const getWalletForChain = (chainName: string, explicitWallet?: string): string => {\n // If explicit wallet provided (object format), use it\n if (explicitWallet) return explicitWallet;\n // For Solana chains, use solana_wallet if available\n if ((chainName === 'solana' || chainName === 'solana_devnet') && provider.solana_wallet) {\n return provider.solana_wallet;\n }\n // Default to EVM wallet\n return provider.wallet;\n };\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 const explicitWallet = typeof c === 'object' ? c.wallet : null;\n return {\n network: CHAIN_TO_NETWORK[chainName] || 'eip155:8453',\n wallet: getWalletForChain(chainName, explicitWallet || undefined),\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: getWalletForChain(chain),\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 const authHeader = req.headers[MPP_AUTH_HEADER] as string | undefined;\n return await this.handleProxy(body, paymentHeader, authHeader, 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 solana_wallet: this.manifest.provider.solana_wallet,\n chains: this.manifest.provider.chains,\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 // For Solana: settle FIRST (blockhash expires quickly ~60s)\n // For EVM: pay-for-success (execute first, settle after)\n const isSolana = isSolanaNetwork(paymentNetwork);\n let settlement: any = null;\n\n if (isSolana) {\n console.log(`[MoltsPay] Solana detected - settling payment FIRST (blockhash expiry protection)`);\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] Solana settlement failed:', err.message);\n return this.sendJson(res, 402, {\n error: 'Payment settlement failed',\n message: err.message,\n });\n }\n }\n\n // Execute skill (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 // For Solana: payment already settled, skill failed - no refund (user accepted risk)\n // For EVM: payment not settled yet, user keeps their money\n return this.sendJson(res, 500, {\n error: 'Service execution failed',\n message: err.message,\n paymentSettled: isSolana ? true : false,\n note: isSolana ? 'Payment was settled before execution. Contact support for refund.' : undefined,\n });\n }\n\n // For EVM: settle payment now (pay-for-success)\n if (!isSolana) {\n console.log(`[MoltsPay] Skill succeeded, settling payment...`);\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\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 const requirements: X402PaymentRequirements = {\n scheme: 'exact',\n network: selectedNetwork,\n asset: tokenAddress,\n amount: amountInUnits,\n payTo: selectedWallet,\n maxTimeoutSeconds: 300,\n extra: tokenDomain,\n };\n \n // For Solana: include fee payer pubkey if available (gasless mode)\n if (selectedNetwork === 'solana:mainnet' || selectedNetwork === 'solana:devnet') {\n const solanaFacilitator = this.registry.get('solana') as any;\n const feePayerPubkey = solanaFacilitator?.getFeePayerPubkey?.();\n if (feePayerPubkey) {\n (requirements.extra as any) = {\n ...(requirements.extra || {}),\n solanaFeePayer: feePayerPubkey,\n };\n }\n }\n \n // For BNB: include spender address for client approval\n if (selectedNetwork === 'eip155:56' || selectedNetwork === 'eip155:97') {\n const bnbFacilitator = this.registry.get('bnb') as any;\n const spenderAddress = bnbFacilitator?.getSpenderAddress?.();\n if (spenderAddress) {\n (requirements.extra as any) = {\n ...(requirements.extra || {}),\n bnbSpender: spenderAddress,\n };\n }\n }\n \n return requirements;\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, allow all (for testing/open mode)\n if (allowedIPs.length === 0) {\n return true;\n }\n \n // If '*' is in the list, allow all\n if (allowedIPs.includes('*')) {\n return true;\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/MPP 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 * For x402 (base, polygon, base_sepolia):\n * Without X-Payment header: returns 402 with X-Payment-Required\n * With X-Payment header: verifies payment via CDP\n * \n * For MPP (tempo_moderato):\n * Without Authorization header: returns 402 with WWW-Authenticate\n * With Authorization: Payment header: verifies tx on Tempo chain\n */\n private async handleProxy(\n body: any,\n paymentHeader: string | undefined,\n authHeader: 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 chain if provided\n const supportedChains = ['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'bnb', 'bnb_testnet', 'solana', 'solana_devnet'];\n if (chain && !supportedChains.includes(chain)) {\n return this.sendJson(res, 400, { error: `Unsupported chain: ${chain}. Supported: ${supportedChains.join(', ')}` });\n }\n\n // Validate wallet format based on chain\n const isSolanaChain = chain === 'solana' || chain === 'solana_devnet';\n const isValidEvmAddress = /^0x[a-fA-F0-9]{40}$/.test(wallet);\n const isValidSolanaAddress = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(wallet);\n \n if (isSolanaChain && !isValidSolanaAddress) {\n return this.sendJson(res, 400, { error: 'Invalid Solana wallet address format' });\n }\n if (!isSolanaChain && !isValidEvmAddress) {\n return this.sendJson(res, 400, { error: 'Invalid EVM 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 // 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 // ========== MPP Protocol for tempo_moderato ==========\n if (chain === 'tempo_moderato') {\n return await this.handleProxyMPP(body, proxyConfig, authHeader, res);\n }\n\n // ========== x402 Protocol for other chains ==========\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, handle skill + payment\n if (execute && 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 // For Solana: settle FIRST (blockhash expires quickly ~60s)\n // For EVM: pay-for-success (execute first, settle after)\n const isSolana = isSolanaNetwork(network);\n let settlement: any = null;\n\n if (isSolana) {\n console.log(`[MoltsPay] /proxy: Solana detected - settling payment FIRST`);\n try {\n settlement = await this.registry.settle(payment, requirements);\n console.log(`[MoltsPay] /proxy: Payment settled by ${settlement.facilitator}: ${settlement.transaction || 'pending'}`);\n \n // Check if settlement actually succeeded (registry returns {success: false} on failure)\n if (!settlement.success) {\n console.error(`[MoltsPay] /proxy: Solana settlement failed: ${settlement.error}`);\n return this.sendJson(res, 402, {\n success: false,\n paymentSettled: false,\n error: `Payment settlement failed: ${settlement.error || 'Unknown error'}`,\n });\n }\n } catch (err: any) {\n console.error('[MoltsPay] /proxy: Solana settlement failed:', err.message);\n return this.sendJson(res, 402, {\n success: false,\n paymentSettled: false,\n error: `Payment settlement failed: ${err.message}`,\n });\n }\n } else {\n console.log(`[MoltsPay] /proxy: Executing skill first (pay on success): ${service}`);\n }\n\n // Execute skill (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`);\n } catch (err: any) {\n // Skill failed or timeout\n console.error(`[MoltsPay] /proxy: Skill failed: ${err.message}`);\n // For Solana: payment already settled, skill failed - no refund (user accepted risk)\n // For EVM: payment not settled yet, user keeps their money\n return this.sendJson(res, 500, {\n success: false,\n paymentSettled: isSolana ? true : false,\n error: `Service execution failed: ${err.message}`,\n note: isSolana ? 'Payment was settled before execution. Contact support for refund.' : undefined,\n });\n }\n\n // For EVM: settle payment now (pay-for-success)\n if (!isSolana) {\n console.log(`[MoltsPay] /proxy: Settling payment...`);\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,\n paidTo: wallet,\n amount: amountNum,\n currency: currency || 'USDC',\n memo,\n result,\n });\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,\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 * Handle MPP payment flow for /proxy endpoint (tempo_moderato chain)\n */\n private async handleProxyMPP(\n body: any,\n config: ServiceConfig,\n authHeader: string | undefined,\n res: ServerResponse\n ): Promise<void> {\n const { wallet, amount, memo, serviceId } = body;\n const amountNum = parseFloat(amount);\n const amountInUnits = Math.floor(amountNum * 1e6).toString();\n \n // If no Authorization header, return 402 with WWW-Authenticate\n if (!authHeader || !authHeader.toLowerCase().startsWith('payment ')) {\n const challengeId = this.generateChallengeId();\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: 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 const wwwAuth = `Payment id=\"${challengeId}\", realm=\"MoltsPay Proxy\", method=\"tempo\", intent=\"charge\", request=\"${mppRequestEncoded}\", description=\"${config.name}\", expires=\"${expiresAt}\"`;\n \n res.writeHead(402, {\n 'Content-Type': 'application/problem+json',\n [MPP_WWW_AUTH_HEADER]: wwwAuth,\n });\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: serviceId || 'proxy',\n price: amountNum,\n currency: 'USDC',\n }, null, 2));\n return;\n }\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: { id: string; realm: string; method: string; intent: string; request: any };\n payload: { hash?: string; type: 'hash' | 'transaction' };\n source?: string;\n };\n \n try {\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] /proxy MPP: Failed to parse credential:', err);\n return this.sendJson(res, 400, { error: 'Invalid payment credential encoding' });\n }\n\n // Extract transaction hash\n let txHash: string | undefined;\n if (mppCredential.payload?.type === 'hash' && mppCredential.payload?.hash) {\n txHash = mppCredential.payload.hash;\n } else {\n return this.sendJson(res, 400, { error: 'Missing transaction hash in credential' });\n }\n\n console.log(`[MoltsPay] /proxy MPP: Verifying tx ${txHash} on Tempo...`);\n\n // Build requirements for verification\n const requirements = this.buildPaymentRequirements(config, 'eip155:42431', wallet, 'USDC');\n\n // Create x402-compatible payload for facilitator\n const paymentPayload: X402PaymentPayload = {\n x402Version: X402_VERSION,\n scheme: 'exact',\n network: 'eip155:42431',\n payload: { txHash, chainId: 42431 },\n };\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] /proxy MPP: Payment verified by ${verification.facilitator}`);\n\n // Check if execution requested\n const { execute, service, params } = body;\n \n if (execute && service) {\n console.log(`[MoltsPay] /proxy MPP: Executing skill: ${service}`);\n const skill = this.skills.get(service);\n if (!skill) {\n return this.sendJson(res, 404, {\n success: false,\n paymentSettled: true, // Payment already happened on Tempo\n error: `Service not found: ${service}`,\n });\n }\n\n // Execute skill\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 } catch (err: any) {\n console.error(`[MoltsPay] /proxy MPP: Skill failed: ${err.message}`);\n return this.sendJson(res, 500, {\n success: false,\n paymentSettled: true,\n error: `Service execution failed: ${err.message}`,\n });\n }\n\n return this.sendJson(res, 200, {\n success: true,\n verified: true,\n txHash,\n chain: 'tempo_moderato',\n paidTo: wallet,\n amount: amountNum,\n currency: 'USDC',\n facilitator: verification.facilitator,\n memo,\n result,\n });\n }\n\n // No execution requested - just return verification success\n this.sendJson(res, 200, {\n success: true,\n verified: true,\n txHash,\n chain: 'tempo_moderato',\n paidTo: wallet,\n amount: amountNum,\n currency: 'USDC',\n facilitator: verification.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 const requirements: X402PaymentRequirements = {\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 // For BNB: include spender address for client approval\n if (networkId === 'eip155:56' || networkId === 'eip155:97') {\n const bnbFacilitator = this.registry.get('bnb') as any;\n const spenderAddress = bnbFacilitator?.getSpenderAddress?.();\n if (spenderAddress) {\n (requirements.extra as any) = {\n ...(requirements.extra || {}),\n bnbSpender: spenderAddress,\n };\n }\n }\n\n return requirements;\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 Module\n * \n * Provides pluggable payment facilitator support for MoltsPay.\n * \n * @example\n * ```typescript\n * import { FacilitatorRegistry, CDPFacilitator } from 'moltspay/facilitators';\n * \n * // Use default CDP facilitator\n * const registry = new FacilitatorRegistry();\n * const result = await registry.verify(paymentPayload, requirements);\n * \n * // Or with custom config\n * const registry = new FacilitatorRegistry({\n * primary: 'cdp',\n * fallback: ['chaoschain'], // Coming in v0.9.0\n * strategy: 'failover',\n * config: {\n * cdp: { useMainnet: true }\n * }\n * });\n * ```\n */\n\n// Interface & types\nexport {\n Facilitator,\n BaseFacilitator,\n FacilitatorConfig,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n FacilitatorFee,\n} from './interface.js';\n\n// CDP Facilitator\nexport {\n CDPFacilitator,\n CDPFacilitatorConfig,\n} from './cdp.js';\n\n// Tempo Facilitator\nexport {\n TempoFacilitator,\n} from './tempo.js';\n\n// BNB Facilitator\nexport {\n BNBFacilitator,\n BNBPaymentIntent,\n createIntentTypedData,\n} from './bnb.js';\n\n// Solana Facilitator\nexport {\n SolanaFacilitator,\n createSolanaPaymentTransaction,\n type SolanaPaymentPayload,\n} from './solana.js';\n\n// Registry\nexport {\n FacilitatorRegistry,\n FacilitatorSelection,\n SelectionStrategy,\n getDefaultRegistry,\n createRegistry,\n} from './registry.js';\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 * 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 * BNB Chain Facilitator\n * \n * Handles pay-for-success payments on BNB Smart Chain.\n * \n * Flow:\n * 1. Client pre-approves server wallet (one-time, via `moltspay init`)\n * 2. Client signs EIP-712 intent (no gas, just signature)\n * 3. Server verifies intent signature\n * 4. Server executes service\n * 5. Success → Server calls transferFrom (server pays gas)\n * 6. Failure → No transfer, client keeps money\n * \n * Key difference from Tempo:\n * - Tempo: Client pays first → service might fail → money lost\n * - BNB: Service runs first → success = payment (pay-for-success)\n */\n\nimport {\n BaseFacilitator,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n} from './interface.js';\nimport { CHAINS, ChainConfig } from '../chains/index.js';\nimport { privateKeyToAccount } from 'viem/accounts';\n\n// ERC20 Transfer event signature\nconst TRANSFER_EVENT_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';\n\n// EIP-712 Domain\nconst EIP712_DOMAIN = {\n name: 'MoltsPay',\n version: '1',\n};\n\n// EIP-712 Types for Payment Intent\nconst INTENT_TYPES = {\n PaymentIntent: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n { name: 'token', type: 'address' },\n { name: 'service', type: 'string' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n};\n\n// ERC20 ABI (minimal)\nconst ERC20_ABI = {\n transfer: 'function transfer(address to, uint256 amount) returns (bool)',\n transferFrom: 'function transferFrom(address from, address to, uint256 amount) returns (bool)',\n allowance: 'function allowance(address owner, address spender) view returns (uint256)',\n balanceOf: 'function balanceOf(address account) view returns (uint256)',\n approve: 'function approve(address spender, uint256 amount) returns (bool)',\n};\n\n/**\n * BNB Payment Intent (signed by client)\n */\nexport interface BNBPaymentIntent {\n from: string;\n to: string;\n amount: string;\n token: string;\n service: string;\n nonce: number;\n deadline: number;\n signature: string;\n}\n\n/**\n * BNB Payment Payload (from client in x402 request)\n */\ninterface BNBPaymentPayload {\n intent: BNBPaymentIntent;\n chainId: number;\n}\n\n/**\n * BNB Chain Facilitator\n * \n * Handles pay-for-success payments on BNB mainnet (chainId 56) and testnet (chainId 97).\n * Server wallet executes transferFrom after successful service delivery.\n */\nexport class BNBFacilitator extends BaseFacilitator {\n readonly name = 'bnb';\n readonly displayName = 'BNB Smart Chain';\n readonly supportedNetworks = ['eip155:56', 'eip155:97']; // Mainnet + Testnet\n\n private serverPrivateKey: string;\n private spenderAddress: string | null = null;\n private chainConfigs: { [key: number]: { rpc: string; chain: ChainConfig } };\n\n constructor(serverPrivateKey?: string) {\n super();\n this.serverPrivateKey = serverPrivateKey || process.env.BNB_SERVER_PRIVATE_KEY || '';\n \n // Pre-compute spender address synchronously using viem\n if (this.serverPrivateKey) {\n const key = this.serverPrivateKey.startsWith('0x') \n ? this.serverPrivateKey as `0x${string}`\n : `0x${this.serverPrivateKey}` as `0x${string}`;\n const account = privateKeyToAccount(key);\n this.spenderAddress = account.address;\n }\n \n this.chainConfigs = {\n 56: { rpc: CHAINS.bnb.rpc, chain: CHAINS.bnb },\n 97: { rpc: CHAINS.bnb_testnet.rpc, chain: CHAINS.bnb_testnet },\n };\n }\n\n async healthCheck(): Promise<HealthCheckResult> {\n const start = Date.now();\n try {\n // Check mainnet\n const response = await fetch(this.chainConfigs[56].rpc, {\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 !== 56) {\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 /**\n * Verify a payment intent signature (before service execution)\n * \n * This verifies:\n * 1. Signature is valid for the intent\n * 2. Client has approved server wallet\n * 3. Client has sufficient balance\n * 4. Intent hasn't expired\n */\n async verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult> {\n try {\n const bnbPayload = paymentPayload.payload as BNBPaymentPayload;\n \n if (!bnbPayload?.intent) {\n return { valid: false, error: 'Missing intent in payment payload' };\n }\n\n const { intent, chainId } = bnbPayload;\n const config = this.chainConfigs[chainId];\n \n if (!config) {\n return { valid: false, error: `Unsupported chainId: ${chainId}` };\n }\n\n // Check deadline\n if (intent.deadline < Date.now()) {\n return { valid: false, error: 'Intent expired' };\n }\n\n // Verify signature\n const recoveredAddress = await this.recoverIntentSigner(intent, chainId);\n if (recoveredAddress.toLowerCase() !== intent.from.toLowerCase()) {\n return { valid: false, error: 'Invalid signature' };\n }\n\n // Verify recipient matches\n if (intent.to.toLowerCase() !== requirements.payTo.toLowerCase()) {\n return { valid: false, error: `Wrong recipient: ${intent.to}` };\n }\n\n // Verify amount matches\n if (BigInt(intent.amount) < BigInt(requirements.amount)) {\n return { valid: false, error: `Insufficient amount: ${intent.amount}` };\n }\n\n // Verify token matches\n if (intent.token.toLowerCase() !== requirements.asset.toLowerCase()) {\n return { valid: false, error: `Wrong token: ${intent.token}` };\n }\n\n // Check allowance\n const serverAddress = await this.getServerAddress();\n const allowance = await this.getAllowance(intent.from, serverAddress, intent.token, config.rpc);\n \n if (BigInt(allowance) < BigInt(intent.amount)) {\n return { valid: false, error: 'Insufficient allowance. Run: npx moltspay init --chain bnb' };\n }\n\n // Check balance\n const balance = await this.getBalance(intent.from, intent.token, config.rpc);\n if (BigInt(balance) < BigInt(intent.amount)) {\n return { valid: false, error: 'Insufficient balance' };\n }\n\n return { \n valid: true, \n details: {\n from: intent.from,\n to: intent.to,\n amount: intent.amount,\n token: intent.token,\n service: intent.service,\n nonce: intent.nonce,\n deadline: intent.deadline,\n }\n };\n } catch (error) {\n return { valid: false, error: `Verification failed: ${error}` };\n }\n }\n\n /**\n * Settle a payment by executing transferFrom\n * \n * This is called AFTER the service has been successfully delivered.\n * Server pays gas, transfers tokens from client to provider.\n */\n async settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult> {\n if (!this.serverPrivateKey) {\n return { success: false, error: 'Server wallet not configured (BNB_SERVER_PRIVATE_KEY)' };\n }\n\n try {\n // First verify the intent\n const verifyResult = await this.verify(paymentPayload, requirements);\n if (!verifyResult.valid) {\n return { success: false, error: verifyResult.error };\n }\n\n const bnbPayload = paymentPayload.payload as BNBPaymentPayload;\n const { intent, chainId } = bnbPayload;\n const config = this.chainConfigs[chainId];\n\n // Execute transferFrom\n const txHash = await this.executeTransferFrom(\n intent.from,\n intent.to,\n intent.amount,\n intent.token,\n config.rpc\n );\n\n return { \n success: true, \n transaction: txHash,\n status: 'settled'\n };\n } catch (error) {\n return { success: false, error: `Settlement failed: ${error}` };\n }\n }\n\n /**\n * Check if client has approved the server wallet\n */\n async checkApproval(\n clientAddress: string, \n token: string, \n chainId: number\n ): Promise<{ approved: boolean; allowance: string }> {\n const config = this.chainConfigs[chainId];\n if (!config) {\n throw new Error(`Unsupported chainId: ${chainId}`);\n }\n\n const serverAddress = await this.getServerAddress();\n const allowance = await this.getAllowance(clientAddress, serverAddress, token, config.rpc);\n \n // Consider approved if allowance > 1000 USDC (with 18 decimals)\n const minAllowance = BigInt('1000000000000000000000'); // 1000 tokens\n \n return {\n approved: BigInt(allowance) >= minAllowance,\n allowance,\n };\n }\n\n /**\n * Verify a completed transaction (for checking past payments)\n */\n async verifyTransaction(\n txHash: string, \n expected: { to: string; amount: string; token: string },\n chainId: number\n ): Promise<VerifyResult> {\n const config = this.chainConfigs[chainId];\n if (!config) {\n return { valid: false, error: `Unsupported chainId: ${chainId}` };\n }\n\n try {\n const receipt = await this.getTransactionReceipt(txHash, config.rpc);\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 log.address.toLowerCase() === expected.token.toLowerCase()\n );\n\n if (!transferLog) {\n return { valid: false, error: 'No Transfer event found' };\n }\n\n // Verify recipient\n const toAddress = '0x' + transferLog.topics[2].slice(26).toLowerCase();\n if (toAddress !== expected.to.toLowerCase()) {\n return { valid: false, error: `Wrong recipient: ${toAddress}` };\n }\n\n // Verify amount\n const amount = BigInt(transferLog.data);\n if (amount < BigInt(expected.amount)) {\n return { valid: false, error: `Insufficient amount: ${amount}` };\n }\n\n return { \n valid: true, \n details: {\n txHash,\n from: '0x' + transferLog.topics[1].slice(26),\n to: toAddress,\n amount: amount.toString(),\n token: transferLog.address,\n }\n };\n } catch (error) {\n return { valid: false, error: `Verification failed: ${error}` };\n }\n }\n\n // ==================== Private Methods ====================\n\n /**\n * Get the server's spender address (public, for 402 responses)\n * Returns cached value computed at construction time.\n */\n getSpenderAddress(): string | null {\n return this.spenderAddress;\n }\n\n private async getServerAddress(): Promise<string> {\n // Derive address from private key using ethers\n const { ethers } = await import('ethers');\n const wallet = new ethers.Wallet(this.serverPrivateKey);\n return wallet.address;\n }\n\n private async recoverIntentSigner(intent: BNBPaymentIntent, chainId: number): Promise<string> {\n // Use ethers for EIP-712 signature recovery\n const { ethers } = await import('ethers');\n \n const domain = {\n ...EIP712_DOMAIN,\n chainId,\n };\n\n const message = {\n from: intent.from,\n to: intent.to,\n amount: intent.amount,\n token: intent.token,\n service: intent.service,\n nonce: intent.nonce,\n deadline: intent.deadline,\n };\n\n const recoveredAddress = ethers.verifyTypedData(\n domain,\n INTENT_TYPES,\n message,\n intent.signature\n );\n\n return recoveredAddress;\n }\n\n private async getAllowance(owner: string, spender: string, token: string, rpcUrl: string): Promise<string> {\n // allowance(address,address) selector + params\n const selector = '0xdd62ed3e';\n const ownerPadded = owner.toLowerCase().replace('0x', '').padStart(64, '0');\n const spenderPadded = spender.toLowerCase().replace('0x', '').padStart(64, '0');\n const data = selector + ownerPadded + spenderPadded;\n\n const response = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_call',\n params: [{ to: token, data }, 'latest'],\n id: 1,\n }),\n });\n\n const result = await response.json() as { result: string };\n return result.result || '0x0';\n }\n\n private async getBalance(account: string, token: string, rpcUrl: string): Promise<string> {\n // balanceOf(address) selector + param\n const selector = '0x70a08231';\n const accountPadded = account.toLowerCase().replace('0x', '').padStart(64, '0');\n const data = selector + accountPadded;\n\n const response = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_call',\n params: [{ to: token, data }, 'latest'],\n id: 1,\n }),\n });\n\n const result = await response.json() as { result: string };\n return result.result || '0x0';\n }\n\n private async executeTransferFrom(\n from: string,\n to: string,\n amount: string,\n token: string,\n rpcUrl: string\n ): Promise<string> {\n const { ethers } = await import('ethers');\n \n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const wallet = new ethers.Wallet(this.serverPrivateKey, provider);\n \n const tokenContract = new ethers.Contract(token, [\n 'function transferFrom(address from, address to, uint256 amount) returns (bool)',\n ], wallet);\n\n const tx = await tokenContract.transferFrom(from, to, amount);\n const receipt = await tx.wait();\n \n return receipt.hash;\n }\n\n private async getTransactionReceipt(txHash: string, rpcUrl: string): Promise<any> {\n const response = await fetch(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/**\n * Create EIP-712 typed data for signing a payment intent\n * \n * Used by clients to sign their payment intent.\n */\nexport function createIntentTypedData(\n intent: Omit<BNBPaymentIntent, 'signature'>,\n chainId: number\n) {\n return {\n domain: {\n ...EIP712_DOMAIN,\n chainId,\n },\n types: INTENT_TYPES,\n primaryType: 'PaymentIntent' as const,\n message: {\n from: intent.from,\n to: intent.to,\n amount: intent.amount,\n token: intent.token,\n service: intent.service,\n nonce: intent.nonce,\n deadline: intent.deadline,\n },\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';\nimport { BNBFacilitator } from './bnb.js';\nimport { SolanaFacilitator, SolanaFacilitatorConfig } from './solana.js';\nimport { Keypair } from '@solana/web3.js';\nimport bs58 from 'bs58';\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 this.registerFactory('bnb', (config) => new BNBFacilitator(config?.serverPrivateKey as string));\n this.registerFactory('solana', (config) => {\n // Load fee payer keypair from config or env\n let feePayerKeypair: Keypair | undefined;\n const feePayerKey = (config as any)?.feePayerPrivateKey || process.env.SOLANA_FEE_PAYER_KEY;\n \n if (feePayerKey) {\n try {\n feePayerKeypair = Keypair.fromSecretKey(bs58.decode(feePayerKey));\n } catch (e: any) {\n console.warn(`[SolanaFacilitator] Invalid fee payer key: ${e.message}`);\n }\n }\n \n return new SolanaFacilitator({ feePayerKeypair } as SolanaFacilitatorConfig);\n });\n \n // Default selection\n this.selection = selection || { primary: 'cdp', fallback: ['tempo', 'bnb', 'solana'], 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","/**\n * MoltsPay Server Types\n */\n\n// Supported token types\nexport type TokenSymbol = 'USDC' | 'USDT';\n\n// Service definition from moltspay.services.json\nexport interface ServiceConfig {\n id: string;\n name: string;\n description?: string;\n price: number;\n currency: string;\n /** \n * Tokens accepted for payment (optional).\n * If not specified, defaults to [currency].\n * Example: [\"USDC\", \"USDT\"]\n */\n acceptedCurrencies?: TokenSymbol[];\n input: Record<string, InputField>;\n output: Record<string, OutputField>;\n /** Shell command to execute for this service. Params passed as JSON to stdin. */\n command?: string;\n /** Function name to import from skill's index.js (new skill-based approach) */\n function?: string;\n}\n\nexport interface InputField {\n type: 'string' | 'number' | 'boolean' | 'object';\n required?: boolean;\n description?: string;\n}\n\nexport interface OutputField {\n type: 'string' | 'number' | 'boolean' | 'object';\n description?: string;\n}\n\n// Chain configuration for multi-chain support\nexport interface ChainConfig {\n chain: string;\n network: string;\n wallet?: string; // Optional per-chain wallet, falls back to provider.wallet\n tokens?: TokenSymbol[];\n}\n\n// Provider config from moltspay.services.json\nexport interface ProviderConfig {\n name: string;\n description?: string;\n wallet: string;\n solana_wallet?: string; // Solana chains receiving wallet\n chain?: string; // Single chain (backward compat)\n chains?: ChainConfig[]; // Multi-chain support\n}\n\n// Full services.json structure\nexport interface ServicesManifest {\n provider: ProviderConfig;\n services: ServiceConfig[];\n}\n\n// Skill function type\nexport type SkillFunction = (params: Record<string, any>) => Promise<Record<string, any>>;\n\n// Registered skill\nexport interface RegisteredSkill {\n id: string;\n config: ServiceConfig;\n handler: SkillFunction;\n}\n\n// Payment request (returned to client)\nexport interface PaymentRequest {\n chargeId: string;\n service: string;\n amount: number;\n currency: string;\n wallet: string;\n chain: string;\n expiresAt: number;\n}\n\n// Payment verification request\nexport interface VerifyRequest {\n chargeId: string;\n txHash: string;\n}\n\n// Charge status\nexport type ChargeStatus = 'pending' | 'paid' | 'completed' | 'expired' | 'failed';\n\n// Internal charge record\nexport interface Charge {\n id: string;\n service: string;\n params: Record<string, any>;\n amount: number;\n currency: string;\n status: ChargeStatus;\n txHash?: string;\n result?: Record<string, any>;\n createdAt: number;\n expiresAt: number;\n paidAt?: number;\n completedAt?: number;\n}\n\n// Server options\nexport interface MoltsPayServerOptions {\n port?: number;\n host?: string;\n chargeExpirySecs?: number;\n /** x402 Facilitator URL (default: https://x402.org/facilitator) */\n facilitatorUrl?: string;\n}\n","/**\n * Coinbase Pay Integration\n * \n * Generate session token and URL for users to buy USDC with fiat\n * via Coinbase Pay (US only, debit card / Apple Pay)\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nconst CDP_API_BASE = 'https://api.developer.coinbase.com';\n\ninterface CDPCredentials {\n apiKeyId: string;\n apiKeySecret: string;\n}\n\n/**\n * Load CDP credentials from environment or .env file\n */\nfunction loadCredentials(): CDPCredentials | null {\n let apiKeyId = process.env.CDP_API_KEY_ID;\n let apiKeySecret = process.env.CDP_API_KEY_SECRET;\n\n if (!apiKeyId || !apiKeySecret) {\n const envPath = join(homedir(), '.moltspay', '.env');\n if (existsSync(envPath)) {\n const envContent = readFileSync(envPath, 'utf-8');\n for (const line of envContent.split('\\n')) {\n const [key, ...valueParts] = line.split('=');\n const value = valueParts.join('=').trim();\n if (key === 'CDP_API_KEY_ID') apiKeyId = value;\n if (key === 'CDP_API_KEY_SECRET') apiKeySecret = value;\n }\n }\n }\n\n if (!apiKeyId || !apiKeySecret) {\n return null;\n }\n\n return { apiKeyId, apiKeySecret };\n}\n\n/**\n * Get public IP address\n */\nasync function getPublicIp(): Promise<string> {\n const response = await fetch('https://api.ipify.org');\n if (!response.ok) {\n throw new Error('Failed to get public IP');\n }\n return (await response.text()).trim();\n}\n\n/**\n * Generate JWT for CDP API authentication\n */\nasync function generateCdpJwt(\n credentials: CDPCredentials,\n method: string,\n path: string\n): Promise<string> {\n const { SignJWT, importJWK } = await import('jose');\n const crypto = await import('crypto');\n\n const now = Math.floor(Date.now() / 1000);\n const nonce = crypto.randomBytes(16).toString('hex');\n\n // URI format: \"METHOD host/path\" (no https://)\n const uri = `${method} api.developer.coinbase.com${path}`;\n\n const claims = {\n sub: credentials.apiKeyId,\n iss: 'cdp',\n nbf: now,\n exp: now + 120,\n uri,\n };\n\n // Ed25519 key: 64 bytes = 32 seed + 32 public\n const decoded = Buffer.from(credentials.apiKeySecret, 'base64');\n const seed = decoded.subarray(0, 32);\n const publicKey = decoded.subarray(32);\n\n const jwk = {\n kty: 'OKP' as const,\n crv: 'Ed25519' as const,\n d: seed.toString('base64url'),\n x: publicKey.toString('base64url'),\n };\n\n const key = await importJWK(jwk, 'EdDSA');\n\n return await new SignJWT(claims)\n .setProtectedHeader({ alg: 'EdDSA', kid: credentials.apiKeyId, typ: 'JWT', nonce })\n .sign(key);\n}\n\n/**\n * Get session token from CDP Onramp API\n */\nasync function getSessionToken(params: {\n address: string;\n chain: 'base' | 'polygon';\n clientIp: string;\n}): Promise<{ token: string; channelId: string }> {\n const credentials = loadCredentials();\n if (!credentials) {\n throw new Error('CDP credentials not found. Set CDP_API_KEY_ID and CDP_API_KEY_SECRET.');\n }\n\n const path = '/onramp/v1/token';\n const jwt = await generateCdpJwt(credentials, 'POST', path);\n\n const response = await fetch(`${CDP_API_BASE}${path}`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${jwt}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n addresses: [\n {\n address: params.address,\n blockchains: [params.chain],\n },\n ],\n clientIp: params.clientIp,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`CDP API error (${response.status}): ${errorText}`);\n }\n\n const result = await response.json() as { token: string; channel_id: string };\n return {\n token: result.token,\n channelId: result.channel_id,\n };\n}\n\n/**\n * Generate Coinbase Pay URL with session token\n */\nexport async function generateOnrampUrl(params: {\n destinationAddress: string;\n amount: number;\n chain?: 'base' | 'polygon';\n}): Promise<string> {\n const chain = params.chain || 'base';\n\n // Get public IP\n const clientIp = await getPublicIp();\n\n // Get session token\n const { token } = await getSessionToken({\n address: params.destinationAddress,\n chain,\n clientIp,\n });\n\n // Build URL with session token\n const queryParams = new URLSearchParams({\n sessionToken: token,\n defaultAsset: 'USDC',\n defaultNetwork: chain,\n presetFiatAmount: params.amount.toString(),\n });\n\n return `https://pay.coinbase.com/buy/select-asset?${queryParams.toString()}`;\n}\n\n/**\n * Print QR code to terminal\n */\nexport async function printQRCode(url: string): Promise<void> {\n const qrcodeModule = await import('qrcode-terminal');\n const qrcode = qrcodeModule.default || qrcodeModule;\n\n return new Promise((resolve) => {\n qrcode.generate(url, { small: true }, (qr: string) => {\n console.log(qr);\n resolve();\n });\n });\n}\n"],"mappings":"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","names":["import_os","import_path","import_fs","import_ethers","import_fs","import_os","import_path","import_web3","bs58","import_web3","import_spl_token","config","import_web3","network","req","payTo","privateKeyToAccount","import_fs","path","import_fs","X402_VERSION","TRANSFER_EVENT_TOPIC","TRANSFER_EVENT_TOPIC","ethers","import_web3","import_bs58","bs58","X402_VERSION","PAYMENT_REQUIRED_HEADER","PAYMENT_HEADER","loadEnvFile","resolve","isValidSolanaAddress","settlement","resolve","DEFAULT_CONFIG_DIR","resolve","solanaAddress"]}
1
+ {"version":3,"sources":["../../node_modules/tsup/assets/cjs_shims.js","../../src/cli/index.ts","../../src/client/index.ts","../../src/client/node/index.ts","../../src/chains/index.ts","../../src/wallet/solana.ts","../../src/chains/solana.ts","../../src/facilitators/solana.ts","../../src/facilitators/interface.ts","../../src/client/core/index.ts","../../src/client/core/types.ts","../../src/client/core/chain-map.ts","../../src/client/core/base64.ts","../../src/client/core/errors.ts","../../src/client/core/eip3009.ts","../../src/client/core/eip2612.ts","../../src/client/core/bnb-intent.ts","../../src/client/core/solana-tx.ts","../../src/client/core/x402.ts","../../src/client/node/signer.ts","../../src/client/alipay/index.ts","../../src/client/alipay/cli.ts","../../src/client/alipay/log.ts","../../src/client/alipay/install.ts","../../src/client/alipay/errors.ts","../../src/client/alipay/poll.ts","../../src/client/alipay/router.ts","../../src/client/types.ts","../../src/server/index.ts","../../src/facilitators/index.ts","../../src/facilitators/cdp.ts","../../src/facilitators/tempo.ts","../../src/facilitators/bnb.ts","../../src/facilitators/alipay.ts","../../src/facilitators/alipay/rsa2.ts","../../src/facilitators/alipay/encoding.ts","../../src/facilitators/alipay/openapi.ts","../../src/facilitators/registry.ts","../../src/server/types.ts","../../src/onramp/index.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","#!/usr/bin/env node\n\n/**\n * MoltsPay CLI\n * \n * Commands:\n * npx moltspay init - Create wallet, set limits\n * npx moltspay config - Update settings\n * npx moltspay fund <amount> - Fund wallet via Coinbase (US only)\n * npx moltspay status - Show wallet and balance\n * npx moltspay services <url> - List services from provider\n * npx moltspay start <manifest> - Start server from services.json\n */\n\n// Polyfill crypto for Node.js 18\nimport { webcrypto } from 'crypto';\nif (!globalThis.crypto) {\n (globalThis as any).crypto = webcrypto;\n}\n\nimport { Command } from 'commander';\nimport { homedir } from 'os';\nimport { join, dirname, resolve } from 'path';\nimport { existsSync, writeFileSync, readFileSync, unlinkSync, mkdirSync } from 'fs';\nimport { spawn } from 'child_process';\nimport { ethers } from 'ethers';\nimport { MoltsPayClient } from '../client/index.js';\nimport { MoltsPayServer } from '../server/index.js';\nimport { filterEnv as filterAlipayEnv } from '../client/alipay/cli.js';\nimport { printQRCode } from '../onramp/index.js';\nimport { CHAINS } from '../chains/index.js';\nimport { SOLANA_CHAINS, getSolanaExplorerUrl, getSolanaTxExplorerUrl, isSolanaChain } from '../chains/solana.js';\nimport { \n loadSolanaWallet, \n createSolanaWallet, \n getSolanaAddress, \n getSolanaBalances,\n solanaWalletExists,\n isValidSolanaAddress,\n} from '../wallet/solana.js';\nimport type { ChainName } from '../types/index.js';\nimport * as readline from 'readline';\n\n// Read version from package.json at runtime\nfunction getVersion(): string {\n // Try to find package.json in common locations\n const locations = [\n join(__dirname, '../../package.json'),\n join(__dirname, '../package.json'),\n join(process.cwd(), 'node_modules/moltspay/package.json'),\n ];\n for (const loc of locations) {\n try {\n if (existsSync(loc)) {\n const pkg = JSON.parse(readFileSync(loc, 'utf-8'));\n if (pkg.name === 'moltspay') return pkg.version;\n }\n } catch { /* ignore */ }\n }\n return '0.0.0'; // fallback\n}\n\n// Server wallet for BNB gas sponsorship (loaded from env)\nconst BNB_SPONSOR_KEY = process.env.MOLTSPAY_BNB_SPONSOR_KEY;\n// Server wallet address that will call transferFrom (for pay-for-success)\nconst BNB_SPENDER_ADDRESS = process.env.MOLTSPAY_BNB_SPENDER || '0xEBB45208D806A0c73F9673E0c5713FF720DD6b79';\n\nconst ERC20_APPROVE_ABI = [\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n];\n\n/**\n * Set up BNB chain approvals for pay-for-success flow\n * This allows the server to call transferFrom after service succeeds\n */\nasync function setupBNBApprovals(\n client: MoltsPayClient, \n chain: 'bnb' | 'bnb_testnet',\n spenderAddress: string,\n sponsorGas: boolean = false\n): Promise<void> {\n const chainConfig = CHAINS[chain];\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n \n // Get wallet from client\n const wallet = client.getWallet();\n if (!wallet) {\n console.log(' ❌ No wallet found');\n return;\n }\n const signer = wallet.connect(provider);\n \n console.log(` Spender: ${spenderAddress}`);\n \n // Check BNB balance for gas\n let bnbBalance = await provider.getBalance(wallet.address);\n const minGasRequired = ethers.parseEther('0.0005'); // ~0.0002 per approval × 2 + buffer\n \n if (bnbBalance < minGasRequired) {\n if (sponsorGas && BNB_SPONSOR_KEY) {\n console.log(' ⏳ Sponsoring BNB gas for approvals...');\n try {\n const sponsorWallet = new ethers.Wallet(BNB_SPONSOR_KEY, provider);\n const tx = await sponsorWallet.sendTransaction({\n to: wallet.address,\n value: ethers.parseEther('0.001'),\n });\n await tx.wait();\n console.log(` ✅ Sponsored 0.001 BNB (tx: ${tx.hash.slice(0, 10)}...)`);\n bnbBalance = await provider.getBalance(wallet.address);\n } catch (err: any) {\n console.log(` ⚠️ Gas sponsorship failed: ${err.message}`);\n console.log(` 💡 Get testnet BNB: https://testnet.bnbchain.org/faucet-smart`);\n return;\n }\n } else {\n console.log(` ⚠️ Need BNB for gas (~0.0005 BNB)`);\n console.log(` 💡 Run: npx moltspay faucet --chain bnb_testnet`);\n console.log(` Then run: npx moltspay approve --chain ${chain} --spender ${spenderAddress}`);\n return;\n }\n }\n \n // Approve USDT and USDC for the spender address\n for (const tokenSymbol of ['USDT', 'USDC'] as const) {\n const tokenConfig = chainConfig.tokens[tokenSymbol];\n const tokenContract = new ethers.Contract(tokenConfig.address, ERC20_APPROVE_ABI, signer);\n \n // Check existing allowance\n const allowance = await tokenContract.allowance(wallet.address, spenderAddress);\n if (allowance > 0n) {\n console.log(` ✅ ${tokenSymbol}: already approved for ${spenderAddress.slice(0, 10)}...`);\n continue;\n }\n \n console.log(` ⏳ Approving ${tokenSymbol}...`);\n try {\n const tx = await tokenContract.approve(spenderAddress, ethers.MaxUint256);\n await tx.wait();\n console.log(` ✅ ${tokenSymbol}: approved (tx: ${tx.hash.slice(0, 10)}...)`);\n } catch (err: any) {\n console.log(` ❌ ${tokenSymbol}: approval failed - ${err.message}`);\n }\n }\n \n console.log('');\n}\n\n/**\n * Check BNB approval status\n */\nasync function checkBNBApprovals(\n address: string,\n chain: 'bnb' | 'bnb_testnet',\n configDir: string = DEFAULT_CONFIG_DIR\n): Promise<{ usdt: boolean; usdc: boolean; spender: string | null }> {\n const chainConfig = CHAINS[chain];\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n \n // Read spender from wallet config (saved during approve command)\n let spenderAddress: string | null = null;\n try {\n const walletPath = join(configDir, 'wallet.json');\n const walletData = JSON.parse(readFileSync(walletPath, 'utf-8'));\n spenderAddress = walletData.approvals?.[chain] || null;\n } catch {\n // No saved spender\n }\n \n const result = { usdt: false, usdc: false, spender: spenderAddress };\n \n if (!spenderAddress) {\n return result; // No spender saved, can't check approvals\n }\n \n for (const tokenSymbol of ['USDT', 'USDC'] as const) {\n const tokenConfig = chainConfig.tokens[tokenSymbol];\n const tokenContract = new ethers.Contract(tokenConfig.address, ERC20_APPROVE_ABI, provider);\n const allowance = await tokenContract.allowance(address, spenderAddress);\n result[tokenSymbol.toLowerCase() as 'usdt' | 'usdc'] = allowance > 0n;\n }\n \n return result;\n}\n\nconst program = new Command();\nconst DEFAULT_CONFIG_DIR = join(homedir(), '.moltspay');\nconst PID_FILE = join(DEFAULT_CONFIG_DIR, 'server.pid');\n\n// Ensure config dir exists\nif (!existsSync(DEFAULT_CONFIG_DIR)) {\n mkdirSync(DEFAULT_CONFIG_DIR, { recursive: true });\n}\n\nfunction prompt(question: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise(resolve => {\n rl.question(question, answer => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nprogram\n .name('moltspay')\n .description('MoltsPay - Payment infrastructure for AI Agents')\n .version(getVersion());\n\n/**\n * npx moltspay init\n */\nprogram\n .command('init')\n .description('Initialize MoltsPay client (create wallet, set limits)')\n .option('--chain <chain>', 'Blockchain to use', 'base')\n .option('--max-per-tx <amount>', 'Max amount per transaction')\n .option('--max-per-day <amount>', 'Max amount per day')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n // Get chain option\n let chain = options.chain;\n \n // Validate chain\n const supportedEVMChains = ['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'bnb', 'bnb_testnet'];\n const supportedSolanaChains = ['solana', 'solana_devnet'];\n const supportedChains = [...supportedEVMChains, ...supportedSolanaChains];\n \n if (!supportedChains.includes(chain)) {\n console.error(`❌ Unknown chain: ${chain}. Supported: ${supportedChains.join(', ')}`);\n process.exit(1);\n }\n \n // Handle Solana chains separately (different wallet)\n if (supportedSolanaChains.includes(chain)) {\n console.log('\\n🟣 Solana Wallet Setup\\n');\n \n if (solanaWalletExists(options.configDir)) {\n const existingAddress = getSolanaAddress(options.configDir);\n console.log(`⚠️ Solana wallet already exists: ${existingAddress}`);\n console.log(` Config dir: ${options.configDir}`);\n return;\n }\n \n console.log('Creating Solana wallet...');\n const keypair = createSolanaWallet(options.configDir);\n const address = keypair.publicKey.toBase58();\n \n console.log(`\\n✅ Solana wallet created: ${address}`);\n console.log(`\\n📁 Config saved to: ${join(options.configDir, 'wallet-solana.json')}`);\n console.log(`\\n⚠️ IMPORTANT: Back up your wallet file!`);\n console.log(` This file contains your private key!\\n`);\n \n if (chain === 'solana_devnet') {\n console.log('💡 Get testnet tokens:');\n console.log(' npx moltspay faucet --chain solana_devnet\\n');\n } else {\n console.log(`💰 Fund your wallet with USDC on Solana to start (gasless - no SOL needed).\\n`);\n }\n \n return;\n }\n\n // For EVM chains, check if already initialized\n console.log('\\n🔐 MoltsPay Client Setup\\n');\n \n if (existsSync(join(options.configDir, 'wallet.json'))) {\n console.log('⚠️ EVM wallet already initialized. Use \"moltspay config\" to update settings.');\n console.log(` Config dir: ${options.configDir}`);\n return;\n }\n \n let maxPerTx = options.maxPerTx ? parseFloat(options.maxPerTx) : null;\n let maxPerDay = options.maxPerDay ? parseFloat(options.maxPerDay) : null;\n\n if (!maxPerTx) {\n const answer = await prompt('Max per transaction (USD) [100]: ');\n maxPerTx = answer ? parseFloat(answer) : 100;\n }\n\n if (!maxPerDay) {\n const answer = await prompt('Max per day (USD) [1000]: ');\n maxPerDay = answer ? parseFloat(answer) : 1000;\n }\n\n console.log('\\nCreating wallet...');\n\n const result = MoltsPayClient.init(options.configDir, {\n chain,\n maxPerTx,\n maxPerDay,\n });\n\n console.log(`\\n✅ Wallet created: ${result.address}`);\n console.log(`\\n📁 Config saved to: ${result.configDir}`);\n console.log(`\\n⚠️ IMPORTANT: Back up ${join(result.configDir, 'wallet.json')}`);\n console.log(` This file contains your private key!\\n`);\n\n // For BNB chains, set up approvals (requires gas sponsorship for new wallets)\n if (chain === 'bnb' || chain === 'bnb_testnet') {\n console.log('📋 Setting up BNB chain approvals...\\n');\n console.log(' ℹ️ Using default spender. For other services, run:');\n console.log(` npx moltspay approve --chain ${chain} --spender <address>\\n`);\n const client = new MoltsPayClient({ configDir: options.configDir });\n await setupBNBApprovals(client, chain, BNB_SPENDER_ADDRESS, true); // true = sponsor gas\n }\n\n console.log(`💰 Fund your wallet with USDC on ${chain} to start using services.\\n`);\n });\n\n/**\n * npx moltspay config\n */\nprogram\n .command('config')\n .description('Update MoltsPay settings')\n .option('--max-per-tx <amount>', 'Max amount per transaction')\n .option('--max-per-day <amount>', 'Max amount per day')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n\n if (!client.isInitialized) {\n console.log('❌ Not initialized. Run: npx moltspay init');\n return;\n }\n\n const currentConfig = client.getConfig();\n\n // If no options provided, show interactive mode\n if (!options.maxPerTx && !options.maxPerDay) {\n console.log('\\n📋 Current Settings:\\n');\n console.log(` Wallet: ${client.address}`);\n console.log(` Chain: ${currentConfig.chain}`);\n console.log(` Max per tx: $${currentConfig.limits.maxPerTx}`);\n console.log(` Max per day: $${currentConfig.limits.maxPerDay}`);\n console.log('');\n\n const maxPerTxAnswer = await prompt(`New max per tx (USD) [${currentConfig.limits.maxPerTx}]: `);\n const maxPerDayAnswer = await prompt(`New max per day (USD) [${currentConfig.limits.maxPerDay}]: `);\n\n if (maxPerTxAnswer) {\n client.updateConfig({ maxPerTx: parseFloat(maxPerTxAnswer) });\n console.log(`✅ Updated max per tx to $${maxPerTxAnswer}`);\n }\n\n if (maxPerDayAnswer) {\n client.updateConfig({ maxPerDay: parseFloat(maxPerDayAnswer) });\n console.log(`✅ Updated max per day to $${maxPerDayAnswer}`);\n }\n } else {\n // Non-interactive mode\n if (options.maxPerTx) {\n client.updateConfig({ maxPerTx: parseFloat(options.maxPerTx) });\n console.log(`✅ Updated max per tx to $${options.maxPerTx}`);\n }\n if (options.maxPerDay) {\n client.updateConfig({ maxPerDay: parseFloat(options.maxPerDay) });\n console.log(`✅ Updated max per day to $${options.maxPerDay}`);\n }\n }\n });\n\n/**\n * npx moltspay fund <amount>\n * \n * Fund wallet with USDC via Coinbase Pay\n * US residents only, debit card or Apple Pay\n */\nprogram\n .command('fund <amount>')\n .description('Fund wallet with USDC via Coinbase (US debit card / Apple Pay)')\n .option('--chain <chain>', 'Chain to fund (base, polygon, solana, base_sepolia, bnb, or bnb_testnet)', 'base')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (amountStr, options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n\n const amount = parseFloat(amountStr);\n if (isNaN(amount) || amount < 5) {\n console.log('❌ Minimum $5.');\n return;\n }\n\n const chain = (options.chain?.toLowerCase() || 'base') as 'base' | 'polygon' | 'base_sepolia' | 'solana' | 'bnb' | 'bnb_testnet';\n if (!['base', 'polygon', 'base_sepolia', 'solana', 'bnb', 'bnb_testnet'].includes(chain)) {\n console.log('❌ Invalid chain. Use: base, polygon, solana, base_sepolia, bnb, or bnb_testnet');\n return;\n }\n \n // Determine wallet address based on chain\n let walletAddress: string;\n if (chain === 'solana') {\n // Load Solana wallet\n const solanaWallet = loadSolanaWallet(options.configDir || DEFAULT_CONFIG_DIR);\n if (!solanaWallet) {\n console.log('❌ No Solana wallet found. Run: npx moltspay init --chain solana');\n return;\n }\n walletAddress = getSolanaAddress(options.configDir || DEFAULT_CONFIG_DIR) || '';\n if (!walletAddress) {\n console.log('❌ Could not get Solana wallet address.');\n return;\n }\n } else {\n // EVM chains use the client wallet\n if (!client.isInitialized) {\n console.log('❌ Not initialized. Run: npx moltspay init');\n return;\n }\n walletAddress = client.address!;\n }\n \n // Testnet: use faucet instead of Coinbase Pay\n if (chain === 'base_sepolia') {\n console.log('\\n🧪 Testnet Funding\\n');\n console.log(` Wallet: ${walletAddress}`);\n console.log(` Chain: Base Sepolia (testnet)\\n`);\n console.log('💡 Use the MoltsPay faucet to get free testnet USDC:\\n');\n console.log(' npx moltspay faucet\\n');\n console.log(' Or get from Circle Faucet: https://faucet.circle.com/\\n');\n return;\n }\n \n // BNB Testnet: use faucet (gives USDC + tBNB for gas)\n if (chain === 'bnb_testnet') {\n console.log('\\n🧪 BNB Testnet Funding\\n');\n console.log(` Wallet: ${walletAddress}`);\n console.log(` Chain: BNB Testnet\\n`);\n console.log('💡 Use the MoltsPay faucet to get testnet USDC + tBNB:\\n');\n console.log(' npx moltspay faucet --chain bnb_testnet\\n');\n console.log(' This gives you:\\n');\n console.log(' • 1 USDC (testnet) for payments');\n console.log(' • 0.001 tBNB for gas (first approval tx)\\n');\n return;\n }\n \n // BNB Mainnet: manual funding required (no Coinbase onramp)\n if (chain === 'bnb') {\n console.log('\\n📋 BNB Chain Funding\\n');\n console.log(` Wallet: ${walletAddress}\\n`);\n console.log(' To use MoltsPay on BNB Chain, you need:\\n');\n console.log(' 1. USDC for payments');\n console.log(' → Withdraw from Binance/exchange to your wallet address\\n');\n console.log(' 2. Small amount of BNB for gas (~0.001 BNB / ~$0.60)');\n console.log(' → First approval transaction requires gas');\n console.log(' → After approval, all payments are gasless\\n');\n console.log(' 💡 Tip: Most exchanges include BNB dust when you withdraw to BNB Chain\\n');\n console.log(' ─────────────────────────────────────────────────────────────');\n console.log(' After funding, check status: npx moltspay status\\n');\n return;\n }\n\n console.log('\\n💳 Fund your agent wallet\\n');\n console.log(` Wallet: ${walletAddress}`);\n console.log(` Chain: ${chain === 'solana' ? 'Solana' : chain}`);\n console.log(` Amount: $${amount.toFixed(2)}\\n`);\n\n try {\n // Call server API to generate onramp URL (no local CDP keys needed)\n const ONRAMP_API = process.env.MOLTSPAY_ONRAMP_API || 'https://moltspay.com/api/v1/onramp';\n \n const response = await fetch(`${ONRAMP_API}/create`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n address: walletAddress,\n amount,\n chain,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({ error: 'Server error' })) as { error?: string };\n throw new Error(errorData.error || `Server returned ${response.status}`);\n }\n\n const result = await response.json() as { url: string };\n const { url } = result;\n\n console.log(' Scan to pay (US debit card / Apple Pay):\\n');\n await printQRCode(url);\n console.log('\\n ⏱️ QR code expires in 5 minutes\\n');\n } catch (error) {\n console.log(`❌ ${(error as Error).message}`);\n }\n });\n\n/**\n * npx moltspay approve\n * \n * Approve a spender address for BNB chain payments (required before paying)\n */\nprogram\n .command('approve')\n .description('Approve a spender address for BNB chain payments')\n .requiredOption('--spender <address>', 'Spender address to approve (from server 402 response)')\n .option('--chain <chain>', 'BNB chain (bnb or bnb_testnet)', 'bnb_testnet')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n const chain = options.chain as 'bnb' | 'bnb_testnet';\n \n if (chain !== 'bnb' && chain !== 'bnb_testnet') {\n console.log('❌ approve command is only for BNB chains (bnb or bnb_testnet)');\n return;\n }\n \n if (!options.spender.match(/^0x[a-fA-F0-9]{40}$/)) {\n console.log('❌ Invalid spender address format');\n return;\n }\n \n const client = new MoltsPayClient({ configDir: options.configDir });\n if (!client.isInitialized) {\n console.log('❌ Wallet not initialized. Run: npx moltspay init --chain ' + chain);\n return;\n }\n \n console.log(`\\n🔐 Approving spender for ${chain}...\\n`);\n await setupBNBApprovals(client, chain, options.spender, false);\n \n // Save approved spender to wallet config for status command\n const walletPath = join(options.configDir || DEFAULT_CONFIG_DIR, 'wallet.json');\n try {\n const walletData = JSON.parse(readFileSync(walletPath, 'utf-8'));\n walletData.approvals = walletData.approvals || {};\n walletData.approvals[chain] = options.spender;\n writeFileSync(walletPath, JSON.stringify(walletData, null, 2));\n console.log(`✅ Approval complete! Spender saved for ${chain}.\\n`);\n } catch (err) {\n console.log('✅ Approval complete!\\n');\n console.log('⚠️ Could not save spender to wallet config');\n }\n });\n\n/**\n * npx moltspay faucet\n * \n * Request testnet tokens from faucets (Base Sepolia or Tempo Moderato)\n */\nprogram\n .command('faucet')\n .description('Request testnet tokens from faucet (Base Sepolia, Tempo Moderato, BNB Testnet, or Solana Devnet)')\n .option('--chain <chain>', 'Chain to get tokens on (base_sepolia, tempo_moderato, bnb_testnet, or solana_devnet)', 'base_sepolia')\n .option('--address <address>', 'Wallet address (defaults to your wallet)')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n let address = options.address;\n const chain = options.chain?.toLowerCase() || 'base_sepolia';\n\n // Validate chain\n if (!['base_sepolia', 'tempo_moderato', 'bnb_testnet', 'solana_devnet'].includes(chain)) {\n console.log('❌ Invalid chain. Use: base_sepolia, tempo_moderato, bnb_testnet, or solana_devnet');\n return;\n }\n\n // Handle Solana devnet separately\n if (chain === 'solana_devnet') {\n // Get Solana address\n if (!address) {\n address = getSolanaAddress(options.configDir);\n if (!address) {\n console.log('❌ No Solana wallet found. Run: npx moltspay init --chain solana_devnet');\n return;\n }\n }\n\n // Validate Solana address format\n if (!isValidSolanaAddress(address)) {\n console.log('❌ Invalid Solana address');\n return;\n }\n\n console.log('\\n🚰 Solana Devnet Faucet (Gasless Mode)\\n');\n console.log(` Address: ${address}\\n`);\n\n let usdcSuccess = false;\n\n // Request USDC from MoltsPay faucet API (no SOL needed - server pays fees)\n try {\n console.log(' ⏳ Requesting 1 USDC from faucet...');\n const FAUCET_API = process.env.MOLTSPAY_FAUCET_API || 'https://moltspay.com/api/v1/faucet';\n \n const response = await fetch(FAUCET_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ address, chain: 'solana_devnet' }),\n });\n\n const result = await response.json() as {\n success?: boolean;\n amount?: string;\n transaction?: string;\n explorer?: string;\n faucet_balance?: string;\n error?: string;\n hint?: string;\n retry_after?: string;\n };\n\n if (!response.ok) {\n console.log(` ⚠️ USDC faucet: ${result.error || 'Request failed'}`);\n if (result.hint) console.log(` ${result.hint}`);\n if (result.retry_after) console.log(` Retry after: ${result.retry_after}`);\n } else {\n console.log(` ✅ Received ${result.amount} USDC!`);\n console.log(` Transaction: ${result.explorer}`);\n if (result.faucet_balance) {\n console.log(` Faucet balance: ${result.faucet_balance} USDC remaining`);\n }\n usdcSuccess = true;\n }\n } catch (error: any) {\n console.log(` ⚠️ USDC faucet error: ${error.message}`);\n }\n\n console.log('');\n if (usdcSuccess) {\n console.log('💡 Check your balance:');\n console.log(' npx moltspay status\\n');\n } else {\n console.log('❌ Faucet request failed. Try again in a few minutes.\\n');\n }\n return;\n }\n\n // If no address provided, try to use initialized EVM wallet\n if (!address) {\n const client = new MoltsPayClient({ configDir: options.configDir });\n if (client.isInitialized) {\n address = client.address;\n } else {\n console.log('❌ No wallet found. Either run \"npx moltspay init\" or provide --address');\n return;\n }\n }\n\n // Validate EVM address format\n if (!address.match(/^0x[a-fA-F0-9]{40}$/)) {\n console.log('❌ Invalid Ethereum address');\n return;\n }\n\n console.log('\\n🚰 MoltsPay Testnet Faucet\\n');\n\n if (chain === 'tempo_moderato') {\n // Tempo Moderato faucet\n console.log(` Requesting testnet tokens on Tempo Moderato...`);\n console.log(` Address: ${address}\\n`);\n\n try {\n // Tempo docs faucet API - sends all 4 testnet tokens (pathUSD, AlphaUSD, BetaUSD, ThetaUSD)\n const TEMPO_FAUCET_API = 'https://docs.tempo.xyz/api/faucet';\n \n const response = await fetch(TEMPO_FAUCET_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ address }),\n });\n\n const result = await response.json() as { data?: { hash: string }[]; error?: string };\n\n if (response.ok && result.data && result.data.length > 0) {\n console.log(`✅ Received testnet tokens!\\n`);\n console.log(` Tokens: pathUSD, AlphaUSD, BetaUSD, ThetaUSD (1M each)`);\n console.log(` Transactions:`);\n for (const tx of result.data) {\n console.log(` https://explore.testnet.tempo.xyz/tx/${tx.hash}`);\n }\n console.log('\\n💡 Use these tokens to test MPP payments:');\n console.log(` npx moltspay pay <service-url> <service-id> --chain tempo_moderato\\n`);\n } else {\n console.log(`❌ ${result.error || 'Faucet request failed'}`);\n console.log('\\n Try again later or use Tempo Wallet: https://wallet.tempo.xyz\\n');\n }\n } catch (error) {\n console.log(`❌ ${(error as Error).message}`);\n console.log('\\n Try Tempo Wallet instead: https://wallet.tempo.xyz\\n');\n }\n } else if (chain === 'bnb_testnet') {\n // BNB Testnet faucet - uses unified MoltsPay faucet API\n console.log(` Requesting 1 USDC on BNB Testnet...`);\n console.log(` Address: ${address}\\n`);\n\n try {\n const FAUCET_API = process.env.MOLTSPAY_FAUCET_API || 'https://moltspay.com/api/v1/faucet';\n \n const response = await fetch(FAUCET_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ address, chain: 'bnb_testnet' }),\n });\n\n const result = await response.json() as {\n success?: boolean;\n amount?: string;\n token?: string;\n chain_name?: string;\n transaction?: string;\n explorer?: string;\n faucet_balance?: string;\n error?: string;\n hint?: string;\n retry_after?: string;\n };\n\n if (!response.ok) {\n console.log(`❌ ${result.error || 'Request failed'}`);\n if (result.hint) console.log(` ${result.hint}`);\n if (result.retry_after) console.log(` Retry after: ${result.retry_after}`);\n \n // Show manual faucet instructions as fallback\n console.log('\\n💡 Alternatively, get tokens manually:');\n console.log(` 1. Get test BNB: https://www.bnbchain.org/en/testnet-faucet`);\n console.log(` 2. Select \"Peggy Tokens\" -> USDC`);\n console.log(` 3. Enter: ${address}\\n`);\n return;\n }\n\n console.log(`✅ Received ${result.amount} ${result.token || 'USDC'} on ${result.chain_name || 'BNB Testnet'}!\\n`);\n console.log(` Transaction: ${result.explorer || `https://testnet.bscscan.com/tx/${result.transaction}`}`);\n if (result.faucet_balance) {\n console.log(` Faucet balance: ${result.faucet_balance} USDC`);\n }\n console.log('\\n💡 Now you can test BNB payments:');\n console.log(` npx moltspay pay <service-url> <service-id> --chain bnb_testnet\\n`);\n } catch (error) {\n console.log(`❌ ${(error as Error).message}`);\n console.log('\\n💡 Get tokens manually:');\n console.log(` 1. Get test BNB: https://www.bnbchain.org/en/testnet-faucet`);\n console.log(` 2. Select \"Peggy Tokens\" -> USDC`);\n console.log(` 3. Enter: ${address}\\n`);\n }\n } else {\n // Base Sepolia faucet (existing)\n console.log(` Requesting 1 USDC on Base Sepolia...`);\n console.log(` Address: ${address}\\n`);\n\n try {\n const FAUCET_API = process.env.MOLTSPAY_FAUCET_API || 'https://moltspay.com/api/v1/faucet';\n \n const response = await fetch(FAUCET_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ address, chain: 'base_sepolia' }),\n });\n\n const result = await response.json() as {\n success?: boolean;\n amount?: string;\n transaction?: string;\n explorer?: string;\n faucet_balance?: string;\n error?: string;\n hint?: string;\n retry_after?: string;\n };\n\n if (!response.ok) {\n console.log(`❌ ${result.error || 'Request failed'}`);\n if (result.hint) console.log(` ${result.hint}`);\n if (result.retry_after) console.log(` Retry after: ${result.retry_after}`);\n return;\n }\n\n console.log(`✅ Received ${result.amount} USDC!\\n`);\n console.log(` Transaction: ${result.transaction}`);\n console.log(` Explorer: ${result.explorer}`);\n console.log(` Faucet balance: ${result.faucet_balance} USDC remaining\\n`);\n console.log('💡 Use this USDC to test x402 payments:');\n console.log(` npx moltspay pay <service-url> <service-id> --chain base_sepolia\\n`);\n } catch (error) {\n console.log(`❌ ${(error as Error).message}`);\n }\n }\n });\n\n/**\n * npx moltspay status\n */\nprogram\n .command('status')\n .description('Show wallet status and balance')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n\n if (!client.isInitialized) {\n if (options.json) {\n console.log(JSON.stringify({ error: 'Not initialized' }));\n } else {\n console.log('❌ Not initialized. Run: npx moltspay init');\n }\n return;\n }\n\n const config = client.getConfig();\n \n // Get balances on all supported chains\n let allBalances: Record<string, { usdc: number; usdt: number; native: number }> = {};\n try {\n allBalances = await client.getAllBalances();\n } catch (err: any) {\n console.error('Warning: Could not fetch balances:', err.message);\n }\n\n // Check for Solana wallet\n const solanaAddress = getSolanaAddress(options.configDir);\n let solanaBalances: { devnet?: { sol: number; usdc: number }; mainnet?: { sol: number; usdc: number } } = {};\n \n if (solanaAddress) {\n try {\n solanaBalances.devnet = await getSolanaBalances(solanaAddress, 'solana_devnet');\n } catch { /* ignore */ }\n try {\n solanaBalances.mainnet = await getSolanaBalances(solanaAddress, 'solana');\n } catch { /* ignore */ }\n }\n\n if (options.json) {\n const output: any = {\n address: client.address,\n balances: allBalances,\n limits: config.limits,\n };\n if (solanaAddress) {\n output.solana = {\n address: solanaAddress,\n balances: solanaBalances,\n };\n }\n console.log(JSON.stringify(output, null, 2));\n } else {\n console.log('\\n📊 MoltsPay Wallet Status\\n');\n console.log(` Address: ${client.address}`);\n console.log('');\n console.log(' Balances:');\n for (const [chainName, balance] of Object.entries(allBalances)) {\n // Format chain label nicely\n let chainLabel: string;\n if (chainName === 'base_sepolia') {\n chainLabel = 'Base Sepolia';\n } else if (chainName === 'tempo_moderato') {\n chainLabel = 'Tempo Moderato';\n } else {\n chainLabel = chainName.charAt(0).toUpperCase() + chainName.slice(1);\n }\n \n // Tempo: show all 4 testnet tokens + native balance\n if (chainName === 'tempo_moderato' && (balance as any).tempo) {\n const tempo = (balance as any).tempo;\n // Format large native balance with scientific notation if needed\n const nativeStr = balance.native > 1e12 \n ? balance.native.toExponential(2) \n : balance.native.toFixed(2);\n console.log(` ${chainLabel}:`);\n console.log(` Native: ${nativeStr} TEMPO (for gas)`);\n console.log(` pathUSD: ${tempo.pathUSD.toFixed(2)}`);\n console.log(` alphaUSD: ${tempo.alphaUSD.toFixed(2)}`);\n console.log(` betaUSD: ${tempo.betaUSD.toFixed(2)}`);\n console.log(` thetaUSD: ${tempo.thetaUSD.toFixed(2)}`);\n } else if (chainName === 'bnb' || chainName === 'bnb_testnet') {\n // BNB chains: show balance + native BNB for gas\n const bnbBalance = balance.native;\n const bnbWarning = bnbBalance < 0.0005 ? ' ⚠️ Low gas' : '';\n console.log(` ${chainLabel.padEnd(14)} ${balance.usdc.toFixed(2)} USDC | ${balance.usdt.toFixed(2)} USDT | ${bnbBalance.toFixed(4)} BNB${bnbWarning}`);\n } else {\n // EVM chains: show USDC/USDT\n console.log(` ${chainLabel.padEnd(14)} ${balance.usdc.toFixed(2)} USDC | ${balance.usdt.toFixed(2)} USDT`);\n }\n }\n \n // Check BNB approval status\n const address = client.address!;\n let bnbApprovalStatus: { usdt: boolean; usdc: boolean; spender: string | null } | null = null;\n let bnbTestnetApprovalStatus: { usdt: boolean; usdc: boolean; spender: string | null } | null = null;\n \n try {\n if (allBalances['bnb']) {\n bnbApprovalStatus = await checkBNBApprovals(address, 'bnb', options.configDir);\n }\n if (allBalances['bnb_testnet']) {\n bnbTestnetApprovalStatus = await checkBNBApprovals(address, 'bnb_testnet', options.configDir);\n }\n } catch { /* ignore approval check errors */ }\n \n if (bnbApprovalStatus || bnbTestnetApprovalStatus) {\n console.log('');\n console.log(' BNB Approvals (pay-for-success):');\n if (bnbApprovalStatus) {\n if (!bnbApprovalStatus.spender) {\n console.log(' BNB: ⚠️ No spender configured');\n console.log(' └─ Run a payment first, or: npx moltspay approve --chain bnb --spender <address>');\n } else {\n const status = bnbApprovalStatus.usdt && bnbApprovalStatus.usdc ? '✅' : '⚠️';\n const tokens = [\n bnbApprovalStatus.usdt ? 'USDT✓' : 'USDT✗',\n bnbApprovalStatus.usdc ? 'USDC✓' : 'USDC✗',\n ].join(', ');\n console.log(` BNB: ${status} ${tokens}`);\n \n // Show warning if no approval and low BNB\n const bnbNative = allBalances['bnb']?.native || 0;\n if (!bnbApprovalStatus.usdc && !bnbApprovalStatus.usdt && bnbNative < 0.0005) {\n console.log(' ⚠️ Need ~0.001 BNB for first approval tx. Get from exchange.');\n }\n }\n }\n if (bnbTestnetApprovalStatus) {\n if (!bnbTestnetApprovalStatus.spender) {\n console.log(' BNB Testnet: ⚠️ No spender configured');\n console.log(' └─ Run a payment first, or: npx moltspay approve --chain bnb_testnet --spender <address>');\n } else {\n const status = bnbTestnetApprovalStatus.usdt && bnbTestnetApprovalStatus.usdc ? '✅' : '⚠️';\n const tokens = [\n bnbTestnetApprovalStatus.usdt ? 'USDT✓' : 'USDT✗',\n bnbTestnetApprovalStatus.usdc ? 'USDC✓' : 'USDC✗',\n ].join(', ');\n console.log(` BNB Testnet: ${status} ${tokens}`);\n \n // Show warning if no approval and low tBNB\n const tbnbNative = allBalances['bnb_testnet']?.native || 0;\n if (!bnbTestnetApprovalStatus.usdc && !bnbTestnetApprovalStatus.usdt && tbnbNative < 0.0005) {\n console.log(' ⚠️ Need tBNB for approval. Run: npx moltspay faucet --chain bnb_testnet');\n }\n }\n }\n }\n \n console.log('');\n console.log(' Spending Limits:');\n console.log(` Per Transaction: $${config.limits.maxPerTx}`);\n console.log(` Daily: $${config.limits.maxPerDay}`);\n \n // Show Solana wallet status if it exists\n const solanaAddress = getSolanaAddress(options.configDir);\n if (solanaAddress) {\n console.log('');\n console.log(' ─────────────────────────────────');\n console.log(` 🟣 Solana: ${solanaAddress}`);\n \n try {\n // Get Solana devnet balances\n const devnetBalances = await getSolanaBalances(solanaAddress, 'solana_devnet');\n console.log(` Devnet: ${devnetBalances.sol.toFixed(4)} SOL | ${devnetBalances.usdc.toFixed(2)} USDC`);\n } catch (err: any) {\n console.log(` Devnet: (unable to fetch)`);\n }\n \n try {\n // Get Solana mainnet balances\n const mainnetBalances = await getSolanaBalances(solanaAddress, 'solana');\n console.log(` Mainnet: ${mainnetBalances.sol.toFixed(4)} SOL | ${mainnetBalances.usdc.toFixed(2)} USDC`);\n } catch (err: any) {\n console.log(` Mainnet: (unable to fetch)`);\n }\n }\n \n console.log('');\n }\n });\n\n/**\n * npx moltspay list\n * \n * List transactions for the agent wallet using Blockscout APIs (free, no API key needed)\n */\nprogram\n .command('list')\n .description('List recent transactions')\n .option('--days <n>', 'Number of days to look back', '7')\n .option('--chain <chain>', 'Chain to query (base, polygon, base_sepolia, or all)', 'all')\n .option('--limit <n>', 'Max transactions to show', '20')\n .option('--config-dir <dir>', 'Config directory', DEFAULT_CONFIG_DIR)\n .action(async (options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n\n if (!client.isInitialized) {\n console.log('❌ Not initialized. Run: npx moltspay init');\n return;\n }\n\n const days = parseInt(options.days) || 7;\n const limit = parseInt(options.limit) || 20;\n const chain = options.chain?.toLowerCase() || 'all';\n\n if (!['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'all'].includes(chain)) {\n console.log('❌ Invalid chain. Use: base, polygon, base_sepolia, tempo_moderato, or all');\n return;\n }\n\n const wallet = client.address!;\n const cutoffTime = Date.now() - (days * 24 * 60 * 60 * 1000);\n\n // Blockscout API configs (free, no API key needed)\n const explorers: Record<string, { api: string; usdc: string; name: string }> = {\n base: {\n api: 'https://base.blockscout.com/api/v2',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n name: 'Base',\n },\n polygon: {\n api: 'https://polygon.blockscout.com/api/v2',\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n name: 'Polygon',\n },\n base_sepolia: {\n api: 'https://base-sepolia.blockscout.com/api/v2',\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n name: 'Base Sepolia',\n },\n // Tempo explorer doesn't have public API yet\n tempo_moderato: {\n api: '', // No API available\n usdc: '0x20c0000000000000000000000000000000000000',\n name: 'Tempo Moderato',\n },\n };\n\n const chainsToQuery = chain === 'all' ? ['base', 'polygon', 'base_sepolia', 'tempo_moderato'] : [chain];\n\n console.log(`\\n📜 Transactions (last ${days} day${days > 1 ? 's' : ''})\\n`);\n\n interface TokenTx {\n chain: string;\n timestamp: number;\n type: string;\n amount: number;\n other: string;\n hash: string;\n token?: string; // Token name (e.g., pathUSD, alphaUSD for Tempo)\n }\n\n let allTxns: TokenTx[] = [];\n\n for (const c of chainsToQuery) {\n const explorer = explorers[c];\n \n try {\n if (c === 'tempo_moderato') {\n // Tempo: use eth_getLogs RPC instead of Blockscout API\n const tempoTokens = [\n { address: '0x20c0000000000000000000000000000000000000', name: 'pathUSD' },\n { address: '0x20c0000000000000000000000000000000000001', name: 'alphaUSD' },\n { address: '0x20c0000000000000000000000000000000000002', name: 'betaUSD' },\n { address: '0x20c0000000000000000000000000000000000003', name: 'thetaUSD' },\n ];\n \n // Transfer event topic: keccak256(\"Transfer(address,address,uint256)\")\n const transferTopic = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';\n const walletTopic = '0x000000000000000000000000' + wallet.toLowerCase().slice(2);\n \n // Get latest block with retry\n let latestBlock = 0;\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n const blockRes = await fetch('https://rpc.moderato.tempo.xyz', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ jsonrpc: '2.0', method: 'eth_blockNumber', params: [], id: 1 }),\n });\n const blockData = await blockRes.json() as { result: string };\n if (blockData.result) {\n latestBlock = parseInt(blockData.result, 16);\n break;\n }\n } catch (e) {\n if (attempt === 2) throw e;\n await new Promise(r => setTimeout(r, 500)); // Wait 500ms before retry\n }\n }\n \n if (latestBlock === 0) {\n console.log(' ⚠️ Tempo Moderato: Could not get latest block');\n continue;\n }\n \n // Tempo RPC has 100000 block limit, so we can only query ~14 hours back\n // For longer ranges, we'd need multiple queries (not implemented yet)\n const maxBlocks = 100000;\n const blocksPerDay = 172800; // at ~0.5s/block\n const requestedBlocks = blocksPerDay * days;\n const actualBlocks = Math.min(requestedBlocks, maxBlocks);\n const fromBlock = '0x' + Math.max(0, latestBlock - actualBlocks).toString(16);\n const toBlock = '0x' + latestBlock.toString(16); // Use fixed block to avoid range drift\n \n // Note: Tempo RPC has 100k block limit (~14 hours at 0.5s/block)\n if (requestedBlocks > maxBlocks) {\n console.log(` ℹ️ Tempo: querying last ~14 hours (RPC limit: 100k blocks)`);\n }\n \n for (const token of tempoTokens) {\n try {\n // Query incoming transfers (to = wallet)\n const inRes = await fetch('https://rpc.moderato.tempo.xyz', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_getLogs',\n params: [{ fromBlock, toBlock, address: token.address, topics: [transferTopic, null, walletTopic] }],\n id: 1,\n }),\n });\n const inData = await inRes.json() as { result?: Array<{ data: string; topics: string[]; transactionHash: string; blockTimestamp: string }>; error?: { message: string } };\n \n if (inData.error) {\n console.log(` ⚠️ ${token.name}: ${inData.error.message}`);\n continue;\n }\n \n if (inData.result && Array.isArray(inData.result)) {\n for (const log of inData.result) {\n const timestamp = parseInt(log.blockTimestamp, 16) * 1000;\n if (timestamp < cutoffTime) continue;\n const amount = parseInt(log.data, 16) / 1e6;\n const from = '0x' + log.topics[1].slice(26);\n allTxns.push({\n chain: c,\n timestamp,\n type: 'IN',\n amount,\n other: from,\n hash: log.transactionHash,\n token: token.name,\n });\n }\n }\n \n // Query outgoing transfers (from = wallet)\n const outRes = await fetch('https://rpc.moderato.tempo.xyz', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_getLogs',\n params: [{ fromBlock, toBlock, address: token.address, topics: [transferTopic, walletTopic, null] }],\n id: 1,\n }),\n });\n const outData = await outRes.json() as { result?: Array<{ data: string; topics: string[]; transactionHash: string; blockTimestamp: string }>; error?: { message: string } };\n \n if (outData.result && Array.isArray(outData.result)) {\n for (const log of outData.result) {\n const timestamp = parseInt(log.blockTimestamp, 16) * 1000;\n if (timestamp < cutoffTime) continue;\n const amount = parseInt(log.data, 16) / 1e6;\n const to = '0x' + log.topics[2].slice(26);\n allTxns.push({\n chain: c,\n timestamp,\n type: 'OUT',\n amount,\n other: to,\n hash: log.transactionHash,\n token: token.name,\n });\n }\n }\n } catch (tokenError) {\n // Silently continue to next token if one fails\n continue;\n }\n }\n } else {\n // Other chains: use Blockscout API\n const url = `${explorer.api}/addresses/${wallet}/token-transfers?type=ERC-20&token=${explorer.usdc}`;\n const response = await fetch(url);\n const data = await response.json() as { \n items: Array<{\n timestamp: string;\n from: { hash: string };\n to: { hash: string };\n total: { value: string; decimals: string };\n transaction_hash: string;\n }>;\n };\n\n if (data.items && Array.isArray(data.items)) {\n for (const tx of data.items) {\n const timestamp = new Date(tx.timestamp).getTime();\n if (timestamp < cutoffTime) continue;\n\n const isIncoming = tx.to.hash.toLowerCase() === wallet.toLowerCase();\n const decimals = parseInt(tx.total.decimals) || 6;\n allTxns.push({\n chain: c,\n timestamp,\n type: isIncoming ? 'IN' : 'OUT',\n amount: parseInt(tx.total.value) / Math.pow(10, decimals),\n other: isIncoming ? tx.from.hash : tx.to.hash,\n hash: tx.transaction_hash,\n });\n }\n }\n }\n } catch (error) {\n // Show error details for debugging\n const errMsg = error instanceof Error ? error.message : String(error);\n console.log(` ⚠️ ${explorer.name}: ${errMsg}`);\n }\n }\n\n // Sort by timestamp descending\n allTxns.sort((a, b) => b.timestamp - a.timestamp);\n\n // Apply limit\n allTxns = allTxns.slice(0, limit);\n\n if (allTxns.length === 0) {\n console.log(' (no transactions found)\\n');\n } else {\n for (const tx of allTxns) {\n const sign = tx.type === 'IN' ? '+' : '-';\n const color = tx.type === 'IN' ? '\\x1b[32m' : '\\x1b[31m';\n const reset = '\\x1b[0m';\n const date = new Date(tx.timestamp).toISOString().slice(5, 16).replace('T', ' ');\n let chainLabel = tx.chain.toUpperCase();\n if (tx.chain === 'tempo_moderato') chainLabel = 'TEMPO';\n else if (tx.chain === 'base_sepolia') chainLabel = 'BASE_SEPOLIA';\n const chainTag = chain === 'all' ? `[${chainLabel}] ` : '';\n \n const tokenName = tx.token || 'USDC';\n console.log(` ${color}${sign}${tx.amount.toFixed(2)} ${tokenName}${reset} | ${chainTag}${tx.type === 'IN' ? 'from' : 'to'} ${tx.other.slice(0, 10)}...${tx.other.slice(-4)} | ${date}`);\n }\n \n // Summary\n const inTotal = allTxns.filter(t => t.type === 'IN').reduce((s, t) => s + t.amount, 0);\n const outTotal = allTxns.filter(t => t.type === 'OUT').reduce((s, t) => s + t.amount, 0);\n console.log(`\\n 📊 ${allTxns.length} transaction(s) | \\x1b[32m+$${inTotal.toFixed(2)}\\x1b[0m in | \\x1b[31m-$${outTotal.toFixed(2)}\\x1b[0m out\\n`);\n }\n });\n\n/**\n * npx moltspay services <url>\n */\nprogram\n .command('services [url]')\n .description('List services from registry or a specific provider')\n .option('-q, --query <keyword>', 'Search by keyword (name, description, tags)')\n .option('--max-price <price>', 'Maximum price in USD')\n .option('--type <type>', 'Filter by type: api_service | file_download')\n .option('--tag <tag>', 'Filter by tag')\n .option('--json', 'Output as JSON')\n .action(async (url, options) => {\n const MOLTSPAY_REGISTRY = 'https://moltspay.com';\n \n try {\n let services: any;\n let isRegistry = false;\n \n if (url) {\n // Query specific provider\n const client = new MoltsPayClient();\n services = await client.getServices(url);\n } else {\n // Query MoltsPay registry with filters\n isRegistry = true;\n const params = new URLSearchParams();\n if (options.query) params.set('q', options.query);\n if (options.maxPrice) params.set('maxPrice', options.maxPrice);\n if (options.type) params.set('type', options.type);\n if (options.tag) params.set('tag', options.tag);\n \n const queryString = params.toString();\n const registryUrl = `${MOLTSPAY_REGISTRY}/registry/services${queryString ? '?' + queryString : ''}`;\n \n const res = await fetch(registryUrl);\n if (!res.ok) {\n throw new Error(`Registry request failed: ${res.status}`);\n }\n services = await res.json();\n }\n\n if (options.json) {\n console.log(JSON.stringify(services, null, 2));\n } else {\n const serviceList = services.services || [];\n \n if (isRegistry) {\n // Registry listing\n if (options.query) {\n console.log(`\\n🔍 Search: \"${options.query}\" (${serviceList.length} results)\\n`);\n } else {\n const filters = [];\n if (options.maxPrice) filters.push(`max $${options.maxPrice}`);\n if (options.type) filters.push(options.type);\n if (options.tag) filters.push(`#${options.tag}`);\n const filterStr = filters.length > 0 ? ` (${filters.join(', ')})` : '';\n console.log(`\\n🔍 MoltsPay Registry${filterStr} - ${serviceList.length} services\\n`);\n }\n \n // Table-like output for registry\n for (const svc of serviceList) {\n const name = (svc.name || svc.id).slice(0, 30).padEnd(30);\n const price = `$${svc.price}`.padEnd(8);\n const type = (svc.type || 'unknown').padEnd(14);\n const provider = `@${svc.provider?.username || 'unknown'}`;\n console.log(` ${name} ${price} ${type} ${provider}`);\n }\n \n if (serviceList.length > 0) {\n console.log(`\\n 💡 Use: moltspay pay <provider-url> <service-id>\\n`);\n }\n } else {\n // Single provider format\n if (services.provider) {\n console.log(`\\n🏪 ${services.provider.name}\\n`);\n console.log(` ${services.provider.description || ''}`);\n console.log(` Wallet: ${services.provider.wallet}`);\n \n const chains = services.provider.chains \n ? (Array.isArray(services.provider.chains) \n ? services.provider.chains.map((c: any) => typeof c === 'string' ? c : c.chain).join(', ')\n : services.provider.chains)\n : services.provider.chain || 'base';\n console.log(` Chains: ${chains}`);\n } else {\n console.log(`\\n🏪 Provider Services\\n`);\n console.log(` ${serviceList.length} services available`);\n }\n \n console.log('\\n📦 Services:\\n');\n \n for (const svc of serviceList) {\n const status = svc.available !== false ? '✅' : '❌';\n console.log(` ${status} ${svc.id || svc.name}`);\n console.log(` ${svc.name} - $${svc.price} ${svc.currency}`);\n if (svc.description) {\n console.log(` ${svc.description}`);\n }\n if (svc.provider && !services.provider) {\n console.log(` Provider: ${svc.provider.name || svc.provider.username}`);\n }\n console.log('');\n }\n }\n }\n } catch (err: any) {\n console.error('❌ Error:', err.message);\n }\n });\n\n/**\n * npx moltspay start <paths...>\n * \n * Start server from skill directories or manifest files.\n * \n * Supports:\n * - Skill directory: ./skills/video_gen/ (with moltspay.services.json + index.js)\n * - Legacy manifest: ./moltspay.services.json (with optional command field)\n * - Multiple paths: ./skills/video_gen/ ./skills/translation/\n * \n * Services with \"function\" field load from skill's index.js\n * Services with \"command\" field execute shell commands (legacy)\n */\nprogram\n .command('start <paths...>')\n .description('Start MoltsPay server from skill directories or manifest files')\n .option('-p, --port <port>', 'Port to listen on', '3000')\n .option('--host <host>', 'Host to bind', '0.0.0.0')\n .option('--facilitator <url>', 'x402 facilitator URL (default: https://x402.org/facilitator)')\n .action(async (paths, options) => {\n const port = parseInt(options.port, 10);\n const host = options.host;\n const facilitatorUrl = options.facilitator;\n\n // Support comma-separated paths\n const allPaths = paths.flatMap((p: string) => p.split(',').map(s => s.trim())).filter(Boolean);\n\n console.log(`\\n🚀 Starting MoltsPay Server (x402 protocol)\\n`);\n\n // Collect all services and handlers from all paths\n const allServices: any[] = [];\n const handlers: Map<string, (params: any) => Promise<any>> = new Map();\n let provider: any = null;\n\n for (const inputPath of allPaths) {\n const resolvedPath = resolve(inputPath);\n \n // Determine if it's a directory (skill) or file (manifest)\n let manifestPath: string;\n let skillDir: string;\n let isSkillDir = false;\n\n if (existsSync(join(resolvedPath, 'moltspay.services.json'))) {\n // It's a skill directory\n manifestPath = join(resolvedPath, 'moltspay.services.json');\n skillDir = resolvedPath;\n isSkillDir = true;\n } else if (existsSync(resolvedPath) && resolvedPath.endsWith('.json')) {\n // It's a manifest file\n manifestPath = resolvedPath;\n skillDir = dirname(resolvedPath);\n } else if (existsSync(resolvedPath)) {\n // Directory without moltspay.services.json\n console.error(`❌ No moltspay.services.json found in: ${resolvedPath}`);\n continue;\n } else {\n console.error(`❌ Path not found: ${resolvedPath}`);\n continue;\n }\n\n console.log(`📦 Loading: ${manifestPath}`);\n\n try {\n const manifestContent = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n \n // Use first provider found, or merge\n if (!provider) {\n provider = manifestContent.provider;\n }\n\n // Load skill module if it's a skill directory\n let skillModule: any = null;\n if (isSkillDir) {\n // Determine entry point: check package.json main, fallback to index.js\n let entryPoint = 'index.js';\n const pkgJsonPath = join(skillDir, 'package.json');\n if (existsSync(pkgJsonPath)) {\n try {\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));\n if (pkgJson.main) {\n entryPoint = pkgJson.main;\n }\n } catch {\n // Ignore package.json parse errors\n }\n }\n\n const modulePath = join(skillDir, entryPoint);\n if (existsSync(modulePath)) {\n try {\n skillModule = await import(modulePath);\n console.log(` ✅ Loaded module: ${modulePath}`);\n } catch (err: any) {\n console.error(` ⚠️ Failed to load module: ${err.message}`);\n }\n } else {\n console.error(` ⚠️ Entry point not found: ${modulePath}`);\n }\n }\n\n // Register each service\n for (const service of manifestContent.services) {\n allServices.push(service);\n\n // Priority: function > command\n if (service.function && skillModule) {\n // New skill-based approach: import function from index.js\n const fn = skillModule[service.function] || skillModule.default?.[service.function];\n if (fn && typeof fn === 'function') {\n handlers.set(service.id, fn);\n console.log(` ✅ ${service.id} → ${service.function}()`);\n } else {\n console.error(` ❌ Function '${service.function}' not found in index.js`);\n }\n } else if (service.command) {\n // Legacy command-based approach\n const workdir = skillDir;\n handlers.set(service.id, async (params) => {\n return new Promise((resolvePromise, reject) => {\n const proc = spawn('sh', ['-c', service.command], {\n cwd: workdir,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n\n proc.stdout.on('data', (data) => {\n stdout += data.toString();\n });\n\n proc.stderr.on('data', (data) => {\n stderr += data.toString();\n process.stderr.write(data);\n });\n\n proc.stdin.write(JSON.stringify(params));\n proc.stdin.end();\n\n proc.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Command failed (exit ${code}): ${stderr || 'Unknown error'}`));\n return;\n }\n try {\n resolvePromise(JSON.parse(stdout.trim()));\n } catch {\n resolvePromise({ output: stdout.trim() });\n }\n });\n\n proc.on('error', (err) => {\n reject(new Error(`Failed to spawn command: ${err.message}`));\n });\n });\n });\n console.log(` ✅ ${service.id} → command`);\n } else {\n console.warn(` ⚠️ ${service.id}: no function or command defined`);\n }\n }\n } catch (err: any) {\n console.error(`❌ Failed to load ${manifestPath}: ${err.message}`);\n continue;\n }\n }\n\n if (allServices.length === 0) {\n console.error('\\n❌ No services loaded. Exiting.');\n process.exit(1);\n }\n\n if (!provider) {\n console.error('\\n❌ No provider config found. Exiting.');\n process.exit(1);\n }\n\n // Create combined manifest for server\n const combinedManifest = {\n provider,\n services: allServices,\n };\n\n // Write temporary manifest for server\n const tempManifestPath = join(DEFAULT_CONFIG_DIR, 'combined-manifest.json');\n writeFileSync(tempManifestPath, JSON.stringify(combinedManifest, null, 2));\n\n console.log(`\\n📋 Combined manifest: ${allServices.length} services`);\n console.log(` Provider: ${provider.name}`);\n console.log(` Wallet: ${provider.wallet}`);\n console.log(` Port: ${port}`);\n console.log('');\n\n try {\n const server = new MoltsPayServer(tempManifestPath, { port, host, facilitatorUrl });\n\n // Register all handlers\n for (const [serviceId, handler] of handlers) {\n server.skill(serviceId, handler);\n }\n\n // Write PID file\n const pidData = { pid: process.pid, port, paths: allPaths };\n writeFileSync(PID_FILE, JSON.stringify(pidData, null, 2));\n\n // Start listening\n server.listen(port);\n\n // Cleanup function\n const cleanup = () => {\n try {\n if (existsSync(PID_FILE)) unlinkSync(PID_FILE);\n if (existsSync(tempManifestPath)) unlinkSync(tempManifestPath);\n } catch {}\n };\n\n process.on('SIGINT', () => {\n console.log('\\n\\n👋 Shutting down...');\n cleanup();\n process.exit(0);\n });\n\n process.on('SIGTERM', () => {\n console.log('\\n\\n👋 Shutting down...');\n cleanup();\n process.exit(0);\n });\n\n process.on('exit', cleanup);\n\n } catch (err: any) {\n console.error(`❌ Failed to start server: ${err.message}`);\n process.exit(1);\n }\n });\n\n/**\n * npx moltspay stop\n * \n * Stop the running MoltsPay server gracefully\n */\nprogram\n .command('stop')\n .description('Stop the running MoltsPay server')\n .action(async () => {\n if (!existsSync(PID_FILE)) {\n console.log('❌ No running server found (no PID file)');\n process.exit(1);\n }\n\n try {\n const pidData = JSON.parse(readFileSync(PID_FILE, 'utf-8'));\n const { pid, port, manifest } = pidData;\n\n console.log(`\\n🛑 Stopping MoltsPay Server\\n`);\n console.log(` PID: ${pid}`);\n console.log(` Port: ${port}`);\n console.log(` Manifest: ${manifest}`);\n console.log('');\n\n // Check if process is running\n try {\n process.kill(pid, 0); // Test if process exists\n } catch {\n console.log('⚠️ Process not running, cleaning up PID file...');\n unlinkSync(PID_FILE);\n process.exit(0);\n }\n\n // Send SIGTERM for graceful shutdown\n process.kill(pid, 'SIGTERM');\n console.log('✅ Sent SIGTERM to server');\n\n // Wait a bit and check if it stopped\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n try {\n process.kill(pid, 0);\n console.log('⚠️ Server still running, sending SIGKILL...');\n process.kill(pid, 'SIGKILL');\n } catch {\n // Process is gone, good\n }\n\n // Clean up PID file if still exists\n if (existsSync(PID_FILE)) {\n unlinkSync(PID_FILE);\n }\n\n console.log('✅ Server stopped\\n');\n\n } catch (err: any) {\n console.error(`❌ Failed to stop server: ${err.message}`);\n process.exit(1);\n }\n });\n\n/**\n * npx moltspay pay <server> <service> <params>\n * \n * Pay for a service and get the result\n * \n * --image can be a URL or local file path:\n * URL: https://example.com/image.jpg -> sends as image_url\n * File: ./image.jpg or /path/to/image.jpg -> sends as image_base64\n * \n * --token specifies which stablecoin to use (USDC or USDT)\n * --chain specifies which chain to pay on (base or polygon, default: base)\n */\nprogram\n .command('pay <server> <service> [params]')\n .description('Pay for a service and get the result')\n .option('--prompt <text>', 'Prompt for the service')\n .option('--image <path>', 'Image URL or local file path')\n .option('--data <json>', 'Raw JSON data to send (for custom input formats)')\n .option('--token <token>', 'Token to pay with (USDC or USDT)', 'USDC')\n .option('--chain <chain>', 'Chain to pay on (base, polygon, base_sepolia, tempo_moderato, solana, or solana_devnet).')\n .option('--rail <rail>', 'Payment rail: a chain name, or \"alipay\" for the Alipay fiat rail (CNY via alipay-bot)')\n .option('--config-dir <dir>', 'Config directory with wallet.json', DEFAULT_CONFIG_DIR)\n .option('--json', 'Output raw JSON only')\n .action(async (server, service, paramsJson, options) => {\n const client = new MoltsPayClient({ configDir: options.configDir });\n const useAlipay = options.rail?.toLowerCase() === 'alipay';\n\n // The Alipay rail is backed by alipay-bot and needs no EVM wallet.\n if (!useAlipay && !client.isInitialized) {\n console.error('❌ Wallet not initialized. Run: npx moltspay init');\n process.exit(1);\n }\n\n // Build params from JSON string or options\n let params: Record<string, any> = {};\n let useRawData = false;\n \n // --data flag: raw JSON for custom input formats (takes priority)\n if (options.data) {\n try {\n params = JSON.parse(options.data);\n useRawData = true;\n } catch {\n console.error('❌ Invalid JSON in --data flag');\n process.exit(1);\n }\n } else if (paramsJson) {\n try {\n params = JSON.parse(paramsJson);\n } catch {\n console.error('❌ Invalid JSON params');\n process.exit(1);\n }\n }\n \n // Override with CLI options (only if not using --data)\n if (!useRawData && options.prompt) params.prompt = options.prompt;\n \n // Handle --image: URL or local file\n if (options.image) {\n const imagePath = options.image;\n \n if (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {\n // It's a URL\n params.image_url = imagePath;\n } else {\n // It's a local file - read and convert to base64\n const filePath = resolve(imagePath);\n \n if (!existsSync(filePath)) {\n console.error(`❌ Image file not found: ${filePath}`);\n process.exit(1);\n }\n \n const imageData = readFileSync(filePath);\n params.image_base64 = imageData.toString('base64');\n }\n }\n\n // Validate chain option (if specified)\n const supportedPayChains = ['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'bnb', 'bnb_testnet', 'solana', 'solana_devnet'];\n const chain = options.chain?.toLowerCase();\n if (chain && !supportedPayChains.includes(chain)) {\n console.error(`❌ Unknown chain: ${chain}. Supported: ${supportedPayChains.join(', ')}`);\n process.exit(1);\n }\n\n const imageDisplay = params.image_url || (params.image_base64 ? `[local file: ${options.image}]` : null);\n const token = (options.token || 'USDC').toUpperCase();\n\n // USDT requires gas - check native balance (EVM rails only)\n if (!useAlipay && token === 'USDT') {\n const balance = await client.getBalance();\n if (balance.native < 0.0001) {\n console.log('\\n⚠️ USDT requires a small amount of ETH for gas (~$0.01)');\n console.log(` Your ETH balance: ${balance.native.toFixed(6)} ETH`);\n console.log(' Please add a tiny amount of ETH to your wallet.\\n');\n process.exit(1);\n }\n if (!options.json) {\n console.log('\\n⚠️ Note: USDT payments require gas (~$0.01 on Base)');\n }\n }\n\n if (!options.json) {\n console.log(`\\n💳 MoltsPay - Paying for service\\n`);\n console.log(` Server: ${server}`);\n console.log(` Service: ${service}`);\n if (useRawData) {\n console.log(` Data: ${JSON.stringify(params).slice(0, 50)}${JSON.stringify(params).length > 50 ? '...' : ''}`);\n } else {\n console.log(` Prompt: ${params.prompt}`);\n }\n if (imageDisplay) console.log(` Image: ${imageDisplay}`);\n if (useAlipay) {\n console.log(` Rail: alipay (CNY via alipay-bot)`);\n } else {\n console.log(` Chain: ${chain || '(auto)'}`); // Will be determined by server\n console.log(` Token: ${token}`);\n console.log(` Wallet: ${client.address}`);\n }\n console.log('');\n }\n\n try {\n // All chains use the same pay() flow - protocol detection happens inside.\n // --rail alipay dispatches to the alipay-bot-backed AlipayClient, which\n // streams CLI output verbatim and surfaces the payment URL to the user.\n const result = await client.pay(server, service, params, useAlipay ? {\n rail: 'alipay',\n rawData: useRawData,\n onPaymentPending: ({ paymentUrl, shortenUrl }) => {\n if (!options.json) {\n process.stdout.write(`\\n📲 请用支付宝扫码或访问:${shortenUrl ?? paymentUrl}\\n\\n`);\n }\n },\n onLine: (line) => { if (!options.json) process.stdout.write(line + '\\n'); },\n } : {\n token: token as 'USDC' | 'USDT',\n chain,\n rawData: useRawData\n });\n\n if (options.json) {\n console.log(JSON.stringify(result));\n } else {\n console.log('✅ Success!\\n');\n console.log(JSON.stringify(result, null, 2));\n console.log('');\n }\n } catch (err: any) {\n if (options.json) {\n console.log(JSON.stringify({ error: err.message }));\n } else {\n console.error(`❌ Error: ${err.message}`);\n }\n process.exit(1);\n }\n });\n\n/**\n * npx moltspay alipay <action> [args...]\n *\n * Thin pass-through to alipay-bot for first-time Alipay wallet setup (design\n * §5.2.9). Forwards stdout/stderr verbatim with the AIPAY_* env whitelist so\n * interactive `apply`/`bind` prompts work. These are user-driven account\n * actions, intentionally NOT part of the automated pay402() state machine.\n */\nprogram\n .command('alipay <action> [args...]')\n .description('Alipay wallet setup via alipay-bot: check | apply | bind')\n .allowUnknownOption()\n .action(async (action: string, args: string[]) => {\n // Real alipay-bot subcommand names (verified against alipay-bot-cli 0.3.15).\n const map: Record<string, string> = {\n check: 'check-wallet', apply: 'apply-wallet', bind: 'bind-wallet',\n };\n const sub = map[action] ?? action;\n const child = spawn('alipay-bot', [sub, ...(args ?? [])], {\n stdio: 'inherit',\n env: filterAlipayEnv(process.env),\n });\n child.on('error', (e: any) => {\n if (e?.code === 'ENOENT') {\n console.error(\n '❌ alipay-bot not installed. Run: npx -y @alipay/agent-payment install-cli',\n );\n } else {\n console.error(`❌ ${e.message}`);\n }\n process.exit(1);\n });\n child.on('exit', (code) => process.exit(code ?? 1));\n });\n\n/**\n * npx moltspay validate <path>\n */\nprogram\n .command('validate <path>')\n .description('Validate a moltspay.services.json file against the schema')\n .action(async (inputPath) => {\n const resolvedPath = resolve(inputPath);\n \n // Find manifest file\n let manifestPath: string;\n if (existsSync(join(resolvedPath, 'moltspay.services.json'))) {\n manifestPath = join(resolvedPath, 'moltspay.services.json');\n } else if (resolvedPath.endsWith('.json') && existsSync(resolvedPath)) {\n manifestPath = resolvedPath;\n } else {\n console.error(`❌ Not found: ${resolvedPath}`);\n process.exit(1);\n }\n\n console.log(`\\n📋 Validating: ${manifestPath}\\n`);\n\n try {\n const content = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n const errors: string[] = [];\n\n // Validate provider\n if (!content.provider) {\n errors.push('Missing required field: provider');\n } else {\n if (!content.provider.name) errors.push('Missing provider.name');\n if (!content.provider.wallet) errors.push('Missing provider.wallet');\n else if (!/^0x[a-fA-F0-9]{40}$/.test(content.provider.wallet)) {\n errors.push('Invalid provider.wallet (must be Ethereum address)');\n }\n }\n\n // Validate services\n if (!content.services || !Array.isArray(content.services)) {\n errors.push('Missing required field: services (array)');\n } else if (content.services.length === 0) {\n errors.push('services array must have at least one service');\n } else {\n content.services.forEach((svc: any, i: number) => {\n const prefix = `services[${i}]`;\n if (!svc.id) errors.push(`${prefix}: missing id`);\n else if (!/^[a-z0-9-]+$/.test(svc.id)) {\n errors.push(`${prefix}: id must be lowercase with hyphens only`);\n }\n if (typeof svc.price !== 'number') errors.push(`${prefix}: missing or invalid price`);\n if (!svc.currency) errors.push(`${prefix}: missing currency`);\n if (!svc.function && !svc.command) {\n errors.push(`${prefix}: must have either \"function\" or \"command\"`);\n }\n });\n }\n\n if (errors.length > 0) {\n console.log('❌ Validation failed:\\n');\n errors.forEach(e => console.log(` • ${e}`));\n console.log('');\n process.exit(1);\n }\n\n console.log('✅ Valid!\\n');\n console.log(` Provider: ${content.provider.name}`);\n console.log(` Wallet: ${content.provider.wallet}`);\n console.log(` Services: ${content.services.length}`);\n content.services.forEach((svc: any) => {\n console.log(` - ${svc.id} ($${svc.price} ${svc.currency})`);\n });\n console.log('');\n\n } catch (err: any) {\n console.error(`❌ Parse error: ${err.message}`);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","/**\n * Backwards-compatibility re-export for `src/client/index.ts`.\n *\n * The Node client implementation moved to `./node/index.ts` in 1.6.0 as part\n * of the Web Client work (see docs/WEB-CLIENT-DESIGN.md, Phase 1).\n *\n * This file keeps `import { MoltsPayClient } from 'moltspay/client'` working\n * for existing callers and preserves the published `dist/client/index.*`\n * bundle path declared in package.json exports.\n */\n\nexport * from './node/index.js';\n","/**\n * MoltsPay Client - Pay for AI Agent services\n * \n * Uses x402 protocol for gasless, pay-for-success payments.\n * \n * Usage:\n * const client = new MoltsPayClient(); // Loads from ~/.moltspay/\n * const services = await client.getServices('http://provider:3000');\n * const result = await client.pay('http://provider:3000', 'text-to-video', { prompt: '...' });\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, statSync, chmodSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { Wallet, ethers } from 'ethers';\nimport { getChain, type ChainName, type EvmChainName, type TokenSymbol, type ChainConfig } from '../../chains/index.js';\nimport { SOLANA_CHAINS, type SolanaChainName } from '../../chains/solana.js';\nimport { loadSolanaWallet, getSolanaAddress } from '../../wallet/solana.js';\nimport { createSolanaPaymentTransaction } from '../../facilitators/solana.js';\nimport { Connection, PublicKey, Keypair } from '@solana/web3.js';\nimport {\n ClientConfig,\n WalletData,\n ServicesResponse,\n MoltsPayClientOptions,\n} from '../types.js';\nimport {\n X402_VERSION,\n PAYMENT_REQUIRED_HEADER,\n PAYMENT_HEADER,\n type X402PaymentRequirements,\n type EIP3009Authorization,\n networkToChainName as coreNetworkToChainName,\n type ChainName as CoreChainName,\n buildEIP3009TypedData,\n buildBnbIntentTypedData,\n} from '../core/index.js';\nimport type { PaymentSigner } from '../signer.js';\nimport { NodeSigner } from './signer.js';\nimport { AlipayClient } from '../alipay/index.js';\nimport { timeStep } from '../alipay/log.js';\nimport { selectRail, ALIPAY_RAIL } from '../alipay/router.js';\n\nexport * from '../types.js';\n\nexport interface PayOptions {\n /** Token to pay with (default: USDC, or auto-select based on balance) */\n token?: TokenSymbol;\n /** Auto-select token based on balance (default: false) */\n autoSelect?: boolean;\n /** Chain to pay on */\n chain?: 'base' | 'polygon' | 'base_sepolia' | 'tempo_moderato' | 'bnb' | 'bnb_testnet' | 'solana' | 'solana_devnet';\n /** Send raw data at top level instead of wrapped in { params } */\n rawData?: boolean;\n /**\n * Explicit payment rail (2.0.0): `'alipay'` or a chain name. When set,\n * routing skips the default crypto path. `'alipay'` dispatches to the\n * alipay-bot-backed {@link AlipayClient} and needs no EVM wallet.\n */\n rail?: string;\n /** Alipay: surfaced once the payment URL + tradeNo are known. */\n onPaymentPending?: (info: { paymentUrl: string; shortenUrl?: string; tradeNo: string }) => void;\n /** Alipay: forward CLI output to the user verbatim (line by line). */\n onLine?: (line: string) => void;\n /** Alipay: overall budget; defaults to the challenge's pay_before window. */\n timeoutMs?: number;\n /** Cancellation (alipay poll loop). */\n signal?: AbortSignal;\n}\n\n// x402 constants, X402PaymentRequirements, and EIP3009Authorization\n// are re-exported from `../core/index.js` (imported above).\n\nconst DEFAULT_CONFIG: ClientConfig = {\n chain: 'base',\n limits: {\n maxPerTx: 100,\n maxPerDay: 1000,\n },\n};\n\nexport class MoltsPayClient {\n private configDir: string;\n private config: ClientConfig;\n private walletData: WalletData | null = null;\n private wallet: Wallet | null = null;\n private signer: PaymentSigner | null = null;\n private todaySpending: number = 0;\n private lastSpendingReset: number = 0;\n private railPreference?: string[];\n private alipaySessionId?: string;\n\n constructor(options: MoltsPayClientOptions = {}) {\n this.configDir = options.configDir || join(homedir(), '.moltspay');\n this.config = this.loadConfig();\n // Rail preference: explicit option wins over persisted config.\n this.railPreference = options.railPreference ?? this.config.railPreference;\n this.alipaySessionId = options.alipaySessionId;\n this.walletData = this.loadWallet();\n this.loadSpending(); // Load persisted spending data\n\n if (this.walletData) {\n this.wallet = new Wallet(this.walletData.privateKey);\n // Signer abstracts all signing. Solana key is loaded lazily so we don't\n // touch disk for callers that only pay on EVM chains.\n const configDir = this.configDir;\n this.signer = new NodeSigner(this.wallet, {\n getSolanaKeypair: () => loadSolanaWallet(configDir),\n });\n }\n }\n\n /**\n * Check if client is initialized (has wallet)\n */\n get isInitialized(): boolean {\n return this.wallet !== null;\n }\n\n /**\n * Get wallet address\n */\n get address(): string | null {\n return this.wallet?.address || null;\n }\n\n /**\n * Get wallet instance (for direct operations like approvals)\n */\n getWallet(): Wallet | null {\n return this.wallet;\n }\n\n /**\n * Get current config\n */\n getConfig(): ClientConfig {\n return { ...this.config };\n }\n\n /**\n * Update config\n */\n updateConfig(updates: Partial<ClientConfig['limits']>): void {\n if (updates.maxPerTx !== undefined) {\n this.config.limits.maxPerTx = updates.maxPerTx;\n }\n if (updates.maxPerDay !== undefined) {\n this.config.limits.maxPerDay = updates.maxPerDay;\n }\n this.saveConfig();\n }\n\n /**\n * Get services from a provider\n */\n async getServices(serverUrl: string): Promise<ServicesResponse> {\n // Normalize URL - don't append /services if already present\n const normalizedUrl = serverUrl.replace(/\\/(services|api\\/services|registry\\/services)\\/?$/, '');\n \n // Try /services first (standard provider endpoint)\n const endpoints = ['/services', '/api/services', '/registry/services'];\n \n for (const endpoint of endpoints) {\n try {\n const res = await fetch(`${normalizedUrl}${endpoint}`);\n if (!res.ok) continue;\n \n const contentType = res.headers.get('content-type') || '';\n if (!contentType.includes('application/json')) continue;\n \n return await res.json() as ServicesResponse;\n } catch {\n continue;\n }\n }\n \n throw new Error(`Failed to get services: no valid endpoint found at ${normalizedUrl}`);\n }\n\n /**\n * Pay for a service and get the result (x402 protocol)\n * \n * This is GASLESS for the client - server pays gas to claim payment.\n * This is PAY-FOR-SUCCESS - payment only claimed if service succeeds.\n * \n * @param serverUrl - Server URL\n * @param service - Service ID\n * @param params - Service parameters\n * @param options - Payment options (token selection)\n */\n async pay(\n serverUrl: string,\n service: string,\n params: Record<string, any>,\n options: PayOptions = {}\n ): Promise<Record<string, any>> {\n // Alipay fiat rail (2.0.0): when the caller explicitly asks for alipay,\n // dispatch BEFORE the EVM wallet check — the alipay rail is backed by\n // alipay-bot and needs no EVM wallet.\n if (options.rail === ALIPAY_RAIL) {\n return this.payViaAlipay(serverUrl, service, params, options);\n }\n\n if (!this.wallet || !this.walletData) {\n throw new Error('Client not initialized. Run: npx moltspay init');\n }\n\n // Step 1: Discover service endpoint\n console.log(`[MoltsPay] Requesting service: ${service}`);\n let executeUrl = `${serverUrl}/execute`; // Default fallback\n \n try {\n const services = await this.getServices(serverUrl);\n const svc = services.services?.find((s: any) => s.id === service);\n if (svc?.endpoint) {\n // Use the endpoint from service discovery (for Cloudflare Workers, etc.)\n executeUrl = `${serverUrl}${svc.endpoint}`;\n console.log(`[MoltsPay] Using service endpoint: ${svc.endpoint}`);\n }\n } catch {\n // Fall back to /execute if service discovery fails\n }\n \n // Build request body - raw mode sends data at top level, standard mode wraps in { params }\n let requestBody: any;\n if (options.rawData) {\n // Raw mode: { service, chain, ...params } - user's data at top level\n requestBody = { service, ...params };\n } else {\n // Standard mode: { service, params } - wrapped format\n requestBody = { service, params };\n }\n if (options.chain) {\n requestBody.chain = options.chain;\n }\n const initialRes = await fetch(executeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n });\n\n // If not 402, check for success or error\n if (initialRes.status !== 402) {\n const data = await initialRes.json() as any;\n if (initialRes.ok && data.result) {\n return data.result;\n }\n throw new Error(data.error || 'Unexpected response');\n }\n\n // Step 2: Detect protocol from 402 response\n // MPP uses WWW-Authenticate header, x402 uses X-Payment-Required header\n const wwwAuthHeader = initialRes.headers.get('www-authenticate');\n const paymentRequiredHeader = initialRes.headers.get(PAYMENT_REQUIRED_HEADER);\n \n // If WWW-Authenticate with Payment scheme, use MPP flow\n if (wwwAuthHeader && wwwAuthHeader.toLowerCase().includes('payment')) {\n console.log('[MoltsPay] Detected MPP protocol, using Tempo flow...');\n return await this.handleMPPPayment(executeUrl, service, params, wwwAuthHeader, options);\n }\n \n if (!paymentRequiredHeader) {\n throw new Error('Missing payment header (x-payment-required or www-authenticate)');\n }\n\n let requirements: X402PaymentRequirements[];\n try {\n const decoded = Buffer.from(paymentRequiredHeader, 'base64').toString('utf-8');\n const parsed = JSON.parse(decoded);\n \n // Handle both v1 (array) and v2 (object with accepts) formats\n if (Array.isArray(parsed)) {\n // v1 format: direct array of requirements\n requirements = parsed;\n } else if (parsed.accepts && Array.isArray(parsed.accepts)) {\n // v2 format: { x402Version: 2, accepts: [...] }\n requirements = parsed.accepts;\n } else {\n // Single requirement object\n requirements = [parsed];\n }\n } catch {\n throw new Error('Invalid x-payment-required header');\n }\n\n // Get server's accepted chains (uses shared core mapping — same output as 1.5.x)\n const serverChains = requirements\n .map(r => coreNetworkToChainName(r.network))\n .filter((c): c is CoreChainName => c !== null);\n\n // Determine which chain to use\n const userSpecifiedChain = options.chain;\n let selectedChain: string;\n\n if (userSpecifiedChain) {\n // User specified --chain, validate it's accepted by server\n if (!serverChains.includes(userSpecifiedChain)) {\n throw new Error(\n `Server doesn't accept '${userSpecifiedChain}'.\\n` +\n `Server accepts: ${serverChains.join(', ')}`\n );\n }\n selectedChain = userSpecifiedChain;\n } else {\n // No --chain provided\n if (serverChains.length === 1 && serverChains[0] === 'base') {\n // Only default to base if server ONLY accepts base\n selectedChain = 'base';\n } else {\n throw new Error(\n `Server accepts: ${serverChains.join(', ')}\\n` +\n `Please specify: --chain <chain_name>`\n );\n }\n }\n\n // Handle Solana chains separately\n if (selectedChain === 'solana' || selectedChain === 'solana_devnet') {\n const solanaChain = selectedChain as SolanaChainName;\n const network = solanaChain === 'solana' ? 'solana:mainnet' : 'solana:devnet';\n const req = requirements.find(r => r.network === network);\n \n if (!req) {\n throw new Error(`Failed to find payment requirement for ${selectedChain}`);\n }\n \n return await this.handleSolanaPayment(executeUrl, service, params, req, solanaChain, options);\n }\n\n // EVM chain handling\n const chainName = selectedChain as EvmChainName;\n const chain = getChain(chainName);\n const network = `eip155:${chain.chainId}`;\n const req = requirements.find(r => r.scheme === 'exact' && r.network === network);\n\n if (!req) {\n throw new Error(`Failed to find payment requirement for ${chainName}`);\n }\n\n // Step 3: Check limits\n // v2 uses 'amount', v1 uses 'maxAmountRequired'\n const amountRaw = req.amount || req.maxAmountRequired;\n if (!amountRaw) {\n throw new Error('Missing amount in payment requirements');\n }\n const amount = Number(amountRaw) / 1e6;\n this.checkLimits(amount);\n\n // Determine which token to use\n let token: TokenSymbol = options.token || 'USDC';\n \n // Auto-select token based on balance if requested\n if (options.autoSelect) {\n const balances = await this.getBalance();\n if (balances.usdc >= amount) {\n token = 'USDC';\n } else if (balances.usdt >= amount) {\n token = 'USDT';\n } else {\n throw new Error(`Insufficient balance: need $${amount}, have ${balances.usdc} USDC / ${balances.usdt} USDT`);\n }\n }\n\n // USDT does not support gasless transfers (no EIP-2612 permit)\n // It requires on-chain approve + transfer, meaning the user pays gas\n if (token === 'USDT') {\n const balances = await this.getBalance();\n if (balances.native < 0.0001) {\n throw new Error(\n `USDT requires ETH for gas (~$0.01 on Base). ` +\n `Your ETH balance: ${balances.native.toFixed(6)} ETH. ` +\n `Please add a small amount of ETH to your wallet, or use USDC (gasless).`\n );\n }\n console.log(`[MoltsPay] ⚠️ USDT requires gas (~$0.01). Proceeding with payment...`);\n } else {\n console.log(`[MoltsPay] Signing payment: $${amount} ${token} (gasless)`);\n }\n\n // BNB chains use intent-based flow (pre-approval + intent signature)\n if (chainName === 'bnb' || chainName === 'bnb_testnet') {\n console.log(`[MoltsPay] Using BNB intent-based payment flow...`);\n const payTo = req.payTo || req.resource;\n if (!payTo) {\n throw new Error('Missing payTo address in payment requirements');\n }\n // Get spender address from server response (dynamic, not hardcoded)\n const bnbSpender = (req.extra as any)?.bnbSpender;\n if (!bnbSpender) {\n throw new Error('Server did not provide bnbSpender address. Server may not support BNB payments.');\n }\n return await this.handleBNBPayment(executeUrl, service, params, {\n to: payTo,\n amount,\n token,\n chainName,\n chain,\n spender: bnbSpender,\n }, options);\n }\n\n // Step 4: Sign EIP-3009 authorization (GASLESS - just signing)\n // payTo is the recipient address (v2 format)\n const payTo = req.payTo || req.resource; // fallback for v1 compatibility\n if (!payTo) {\n throw new Error('Missing payTo address in payment requirements');\n }\n \n // Use server's extra field for domain info (contains correct EIP-712 domain for the token on this network)\n const domainOverride = (req.extra && typeof req.extra === 'object' && req.extra.name) \n ? { name: req.extra.name as string, version: (req.extra.version as string) || '2' }\n : undefined;\n \n const authorization = await this.signEIP3009(payTo, amount, chain, token, domainOverride);\n\n // Get token-specific info for accepted field\n const tokenConfig = chain.tokens[token];\n\n // Step 5: Create x402 payment payload (v2 requires scheme, network, payload, AND accepted)\n // Use server's extra field if provided (contains correct EIP-712 domain for the token on this network)\n // Fall back to local config for backward compatibility\n const extra = (req.extra && typeof req.extra === 'object') \n ? req.extra \n : {\n name: (tokenConfig as any).eip712Name || 'USD Coin',\n version: '2',\n };\n \n const payload = {\n x402Version: X402_VERSION,\n scheme: 'exact',\n network,\n payload: authorization, // { authorization: {...}, signature: \"0x...\" }\n accepted: {\n scheme: 'exact',\n network,\n asset: tokenConfig.address,\n amount: amountRaw,\n payTo,\n maxTimeoutSeconds: req.maxTimeoutSeconds || 300,\n extra,\n },\n };\n const paymentHeader = Buffer.from(JSON.stringify(payload)).toString('base64');\n\n // Step 6: Retry with payment header\n console.log(`[MoltsPay] Sending request with payment...`);\n const paidRequestBody: any = options.rawData\n ? { service, ...params }\n : { service, params };\n if (options.chain) {\n paidRequestBody.chain = options.chain;\n }\n const paidRes = await fetch(executeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n [PAYMENT_HEADER]: paymentHeader,\n },\n body: JSON.stringify(paidRequestBody),\n });\n\n const result = await paidRes.json() as any;\n\n if (!paidRes.ok) {\n throw new Error(result.error || 'Service execution failed');\n }\n\n // Update spending tracking\n this.recordSpending(amount);\n\n console.log(`[MoltsPay] Success! Payment: ${result.payment?.status || 'claimed'}`);\n\n // Support both MoltsPay Server format ({ result: ... }) and direct response format\n return result.result || result;\n }\n\n /**\n * Pay for a service over the Alipay fiat rail (2.0.0).\n *\n * Unlike the crypto path this needs no EVM wallet — it shells out to\n * alipay-bot via {@link AlipayClient}. Flow: hit the resource with no\n * payment to get the 402 challenge, confirm the server actually offers the\n * alipay rail (selectRail), then run the 8-step state machine and return the\n * resource body.\n */\n private async payViaAlipay(\n serverUrl: string,\n service: string,\n params: Record<string, any>,\n options: PayOptions,\n ): Promise<Record<string, any>> {\n // Flow correlation id for the pre-spawn (local) timing nodes.\n const flow = this.alipaySessionId;\n\n // Discover the resource endpoint (same as the crypto path).\n let executeUrl = `${serverUrl}/execute`;\n try {\n const services = await timeStep('discover-services', flow, () =>\n this.getServices(serverUrl),\n );\n const svc = services.services?.find((s: any) => s.id === service);\n if (svc?.endpoint) executeUrl = `${serverUrl}${svc.endpoint}`;\n } catch {\n // Fall back to /execute.\n }\n\n const requestBody: any = options.rawData ? { service, ...params } : { service, params };\n const bodyJson = JSON.stringify(requestBody);\n\n // Trigger the 402 challenge.\n const res = await timeStep('challenge-402', flow, () =>\n fetch(executeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: bodyJson,\n }),\n );\n if (res.status !== 402) {\n const data = await res.json().catch(() => ({}));\n if (res.ok && (data as any).result) return (data as any).result;\n throw new Error((data as any).error || `Expected 402, got ${res.status}`);\n }\n\n const header = res.headers.get(PAYMENT_REQUIRED_HEADER);\n if (!header) throw new Error('Missing x-payment-required header on 402');\n const parsed = JSON.parse(Buffer.from(header, 'base64').toString('utf-8'));\n const accepts: X402PaymentRequirements[] = Array.isArray(parsed)\n ? parsed\n : parsed.accepts ?? [parsed];\n\n // Confirm the server offers alipay (throws UnsupportedRailError otherwise).\n const { requirement } = selectRail({\n serverAccepts: accepts,\n explicitRail: ALIPAY_RAIL,\n preference: this.railPreference,\n availability: { evmReady: this.isInitialized },\n });\n\n const onLine = options.onLine ?? ((line: string) => process.stdout.write(line + '\\n'));\n const alipay = new AlipayClient({\n sessionId: this.alipaySessionId,\n configDir: this.configDir,\n });\n const result = await alipay.pay402({\n resourceUrl: executeUrl,\n requirement,\n method: 'POST',\n data: bodyJson,\n onLine,\n onPaymentPending: options.onPaymentPending,\n timeoutMs: options.timeoutMs,\n signal: options.signal,\n });\n\n // Best-effort: parse a JSON body, else return it raw under `body`.\n try {\n const json = JSON.parse(result.body);\n return json.result ?? json;\n } catch {\n return { body: result.body, payment: result.payment, media: result.media };\n }\n }\n\n /**\n * Handle MPP (Machine Payments Protocol) payment flow\n * Called when pay() detects WWW-Authenticate header in 402 response\n */\n private async handleMPPPayment(\n executeUrl: string,\n service: string,\n params: Record<string, any>,\n wwwAuthHeader: string,\n options: PayOptions = {}\n ): Promise<Record<string, any>> {\n // Dynamic imports for ESM-only packages\n const { privateKeyToAccount } = await import('viem/accounts');\n const { createWalletClient, createPublicClient, http } = await import('viem');\n const { tempoModerato } = await import('viem/chains');\n const { Actions } = await import('viem/tempo');\n\n // Get private key from wallet data\n const privateKey = this.walletData!.privateKey as `0x${string}`;\n const account = privateKeyToAccount(privateKey);\n\n console.log(`[MoltsPay] Using MPP protocol on Tempo`);\n console.log(`[MoltsPay] Account: ${account.address}`);\n\n // Parse WWW-Authenticate: Payment id=\"...\", method=\"tempo\", request=\"...\"\n const parseAuthParam = (header: string, key: string): string | null => {\n const match = header.match(new RegExp(`${key}=\"([^\"]+)\"`, 'i'));\n return match ? match[1] : null;\n };\n\n const challengeId = parseAuthParam(wwwAuthHeader, 'id');\n const method = parseAuthParam(wwwAuthHeader, 'method');\n const realm = parseAuthParam(wwwAuthHeader, 'realm');\n const requestB64 = parseAuthParam(wwwAuthHeader, 'request');\n\n if (method !== 'tempo') {\n throw new Error(`Unsupported payment method: ${method}`);\n }\n\n if (!requestB64) {\n throw new Error('Missing request in WWW-Authenticate');\n }\n\n // Decode payment request\n const requestJson = Buffer.from(requestB64, 'base64').toString('utf-8');\n const paymentRequest = JSON.parse(requestJson);\n \n const { amount, currency, recipient, methodDetails } = paymentRequest;\n const chainId = methodDetails?.chainId || 42431;\n const amountDisplay = Number(amount) / 1e6;\n\n console.log(`[MoltsPay] Payment: $${amountDisplay} to ${recipient}`);\n\n // Check limits\n this.checkLimits(amountDisplay);\n\n // Execute transfer on Tempo\n console.log(`[MoltsPay] Sending transaction on Tempo...`);\n\n const tempoChain = { ...tempoModerato, feeToken: currency as `0x${string}` };\n \n const publicClient = createPublicClient({\n chain: tempoChain,\n transport: http('https://rpc.moderato.tempo.xyz'),\n });\n\n const walletClient = createWalletClient({\n account,\n chain: tempoChain,\n transport: http('https://rpc.moderato.tempo.xyz'),\n });\n\n // TIP-20 transfer\n const txHash = await Actions.token.transfer(walletClient, {\n to: recipient as `0x${string}`,\n amount: BigInt(amount),\n token: currency as `0x${string}`,\n });\n\n console.log(`[MoltsPay] Transaction: ${txHash}`);\n\n // Wait for confirmation\n await publicClient.waitForTransactionReceipt({ hash: txHash });\n console.log(`[MoltsPay] Confirmed! Retrying with credential...`);\n\n // Build credential\n const credential = {\n challenge: {\n id: challengeId,\n realm,\n method: 'tempo',\n intent: 'charge',\n request: paymentRequest,\n },\n payload: { hash: txHash, type: 'hash' },\n source: `did:pkh:eip155:${chainId}:${account.address}`,\n };\n\n const credentialB64 = Buffer.from(JSON.stringify(credential))\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n // Retry with credential - respect rawData option\n const retryBody = options.rawData \n ? { service, ...params, chain: 'tempo_moderato' }\n : { service, params, chain: 'tempo_moderato' };\n \n const paidRes = await fetch(executeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Payment ${credentialB64}`,\n },\n body: JSON.stringify(retryBody),\n });\n\n const result = await paidRes.json() as any;\n\n if (!paidRes.ok) {\n throw new Error(result.error || 'Payment verification failed');\n }\n\n // Update spending tracking\n this.recordSpending(amountDisplay);\n\n console.log(`[MoltsPay] Success!`);\n return result.result || result;\n }\n\n /**\n * Handle BNB Chain payment flow (pre-approval + intent signature)\n * \n * Flow:\n * 1. Check client has approved server wallet (done via `moltspay init`)\n * 2. Sign EIP-712 payment intent (no gas, just signature)\n * 3. Send intent to server\n * 4. Server executes service\n * 5. Server calls transferFrom if successful (pay-for-success)\n */\n private async handleBNBPayment(\n executeUrl: string,\n service: string,\n params: Record<string, any>,\n paymentDetails: {\n to: string;\n amount: number;\n token: TokenSymbol;\n chainName: ChainName;\n chain: ChainConfig;\n spender: string;\n },\n options: PayOptions = {}\n ): Promise<Record<string, any>> {\n const { to, amount, token, chainName, chain, spender } = paymentDetails;\n const tokenConfig = chain.tokens[token];\n \n // Check approval status\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n const allowance = await this.checkAllowance(tokenConfig.address, spender, provider);\n const amountWeiCheck = BigInt(Math.floor(amount * (10 ** tokenConfig.decimals)));\n \n if (allowance < amountWeiCheck) {\n // Check if user has enough BNB for gas to approve\n const nativeBalance = await provider.getBalance(this.wallet!.address);\n const minGasBalance = ethers.parseEther('0.0005'); // ~0.0005 BNB minimum for approval\n \n if (nativeBalance < minGasBalance) {\n const nativeBNB = parseFloat(ethers.formatEther(nativeBalance)).toFixed(4);\n const isTestnet = chainName === 'bnb_testnet';\n \n if (isTestnet) {\n throw new Error(\n `❌ Insufficient tBNB for approval transaction\\n\\n` +\n ` Current tBNB: ${nativeBNB}\\n` +\n ` Required: ~0.001 tBNB\\n\\n` +\n ` Get testnet tokens: npx moltspay faucet --chain bnb_testnet\\n` +\n ` (Gives USDC + tBNB for gas)`\n );\n } else {\n throw new Error(\n `❌ Insufficient BNB for approval transaction\\n\\n` +\n ` Current BNB: ${nativeBNB}\\n` +\n ` Required: ~0.001 BNB (~$0.60)\\n\\n` +\n ` To get BNB:\\n` +\n ` • Withdraw from Binance/exchange to your wallet\\n` +\n ` • Most exchanges include BNB dust with withdrawals\\n\\n` +\n ` After funding, run:\\n` +\n ` npx moltspay approve --chain ${chainName} --spender ${spender}`\n );\n }\n }\n \n throw new Error(\n `Insufficient allowance for ${spender.slice(0, 10)}...\\n` +\n `Run: npx moltspay approve --chain ${chainName} --spender ${spender}`\n );\n }\n \n // Convert amount to wei (BNB uses 18 decimals)\n const amountWei = BigInt(Math.floor(amount * (10 ** tokenConfig.decimals))).toString();\n\n // Build PaymentIntent envelope via shared core builder, sign through PaymentSigner.\n const intentNonce = Date.now();\n const intentDeadline = Date.now() + 3600000; // 1 hour\n const envelope = buildBnbIntentTypedData({\n from: this.wallet!.address,\n to,\n amount: amountWei,\n tokenAddress: tokenConfig.address,\n service,\n nonce: intentNonce,\n deadline: intentDeadline,\n chainId: chain.chainId,\n });\n\n console.log(`[MoltsPay] Signing BNB payment intent...`);\n const signature = await this.signer!.signTypedData(envelope);\n const intent = envelope.message;\n\n // Create x402 payment payload with BNB-specific format\n const network = `eip155:${chain.chainId}`;\n const payload = {\n x402Version: 2,\n scheme: 'exact',\n network,\n payload: {\n intent: {\n ...intent,\n signature,\n },\n chainId: chain.chainId,\n },\n accepted: {\n scheme: 'exact',\n network,\n asset: tokenConfig.address,\n amount: amountWei,\n payTo: to,\n maxTimeoutSeconds: 300,\n },\n };\n\n const paymentHeader = Buffer.from(JSON.stringify(payload)).toString('base64');\n\n // Send request with payment - respect rawData option\n console.log(`[MoltsPay] Sending BNB payment request...`);\n const bnbRequestBody = options.rawData\n ? { service, ...params, chain: chainName }\n : { service, params, chain: chainName };\n const paidRes = await fetch(executeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Payment': paymentHeader,\n },\n body: JSON.stringify(bnbRequestBody),\n });\n\n const result = await paidRes.json() as any;\n\n if (!paidRes.ok) {\n throw new Error(result.error || 'BNB payment failed');\n }\n\n // Update spending tracking\n this.recordSpending(amount);\n\n console.log(`[MoltsPay] Success! BNB payment settled.`);\n return result.result || result;\n }\n\n /**\n * Handle Solana payment flow\n * \n * Solana uses SPL token transfers with pay-for-success model:\n * 1. Client creates and signs a transfer transaction\n * 2. Server submits the transaction after service completes\n */\n private async handleSolanaPayment(\n executeUrl: string,\n service: string,\n params: Record<string, any>,\n requirements: X402PaymentRequirements,\n chain: SolanaChainName,\n options: PayOptions = {}\n ): Promise<Record<string, any>> {\n // Load Solana wallet\n const solanaWallet = loadSolanaWallet(this.configDir);\n if (!solanaWallet) {\n throw new Error('No Solana wallet found. Run: npx moltspay init --chain solana_devnet');\n }\n\n const amount = Number(requirements.amount);\n const amountUSDC = amount / 1e6;\n \n // Check limits\n this.checkLimits(amountUSDC);\n\n console.log(`[MoltsPay] Creating Solana payment: $${amountUSDC} USDC`);\n\n // Validate payTo address\n if (!requirements.payTo) {\n throw new Error('Missing payTo address in payment requirements');\n }\n\n // Check for gasless mode (server pays fees)\n const solanaFeePayer = (requirements.extra as any)?.solanaFeePayer;\n const feePayerPubkey = solanaFeePayer ? new PublicKey(solanaFeePayer) : undefined;\n \n if (feePayerPubkey) {\n console.log(`[MoltsPay] Gasless mode: server pays fees`);\n }\n\n // Create the transfer transaction\n const recipientPubkey = new PublicKey(requirements.payTo);\n const transaction = await createSolanaPaymentTransaction(\n solanaWallet.publicKey,\n recipientPubkey,\n BigInt(amount),\n chain,\n feePayerPubkey // Optional fee payer for gasless mode\n );\n\n // Sign the transaction through PaymentSigner (partial sign in gasless mode).\n // Serializing before signing keeps the Web Client (Phase 4) wallet-adapter\n // flow identical to this one.\n const unsignedBase64 = transaction\n .serialize({ requireAllSignatures: false, verifySignatures: false })\n .toString('base64');\n const signedTx = await this.signer!.signSolanaTransaction!({\n transactionBase64: unsignedBase64,\n partialSign: !!feePayerPubkey,\n });\n\n console.log(`[MoltsPay] Transaction signed, sending to server...`);\n\n // Create x402 payload with Solana-specific format\n const network = chain === 'solana' ? 'solana:mainnet' : 'solana:devnet';\n const payload = {\n x402Version: 2,\n scheme: 'exact',\n network,\n payload: {\n signedTransaction: signedTx,\n sender: solanaWallet.publicKey.toBase58(),\n chain,\n },\n accepted: {\n scheme: 'exact',\n network,\n asset: requirements.asset,\n amount: requirements.amount,\n payTo: requirements.payTo,\n maxTimeoutSeconds: 300,\n },\n };\n\n const paymentHeader = Buffer.from(JSON.stringify(payload)).toString('base64');\n\n // Send request with payment - respect rawData option\n const solanaRequestBody = options.rawData\n ? { service, ...params, chain }\n : { service, params, chain };\n const paidRes = await fetch(executeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Payment': paymentHeader,\n },\n body: JSON.stringify(solanaRequestBody),\n });\n\n const result = await paidRes.json() as any;\n\n if (!paidRes.ok) {\n throw new Error(result.error || 'Solana payment failed');\n }\n\n // Update spending tracking\n this.recordSpending(amountUSDC);\n\n console.log(`[MoltsPay] Success! Solana payment settled.`);\n if (result.payment?.transaction) {\n const explorerUrl = chain === 'solana' \n ? `https://solscan.io/tx/${result.payment.transaction}`\n : `https://solscan.io/tx/${result.payment.transaction}?cluster=devnet`;\n console.log(`[MoltsPay] Transaction: ${explorerUrl}`);\n }\n\n return result.result || result;\n }\n\n /**\n * Check ERC20 allowance for a spender\n */\n private async checkAllowance(\n tokenAddress: string,\n spender: string,\n provider: ethers.JsonRpcProvider\n ): Promise<bigint> {\n const contract = new ethers.Contract(\n tokenAddress,\n ['function allowance(address owner, address spender) view returns (uint256)'],\n provider\n );\n return await contract.allowance(this.wallet!.address, spender);\n }\n\n /**\n * Sign EIP-3009 transferWithAuthorization (GASLESS)\n * This only signs - no on-chain transaction, no gas needed.\n * Supports both USDC and USDT.\n *\n * Delegates typed-data construction to `core/eip3009.ts` and the signature\n * itself to `this.signer`. That way Web Client (Phase 4) can reuse the same\n * flow with an EIP-1193 signer without duplicating typed-data layout.\n */\n private async signEIP3009(\n to: string,\n amount: number,\n chain: { chainId: number; tokens: Record<TokenSymbol, { address: string; decimals: number }> },\n token: TokenSymbol = 'USDC',\n domainOverride?: { name: string; version: string }\n ): Promise<{ authorization: EIP3009Authorization; signature: string }> {\n const tokenConfig = chain.tokens[token];\n const value = BigInt(Math.floor(amount * (10 ** tokenConfig.decimals))).toString();\n const nonce = ethers.hexlify(ethers.randomBytes(32));\n\n // EIP-712 domain - use server's domain info if provided (handles mainnet vs testnet differences)\n // Fall back to local token config for backward compatibility.\n const tokenName = domainOverride?.name || (tokenConfig as any).eip712Name || (token === 'USDC' ? 'USD Coin' : 'Tether USD');\n const tokenVersion = domainOverride?.version || '2';\n\n const envelope = buildEIP3009TypedData({\n from: this.wallet!.address,\n to,\n value,\n nonce,\n chainId: chain.chainId,\n tokenAddress: tokenConfig.address,\n tokenName,\n tokenVersion,\n });\n\n const signature = await this.signer!.signTypedData(envelope);\n return { authorization: envelope.message, signature };\n }\n\n /**\n * Check spending limits\n */\n private checkLimits(amount: number): void {\n // Check per-tx limit\n if (amount > this.config.limits.maxPerTx) {\n throw new Error(\n `Amount $${amount} exceeds max per transaction ($${this.config.limits.maxPerTx})`\n );\n }\n\n // Reset daily spending if new day\n const today = new Date().setHours(0, 0, 0, 0);\n if (today > this.lastSpendingReset) {\n this.todaySpending = 0;\n this.lastSpendingReset = today;\n this.saveSpending(); // Persist reset\n }\n\n // Check daily limit\n if (this.todaySpending + amount > this.config.limits.maxPerDay) {\n throw new Error(\n `Would exceed daily limit ($${this.todaySpending} + $${amount} > $${this.config.limits.maxPerDay})`\n );\n }\n }\n\n /**\n * Record spending and persist to disk\n */\n private recordSpending(amount: number): void {\n this.todaySpending += amount;\n this.saveSpending();\n }\n\n // --- Config & Wallet Management ---\n\n private loadConfig(): ClientConfig {\n const configPath = join(this.configDir, 'config.json');\n if (existsSync(configPath)) {\n const content = readFileSync(configPath, 'utf-8');\n return { ...DEFAULT_CONFIG, ...JSON.parse(content) };\n }\n return { ...DEFAULT_CONFIG };\n }\n\n private saveConfig(): void {\n mkdirSync(this.configDir, { recursive: true });\n const configPath = join(this.configDir, 'config.json');\n writeFileSync(configPath, JSON.stringify(this.config, null, 2));\n }\n\n /**\n * Load spending data from disk\n */\n private loadSpending(): void {\n const spendingPath = join(this.configDir, 'spending.json');\n if (existsSync(spendingPath)) {\n try {\n const data = JSON.parse(readFileSync(spendingPath, 'utf-8'));\n const today = new Date().setHours(0, 0, 0, 0);\n \n // Only load if it's from today\n if (data.date && data.date === today) {\n this.todaySpending = data.amount || 0;\n this.lastSpendingReset = data.date;\n } else {\n // Data is from a previous day, reset\n this.todaySpending = 0;\n this.lastSpendingReset = today;\n }\n } catch {\n // Ignore parse errors, start fresh\n this.todaySpending = 0;\n this.lastSpendingReset = new Date().setHours(0, 0, 0, 0);\n }\n }\n }\n\n /**\n * Save spending data to disk\n */\n private saveSpending(): void {\n mkdirSync(this.configDir, { recursive: true });\n const spendingPath = join(this.configDir, 'spending.json');\n const data = {\n date: this.lastSpendingReset || new Date().setHours(0, 0, 0, 0),\n amount: this.todaySpending,\n updatedAt: Date.now(),\n };\n writeFileSync(spendingPath, JSON.stringify(data, null, 2));\n }\n\n private loadWallet(): WalletData | null {\n const walletPath = join(this.configDir, 'wallet.json');\n if (existsSync(walletPath)) {\n // POSIX-only: Windows reports synthesized mode bits and chmod can't\n // express NTFS ACLs, so the check is meaningless there.\n if (process.platform !== 'win32') {\n try {\n const stats = statSync(walletPath);\n const mode = stats.mode & 0o777;\n if (mode !== 0o600) {\n console.warn(`[MoltsPay] WARNING: wallet.json has insecure permissions (${mode.toString(8)})`);\n console.warn(`[MoltsPay] Fixing permissions to 0600...`);\n chmodSync(walletPath, 0o600);\n }\n } catch {\n /* ignored */\n }\n }\n\n const content = readFileSync(walletPath, 'utf-8');\n return JSON.parse(content);\n }\n return null;\n }\n\n /**\n * Initialize a new wallet (called by CLI)\n */\n static init(\n configDir: string,\n options: { chain: string; maxPerTx: number; maxPerDay: number }\n ): { address: string; configDir: string } {\n mkdirSync(configDir, { recursive: true });\n\n // Create wallet\n const wallet = Wallet.createRandom();\n const walletData: WalletData = {\n address: wallet.address,\n privateKey: wallet.privateKey,\n createdAt: Date.now(),\n };\n\n // Save wallet with secure permissions (0o600 = owner read/write only)\n const walletPath = join(configDir, 'wallet.json');\n writeFileSync(walletPath, JSON.stringify(walletData, null, 2), { mode: 0o600 });\n\n // Save config\n const config: ClientConfig = {\n chain: options.chain,\n limits: {\n maxPerTx: options.maxPerTx,\n maxPerDay: options.maxPerDay,\n },\n };\n const configPath = join(configDir, 'config.json');\n writeFileSync(configPath, JSON.stringify(config, null, 2));\n\n return { address: wallet.address, configDir };\n }\n\n /**\n * Get wallet balance (USDC, USDT, and native token) on default chain\n */\n async getBalance(): Promise<{ usdc: number; usdt: number; native: number }> {\n if (!this.wallet) {\n throw new Error('Client not initialized');\n }\n\n let chain;\n try {\n chain = getChain(this.config.chain as EvmChainName);\n } catch {\n throw new Error(`Unknown chain: ${this.config.chain}`);\n }\n\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n const tokenAbi = ['function balanceOf(address) view returns (uint256)'];\n\n // Get all balances in parallel\n const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([\n provider.getBalance(this.wallet.address),\n new ethers.Contract(chain.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),\n new ethers.Contract(chain.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address),\n ]);\n\n return {\n usdc: parseFloat(ethers.formatUnits(usdcBalance, chain.tokens.USDC.decimals)),\n usdt: parseFloat(ethers.formatUnits(usdtBalance, chain.tokens.USDT.decimals)),\n native: parseFloat(ethers.formatEther(nativeBalance)),\n };\n }\n\n /**\n * Get wallet balances on all supported chains (Base + Polygon + Tempo)\n */\n async getAllBalances(): Promise<Record<string, { usdc: number; usdt: number; native: number; tempo?: { pathUSD: number; alphaUSD: number; betaUSD: number; thetaUSD: number } }>> {\n if (!this.wallet) {\n throw new Error('Client not initialized');\n }\n\n const supportedChains: EvmChainName[] = ['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'bnb', 'bnb_testnet'];\n const tokenAbi = ['function balanceOf(address) view returns (uint256)'];\n const results: Record<string, { usdc: number; usdt: number; native: number; tempo?: { pathUSD: number; alphaUSD: number; betaUSD: number; thetaUSD: number } }> = {};\n\n // Tempo testnet token addresses\n const tempoTokens = {\n pathUSD: '0x20c0000000000000000000000000000000000000',\n alphaUSD: '0x20c0000000000000000000000000000000000001',\n betaUSD: '0x20c0000000000000000000000000000000000002',\n thetaUSD: '0x20c0000000000000000000000000000000000003',\n };\n\n // Query all chains in parallel\n await Promise.all(\n supportedChains.map(async (chainName) => {\n try {\n const chain = getChain(chainName);\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n\n if (chainName === 'tempo_moderato') {\n // Tempo: fetch all 4 testnet tokens\n const [nativeBalance, pathUSD, alphaUSD, betaUSD, thetaUSD] = await Promise.all([\n provider.getBalance(this.wallet!.address),\n new ethers.Contract(tempoTokens.pathUSD, tokenAbi, provider).balanceOf(this.wallet!.address),\n new ethers.Contract(tempoTokens.alphaUSD, tokenAbi, provider).balanceOf(this.wallet!.address),\n new ethers.Contract(tempoTokens.betaUSD, tokenAbi, provider).balanceOf(this.wallet!.address),\n new ethers.Contract(tempoTokens.thetaUSD, tokenAbi, provider).balanceOf(this.wallet!.address),\n ]);\n\n results[chainName] = {\n usdc: parseFloat(ethers.formatUnits(pathUSD, 6)), // pathUSD as default USDC\n usdt: parseFloat(ethers.formatUnits(alphaUSD, 6)), // alphaUSD as default USDT\n native: parseFloat(ethers.formatEther(nativeBalance)),\n tempo: {\n pathUSD: parseFloat(ethers.formatUnits(pathUSD, 6)),\n alphaUSD: parseFloat(ethers.formatUnits(alphaUSD, 6)),\n betaUSD: parseFloat(ethers.formatUnits(betaUSD, 6)),\n thetaUSD: parseFloat(ethers.formatUnits(thetaUSD, 6)),\n },\n };\n } else {\n // Other chains: fetch USDC and USDT\n const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([\n provider.getBalance(this.wallet!.address),\n new ethers.Contract(chain.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet!.address),\n new ethers.Contract(chain.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet!.address),\n ]);\n\n results[chainName] = {\n usdc: parseFloat(ethers.formatUnits(usdcBalance, chain.tokens.USDC.decimals)),\n usdt: parseFloat(ethers.formatUnits(usdtBalance, chain.tokens.USDT.decimals)),\n native: parseFloat(ethers.formatEther(nativeBalance)),\n };\n }\n } catch (err) {\n // If chain query fails, show zeros\n results[chainName] = { usdc: 0, usdt: 0, native: 0 };\n }\n })\n );\n\n return results;\n }\n\n /**\n * Pay for a service using MPP (Machine Payments Protocol)\n * \n * This implements the MPP flow manually for EOA wallets:\n * 1. Request service → get 402 with WWW-Authenticate\n * 2. Parse payment requirements\n * 3. Execute transfer on Tempo chain\n * 4. Retry with transaction hash as credential\n * \n * @param url - Full URL of the MPP-enabled endpoint\n * @param options - Request options (body, headers)\n * @returns Response from the service\n */\n async payWithMPP(\n url: string,\n options: {\n body?: any;\n headers?: Record<string, string>;\n } = {}\n ): Promise<any> {\n if (!this.wallet || !this.walletData) {\n throw new Error('Client not initialized. Run: npx moltspay init');\n }\n\n // Dynamic imports for ESM-only packages\n const { privateKeyToAccount } = await import('viem/accounts');\n const { createWalletClient, createPublicClient, http } = await import('viem');\n const { tempoModerato } = await import('viem/chains');\n const { Actions } = await import('viem/tempo');\n\n // Get private key from wallet data\n const privateKey = this.walletData.privateKey as `0x${string}`;\n const account = privateKeyToAccount(privateKey);\n\n console.log(`[MoltsPay] Making MPP request to: ${url}`);\n console.log(`[MoltsPay] Using account: ${account.address}`);\n\n // Step 1: Initial request to get 402 with payment requirements\n const initResponse = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n });\n\n // If not 402, handle directly\n if (initResponse.status !== 402) {\n if (initResponse.ok) {\n return initResponse.json();\n }\n const errorText = await initResponse.text();\n throw new Error(`Request failed (${initResponse.status}): ${errorText}`);\n }\n\n // Step 2: Parse WWW-Authenticate header\n const wwwAuth = initResponse.headers.get('www-authenticate');\n if (!wwwAuth || !wwwAuth.toLowerCase().includes('payment')) {\n throw new Error('No WWW-Authenticate Payment challenge in 402 response');\n }\n\n console.log(`[MoltsPay] Got 402, parsing payment challenge...`);\n\n // Parse WWW-Authenticate: Payment id=\"...\", method=\"tempo\", request=\"...\"\n const parseAuthParam = (header: string, key: string): string | null => {\n const match = header.match(new RegExp(`${key}=\"([^\"]+)\"`, 'i'));\n return match ? match[1] : null;\n };\n\n const challengeId = parseAuthParam(wwwAuth, 'id');\n const method = parseAuthParam(wwwAuth, 'method');\n const realm = parseAuthParam(wwwAuth, 'realm');\n const requestB64 = parseAuthParam(wwwAuth, 'request');\n\n if (method !== 'tempo') {\n throw new Error(`Unsupported payment method: ${method}`);\n }\n\n if (!requestB64) {\n throw new Error('Missing request in WWW-Authenticate');\n }\n\n // Decode payment request\n const requestJson = Buffer.from(requestB64, 'base64').toString('utf-8');\n const paymentRequest = JSON.parse(requestJson);\n \n console.log(`[MoltsPay] Payment request:`, paymentRequest);\n\n const { amount, currency, recipient, methodDetails } = paymentRequest;\n const chainId = methodDetails?.chainId || 42431;\n\n // Step 3: Execute transfer on Tempo\n console.log(`[MoltsPay] Executing transfer on Tempo (chainId: ${chainId})...`);\n console.log(`[MoltsPay] Amount: ${amount}, To: ${recipient}`);\n\n // Create viem client for Tempo (with feeToken for gas-free transactions)\n const tempoChain = { ...tempoModerato, feeToken: currency as `0x${string}` };\n \n const publicClient = createPublicClient({\n chain: tempoChain,\n transport: http('https://rpc.moderato.tempo.xyz'),\n });\n\n const walletClient = createWalletClient({\n account,\n chain: tempoChain,\n transport: http('https://rpc.moderato.tempo.xyz'),\n });\n\n // Use viem's Tempo Actions for TIP-20 transfer\n const txHash = await Actions.token.transfer(walletClient, {\n to: recipient as `0x${string}`,\n amount: BigInt(amount),\n token: currency as `0x${string}`,\n });\n\n console.log(`[MoltsPay] Transaction sent: ${txHash}`);\n\n // Wait for confirmation\n console.log(`[MoltsPay] Waiting for confirmation...`);\n await publicClient.waitForTransactionReceipt({ hash: txHash });\n console.log(`[MoltsPay] Transaction confirmed!`);\n\n // Step 4: Build credential and retry\n const challenge = {\n id: challengeId,\n realm,\n method: 'tempo',\n intent: 'charge',\n request: paymentRequest,\n };\n\n const credential = {\n challenge,\n payload: { hash: txHash, type: 'hash' },\n source: `did:pkh:eip155:${chainId}:${account.address}`,\n };\n\n const credentialB64 = Buffer.from(JSON.stringify(credential))\n .toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, ''); // base64url without padding\n\n console.log(`[MoltsPay] Retrying with payment credential...`);\n\n // Retry with credential\n const paidResponse = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Payment ${credentialB64}`,\n ...options.headers,\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n });\n\n if (!paidResponse.ok) {\n const errorText = await paidResponse.text();\n throw new Error(`Payment verification failed (${paidResponse.status}): ${errorText}`);\n }\n\n console.log(`[MoltsPay] Payment verified! Service completed.`);\n return paidResponse.json();\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName, EvmChainName, TokenSymbol } from '../types/index.js';\n\nexport const CHAINS: Record<EvmChainName, 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 // ============ BNB Chain Testnet ============\n bnb_testnet: {\n name: 'BNB Testnet',\n chainId: 97,\n rpc: 'https://data-seed-prebsc-1-s1.binance.org:8545',\n tokens: {\n // Note: BNB uses 18 decimals for stablecoins (unlike Base/Polygon which use 6)\n // Using official Binance-Peg testnet tokens\n USDC: {\n address: '0x64544969ed7EBf5f083679233325356EbE738930', // Testnet USDC\n decimals: 18,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0x337610d27c682E347C9cD60BD4b3b107C9d34dDd', // Testnet USDT\n decimals: 18,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x64544969ed7EBf5f083679233325356EbE738930',\n explorer: 'https://testnet.bscscan.com/address/',\n explorerTx: 'https://testnet.bscscan.com/tx/',\n avgBlockTime: 3,\n // BNB-specific: requires approval for pay-for-success flow\n requiresApproval: true,\n },\n // ============ BNB Chain Mainnet ============\n bnb: {\n name: 'BNB Smart Chain',\n chainId: 56,\n rpc: 'https://bsc-dataseed.binance.org',\n tokens: {\n // Note: BNB uses 18 decimals for stablecoins\n USDC: {\n address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n decimals: 18,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0x55d398326f99059fF775485246999027B3197955',\n decimals: 18,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n explorer: 'https://bscscan.com/address/',\n explorerTx: 'https://bscscan.com/tx/',\n avgBlockTime: 3,\n // BNB-specific: requires approval for pay-for-success flow\n requiresApproval: true,\n },\n};\n\n/**\n * Get token address for a chain\n */\nexport function getTokenAddress(chainName: EvmChainName, 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: EvmChainName, 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: EvmChainName): 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 EVM chains\n */\nexport function listChains(): EvmChainName[] {\n return Object.keys(CHAINS) as EvmChainName[];\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// ============ Alipay AI 收 Fiat Rail (2.0.0+) ============\n\n/**\n * Chain-id string for the Alipay AI 收 fiat rail.\n * Used in `provider.chains: [\"alipay\", ...]` to opt the provider into\n * accepting CNY payments alongside USDC.\n */\nexport const ALIPAY_CHAIN_ID = 'alipay' as const;\n\n/**\n * Rail metadata for the Alipay AI 收 fiat rail (2.0.0+).\n *\n * Intentionally kept **outside** the {@link CHAINS} Record because that\n * Record is `Record<EvmChainName, ChainConfig>` and an EVM `ChainConfig`\n * (rpc / tokens / chainId) is not meaningful for a fiat rail.\n *\n * The rail uses `type: \"fiat-rail\"`, distinct from `ChainFamily`'s\n * existing `\"evm\"` and `\"svm\"`. Server dispatch detects alipay via\n * {@link isAlipayChainId} rather than via the EVM/SVM type guards.\n */\nexport const ALIPAY_RAIL = {\n /** Chain-id string used in user manifests + routing. */\n id: ALIPAY_CHAIN_ID,\n /** Rail family — distinct from `ChainFamily` ('evm' | 'svm'). */\n type: 'fiat-rail' as const,\n /** Quote currency. */\n currency: 'CNY' as const,\n /** Decimal places for the `amount` field (元 with up to 2 decimals). */\n decimals: 2 as const,\n /** x402 `scheme` string — matches `ALIPAY_SCHEME` in src/facilitators/alipay.ts. */\n facilitator: 'alipay-aipay' as const,\n} as const;\n\n/**\n * Runtime type guard: is this chain-id string the Alipay fiat rail?\n *\n * Used by the server layer to route a `Payment-Proof` request to\n * {@link AlipayFacilitator} instead of an EVM/SVM verifier.\n */\nexport function isAlipayChainId(id: string): id is typeof ALIPAY_CHAIN_ID {\n return id === ALIPAY_CHAIN_ID;\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, EvmChainName, TokenSymbol };\n","/**\n * Solana Wallet Management\n * \n * Separate from EVM wallets - uses ed25519 keypairs.\n * Stored in ~/.moltspay/wallet-solana.json\n */\n\nimport { Keypair, PublicKey, Connection, LAMPORTS_PER_SOL } from '@solana/web3.js';\nimport { getAssociatedTokenAddress, getAccount } from '@solana/spl-token';\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport bs58 from 'bs58';\nimport { getSolanaConnection, getUSDCMint, type SolanaChainName } from '../chains/solana.js';\n\nconst DEFAULT_CONFIG_DIR = join(homedir(), '.moltspay');\nconst SOLANA_WALLET_FILE = 'wallet-solana.json';\n\nexport interface SolanaWalletData {\n publicKey: string; // Base58 encoded\n secretKey: string; // Base58 encoded (should be encrypted in production)\n createdAt: string;\n}\n\n/**\n * Get the path to the Solana wallet file\n */\nexport function getSolanaWalletPath(configDir: string = DEFAULT_CONFIG_DIR): string {\n return join(configDir, SOLANA_WALLET_FILE);\n}\n\n/**\n * Check if Solana wallet exists\n */\nexport function solanaWalletExists(configDir: string = DEFAULT_CONFIG_DIR): boolean {\n return existsSync(getSolanaWalletPath(configDir));\n}\n\n/**\n * Load existing Solana wallet\n */\nexport function loadSolanaWallet(configDir: string = DEFAULT_CONFIG_DIR): Keypair | null {\n const walletPath = getSolanaWalletPath(configDir);\n \n if (!existsSync(walletPath)) {\n return null;\n }\n \n try {\n const data: SolanaWalletData = JSON.parse(readFileSync(walletPath, 'utf-8'));\n const secretKey = bs58.decode(data.secretKey);\n return Keypair.fromSecretKey(secretKey);\n } catch (error) {\n console.error('Failed to load Solana wallet:', error);\n return null;\n }\n}\n\n/**\n * Create new Solana wallet\n */\nexport function createSolanaWallet(configDir: string = DEFAULT_CONFIG_DIR): Keypair {\n // Ensure config directory exists\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n \n const keypair = Keypair.generate();\n const data: SolanaWalletData = {\n publicKey: keypair.publicKey.toBase58(),\n secretKey: bs58.encode(keypair.secretKey),\n createdAt: new Date().toISOString(),\n };\n \n const walletPath = getSolanaWalletPath(configDir);\n writeFileSync(walletPath, JSON.stringify(data, null, 2));\n \n return keypair;\n}\n\n/**\n * Get Solana wallet address (public key as Base58)\n */\nexport function getSolanaAddress(configDir: string = DEFAULT_CONFIG_DIR): string | null {\n const wallet = loadSolanaWallet(configDir);\n return wallet?.publicKey.toBase58() || null;\n}\n\n/**\n * Get SOL balance (native token for gas)\n */\nexport async function getSolanaBalance(\n address: string,\n chain: SolanaChainName\n): Promise<number> {\n const connection = getSolanaConnection(chain);\n const pubkey = new PublicKey(address);\n \n const balance = await connection.getBalance(pubkey);\n return balance / LAMPORTS_PER_SOL;\n}\n\n/**\n * Get USDC balance on Solana\n */\nexport async function getSolanaUSDCBalance(\n address: string,\n chain: SolanaChainName\n): Promise<number> {\n const connection = getSolanaConnection(chain);\n const owner = new PublicKey(address);\n const mint = getUSDCMint(chain);\n \n try {\n const ata = await getAssociatedTokenAddress(mint, owner);\n const account = await getAccount(connection, ata);\n // USDC has 6 decimals on Solana\n return Number(account.amount) / 1e6;\n } catch (error: any) {\n // Account doesn't exist = 0 balance\n if (error.name === 'TokenAccountNotFoundError' || \n error.message?.includes('could not find account')) {\n return 0;\n }\n throw error;\n }\n}\n\n/**\n * Get all Solana balances (SOL + USDC)\n */\nexport async function getSolanaBalances(\n address: string,\n chain: SolanaChainName\n): Promise<{ sol: number; usdc: number }> {\n const [sol, usdc] = await Promise.all([\n getSolanaBalance(address, chain),\n getSolanaUSDCBalance(address, chain),\n ]);\n \n return { sol, usdc };\n}\n\n/**\n * Request SOL airdrop (devnet only)\n */\nexport async function requestSolanaAirdrop(\n address: string,\n chain: SolanaChainName,\n amount: number = 1\n): Promise<string> {\n if (chain !== 'solana_devnet') {\n throw new Error('Airdrop only available on devnet');\n }\n \n const connection = getSolanaConnection(chain);\n const pubkey = new PublicKey(address);\n \n const signature = await connection.requestAirdrop(\n pubkey,\n amount * LAMPORTS_PER_SOL\n );\n \n // Wait for confirmation\n await connection.confirmTransaction(signature, 'confirmed');\n \n return signature;\n}\n\n/**\n * Validate Solana address format\n */\nexport function isValidSolanaAddress(address: string): boolean {\n try {\n new PublicKey(address);\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * Solana Chain Configuration\n * \n * Solana is NOT an EVM chain - uses different:\n * - Key format: ed25519 (EdDSA) vs secp256k1 (ECDSA)\n * - Address format: Base58 vs 0x hex\n * - Token standard: SPL vs ERC-20\n */\n\nimport { Connection, PublicKey } from '@solana/web3.js';\n\nexport interface SolanaChainConfig {\n name: string;\n cluster: 'mainnet-beta' | 'devnet' | 'testnet';\n rpc: string;\n explorer: string;\n explorerTx: string;\n tokens: {\n USDC: {\n mint: string;\n decimals: number;\n };\n };\n}\n\nexport type SolanaChainName = 'solana' | 'solana_devnet';\n\nexport const SOLANA_CHAINS: Record<SolanaChainName, SolanaChainConfig> = {\n solana: {\n name: 'Solana Mainnet',\n cluster: 'mainnet-beta',\n rpc: 'https://api.mainnet-beta.solana.com',\n explorer: 'https://solscan.io/account/',\n explorerTx: 'https://solscan.io/tx/',\n tokens: {\n USDC: {\n mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // Circle official USDC\n decimals: 6,\n },\n },\n },\n solana_devnet: {\n name: 'Solana Devnet',\n cluster: 'devnet',\n rpc: 'https://api.devnet.solana.com',\n explorer: 'https://solscan.io/account/',\n explorerTx: 'https://solscan.io/tx/',\n tokens: {\n USDC: {\n // Circle's devnet USDC (if not available, we'll deploy our own test token)\n mint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n decimals: 6,\n },\n },\n },\n};\n\n/**\n * Get Solana RPC connection\n */\nexport function getSolanaConnection(chain: SolanaChainName): Connection {\n const config = SOLANA_CHAINS[chain];\n return new Connection(config.rpc, 'confirmed');\n}\n\n/**\n * Get USDC mint public key for a Solana chain\n */\nexport function getUSDCMint(chain: SolanaChainName): PublicKey {\n return new PublicKey(SOLANA_CHAINS[chain].tokens.USDC.mint);\n}\n\n/**\n * Get Solana chain config\n */\nexport function getSolanaChain(name: SolanaChainName): SolanaChainConfig {\n const config = SOLANA_CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported Solana chain: ${name}. Supported: ${Object.keys(SOLANA_CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * Check if a chain name is a Solana chain\n */\nexport function isSolanaChain(chain: string): chain is SolanaChainName {\n return chain === 'solana' || chain === 'solana_devnet';\n}\n\n/**\n * Get explorer URL for a Solana address\n */\nexport function getSolanaExplorerUrl(chain: SolanaChainName, address: string): string {\n const config = SOLANA_CHAINS[chain];\n const clusterParam = chain === 'solana_devnet' ? '?cluster=devnet' : '';\n return `${config.explorer}${address}${clusterParam}`;\n}\n\n/**\n * Get explorer URL for a Solana transaction\n */\nexport function getSolanaTxExplorerUrl(chain: SolanaChainName, signature: string): string {\n const config = SOLANA_CHAINS[chain];\n const clusterParam = chain === 'solana_devnet' ? '?cluster=devnet' : '';\n return `${config.explorerTx}${signature}${clusterParam}`;\n}\n","/**\n * Solana Facilitator\n * \n * Pay-for-success payment settlement for Solana SPL token transfers.\n * Unlike EVM chains, Solana doesn't have a third-party facilitator - \n * we verify and settle directly on-chain.\n * \n * Flow:\n * 1. Client signs a SPL token transfer authorization\n * 2. Server receives the signed transaction\n * 3. Server verifies the signature and amount\n * 4. Server submits the transaction to settle payment\n */\n\nimport { \n Connection, \n PublicKey, \n Transaction,\n VersionedTransaction,\n sendAndConfirmTransaction,\n Keypair,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n createTransferCheckedInstruction,\n getAccount,\n createAssociatedTokenAccountInstruction,\n TOKEN_PROGRAM_ID,\n} from '@solana/spl-token';\nimport { \n BaseFacilitator, \n type X402PaymentPayload, \n type X402PaymentRequirements,\n type VerifyResult,\n type SettleResult,\n type HealthCheckResult,\n} from './interface.js';\nimport { SOLANA_CHAINS, type SolanaChainName } from '../chains/solana.js';\n\n/**\n * Solana payment payload structure\n */\nexport interface SolanaPaymentPayload {\n /** Base58 encoded signed transaction */\n signedTransaction: string;\n /** Sender's public key (Base58) */\n sender: string;\n /** Chain: solana or solana_devnet */\n chain: SolanaChainName;\n}\n\n/**\n * Solana Facilitator configuration\n */\nexport interface SolanaFacilitatorConfig {\n /** Optional fee payer keypair for gasless transactions */\n feePayerKeypair?: Keypair;\n}\n\n/**\n * Solana Facilitator for pay-for-success payments\n * \n * Supports gasless mode: if feePayerKeypair is provided, server pays tx fees\n */\nexport class SolanaFacilitator extends BaseFacilitator {\n readonly name = 'solana';\n readonly displayName = 'Solana Direct';\n readonly supportedNetworks = ['solana:mainnet', 'solana:devnet'];\n\n private connections: Map<SolanaChainName, Connection> = new Map();\n private feePayerKeypair?: Keypair;\n\n constructor(config?: SolanaFacilitatorConfig) {\n super();\n this.feePayerKeypair = config?.feePayerKeypair;\n \n // Initialize connections\n for (const [chain, config] of Object.entries(SOLANA_CHAINS)) {\n this.connections.set(\n chain as SolanaChainName, \n new Connection(config.rpc, 'confirmed')\n );\n }\n \n if (this.feePayerKeypair) {\n console.log(`[SolanaFacilitator] Gasless mode enabled. Fee payer: ${this.feePayerKeypair.publicKey.toBase58()}`);\n }\n }\n \n /**\n * Get fee payer public key (for gasless transactions)\n */\n getFeePayerPubkey(): string | null {\n return this.feePayerKeypair?.publicKey.toBase58() || null;\n }\n\n private getConnection(chain: SolanaChainName): Connection {\n const conn = this.connections.get(chain);\n if (!conn) {\n throw new Error(`No connection for chain: ${chain}`);\n }\n return conn;\n }\n\n /**\n * Convert our chain name to network identifier\n */\n static chainToNetwork(chain: SolanaChainName): string {\n return chain === 'solana' ? 'solana:mainnet' : 'solana:devnet';\n }\n\n /**\n * Convert network identifier to chain name\n */\n static networkToChain(network: string): SolanaChainName | null {\n if (network === 'solana:mainnet') return 'solana';\n if (network === 'solana:devnet') return 'solana_devnet';\n return null;\n }\n\n async healthCheck(): Promise<HealthCheckResult> {\n const start = Date.now();\n try {\n // Check devnet connection\n const conn = this.getConnection('solana_devnet');\n await conn.getSlot();\n return {\n healthy: true,\n latencyMs: Date.now() - start,\n };\n } catch (error: any) {\n return {\n healthy: false,\n error: error.message,\n };\n }\n }\n\n /**\n * Verify a Solana payment\n * \n * Checks:\n * 1. Transaction is valid and properly signed\n * 2. Transfer instruction matches expected amount and recipient\n */\n async verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult> {\n try {\n const solanaPayload = paymentPayload.payload as SolanaPaymentPayload;\n if (!solanaPayload || !solanaPayload.signedTransaction) {\n return { valid: false, error: 'Missing signed transaction' };\n }\n\n const chain = solanaPayload.chain || 'solana_devnet';\n const chainConfig = SOLANA_CHAINS[chain];\n if (!chainConfig) {\n return { valid: false, error: `Invalid chain: ${chain}` };\n }\n\n // Decode the transaction\n const txBuffer = Buffer.from(solanaPayload.signedTransaction, 'base64');\n let tx: Transaction | VersionedTransaction;\n \n try {\n // Try legacy transaction first\n tx = Transaction.from(txBuffer);\n } catch {\n // Try versioned transaction\n tx = VersionedTransaction.deserialize(txBuffer);\n }\n\n // Verify at least one signature exists (may be partial in gasless mode)\n if (tx instanceof Transaction) {\n // In gasless mode, fee payer signature is added by server\n // Client only signs for token transfer authority\n const hasAnySignature = tx.signatures.some(sig => \n sig.signature && !sig.signature.every(b => b === 0)\n );\n if (!hasAnySignature) {\n return { valid: false, error: 'Transaction not signed' };\n }\n }\n\n // Parse expected values from requirements\n const expectedAmount = BigInt(requirements.amount);\n const expectedRecipient = new PublicKey(requirements.payTo);\n\n // For now, we trust the transaction structure\n // Full verification happens at settlement time\n return {\n valid: true,\n details: {\n chain,\n sender: solanaPayload.sender,\n recipient: requirements.payTo,\n amount: requirements.amount,\n },\n };\n } catch (error: any) {\n return { valid: false, error: error.message };\n }\n }\n\n /**\n * Settle a Solana payment\n * \n * Submits the signed transaction to the network.\n * In gasless mode, adds fee payer signature before submitting.\n */\n async settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult> {\n try {\n const solanaPayload = paymentPayload.payload as SolanaPaymentPayload;\n if (!solanaPayload || !solanaPayload.signedTransaction) {\n return { success: false, error: 'Missing signed transaction' };\n }\n\n const chain = solanaPayload.chain || 'solana_devnet';\n const connection = this.getConnection(chain);\n\n // Decode the transaction\n const txBuffer = Buffer.from(solanaPayload.signedTransaction, 'base64');\n \n let txToSend: Buffer;\n \n try {\n // Try legacy transaction\n const tx = Transaction.from(txBuffer);\n \n // Check if we need to add fee payer signature (gasless mode)\n if (this.feePayerKeypair && tx.feePayer) {\n const feePayerPubkey = this.feePayerKeypair.publicKey.toBase58();\n const txFeePayer = tx.feePayer.toBase58();\n \n if (txFeePayer === feePayerPubkey) {\n // Gasless mode: add fee payer signature\n console.log(`[SolanaFacilitator] Gasless mode: adding fee payer signature`);\n tx.partialSign(this.feePayerKeypair);\n }\n }\n \n txToSend = tx.serialize();\n } catch (e: any) {\n // Fall back to versioned transaction (no gasless support for versioned yet)\n txToSend = txBuffer;\n }\n\n // Send the transaction\n const signature = await connection.sendRawTransaction(txToSend, {\n skipPreflight: false,\n preflightCommitment: 'confirmed',\n });\n\n // Wait for confirmation\n const confirmation = await connection.confirmTransaction(signature, 'confirmed');\n \n if (confirmation.value.err) {\n return {\n success: false,\n error: `Transaction failed: ${JSON.stringify(confirmation.value.err)}`,\n transaction: signature,\n };\n }\n\n return {\n success: true,\n transaction: signature,\n status: 'confirmed',\n };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n }\n\n supportsNetwork(network: string): boolean {\n return this.supportedNetworks.includes(network);\n }\n}\n\n/**\n * Create a Solana payment transaction for signing\n * \n * This is called by the client to create the transaction to sign.\n * \n * @param senderPubkey - The sender's public key (token owner)\n * @param recipientPubkey - The recipient's public key\n * @param amount - Amount in token base units\n * @param chain - Solana chain (solana or solana_devnet)\n * @param feePayerPubkey - Optional fee payer public key for gasless transactions\n */\nexport async function createSolanaPaymentTransaction(\n senderPubkey: PublicKey,\n recipientPubkey: PublicKey,\n amount: bigint,\n chain: SolanaChainName,\n feePayerPubkey?: PublicKey,\n connection?: Connection,\n): Promise<Transaction> {\n const chainConfig = SOLANA_CHAINS[chain];\n const conn = connection ?? new Connection(chainConfig.rpc, 'confirmed');\n const mint = new PublicKey(chainConfig.tokens.USDC.mint);\n\n // Determine who pays fees (gasless mode uses server's fee payer)\n const actualFeePayer = feePayerPubkey || senderPubkey;\n\n // Get ATAs\n const senderATA = await getAssociatedTokenAddress(mint, senderPubkey);\n const recipientATA = await getAssociatedTokenAddress(mint, recipientPubkey);\n\n const transaction = new Transaction();\n\n // Check if recipient ATA exists\n try {\n await getAccount(conn, recipientATA);\n } catch {\n // Create ATA for recipient (fee payer pays rent in gasless mode)\n transaction.add(\n createAssociatedTokenAccountInstruction(\n actualFeePayer, // payer (fee payer in gasless mode)\n recipientATA, // ata to create\n recipientPubkey, // owner\n mint // mint\n )\n );\n }\n\n // Add transfer instruction\n transaction.add(\n createTransferCheckedInstruction(\n senderATA, // source\n mint, // mint\n recipientATA, // destination\n senderPubkey, // owner (sender still authorizes the transfer)\n amount, // amount\n chainConfig.tokens.USDC.decimals // decimals\n )\n );\n\n // Get recent blockhash\n const { blockhash, lastValidBlockHeight } = await conn.getLatestBlockhash();\n transaction.recentBlockhash = blockhash;\n transaction.feePayer = actualFeePayer;\n\n return transaction;\n}\n\nexport default SolanaFacilitator;\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 *\n * **Per-scheme `extra` conventions:**\n * - `alipay-aipay` (2.0.0+): `extra` carries the parallel `Payment-Needed`\n * contents so x402-aware clients don't need to read the separate HTTP\n * header. Server side, `AlipayFacilitator.createPaymentRequirements`\n * populates: `payment_needed_header` (Base64URL of nested\n * `{protocol, method}` JSON), `out_trade_no`, `pay_before`, `service_id`.\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 * MoltsPay Client — Core (runtime-agnostic protocol logic)\n *\n * Pure, Node-API-free modules usable by both Node and Web clients.\n * All code here must avoid `fs`, `os`, `path`, `crypto` (beyond webcrypto),\n * and other Node-only APIs so it bundles cleanly for the browser.\n */\n\nexport * from './types.js';\nexport * from './chain-map.js';\nexport * from './base64.js';\nexport * from './errors.js';\nexport * from './eip3009.js';\nexport * from './eip2612.js';\nexport * from './bnb-intent.js';\nexport * from './solana-tx.js';\nexport * from './x402.js';\n","/**\n * Core protocol types — shared between Node and Web clients.\n *\n * These describe x402 / MPP wire formats and EIP-712 typed-data shapes.\n * They MUST NOT import from any Node-only modules.\n */\n\n// ===== x402 protocol constants =====\n\nexport const X402_VERSION = 2;\nexport const PAYMENT_REQUIRED_HEADER = 'x-payment-required';\nexport const PAYMENT_HEADER = 'x-payment';\n\n// ===== x402 payment requirements (server → client) =====\n\nexport interface X402PaymentRequirements {\n scheme: string;\n network: string;\n\n // v2 fields\n amount?: string;\n asset?: string;\n payTo?: string;\n maxTimeoutSeconds?: number;\n extra?: Record<string, unknown>;\n\n // v1 legacy fields\n maxAmountRequired?: string;\n resource?: string;\n description?: string;\n}\n\n// ===== EIP-3009 TransferWithAuthorization (Base / Polygon / Base Sepolia) =====\n\nexport interface EIP3009Authorization {\n from: string;\n to: string;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: string;\n}\n\n// ===== EIP-2612 Permit (Tempo — pathUSD / AlphaUSD / BetaUSD / ThetaUSD) =====\n\nexport interface EIP2612PermitMessage {\n owner: string;\n spender: string;\n value: string;\n nonce: string;\n deadline: string;\n}\n\n/** Signed permit payload carried inside an x402 `scheme: \"permit\"` payment. */\nexport interface EIP2612PermitPayload {\n owner: string;\n spender: string;\n value: string;\n nonce: string;\n deadline: string;\n v: number;\n r: string;\n s: string;\n}\n\n// ===== BNB payment intent (Phase 3c+ pre-approval flow) =====\n\nexport interface BnbPaymentIntent {\n from: string;\n to: string;\n amount: string;\n token: string;\n service: string;\n nonce: number;\n deadline: number;\n}\n\n// ===== EIP-712 typed-data envelope (runtime-agnostic signing input) =====\n\nexport interface TypedDataDomain {\n name?: string;\n version?: string;\n chainId?: number;\n verifyingContract?: string;\n salt?: string;\n}\n\nexport interface TypedDataField {\n name: string;\n type: string;\n}\n\nexport interface TypedDataEnvelope<TMessage = Record<string, unknown>> {\n domain: TypedDataDomain;\n types: Record<string, readonly TypedDataField[]>;\n primaryType: string;\n message: TMessage;\n}\n","/**\n * Chain identifier mapping — pure, runtime-agnostic.\n *\n * Translates between x402 `network` field values (CAIP-2 style, e.g.\n * `eip155:8453`, `solana:mainnet`) and MoltsPay's internal chain names\n * (e.g. `base`, `solana`, `tempo_moderato`).\n */\n\nexport type ChainName =\n | 'base'\n | 'polygon'\n | 'base_sepolia'\n | 'tempo_moderato'\n | 'bnb'\n | 'bnb_testnet'\n | 'solana'\n | 'solana_devnet';\n\nconst NETWORK_TO_CHAIN: Record<string, ChainName> = {\n 'eip155:8453': 'base',\n 'eip155:137': 'polygon',\n 'eip155:84532': 'base_sepolia',\n 'eip155:42431': 'tempo_moderato',\n 'eip155:56': 'bnb',\n 'eip155:97': 'bnb_testnet',\n 'solana:mainnet': 'solana',\n 'solana:devnet': 'solana_devnet',\n};\n\nconst CHAIN_TO_NETWORK: Record<ChainName, string> = Object.fromEntries(\n Object.entries(NETWORK_TO_CHAIN).map(([network, chain]) => [chain, network])\n) as Record<ChainName, string>;\n\n/** Convert an x402 `network` identifier to a MoltsPay chain name, or null if unknown. */\nexport function networkToChainName(network: string): ChainName | null {\n return NETWORK_TO_CHAIN[network] ?? null;\n}\n\n/** Convert a MoltsPay chain name to its x402 `network` identifier. */\nexport function chainNameToNetwork(chain: ChainName): string {\n return CHAIN_TO_NETWORK[chain];\n}\n\n/** Check if an x402 `network` identifier is Solana (SVM). */\nexport function isSolanaNetwork(network: string): boolean {\n return network.startsWith('solana:');\n}\n\n/** List every supported chain name. */\nexport function listSupportedChains(): ChainName[] {\n return Object.keys(CHAIN_TO_NETWORK) as ChainName[];\n}\n","/**\n * Universal base64 — works in both browser and Node without polyfills.\n *\n * Node has `Buffer`, browsers have `btoa`/`atob`. We detect at runtime to\n * avoid pulling a Buffer polyfill into the web bundle.\n */\n\ntype BufferLike = {\n from(input: string | Uint8Array, encoding?: string): { toString(enc: string): string };\n};\n\nconst BufferCtor: BufferLike | undefined =\n (globalThis as { Buffer?: BufferLike }).Buffer;\n\n/** Encode a UTF-8 string as base64 (standard, with padding). */\nexport function encodeBase64(input: string): string {\n if (BufferCtor) {\n return BufferCtor.from(input, 'utf-8').toString('base64');\n }\n // Browser path: btoa requires binary (Latin-1) string; UTF-8 → bytes → binary string.\n const bytes = new TextEncoder().encode(input);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/** Decode a standard base64 string into a UTF-8 string. */\nexport function decodeBase64(input: string): string {\n if (BufferCtor) {\n return BufferCtor.from(input, 'base64').toString('utf-8');\n }\n const binary = atob(input);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n}\n\n/** Decode a base64url string (RFC 4648 §5: `-` and `_` instead of `+` and `/`, optional padding). */\nexport function decodeBase64Url(input: string): string {\n const standard = input.replace(/-/g, '+').replace(/_/g, '/');\n const padded = standard + '='.repeat((4 - (standard.length % 4)) % 4);\n return decodeBase64(padded);\n}\n\n/** Encode a UTF-8 string as base64url (no padding). */\nexport function encodeBase64Url(input: string): string {\n return encodeBase64(input)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/** Decode a base64 string to raw bytes. Used for Solana transactions where the payload is binary. */\nexport function base64ToUint8Array(input: string): Uint8Array {\n if (BufferCtor) {\n const buf = BufferCtor.from(input, 'base64') as unknown as Uint8Array;\n return new Uint8Array(buf);\n }\n const binary = atob(input);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/** Encode raw bytes as a base64 string. */\nexport function uint8ArrayToBase64(bytes: Uint8Array): string {\n if (BufferCtor) {\n return BufferCtor.from(bytes).toString('base64');\n }\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n","/**\n * Structured error classes used by both Node and Web clients.\n *\n * Every error carries a `code` field so callers can branch on the kind\n * without string-matching `.message`.\n */\n\nexport class MoltsPayError extends Error {\n readonly code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = 'MoltsPayError';\n this.code = code;\n }\n}\n\nexport class NotInitializedError extends MoltsPayError {\n constructor(message = 'Client not initialized') {\n super('NOT_INITIALIZED', message);\n this.name = 'NotInitializedError';\n }\n}\n\nexport class UnsupportedChainError extends MoltsPayError {\n constructor(public readonly chain: string, message?: string) {\n super('UNSUPPORTED_CHAIN', message ?? `Chain not supported: ${chain}`);\n this.name = 'UnsupportedChainError';\n }\n}\n\nexport interface NeedsApprovalDetails {\n chain: string;\n spender: string;\n token: string;\n currentAllowance: string;\n required: string;\n}\n\nexport class NeedsApprovalError extends MoltsPayError {\n constructor(public readonly details: NeedsApprovalDetails, message?: string) {\n super(\n 'NEEDS_APPROVAL',\n message ??\n `Insufficient allowance for ${details.spender}. Current=${details.currentAllowance}, required=${details.required}.`\n );\n this.name = 'NeedsApprovalError';\n }\n}\n\nexport class InsufficientBalanceError extends MoltsPayError {\n constructor(message: string) {\n super('INSUFFICIENT_BALANCE', message);\n this.name = 'InsufficientBalanceError';\n }\n}\n\nexport class SpendingLimitExceededError extends MoltsPayError {\n constructor(message: string) {\n super('SPENDING_LIMIT_EXCEEDED', message);\n this.name = 'SpendingLimitExceededError';\n }\n}\n\nexport class PaymentRejectedError extends MoltsPayError {\n constructor(message: string) {\n super('PAYMENT_REJECTED', message);\n this.name = 'PaymentRejectedError';\n }\n}\n\nexport class ServerError extends MoltsPayError {\n constructor(public readonly status: number, message: string) {\n super('SERVER_ERROR', message);\n this.name = 'ServerError';\n }\n}\n\nexport class InvalidPaymentHeaderError extends MoltsPayError {\n constructor(message: string) {\n super('INVALID_PAYMENT_HEADER', message);\n this.name = 'InvalidPaymentHeaderError';\n }\n}\n","/**\n * EIP-3009 TransferWithAuthorization typed-data builder (pure).\n *\n * Used for gasless payments on Base / Polygon / Base Sepolia where the token\n * contract (USDC, USDT variants) implements the `transferWithAuthorization`\n * function selector.\n *\n * The builder is runtime-agnostic: it returns the envelope, and the signer\n * (Node `ethers.Wallet` or Web EIP-1193 provider) does the actual signing.\n */\n\nimport type {\n EIP3009Authorization,\n TypedDataEnvelope,\n} from './types.js';\n\nexport interface BuildEIP3009Args {\n /** Payer address (will become `from`). */\n from: string;\n /** Payee address (will become `to`). */\n to: string;\n /** Token amount in the token's smallest unit (e.g. 6 decimals for USDC → 500000 = $0.50). */\n value: string;\n /** Random 32-byte nonce as 0x-prefixed hex. Caller generates with their environment's CSPRNG. */\n nonce: string;\n /** Unix seconds when the authorization starts being valid. Default 0. */\n validAfter?: string;\n /** Unix seconds when the authorization expires. Default now + 3600. */\n validBefore?: string;\n\n /** EIP-155 chain id. */\n chainId: number;\n /** Token contract address. */\n tokenAddress: string;\n /** EIP-712 domain name as declared on-chain (e.g. \"USD Coin\" for USDC Base). */\n tokenName: string;\n /** EIP-712 domain version. Usually \"2\" for USDC, varies for USDT. */\n tokenVersion: string;\n}\n\nexport const EIP3009_TYPES = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n} as const;\n\nexport function buildEIP3009TypedData(\n args: BuildEIP3009Args\n): TypedDataEnvelope<EIP3009Authorization> {\n const validAfter = args.validAfter ?? '0';\n const validBefore =\n args.validBefore ?? (Math.floor(Date.now() / 1000) + 3600).toString();\n\n const authorization: EIP3009Authorization = {\n from: args.from,\n to: args.to,\n value: args.value,\n validAfter,\n validBefore,\n nonce: args.nonce,\n };\n\n return {\n domain: {\n name: args.tokenName,\n version: args.tokenVersion,\n chainId: args.chainId,\n verifyingContract: args.tokenAddress,\n },\n types: EIP3009_TYPES,\n primaryType: 'TransferWithAuthorization',\n message: authorization,\n };\n}\n","/**\n * EIP-2612 Permit typed-data builder (pure).\n *\n * Used for gasless payments on Tempo Moderato, where the TIP-20 stablecoin\n * contracts (pathUSD, AlphaUSD, BetaUSD, ThetaUSD) implement EIP-2612 permit\n * but not EIP-3009 transferWithAuthorization.\n *\n * Domain values below were verified on-chain against the live\n * `DOMAIN_SEPARATOR()` returned by each token contract on 2026-04-21.\n * See docs/TEMPO-WEB-SUPPORT.md Section 2 and Phase 0 results in\n * docs/WEB-CLIENT-DESIGN.md.\n */\n\nimport type {\n EIP2612PermitMessage,\n TypedDataEnvelope,\n} from './types.js';\n\nexport interface BuildEIP2612PermitArgs {\n owner: string;\n spender: string;\n /** Token amount in the token's smallest unit. */\n value: string;\n /** Current `nonces(owner)` value on the token contract. Caller must read from chain. */\n nonce: string;\n /** Unix seconds until the permit expires. */\n deadline: string;\n\n chainId: number;\n /** Token contract address (the `verifyingContract` for EIP-712 domain). */\n tokenAddress: string;\n /** EIP-712 domain name as declared on-chain. See `TEMPO_EIP2612_DOMAINS` for Tempo tokens. */\n tokenName: string;\n /** EIP-712 domain version. */\n tokenVersion: string;\n}\n\nexport const EIP2612_TYPES = {\n Permit: [\n { name: 'owner', type: 'address' },\n { name: 'spender', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n} as const;\n\nexport function buildEIP2612PermitTypedData(\n args: BuildEIP2612PermitArgs\n): TypedDataEnvelope<EIP2612PermitMessage> {\n const message: EIP2612PermitMessage = {\n owner: args.owner,\n spender: args.spender,\n value: args.value,\n nonce: args.nonce,\n deadline: args.deadline,\n };\n\n return {\n domain: {\n name: args.tokenName,\n version: args.tokenVersion,\n chainId: args.chainId,\n verifyingContract: args.tokenAddress,\n },\n types: EIP2612_TYPES,\n primaryType: 'Permit',\n message,\n };\n}\n\n// ===== Tempo Moderato TIP-20 domain fixtures (verified on-chain 2026-04-21) =====\n\nexport const TEMPO_CHAIN_ID = 42431;\n\nexport interface TempoTokenDomain {\n /** Symbol case-preserved (e.g. \"pathUSD\"). */\n symbol: string;\n /** Token contract address. */\n address: string;\n /** EIP-712 domain name (first letter capitalized, e.g. \"PathUSD\"). */\n name: string;\n /** EIP-712 domain version (uniformly \"1\" across all 4 Tempo TIP-20s). */\n version: string;\n /** Expected on-chain DOMAIN_SEPARATOR. Used as a guardrail fixture in tests. */\n expectedDomainSeparator: string;\n /** Token decimals. */\n decimals: number;\n}\n\nexport const TEMPO_EIP2612_DOMAINS: Record<string, TempoTokenDomain> = {\n pathUSD: {\n symbol: 'pathUSD',\n address: '0x20c0000000000000000000000000000000000000',\n name: 'PathUSD',\n version: '1',\n expectedDomainSeparator:\n '0xc601a8a9918b2bf5076e4a47925ebe14407230ba77dc84e248c15218a46ad6b4',\n decimals: 6,\n },\n AlphaUSD: {\n symbol: 'AlphaUSD',\n address: '0x20c0000000000000000000000000000000000001',\n name: 'AlphaUSD',\n version: '1',\n expectedDomainSeparator:\n '0x32d762f61205377e7b402fe1ef8014637c3b3a18234a5629cfab1982efdc2630',\n decimals: 6,\n },\n BetaUSD: {\n symbol: 'BetaUSD',\n address: '0x20c0000000000000000000000000000000000002',\n name: 'BetaUSD',\n version: '1',\n expectedDomainSeparator:\n '0x99a494a75ff574cc1ff179a3b4f4ec0aff55b51cdd0906994aa8e91bf95137d3',\n decimals: 6,\n },\n ThetaUSD: {\n symbol: 'ThetaUSD',\n address: '0x20c0000000000000000000000000000000000003',\n name: 'ThetaUSD',\n version: '1',\n expectedDomainSeparator:\n '0x657494dec20c65c40c636bb1781412e1dd3eb5aba55cd8dc8346a00753b9a782',\n decimals: 6,\n },\n};\n\n/** Convenience: build a Permit for a Tempo token by symbol. */\nexport function buildTempoPermitTypedData(args: {\n symbol: keyof typeof TEMPO_EIP2612_DOMAINS | string;\n owner: string;\n spender: string;\n value: string;\n nonce: string;\n deadline: string;\n}): TypedDataEnvelope<EIP2612PermitMessage> {\n const token = TEMPO_EIP2612_DOMAINS[args.symbol];\n if (!token) {\n throw new Error(`Unknown Tempo token: ${args.symbol}`);\n }\n return buildEIP2612PermitTypedData({\n owner: args.owner,\n spender: args.spender,\n value: args.value,\n nonce: args.nonce,\n deadline: args.deadline,\n chainId: TEMPO_CHAIN_ID,\n tokenAddress: token.address,\n tokenName: token.name,\n tokenVersion: token.version,\n });\n}\n","/**\n * BNB PaymentIntent typed-data builder (pure).\n *\n * Used on BNB Smart Chain (mainnet 56, testnet 97) where the user has already\n * approved the MoltsPay spender contract (via `npx moltspay approve` on CLI,\n * or `client.approveBnb()` on Web) and now signs an EIP-712 intent that\n * authorizes a specific spender → payTo transfer for a specific service.\n *\n * The server's spender contract verifies the signature in `transferFrom`-like\n * flow and moves tokens from owner → payTo.\n */\n\nimport type { BnbPaymentIntent, TypedDataEnvelope } from './types.js';\n\nexport interface BuildBnbIntentArgs {\n /** Owner address (payer). */\n from: string;\n /** Recipient address (payTo). */\n to: string;\n /** Amount in token's smallest unit (BNB stablecoins use 18 decimals). */\n amount: string;\n /** Token contract address on BNB chain. */\n tokenAddress: string;\n /** Service ID the intent authorizes payment for. */\n service: string;\n /** Intent nonce — any uint256 value unique per (owner, service). Caller supplies. */\n nonce: number;\n /** Unix milliseconds when the intent expires. */\n deadline: number;\n /** Chain id (56 or 97). */\n chainId: number;\n}\n\nexport const BNB_INTENT_TYPES = {\n PaymentIntent: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n { name: 'token', type: 'address' },\n { name: 'service', type: 'string' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n} as const;\n\nexport const BNB_DOMAIN_NAME = 'MoltsPay';\nexport const BNB_DOMAIN_VERSION = '1';\n\nexport function buildBnbIntentTypedData(\n args: BuildBnbIntentArgs\n): TypedDataEnvelope<BnbPaymentIntent> {\n const intent: BnbPaymentIntent = {\n from: args.from,\n to: args.to,\n amount: args.amount,\n token: args.tokenAddress,\n service: args.service,\n nonce: args.nonce,\n deadline: args.deadline,\n };\n\n return {\n domain: {\n name: BNB_DOMAIN_NAME,\n version: BNB_DOMAIN_VERSION,\n chainId: args.chainId,\n },\n types: BNB_INTENT_TYPES,\n primaryType: 'PaymentIntent',\n message: intent,\n };\n}\n","/**\n * Solana SPL token transfer transaction builder (pure).\n *\n * Re-export of the browser-compatible builder from\n * `src/facilitators/solana.ts`. The builder uses only\n * `@solana/web3.js` + `@solana/spl-token`, both of which bundle cleanly\n * for the browser.\n *\n * The Node client uses its local Keypair to sign the returned `Transaction`;\n * the Web client passes the transaction to a Wallet Adapter's\n * `signTransaction` method. In both cases the server submits the signed\n * transaction — the client never broadcasts.\n */\n\nexport { createSolanaPaymentTransaction } from '../../facilitators/solana.js';\n","/**\n * x402 protocol primitives — pure, runtime-agnostic.\n *\n * Handles:\n * - Decoding the `X-Payment-Required` header into a list of requirements\n * (supporting v1 array / v2 object-with-accepts / single-object shapes).\n * - Selecting the right requirement for a user-chosen chain.\n * - Assembling and base64-encoding the `X-Payment` request header.\n *\n * All inputs and outputs are JSON-serializable. No network I/O, no signing.\n */\n\nimport {\n decodeBase64,\n encodeBase64,\n} from './base64.js';\nimport {\n networkToChainName,\n chainNameToNetwork,\n type ChainName,\n} from './chain-map.js';\nimport { InvalidPaymentHeaderError, UnsupportedChainError } from './errors.js';\nimport {\n X402_VERSION,\n type X402PaymentRequirements,\n} from './types.js';\n\n/**\n * Decode a base64-encoded `X-Payment-Required` header into an array of\n * requirement entries. Accepts all three observed shapes:\n * - v1: `[req1, req2, ...]`\n * - v2: `{ x402Version: 2, accepts: [req1, req2, ...] }`\n * - single: `{ scheme, network, ... }`\n */\nexport function parsePaymentRequiredHeader(\n header: string\n): X402PaymentRequirements[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(decodeBase64(header));\n } catch {\n throw new InvalidPaymentHeaderError('Invalid x-payment-required header');\n }\n\n if (Array.isArray(parsed)) {\n return parsed as X402PaymentRequirements[];\n }\n if (\n parsed &&\n typeof parsed === 'object' &&\n Array.isArray((parsed as { accepts?: unknown }).accepts)\n ) {\n return (parsed as { accepts: X402PaymentRequirements[] }).accepts;\n }\n // Single requirement object\n return [parsed as X402PaymentRequirements];\n}\n\n/** Collect the set of chain names the server accepts, from its requirements list. */\nexport function serverAcceptedChains(\n requirements: X402PaymentRequirements[]\n): ChainName[] {\n return requirements\n .map(r => networkToChainName(r.network))\n .filter((c): c is ChainName => c !== null);\n}\n\n/**\n * Select the chain to pay on, using the 1.5.x rules:\n * - If the caller specified a chain, it must be in the server's accepted set.\n * - Otherwise, default to `base` **only** when `base` is the sole accepted chain;\n * otherwise require the caller to be explicit.\n */\nexport function selectChain(\n requirements: X402PaymentRequirements[],\n userSpecifiedChain?: ChainName\n): ChainName {\n const accepted = serverAcceptedChains(requirements);\n\n if (userSpecifiedChain) {\n if (!accepted.includes(userSpecifiedChain)) {\n throw new UnsupportedChainError(\n userSpecifiedChain,\n `Server doesn't accept '${userSpecifiedChain}'. Server accepts: ${accepted.join(', ')}`\n );\n }\n return userSpecifiedChain;\n }\n\n if (accepted.length === 1 && accepted[0] === 'base') {\n return 'base';\n }\n\n throw new UnsupportedChainError(\n 'unspecified',\n `Server accepts: ${accepted.join(', ')}. Please specify a chain explicitly.`\n );\n}\n\n/** Find the requirement entry matching a given chain name. */\nexport function findRequirementForChain(\n requirements: X402PaymentRequirements[],\n chain: ChainName\n): X402PaymentRequirements | null {\n const network = chainNameToNetwork(chain);\n return requirements.find(r => r.network === network) ?? null;\n}\n\n/** x402 v2 payment payload envelope, returned by the scheme-specific builders. */\nexport interface X402PaymentPayloadEnvelope {\n x402Version: typeof X402_VERSION;\n scheme: string;\n network: string;\n payload: Record<string, unknown>;\n accepted: X402PaymentRequirements;\n}\n\n/**\n * Assemble an x402 v2 payment payload.\n *\n * `payload` is scheme-specific (EIP-3009 authorization, EIP-2612 permit\n * struct, BNB intent, Solana signed transaction, etc.). `accepted` mirrors\n * the server's requirement so settlement can verify exact match.\n */\nexport function buildPaymentPayload(args: {\n scheme: string;\n network: string;\n payload: Record<string, unknown>;\n accepted: X402PaymentRequirements;\n}): X402PaymentPayloadEnvelope {\n return {\n x402Version: X402_VERSION,\n scheme: args.scheme,\n network: args.network,\n payload: args.payload,\n accepted: args.accepted,\n };\n}\n\n/** Base64-encode a payment payload for the `X-Payment` request header. */\nexport function encodePaymentHeader(\n payload: X402PaymentPayloadEnvelope | Record<string, unknown>\n): string {\n return encodeBase64(JSON.stringify(payload));\n}\n","/**\n * NodeSigner — PaymentSigner implementation for Node.js.\n *\n * Wraps:\n * - an ethers.Wallet for EVM signTypedData + sendEvmTransaction\n * - an optional (lazy-loaded) @solana/web3.js Keypair for signSolanaTransaction\n *\n * The Node CLI's `MoltsPayClient` constructs this from the local wallet files\n * in `~/.moltspay/`. Public surface is the same `PaymentSigner` interface that\n * Web signers implement (Phase 4), so `MoltsPayClient.pay()` doesn't branch on\n * runtime.\n */\n\nimport { ethers, Wallet } from 'ethers';\nimport { Transaction, Keypair } from '@solana/web3.js';\nimport type { PaymentSigner } from '../signer.js';\nimport type { TypedDataEnvelope } from '../core/index.js';\nimport { CHAINS } from '../../chains/index.js';\n\nexport interface NodeSignerOptions {\n /** Lazy loader for the Solana Keypair. Resolves to null when no Solana wallet is configured. */\n getSolanaKeypair?: () => Keypair | null;\n}\n\nexport class NodeSigner implements PaymentSigner {\n private readonly evmWallet: Wallet;\n private readonly getSolanaKeypair: () => Keypair | null;\n\n constructor(evmWallet: Wallet, options: NodeSignerOptions = {}) {\n this.evmWallet = evmWallet;\n this.getSolanaKeypair = options.getSolanaKeypair ?? (() => null);\n }\n\n async getEvmAddress(): Promise<string> {\n return this.evmWallet.address;\n }\n\n async getSolanaAddress(): Promise<string | null> {\n const kp = this.getSolanaKeypair();\n return kp ? kp.publicKey.toBase58() : null;\n }\n\n async signTypedData<TMessage>(envelope: TypedDataEnvelope<TMessage>): Promise<string> {\n // ethers expects types without the implicit EIP712Domain entry (our envelopes\n // already exclude it) and mutable arrays; core stores them `readonly`, so we\n // shallow-copy each type-list to satisfy the ethers signature.\n const mutableTypes: Record<string, { name: string; type: string }[]> = {};\n for (const [key, fields] of Object.entries(envelope.types)) {\n mutableTypes[key] = [...fields];\n }\n return this.evmWallet.signTypedData(\n envelope.domain,\n mutableTypes,\n envelope.message as Record<string, unknown>\n );\n }\n\n async sendEvmTransaction(args: {\n chainId: number;\n to: string;\n data: string;\n value?: string;\n }): Promise<string> {\n const chain = findChainByChainId(args.chainId);\n if (!chain) {\n throw new Error(`sendEvmTransaction: unknown chainId ${args.chainId}`);\n }\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n const connected = this.evmWallet.connect(provider);\n const tx = await connected.sendTransaction({\n to: args.to,\n data: args.data,\n value: args.value ? BigInt(args.value) : 0n,\n });\n return tx.hash;\n }\n\n async signSolanaTransaction(args: {\n transactionBase64: string;\n partialSign: boolean;\n }): Promise<string> {\n const kp = this.getSolanaKeypair();\n if (!kp) {\n throw new Error('signSolanaTransaction: no Solana wallet configured');\n }\n const tx = Transaction.from(Buffer.from(args.transactionBase64, 'base64'));\n if (args.partialSign) {\n tx.partialSign(kp);\n } else {\n tx.sign(kp);\n }\n return tx.serialize({ requireAllSignatures: false }).toString('base64');\n }\n}\n\n// CHAINS is a Record<ChainName, ChainConfig>; we look up by numeric chainId.\nfunction findChainByChainId(chainId: number): { rpc: string } | undefined {\n for (const cfg of Object.values(CHAINS)) {\n if ((cfg as { chainId?: number }).chainId === chainId) {\n return cfg as { rpc: string };\n }\n }\n return undefined;\n}\n","/**\n * AlipayClient — the 8-step `pay402()` state machine (design §5.2.3).\n *\n * The Alipay skill guide §5 forbids skipping any step; each maps to one\n * `alipay-bot` spawn. This class drives them in order and hands the caller a\n * single terminal `AlipayPaymentResult`, so paying via Alipay looks the same\n * as awaiting an EVM settle (design §5.2.3 \"关键设计\").\n *\n * 0. ensureCli() version gate (≥ MIN_CLI_VERSION)\n * 1b. alipay-bot payment-intent … session handshake\n * 2. alipay-bot check-wallet → NeedsWalletSetupError if unopened\n * 3. dump Payment-Needed → tmp file (internal, user-invisible)\n * 4. alipay-bot 402-buyer-pay -f … -r … → paymentUrl + tradeNo → onPaymentPending\n * 5. pollUntil(tradeNo) 3s poll until paid / rejected / timeout\n * 7. return resource body\n * 8. alipay-bot 402-buyer-fulfillment-ack fire-and-forget\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { mkdir, writeFile } from 'fs/promises';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport type { X402PaymentRequirements } from '../core/types.js';\nimport type { CliRunner } from './cli.js';\nimport { runCli } from './cli.js';\nimport { ensureCli, type VersionGetter } from './install.js';\nimport { pollUntil } from './poll.js';\nimport { AlipayProtocolError, NeedsWalletSetupError } from './errors.js';\nimport { alipayLog, timeStep } from './log.js';\n\nexport interface AlipayPendingInfo {\n paymentUrl: string;\n shortenUrl?: string;\n tradeNo: string;\n}\n\nexport interface AlipayPayOptions {\n /** The resource URL being paid for (alipay-bot `-r`). */\n resourceUrl: string;\n /** The alipay 402 accepts[] entry (carries extra.payment_needed_header etc.). */\n requirement: X402PaymentRequirements;\n /** Verbatim CLI passthrough (MEDIA: lines are stripped before this is called). */\n onLine?: (line: string) => void;\n /** Surfaced once the payment URL + tradeNo are known (Step 4). */\n onPaymentPending?: (info: AlipayPendingInfo) => void;\n /** Overall budget; defaults to the challenge's pay_before window. */\n timeoutMs?: number;\n /** Cancellation. */\n signal?: AbortSignal;\n /** Non-GET resource verb / body, forwarded to 402-buyer-pay. */\n method?: string;\n data?: string;\n /**\n * One-line payment intent summary (alipay-bot `payment-intent -i`, REQUIRED\n * by the CLI). Defaults to a summary derived from the requirement amount.\n */\n intentSummary?: string;\n}\n\nexport interface AlipayPaymentResult {\n /** The resource response body, verbatim. */\n body: string;\n payment: { tradeNo: string; outTradeNo?: string };\n /** Any MEDIA: image paths alipay-bot surfaced, stripped from the stream. */\n media: string[];\n}\n\nexport interface AlipayClientOptions {\n /** Stable session id; falls back to AIPAY_SESSION_ID, then a fresh UUID. */\n sessionId?: string;\n configDir?: string;\n /**\n * Host framework for alipay-bot session-path resolution (claudecode,\n * openclaw, nanobot, …). Defaults to AIPAY_FRAMEWORK, then 'openclaw'.\n * Note: 'moltspay' is NOT a framework alipay-bot recognizes.\n */\n framework?: string;\n /** DI seams for tests. */\n runner?: CliRunner;\n getVersion?: VersionGetter;\n now?: () => number;\n /**\n * Whether check-wallet results may use the process-level cache. Defaults to\n * \"only when the default (real-CLI) runner is used\", so injected test/DI\n * runners always spawn. Set explicitly to exercise the cache in tests.\n */\n cacheWallet?: boolean;\n /**\n * Whether the payment-intent handshake may be skipped via the process-level\n * cache. Same default as {@link cacheWallet} (only for the default runner).\n */\n cacheIntent?: boolean;\n}\n\nconst TRADE_NO_RE = /^\\d{32}$/;\n\n/**\n * Resolve the session id. The skill guide forbids *fabricating* a session-like\n * string, NOT generating a real UUID — so a crypto UUID is the correct default.\n */\nexport function resolveSessionId(explicit?: string, envSession?: string): string {\n return explicit ?? envSession ?? randomUUID();\n}\n\n/** Skill guide §5 Step 8: tradeNo must be exactly 32 digits. */\nexport function assertTradeNo(t: string): void {\n if (!TRADE_NO_RE.test(t)) {\n throw new AlipayProtocolError(`invalid tradeNo (expect 32 digits): ${t}`);\n }\n}\n\n/** Pull a 32-digit tradeNo from CLI output (bare or `tradeNo: …` / `trade_no=…`). */\nexport function parseTradeNo(lines: string[]): string | null {\n for (const line of lines) {\n const labeled = line.match(/trade[_-]?no[\"'\\s:=]+(\\d{32})/i);\n if (labeled) return labeled[1];\n const bare = line.match(/\\b(\\d{32})\\b/);\n if (bare) return bare[1];\n }\n return null;\n}\n\n/** Pull the payment URL (and optional shortened URL) from buyer-pay output. */\nexport function parsePaymentUrl(lines: string[]): { paymentUrl?: string; shortenUrl?: string } {\n let paymentUrl: string | undefined;\n let shortenUrl: string | undefined;\n for (const line of lines) {\n const m = line.match(/(alipays?:\\/\\/\\S+|https?:\\/\\/\\S+)/i);\n if (!m) continue;\n // alipay-bot prints the link inside markdown `[文字](url)`; the greedy `\\S+`\n // swallows the trailing `)` (and any `]`/`` ` ``/`>`), yielding a URL that\n // 404s. Strip those trailing chars.\n const url = m[1].replace(/[)\\]`>]+$/, '');\n if (/short|qr\\.alipay|surl|\\/s\\//i.test(line) && !shortenUrl) shortenUrl = url;\n else if (!paymentUrl) paymentUrl = url;\n }\n // A lone URL on a \"short\" line should still serve as the payment URL.\n if (!paymentUrl && shortenUrl) paymentUrl = shortenUrl;\n return { paymentUrl, shortenUrl };\n}\n\n/** Split MEDIA: image-path lines out of the stream (design §5.2.4). */\nexport function extractMedia(line: string): string | null {\n const m = line.match(/^\\s*MEDIA:\\s*(.+?)\\s*$/);\n return m ? m[1] : null;\n}\n\n/**\n * Decide whether check-wallet reports an opened, ready wallet.\n *\n * Observed real output (alipay-bot 0.3.15): a JSON object `{code, message,\n * reason}` — `code: 500, message: \"未开通\"` when the wallet is NOT opened, and\n * crucially the **process still exits 0**, so the exit code is useless here.\n * We therefore key off `code` (200 = ready) and fall back to textual markers.\n */\nexport function isWalletReady(lines: string[]): boolean {\n const text = lines.join('\\n').trim();\n try {\n const json = JSON.parse(text);\n if (json && typeof json.code !== 'undefined') return Number(json.code) === 200;\n } catch {\n // Not JSON — fall through to textual markers.\n }\n return !/未开通|未开启|NOT[_\\s-]*(OPEN|BOUND|SET)|NEEDS?[_\\s-]*SETUP|NO[_\\s-]*WALLET/i.test(text);\n}\n\n/**\n * Pull the embedded resource JSON out of an alipay-bot 0.3.15 status report.\n *\n * The settled `402-query-payment-status` report (Shape C) embeds the re-fetched\n * resource after a `资源响应体:` label, e.g. `**资源响应体**:\\n{ \"success\": true,\n * \"result\": { … } }`. We locate that label, brace-match the following JSON\n * object (string-aware, so braces inside values don't fool it), parse it and\n * surface `.result` (the seller's handler output). Returns `undefined` if no\n * embedded object is found, so the caller can fall back to the raw report.\n */\nfunction extractResourceFromReport(report: string): string | undefined {\n const label = report.search(/资源响应体/);\n const start = report.indexOf('{', label === -1 ? 0 : label);\n if (start === -1) return undefined;\n let depth = 0, inStr = false, esc = false;\n for (let i = start; i < report.length; i++) {\n const ch = report[i];\n if (inStr) {\n if (esc) esc = false;\n else if (ch === '\\\\') esc = true;\n else if (ch === '\"') inStr = false;\n continue;\n }\n if (ch === '\"') inStr = true;\n else if (ch === '{') depth++;\n else if (ch === '}' && --depth === 0) {\n const slice = report.slice(start, i + 1);\n try {\n const obj = JSON.parse(slice);\n const r = obj?.resourceResponse ?? obj?.result ?? obj?.data ?? obj?.body ?? obj;\n return typeof r === 'string' ? r : JSON.stringify(r);\n } catch {\n return slice;\n }\n }\n }\n return undefined;\n}\n\n/**\n * Extract the resource body from the paid status-poll output.\n *\n * alipay-bot 0.3.15 (Shape C) wraps the settled report in `{body: \"<markdown>\"}`\n * with the resource embedded under a `资源响应体:` label — pull that out and\n * surface `.result`. Older/other shapes put the resource under data/result/body\n * at the top level. Falls back to a `BODY:` marker, then to the joined\n * non-marker lines. Verified live 2026-06-10 against a real completed trade.\n */\nexport function extractBody(lines: string[]): string {\n const text = lines.join('\\n').trim();\n try {\n const json = JSON.parse(text);\n if (json && typeof json === 'object') {\n // Preferred (alipay-bot ≥1.0.x): the settled result carries the delivered\n // resource in a structured `resourceResponse` field — the HTTP response\n // body from the bot's OWN authenticated x402 re-request (the bot holds the\n // Payment-Proof and re-requests `/execute` for us). Read that field\n // directly instead of scraping the human report. See docs/ALIPAY-RAIL.md\n // §9.3. `resourceResponse` may itself wrap the seller output under\n // `.result`/`.data`/`.body`, so surface that the same way the report path does.\n if (json.resourceResponse !== undefined && json.resourceResponse !== null) {\n const rr = json.resourceResponse;\n const r = (typeof rr === 'object')\n ? (rr.result ?? rr.data ?? rr.body ?? rr)\n : rr;\n return typeof r === 'string' ? r : JSON.stringify(r);\n }\n // Shape C: {body:\"<markdown report>\"} — dig out the embedded resource.\n if (typeof json.body === 'string') {\n const inner = extractResourceFromReport(json.body);\n return inner ?? json.body;\n }\n const body = json.data ?? json.result ?? json.body ?? json.resource;\n if (body !== undefined) return typeof body === 'string' ? body : JSON.stringify(body);\n return text;\n }\n } catch {\n // Not JSON — fall through.\n }\n const idx = lines.findIndex((l) => /^\\s*BODY:/.test(l));\n if (idx !== -1) {\n const first = lines[idx].replace(/^\\s*BODY:\\s*/, '');\n return [first, ...lines.slice(idx + 1)].join('\\n').trim();\n }\n return lines.filter((l) => !/^\\s*(MEDIA|STATUS|INFO):/.test(l)).join('\\n').trim();\n}\n\n/**\n * Default TTL (ms) for the positive check-wallet cache. The wallet\n * authorization is ACCOUNT-level and stable once opened, yet `pay402` re-runs\n * `check-wallet` on EVERY payment — measured ~22s each (the per-line timeline\n * shows a single silent ~22s gateway round-trip, then an instant `{code:200}`\n * dump). Overridable via `MOLTSPAY_ALIPAY_WALLET_TTL_MS`; set it to `0` to\n * disable the cache and always spawn `check-wallet`.\n */\nconst DEFAULT_WALLET_TTL_MS = 10 * 60 * 1000; // 10 min\n\nfunction resolveWalletTtlMs(): number {\n const raw = process.env.MOLTSPAY_ALIPAY_WALLET_TTL_MS;\n if (raw === undefined || raw.trim() === '') return DEFAULT_WALLET_TTL_MS;\n const n = Number(raw);\n return Number.isFinite(n) && n >= 0 ? n : DEFAULT_WALLET_TTL_MS;\n}\n\n// Process-level positive cache, keyed by (configDir, framework) so distinct\n// accounts never share state. We cache ONLY the \"ready\" verdict (a freshly\n// bound wallet must be observed live, so NOT-ready is never cached) and ONLY\n// for the DEFAULT runner — injected (test/DI) runners always spawn, exactly\n// like the ensure-cli cache in ./install.ts.\nconst walletReadyUntil = new Map<string, number>();\n\n/** Clear the check-wallet cache (tests, or after the user (un)binds a wallet). */\nexport function resetWalletCache(): void {\n walletReadyUntil.clear();\n}\n\n/**\n * Default TTL (ms) for the payment-intent handshake skip-cache. `payment-intent`\n * is a session handshake whose OUTPUT pay402 discards — it runs purely for its\n * CLI/server side-effect. The profiler showed each spawn costs ~5-9s, almost\n * all of it the alipay-bot per-process cold start (device-fingerprint + native\n * risk-control init), NOT gateway. Because `402-buyer-pay` is passed `-s/-i/-w`\n * and is \"self-sufficient even if the cached intent didn't stick\" (see step 4),\n * a handshake already done for this account need not be repeated per payment.\n * We therefore skip the spawn once one has succeeded within the TTL. The session\n * id is per-payment random, so — exactly like the wallet cache — we key by\n * (configDir, framework), the account-stable identity. Override via\n * `MOLTSPAY_ALIPAY_INTENT_TTL_MS`; set `0` to disable and always handshake.\n */\nconst DEFAULT_INTENT_TTL_MS = 10 * 60 * 1000; // 10 min\n\nfunction resolveIntentTtlMs(): number {\n const raw = process.env.MOLTSPAY_ALIPAY_INTENT_TTL_MS;\n if (raw === undefined || raw.trim() === '') return DEFAULT_INTENT_TTL_MS;\n const n = Number(raw);\n return Number.isFinite(n) && n >= 0 ? n : DEFAULT_INTENT_TTL_MS;\n}\n\n// Process-level \"handshake done\" cache, keyed (configDir, framework) like the\n// wallet cache, and likewise only honored for the DEFAULT runner.\nconst intentDoneUntil = new Map<string, number>();\n\n/** Clear the payment-intent skip-cache (tests, or after (un)bind / session reset). */\nexport function resetIntentCache(): void {\n intentDoneUntil.clear();\n}\n\nexport class AlipayClient {\n private readonly sessionId: string;\n private readonly configDir: string;\n private readonly framework: string;\n private readonly runner: CliRunner;\n private readonly getVersion?: VersionGetter;\n private readonly now: () => number;\n /** Only the default runner may use the process-level wallet cache. */\n private readonly walletCacheable: boolean;\n /** Only the default runner may use the process-level payment-intent cache. */\n private readonly intentCacheable: boolean;\n\n constructor(opts: AlipayClientOptions = {}) {\n this.sessionId = resolveSessionId(opts.sessionId, process.env.AIPAY_SESSION_ID);\n this.configDir = opts.configDir ?? join(homedir(), '.moltspay');\n this.framework = opts.framework ?? process.env.AIPAY_FRAMEWORK ?? 'openclaw';\n this.runner = opts.runner ?? runCli;\n this.getVersion = opts.getVersion;\n this.now = opts.now ?? Date.now;\n this.walletCacheable = opts.cacheWallet ?? !opts.runner;\n this.intentCacheable = opts.cacheIntent ?? !opts.runner;\n }\n\n /**\n * Throws NeedsWalletSetupError unless alipay-bot reports an opened wallet.\n *\n * Skips the ~22s `check-wallet` spawn entirely when a prior call cached a\n * \"ready\" verdict within the TTL (see {@link DEFAULT_WALLET_TTL_MS}).\n */\n async checkWallet(signal?: AbortSignal, flow?: string): Promise<void> {\n const ttlMs = resolveWalletTtlMs();\n const cacheKey = `${this.configDir}::${this.framework}`;\n const useCache = this.walletCacheable && ttlMs > 0;\n\n if (useCache) {\n const until = walletReadyUntil.get(cacheKey);\n if (until !== undefined && this.now() < until) {\n alipayLog.info('wallet.cache', { flow, step: 'check-wallet', hit: true, ttlMsLeft: until - this.now() });\n return;\n }\n }\n\n const { lines } = await this.runner(['check-wallet'], { signal, step: 'check-wallet', flow });\n if (!isWalletReady(lines)) {\n // Defensive: drop any cache entry for this key. (We only reach here on a\n // cache MISS, so the entry is already absent or expired — but this keeps\n // the map from ever holding a key whose last observed verdict was NOT\n // ready. A fresh positive is recovered explicitly via resetWalletCache.)\n if (this.walletCacheable) walletReadyUntil.delete(cacheKey);\n throw new NeedsWalletSetupError(\n 'Alipay wallet not opened. Run: moltspay alipay apply (then: moltspay alipay bind)',\n );\n }\n if (useCache) {\n walletReadyUntil.set(cacheKey, this.now() + ttlMs);\n alipayLog.info('wallet.cache', { flow, step: 'check-wallet', hit: false, cachedForMs: ttlMs });\n }\n }\n\n /** Run the full 8-step flow and resolve with the resource body. */\n async pay402(opts: AlipayPayOptions): Promise<AlipayPaymentResult> {\n const { resourceUrl, requirement, signal } = opts;\n const extra = (requirement.extra ?? {}) as Record<string, unknown>;\n const paymentNeededHeader = String(extra.payment_needed_header ?? '');\n if (!paymentNeededHeader) {\n throw new AlipayProtocolError('alipay requirement missing extra.payment_needed_header');\n }\n\n // Correlation id + clock for the per-flow timing breakdown (see ./log.ts).\n const flow = this.sessionId;\n const flowStart = this.now();\n alipayLog.info('flow.start', { flow, resource: resourceUrl });\n\n // MEDIA: lines are stripped from the verbatim stream and collected.\n const media: string[] = [];\n const onLine = (line: string) => {\n const m = extractMedia(line);\n if (m) media.push(m);\n else opts.onLine?.(line);\n };\n\n // intent-summary is REQUIRED by alipay-bot's payment-intent; derive a\n // minimal one from the requirement when the caller didn't supply it.\n const intentSummary =\n opts.intentSummary?.trim() ||\n `支付 ${requirement.amount ?? ''} ${requirement.asset ?? 'CNY'}`.trim();\n\n // Step 0: version gate.\n await timeStep('ensure-cli', flow, () => ensureCli(this.getVersion));\n\n // Step 1b: session handshake (--intent-summary is mandatory). Skipped when a\n // prior handshake for this (configDir, framework) is still within TTL — the\n // ~5-9s spawn is almost all CLI cold start, and 402-buyer-pay re-supplies\n // -s/-i/-w so it stands alone. See {@link DEFAULT_INTENT_TTL_MS}.\n const intentTtlMs = resolveIntentTtlMs();\n const intentKey = `${this.configDir}::${this.framework}`;\n const useIntentCache = this.intentCacheable && intentTtlMs > 0;\n const intentUntil = useIntentCache ? intentDoneUntil.get(intentKey) : undefined;\n if (intentUntil !== undefined && this.now() < intentUntil) {\n alipayLog.info('intent.cache', { flow, step: 'payment-intent', hit: true, ttlMsLeft: intentUntil - this.now() });\n } else {\n await this.runner(\n ['payment-intent', '--session-id', this.sessionId, '--intent-summary', intentSummary,\n '--framework', this.framework],\n { onLine, signal, step: 'payment-intent', flow },\n );\n if (useIntentCache) {\n intentDoneUntil.set(intentKey, this.now() + intentTtlMs);\n alipayLog.info('intent.cache', { flow, step: 'payment-intent', hit: false, cachedForMs: intentTtlMs });\n }\n }\n\n // Step 2: wallet must be opened.\n await this.checkWallet(signal, flow);\n\n // Step 3: dump Payment-Needed to a tmp file for 402-buyer-pay -f.\n const reqId = String(extra.out_trade_no ?? randomUUID());\n const dir = join(this.configDir, 'alipay');\n await mkdir(dir, { recursive: true });\n const challengeFile = join(dir, `402_${reqId}.txt`);\n await writeFile(challengeFile, paymentNeededHeader, 'utf-8');\n\n // Step 4: initiate the buyer payment → paymentUrl + tradeNo. Pass session +\n // intent + framework so buyer-pay is self-sufficient even if the cached\n // intent didn't stick.\n const payArgs = ['402-buyer-pay', '-f', challengeFile, '-r', resourceUrl,\n '-s', this.sessionId, '-i', intentSummary, '-w', this.framework];\n if (opts.method) payArgs.push('-m', opts.method);\n if (opts.data) payArgs.push('-d', opts.data);\n const payRun = await this.runner(payArgs, { onLine, signal, step: '402-buyer-pay', flow });\n\n const tradeNo = parseTradeNo(payRun.lines);\n if (!tradeNo) {\n throw new AlipayProtocolError('402-buyer-pay did not return a tradeNo');\n }\n assertTradeNo(tradeNo);\n\n const { paymentUrl, shortenUrl } = parsePaymentUrl(payRun.lines);\n if (paymentUrl) {\n // End of the user-visible \"pre-QR\" window: everything from flow.start to\n // here (402 → payment-intent → check-wallet → buyer-pay) ran before the\n // QR/link could be shown. This `ms` is the number to optimize.\n alipayLog.info('flow.pending', { flow, tradeNo, ms: this.now() - flowStart });\n opts.onPaymentPending?.({ paymentUrl, shortenUrl, tradeNo });\n }\n\n // Step 5: poll until terminal. Deadline = explicit timeout or pay_before window.\n const pendingAt = this.now();\n const windowMs = (requirement.maxTimeoutSeconds ?? 30 * 60) * 1000;\n const deadline = this.now() + (opts.timeoutMs ?? windowMs);\n const poll = await pollUntil(tradeNo, resourceUrl, {\n // No onLine: the status-poll output embeds the resource and must not reach\n // the log stream — the body is surfaced via the return value below (§9.3).\n deadline,\n signal,\n runner: this.runner,\n now: this.now,\n // Re-fetch the resource the same way it was paid (POST + body), else the\n // status poll defaults to GET and 404s on a POST-only `/execute`.\n method: opts.method,\n data: opts.data,\n });\n\n // Settlement reached: time spent waiting for the buyer to scan + pay + the\n // facilitator to confirm (distinct from the pre-QR window above).\n alipayLog.info('flow.settled', { flow, tradeNo, ms: this.now() - pendingAt });\n\n // Step 7: surface the resource body.\n const body = extractBody(poll.lines);\n\n // Step 8: fire-and-forget fulfillment ack (best-effort; never blocks the result).\n void this.runner(['402-buyer-fulfillment-ack', '-t', tradeNo], {\n onLine, signal, step: '402-buyer-fulfillment-ack', flow,\n }).catch(() => undefined);\n\n return { body, payment: { tradeNo, outTradeNo: reqId }, media };\n }\n}\n","/**\n * alipay-bot shell-out (design §5.2.4).\n *\n * Hard constraints from the Alipay skill guide, implemented here so they hold\n * regardless of CLI version:\n *\n * - **spawn, never exec** — the skill guide requires CLI output be forwarded\n * to the user verbatim, line by line, with no wrapping/truncation. Only a\n * streaming stdout API can do that, and `paymentUrl` carries a crypto\n * signature that any truncation would invalidate.\n * - **env whitelist** — only the AIPAY_* channel vars + a minimal survival\n * set (PATH/HOME) are passed through; nothing else leaks into the child.\n */\n\nimport { spawn } from 'child_process';\nimport { alipayLog } from './log.js';\n\n/** The only env vars allowed through to alipay-bot (skill guide §7). */\nexport const ALLOWED_ENV = new Set([\n 'AIPAY_OUTPUT_CHANNEL',\n 'AIPAY_SESSION_ID',\n 'AIPAY_FRAMEWORK',\n 'AIPAY_MODEL',\n 'AIPAY_OS',\n // Minimal survival set for spawn to find the binary and a home dir.\n 'PATH',\n 'HOME',\n]);\n\n/** Project the environment down to the whitelist. */\nexport function filterEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n return Object.fromEntries(\n Object.entries(env).filter(([k]) => ALLOWED_ENV.has(k)),\n ) as NodeJS.ProcessEnv;\n}\n\nexport interface RunCliOptions {\n /** Called for every line of stdout/stderr, verbatim, in arrival order. */\n onLine?: (line: string) => void;\n /** Abort the run (sends SIGTERM to the child). */\n signal?: AbortSignal;\n /** Override the binary (default 'alipay-bot'); used by tests. */\n bin?: string;\n /** Extra env to merge on top of the whitelisted process env. */\n env?: NodeJS.ProcessEnv;\n /** Log label for this spawn (defaults to the first CLI arg / subcommand). */\n step?: string;\n /** Correlation id grouping this spawn with the rest of its payment flow. */\n flow?: string;\n}\n\nexport interface RunCliResult {\n exitCode: number;\n /** Every stdout+stderr line, in arrival order (for parsing). */\n lines: string[];\n}\n\n/** Split a chunk into complete lines, keeping a remainder buffer per stream. */\nfunction makeLineSplitter(onLine: (line: string) => void): (chunk: Buffer) => void {\n let buf = '';\n return (chunk: Buffer) => {\n buf += chunk.toString('utf-8');\n let nl: number;\n while ((nl = buf.indexOf('\\n')) !== -1) {\n onLine(buf.slice(0, nl));\n buf = buf.slice(nl + 1);\n }\n };\n}\n\n/** The runCli signature, so higher modules can inject a fake in tests. */\nexport type CliRunner = (args: string[], opts?: RunCliOptions) => Promise<RunCliResult>;\n\n/**\n * Opt-in CPU/network/native profiling of a single spawn (observe-only).\n *\n * Dormant unless BOTH are set in the bot's env:\n * MOLTSPAY_ALIPAY_CLI_PROFILE comma list of steps to profile (or \"all\")\n * MOLTSPAY_ALIPAY_CLI_PROFILE_HOOK abs path to scripts/cli-profile-hook.cjs\n * When active for `step`, injects NODE_OPTIONS=--require=<hook> + a per-spawn\n * MOLTSPAY_CLI_PROFILE_OUT jsonl path so the hook can decompose the spawn's\n * wall time into childSync / network / nativeStall buckets. stdout is left\n * untouched — the hook only ever writes to its own file. See the hook header\n * and docs/ALIPAY-SLOWNESS-REPORT for the why.\n */\nfunction profileEnv(step: string, flow?: string): NodeJS.ProcessEnv {\n const want = process.env.MOLTSPAY_ALIPAY_CLI_PROFILE;\n const hook = process.env.MOLTSPAY_ALIPAY_CLI_PROFILE_HOOK;\n if (!want || !hook) return {};\n const steps = want.split(',').map((s) => s.trim());\n if (!steps.includes('all') && !steps.includes(step)) return {};\n const dir = process.env.MOLTSPAY_ALIPAY_CLI_PROFILE_DIR || '/tmp';\n const safe = `${flow ?? 'noflow'}-${step}-${Date.now()}`.replace(/[^a-zA-Z0-9._-]/g, '_');\n const out = `${dir}/cli-profile-${safe}.json`;\n // filterEnv already strips the bot's own NODE_OPTIONS from the child, so the\n // CLI normally gets none — give it ONLY the profiling require, nothing else,\n // to avoid perturbing the very spawn we're measuring.\n alipayLog.info('cli.profile', { flow, step, out });\n return {\n NODE_OPTIONS: `--require=${hook}`,\n MOLTSPAY_CLI_PROFILE_OUT: out,\n };\n}\n\n/**\n * Spawn alipay-bot with the given args, forwarding every output line verbatim\n * and collecting them for the caller to parse. Resolves with the exit code.\n */\nexport const runCli: CliRunner = (args, opts = {}) => {\n const bin = opts.bin ?? 'alipay-bot';\n const step = opts.step ?? args[0] ?? '(no-arg)';\n const startedAt = Date.now();\n const lines: string[] = [];\n const collect = (line: string) => {\n lines.push(line);\n // Per-line timeline: offset (ms since spawn) + a short preview. At debug\n // level this cracks open an otherwise opaque spawn (e.g. 402-buyer-pay's\n // ~40s) into its progress timeline, revealing whether the time is one long\n // wait or many round-trips — without touching the real-charge call itself.\n alipayLog.debug('cli.line', {\n flow: opts.flow, step, ms: Date.now() - startedAt, preview: line.slice(0, 120),\n });\n opts.onLine?.(line);\n };\n\n alipayLog.debug('step.start', { flow: opts.flow, step });\n\n return new Promise<RunCliResult>((resolve, reject) => {\n const child = spawn(bin, args, {\n env: { ...filterEnv(process.env), ...profileEnv(step, opts.flow), ...(opts.env ?? {}) },\n });\n\n if (opts.signal) {\n if (opts.signal.aborted) child.kill('SIGTERM');\n opts.signal.addEventListener('abort', () => child.kill('SIGTERM'), { once: true });\n }\n\n // Raw chunk timeline (debug): catches output that never produces a newline\n // — spinners using '\\r', or a CLI that buffers then flushes — which the\n // line splitter alone would miss. The first chunk's offset ≈ time-to-first\n // -byte (cold start + first round-trip); gaps between chunks = real waits.\n let sawByte = false;\n const onChunk = (stream: 'out' | 'err') => (chunk: Buffer) => {\n const ms = Date.now() - startedAt;\n if (!sawByte) {\n sawByte = true;\n alipayLog.debug('cli.firstbyte', { flow: opts.flow, step, ms });\n }\n alipayLog.debug('cli.chunk', { flow: opts.flow, step, ms, stream, bytes: chunk.length });\n };\n\n const onStdout = makeLineSplitter(collect);\n const onStderr = makeLineSplitter(collect);\n child.stdout?.on('data', onChunk('out'));\n child.stderr?.on('data', onChunk('err'));\n child.stdout?.on('data', onStdout);\n child.stderr?.on('data', onStderr);\n\n child.on('error', (err) => {\n alipayLog.info('cli.exit', {\n flow: opts.flow, step, ms: Date.now() - startedAt, ok: false, err: err.message,\n });\n reject(err);\n });\n child.on('close', (code) => {\n alipayLog.info('cli.exit', {\n flow: opts.flow, step, ms: Date.now() - startedAt, ok: (code ?? 1) === 0, code: code ?? 1,\n });\n resolve({ exitCode: code ?? 1, lines });\n });\n });\n};\n","/**\n * Alipay rail log management (design §5.2 observability).\n *\n * The Alipay rail's latency lives in a chain of `alipay-bot` subprocess spawns\n * and gateway round-trips that, in production, are invisible: the only output is\n * the verbatim CLI passthrough the skill guide mandates on stdout. This module\n * adds a structured, opt-in log channel so every node of the `pay402` state\n * machine — and how long it took — can be observed and routed into the host\n * app's log pipeline, WITHOUT changing default behavior or polluting stdout.\n *\n * Usage (host app):\n * import { setAlipayLogLevel, setAlipayLogSink } from 'moltspay';\n * setAlipayLogLevel('info'); // or env MOLTSPAY_ALIPAY_LOG=info\n * setAlipayLogSink((line) => myLogger.info(line)); // default: process.stderr\n *\n * Levels: 'off' (default) < 'info' (node timings + flow totals) < 'debug'\n * (adds per-spawn start/exit and per-poll ticks). The level is read from\n * MOLTSPAY_ALIPAY_LOG at load and can be overridden at runtime.\n */\n\nexport type AlipayLogLevel = 'off' | 'info' | 'debug';\n\n/** A single structured log record. The sink receives both the line and this. */\nexport interface AlipayLogEvent {\n /** ISO-8601 timestamp. */\n ts: string;\n level: 'info' | 'debug';\n /** Event name: flow.start | flow.pending | flow.settled | flow.failed |\n * step.start | step.end | cli.exit | poll.tick. */\n event: string;\n /** Correlation id grouping all lines of one payment flow (session/tradeNo). */\n flow?: string;\n /** Node/step name, e.g. 'ensure-cli', 'payment-intent', '402-buyer-pay'. */\n step?: string;\n /** Elapsed milliseconds (on *.end / *.exit / flow.* total events). */\n ms?: number;\n [k: string]: unknown;\n}\n\nexport type AlipayLogSink = (line: string, event: AlipayLogEvent) => void;\n\nconst RANK: Record<AlipayLogLevel, number> = { off: 0, info: 1, debug: 2 };\n\nfunction normalizeLevel(v: string | undefined): AlipayLogLevel {\n const s = (v ?? '').toLowerCase();\n return s === 'info' || s === 'debug' ? s : 'off';\n}\n\nlet level: AlipayLogLevel = normalizeLevel(process.env.MOLTSPAY_ALIPAY_LOG);\n\n// Default sink: stderr, so structured logs never corrupt the verbatim CLI\n// stdout stream the skill guide requires.\nlet sink: AlipayLogSink = (line) => {\n process.stderr.write(line + '\\n');\n};\n\n/** Set the verbosity at runtime (overrides the MOLTSPAY_ALIPAY_LOG env). */\nexport function setAlipayLogLevel(next: AlipayLogLevel): void {\n level = next;\n}\n\n/** Current effective level. */\nexport function getAlipayLogLevel(): AlipayLogLevel {\n return level;\n}\n\n/** Route alipay log lines anywhere (host log pipeline, file, collector, …). */\nexport function setAlipayLogSink(fn: AlipayLogSink): void {\n sink = fn;\n}\n\nfunction enabledFor(want: 'info' | 'debug'): boolean {\n return RANK[level] >= RANK[want];\n}\n\nfunction render(event: string, fields: Record<string, unknown>): string {\n const parts = ['[moltspay:alipay]', String(fields.ts), event];\n if (fields.flow) parts.push(`flow=${fields.flow}`);\n if (fields.step) parts.push(`step=${fields.step}`);\n if (typeof fields.ms === 'number') parts.push(`${fields.ms}ms`);\n for (const [k, v] of Object.entries(fields)) {\n // ts/level/event are already in the prefix; flow/step/ms rendered above.\n if (['ts', 'level', 'event', 'flow', 'step', 'ms'].includes(k)) continue;\n parts.push(`${k}=${typeof v === 'string' ? v : JSON.stringify(v)}`);\n }\n return parts.join(' ');\n}\n\nfunction emit(lvl: 'info' | 'debug', event: string, fields: Record<string, unknown>): void {\n if (!enabledFor(lvl)) return;\n const full: AlipayLogEvent = { ts: new Date().toISOString(), level: lvl, event, ...fields };\n try {\n sink(render(event, full), full);\n } catch {\n // A broken sink must never break a payment.\n }\n}\n\nexport const alipayLog = {\n info: (event: string, fields: Record<string, unknown> = {}): void => emit('info', event, fields),\n debug: (event: string, fields: Record<string, unknown> = {}): void => emit('debug', event, fields),\n /** True if anything at all would be logged (cheap guard for hot paths). */\n enabled: (): boolean => level !== 'off',\n};\n\n/**\n * Time one async node of the flow: logs `step.start` (debug) then `step.end`\n * (info) with elapsed ms and ok/err, and re-throws on failure. Returns fn's\n * value unchanged, so it wraps a call transparently:\n *\n * await timeStep('ensure-cli', flow, () => ensureCli(getVersion));\n */\nexport async function timeStep<T>(\n step: string,\n flow: string | undefined,\n fn: () => Promise<T>,\n): Promise<T> {\n if (!alipayLog.enabled()) return fn();\n const t0 = Date.now();\n alipayLog.debug('step.start', { flow, step });\n try {\n const out = await fn();\n alipayLog.info('step.end', { flow, step, ms: Date.now() - t0, ok: true });\n return out;\n } catch (err) {\n alipayLog.info('step.end', {\n flow,\n step,\n ms: Date.now() - t0,\n ok: false,\n err: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n}\n","/**\n * alipay-bot presence + version gate (design §5.2.4).\n *\n * alipay-bot is a runtime dependency of the Alipay payment rail. It is NOT on\n * npm (Alipay distributes it from their own CDN) and is licensed UNLICENSED, so\n * it can neither be a package.json dependency nor be bundled into this package.\n * Installing moltspay provisions it automatically via the @alipay/agent-payment\n * helper's `install-cli` (see scripts/postinstall.js) — the user opted into it\n * by installing this SDK, so provisioning a declared rail dependency is part of\n * that install (this supersedes the older 1.6.0 \"never touch the user's machine\"\n * stance for the specific case of an explicitly-installed rail dependency).\n *\n * This gate is the runtime safety net for when that provisioning did not run or\n * finish (`npm install --ignore-scripts`, or offline at install time): we fail\n * with a clear, actionable error telling the user the one command to run.\n */\n\nimport { execFile } from 'child_process';\nimport { promisify } from 'util';\nimport { AlipayCliNotFoundError, AlipayCliVersionError } from './errors.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** Minimum alipay-bot version with the 402-buyer-* subcommands this client drives. */\nexport const MIN_CLI_VERSION = '0.3.15';\n\n/** Compare two `major.minor.patch` strings. Returns true iff a < b. */\nexport function semverLt(a: string, b: string): boolean {\n const pa = a.split('.').map((n) => parseInt(n, 10));\n const pb = b.split('.').map((n) => parseInt(n, 10));\n for (let i = 0; i < 3; i++) {\n const x = pa[i] ?? 0;\n const y = pb[i] ?? 0;\n if (x !== y) return x < y;\n }\n return false;\n}\n\n/** Pull a `x.y.z` out of an `alipay-bot --version` line (handles a leading `v`). */\nexport function parseVersion(stdout: string): string | null {\n return stdout.match(/v?(\\d+\\.\\d+\\.\\d+)/)?.[1] ?? null;\n}\n\n/** Injectable for tests: returns the raw `alipay-bot --version` stdout. */\nexport type VersionGetter = () => Promise<string>;\n\nconst defaultGetVersion: VersionGetter = async () => {\n const { stdout } = await execFileAsync('alipay-bot', ['--version']);\n return stdout;\n};\n\n/** Run the gate once, no caching (the original logic). */\nasync function ensureCliUncached(getVersion: VersionGetter): Promise<string> {\n let stdout: string;\n try {\n stdout = await getVersion();\n } catch (e: any) {\n if (e?.code === 'ENOENT') {\n throw new AlipayCliNotFoundError(\n 'alipay-bot not installed. Run: npx -y @alipay/agent-payment install-cli',\n );\n }\n throw e;\n }\n\n const version = parseVersion(stdout);\n if (!version || semverLt(version, MIN_CLI_VERSION)) {\n throw new AlipayCliVersionError(\n `alipay-bot ${version ?? '?'} found, need ≥ ${MIN_CLI_VERSION}. ` +\n 'Run: npx -y @alipay/agent-payment@latest update',\n );\n }\n return version;\n}\n\n// Process-level memo for the real-CLI path. The installed alipay-bot version is\n// immutable for a process's lifetime, yet `pay402` re-runs the gate on EVERY\n// payment — and spawning `alipay-bot --version` measured ~3.8s each (a pure-\n// overhead cold start). Cache the first SUCCESS so subsequent payments skip the\n// spawn entirely. We never cache failures (a transient/ENOENT stays retryable),\n// and only cache the DEFAULT getter so injected (test/DI) getters run uncached.\nlet cachedVersion: string | null = null;\nlet inflight: Promise<string> | null = null;\n\n/** Clear the cached version gate (tests / after a CLI upgrade). */\nexport function resetCliVersionCache(): void {\n cachedVersion = null;\n inflight = null;\n}\n\n/**\n * Ensure alipay-bot is installed and new enough. Throws:\n * - AlipayCliNotFoundError if the binary is missing (ENOENT)\n * - AlipayCliVersionError if older than {@link MIN_CLI_VERSION}\n *\n * Memoized per process for the default getter: only the first call spawns\n * `alipay-bot --version`; later calls return the cached version immediately.\n * Concurrent first calls share a single in-flight spawn.\n */\nexport async function ensureCli(getVersion: VersionGetter = defaultGetVersion): Promise<string> {\n // Injected getters (tests/DI) bypass the cache so each call observes the fake.\n if (getVersion !== defaultGetVersion) {\n return ensureCliUncached(getVersion);\n }\n if (cachedVersion) return cachedVersion;\n if (!inflight) {\n inflight = ensureCliUncached(getVersion)\n .then((v) => {\n cachedVersion = v;\n return v;\n })\n .finally(() => {\n inflight = null;\n });\n }\n return inflight;\n}\n","/**\n * Alipay-rail client errors (2.0.0).\n *\n * Every class carries a stable `code` (the 1.6.0 convention established in\n * `../core/errors.ts`) so MCP hosts / upper-layer agents can branch on the\n * kind without string-matching `.message`:\n *\n * - ALIPAY_CLI_NOT_FOUND → guide the user to install alipay-bot\n * - ALIPAY_CLI_VERSION → guide the user to update alipay-bot\n * - ALIPAY_NEEDS_WALLET_SETUP→ guide the user to open/bind a wallet\n * - ALIPAY_PAYMENT_REJECTED → user declined / Alipay rejected the charge\n * - ALIPAY_PAYMENT_TIMEOUT → pay_before elapsed before completion (retryable)\n * - ALIPAY_PROTOCOL → malformed CLI output / contract violation\n * - UNSUPPORTED_RAIL → the requested rail is not in server accepts[]\n */\n\nimport { MoltsPayError } from '../core/errors.js';\n\nexport class AlipayCliNotFoundError extends MoltsPayError {\n constructor(message: string) {\n super('ALIPAY_CLI_NOT_FOUND', message);\n this.name = 'AlipayCliNotFoundError';\n }\n}\n\nexport class AlipayCliVersionError extends MoltsPayError {\n constructor(message: string) {\n super('ALIPAY_CLI_VERSION', message);\n this.name = 'AlipayCliVersionError';\n }\n}\n\nexport class NeedsWalletSetupError extends MoltsPayError {\n constructor(message = 'Alipay wallet not set up. Run: moltspay alipay apply') {\n super('ALIPAY_NEEDS_WALLET_SETUP', message);\n this.name = 'NeedsWalletSetupError';\n }\n}\n\nexport class AlipayPaymentRejectedError extends MoltsPayError {\n constructor(message: string) {\n super('ALIPAY_PAYMENT_REJECTED', message);\n this.name = 'AlipayPaymentRejectedError';\n }\n}\n\nexport class AlipayPaymentTimeoutError extends MoltsPayError {\n constructor(message: string) {\n super('ALIPAY_PAYMENT_TIMEOUT', message);\n this.name = 'AlipayPaymentTimeoutError';\n }\n}\n\nexport class AlipayProtocolError extends MoltsPayError {\n constructor(message: string) {\n super('ALIPAY_PROTOCOL', message);\n this.name = 'AlipayProtocolError';\n }\n}\n\nexport class UnsupportedRailError extends MoltsPayError {\n constructor(public readonly rail: string, message?: string) {\n super('UNSUPPORTED_RAIL', message ?? `Rail not supported by server: ${rail}`);\n this.name = 'UnsupportedRailError';\n }\n}\n","/**\n * Payment-status poller (design §5.2.3 Step 5).\n *\n * Wraps the user's long-tail \"open Alipay, scan, confirm\" behavior into a\n * single awaitable that resolves with a terminal PaymentResult — aligning the\n * Alipay rail to the EVM \"await settle\" semantics so callers need no special\n * code. Polls `alipay-bot 402-query-payment-status` until paid, rejected, the\n * `pay_before` deadline elapses, or the AbortSignal fires.\n *\n * OVERLAPPING POLLS (latency optimization, Rec #3): each\n * `402-query-payment-status` spawn is itself a SINGLE long blocking call —\n * measured ~25–36s (CLI cold start + one gateway snapshot query; first-byte ≈\n * total, NOT a server-side long-poll). A naive \"spawn → await full → wait →\n * spawn\" loop therefore detects a payment up to ~(spawn + gap + spawn) ≈ 50–60s\n * after the buyer actually pays. We can't shrink a single spawn from Node, but\n * we CAN launch the next poll on a fixed cadence WITHOUT waiting for the prior\n * one to finish, capped at {@link POLL_MAX_INFLIGHT} concurrent in-flight polls.\n * The first poll to observe \"paid\" wins. This bounds the post-payment detection\n * lag to roughly (launch cadence + one spawn) instead of (two spawns + gap).\n *\n * SAFETY: this issues concurrent `402-query-payment-status` calls, each of which\n * re-requests the resource (POST `/execute`) — and `/execute` DOES drive Alipay\n * fulfillment confirmation, it is not a no-op. Concurrency is nonetheless safe\n * because (a) Alipay fulfillment is IDEMPOTENT: the buyer already paid, so no\n * concurrent call double-charges, and the first `/execute` to reach the gateway\n * fulfills (`status:\"fulfilled\"`) while any concurrent sibling is rejected with\n * `40004 交易状态不允许履约` (\"trade state does not allow fulfillment\") — observed\n * live 2026-06-06, flow …048039. A 40004 sibling parses to `unknown` (NOT\n * `rejected`), so a loser never terminates the poll falsely. (b) Actual delivery\n * (e.g. the Discord role) is decoupled into the seller's single `onPaid`, fired\n * ONCE when this function resolves — never per-poll. So repeated/concurrent calls\n * neither double-charge nor double-deliver. Set concurrency to 1 to restore\n * strict sequential polling.\n */\n\nimport type { CliRunner } from './cli.js';\nimport { runCli } from './cli.js';\nimport { AlipayPaymentRejectedError, AlipayPaymentTimeoutError } from './errors.js';\nimport { alipayLog } from './log.js';\n\n/** Minimum gap (ms) between successive poll LAUNCHES (the cadence floor). */\nexport const POLL_INTERVAL_MS = 3_000;\n\n/** Default max concurrent in-flight status polls (1 = strict sequential). */\nexport const POLL_MAX_INFLIGHT = 2;\n\n/** Resolve max in-flight polls: opts > env > default. `1` disables overlap. */\nfunction resolveMaxInflight(override?: number): number {\n if (override !== undefined) return Math.max(1, Math.floor(override));\n const raw = process.env.MOLTSPAY_ALIPAY_POLL_MAX_INFLIGHT;\n if (raw !== undefined && raw.trim() !== '') {\n const n = Number(raw);\n if (Number.isFinite(n) && n >= 1) return Math.floor(n);\n }\n return POLL_MAX_INFLIGHT;\n}\n\n/** Resolve the launch-cadence gap (ms): opts > env > default. */\nfunction resolveLaunchGap(override?: number): number {\n if (override !== undefined) return Math.max(0, override);\n const raw = process.env.MOLTSPAY_ALIPAY_POLL_LAUNCH_MS;\n if (raw !== undefined && raw.trim() !== '') {\n const n = Number(raw);\n if (Number.isFinite(n) && n >= 0) return n;\n }\n return POLL_INTERVAL_MS;\n}\n\nexport type PaymentStatus = 'paid' | 'rejected' | 'pending' | 'unknown';\n\n/**\n * Classify a status poll's output lines.\n *\n * alipay-bot 402-query-payment-status emits a JSON envelope. Two observed\n * shapes (verified live against 0.3.15):\n * - `{success: boolean, errorCode, errorMsg}` — success:false +\n * errorCode TRADE_STATUS_UNPAID is STILL PENDING (the buyer hasn't paid\n * yet); success:true means the resource was delivered.\n * - `{code, message, reason}` — code 200 = delivered.\n *\n * NOTE: we must NOT text-match bare words like \"SUCCESS\"/\"PAID\" — the literal\n * JSON key `\"success\"` appears even when `success:false` (TRADE_STATUS_UNPAID),\n * which a naive regex misread as paid and returned an unpaid trade as success\n * (caught by the live 1-CNY E2E). So classify off the parsed fields only, and\n * fall back to anchored status tokens for non-JSON output.\n */\nexport function parseStatus(lines: string[]): PaymentStatus {\n const raw = lines.join('\\n').trim();\n try {\n const json = JSON.parse(raw);\n if (json && typeof json === 'object') {\n // Shape A: {success, errorCode, errorMsg}\n if (typeof json.success === 'boolean') {\n if (json.success) return 'paid';\n const err = String(json.errorCode ?? '').toUpperCase();\n if (/UNPAID|WAIT|PENDING|PROCESS|NOTPAY/.test(err)) return 'pending';\n if (/CLOSED|CANCEL|FAIL|REJECT|REFUSE|TIMEOUT|EXPIRE/.test(err)) return 'rejected';\n return 'pending'; // non-terminal error → keep waiting\n }\n // Shape B: {code, message, reason}\n if (typeof json.code !== 'undefined') {\n if (Number(json.code) === 200) return 'paid';\n const msg = `${json.message ?? ''}${json.reason ?? ''}`;\n if (/关闭|失败|拒绝|取消|超时|已撤销/.test(msg)) return 'rejected';\n return 'pending';\n }\n // Shape C (alipay-bot 0.3.15, live): {body: \"<markdown report>\"}. The\n // `402-query-payment-status` renders a human report (NOT the bare A/B\n // envelope), embedding the re-fetched resource. Classify off the report\n // text. Verified live 2026-06-10 against a real completed 1-CNY trade\n // (tradeNo …065406): the prior heuristic JSON.parse'd this to `{body}`,\n // matched neither A nor B, fell through to the raw-text markers (which the\n // Chinese report lacks) and returned `unknown` — so the poll never\n // terminated despite a SUCCESSFUL payment + resource fetch.\n if (typeof json.body === 'string') {\n return classifyReportText(json.body);\n }\n }\n } catch {\n // Not JSON — fall through to anchored textual markers on the raw output.\n }\n return classifyReportText(raw);\n}\n\n/**\n * Classify a status-report's text into a PaymentStatus.\n *\n * Used for both non-JSON CLI output and the Shape-C `{body}` markdown report.\n * Paid markers are anchored and only appear AFTER the buyer paid and the\n * facilitator verified: the report's \"查询支付状态成功并获取资源\" header and a\n * `资源响应状态 200` resource re-fetch are emitted only on a settled trade\n * (before payment the re-fetch returns 402). We also accept the x402/server\n * `\"status\":\"fulfilled\"` marker and Alipay `TRADE_SUCCESS/TRADE_FINISHED`.\n * We must NOT match bare \"SUCCESS\"/\"PAID\": the literal `\"success\"` key appears\n * even when success:false / TRADE_STATUS_UNPAID.\n */\nfunction classifyReportText(s: string): PaymentStatus {\n const text = s.toUpperCase();\n if (\n /查询支付状态成功并获取资源/.test(s) ||\n /资源响应状态[^0-9\\n]{0,8}200/.test(s) ||\n /TRADE_SUCCESS|TRADE_FINISHED|\"STATUS\":\\s*\"FULFILLED\"/.test(text)\n ) return 'paid';\n if (\n /TRADE_CLOSED|REJECTED|REFUSE|CANCEL/.test(text) ||\n /交易关闭|支付失败|已拒绝|已取消|已撤销|交易超时/.test(s)\n ) return 'rejected';\n if (\n /WAIT_BUYER_PAY|UNPAID|PENDING|WAITING/.test(text) ||\n /交易未支付|等待付款|待支付|未支付/.test(s)\n ) return 'pending';\n return 'unknown';\n}\n\nexport interface PollOptions {\n /** Hard deadline (epoch ms) from the challenge's `pay_before`. */\n deadline: number;\n /** Abort the poll loop (e.g. caller cancellation). */\n signal?: AbortSignal;\n // NOTE: there is intentionally NO `onLine` here. The status-poll output embeds\n // the delivered resource, so its raw lines must never be forwarded to the\n // user's log stream (docs/ALIPAY-RAIL.md §9.3). The resource is surfaced only\n // via pay402()'s `{body}` return value.\n /** Injectable CLI runner (default: real spawn). */\n runner?: CliRunner;\n /** Injectable sleep (default: real timer that also rejects on abort). */\n sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;\n /** Injectable clock (default: Date.now). */\n now?: () => number;\n /**\n * HTTP method + body for the resource re-fetch, mirrored from the buyer-pay\n * step. Required so `402-query-payment-status` re-requests the resource the\n * SAME way it was paid (POST + body). Without these it defaults to GET, which\n * 404s against a POST-only `/execute` and leaves the trade undetectable as paid.\n */\n method?: string;\n data?: string;\n /**\n * Max concurrent in-flight status polls. Overrides\n * `MOLTSPAY_ALIPAY_POLL_MAX_INFLIGHT` / {@link POLL_MAX_INFLIGHT}. `1` =\n * strict sequential (legacy behavior).\n */\n maxInflight?: number;\n /**\n * Minimum gap (ms) between successive poll launches. Overrides\n * `MOLTSPAY_ALIPAY_POLL_LAUNCH_MS` / {@link POLL_INTERVAL_MS}.\n */\n launchIntervalMs?: number;\n}\n\nfunction defaultSleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal?.aborted) return reject(new Error('aborted'));\n const t = setTimeout(resolve, ms);\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(t);\n reject(new Error('aborted'));\n },\n { once: true },\n );\n });\n}\n\nexport interface PollResult {\n status: 'paid';\n /** All lines from the final (paid) status poll, for body extraction. */\n lines: string[];\n}\n\ntype TickResult = { status: PaymentStatus; lines: string[] };\n\n/** Sentinel raced against in-flight polls to signal \"cadence elapsed, launch\". */\nconst LAUNCH = Symbol('launch');\n\n/**\n * Poll until the payment reaches a terminal state. Launches up to `maxInflight`\n * overlapping `402-query-payment-status` spawns on a fixed launch cadence; the\n * first to observe \"paid\" wins (see the module header for why and why it's safe).\n * @throws AlipayPaymentRejectedError if the buyer/Alipay rejects the charge.\n * @throws AlipayPaymentTimeoutError if `deadline` elapses while still pending.\n */\nexport async function pollUntil(\n tradeNo: string,\n resourceUrl: string,\n opts: PollOptions,\n): Promise<PollResult> {\n const runner = opts.runner ?? runCli;\n const sleep = opts.sleep ?? defaultSleep;\n const now = opts.now ?? Date.now;\n const maxInflight = resolveMaxInflight(opts.maxInflight);\n const launchGap = resolveLaunchGap(opts.launchIntervalMs);\n const args = [\n '402-query-payment-status', '-t', tradeNo, '-r', resourceUrl,\n ...(opts.method ? ['-m', opts.method] : []),\n ...(opts.data ? ['-d', opts.data] : []),\n ];\n\n // Internal abort cancels leftover sibling polls the moment we settle (so a\n // \"paid\" result stops the other in-flight spawns instead of letting them burn\n // a full gateway round-trip). Merged with the caller's signal so either source\n // tears the whole loop down.\n const internal = new AbortController();\n const signal = opts.signal ? AbortSignal.any([opts.signal, internal.signal]) : internal.signal;\n\n let tick = 0;\n let lastLaunch = -Infinity;\n const inflight = new Set<Promise<TickResult>>();\n\n const launch = (): void => {\n tick += 1;\n const myTick = tick;\n lastLaunch = now();\n const run = (async (): Promise<TickResult> => {\n // SECURITY (docs/ALIPAY-RAIL.md §9.3): the settled `402-query-payment-status`\n // output embeds the delivered resource (e.g. a video's base64). We must NOT\n // forward this spawn's raw stdout to the caller — that would leak the\n // deliverable into stdout/logs. So no `onLine` here. The runner still\n // collects `lines` independently of onLine (see cli.ts), and parseStatus /\n // extractBody read that RETURN value — so status detection and body\n // extraction are unaffected. The resource reaches the caller ONLY via\n // pay402()'s typed `{body}` result, never the log stream.\n const { lines } = await runner(args, {\n signal, step: 'query-payment-status', flow: tradeNo,\n });\n const status = parseStatus(lines);\n alipayLog.debug('poll.tick', { flow: tradeNo, tick: myTick, status });\n return { status, lines };\n })();\n // Track the .finally-wrapped promise so a settled poll frees its slot\n // before we race again. The value passes through unchanged.\n const tracked: Promise<TickResult> = run.finally(() => { inflight.delete(tracked); });\n inflight.add(tracked);\n };\n\n try {\n for (;;) {\n if (opts.signal?.aborted) throw new Error('aborted');\n const expired = now() >= opts.deadline;\n // Timeout only once nothing is still in flight — an already-launched poll\n // may yet return \"paid\" just past the deadline (matches the legacy loop,\n // which checked the deadline only before each spawn).\n if (expired && inflight.size === 0) {\n throw new AlipayPaymentTimeoutError(\n `Payment ${tradeNo} not completed before pay_before deadline`,\n );\n }\n\n // Fill open slots while the cadence allows (and we're not past deadline).\n while (!expired && inflight.size < maxInflight && now() - lastLaunch >= launchGap) {\n launch();\n }\n\n const waiters: Array<Promise<TickResult | typeof LAUNCH>> = [...inflight];\n if (!expired && inflight.size < maxInflight) {\n // Wait out the remaining cadence gap, then loop back to launch.\n const untilNext = Math.max(0, launchGap - (now() - lastLaunch));\n // On abort the launch timer rejects; resolve it to LAUNCH instead so an\n // abandoned timer (the poll won this race) never becomes an unhandled\n // rejection. Real aborts still propagate via the in-flight runner / the\n // signal.aborted check at the top of the loop.\n waiters.push(sleep(untilNext, signal).then(() => LAUNCH, () => LAUNCH));\n }\n\n // waiters is non-empty: either something is in flight, or we just queued a\n // launch timer. (If expired with nothing in flight we returned above.)\n const winner = await Promise.race(waiters);\n if (winner === LAUNCH) continue;\n if (winner.status === 'paid') return { status: 'paid', lines: winner.lines };\n if (winner.status === 'rejected') {\n throw new AlipayPaymentRejectedError(`Payment ${tradeNo} was rejected`);\n }\n // pending / unknown → the slot is freed; loop to relaunch.\n }\n } finally {\n // Cancel any siblings still running, and swallow their resulting rejections\n // so an aborted spawn never surfaces as an unhandled promise rejection.\n internal.abort();\n for (const p of inflight) p.catch(() => undefined);\n }\n}\n","/**\n * Rail routing (design §5.2.5).\n *\n * 1.6.0 and earlier, a service accepted exactly one payment method. With the\n * 2.0.0 Alipay rail the server's 402 `accepts[]` can carry BOTH crypto\n * (USDC on Base, …) and fiat (CNY via Alipay). `selectRail` picks one,\n * deterministically, from the caller's intent + the server's offer.\n *\n * Pure function — no Node-only imports, safe in the Web bundle.\n */\n\nimport type { X402PaymentRequirements } from '../core/types.js';\nimport { networkToChainName } from '../core/chain-map.js';\nimport { UnsupportedRailError } from './errors.js';\n\n/** Rail identifier as used in `{ rail }` / `--rail`: 'alipay' or a chain name. */\nexport const ALIPAY_RAIL = 'alipay';\n\nexport interface RailAvailability {\n /** Caller has an EVM wallet able to pay (e.g. funded USDC). */\n evmReady?: boolean;\n /** alipay-bot is installed/online and a wallet is opened. */\n alipayReady?: boolean;\n}\n\nexport interface SelectRailInput {\n /** The server's 402 `accepts[]`. */\n serverAccepts: X402PaymentRequirements[];\n /** Explicit caller choice from `{ rail }` / `--rail`. Highest priority. */\n explicitRail?: string;\n /** Client-configured ordered preference (e.g. `[\"base\", \"alipay\"]`). */\n preference?: string[];\n /** What the caller can actually do right now. */\n availability?: RailAvailability;\n}\n\nexport interface RailSelection {\n rail: string;\n requirement: X402PaymentRequirements;\n}\n\n/**\n * Map a single 402 accepts entry to its rail identifier.\n * Alipay → 'alipay'; EVM/SVM → the chain name; unknown → the raw network.\n */\nexport function railOf(req: X402PaymentRequirements): string {\n if (req.scheme === 'alipay-aipay' || req.network === ALIPAY_RAIL) return ALIPAY_RAIL;\n return networkToChainName(req.network) ?? req.network;\n}\n\nfunction findRail(accepts: X402PaymentRequirements[], rail: string): RailSelection | null {\n const requirement = accepts.find((r) => railOf(r) === rail);\n return requirement ? { rail, requirement } : null;\n}\n\n/**\n * Choose the rail to pay on. Decision order (design §5.2.5):\n * 1. explicitRail → use it, else UnsupportedRailError\n * 2. preference list → first entry that the server also accepts\n * 3. availability → EVM if ready, else Alipay if ready\n * 4. fallback → server accepts[0]\n */\nexport function selectRail(input: SelectRailInput): RailSelection {\n const { serverAccepts, explicitRail, preference, availability } = input;\n\n if (!serverAccepts || serverAccepts.length === 0) {\n throw new UnsupportedRailError(explicitRail ?? 'unknown', 'Server offered no payment options');\n }\n\n // 1. Explicit caller choice wins.\n if (explicitRail) {\n const hit = findRail(serverAccepts, explicitRail);\n if (!hit) {\n const offered = serverAccepts.map(railOf);\n throw new UnsupportedRailError(\n explicitRail,\n `Server doesn't accept rail '${explicitRail}'. Offered: ${offered.join(', ')}`,\n );\n }\n return hit;\n }\n\n // 2. Client-configured ordered preference ∩ server offer.\n if (preference) {\n for (const pref of preference) {\n const hit = findRail(serverAccepts, pref);\n if (hit) return hit;\n }\n }\n\n // 3. Availability-based.\n if (availability?.evmReady) {\n const evm = serverAccepts.find((r) => railOf(r) !== ALIPAY_RAIL);\n if (evm) return { rail: railOf(evm), requirement: evm };\n }\n if (availability?.alipayReady) {\n const hit = findRail(serverAccepts, ALIPAY_RAIL);\n if (hit) return hit;\n }\n\n // 4. Fallback to the server's first offer.\n return { rail: railOf(serverAccepts[0]), requirement: serverAccepts[0] };\n}\n","/**\n * MoltsPay Client Types\n */\n\n// Client configuration (stored in ~/.moltspay/)\nexport interface ClientConfig {\n chain: string;\n limits: {\n maxPerTx: number;\n maxPerDay: number;\n };\n /**\n * Ordered rail preference (2.0.0). When the server's 402 offers more than\n * one rail (e.g. USDC on Base AND CNY via Alipay) and the caller didn't\n * pass an explicit `rail`, the first entry here that the server also\n * accepts wins. e.g. `[\"base\", \"alipay\"]`.\n */\n railPreference?: string[];\n}\n\n// Wallet data (stored in ~/.moltspay/wallet.json)\nexport interface WalletData {\n address: string;\n privateKey: string;\n createdAt: number;\n}\n\n// Payment response from server\nexport interface PaymentRequired {\n message: string;\n payment: {\n chargeId: string;\n service: string;\n amount: number;\n currency: string;\n wallet: string;\n chain: string;\n expiresAt: number;\n };\n}\n\n// Service info from server\nexport interface ServiceInfo {\n id: string;\n name: string;\n description?: string;\n price: number;\n currency: string;\n input: Record<string, any>;\n output: Record<string, any>;\n available: boolean;\n provider?: ProviderInfo; // For marketplace listings\n endpoint?: string; // Custom endpoint path (e.g., for Cloudflare Workers)\n}\n\n// Provider info from server\nexport interface ProviderInfo {\n name: string;\n username?: string;\n description?: string;\n wallet: string;\n chain?: string;\n chains?: string[] | { chain: string }[]; // Multi-chain support\n}\n\n// Services response from server\nexport interface ServicesResponse {\n provider?: ProviderInfo; // Optional for marketplace listings\n services: ServiceInfo[];\n}\n\n// Verify response from server\nexport interface VerifyResponse {\n status: string;\n chargeId: string;\n txHash: string;\n result: Record<string, any>;\n}\n\n// Client options\nexport interface MoltsPayClientOptions {\n configDir?: string; // Default: ~/.moltspay\n /** Ordered rail preference; see {@link ClientConfig.railPreference}. */\n railPreference?: string[];\n /** Stable Alipay session id (else AIPAY_SESSION_ID, else a fresh UUID). */\n alipaySessionId?: string;\n}\n","/**\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 FacilitatorConfig,\n X402PaymentPayload,\n X402PaymentRequirements,\n SettleResult,\n AlipayFacilitator,\n AlipayFacilitatorConfig,\n ALIPAY_NETWORK,\n ALIPAY_SCHEME,\n} from '../facilitators/index.js';\nimport { toPem } from '../facilitators/alipay/encoding.js';\nimport { isAlipayChainId } from '../chains/index.js';\nimport {\n ServicesManifest,\n ServiceConfig,\n SkillFunction,\n RegisteredSkill,\n MoltsPayServerOptions,\n CorsOptions,\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// Alipay AI 收 fiat rail constants (2.0.0)\n// Legacy `Payment-Needed` 402 challenge header, mirror of `X-Payment-Required`,\n// kept so `alipay-bot` (@alipay/agent-payment) skills work unchanged.\nconst ALIPAY_PAYMENT_NEEDED_HEADER = 'payment-needed';\n// Buyer's proof header: alipay-bot re-requests the resource carrying the\n// Base64URL `{protocol:{payment_proof,trade_no},method:{client_session}}`\n// blob here after the buyer pays. The server verifies it via the facilitator.\nconst ALIPAY_PAYMENT_PROOF_HEADER = 'payment-proof';\n\n/**\n * Make an arbitrary string safe to embed in an HTTP header value.\n *\n * HTTP header values are limited to Latin-1 (RFC 7230 §3.2.6); Node's\n * `res.writeHead` throws `Invalid character in header content` on any\n * code point outside that range. Provider/service names can contain\n * non-Latin-1 characters (e.g. CJK), so we percent-encode anything\n * outside printable ASCII and escape `\"` so it cannot terminate the\n * surrounding `Payment ... realm=\"…\"` quoted-string.\n */\nfunction headerSafe(value: string): string {\n return String(value ?? '')\n .replace(/[^\\x20-\\x7E]/g, ch => encodeURIComponent(ch))\n .replace(/\"/g, '%22');\n}\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 // BNB Smart Chain mainnet\n 'eip155:56': {\n USDC: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n USDT: '0x55d398326f99059fF775485246999027B3197955',\n },\n // BNB Smart Chain testnet\n 'eip155:97': {\n USDC: '0x64544969ed7EBf5f083679233325356EbE738930',\n USDT: '0x337610d27c682E347C9cD60BD4b3b107C9d34dDd',\n },\n // Solana networks use mint addresses (SPL tokens)\n 'solana:mainnet': {\n USDC: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // Circle USDC\n },\n 'solana:devnet': {\n USDC: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU', // Devnet USDC\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 'bnb': 'eip155:56',\n 'bnb_testnet': 'eip155:97',\n 'solana': 'solana:mainnet',\n 'solana_devnet': 'solana:devnet',\n};\n\n// Helper to check if a network is Solana\nfunction isSolanaNetwork(network: string): boolean {\n return network.startsWith('solana:');\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 // Domain names verified against on-chain DOMAIN_SEPARATOR values on 2026-04-21.\n // See docs/TEMPO-WEB-SUPPORT.md Section 2 and test/server/tempo-domain.test.ts.\n // All 4 Tempo TIP-20 tokens (pathUSD / AlphaUSD / BetaUSD / ThetaUSD) use\n // the token symbol with first letter capitalized + version \"1\".\n 'eip155:42431': {\n USDC: { name: 'PathUSD', version: '1' },\n USDT: { name: 'AlphaUSD', version: '1' },\n },\n // BNB Smart Chain mainnet\n 'eip155:56': {\n USDC: { name: 'USD Coin', version: '1' },\n USDT: { name: 'Tether USD', version: '1' },\n },\n // BNB Smart Chain testnet\n 'eip155:97': {\n USDC: { name: 'USD Coin', version: '1' },\n USDT: { name: 'Tether USD', 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 /** Alipay AI 收 facilitator instance, set when `provider.alipay` is configured (2.0.0). */\n private alipayFacilitator: AlipayFacilitator | null = null;\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', 'bnb', and 'solana' in fallback for multi-chain support\n const defaultFallback = ['tempo', 'bnb', 'solana'];\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\n // ── Alipay AI 收 fiat rail (2.0.0): opt-in via provider.alipay ──\n // When configured, resolve the PEM key files (the manifest stores PATHS,\n // the facilitator wants PEM STRINGS) and register the facilitator in the\n // selection so registry.verify/settle route `network: \"alipay\"` to it.\n // Key-load failure is fatal: a misconfigured alipay rail must not start\n // silently and then 500 on the first payment.\n const providerAlipay = this.manifest.provider.alipay;\n if (providerAlipay) {\n try {\n const baseDir = path.dirname(servicesPath);\n // Alipay hands out keys as bare Base64 (no PEM armor); toPem normalizes\n // both that and already-armored PEM into the PEM the facilitator needs.\n const resolvePem = (p: string, kind: 'PRIVATE' | 'PUBLIC') =>\n toPem(readFileSync(path.isAbsolute(p) ? p : path.resolve(baseDir, p), 'utf-8'), kind);\n const alipayFacilitatorConfig: AlipayFacilitatorConfig = {\n seller_id: providerAlipay.seller_id,\n app_id: providerAlipay.app_id,\n seller_name: providerAlipay.seller_name,\n service_id_default: providerAlipay.service_id_default,\n private_key_pem: resolvePem(providerAlipay.private_key_path, 'PRIVATE'),\n alipay_public_key_pem: resolvePem(providerAlipay.alipay_public_key_path, 'PUBLIC'),\n gateway_url: providerAlipay.gateway_url,\n sign_type: providerAlipay.sign_type,\n };\n facilitatorConfig.config = {\n ...facilitatorConfig.config,\n alipay: alipayFacilitatorConfig as unknown as FacilitatorConfig,\n };\n facilitatorConfig.fallback = facilitatorConfig.fallback || [];\n if (facilitatorConfig.primary !== 'alipay' && !facilitatorConfig.fallback.includes('alipay')) {\n facilitatorConfig.fallback.push('alipay');\n }\n } catch (err: any) {\n throw new Error(`[MoltsPay] Alipay rail configured but key load failed: ${err.message}`);\n }\n }\n\n this.registry = new FacilitatorRegistry(facilitatorConfig);\n\n if (providerAlipay) {\n this.alipayFacilitator = this.registry.get('alipay') as AlipayFacilitator;\n console.log(`[MoltsPay] Alipay AI 收 rail enabled (seller ${providerAlipay.seller_id})`);\n }\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 // Helper to get the right wallet for a chain\n const getWalletForChain = (chainName: string, explicitWallet?: string): string => {\n // If explicit wallet provided (object format), use it\n if (explicitWallet) return explicitWallet;\n // For Solana chains, use solana_wallet if available\n if ((chainName === 'solana' || chainName === 'solana_devnet') && provider.solana_wallet) {\n return provider.solana_wallet;\n }\n // Default to EVM wallet\n return provider.wallet;\n };\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 const explicitWallet = typeof c === 'object' ? c.wallet : null;\n return {\n network: CHAIN_TO_NETWORK[chainName] || 'eip155:8453',\n wallet: getWalletForChain(chainName, explicitWallet || undefined),\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: getWalletForChain(chain),\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 * Apply CORS response headers according to the `cors` option.\n *\n * Default (`cors` unset or `true`): `Access-Control-Allow-Origin: *`. Matches 1.5.x behavior\n * and works for every browser client whose origin does not need to send cookies.\n *\n * `cors: false`: emit no CORS headers. Same-origin only.\n * `cors: string[]`: origin allowlist — echo the origin back iff it matches.\n * `cors: CorsOptions`: full control (allowlist + credentials + maxAge).\n *\n * The required-for-Web response headers are always exposed when CORS is active:\n * `X-Payment-Required, X-Payment-Response, WWW-Authenticate, Payment-Receipt`.\n */\n private applyCorsHeaders(req: IncomingMessage, res: ServerResponse): void {\n const cors = (this.options as MoltsPayServerOptions).cors;\n\n // Explicitly disabled: no CORS headers at all (strict same-origin).\n if (cors === false) {\n return;\n }\n\n const requestOrigin = (req.headers.origin as string | undefined) ?? '*';\n\n // Default / explicit `true`: open to any origin (legacy 1.5.x behavior).\n if (cors === undefined || cors === true) {\n this.writeCorsHeaders(res, '*');\n return;\n }\n\n // Array shortcut: origins allowlist, no credentials, default maxAge.\n if (Array.isArray(cors)) {\n if (cors.includes(requestOrigin)) {\n this.writeCorsHeaders(res, requestOrigin);\n res.setHeader('Vary', 'Origin');\n }\n // Origin not on the allowlist → no CORS headers; browser will block.\n return;\n }\n\n // Full CorsOptions object.\n const opt = cors as CorsOptions;\n const isAllowed =\n typeof opt.origins === 'function'\n ? opt.origins(requestOrigin)\n : opt.origins.includes(requestOrigin);\n if (!isAllowed) {\n return;\n }\n this.writeCorsHeaders(res, requestOrigin);\n res.setHeader('Vary', 'Origin');\n if (opt.credentials) {\n res.setHeader('Access-Control-Allow-Credentials', 'true');\n }\n const maxAge = opt.maxAge ?? 600;\n res.setHeader('Access-Control-Max-Age', String(maxAge));\n }\n\n private writeCorsHeaders(res: ServerResponse, origin: string): void {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Payment, Authorization, Payment-Proof');\n res.setHeader(\n 'Access-Control-Expose-Headers',\n 'X-Payment-Required, X-Payment-Response, WWW-Authenticate, Payment-Receipt, Payment-Needed'\n );\n }\n\n /**\n * Handle incoming request\n */\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // CORS — honors the `cors` option (default true = allow any origin, matches 1.5.x).\n this.applyCorsHeaders(req, res);\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 const proofHeader = req.headers[ALIPAY_PAYMENT_PROOF_HEADER] as string | undefined;\n return await this.handleExecute(body, paymentHeader, res, proofHeader);\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 const authHeader = req.headers[MPP_AUTH_HEADER] as string | undefined;\n return await this.handleProxy(body, paymentHeader, authHeader, 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 const proofHeader = req.headers[ALIPAY_PAYMENT_PROOF_HEADER] as string | undefined;\n return await this.handleMPPRequest(skill, body, authHeader, x402Header, res, proofHeader);\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 solana_wallet: this.manifest.provider.solana_wallet,\n chains: this.manifest.provider.chains,\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 proofHeader?: string\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 // Alipay fiat rail (2.0.0): a `Payment-Proof` header means the buyer paid\n // via alipay-bot and is re-requesting the resource with proof. Route to\n // the facilitator verify→fulfill path (the proof's Base64URL blob carries\n // payment_proof / trade_no / client_session).\n if (proofHeader) {\n const alipayPayment: X402PaymentPayload = {\n x402Version: X402_VERSION,\n scheme: ALIPAY_SCHEME,\n network: ALIPAY_NETWORK,\n payload: proofHeader,\n };\n return this.handleAlipayExecute(skill, params || {}, alipayPayment, res);\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 // Alipay fiat rail (2.0.0): route by scheme/network BEFORE the EVM path.\n // validatePayment() only accepts 'exact'/'permit' schemes + EVM/SVM\n // networks, so an alipay payment must branch off here or it'd be rejected.\n const payScheme = payment.accepted?.scheme || payment.scheme;\n const payNetwork = payment.accepted?.network || payment.network;\n if (payScheme === ALIPAY_SCHEME || (payNetwork ? isAlipayChainId(payNetwork) : false)) {\n return this.handleAlipayExecute(skill, params || {}, payment, res);\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 // For Solana: settle FIRST (blockhash expires quickly ~60s)\n // For EVM: pay-for-success (execute first, settle after)\n const isSolana = isSolanaNetwork(paymentNetwork);\n let settlement: any = null;\n\n if (isSolana) {\n console.log(`[MoltsPay] Solana detected - settling payment FIRST (blockhash expiry protection)`);\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] Solana settlement failed:', err.message);\n return this.sendJson(res, 402, {\n error: 'Payment settlement failed',\n message: err.message,\n });\n }\n }\n\n // Execute skill (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 // For Solana: payment already settled, skill failed - no refund (user accepted risk)\n // For EVM: payment not settled yet, user keeps their money\n return this.sendJson(res, 500, {\n error: 'Service execution failed',\n message: err.message,\n paymentSettled: isSolana ? true : false,\n note: isSolana ? 'Payment was settled before execution. Contact support for refund.' : undefined,\n });\n }\n\n // For EVM: settle payment now (pay-for-success)\n if (!isSolana) {\n console.log(`[MoltsPay] Skill succeeded, settling payment...`);\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 settlement = { success: false, error: err.message, facilitator: 'none' };\n }\n\n // Match Solana semantics: settle failure → 402, do NOT claim payment\n // succeeded. Skill was already executed; provider absorbs the cost.\n if (!settlement?.success) {\n return this.sendJson(res, 402, {\n error: 'Payment settlement failed',\n message: settlement?.error || 'Settlement returned no success state',\n facilitator: settlement?.facilitator,\n });\n }\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 * Execute a service paid via the Alipay AI 收 fiat rail (2.0.0).\n *\n * Differs from the EVM/SVM path: no token detection, no EIP-3009/permit\n * validation. Verify hits the Alipay Open API (`payment.verify`). Settlement\n * (`fulfillment.confirm`) is FIRE-AND-FORGET per ALIPAY-INTEGRATION-DESIGN\n * §5.1: a confirm failure is logged but does NOT fail the already-delivered\n * response (the buyer's payment proof was already verified).\n */\n private async handleAlipayExecute(\n skill: RegisteredSkill,\n params: Record<string, any>,\n payment: X402PaymentPayload,\n res: ServerResponse\n ): Promise<void> {\n if (!this.alipayFacilitator) {\n return this.sendJson(res, 402, { error: 'Alipay rail not configured on this server' });\n }\n\n // Verify/settle ignore `requirements` (the proof carries everything), but\n // requirements.network drives registry routing to the alipay facilitator.\n const requirements: X402PaymentRequirements = {\n scheme: ALIPAY_SCHEME,\n network: ALIPAY_NETWORK,\n asset: 'CNY',\n amount: skill.config.alipay?.price_cny || '0',\n payTo: this.manifest.provider.alipay?.seller_id || '',\n maxTimeoutSeconds: 1800,\n };\n\n console.log(`[MoltsPay] Verifying Alipay payment...`);\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] Alipay payment verified by ${verifyResult.facilitator}`);\n\n // Execute skill (same timeout contract as the EVM path).\n const timeoutSeconds = parseInt(process.env.SKILL_TIMEOUT_SECONDS || '1200');\n console.log(`[MoltsPay] Executing skill: ${skill.id} (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 // Fulfillment confirm — fire-and-forget: log failures, never roll back.\n let settlement: (SettleResult & { facilitator: string });\n try {\n settlement = await this.registry.settle(payment, requirements);\n if (settlement.success) {\n console.log(`[MoltsPay] Alipay fulfillment confirmed: ${settlement.transaction}`);\n } else {\n console.error(`[MoltsPay] Alipay fulfillment confirm failed (non-fatal): ${settlement.error}`);\n }\n } catch (err: any) {\n console.error(`[MoltsPay] Alipay fulfillment confirm threw (non-fatal): ${err.message}`);\n settlement = { success: false, error: err.message, facilitator: 'alipay' };\n }\n\n const responseHeaders: Record<string, string> = {};\n if (settlement.success) {\n responseHeaders[PAYMENT_RESPONSE_HEADER] = Buffer.from(JSON.stringify({\n success: true,\n transaction: settlement.transaction,\n network: ALIPAY_NETWORK,\n facilitator: settlement.facilitator,\n })).toString('base64');\n }\n\n this.sendJson(res, 200, {\n success: true,\n result,\n payment: settlement.success\n ? { transaction: settlement.transaction, status: 'fulfilled', facilitator: settlement.facilitator }\n : { status: 'delivered_unconfirmed', error: settlement.error },\n }, responseHeaders);\n }\n\n /**\n * Build the Alipay 402 challenge for a service, or null when the alipay rail\n * isn't configured for this server or this service. Returns the x402\n * `accepts[]` entry plus the Base64URL `Payment-Needed` header value so the\n * 402 responders can dual-emit both the x402 and legacy alipay-bot formats.\n */\n private async buildAlipayChallenge(\n config: ServiceConfig\n ): Promise<{ accepts: X402PaymentRequirements; paymentNeededHeader: string } | null> {\n if (!this.alipayFacilitator || !config.alipay) return null;\n try {\n const req = await this.alipayFacilitator.createPaymentRequirements({\n serviceId: config.alipay.service_id || this.manifest.provider.alipay!.service_id_default,\n priceCny: config.alipay.price_cny,\n goodsName: config.alipay.goods_name,\n resourceId: `/execute?service=${config.id}`,\n });\n return { accepts: req.x402Accepts, paymentNeededHeader: req.paymentNeededHeader };\n } catch (err: any) {\n console.error(`[MoltsPay] Alipay challenge build failed for ${config.id}: ${err.message}`);\n return null;\n }\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 proofHeader?: string\n ): Promise<void> {\n const config = skill.config;\n const params = body || {};\n\n // Alipay buyer re-request with a Payment-Proof header → verify + fulfill.\n if (proofHeader) {\n return await this.handleExecute({ service: config.id, params }, undefined, res, proofHeader);\n }\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 async sendMPPPaymentRequired(config: ServiceConfig, res: ServerResponse): Promise<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 // Alipay fiat rail (2.0.0): append the alipay x402 entry when configured.\n const alipayChallenge = await this.buildAlipayChallenge(config);\n if (alipayChallenge) {\n accepts.push(alipayChallenge.accepts);\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=\"${headerSafe(this.manifest.provider.name)}\", method=\"tempo\", intent=\"charge\", request=\"${mppRequestEncoded}\", description=\"${headerSafe(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 // Dual-emit the legacy `Payment-Needed` header for alipay-bot clients.\n if (alipayChallenge) {\n headers[ALIPAY_PAYMENT_NEEDED_HEADER] = alipayChallenge.paymentNeededHeader;\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 async sendPaymentRequired(config: ServiceConfig, res: ServerResponse): Promise<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 // Alipay fiat rail (2.0.0): append the alipay x402 entry when configured.\n const alipayChallenge = await this.buildAlipayChallenge(config);\n if (alipayChallenge) {\n accepts.push(alipayChallenge.accepts);\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 const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n [PAYMENT_REQUIRED_HEADER]: encoded,\n };\n // Dual-emit the legacy `Payment-Needed` header for alipay-bot clients\n // (@alipay/agent-payment), which only read this header and ignore the\n // x402 `accepts[]`. Mirrors sendMPPPaymentRequired so /execute is\n // byte-for-byte compatible with un-upgraded skills.\n if (alipayChallenge) {\n headers[ALIPAY_PAYMENT_NEEDED_HEADER] = alipayChallenge.paymentNeededHeader;\n }\n\n res.writeHead(402, headers);\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 // Both schemes are supported: EIP-3009 `exact` (Base/Polygon/BNB/Solana) and\n // EIP-2612 `permit` (Tempo Moderato, added in 1.6.0). Facilitator routes\n // permit payloads to TempoFacilitator automatically.\n if (scheme !== 'exact' && scheme !== 'permit') {\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 // Tempo Moderato uses EIP-2612 permit (pathUSD / AlphaUSD don't implement EIP-3009).\n // Every other network uses the standard x402 \"exact\" (EIP-3009) scheme.\n const isTempo = selectedNetwork === 'eip155:42431';\n const scheme = isTempo ? 'permit' : 'exact';\n\n const requirements: X402PaymentRequirements = {\n scheme,\n network: selectedNetwork,\n asset: tokenAddress,\n amount: amountInUnits,\n payTo: selectedWallet,\n maxTimeoutSeconds: 300,\n extra: tokenDomain,\n };\n \n // For Solana: include fee payer pubkey if available (gasless mode)\n if (selectedNetwork === 'solana:mainnet' || selectedNetwork === 'solana:devnet') {\n const solanaFacilitator = this.registry.get('solana') as any;\n const feePayerPubkey = solanaFacilitator?.getFeePayerPubkey?.();\n if (feePayerPubkey) {\n (requirements.extra as any) = {\n ...(requirements.extra || {}),\n solanaFeePayer: feePayerPubkey,\n };\n }\n }\n \n // For BNB: include spender address for client approval\n if (selectedNetwork === 'eip155:56' || selectedNetwork === 'eip155:97') {\n const bnbFacilitator = this.registry.get('bnb') as any;\n const spenderAddress = bnbFacilitator?.getSpenderAddress?.();\n if (spenderAddress) {\n (requirements.extra as any) = {\n ...(requirements.extra || {}),\n bnbSpender: spenderAddress,\n };\n }\n }\n\n // For Tempo: include the settler EOA so the client can sign Permit(spender=settler).\n // If TEMPO_SETTLER_KEY is not configured, tempoSpender will be absent and Web Client\n // will surface a helpful error rather than sign a permit no one can fulfill.\n if (isTempo) {\n const tempoFacilitator = this.registry.get('tempo') as any;\n const tempoSpender = tempoFacilitator?.getSpenderAddress?.();\n if (tempoSpender) {\n (requirements.extra as any) = {\n ...(requirements.extra || {}),\n tempoSpender,\n };\n }\n }\n\n return requirements;\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, allow all (for testing/open mode)\n if (allowedIPs.length === 0) {\n return true;\n }\n \n // If '*' is in the list, allow all\n if (allowedIPs.includes('*')) {\n return true;\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/MPP 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 * For x402 (base, polygon, base_sepolia):\n * Without X-Payment header: returns 402 with X-Payment-Required\n * With X-Payment header: verifies payment via CDP\n * \n * For MPP (tempo_moderato):\n * Without Authorization header: returns 402 with WWW-Authenticate\n * With Authorization: Payment header: verifies tx on Tempo chain\n */\n private async handleProxy(\n body: any,\n paymentHeader: string | undefined,\n authHeader: 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 chain if provided\n const supportedChains = ['base', 'polygon', 'base_sepolia', 'tempo_moderato', 'bnb', 'bnb_testnet', 'solana', 'solana_devnet'];\n if (chain && !supportedChains.includes(chain)) {\n return this.sendJson(res, 400, { error: `Unsupported chain: ${chain}. Supported: ${supportedChains.join(', ')}` });\n }\n\n // Validate wallet format based on chain\n const isSolanaChain = chain === 'solana' || chain === 'solana_devnet';\n const isValidEvmAddress = /^0x[a-fA-F0-9]{40}$/.test(wallet);\n const isValidSolanaAddress = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(wallet);\n \n if (isSolanaChain && !isValidSolanaAddress) {\n return this.sendJson(res, 400, { error: 'Invalid Solana wallet address format' });\n }\n if (!isSolanaChain && !isValidEvmAddress) {\n return this.sendJson(res, 400, { error: 'Invalid EVM 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 // 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 // ========== MPP Protocol for tempo_moderato ==========\n if (chain === 'tempo_moderato') {\n return await this.handleProxyMPP(body, proxyConfig, authHeader, res);\n }\n\n // ========== x402 Protocol for other chains ==========\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' && scheme !== 'permit') {\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, handle skill + payment\n if (execute && 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 // For Solana: settle FIRST (blockhash expires quickly ~60s)\n // For EVM: pay-for-success (execute first, settle after)\n const isSolana = isSolanaNetwork(network);\n let settlement: any = null;\n\n if (isSolana) {\n console.log(`[MoltsPay] /proxy: Solana detected - settling payment FIRST`);\n try {\n settlement = await this.registry.settle(payment, requirements);\n console.log(`[MoltsPay] /proxy: Payment settled by ${settlement.facilitator}: ${settlement.transaction || 'pending'}`);\n \n // Check if settlement actually succeeded (registry returns {success: false} on failure)\n if (!settlement.success) {\n console.error(`[MoltsPay] /proxy: Solana settlement failed: ${settlement.error}`);\n return this.sendJson(res, 402, {\n success: false,\n paymentSettled: false,\n error: `Payment settlement failed: ${settlement.error || 'Unknown error'}`,\n });\n }\n } catch (err: any) {\n console.error('[MoltsPay] /proxy: Solana settlement failed:', err.message);\n return this.sendJson(res, 402, {\n success: false,\n paymentSettled: false,\n error: `Payment settlement failed: ${err.message}`,\n });\n }\n } else {\n console.log(`[MoltsPay] /proxy: Executing skill first (pay on success): ${service}`);\n }\n\n // Execute skill (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`);\n } catch (err: any) {\n // Skill failed or timeout\n console.error(`[MoltsPay] /proxy: Skill failed: ${err.message}`);\n // For Solana: payment already settled, skill failed - no refund (user accepted risk)\n // For EVM: payment not settled yet, user keeps their money\n return this.sendJson(res, 500, {\n success: false,\n paymentSettled: isSolana ? true : false,\n error: `Service execution failed: ${err.message}`,\n note: isSolana ? 'Payment was settled before execution. Contact support for refund.' : undefined,\n });\n }\n\n // For EVM: settle payment now (pay-for-success)\n if (!isSolana) {\n console.log(`[MoltsPay] /proxy: Settling payment...`);\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,\n paidTo: wallet,\n amount: amountNum,\n currency: currency || 'USDC',\n memo,\n result,\n });\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,\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 * Handle MPP payment flow for /proxy endpoint (tempo_moderato chain)\n */\n private async handleProxyMPP(\n body: any,\n config: ServiceConfig,\n authHeader: string | undefined,\n res: ServerResponse\n ): Promise<void> {\n const { wallet, amount, memo, serviceId } = body;\n const amountNum = parseFloat(amount);\n const amountInUnits = Math.floor(amountNum * 1e6).toString();\n \n // If no Authorization header, return 402 with WWW-Authenticate\n if (!authHeader || !authHeader.toLowerCase().startsWith('payment ')) {\n const challengeId = this.generateChallengeId();\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: 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 const wwwAuth = `Payment id=\"${challengeId}\", realm=\"MoltsPay Proxy\", method=\"tempo\", intent=\"charge\", request=\"${mppRequestEncoded}\", description=\"${headerSafe(config.name)}\", expires=\"${expiresAt}\"`;\n \n res.writeHead(402, {\n 'Content-Type': 'application/problem+json',\n [MPP_WWW_AUTH_HEADER]: wwwAuth,\n });\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: serviceId || 'proxy',\n price: amountNum,\n currency: 'USDC',\n }, null, 2));\n return;\n }\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: { id: string; realm: string; method: string; intent: string; request: any };\n payload: { hash?: string; type: 'hash' | 'transaction' };\n source?: string;\n };\n \n try {\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] /proxy MPP: Failed to parse credential:', err);\n return this.sendJson(res, 400, { error: 'Invalid payment credential encoding' });\n }\n\n // Extract transaction hash\n let txHash: string | undefined;\n if (mppCredential.payload?.type === 'hash' && mppCredential.payload?.hash) {\n txHash = mppCredential.payload.hash;\n } else {\n return this.sendJson(res, 400, { error: 'Missing transaction hash in credential' });\n }\n\n console.log(`[MoltsPay] /proxy MPP: Verifying tx ${txHash} on Tempo...`);\n\n // Build requirements for verification\n const requirements = this.buildPaymentRequirements(config, 'eip155:42431', wallet, 'USDC');\n\n // Create x402-compatible payload for facilitator\n const paymentPayload: X402PaymentPayload = {\n x402Version: X402_VERSION,\n scheme: 'exact',\n network: 'eip155:42431',\n payload: { txHash, chainId: 42431 },\n };\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] /proxy MPP: Payment verified by ${verification.facilitator}`);\n\n // Check if execution requested\n const { execute, service, params } = body;\n \n if (execute && service) {\n console.log(`[MoltsPay] /proxy MPP: Executing skill: ${service}`);\n const skill = this.skills.get(service);\n if (!skill) {\n return this.sendJson(res, 404, {\n success: false,\n paymentSettled: true, // Payment already happened on Tempo\n error: `Service not found: ${service}`,\n });\n }\n\n // Execute skill\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 } catch (err: any) {\n console.error(`[MoltsPay] /proxy MPP: Skill failed: ${err.message}`);\n return this.sendJson(res, 500, {\n success: false,\n paymentSettled: true,\n error: `Service execution failed: ${err.message}`,\n });\n }\n\n return this.sendJson(res, 200, {\n success: true,\n verified: true,\n txHash,\n chain: 'tempo_moderato',\n paidTo: wallet,\n amount: amountNum,\n currency: 'USDC',\n facilitator: verification.facilitator,\n memo,\n result,\n });\n }\n\n // No execution requested - just return verification success\n this.sendJson(res, 200, {\n success: true,\n verified: true,\n txHash,\n chain: 'tempo_moderato',\n paidTo: wallet,\n amount: amountNum,\n currency: 'USDC',\n facilitator: verification.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 const requirements: X402PaymentRequirements = {\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 // For BNB: include spender address for client approval\n if (networkId === 'eip155:56' || networkId === 'eip155:97') {\n const bnbFacilitator = this.registry.get('bnb') as any;\n const spenderAddress = bnbFacilitator?.getSpenderAddress?.();\n if (spenderAddress) {\n (requirements.extra as any) = {\n ...(requirements.extra || {}),\n bnbSpender: spenderAddress,\n };\n }\n }\n\n return requirements;\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 Module\n * \n * Provides pluggable payment facilitator support for MoltsPay.\n * \n * @example\n * ```typescript\n * import { FacilitatorRegistry, CDPFacilitator } from 'moltspay/facilitators';\n * \n * // Use default CDP facilitator\n * const registry = new FacilitatorRegistry();\n * const result = await registry.verify(paymentPayload, requirements);\n * \n * // Or with custom config\n * const registry = new FacilitatorRegistry({\n * primary: 'cdp',\n * fallback: ['chaoschain'], // Coming in v0.9.0\n * strategy: 'failover',\n * config: {\n * cdp: { useMainnet: true }\n * }\n * });\n * ```\n */\n\n// Interface & types\nexport {\n Facilitator,\n BaseFacilitator,\n FacilitatorConfig,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n FacilitatorFee,\n} from './interface.js';\n\n// CDP Facilitator\nexport {\n CDPFacilitator,\n CDPFacilitatorConfig,\n} from './cdp.js';\n\n// Tempo Facilitator\nexport {\n TempoFacilitator,\n} from './tempo.js';\n\n// BNB Facilitator\nexport {\n BNBFacilitator,\n BNBPaymentIntent,\n createIntentTypedData,\n} from './bnb.js';\n\n// Solana Facilitator\nexport {\n SolanaFacilitator,\n createSolanaPaymentTransaction,\n type SolanaPaymentPayload,\n} from './solana.js';\n\n// Alipay AI 收 Facilitator (2.0.0)\nexport {\n AlipayFacilitator,\n AlipayFacilitatorConfig,\n AlipayPaymentRequirements,\n AlipayPaymentProof,\n CreatePaymentRequirementsOpts,\n ALIPAY_NETWORK,\n ALIPAY_SCHEME,\n ALIPAY_GATEWAY_PROD,\n ALIPAY_GATEWAY_SANDBOX,\n} from './alipay.js';\n\n// Registry\nexport {\n FacilitatorRegistry,\n FacilitatorSelection,\n SelectionStrategy,\n getDefaultRegistry,\n createRegistry,\n} from './registry.js';\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 * 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 { ethers } from 'ethers';\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\n// ===== Payload shapes (discriminated) =====\n\n/** Legacy MPP / tx-hash payload: client already submitted the TIP-20 transfer. */\ninterface TempoTxHashPayload {\n txHash: string;\n chainId: number;\n}\n\n/** EIP-2612 permit payload: server submits permit + transferFrom from the settler wallet. */\ninterface TempoPermitPayload {\n permit: {\n owner: string;\n spender: string;\n value: string;\n nonce: string;\n deadline: string;\n v: number;\n r: string;\n s: string;\n };\n}\n\n// Minimal ABI for permit + transferFrom calls on the TIP-20 precompile.\nconst TIP20_PERMIT_ABI = [\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'function transferFrom(address from, address to, uint256 value) returns (bool)',\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 private settlerWallet: ethers.Wallet | null = null;\n\n constructor() {\n super();\n this.rpcUrl = CHAINS.tempo_moderato.rpc;\n\n // Optional: load settler key from env. If present, the facilitator can settle\n // EIP-2612 permit payments by submitting permit() + transferFrom() on behalf\n // of the user. If absent, only the legacy tx-hash verification path works.\n const settlerKey = process.env.TEMPO_SETTLER_KEY;\n if (settlerKey) {\n try {\n const provider = new ethers.JsonRpcProvider(this.rpcUrl);\n this.settlerWallet = new ethers.Wallet(settlerKey, provider);\n } catch (err) {\n console.warn('[TempoFacilitator] Invalid TEMPO_SETTLER_KEY, permit settlement disabled:', err);\n this.settlerWallet = null;\n }\n }\n }\n\n /**\n * Settler EOA address advertised to clients via `X-Payment-Required.extra.tempoSpender`.\n * Web Client uses this as the `spender` field in the signed EIP-2612 Permit.\n * Returns null if no TEMPO_SETTLER_KEY is configured — permit settlement unavailable.\n */\n getSpenderAddress(): string | null {\n return this.settlerWallet?.address ?? null;\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 // Dispatch on payload shape:\n // { permit: {...} } → new EIP-2612 permit path (Web Client, Phase 3c)\n // { txHash, chainId } → legacy MPP / Node CLI tx-hash verification\n const inner = paymentPayload.payload as Partial<TempoPermitPayload & TempoTxHashPayload>;\n if (inner && 'permit' in inner && inner.permit) {\n return this.verifyPermit(inner as TempoPermitPayload, requirements);\n }\n return this.verifyTxHash(paymentPayload, requirements);\n }\n\n /**\n * Structural validation of an EIP-2612 permit payload. Does NOT submit\n * anything on-chain — actual submission happens in settlePermit().\n */\n private async verifyPermit(\n payload: TempoPermitPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult> {\n if (!this.settlerWallet) {\n return { valid: false, error: 'Permit settlement not configured (TEMPO_SETTLER_KEY missing)' };\n }\n const p = payload.permit;\n if (!p || !p.owner || !p.spender || !p.value || !p.deadline) {\n return { valid: false, error: 'Invalid permit payload: missing fields' };\n }\n // Spender must match our settler — otherwise permit() would set allowance on a\n // different address and transferFrom() from our settler would fail.\n if (p.spender.toLowerCase() !== this.settlerWallet.address.toLowerCase()) {\n return {\n valid: false,\n error: `Permit spender ${p.spender} does not match configured settler ${this.settlerWallet.address}`,\n };\n }\n // Deadline not expired (evaluate at verify-time; settle runs shortly after).\n const deadline = BigInt(p.deadline);\n const now = BigInt(Math.floor(Date.now() / 1000));\n if (deadline <= now) {\n return { valid: false, error: 'Permit deadline has expired' };\n }\n // Amount must match what the requirement asked for.\n if (BigInt(p.value) < BigInt(requirements.amount || '0')) {\n return {\n valid: false,\n error: `Permit value ${p.value} is less than required ${requirements.amount}`,\n };\n }\n return { valid: true, details: { scheme: 'permit', owner: p.owner } };\n }\n\n private async verifyTxHash(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult> {\n try {\n // Extract Tempo-specific payload\n const tempoPayload = paymentPayload.payload as TempoTxHashPayload;\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 // Dispatch on payload shape, same rule as verify().\n const inner = paymentPayload.payload as Partial<TempoPermitPayload & TempoTxHashPayload>;\n if (inner && 'permit' in inner && inner.permit) {\n return this.settlePermit(inner as TempoPermitPayload, requirements);\n }\n\n // Legacy tx-hash path: client already submitted the transfer; we just re-verify.\n const verifyResult = await this.verifyTxHash(paymentPayload, requirements);\n if (!verifyResult.valid) {\n return { success: false, error: verifyResult.error };\n }\n const tempoPayload = paymentPayload.payload as TempoTxHashPayload;\n return {\n success: true,\n transaction: tempoPayload.txHash,\n status: 'settled',\n };\n }\n\n /**\n * EIP-2612 permit settlement path. Submits two transactions on Tempo:\n * 1. pathUSD.permit(owner, spender=settler, value, deadline, v, r, s)\n * 2. pathUSD.transferFrom(owner, payTo, value)\n *\n * The settler EOA pays Tempo gas (via the TIP-20 `feeToken` mechanism — no\n * native tTEMPO required; any held TIP-20 token balance covers fees).\n */\n private async settlePermit(\n payload: TempoPermitPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult> {\n if (!this.settlerWallet) {\n return { success: false, error: 'Permit settlement not configured (TEMPO_SETTLER_KEY missing)' };\n }\n if (!requirements.asset || !requirements.payTo) {\n return { success: false, error: 'Missing asset or payTo in requirements' };\n }\n\n const verifyResult = await this.verifyPermit(payload, requirements);\n if (!verifyResult.valid) {\n return { success: false, error: verifyResult.error };\n }\n\n const token = new ethers.Contract(requirements.asset, TIP20_PERMIT_ABI, this.settlerWallet);\n const p = payload.permit;\n\n try {\n const permitTx = await token.permit(\n p.owner,\n p.spender,\n p.value,\n p.deadline,\n p.v,\n p.r,\n p.s\n );\n await permitTx.wait();\n\n const transferTx = await token.transferFrom(p.owner, requirements.payTo, p.value);\n await transferTx.wait();\n\n return {\n success: true,\n transaction: transferTx.hash,\n status: 'settled',\n };\n } catch (err) {\n return {\n success: false,\n error: `Tempo permit settlement failed: ${(err as Error).message}`,\n };\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 * BNB Chain Facilitator\n * \n * Handles pay-for-success payments on BNB Smart Chain.\n * \n * Flow:\n * 1. Client pre-approves server wallet (one-time, via `moltspay init`)\n * 2. Client signs EIP-712 intent (no gas, just signature)\n * 3. Server verifies intent signature\n * 4. Server executes service\n * 5. Success → Server calls transferFrom (server pays gas)\n * 6. Failure → No transfer, client keeps money\n * \n * Key difference from Tempo:\n * - Tempo: Client pays first → service might fail → money lost\n * - BNB: Service runs first → success = payment (pay-for-success)\n */\n\nimport {\n BaseFacilitator,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n} from './interface.js';\nimport { CHAINS, ChainConfig } from '../chains/index.js';\nimport { privateKeyToAccount } from 'viem/accounts';\n\n// ERC20 Transfer event signature\nconst TRANSFER_EVENT_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';\n\n// EIP-712 Domain\nconst EIP712_DOMAIN = {\n name: 'MoltsPay',\n version: '1',\n};\n\n// EIP-712 Types for Payment Intent\nconst INTENT_TYPES = {\n PaymentIntent: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'amount', type: 'uint256' },\n { name: 'token', type: 'address' },\n { name: 'service', type: 'string' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n};\n\n// ERC20 ABI (minimal)\nconst ERC20_ABI = {\n transfer: 'function transfer(address to, uint256 amount) returns (bool)',\n transferFrom: 'function transferFrom(address from, address to, uint256 amount) returns (bool)',\n allowance: 'function allowance(address owner, address spender) view returns (uint256)',\n balanceOf: 'function balanceOf(address account) view returns (uint256)',\n approve: 'function approve(address spender, uint256 amount) returns (bool)',\n};\n\n/**\n * BNB Payment Intent (signed by client)\n */\nexport interface BNBPaymentIntent {\n from: string;\n to: string;\n amount: string;\n token: string;\n service: string;\n nonce: number;\n deadline: number;\n signature: string;\n}\n\n/**\n * BNB Payment Payload (from client in x402 request)\n */\ninterface BNBPaymentPayload {\n intent: BNBPaymentIntent;\n chainId: number;\n}\n\n/**\n * BNB Chain Facilitator\n * \n * Handles pay-for-success payments on BNB mainnet (chainId 56) and testnet (chainId 97).\n * Server wallet executes transferFrom after successful service delivery.\n */\nexport class BNBFacilitator extends BaseFacilitator {\n readonly name = 'bnb';\n readonly displayName = 'BNB Smart Chain';\n readonly supportedNetworks = ['eip155:56', 'eip155:97']; // Mainnet + Testnet\n\n private serverPrivateKey: string;\n private spenderAddress: string | null = null;\n private chainConfigs: { [key: number]: { rpc: string; chain: ChainConfig } };\n\n constructor(serverPrivateKey?: string) {\n super();\n this.serverPrivateKey = serverPrivateKey || process.env.BNB_SERVER_PRIVATE_KEY || '';\n \n // Pre-compute spender address synchronously using viem\n if (this.serverPrivateKey) {\n const key = this.serverPrivateKey.startsWith('0x') \n ? this.serverPrivateKey as `0x${string}`\n : `0x${this.serverPrivateKey}` as `0x${string}`;\n const account = privateKeyToAccount(key);\n this.spenderAddress = account.address;\n }\n \n this.chainConfigs = {\n 56: { rpc: CHAINS.bnb.rpc, chain: CHAINS.bnb },\n 97: { rpc: CHAINS.bnb_testnet.rpc, chain: CHAINS.bnb_testnet },\n };\n }\n\n async healthCheck(): Promise<HealthCheckResult> {\n const start = Date.now();\n try {\n // Check mainnet\n const response = await fetch(this.chainConfigs[56].rpc, {\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 !== 56) {\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 /**\n * Verify a payment intent signature (before service execution)\n * \n * This verifies:\n * 1. Signature is valid for the intent\n * 2. Client has approved server wallet\n * 3. Client has sufficient balance\n * 4. Intent hasn't expired\n */\n async verify(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<VerifyResult> {\n try {\n const bnbPayload = paymentPayload.payload as BNBPaymentPayload;\n \n if (!bnbPayload?.intent) {\n return { valid: false, error: 'Missing intent in payment payload' };\n }\n\n const { intent, chainId } = bnbPayload;\n const config = this.chainConfigs[chainId];\n \n if (!config) {\n return { valid: false, error: `Unsupported chainId: ${chainId}` };\n }\n\n // Check deadline\n if (intent.deadline < Date.now()) {\n return { valid: false, error: 'Intent expired' };\n }\n\n // Verify signature\n const recoveredAddress = await this.recoverIntentSigner(intent, chainId);\n if (recoveredAddress.toLowerCase() !== intent.from.toLowerCase()) {\n return { valid: false, error: 'Invalid signature' };\n }\n\n // Verify recipient matches\n if (intent.to.toLowerCase() !== requirements.payTo.toLowerCase()) {\n return { valid: false, error: `Wrong recipient: ${intent.to}` };\n }\n\n // Verify amount matches\n if (BigInt(intent.amount) < BigInt(requirements.amount)) {\n return { valid: false, error: `Insufficient amount: ${intent.amount}` };\n }\n\n // Verify token matches\n if (intent.token.toLowerCase() !== requirements.asset.toLowerCase()) {\n return { valid: false, error: `Wrong token: ${intent.token}` };\n }\n\n // Check allowance\n const serverAddress = await this.getServerAddress();\n const allowance = await this.getAllowance(intent.from, serverAddress, intent.token, config.rpc);\n \n if (BigInt(allowance) < BigInt(intent.amount)) {\n return { valid: false, error: 'Insufficient allowance. Run: npx moltspay init --chain bnb' };\n }\n\n // Check balance\n const balance = await this.getBalance(intent.from, intent.token, config.rpc);\n if (BigInt(balance) < BigInt(intent.amount)) {\n return { valid: false, error: 'Insufficient balance' };\n }\n\n return { \n valid: true, \n details: {\n from: intent.from,\n to: intent.to,\n amount: intent.amount,\n token: intent.token,\n service: intent.service,\n nonce: intent.nonce,\n deadline: intent.deadline,\n }\n };\n } catch (error) {\n return { valid: false, error: `Verification failed: ${error}` };\n }\n }\n\n /**\n * Settle a payment by executing transferFrom\n * \n * This is called AFTER the service has been successfully delivered.\n * Server pays gas, transfers tokens from client to provider.\n */\n async settle(\n paymentPayload: X402PaymentPayload,\n requirements: X402PaymentRequirements\n ): Promise<SettleResult> {\n if (!this.serverPrivateKey) {\n return { success: false, error: 'Server wallet not configured (BNB_SERVER_PRIVATE_KEY)' };\n }\n\n try {\n // First verify the intent\n const verifyResult = await this.verify(paymentPayload, requirements);\n if (!verifyResult.valid) {\n return { success: false, error: verifyResult.error };\n }\n\n const bnbPayload = paymentPayload.payload as BNBPaymentPayload;\n const { intent, chainId } = bnbPayload;\n const config = this.chainConfigs[chainId];\n\n // Execute transferFrom\n const txHash = await this.executeTransferFrom(\n intent.from,\n intent.to,\n intent.amount,\n intent.token,\n config.rpc\n );\n\n return { \n success: true, \n transaction: txHash,\n status: 'settled'\n };\n } catch (error) {\n return { success: false, error: `Settlement failed: ${error}` };\n }\n }\n\n /**\n * Check if client has approved the server wallet\n */\n async checkApproval(\n clientAddress: string, \n token: string, \n chainId: number\n ): Promise<{ approved: boolean; allowance: string }> {\n const config = this.chainConfigs[chainId];\n if (!config) {\n throw new Error(`Unsupported chainId: ${chainId}`);\n }\n\n const serverAddress = await this.getServerAddress();\n const allowance = await this.getAllowance(clientAddress, serverAddress, token, config.rpc);\n \n // Consider approved if allowance > 1000 USDC (with 18 decimals)\n const minAllowance = BigInt('1000000000000000000000'); // 1000 tokens\n \n return {\n approved: BigInt(allowance) >= minAllowance,\n allowance,\n };\n }\n\n /**\n * Verify a completed transaction (for checking past payments)\n */\n async verifyTransaction(\n txHash: string, \n expected: { to: string; amount: string; token: string },\n chainId: number\n ): Promise<VerifyResult> {\n const config = this.chainConfigs[chainId];\n if (!config) {\n return { valid: false, error: `Unsupported chainId: ${chainId}` };\n }\n\n try {\n const receipt = await this.getTransactionReceipt(txHash, config.rpc);\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 log.address.toLowerCase() === expected.token.toLowerCase()\n );\n\n if (!transferLog) {\n return { valid: false, error: 'No Transfer event found' };\n }\n\n // Verify recipient\n const toAddress = '0x' + transferLog.topics[2].slice(26).toLowerCase();\n if (toAddress !== expected.to.toLowerCase()) {\n return { valid: false, error: `Wrong recipient: ${toAddress}` };\n }\n\n // Verify amount\n const amount = BigInt(transferLog.data);\n if (amount < BigInt(expected.amount)) {\n return { valid: false, error: `Insufficient amount: ${amount}` };\n }\n\n return { \n valid: true, \n details: {\n txHash,\n from: '0x' + transferLog.topics[1].slice(26),\n to: toAddress,\n amount: amount.toString(),\n token: transferLog.address,\n }\n };\n } catch (error) {\n return { valid: false, error: `Verification failed: ${error}` };\n }\n }\n\n // ==================== Private Methods ====================\n\n /**\n * Get the server's spender address (public, for 402 responses)\n * Returns cached value computed at construction time.\n */\n getSpenderAddress(): string | null {\n return this.spenderAddress;\n }\n\n private async getServerAddress(): Promise<string> {\n // Derive address from private key using ethers\n const { ethers } = await import('ethers');\n const wallet = new ethers.Wallet(this.serverPrivateKey);\n return wallet.address;\n }\n\n private async recoverIntentSigner(intent: BNBPaymentIntent, chainId: number): Promise<string> {\n // Use ethers for EIP-712 signature recovery\n const { ethers } = await import('ethers');\n \n const domain = {\n ...EIP712_DOMAIN,\n chainId,\n };\n\n const message = {\n from: intent.from,\n to: intent.to,\n amount: intent.amount,\n token: intent.token,\n service: intent.service,\n nonce: intent.nonce,\n deadline: intent.deadline,\n };\n\n const recoveredAddress = ethers.verifyTypedData(\n domain,\n INTENT_TYPES,\n message,\n intent.signature\n );\n\n return recoveredAddress;\n }\n\n private async getAllowance(owner: string, spender: string, token: string, rpcUrl: string): Promise<string> {\n // allowance(address,address) selector + params\n const selector = '0xdd62ed3e';\n const ownerPadded = owner.toLowerCase().replace('0x', '').padStart(64, '0');\n const spenderPadded = spender.toLowerCase().replace('0x', '').padStart(64, '0');\n const data = selector + ownerPadded + spenderPadded;\n\n const response = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_call',\n params: [{ to: token, data }, 'latest'],\n id: 1,\n }),\n });\n\n const result = await response.json() as { result: string };\n return result.result || '0x0';\n }\n\n private async getBalance(account: string, token: string, rpcUrl: string): Promise<string> {\n // balanceOf(address) selector + param\n const selector = '0x70a08231';\n const accountPadded = account.toLowerCase().replace('0x', '').padStart(64, '0');\n const data = selector + accountPadded;\n\n const response = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n method: 'eth_call',\n params: [{ to: token, data }, 'latest'],\n id: 1,\n }),\n });\n\n const result = await response.json() as { result: string };\n return result.result || '0x0';\n }\n\n private async executeTransferFrom(\n from: string,\n to: string,\n amount: string,\n token: string,\n rpcUrl: string\n ): Promise<string> {\n const { ethers } = await import('ethers');\n \n const provider = new ethers.JsonRpcProvider(rpcUrl);\n const wallet = new ethers.Wallet(this.serverPrivateKey, provider);\n \n const tokenContract = new ethers.Contract(token, [\n 'function transferFrom(address from, address to, uint256 amount) returns (bool)',\n ], wallet);\n\n const tx = await tokenContract.transferFrom(from, to, amount);\n const receipt = await tx.wait();\n \n return receipt.hash;\n }\n\n private async getTransactionReceipt(txHash: string, rpcUrl: string): Promise<any> {\n const response = await fetch(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/**\n * Create EIP-712 typed data for signing a payment intent\n * \n * Used by clients to sign their payment intent.\n */\nexport function createIntentTypedData(\n intent: Omit<BNBPaymentIntent, 'signature'>,\n chainId: number\n) {\n return {\n domain: {\n ...EIP712_DOMAIN,\n chainId,\n },\n types: INTENT_TYPES,\n primaryType: 'PaymentIntent' as const,\n message: {\n from: intent.from,\n to: intent.to,\n amount: intent.amount,\n token: intent.token,\n service: intent.service,\n nonce: intent.nonce,\n deadline: intent.deadline,\n },\n };\n}\n","/**\n * Alipay AI 收 Facilitator (2.0.0)\n *\n * Implements the `Facilitator` interface for Alipay's 智能收 (AI Pay) 402\n * protocol. Adds a fiat rail (CNY) alongside the existing USDC/EVM/SVM\n * rails. Server-side only; clients shell out to the `alipay-bot` CLI\n * (see `AlipayClient` under `src/client/alipay/` in 1.7.0-rc.2).\n *\n * Key protocol differences from x402:\n * - Wire challenge is Base64URL-encoded `Payment-Needed` header with\n * nested `{protocol, method}` JSON (not flat `accepts[]`).\n * - Amount unit is **元** (CNY decimal string, not atomic units).\n * - Signature is RSA2 (SHA256WithRSA), not EIP-712 / EIP-3009.\n * - Verify/settle hit Alipay Open API HTTP endpoints, not chain RPC.\n *\n * The server emits **both** `X-Payment-Required` and `Payment-Needed`\n * headers so that legacy `alipay-bot` skills (`@alipay/agent-payment@1.0.9`)\n * keep working without changes.\n *\n * @see ../../docs/ALIPAY-RAIL.md — end-user integration guide\n * @see ../../docs/ALIPAY-INTEGRATION-DESIGN.md — architecture & decisions\n * @see ../../docs/ALIPAY-INTEGRATION-PLAN.md — implementation milestones\n *\n * Stub for 1.7.0-rc.1; bodies tracked in ALIPAY-INTEGRATION-PLAN.md §1.\n */\n\nimport crypto from 'node:crypto';\nimport {\n BaseFacilitator,\n X402PaymentPayload,\n X402PaymentRequirements,\n VerifyResult,\n SettleResult,\n HealthCheckResult,\n} from './interface.js';\nimport { rsa2Sign } from './alipay/rsa2.js';\nimport { base64url, decodeBase64UrlWithPadFix } from './alipay/encoding.js';\nimport { alipayOpenApiCall, AlipayOpenApiConfig } from './alipay/openapi.js';\n\n/** Network identifier exposed via `Facilitator.supportedNetworks`. */\nexport const ALIPAY_NETWORK = 'alipay';\n\n/** x402 `scheme` string identifying the Alipay rail in `accepts[]`. */\nexport const ALIPAY_SCHEME = 'alipay-aipay';\n\n/** Default production gateway URL. */\nexport const ALIPAY_GATEWAY_PROD = 'https://openapi.alipay.com/gateway.do';\n\n/** Sandbox gateway URL (for testing without real CNY). */\nexport const ALIPAY_GATEWAY_SANDBOX = 'https://openapi.alipaydev.com/gateway.do';\n\n/** Validation regex for `price_cny` / `amount` (decimal string, unit 元, ≤ 2 decimal places). */\nexport const ALIPAY_AMOUNT_REGEX = /^\\d+(\\.\\d{1,2})?$/;\n\n/** Lifetime of a 402 challenge before `pay_before` expires (Alipay convention). */\nexport const ALIPAY_PAY_BEFORE_MS = 30 * 60 * 1000;\n\n/**\n * The 8 fields that get RSA2-signed in dictionary order for a 402 challenge.\n * Exposed for visibility; internal to {@link AlipayFacilitator}.\n */\nexport const ALIPAY_SIGNING_FIELDS = [\n 'amount',\n 'currency',\n 'goods_name',\n 'out_trade_no',\n 'pay_before',\n 'resource_id',\n 'seller_id',\n 'service_id',\n] as const;\n\n/**\n * Facilitator-level configuration sourced from `provider.alipay` in\n * `moltspay.services.json`. The server resolves `private_key_path` and\n * `alipay_public_key_path` to PEM strings before constructing the facilitator.\n */\nexport interface AlipayFacilitatorConfig {\n /** Merchant Alipay ID (16 digits, e.g. `\"2088641494699428\"`). */\n seller_id: string;\n /** Application ID from Alipay Open Platform. */\n app_id: string;\n /** Merchant legal name; appears in `method.seller_name` of the 402 challenge. */\n seller_name: string;\n /** Fallback `service_id` when a service doesn't override it. */\n service_id_default: string;\n /** RSA2 merchant private key (PEM). Loaded from `private_key_path` by the server. */\n private_key_pem: string;\n /** Alipay platform public key (PEM). Loaded from `alipay_public_key_path` by the server. */\n alipay_public_key_pem: string;\n /** Open API gateway URL. Defaults to {@link ALIPAY_GATEWAY_PROD}. */\n gateway_url?: string;\n /** Signature algorithm. Only `RSA2` is supported. */\n sign_type?: 'RSA2';\n}\n\n/**\n * Inputs required to construct a 402 `Payment-Needed` challenge for a service.\n */\nexport interface CreatePaymentRequirementsOpts {\n /** Per-service Alipay `service_id` (overrides `provider.alipay.service_id_default`). */\n serviceId: string;\n /** CNY price as decimal string in **元** (e.g. `\"1.00\"` = 1 CNY). */\n priceCny: string;\n /** Goods name shown to the user in the Alipay app. */\n goodsName: string;\n /** Resource identifier (typically the request URL or its hash). */\n resourceId: string;\n /** Client-supplied `out_trade_no`; if omitted the facilitator generates one. */\n outTradeNo?: string;\n}\n\n/**\n * Both headers the server emits in a 402 response:\n * - `x402Accepts` → `X-Payment-Required` (x402 standard, for new MoltsPay clients)\n * - `paymentNeededHeader` → `Payment-Needed` (Alipay standard, for legacy `alipay-bot`)\n *\n * The two headers are mirrors of each other; the single source of truth lives\n * in the server config.\n */\nexport interface AlipayPaymentRequirements {\n x402Accepts: X402PaymentRequirements;\n paymentNeededHeader: string;\n}\n\n/**\n * Decoded `Payment-Proof` header from the buyer's request.\n *\n * The proof is Base64URL of `{protocol: {...}, method: {...}}` where:\n * - `protocol.trade_no` is the 32-digit Alipay trade number\n * - `protocol.payment_proof` is the RSA2-signed payment proof\n * - `method.client_session` echoes the buyer's session for replay protection\n */\nexport interface AlipayPaymentProof {\n protocol: {\n payment_proof: string;\n trade_no: string;\n [k: string]: unknown;\n };\n method: {\n client_session: string;\n [k: string]: unknown;\n };\n}\n\n/**\n * Alipay AI 收 facilitator.\n *\n * Construction is cheap; expensive setup (key parsing, gateway probe) is\n * deferred to `healthCheck()`.\n */\nexport class AlipayFacilitator extends BaseFacilitator {\n readonly name = 'alipay';\n readonly displayName = 'Alipay AI 收';\n readonly supportedNetworks = [ALIPAY_NETWORK];\n\n private readonly config: AlipayFacilitatorConfig;\n\n constructor(config: AlipayFacilitatorConfig) {\n super();\n this.config = {\n gateway_url: ALIPAY_GATEWAY_PROD,\n sign_type: 'RSA2',\n ...config,\n };\n }\n\n /**\n * Build the 402 challenge for a service: signs the 8-field payload with\n * RSA2, packages the nested `{protocol, method}` JSON as Base64URL for\n * `Payment-Needed`, and emits the parallel x402 `accepts[]` entry.\n */\n async createPaymentRequirements(\n opts: CreatePaymentRequirementsOpts,\n ): Promise<AlipayPaymentRequirements> {\n if (!ALIPAY_AMOUNT_REGEX.test(opts.priceCny)) {\n throw new Error(\n `AlipayFacilitator.createPaymentRequirements: priceCny \"${opts.priceCny}\" ` +\n `does not match /^\\\\d+(\\\\.\\\\d{1,2})?$/ (unit is 元, not 分; e.g. \"1.00\" not \"100\")`,\n );\n }\n\n const now = new Date();\n const outTradeNo = opts.outTradeNo ?? generateOutTradeNo();\n const payBefore = formatPayBefore(now);\n\n // 8 fields signed (dictionary order enforced by `ALIPAY_SIGNING_FIELDS`)\n const signedFields = {\n amount: opts.priceCny,\n currency: 'CNY',\n goods_name: opts.goodsName,\n out_trade_no: outTradeNo,\n pay_before: payBefore,\n resource_id: opts.resourceId,\n seller_id: this.config.seller_id,\n service_id: opts.serviceId,\n } as const;\n\n const signingString = ALIPAY_SIGNING_FIELDS\n .map((k) => `${k}=${signedFields[k]}`)\n .join('&');\n const seller_signature = rsa2Sign(signingString, this.config.private_key_pem);\n\n const challenge = {\n protocol: {\n out_trade_no: outTradeNo,\n amount: signedFields.amount,\n currency: signedFields.currency,\n resource_id: signedFields.resource_id,\n pay_before: payBefore,\n seller_signature,\n seller_sign_type: this.config.sign_type ?? 'RSA2',\n seller_unique_id: this.config.seller_id,\n },\n method: {\n seller_name: this.config.seller_name,\n seller_id: this.config.seller_id,\n seller_app_id: this.config.app_id,\n goods_name: signedFields.goods_name,\n seller_unique_id_key: 'seller_id',\n service_id: signedFields.service_id,\n },\n };\n\n const paymentNeededHeader = base64url(JSON.stringify(challenge));\n\n const x402Accepts: X402PaymentRequirements = {\n scheme: ALIPAY_SCHEME,\n network: ALIPAY_NETWORK,\n asset: 'CNY',\n amount: opts.priceCny,\n payTo: this.config.seller_id,\n maxTimeoutSeconds: ALIPAY_PAY_BEFORE_MS / 1000,\n extra: {\n payment_needed_header: paymentNeededHeader,\n out_trade_no: outTradeNo,\n pay_before: payBefore,\n service_id: signedFields.service_id,\n },\n };\n\n return { x402Accepts, paymentNeededHeader };\n }\n\n /**\n * Verify a `Payment-Proof` by calling\n * `alipay.aipay.agent.payment.verify` against the Alipay Open API.\n *\n * The proof is conveyed via `paymentPayload.payload`, which may be:\n * - a raw Base64URL string (the `Payment-Proof` header value), or\n * - an object `{ paymentProof: string }` / `{ proofHeader: string }`.\n *\n * All failure modes (malformed payload, network errors, Alipay\n * `code != 10000`) return `{ valid: false, error }`. No exception\n * escapes, regardless of client-supplied input.\n */\n async verify(\n paymentPayload: X402PaymentPayload,\n _requirements: X402PaymentRequirements,\n ): Promise<VerifyResult> {\n try {\n const proofHeader = extractProofHeader(paymentPayload.payload);\n const decoded = decodeProof(proofHeader);\n\n const response = await alipayOpenApiCall(\n 'alipay.aipay.agent.payment.verify',\n {\n payment_proof: decoded.protocol.payment_proof,\n trade_no: decoded.protocol.trade_no,\n client_session: decoded.method.client_session,\n },\n this.getOpenApiConfig(),\n );\n\n if (response.code !== '10000') {\n return {\n valid: false,\n error: `alipay verify ${response.code}: ${response.sub_msg ?? response.msg ?? 'unknown'}`,\n details: {\n code: response.code,\n sub_code: response.sub_code,\n sub_msg: response.sub_msg,\n },\n };\n }\n\n return {\n valid: true,\n details: {\n trade_no: (response.trade_no as string) ?? decoded.protocol.trade_no,\n amount: response.amount,\n out_trade_no: response.out_trade_no,\n resource_id: response.resource_id,\n active: response.active,\n },\n };\n } catch (e: unknown) {\n return {\n valid: false,\n error: e instanceof Error ? e.message : String(e),\n };\n }\n }\n\n /**\n * Settle by calling `alipay.aipay.agent.fulfillment.confirm` after the\n * service resource has been returned to the buyer.\n *\n * Per the design (see ALIPAY-INTEGRATION-DESIGN.md §5.1, risk row\n * \"履约确认失败\"), this is **fire-and-forget**: the caller (registry /\n * server) is expected to log fulfillment failures but NOT roll back\n * the already-delivered resource.\n *\n * Re-decodes `paymentPayload.payload` to extract `trade_no` (verify\n * does the same; the redundant Base64URL decode is negligible).\n */\n async settle(\n paymentPayload: X402PaymentPayload,\n _requirements: X402PaymentRequirements,\n ): Promise<SettleResult> {\n try {\n const proofHeader = extractProofHeader(paymentPayload.payload);\n const decoded = decodeProof(proofHeader);\n const tradeNo = decoded.protocol.trade_no;\n\n const response = await alipayOpenApiCall(\n 'alipay.aipay.agent.fulfillment.confirm',\n { trade_no: tradeNo },\n this.getOpenApiConfig(),\n );\n\n if (response.code !== '10000') {\n return {\n success: false,\n transaction: tradeNo,\n error: `alipay fulfillment ${response.code}: ${response.sub_msg ?? response.msg ?? 'unknown'}`,\n status: 'fulfillment_failed',\n };\n }\n\n return {\n success: true,\n transaction: tradeNo,\n status: 'fulfilled',\n };\n } catch (e: unknown) {\n return {\n success: false,\n error: e instanceof Error ? e.message : String(e),\n };\n }\n }\n\n /**\n * Validate that the configured RSA keys parse and that the Open API\n * gateway is reachable. Does NOT make a real business API call (would\n * burn quota and could appear as a legitimate verify attempt in logs).\n */\n async healthCheck(): Promise<HealthCheckResult> {\n const start = Date.now();\n\n try {\n crypto.createPrivateKey(this.config.private_key_pem);\n } catch (e: unknown) {\n return {\n healthy: false,\n error: `merchant private_key_pem parse failed: ${e instanceof Error ? e.message : String(e)}`,\n };\n }\n try {\n crypto.createPublicKey(this.config.alipay_public_key_pem);\n } catch (e: unknown) {\n return {\n healthy: false,\n error: `alipay_public_key_pem parse failed: ${e instanceof Error ? e.message : String(e)}`,\n };\n }\n\n const gatewayUrl = this.config.gateway_url ?? ALIPAY_GATEWAY_PROD;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5000);\n const response = await fetch(gatewayUrl, {\n method: 'HEAD',\n signal: controller.signal,\n }).catch(() => null);\n clearTimeout(timeout);\n\n const latencyMs = Date.now() - start;\n\n if (!response) {\n return { healthy: false, error: `gateway unreachable: ${gatewayUrl}`, latencyMs };\n }\n return { healthy: true, latencyMs };\n }\n\n /** Bundle the facilitator config into the shape openapi.ts wants. */\n private getOpenApiConfig(): AlipayOpenApiConfig {\n return {\n gateway_url: this.config.gateway_url ?? ALIPAY_GATEWAY_PROD,\n app_id: this.config.app_id,\n private_key_pem: this.config.private_key_pem,\n alipay_public_key_pem: this.config.alipay_public_key_pem,\n sign_type: this.config.sign_type,\n };\n }\n}\n\n// ─── Internal helpers (exported for unit testing only) ────────────────────────\n\n/**\n * Generate a 32-char `out_trade_no` with `VID` prefix + 29 random base64url\n * chars. Cryptographically random; uniqueness is statistical.\n *\n * @internal\n */\nexport function generateOutTradeNo(): string {\n // 22 random bytes → 30 base64url chars; slice 29 + \"VID\" prefix = 32 chars.\n return 'VID' + crypto.randomBytes(22).toString('base64url').slice(0, 29);\n}\n\n/**\n * Format `pay_before` as ISO 8601 UTC, exactly\n * {@link ALIPAY_PAY_BEFORE_MS} after the provided instant.\n * Strips fractional seconds for cleaner querystring signing.\n *\n * @internal\n */\nexport function formatPayBefore(now: Date): string {\n const expiry = new Date(now.getTime() + ALIPAY_PAY_BEFORE_MS);\n // toISOString returns \"YYYY-MM-DDTHH:mm:ss.sssZ\"; strip the ms.\n return expiry.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/**\n * Extract the Base64URL Payment-Proof header from `paymentPayload.payload`.\n * Accepts a bare string or an object with `paymentProof` / `proofHeader` key.\n *\n * @internal\n * @throws If the payload shape doesn't match either contract\n */\nexport function extractProofHeader(payload: unknown): string {\n if (typeof payload === 'string') {\n if (payload.length === 0) {\n throw new Error('alipay Payment-Proof is empty');\n }\n return payload;\n }\n if (payload !== null && typeof payload === 'object') {\n const obj = payload as Record<string, unknown>;\n const candidate = obj.paymentProof ?? obj.proofHeader;\n if (typeof candidate === 'string' && candidate.length > 0) {\n return candidate;\n }\n }\n throw new Error(\n 'alipay payment payload must be a Base64URL string or ' +\n '{paymentProof: string} / {proofHeader: string}',\n );\n}\n\n/**\n * Decode a Base64URL Payment-Proof header into its `{protocol, method}`\n * JSON shape, validating the three fields used by verify\n * (`protocol.payment_proof`, `protocol.trade_no`, `method.client_session`).\n *\n * @internal\n * @throws If decoding fails or required fields are missing\n */\nexport function decodeProof(proofHeader: string): AlipayPaymentProof {\n let parsed: unknown;\n try {\n parsed = JSON.parse(decodeBase64UrlWithPadFix(proofHeader));\n } catch (e: unknown) {\n throw new Error(\n `failed to decode Payment-Proof: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n if (parsed === null || typeof parsed !== 'object') {\n throw new Error('decoded Payment-Proof is not an object');\n }\n const obj = parsed as Record<string, unknown>;\n const protocol = obj.protocol as Record<string, unknown> | undefined;\n const method = obj.method as Record<string, unknown> | undefined;\n if (!protocol || typeof protocol.payment_proof !== 'string') {\n throw new Error('decoded Payment-Proof missing protocol.payment_proof');\n }\n if (typeof protocol.trade_no !== 'string') {\n throw new Error('decoded Payment-Proof missing protocol.trade_no');\n }\n if (!method || typeof method.client_session !== 'string') {\n throw new Error('decoded Payment-Proof missing method.client_session');\n }\n return parsed as AlipayPaymentProof;\n}\n","/**\n * RSA2 (SHA256WithRSA) signing helpers for Alipay AI 收.\n *\n * Uses Node's built-in `crypto` module. On the merchant side, MoltsPay\n * signs the 8 fields of the 402 challenge in dictionary order\n * (`amount` / `currency` / `goods_name` / `out_trade_no` / `pay_before` /\n * `resource_id` / `seller_id` / `service_id`). On the verify side, the\n * Alipay platform public key is used against `Payment-Proof` headers.\n *\n * Padding: PKCS#1 v1.5 (Node default for `RSA-SHA256`), matching Alipay's\n * `SHA256WithRSA` algorithm identifier.\n */\n\nimport crypto from 'node:crypto';\n\n/**\n * Sign a string with RSA2 (SHA256WithRSA) using a PEM-encoded private key.\n *\n * @param data - The exact bytes to sign (already dictionary-sorted querystring)\n * @param privateKeyPem - PKCS#1 or PKCS#8 PEM-encoded RSA private key\n * @returns Base64-encoded signature suitable for the `seller_signature` field\n * @throws If the private key is malformed\n */\nexport function rsa2Sign(data: string, privateKeyPem: string): string {\n const signer = crypto.createSign('RSA-SHA256');\n signer.update(data, 'utf-8');\n signer.end();\n return signer.sign(privateKeyPem, 'base64');\n}\n\n/**\n * Verify an RSA2 signature against the Alipay platform public key.\n *\n * Returns `false` (never throws) for any failure — malformed input,\n * wrong key, tampered data, or invalid base64. Untrusted callers can\n * pass arbitrary `Payment-Proof` bytes safely.\n *\n * @param data - The exact bytes that were signed\n * @param signature - Base64-encoded signature from `Payment-Proof`\n * @param publicKeyPem - PEM-encoded Alipay platform public key\n * @returns `true` if and only if the signature is valid\n */\nexport function rsa2Verify(\n data: string,\n signature: string,\n publicKeyPem: string,\n): boolean {\n try {\n const verifier = crypto.createVerify('RSA-SHA256');\n verifier.update(data, 'utf-8');\n verifier.end();\n return verifier.verify(publicKeyPem, signature, 'base64');\n } catch {\n return false;\n }\n}\n","/**\n * Base64URL encoding helpers for Alipay AI 收 wire format.\n *\n * Alipay's `Payment-Needed` and `Payment-Proof` headers use Base64URL\n * (`-` replaces `+`, `_` replaces `/`, padding optional). Some proxies\n * strip the trailing `=` padding; `decodeBase64UrlWithPadFix` recovers it\n * and accepts either alphabet.\n */\n\n/**\n * Encode a UTF-8 string as Base64URL (no padding).\n *\n * @param input - UTF-8 string to encode\n * @returns Base64URL representation (no `=` padding)\n */\nexport function base64url(input: string): string {\n return Buffer.from(input, 'utf-8').toString('base64url');\n}\n\n/**\n * Decode a Base64URL (or standard Base64) string to a UTF-8 string.\n *\n * Tolerates either URL-safe (`-` `_`) or standard (`+` `/`) alphabets,\n * with or without trailing `=` padding. Used for `Payment-Needed` and\n * `Payment-Proof` headers where proxies may strip padding.\n *\n * @param input - Base64URL or Base64 string\n * @returns Decoded UTF-8 string\n */\nexport function decodeBase64UrlWithPadFix(input: string): string {\n const normalized = input.replace(/-/g, '+').replace(/_/g, '/');\n const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4);\n return Buffer.from(padded, 'base64').toString('utf-8');\n}\n\n/**\n * Normalize an RSA key into PEM form.\n *\n * Alipay Open Platform hands out keys as **bare Base64** (a single line of\n * Base64-encoded DER, no `-----BEGIN-----` armor), but Node's `crypto`\n * key loaders and {@link rsa2Sign} require PEM. This wraps bare Base64 in\n * the requested PEM armor (64-char lines per RFC 7468); input that already\n * carries a `-----BEGIN` header is returned unchanged (trimmed).\n *\n * @param key Bare Base64 (DER) or an already-armored PEM string.\n * @param kind `'PRIVATE'` → PKCS#8 `PRIVATE KEY`; `'PUBLIC'` → SPKI `PUBLIC KEY`.\n */\nexport function toPem(key: string, kind: 'PRIVATE' | 'PUBLIC'): string {\n const trimmed = key.trim();\n if (trimmed.includes('-----BEGIN')) return trimmed;\n const label = kind === 'PRIVATE' ? 'PRIVATE KEY' : 'PUBLIC KEY';\n const body = trimmed.replace(/\\s+/g, '').match(/.{1,64}/g)?.join('\\n') ?? '';\n return `-----BEGIN ${label}-----\\n${body}\\n-----END ${label}-----\\n`;\n}\n","/**\n * Alipay Open API caller for AI 收 verify and fulfillment.\n *\n * Wraps the `application/x-www-form-urlencoded` gateway protocol\n * (`https://openapi.alipay.com/gateway.do` for production,\n * `https://openapi.alipaydev.com/gateway.do` for sandbox). Handles\n * RSA2 request signing, response unwrapping, and gateway-level error\n * surfacing.\n *\n * Request envelope (8 public params + `sign`):\n * app_id — application ID\n * method — e.g. `alipay.aipay.agent.payment.verify`\n * format — `JSON`\n * charset — `utf-8`\n * sign_type — `RSA2`\n * timestamp — `YYYY-MM-DD HH:mm:ss`\n * version — `1.0`\n * biz_content — JSON-stringified business params\n * sign — RSA2 signature over the other 8 params sorted by key\n *\n * Response envelope:\n * { \"<method_with_underscores>_response\": { code, msg, ... } }\n *\n * NOTE: Response signature verification against the Alipay platform\n * public key is NOT implemented (relies on HTTPS transport integrity).\n * Adding it requires extracting raw bytes for the wrapped response key\n * from the response text; deferred to a future hardening pass.\n */\n\nimport { rsa2Sign } from './rsa2.js';\n\n/**\n * Configuration required to make a single Open API call.\n */\nexport interface AlipayOpenApiConfig {\n gateway_url: string;\n app_id: string;\n private_key_pem: string;\n alipay_public_key_pem: string;\n sign_type?: 'RSA2';\n}\n\n/**\n * Unwrapped response from an Alipay Open API call.\n *\n * `code` is the Alipay business code (`\"10000\"` = success).\n * `sub_code` / `sub_msg` carry the specific failure reason when `code != \"10000\"`.\n */\nexport interface AlipayOpenApiResponse {\n code: string;\n msg?: string;\n sub_code?: string;\n sub_msg?: string;\n [key: string]: unknown;\n}\n\n/**\n * Format a JS Date as Alipay's expected `YYYY-MM-DD HH:mm:ss` timestamp.\n * Uses local time (matches the convention of merchant-region Open API SDKs).\n *\n * Exported for unit testing only.\n */\nexport function formatAlipayTimestamp(d: Date = new Date()): string {\n const pad = (n: number): string => String(n).padStart(2, '0');\n return (\n `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` +\n `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`\n );\n}\n\n/**\n * Build the signing string for a set of Alipay Open API parameters:\n * keys sorted alphabetically, joined as `key=value&key=value`. Values\n * are NOT URL-encoded at this stage.\n *\n * Exported for unit testing only.\n */\nexport function buildSigningString(params: Record<string, string>): string {\n return Object.keys(params)\n .sort()\n .map((k) => `${k}=${params[k]}`)\n .join('&');\n}\n\n/**\n * Derive the response wrapper key for a given method name.\n *\n * \"alipay.aipay.agent.payment.verify\"\n * → \"alipay_aipay_agent_payment_verify_response\"\n *\n * Exported for unit testing only.\n */\nexport function responseWrapperKey(method: string): string {\n return `${method.replace(/\\./g, '_')}_response`;\n}\n\n/**\n * Call an Alipay Open API method.\n *\n * Common methods used by MoltsPay:\n * - `alipay.aipay.agent.payment.verify` — verify a `Payment-Proof`\n * - `alipay.aipay.agent.fulfillment.confirm` — confirm fulfillment\n *\n * @param method - Alipay Open API method name\n * @param bizContent - Method-specific business parameters\n * @param config - Gateway URL + credentials\n * @returns Unwrapped business response; check `code === \"10000\"` for success\n * @throws On HTTP-level failure, malformed JSON, or missing response wrapper\n */\nexport async function alipayOpenApiCall(\n method: string,\n bizContent: Record<string, unknown>,\n config: AlipayOpenApiConfig,\n): Promise<AlipayOpenApiResponse> {\n const publicParams: Record<string, string> = {\n app_id: config.app_id,\n method,\n format: 'JSON',\n charset: 'utf-8',\n sign_type: config.sign_type ?? 'RSA2',\n timestamp: formatAlipayTimestamp(),\n version: '1.0',\n biz_content: JSON.stringify(bizContent),\n };\n\n const signingString = buildSigningString(publicParams);\n const sign = rsa2Sign(signingString, config.private_key_pem);\n\n const body = new URLSearchParams({ ...publicParams, sign }).toString();\n\n const response = await fetch(config.gateway_url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',\n },\n body,\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => '<unreadable>');\n throw new Error(\n `Alipay Open API HTTP ${response.status} for ${method}: ${text.slice(0, 500)}`,\n );\n }\n\n const json = (await response.json()) as Record<string, unknown>;\n const wrapperKey = responseWrapperKey(method);\n const business = json[wrapperKey];\n\n if (business === undefined || business === null || typeof business !== 'object') {\n throw new Error(\n `Alipay Open API response missing \"${wrapperKey}\" wrapper for ${method}: ` +\n `${JSON.stringify(json).slice(0, 500)}`,\n );\n }\n\n return business as AlipayOpenApiResponse;\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';\nimport { BNBFacilitator } from './bnb.js';\nimport { SolanaFacilitator, SolanaFacilitatorConfig } from './solana.js';\nimport { AlipayFacilitator, AlipayFacilitatorConfig } from './alipay.js';\nimport { Keypair } from '@solana/web3.js';\nimport bs58 from 'bs58';\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 this.registerFactory('bnb', (config) => new BNBFacilitator(config?.serverPrivateKey as string));\n this.registerFactory('solana', (config) => {\n // Load fee payer keypair from config or env\n let feePayerKeypair: Keypair | undefined;\n const feePayerKey = (config as any)?.feePayerPrivateKey || process.env.SOLANA_FEE_PAYER_KEY;\n \n if (feePayerKey) {\n try {\n feePayerKeypair = Keypair.fromSecretKey(bs58.decode(feePayerKey));\n } catch (e: any) {\n console.warn(`[SolanaFacilitator] Invalid fee payer key: ${e.message}`);\n }\n }\n \n return new SolanaFacilitator({ feePayerKeypair } as SolanaFacilitatorConfig);\n });\n this.registerFactory('alipay', (config) => new AlipayFacilitator(config as unknown as AlipayFacilitatorConfig));\n\n // Default selection — alipay is opt-in (requires provider.alipay config), kept out of fallback list\n this.selection = selection || { primary: 'cdp', fallback: ['tempo', 'bnb', 'solana'], 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","/**\n * MoltsPay Server Types\n */\n\n// Supported token types\nexport type TokenSymbol = 'USDC' | 'USDT';\n\n// Service definition from moltspay.services.json\nexport interface ServiceConfig {\n id: string;\n name: string;\n description?: string;\n price: number;\n currency: string;\n /**\n * Tokens accepted for payment (optional).\n * If not specified, defaults to [currency].\n * Example: [\"USDC\", \"USDT\"]\n */\n acceptedCurrencies?: TokenSymbol[];\n input: Record<string, InputField>;\n output: Record<string, OutputField>;\n /** Shell command to execute for this service. Params passed as JSON to stdin. */\n command?: string;\n /** Function name to import from skill's index.js (new skill-based approach) */\n function?: string;\n /**\n * Alipay AI 收 per-service config (2.0.0+).\n * Set when this service accepts CNY payments via the alipay rail.\n * The `price`/`currency` fields above still describe USDC pricing\n * for the x402 rails; `alipay.price_cny` is a separate CNY price.\n */\n alipay?: ServiceAlipayConfig;\n}\n\n/**\n * Per-service Alipay AI 收 configuration (2.0.0+).\n *\n * Sample:\n * ```json\n * \"alipay\": {\n * \"service_id\": \"API_0EA6DC4FC99A4DF7\",\n * \"price_cny\": \"7.00\",\n * \"goods_name\": \"产品演示视频 - 系列一\"\n * }\n * ```\n */\nexport interface ServiceAlipayConfig {\n /** Per-service service_id (defaults to provider.alipay.service_id_default). */\n service_id?: string;\n /**\n * CNY price as decimal string in **元** (e.g. `\"7.00\"` = 7 CNY).\n * NOT cents: `\"100\"` means 100 元, not 100 分.\n * Must match `/^\\d+(\\.\\d{1,2})?$/`.\n */\n price_cny: string;\n /** Goods name shown to the user in the Alipay app. */\n goods_name: string;\n}\n\nexport interface InputField {\n type: 'string' | 'number' | 'boolean' | 'object';\n required?: boolean;\n description?: string;\n}\n\nexport interface OutputField {\n type: 'string' | 'number' | 'boolean' | 'object';\n description?: string;\n}\n\n// Chain configuration for multi-chain support\nexport interface ChainConfig {\n chain: string;\n network: string;\n wallet?: string; // Optional per-chain wallet, falls back to provider.wallet\n tokens?: TokenSymbol[];\n}\n\n// Provider config from moltspay.services.json\nexport interface ProviderConfig {\n name: string;\n description?: string;\n wallet: string;\n solana_wallet?: string; // Solana chains receiving wallet\n chain?: string; // Single chain (backward compat)\n chains?: ChainConfig[]; // Multi-chain support\n /**\n * Alipay AI 收 provider-level config (2.0.0+).\n * Required when `chains` includes `\"alipay\"`.\n * Server validates `private_key_path` / `alipay_public_key_path` are\n * readable + parse as RSA PEM at startup; rejects start otherwise.\n */\n alipay?: ProviderAlipayConfig;\n}\n\n/**\n * Provider-level Alipay AI 收 configuration (2.0.0+).\n *\n * The user-facing form uses FILE PATHS for both PEM keys; the server\n * resolves them to PEM strings before constructing AlipayFacilitator.\n *\n * Sample:\n * ```json\n * \"alipay\": {\n * \"seller_id\": \"2088641494699428\",\n * \"app_id\": \"2021006150642142\",\n * \"seller_name\": \"上海超响应数字科技有限公司\",\n * \"service_id_default\": \"API_0EA6DC4FC99A4DF7\",\n * \"private_key_path\": \"./cert/ALIPAY_PRIVATE_KEY.txt\",\n * \"alipay_public_key_path\": \"./cert/ALIPAY_PUBLIC_KEY.txt\"\n * }\n * ```\n */\nexport interface ProviderAlipayConfig {\n /** Merchant Alipay ID (16 digits, e.g. `\"2088641494699428\"`). */\n seller_id: string;\n /** Application ID from Alipay Open Platform. */\n app_id: string;\n /** Merchant legal name; appears in `method.seller_name` of the 402 challenge. */\n seller_name: string;\n /** Default `service_id` when a `services[].alipay` entry doesn't override it. */\n service_id_default: string;\n /** Path to the RSA2 merchant private key PEM file (relative to moltspay.services.json). */\n private_key_path: string;\n /** Path to the Alipay platform public key PEM file (relative to moltspay.services.json). */\n alipay_public_key_path: string;\n /** Open API gateway URL. Defaults to `\"https://openapi.alipay.com/gateway.do\"`. */\n gateway_url?: string;\n /** Signature algorithm. Only `\"RSA2\"` is supported in 2.0.0. */\n sign_type?: 'RSA2';\n}\n\n// Full services.json structure\nexport interface ServicesManifest {\n provider: ProviderConfig;\n services: ServiceConfig[];\n}\n\n// Skill function type\nexport type SkillFunction = (params: Record<string, any>) => Promise<Record<string, any>>;\n\n// Registered skill\nexport interface RegisteredSkill {\n id: string;\n config: ServiceConfig;\n handler: SkillFunction;\n}\n\n// Payment request (returned to client)\nexport interface PaymentRequest {\n chargeId: string;\n service: string;\n amount: number;\n currency: string;\n wallet: string;\n chain: string;\n expiresAt: number;\n}\n\n// Payment verification request\nexport interface VerifyRequest {\n chargeId: string;\n txHash: string;\n}\n\n// Charge status\nexport type ChargeStatus = 'pending' | 'paid' | 'completed' | 'expired' | 'failed';\n\n// Internal charge record\nexport interface Charge {\n id: string;\n service: string;\n params: Record<string, any>;\n amount: number;\n currency: string;\n status: ChargeStatus;\n txHash?: string;\n result?: Record<string, any>;\n createdAt: number;\n expiresAt: number;\n paidAt?: number;\n completedAt?: number;\n}\n\n/**\n * CORS configuration. See MoltsPayServerOptions.cors.\n * Fine-grained shape for providers that need allowlist origins or custom control.\n */\nexport interface CorsOptions {\n /** Explicit origin allowlist. Either an array of origins, or a predicate function. */\n origins: string[] | ((origin: string) => boolean);\n /** Emit `Access-Control-Allow-Credentials: true`. Default false. */\n credentials?: boolean;\n /** Preflight cache seconds (`Access-Control-Max-Age`). Default 600. */\n maxAge?: number;\n}\n\n// Server options\nexport interface MoltsPayServerOptions {\n port?: number;\n host?: string;\n chargeExpirySecs?: number;\n /** x402 Facilitator URL (default: https://x402.org/facilitator) */\n facilitatorUrl?: string;\n\n /**\n * CORS configuration.\n *\n * - `undefined` or `true` (default): allow any origin (`Access-Control-Allow-Origin: *`).\n * This matches the 1.5.x behavior — browser clients from any origin can call this server.\n * - `false`: emit no CORS headers (same-origin only).\n * - `string[]`: explicit origin allowlist. Request's Origin must match an entry.\n * - `CorsOptions` object: fine-grained control (origins + credentials + maxAge).\n *\n * When CORS is active, the server always exposes the following response headers via\n * `Access-Control-Expose-Headers`: `X-Payment-Required`, `X-Payment-Response`,\n * `WWW-Authenticate`, `Payment-Receipt`. These are required for browser clients to\n * read the 402 challenge and the payment receipt on successful responses.\n */\n cors?: boolean | string[] | CorsOptions;\n}\n","/**\n * Coinbase Pay Integration\n * \n * Generate session token and URL for users to buy USDC with fiat\n * via Coinbase Pay (US only, debit card / Apple Pay)\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\n\nconst CDP_API_BASE = 'https://api.developer.coinbase.com';\n\ninterface CDPCredentials {\n apiKeyId: string;\n apiKeySecret: string;\n}\n\n/**\n * Load CDP credentials from environment or .env file\n */\nfunction loadCredentials(): CDPCredentials | null {\n let apiKeyId = process.env.CDP_API_KEY_ID;\n let apiKeySecret = process.env.CDP_API_KEY_SECRET;\n\n if (!apiKeyId || !apiKeySecret) {\n const envPath = join(homedir(), '.moltspay', '.env');\n if (existsSync(envPath)) {\n const envContent = readFileSync(envPath, 'utf-8');\n for (const line of envContent.split('\\n')) {\n const [key, ...valueParts] = line.split('=');\n const value = valueParts.join('=').trim();\n if (key === 'CDP_API_KEY_ID') apiKeyId = value;\n if (key === 'CDP_API_KEY_SECRET') apiKeySecret = value;\n }\n }\n }\n\n if (!apiKeyId || !apiKeySecret) {\n return null;\n }\n\n return { apiKeyId, apiKeySecret };\n}\n\n/**\n * Get public IP address\n */\nasync function getPublicIp(): Promise<string> {\n const response = await fetch('https://api.ipify.org');\n if (!response.ok) {\n throw new Error('Failed to get public IP');\n }\n return (await response.text()).trim();\n}\n\n/**\n * Generate JWT for CDP API authentication\n */\nasync function generateCdpJwt(\n credentials: CDPCredentials,\n method: string,\n path: string\n): Promise<string> {\n const { SignJWT, importJWK } = await import('jose');\n const crypto = await import('crypto');\n\n const now = Math.floor(Date.now() / 1000);\n const nonce = crypto.randomBytes(16).toString('hex');\n\n // URI format: \"METHOD host/path\" (no https://)\n const uri = `${method} api.developer.coinbase.com${path}`;\n\n const claims = {\n sub: credentials.apiKeyId,\n iss: 'cdp',\n nbf: now,\n exp: now + 120,\n uri,\n };\n\n // Ed25519 key: 64 bytes = 32 seed + 32 public\n const decoded = Buffer.from(credentials.apiKeySecret, 'base64');\n const seed = decoded.subarray(0, 32);\n const publicKey = decoded.subarray(32);\n\n const jwk = {\n kty: 'OKP' as const,\n crv: 'Ed25519' as const,\n d: seed.toString('base64url'),\n x: publicKey.toString('base64url'),\n };\n\n const key = await importJWK(jwk, 'EdDSA');\n\n return await new SignJWT(claims)\n .setProtectedHeader({ alg: 'EdDSA', kid: credentials.apiKeyId, typ: 'JWT', nonce })\n .sign(key);\n}\n\n/**\n * Get session token from CDP Onramp API\n */\nasync function getSessionToken(params: {\n address: string;\n chain: 'base' | 'polygon';\n clientIp: string;\n}): Promise<{ token: string; channelId: string }> {\n const credentials = loadCredentials();\n if (!credentials) {\n throw new Error('CDP credentials not found. Set CDP_API_KEY_ID and CDP_API_KEY_SECRET.');\n }\n\n const path = '/onramp/v1/token';\n const jwt = await generateCdpJwt(credentials, 'POST', path);\n\n const response = await fetch(`${CDP_API_BASE}${path}`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${jwt}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n addresses: [\n {\n address: params.address,\n blockchains: [params.chain],\n },\n ],\n clientIp: params.clientIp,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`CDP API error (${response.status}): ${errorText}`);\n }\n\n const result = await response.json() as { token: string; channel_id: string };\n return {\n token: result.token,\n channelId: result.channel_id,\n };\n}\n\n/**\n * Generate Coinbase Pay URL with session token\n */\nexport async function generateOnrampUrl(params: {\n destinationAddress: string;\n amount: number;\n chain?: 'base' | 'polygon';\n}): Promise<string> {\n const chain = params.chain || 'base';\n\n // Get public IP\n const clientIp = await getPublicIp();\n\n // Get session token\n const { token } = await getSessionToken({\n address: params.destinationAddress,\n chain,\n clientIp,\n });\n\n // Build URL with session token\n const queryParams = new URLSearchParams({\n sessionToken: token,\n defaultAsset: 'USDC',\n defaultNetwork: chain,\n presetFiatAmount: params.amount.toString(),\n });\n\n return `https://pay.coinbase.com/buy/select-asset?${queryParams.toString()}`;\n}\n\n/**\n * Print QR code to terminal\n */\nexport async function printQRCode(url: string): Promise<void> {\n const qrcodeModule = await import('qrcode-terminal');\n const qrcode = qrcodeModule.default || qrcodeModule;\n\n return new Promise((resolve) => {\n qrcode.generate(url, { small: true }, (qr: string) => {\n console.log(qr);\n resolve();\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAeA,oBAA0B;AAK1B,uBAAwB;AACxB,IAAAA,aAAwB;AACxB,IAAAC,eAAuC;AACvC,IAAAC,aAA+E;AAC/E,IAAAC,wBAAsB;AACtB,IAAAC,iBAAuB;;;ACzBvB;;;ACAA;AAWA,IAAAC,aAAwF;AACxF,IAAAC,aAAwB;AACxB,IAAAC,eAAqB;AACrB,IAAAC,iBAA+B;;;ACd/B;AAMO,IAAM,SAA4C;AAAA;AAAA,EAEvD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,QAAQ;AAAA,MACN,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM;AAAA;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,QAAQ;AAAA,MACN,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA;AAAA,EAEA,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,QAAQ;AAAA,MACN,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA;AAAA,EAEA,gBAAgB;AAAA,IACd,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,QAAQ;AAAA;AAAA;AAAA,MAGN,MAAM;AAAA,QACJ,SAAS;AAAA;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA;AAAA,EAChB;AAAA;AAAA,EAEA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,QAAQ;AAAA;AAAA;AAAA,MAGN,MAAM;AAAA,QACJ,SAAS;AAAA;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA;AAAA,IAEd,kBAAkB;AAAA,EACpB;AAAA;AAAA,EAEA,KAAK;AAAA,IACH,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,QAAQ;AAAA;AAAA,MAEN,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA;AAAA,IAEd,kBAAkB;AAAA,EACpB;AACF;AA+BO,SAAS,SAAS,MAAiC;AACxD,QAAM,SAAS,OAAO,IAAI;AAC1B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,sBAAsB,IAAI,gBAAgB,OAAO,KAAK,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EAC5F;AACA,SAAO;AACT;AAuBO,IAAM,kBAAkB;AAgCxB,SAAS,gBAAgB,IAA0C;AACxE,SAAO,OAAO;AAChB;;;AC7PA;AAOA,IAAAC,eAAiE;AACjE,uBAAsD;AACtD,gBAAmE;AACnE,kBAAqB;AACrB,gBAAwB;AACxB,kBAAiB;;;ACZjB;AASA,kBAAsC;AAkB/B,IAAM,gBAA4D;AAAA,EACvE,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,MACN,MAAM;AAAA,QACJ,MAAM;AAAA;AAAA,QACN,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA,EACA,eAAe;AAAA,IACb,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,MACN,MAAM;AAAA;AAAA,QAEJ,MAAM;AAAA,QACN,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,oBAAoB,OAAoC;AACtE,QAAM,SAAS,cAAc,KAAK;AAClC,SAAO,IAAI,uBAAW,OAAO,KAAK,WAAW;AAC/C;AAKO,SAAS,YAAY,OAAmC;AAC7D,SAAO,IAAI,sBAAU,cAAc,KAAK,EAAE,OAAO,KAAK,IAAI;AAC5D;;;ADvDA,IAAM,yBAAqB,sBAAK,mBAAQ,GAAG,WAAW;AACtD,IAAM,qBAAqB;AAWpB,SAAS,oBAAoB,YAAoB,oBAA4B;AAClF,aAAO,kBAAK,WAAW,kBAAkB;AAC3C;AAKO,SAAS,mBAAmB,YAAoB,oBAA6B;AAClF,aAAO,sBAAW,oBAAoB,SAAS,CAAC;AAClD;AAKO,SAAS,iBAAiB,YAAoB,oBAAoC;AACvF,QAAM,aAAa,oBAAoB,SAAS;AAEhD,MAAI,KAAC,sBAAW,UAAU,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,OAAyB,KAAK,UAAM,wBAAa,YAAY,OAAO,CAAC;AAC3E,UAAM,YAAY,YAAAC,QAAK,OAAO,KAAK,SAAS;AAC5C,WAAO,qBAAQ,cAAc,SAAS;AAAA,EACxC,SAAS,OAAO;AACd,YAAQ,MAAM,iCAAiC,KAAK;AACpD,WAAO;AAAA,EACT;AACF;AAKO,SAAS,mBAAmB,YAAoB,oBAA6B;AAElF,MAAI,KAAC,sBAAW,SAAS,GAAG;AAC1B,6BAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC1C;AAEA,QAAM,UAAU,qBAAQ,SAAS;AACjC,QAAM,OAAyB;AAAA,IAC7B,WAAW,QAAQ,UAAU,SAAS;AAAA,IACtC,WAAW,YAAAA,QAAK,OAAO,QAAQ,SAAS;AAAA,IACxC,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AAEA,QAAM,aAAa,oBAAoB,SAAS;AAChD,+BAAc,YAAY,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAEvD,SAAO;AACT;AAKO,SAAS,iBAAiB,YAAoB,oBAAmC;AACtF,QAAM,SAAS,iBAAiB,SAAS;AACzC,SAAO,QAAQ,UAAU,SAAS,KAAK;AACzC;AAKA,eAAsB,iBACpB,SACA,OACiB;AACjB,QAAM,aAAa,oBAAoB,KAAK;AAC5C,QAAM,SAAS,IAAI,uBAAU,OAAO;AAEpC,QAAM,UAAU,MAAM,WAAW,WAAW,MAAM;AAClD,SAAO,UAAU;AACnB;AAKA,eAAsB,qBACpB,SACA,OACiB;AACjB,QAAM,aAAa,oBAAoB,KAAK;AAC5C,QAAM,QAAQ,IAAI,uBAAU,OAAO;AACnC,QAAM,OAAO,YAAY,KAAK;AAE9B,MAAI;AACF,UAAM,MAAM,UAAM,4CAA0B,MAAM,KAAK;AACvD,UAAM,UAAU,UAAM,6BAAW,YAAY,GAAG;AAEhD,WAAO,OAAO,QAAQ,MAAM,IAAI;AAAA,EAClC,SAAS,OAAY;AAEnB,QAAI,MAAM,SAAS,+BACf,MAAM,SAAS,SAAS,wBAAwB,GAAG;AACrD,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAKA,eAAsB,kBACpB,SACA,OACwC;AACxC,QAAM,CAAC,KAAK,IAAI,IAAI,MAAM,QAAQ,IAAI;AAAA,IACpC,iBAAiB,SAAS,KAAK;AAAA,IAC/B,qBAAqB,SAAS,KAAK;AAAA,EACrC,CAAC;AAED,SAAO,EAAE,KAAK,KAAK;AACrB;AA+BO,SAAS,qBAAqB,SAA0B;AAC7D,MAAI;AACF,QAAI,uBAAU,OAAO;AACrB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AEnLA;AAcA,IAAAC,eAOO;AACP,IAAAC,oBAMO;;;AC5BP;AA2JO,IAAe,kBAAf,MAAsD;AAAA,EAe3D,gBAAgB,SAA0B;AACxC,WAAO,KAAK,kBAAkB,SAAS,OAAO;AAAA,EAChD;AACF;;;AD7GO,IAAM,oBAAN,cAAgC,gBAAgB;AAAA,EAC5C,OAAO;AAAA,EACP,cAAc;AAAA,EACd,oBAAoB,CAAC,kBAAkB,eAAe;AAAA,EAEvD,cAAgD,oBAAI,IAAI;AAAA,EACxD;AAAA,EAER,YAAY,QAAkC;AAC5C,UAAM;AACN,SAAK,kBAAkB,QAAQ;AAG/B,eAAW,CAAC,OAAOC,OAAM,KAAK,OAAO,QAAQ,aAAa,GAAG;AAC3D,WAAK,YAAY;AAAA,QACf;AAAA,QACA,IAAI,wBAAWA,QAAO,KAAK,WAAW;AAAA,MACxC;AAAA,IACF;AAEA,QAAI,KAAK,iBAAiB;AACxB,cAAQ,IAAI,wDAAwD,KAAK,gBAAgB,UAAU,SAAS,CAAC,EAAE;AAAA,IACjH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAmC;AACjC,WAAO,KAAK,iBAAiB,UAAU,SAAS,KAAK;AAAA,EACvD;AAAA,EAEQ,cAAc,OAAoC;AACxD,UAAM,OAAO,KAAK,YAAY,IAAI,KAAK;AACvC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,4BAA4B,KAAK,EAAE;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,eAAe,OAAgC;AACpD,WAAO,UAAU,WAAW,mBAAmB;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,eAAe,SAAyC;AAC7D,QAAI,YAAY,iBAAkB,QAAO;AACzC,QAAI,YAAY,gBAAiB,QAAO;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAA0C;AAC9C,UAAM,QAAQ,KAAK,IAAI;AACvB,QAAI;AAEF,YAAM,OAAO,KAAK,cAAc,eAAe;AAC/C,YAAM,KAAK,QAAQ;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,KAAK,IAAI,IAAI;AAAA,MAC1B;AAAA,IACF,SAAS,OAAY;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,MAAM;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OACJ,gBACA,cACuB;AACvB,QAAI;AACF,YAAM,gBAAgB,eAAe;AACrC,UAAI,CAAC,iBAAiB,CAAC,cAAc,mBAAmB;AACtD,eAAO,EAAE,OAAO,OAAO,OAAO,6BAA6B;AAAA,MAC7D;AAEA,YAAM,QAAQ,cAAc,SAAS;AACrC,YAAM,cAAc,cAAc,KAAK;AACvC,UAAI,CAAC,aAAa;AAChB,eAAO,EAAE,OAAO,OAAO,OAAO,kBAAkB,KAAK,GAAG;AAAA,MAC1D;AAGA,YAAM,WAAW,OAAO,KAAK,cAAc,mBAAmB,QAAQ;AACtE,UAAI;AAEJ,UAAI;AAEF,aAAK,yBAAY,KAAK,QAAQ;AAAA,MAChC,QAAQ;AAEN,aAAK,kCAAqB,YAAY,QAAQ;AAAA,MAChD;AAGA,UAAI,cAAc,0BAAa;AAG7B,cAAM,kBAAkB,GAAG,WAAW;AAAA,UAAK,SACzC,IAAI,aAAa,CAAC,IAAI,UAAU,MAAM,OAAK,MAAM,CAAC;AAAA,QACpD;AACA,YAAI,CAAC,iBAAiB;AACpB,iBAAO,EAAE,OAAO,OAAO,OAAO,yBAAyB;AAAA,QACzD;AAAA,MACF;AAGA,YAAM,iBAAiB,OAAO,aAAa,MAAM;AACjD,YAAM,oBAAoB,IAAI,uBAAU,aAAa,KAAK;AAI1D,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,UACP;AAAA,UACA,QAAQ,cAAc;AAAA,UACtB,WAAW,aAAa;AAAA,UACxB,QAAQ,aAAa;AAAA,QACvB;AAAA,MACF;AAAA,IACF,SAAS,OAAY;AACnB,aAAO,EAAE,OAAO,OAAO,OAAO,MAAM,QAAQ;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OACJ,gBACA,cACuB;AACvB,QAAI;AACF,YAAM,gBAAgB,eAAe;AACrC,UAAI,CAAC,iBAAiB,CAAC,cAAc,mBAAmB;AACtD,eAAO,EAAE,SAAS,OAAO,OAAO,6BAA6B;AAAA,MAC/D;AAEA,YAAM,QAAQ,cAAc,SAAS;AACrC,YAAM,aAAa,KAAK,cAAc,KAAK;AAG3C,YAAM,WAAW,OAAO,KAAK,cAAc,mBAAmB,QAAQ;AAEtE,UAAI;AAEJ,UAAI;AAEF,cAAM,KAAK,yBAAY,KAAK,QAAQ;AAGpC,YAAI,KAAK,mBAAmB,GAAG,UAAU;AACvC,gBAAM,iBAAiB,KAAK,gBAAgB,UAAU,SAAS;AAC/D,gBAAM,aAAa,GAAG,SAAS,SAAS;AAExC,cAAI,eAAe,gBAAgB;AAEjC,oBAAQ,IAAI,8DAA8D;AAC1E,eAAG,YAAY,KAAK,eAAe;AAAA,UACrC;AAAA,QACF;AAEA,mBAAW,GAAG,UAAU;AAAA,MAC1B,SAAS,GAAQ;AAEf,mBAAW;AAAA,MACb;AAGA,YAAM,YAAY,MAAM,WAAW,mBAAmB,UAAU;AAAA,QAC9D,eAAe;AAAA,QACf,qBAAqB;AAAA,MACvB,CAAC;AAGD,YAAM,eAAe,MAAM,WAAW,mBAAmB,WAAW,WAAW;AAE/E,UAAI,aAAa,MAAM,KAAK;AAC1B,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,uBAAuB,KAAK,UAAU,aAAa,MAAM,GAAG,CAAC;AAAA,UACpE,aAAa;AAAA,QACf;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,QAAQ;AAAA,MACV;AAAA,IACF,SAAS,OAAY;AACnB,aAAO,EAAE,SAAS,OAAO,OAAO,MAAM,QAAQ;AAAA,IAChD;AAAA,EACF;AAAA,EAEA,gBAAgB,SAA0B;AACxC,WAAO,KAAK,kBAAkB,SAAS,OAAO;AAAA,EAChD;AACF;AAaA,eAAsB,+BACpB,cACA,iBACA,QACA,OACA,gBACA,YACsB;AACtB,QAAM,cAAc,cAAc,KAAK;AACvC,QAAM,OAAO,cAAc,IAAI,wBAAW,YAAY,KAAK,WAAW;AACtE,QAAM,OAAO,IAAI,uBAAU,YAAY,OAAO,KAAK,IAAI;AAGvD,QAAM,iBAAiB,kBAAkB;AAGzC,QAAM,YAAY,UAAM,6CAA0B,MAAM,YAAY;AACpE,QAAM,eAAe,UAAM,6CAA0B,MAAM,eAAe;AAE1E,QAAM,cAAc,IAAI,yBAAY;AAGpC,MAAI;AACF,cAAM,8BAAW,MAAM,YAAY;AAAA,EACrC,QAAQ;AAEN,gBAAY;AAAA,UACV;AAAA,QACE;AAAA;AAAA,QACA;AAAA;AAAA,QACA;AAAA;AAAA,QACA;AAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,cAAY;AAAA,QACV;AAAA,MACE;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA,YAAY,OAAO,KAAK;AAAA;AAAA,IAC1B;AAAA,EACF;AAGA,QAAM,EAAE,WAAW,qBAAqB,IAAI,MAAM,KAAK,mBAAmB;AAC1E,cAAY,kBAAkB;AAC9B,cAAY,WAAW;AAEvB,SAAO;AACT;;;AJzUA,IAAAC,eAA+C;;;AMnB/C;;;ACAA;AASO,IAAM,eAAe;AACrB,IAAM,0BAA0B;AAChC,IAAM,iBAAiB;;;ACX9B;AAkBA,IAAM,mBAA8C;AAAA,EAClD,eAAiB;AAAA,EACjB,cAAiB;AAAA,EACjB,gBAAiB;AAAA,EACjB,gBAAiB;AAAA,EACjB,aAAiB;AAAA,EACjB,aAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,iBAAkB;AACpB;AAEA,IAAM,mBAA8C,OAAO;AAAA,EACzD,OAAO,QAAQ,gBAAgB,EAAE,IAAI,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC,OAAO,OAAO,CAAC;AAC7E;AAGO,SAAS,mBAAmB,SAAmC;AACpE,SAAO,iBAAiB,OAAO,KAAK;AACtC;;;ACpCA;AAWA,IAAM,aACH,WAAuC;;;ACZ1C;AAOO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EAC9B;AAAA,EAET,YAAY,MAAc,SAAiB;AACzC,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AAAA,EACd;AACF;;;ACfA;AAwCO,IAAM,gBAAgB;AAAA,EAC3B,2BAA2B;AAAA,IACzB,EAAE,MAAM,QAAe,MAAM,UAAU;AAAA,IACvC,EAAE,MAAM,MAAe,MAAM,UAAU;AAAA,IACvC,EAAE,MAAM,SAAe,MAAM,UAAU;AAAA,IACvC,EAAE,MAAM,cAAe,MAAM,UAAU;AAAA,IACvC,EAAE,MAAM,eAAe,MAAM,UAAU;AAAA,IACvC,EAAE,MAAM,SAAe,MAAM,UAAU;AAAA,EACzC;AACF;AAEO,SAAS,sBACd,MACyC;AACzC,QAAM,aAAa,KAAK,cAAc;AACtC,QAAM,cACJ,KAAK,gBAAgB,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI,MAAM,SAAS;AAEtE,QAAM,gBAAsC;AAAA,IAC1C,MAAM,KAAK;AAAA,IACX,IAAI,KAAK;AAAA,IACT,OAAO,KAAK;AAAA,IACZ;AAAA,IACA;AAAA,IACA,OAAO,KAAK;AAAA,EACd;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,mBAAmB,KAAK;AAAA,IAC1B;AAAA,IACA,OAAO;AAAA,IACP,aAAa;AAAA,IACb,SAAS;AAAA,EACX;AACF;;;AC9EA;;;ACAA;AAiCO,IAAM,mBAAmB;AAAA,EAC9B,eAAe;AAAA,IACb,EAAE,MAAM,QAAY,MAAM,UAAU;AAAA,IACpC,EAAE,MAAM,MAAY,MAAM,UAAU;AAAA,IACpC,EAAE,MAAM,UAAY,MAAM,UAAU;AAAA,IACpC,EAAE,MAAM,SAAY,MAAM,UAAU;AAAA,IACpC,EAAE,MAAM,WAAY,MAAM,SAAU;AAAA,IACpC,EAAE,MAAM,SAAY,MAAM,UAAU;AAAA,IACpC,EAAE,MAAM,YAAY,MAAM,UAAU;AAAA,EACtC;AACF;AAEO,IAAM,kBAAkB;AACxB,IAAM,qBAAqB;AAE3B,SAAS,wBACd,MACqC;AACrC,QAAM,SAA2B;AAAA,IAC/B,MAAM,KAAK;AAAA,IACX,IAAI,KAAK;AAAA,IACT,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK;AAAA,IACZ,SAAS,KAAK;AAAA,IACd,OAAO,KAAK;AAAA,IACZ,UAAU,KAAK;AAAA,EACjB;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,KAAK;AAAA,IAChB;AAAA,IACA,OAAO;AAAA,IACP,aAAa;AAAA,IACb,SAAS;AAAA,EACX;AACF;;;ACvEA;;;ACAA;;;ACAA;AAaA,oBAA+B;AAC/B,IAAAC,eAAqC;AAU9B,IAAM,aAAN,MAA0C;AAAA,EAC9B;AAAA,EACA;AAAA,EAEjB,YAAY,WAAmB,UAA6B,CAAC,GAAG;AAC9D,SAAK,YAAY;AACjB,SAAK,mBAAmB,QAAQ,qBAAqB,MAAM;AAAA,EAC7D;AAAA,EAEA,MAAM,gBAAiC;AACrC,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,MAAM,mBAA2C;AAC/C,UAAM,KAAK,KAAK,iBAAiB;AACjC,WAAO,KAAK,GAAG,UAAU,SAAS,IAAI;AAAA,EACxC;AAAA,EAEA,MAAM,cAAwB,UAAwD;AAIpF,UAAM,eAAiE,CAAC;AACxE,eAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,SAAS,KAAK,GAAG;AAC1D,mBAAa,GAAG,IAAI,CAAC,GAAG,MAAM;AAAA,IAChC;AACA,WAAO,KAAK,UAAU;AAAA,MACpB,SAAS;AAAA,MACT;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,MAKL;AAClB,UAAM,QAAQ,mBAAmB,KAAK,OAAO;AAC7C,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,uCAAuC,KAAK,OAAO,EAAE;AAAA,IACvE;AACA,UAAM,WAAW,IAAI,qBAAO,gBAAgB,MAAM,GAAG;AACrD,UAAM,YAAY,KAAK,UAAU,QAAQ,QAAQ;AACjD,UAAM,KAAK,MAAM,UAAU,gBAAgB;AAAA,MACzC,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,OAAO,KAAK,QAAQ,OAAO,KAAK,KAAK,IAAI;AAAA,IAC3C,CAAC;AACD,WAAO,GAAG;AAAA,EACZ;AAAA,EAEA,MAAM,sBAAsB,MAGR;AAClB,UAAM,KAAK,KAAK,iBAAiB;AACjC,QAAI,CAAC,IAAI;AACP,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AACA,UAAM,KAAK,yBAAY,KAAK,OAAO,KAAK,KAAK,mBAAmB,QAAQ,CAAC;AACzE,QAAI,KAAK,aAAa;AACpB,SAAG,YAAY,EAAE;AAAA,IACnB,OAAO;AACL,SAAG,KAAK,EAAE;AAAA,IACZ;AACA,WAAO,GAAG,UAAU,EAAE,sBAAsB,MAAM,CAAC,EAAE,SAAS,QAAQ;AAAA,EACxE;AACF;AAGA,SAAS,mBAAmB,SAA8C;AACxE,aAAW,OAAO,OAAO,OAAO,MAAM,GAAG;AACvC,QAAK,IAA6B,YAAY,SAAS;AACrD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;;;ACvGA;AAkBA,yBAA2B;AAC3B,sBAAiC;AACjC,IAAAC,aAAwB;AACxB,IAAAC,eAAqB;;;ACrBrB;AAcA,2BAAsB;;;ACdtB;AAyCA,IAAM,OAAuC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,EAAE;AAEzE,SAAS,eAAe,GAAuC;AAC7D,QAAM,KAAK,KAAK,IAAI,YAAY;AAChC,SAAO,MAAM,UAAU,MAAM,UAAU,IAAI;AAC7C;AAEA,IAAI,QAAwB,eAAe,QAAQ,IAAI,mBAAmB;AAI1E,IAAI,OAAsB,CAAC,SAAS;AAClC,UAAQ,OAAO,MAAM,OAAO,IAAI;AAClC;AAiBA,SAAS,WAAW,MAAiC;AACnD,SAAO,KAAK,KAAK,KAAK,KAAK,IAAI;AACjC;AAEA,SAAS,OAAO,OAAe,QAAyC;AACtE,QAAM,QAAQ,CAAC,qBAAqB,OAAO,OAAO,EAAE,GAAG,KAAK;AAC5D,MAAI,OAAO,KAAM,OAAM,KAAK,QAAQ,OAAO,IAAI,EAAE;AACjD,MAAI,OAAO,KAAM,OAAM,KAAK,QAAQ,OAAO,IAAI,EAAE;AACjD,MAAI,OAAO,OAAO,OAAO,SAAU,OAAM,KAAK,GAAG,OAAO,EAAE,IAAI;AAC9D,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAE3C,QAAI,CAAC,MAAM,SAAS,SAAS,QAAQ,QAAQ,IAAI,EAAE,SAAS,CAAC,EAAG;AAChE,UAAM,KAAK,GAAG,CAAC,IAAI,OAAO,MAAM,WAAW,IAAI,KAAK,UAAU,CAAC,CAAC,EAAE;AAAA,EACpE;AACA,SAAO,MAAM,KAAK,GAAG;AACvB;AAEA,SAAS,KAAK,KAAuB,OAAe,QAAuC;AACzF,MAAI,CAAC,WAAW,GAAG,EAAG;AACtB,QAAM,OAAuB,EAAE,KAAI,oBAAI,KAAK,GAAE,YAAY,GAAG,OAAO,KAAK,OAAO,GAAG,OAAO;AAC1F,MAAI;AACF,SAAK,OAAO,OAAO,IAAI,GAAG,IAAI;AAAA,EAChC,QAAQ;AAAA,EAER;AACF;AAEO,IAAM,YAAY;AAAA,EACvB,MAAM,CAAC,OAAe,SAAkC,CAAC,MAAY,KAAK,QAAQ,OAAO,MAAM;AAAA,EAC/F,OAAO,CAAC,OAAe,SAAkC,CAAC,MAAY,KAAK,SAAS,OAAO,MAAM;AAAA;AAAA,EAEjG,SAAS,MAAe,UAAU;AACpC;AASA,eAAsB,SACpB,MACA,MACA,IACY;AACZ,MAAI,CAAC,UAAU,QAAQ,EAAG,QAAO,GAAG;AACpC,QAAM,KAAK,KAAK,IAAI;AACpB,YAAU,MAAM,cAAc,EAAE,MAAM,KAAK,CAAC;AAC5C,MAAI;AACF,UAAM,MAAM,MAAM,GAAG;AACrB,cAAU,KAAK,YAAY,EAAE,MAAM,MAAM,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,KAAK,CAAC;AACxE,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,cAAU,KAAK,YAAY;AAAA,MACzB;AAAA,MACA;AAAA,MACA,IAAI,KAAK,IAAI,IAAI;AAAA,MACjB,IAAI;AAAA,MACJ,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACtD,CAAC;AACD,UAAM;AAAA,EACR;AACF;;;ADpHO,IAAM,cAAc,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,UAAU,KAA2C;AACnE,SAAO,OAAO;AAAA,IACZ,OAAO,QAAQ,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,YAAY,IAAI,CAAC,CAAC;AAAA,EACxD;AACF;AAwBA,SAAS,iBAAiB,QAAyD;AACjF,MAAI,MAAM;AACV,SAAO,CAAC,UAAkB;AACxB,WAAO,MAAM,SAAS,OAAO;AAC7B,QAAI;AACJ,YAAQ,KAAK,IAAI,QAAQ,IAAI,OAAO,IAAI;AACtC,aAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AACvB,YAAM,IAAI,MAAM,KAAK,CAAC;AAAA,IACxB;AAAA,EACF;AACF;AAiBA,SAAS,WAAW,MAAc,MAAkC;AAClE,QAAM,OAAO,QAAQ,IAAI;AACzB,QAAM,OAAO,QAAQ,IAAI;AACzB,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO,CAAC;AAC5B,QAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACjD,MAAI,CAAC,MAAM,SAAS,KAAK,KAAK,CAAC,MAAM,SAAS,IAAI,EAAG,QAAO,CAAC;AAC7D,QAAM,MAAM,QAAQ,IAAI,mCAAmC;AAC3D,QAAM,OAAO,GAAG,QAAQ,QAAQ,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,GAAG,QAAQ,oBAAoB,GAAG;AACxF,QAAM,MAAM,GAAG,GAAG,gBAAgB,IAAI;AAItC,YAAU,KAAK,eAAe,EAAE,MAAM,MAAM,IAAI,CAAC;AACjD,SAAO;AAAA,IACL,cAAc,aAAa,IAAI;AAAA,IAC/B,0BAA0B;AAAA,EAC5B;AACF;AAMO,IAAM,SAAoB,CAAC,MAAM,OAAO,CAAC,MAAM;AACpD,QAAM,MAAM,KAAK,OAAO;AACxB,QAAM,OAAO,KAAK,QAAQ,KAAK,CAAC,KAAK;AACrC,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAU,CAAC,SAAiB;AAChC,UAAM,KAAK,IAAI;AAKf,cAAU,MAAM,YAAY;AAAA,MAC1B,MAAM,KAAK;AAAA,MAAM;AAAA,MAAM,IAAI,KAAK,IAAI,IAAI;AAAA,MAAW,SAAS,KAAK,MAAM,GAAG,GAAG;AAAA,IAC/E,CAAC;AACD,SAAK,SAAS,IAAI;AAAA,EACpB;AAEA,YAAU,MAAM,cAAc,EAAE,MAAM,KAAK,MAAM,KAAK,CAAC;AAEvD,SAAO,IAAI,QAAsB,CAACC,UAAS,WAAW;AACpD,UAAM,YAAQ,4BAAM,KAAK,MAAM;AAAA,MAC7B,KAAK,EAAE,GAAG,UAAU,QAAQ,GAAG,GAAG,GAAG,WAAW,MAAM,KAAK,IAAI,GAAG,GAAI,KAAK,OAAO,CAAC,EAAG;AAAA,IACxF,CAAC;AAED,QAAI,KAAK,QAAQ;AACf,UAAI,KAAK,OAAO,QAAS,OAAM,KAAK,SAAS;AAC7C,WAAK,OAAO,iBAAiB,SAAS,MAAM,MAAM,KAAK,SAAS,GAAG,EAAE,MAAM,KAAK,CAAC;AAAA,IACnF;AAMA,QAAI,UAAU;AACd,UAAM,UAAU,CAAC,WAA0B,CAAC,UAAkB;AAC5D,YAAM,KAAK,KAAK,IAAI,IAAI;AACxB,UAAI,CAAC,SAAS;AACZ,kBAAU;AACV,kBAAU,MAAM,iBAAiB,EAAE,MAAM,KAAK,MAAM,MAAM,GAAG,CAAC;AAAA,MAChE;AACA,gBAAU,MAAM,aAAa,EAAE,MAAM,KAAK,MAAM,MAAM,IAAI,QAAQ,OAAO,MAAM,OAAO,CAAC;AAAA,IACzF;AAEA,UAAM,WAAW,iBAAiB,OAAO;AACzC,UAAM,WAAW,iBAAiB,OAAO;AACzC,UAAM,QAAQ,GAAG,QAAQ,QAAQ,KAAK,CAAC;AACvC,UAAM,QAAQ,GAAG,QAAQ,QAAQ,KAAK,CAAC;AACvC,UAAM,QAAQ,GAAG,QAAQ,QAAQ;AACjC,UAAM,QAAQ,GAAG,QAAQ,QAAQ;AAEjC,UAAM,GAAG,SAAS,CAAC,QAAQ;AACzB,gBAAU,KAAK,YAAY;AAAA,QACzB,MAAM,KAAK;AAAA,QAAM;AAAA,QAAM,IAAI,KAAK,IAAI,IAAI;AAAA,QAAW,IAAI;AAAA,QAAO,KAAK,IAAI;AAAA,MACzE,CAAC;AACD,aAAO,GAAG;AAAA,IACZ,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,gBAAU,KAAK,YAAY;AAAA,QACzB,MAAM,KAAK;AAAA,QAAM;AAAA,QAAM,IAAI,KAAK,IAAI,IAAI;AAAA,QAAW,KAAK,QAAQ,OAAO;AAAA,QAAG,MAAM,QAAQ;AAAA,MAC1F,CAAC;AACD,MAAAA,SAAQ,EAAE,UAAU,QAAQ,GAAG,MAAM,CAAC;AAAA,IACxC,CAAC;AAAA,EACH,CAAC;AACH;;;AE3KA;AAiBA,IAAAC,wBAAyB;AACzB,kBAA0B;;;AClB1B;AAkBO,IAAM,yBAAN,cAAqC,cAAc;AAAA,EACxD,YAAY,SAAiB;AAC3B,UAAM,wBAAwB,OAAO;AACrC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,wBAAN,cAAoC,cAAc;AAAA,EACvD,YAAY,SAAiB;AAC3B,UAAM,sBAAsB,OAAO;AACnC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,wBAAN,cAAoC,cAAc;AAAA,EACvD,YAAY,UAAU,wDAAwD;AAC5E,UAAM,6BAA6B,OAAO;AAC1C,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,6BAAN,cAAyC,cAAc;AAAA,EAC5D,YAAY,SAAiB;AAC3B,UAAM,2BAA2B,OAAO;AACxC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,4BAAN,cAAwC,cAAc;AAAA,EAC3D,YAAY,SAAiB;AAC3B,UAAM,0BAA0B,OAAO;AACvC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,cAAkC,cAAc;AAAA,EACrD,YAAY,SAAiB;AAC3B,UAAM,mBAAmB,OAAO;AAChC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,uBAAN,cAAmC,cAAc;AAAA,EACtD,YAA4B,MAAc,SAAkB;AAC1D,UAAM,oBAAoB,WAAW,iCAAiC,IAAI,EAAE;AADlD;AAE1B,SAAK,OAAO;AAAA,EACd;AACF;;;AD5CA,IAAM,oBAAgB,uBAAU,8BAAQ;AAGjC,IAAM,kBAAkB;AAGxB,SAAS,SAAS,GAAW,GAAoB;AACtD,QAAM,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAClD,QAAM,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAClD,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,IAAI,GAAG,CAAC,KAAK;AACnB,UAAM,IAAI,GAAG,CAAC,KAAK;AACnB,QAAI,MAAM,EAAG,QAAO,IAAI;AAAA,EAC1B;AACA,SAAO;AACT;AAGO,SAAS,aAAa,QAA+B;AAC1D,SAAO,OAAO,MAAM,mBAAmB,IAAI,CAAC,KAAK;AACnD;AAKA,IAAM,oBAAmC,YAAY;AACnD,QAAM,EAAE,OAAO,IAAI,MAAM,cAAc,cAAc,CAAC,WAAW,CAAC;AAClE,SAAO;AACT;AAGA,eAAe,kBAAkBC,aAA4C;AAC3E,MAAI;AACJ,MAAI;AACF,aAAS,MAAMA,YAAW;AAAA,EAC5B,SAAS,GAAQ;AACf,QAAI,GAAG,SAAS,UAAU;AACxB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAEA,QAAM,UAAU,aAAa,MAAM;AACnC,MAAI,CAAC,WAAW,SAAS,SAAS,eAAe,GAAG;AAClD,UAAM,IAAI;AAAA,MACR,cAAc,WAAW,GAAG,uBAAkB,eAAe;AAAA,IAE/D;AAAA,EACF;AACA,SAAO;AACT;AAQA,IAAI,gBAA+B;AACnC,IAAI,WAAmC;AAiBvC,eAAsB,UAAUC,cAA4B,mBAAoC;AAE9F,MAAIA,gBAAe,mBAAmB;AACpC,WAAO,kBAAkBA,WAAU;AAAA,EACrC;AACA,MAAI,cAAe,QAAO;AAC1B,MAAI,CAAC,UAAU;AACb,eAAW,kBAAkBA,WAAU,EACpC,KAAK,CAAC,MAAM;AACX,sBAAgB;AAChB,aAAO;AAAA,IACT,CAAC,EACA,QAAQ,MAAM;AACb,iBAAW;AAAA,IACb,CAAC;AAAA,EACL;AACA,SAAO;AACT;;;AEpHA;AAyCO,IAAM,mBAAmB;AAGzB,IAAM,oBAAoB;AAGjC,SAAS,mBAAmB,UAA2B;AACrD,MAAI,aAAa,OAAW,QAAO,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,CAAC;AACnE,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,QAAQ,UAAa,IAAI,KAAK,MAAM,IAAI;AAC1C,UAAM,IAAI,OAAO,GAAG;AACpB,QAAI,OAAO,SAAS,CAAC,KAAK,KAAK,EAAG,QAAO,KAAK,MAAM,CAAC;AAAA,EACvD;AACA,SAAO;AACT;AAGA,SAAS,iBAAiB,UAA2B;AACnD,MAAI,aAAa,OAAW,QAAO,KAAK,IAAI,GAAG,QAAQ;AACvD,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,QAAQ,UAAa,IAAI,KAAK,MAAM,IAAI;AAC1C,UAAM,IAAI,OAAO,GAAG;AACpB,QAAI,OAAO,SAAS,CAAC,KAAK,KAAK,EAAG,QAAO;AAAA,EAC3C;AACA,SAAO;AACT;AAoBO,SAAS,YAAY,OAAgC;AAC1D,QAAM,MAAM,MAAM,KAAK,IAAI,EAAE,KAAK;AAClC,MAAI;AACF,UAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,QAAI,QAAQ,OAAO,SAAS,UAAU;AAEpC,UAAI,OAAO,KAAK,YAAY,WAAW;AACrC,YAAI,KAAK,QAAS,QAAO;AACzB,cAAM,MAAM,OAAO,KAAK,aAAa,EAAE,EAAE,YAAY;AACrD,YAAI,qCAAqC,KAAK,GAAG,EAAG,QAAO;AAC3D,YAAI,kDAAkD,KAAK,GAAG,EAAG,QAAO;AACxE,eAAO;AAAA,MACT;AAEA,UAAI,OAAO,KAAK,SAAS,aAAa;AACpC,YAAI,OAAO,KAAK,IAAI,MAAM,IAAK,QAAO;AACtC,cAAM,MAAM,GAAG,KAAK,WAAW,EAAE,GAAG,KAAK,UAAU,EAAE;AACrD,YAAI,qBAAqB,KAAK,GAAG,EAAG,QAAO;AAC3C,eAAO;AAAA,MACT;AASA,UAAI,OAAO,KAAK,SAAS,UAAU;AACjC,eAAO,mBAAmB,KAAK,IAAI;AAAA,MACrC;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO,mBAAmB,GAAG;AAC/B;AAcA,SAAS,mBAAmB,GAA0B;AACpD,QAAM,OAAO,EAAE,YAAY;AAC3B,MACE,gBAAgB,KAAK,CAAC,KACtB,yBAAyB,KAAK,CAAC,KAC/B,uDAAuD,KAAK,IAAI,EAChE,QAAO;AACT,MACE,sCAAsC,KAAK,IAAI,KAC/C,6BAA6B,KAAK,CAAC,EACnC,QAAO;AACT,MACE,wCAAwC,KAAK,IAAI,KACjD,qBAAqB,KAAK,CAAC,EAC3B,QAAO;AACT,SAAO;AACT;AAsCA,SAAS,aAAa,IAAY,QAAqC;AACrE,SAAO,IAAI,QAAc,CAACC,UAAS,WAAW;AAC5C,QAAI,QAAQ,QAAS,QAAO,OAAO,IAAI,MAAM,SAAS,CAAC;AACvD,UAAM,IAAI,WAAWA,UAAS,EAAE;AAChC,YAAQ;AAAA,MACN;AAAA,MACA,MAAM;AACJ,qBAAa,CAAC;AACd,eAAO,IAAI,MAAM,SAAS,CAAC;AAAA,MAC7B;AAAA,MACA,EAAE,MAAM,KAAK;AAAA,IACf;AAAA,EACF,CAAC;AACH;AAWA,IAAM,SAAS,uBAAO,QAAQ;AAS9B,eAAsB,UACpB,SACA,aACA,MACqB;AACrB,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,QAAQ,KAAK,SAAS;AAC5B,QAAM,MAAM,KAAK,OAAO,KAAK;AAC7B,QAAM,cAAc,mBAAmB,KAAK,WAAW;AACvD,QAAM,YAAY,iBAAiB,KAAK,gBAAgB;AACxD,QAAM,OAAO;AAAA,IACX;AAAA,IAA4B;AAAA,IAAM;AAAA,IAAS;AAAA,IAAM;AAAA,IACjD,GAAI,KAAK,SAAS,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC;AAAA,IACzC,GAAI,KAAK,OAAO,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC;AAAA,EACvC;AAMA,QAAM,WAAW,IAAI,gBAAgB;AACrC,QAAM,SAAS,KAAK,SAAS,YAAY,IAAI,CAAC,KAAK,QAAQ,SAAS,MAAM,CAAC,IAAI,SAAS;AAExF,MAAI,OAAO;AACX,MAAI,aAAa;AACjB,QAAMC,YAAW,oBAAI,IAAyB;AAE9C,QAAM,SAAS,MAAY;AACzB,YAAQ;AACR,UAAM,SAAS;AACf,iBAAa,IAAI;AACjB,UAAM,OAAO,YAAiC;AAS5C,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,MAAM;AAAA,QACnC;AAAA,QAAQ,MAAM;AAAA,QAAwB,MAAM;AAAA,MAC9C,CAAC;AACD,YAAM,SAAS,YAAY,KAAK;AAChC,gBAAU,MAAM,aAAa,EAAE,MAAM,SAAS,MAAM,QAAQ,OAAO,CAAC;AACpE,aAAO,EAAE,QAAQ,MAAM;AAAA,IACzB,GAAG;AAGH,UAAM,UAA+B,IAAI,QAAQ,MAAM;AAAE,MAAAA,UAAS,OAAO,OAAO;AAAA,IAAG,CAAC;AACpF,IAAAA,UAAS,IAAI,OAAO;AAAA,EACtB;AAEA,MAAI;AACF,eAAS;AACP,UAAI,KAAK,QAAQ,QAAS,OAAM,IAAI,MAAM,SAAS;AACnD,YAAM,UAAU,IAAI,KAAK,KAAK;AAI9B,UAAI,WAAWA,UAAS,SAAS,GAAG;AAClC,cAAM,IAAI;AAAA,UACR,WAAW,OAAO;AAAA,QACpB;AAAA,MACF;AAGA,aAAO,CAAC,WAAWA,UAAS,OAAO,eAAe,IAAI,IAAI,cAAc,WAAW;AACjF,eAAO;AAAA,MACT;AAEA,YAAM,UAAsD,CAAC,GAAGA,SAAQ;AACxE,UAAI,CAAC,WAAWA,UAAS,OAAO,aAAa;AAE3C,cAAM,YAAY,KAAK,IAAI,GAAG,aAAa,IAAI,IAAI,WAAW;AAK9D,gBAAQ,KAAK,MAAM,WAAW,MAAM,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,CAAC;AAAA,MACxE;AAIA,YAAM,SAAS,MAAM,QAAQ,KAAK,OAAO;AACzC,UAAI,WAAW,OAAQ;AACvB,UAAI,OAAO,WAAW,OAAQ,QAAO,EAAE,QAAQ,QAAQ,OAAO,OAAO,MAAM;AAC3E,UAAI,OAAO,WAAW,YAAY;AAChC,cAAM,IAAI,2BAA2B,WAAW,OAAO,eAAe;AAAA,MACxE;AAAA,IAEF;AAAA,EACF,UAAE;AAGA,aAAS,MAAM;AACf,eAAW,KAAKA,UAAU,GAAE,MAAM,MAAM,MAAS;AAAA,EACnD;AACF;;;ALnOA,IAAM,cAAc;AAMb,SAAS,iBAAiB,UAAmB,YAA6B;AAC/E,SAAO,YAAY,kBAAc,+BAAW;AAC9C;AAGO,SAAS,cAAc,GAAiB;AAC7C,MAAI,CAAC,YAAY,KAAK,CAAC,GAAG;AACxB,UAAM,IAAI,oBAAoB,uCAAuC,CAAC,EAAE;AAAA,EAC1E;AACF;AAGO,SAAS,aAAa,OAAgC;AAC3D,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,MAAM,gCAAgC;AAC3D,QAAI,QAAS,QAAO,QAAQ,CAAC;AAC7B,UAAM,OAAO,KAAK,MAAM,cAAc;AACtC,QAAI,KAAM,QAAO,KAAK,CAAC;AAAA,EACzB;AACA,SAAO;AACT;AAGO,SAAS,gBAAgB,OAA+D;AAC7F,MAAI;AACJ,MAAI;AACJ,aAAW,QAAQ,OAAO;AACxB,UAAM,IAAI,KAAK,MAAM,oCAAoC;AACzD,QAAI,CAAC,EAAG;AAIR,UAAM,MAAM,EAAE,CAAC,EAAE,QAAQ,aAAa,EAAE;AACxC,QAAI,+BAA+B,KAAK,IAAI,KAAK,CAAC,WAAY,cAAa;AAAA,aAClE,CAAC,WAAY,cAAa;AAAA,EACrC;AAEA,MAAI,CAAC,cAAc,WAAY,cAAa;AAC5C,SAAO,EAAE,YAAY,WAAW;AAClC;AAGO,SAAS,aAAa,MAA6B;AACxD,QAAM,IAAI,KAAK,MAAM,wBAAwB;AAC7C,SAAO,IAAI,EAAE,CAAC,IAAI;AACpB;AAUO,SAAS,cAAc,OAA0B;AACtD,QAAM,OAAO,MAAM,KAAK,IAAI,EAAE,KAAK;AACnC,MAAI;AACF,UAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,QAAI,QAAQ,OAAO,KAAK,SAAS,YAAa,QAAO,OAAO,KAAK,IAAI,MAAM;AAAA,EAC7E,QAAQ;AAAA,EAER;AACA,SAAO,CAAC,yEAAyE,KAAK,IAAI;AAC5F;AAYA,SAAS,0BAA0B,QAAoC;AACrE,QAAM,QAAQ,OAAO,OAAO,OAAO;AACnC,QAAM,QAAQ,OAAO,QAAQ,KAAK,UAAU,KAAK,IAAI,KAAK;AAC1D,MAAI,UAAU,GAAI,QAAO;AACzB,MAAI,QAAQ,GAAG,QAAQ,OAAO,MAAM;AACpC,WAAS,IAAI,OAAO,IAAI,OAAO,QAAQ,KAAK;AAC1C,UAAM,KAAK,OAAO,CAAC;AACnB,QAAI,OAAO;AACT,UAAI,IAAK,OAAM;AAAA,eACN,OAAO,KAAM,OAAM;AAAA,eACnB,OAAO,IAAK,SAAQ;AAC7B;AAAA,IACF;AACA,QAAI,OAAO,IAAK,SAAQ;AAAA,aACf,OAAO,IAAK;AAAA,aACZ,OAAO,OAAO,EAAE,UAAU,GAAG;AACpC,YAAM,QAAQ,OAAO,MAAM,OAAO,IAAI,CAAC;AACvC,UAAI;AACF,cAAM,MAAM,KAAK,MAAM,KAAK;AAC5B,cAAM,IAAI,KAAK,oBAAoB,KAAK,UAAU,KAAK,QAAQ,KAAK,QAAQ;AAC5E,eAAO,OAAO,MAAM,WAAW,IAAI,KAAK,UAAU,CAAC;AAAA,MACrD,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAWO,SAAS,YAAY,OAAyB;AACnD,QAAM,OAAO,MAAM,KAAK,IAAI,EAAE,KAAK;AACnC,MAAI;AACF,UAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,QAAI,QAAQ,OAAO,SAAS,UAAU;AAQpC,UAAI,KAAK,qBAAqB,UAAa,KAAK,qBAAqB,MAAM;AACzE,cAAM,KAAK,KAAK;AAChB,cAAM,IAAK,OAAO,OAAO,WACpB,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,KACpC;AACJ,eAAO,OAAO,MAAM,WAAW,IAAI,KAAK,UAAU,CAAC;AAAA,MACrD;AAEA,UAAI,OAAO,KAAK,SAAS,UAAU;AACjC,cAAM,QAAQ,0BAA0B,KAAK,IAAI;AACjD,eAAO,SAAS,KAAK;AAAA,MACvB;AACA,YAAM,OAAO,KAAK,QAAQ,KAAK,UAAU,KAAK,QAAQ,KAAK;AAC3D,UAAI,SAAS,OAAW,QAAO,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,IAAI;AACpF,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AACA,QAAM,MAAM,MAAM,UAAU,CAAC,MAAM,YAAY,KAAK,CAAC,CAAC;AACtD,MAAI,QAAQ,IAAI;AACd,UAAM,QAAQ,MAAM,GAAG,EAAE,QAAQ,gBAAgB,EAAE;AACnD,WAAO,CAAC,OAAO,GAAG,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE,KAAK;AAAA,EAC1D;AACA,SAAO,MAAM,OAAO,CAAC,MAAM,CAAC,2BAA2B,KAAK,CAAC,CAAC,EAAE,KAAK,IAAI,EAAE,KAAK;AAClF;AAUA,IAAM,wBAAwB,KAAK,KAAK;AAExC,SAAS,qBAA6B;AACpC,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,QAAQ,UAAa,IAAI,KAAK,MAAM,GAAI,QAAO;AACnD,QAAM,IAAI,OAAO,GAAG;AACpB,SAAO,OAAO,SAAS,CAAC,KAAK,KAAK,IAAI,IAAI;AAC5C;AAOA,IAAM,mBAAmB,oBAAI,IAAoB;AAoBjD,IAAM,wBAAwB,KAAK,KAAK;AAExC,SAAS,qBAA6B;AACpC,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,QAAQ,UAAa,IAAI,KAAK,MAAM,GAAI,QAAO;AACnD,QAAM,IAAI,OAAO,GAAG;AACpB,SAAO,OAAO,SAAS,CAAC,KAAK,KAAK,IAAI,IAAI;AAC5C;AAIA,IAAM,kBAAkB,oBAAI,IAAoB;AAOzC,IAAM,eAAN,MAAmB;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAEjB,YAAY,OAA4B,CAAC,GAAG;AAC1C,SAAK,YAAY,iBAAiB,KAAK,WAAW,QAAQ,IAAI,gBAAgB;AAC9E,SAAK,YAAY,KAAK,iBAAa,uBAAK,oBAAQ,GAAG,WAAW;AAC9D,SAAK,YAAY,KAAK,aAAa,QAAQ,IAAI,mBAAmB;AAClE,SAAK,SAAS,KAAK,UAAU;AAC7B,SAAK,aAAa,KAAK;AACvB,SAAK,MAAM,KAAK,OAAO,KAAK;AAC5B,SAAK,kBAAkB,KAAK,eAAe,CAAC,KAAK;AACjD,SAAK,kBAAkB,KAAK,eAAe,CAAC,KAAK;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YAAY,QAAsB,MAA8B;AACpE,UAAM,QAAQ,mBAAmB;AACjC,UAAM,WAAW,GAAG,KAAK,SAAS,KAAK,KAAK,SAAS;AACrD,UAAM,WAAW,KAAK,mBAAmB,QAAQ;AAEjD,QAAI,UAAU;AACZ,YAAM,QAAQ,iBAAiB,IAAI,QAAQ;AAC3C,UAAI,UAAU,UAAa,KAAK,IAAI,IAAI,OAAO;AAC7C,kBAAU,KAAK,gBAAgB,EAAE,MAAM,MAAM,gBAAgB,KAAK,MAAM,WAAW,QAAQ,KAAK,IAAI,EAAE,CAAC;AACvG;AAAA,MACF;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,EAAE,QAAQ,MAAM,gBAAgB,KAAK,CAAC;AAC5F,QAAI,CAAC,cAAc,KAAK,GAAG;AAKzB,UAAI,KAAK,gBAAiB,kBAAiB,OAAO,QAAQ;AAC1D,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,QAAI,UAAU;AACZ,uBAAiB,IAAI,UAAU,KAAK,IAAI,IAAI,KAAK;AACjD,gBAAU,KAAK,gBAAgB,EAAE,MAAM,MAAM,gBAAgB,KAAK,OAAO,aAAa,MAAM,CAAC;AAAA,IAC/F;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,OAAO,MAAsD;AACjE,UAAM,EAAE,aAAa,aAAa,OAAO,IAAI;AAC7C,UAAM,QAAS,YAAY,SAAS,CAAC;AACrC,UAAM,sBAAsB,OAAO,MAAM,yBAAyB,EAAE;AACpE,QAAI,CAAC,qBAAqB;AACxB,YAAM,IAAI,oBAAoB,wDAAwD;AAAA,IACxF;AAGA,UAAM,OAAO,KAAK;AAClB,UAAM,YAAY,KAAK,IAAI;AAC3B,cAAU,KAAK,cAAc,EAAE,MAAM,UAAU,YAAY,CAAC;AAG5D,UAAM,QAAkB,CAAC;AACzB,UAAM,SAAS,CAAC,SAAiB;AAC/B,YAAM,IAAI,aAAa,IAAI;AAC3B,UAAI,EAAG,OAAM,KAAK,CAAC;AAAA,UACd,MAAK,SAAS,IAAI;AAAA,IACzB;AAIA,UAAM,gBACJ,KAAK,eAAe,KAAK,KACzB,gBAAM,YAAY,UAAU,EAAE,IAAI,YAAY,SAAS,KAAK,GAAG,KAAK;AAGtE,UAAM,SAAS,cAAc,MAAM,MAAM,UAAU,KAAK,UAAU,CAAC;AAMnE,UAAM,cAAc,mBAAmB;AACvC,UAAM,YAAY,GAAG,KAAK,SAAS,KAAK,KAAK,SAAS;AACtD,UAAM,iBAAiB,KAAK,mBAAmB,cAAc;AAC7D,UAAM,cAAc,iBAAiB,gBAAgB,IAAI,SAAS,IAAI;AACtE,QAAI,gBAAgB,UAAa,KAAK,IAAI,IAAI,aAAa;AACzD,gBAAU,KAAK,gBAAgB,EAAE,MAAM,MAAM,kBAAkB,KAAK,MAAM,WAAW,cAAc,KAAK,IAAI,EAAE,CAAC;AAAA,IACjH,OAAO;AACL,YAAM,KAAK;AAAA,QACT;AAAA,UAAC;AAAA,UAAkB;AAAA,UAAgB,KAAK;AAAA,UAAW;AAAA,UAAoB;AAAA,UACrE;AAAA,UAAe,KAAK;AAAA,QAAS;AAAA,QAC/B,EAAE,QAAQ,QAAQ,MAAM,kBAAkB,KAAK;AAAA,MACjD;AACA,UAAI,gBAAgB;AAClB,wBAAgB,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW;AACvD,kBAAU,KAAK,gBAAgB,EAAE,MAAM,MAAM,kBAAkB,KAAK,OAAO,aAAa,YAAY,CAAC;AAAA,MACvG;AAAA,IACF;AAGA,UAAM,KAAK,YAAY,QAAQ,IAAI;AAGnC,UAAM,QAAQ,OAAO,MAAM,oBAAgB,+BAAW,CAAC;AACvD,UAAM,UAAM,mBAAK,KAAK,WAAW,QAAQ;AACzC,cAAM,uBAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,UAAM,oBAAgB,mBAAK,KAAK,OAAO,KAAK,MAAM;AAClD,cAAM,2BAAU,eAAe,qBAAqB,OAAO;AAK3D,UAAM,UAAU;AAAA,MAAC;AAAA,MAAiB;AAAA,MAAM;AAAA,MAAe;AAAA,MAAM;AAAA,MAC3D;AAAA,MAAM,KAAK;AAAA,MAAW;AAAA,MAAM;AAAA,MAAe;AAAA,MAAM,KAAK;AAAA,IAAS;AACjE,QAAI,KAAK,OAAQ,SAAQ,KAAK,MAAM,KAAK,MAAM;AAC/C,QAAI,KAAK,KAAM,SAAQ,KAAK,MAAM,KAAK,IAAI;AAC3C,UAAM,SAAS,MAAM,KAAK,OAAO,SAAS,EAAE,QAAQ,QAAQ,MAAM,iBAAiB,KAAK,CAAC;AAEzF,UAAM,UAAU,aAAa,OAAO,KAAK;AACzC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,oBAAoB,wCAAwC;AAAA,IACxE;AACA,kBAAc,OAAO;AAErB,UAAM,EAAE,YAAY,WAAW,IAAI,gBAAgB,OAAO,KAAK;AAC/D,QAAI,YAAY;AAId,gBAAU,KAAK,gBAAgB,EAAE,MAAM,SAAS,IAAI,KAAK,IAAI,IAAI,UAAU,CAAC;AAC5E,WAAK,mBAAmB,EAAE,YAAY,YAAY,QAAQ,CAAC;AAAA,IAC7D;AAGA,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,YAAY,YAAY,qBAAqB,KAAK,MAAM;AAC9D,UAAM,WAAW,KAAK,IAAI,KAAK,KAAK,aAAa;AACjD,UAAM,OAAO,MAAM,UAAU,SAAS,aAAa;AAAA;AAAA;AAAA,MAGjD;AAAA,MACA;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,KAAK,KAAK;AAAA;AAAA;AAAA,MAGV,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,IACb,CAAC;AAID,cAAU,KAAK,gBAAgB,EAAE,MAAM,SAAS,IAAI,KAAK,IAAI,IAAI,UAAU,CAAC;AAG5E,UAAM,OAAO,YAAY,KAAK,KAAK;AAGnC,SAAK,KAAK,OAAO,CAAC,6BAA6B,MAAM,OAAO,GAAG;AAAA,MAC7D;AAAA,MAAQ;AAAA,MAAQ,MAAM;AAAA,MAA6B;AAAA,IACrD,CAAC,EAAE,MAAM,MAAM,MAAS;AAExB,WAAO,EAAE,MAAM,SAAS,EAAE,SAAS,YAAY,MAAM,GAAG,MAAM;AAAA,EAChE;AACF;;;AM1eA;AAgBO,IAAM,cAAc;AA6BpB,SAAS,OAAO,KAAsC;AAC3D,MAAI,IAAI,WAAW,kBAAkB,IAAI,YAAY,YAAa,QAAO;AACzE,SAAO,mBAAmB,IAAI,OAAO,KAAK,IAAI;AAChD;AAEA,SAAS,SAAS,SAAoC,MAAoC;AACxF,QAAM,cAAc,QAAQ,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,IAAI;AAC1D,SAAO,cAAc,EAAE,MAAM,YAAY,IAAI;AAC/C;AASO,SAAS,WAAW,OAAuC;AAChE,QAAM,EAAE,eAAe,cAAc,YAAY,aAAa,IAAI;AAElE,MAAI,CAAC,iBAAiB,cAAc,WAAW,GAAG;AAChD,UAAM,IAAI,qBAAqB,gBAAgB,WAAW,mCAAmC;AAAA,EAC/F;AAGA,MAAI,cAAc;AAChB,UAAM,MAAM,SAAS,eAAe,YAAY;AAChD,QAAI,CAAC,KAAK;AACR,YAAM,UAAU,cAAc,IAAI,MAAM;AACxC,YAAM,IAAI;AAAA,QACR;AAAA,QACA,+BAA+B,YAAY,eAAe,QAAQ,KAAK,IAAI,CAAC;AAAA,MAC9E;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,MAAI,YAAY;AACd,eAAW,QAAQ,YAAY;AAC7B,YAAM,MAAM,SAAS,eAAe,IAAI;AACxC,UAAI,IAAK,QAAO;AAAA,IAClB;AAAA,EACF;AAGA,MAAI,cAAc,UAAU;AAC1B,UAAM,MAAM,cAAc,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,WAAW;AAC/D,QAAI,IAAK,QAAO,EAAE,MAAM,OAAO,GAAG,GAAG,aAAa,IAAI;AAAA,EACxD;AACA,MAAI,cAAc,aAAa;AAC7B,UAAM,MAAM,SAAS,eAAe,WAAW;AAC/C,QAAI,IAAK,QAAO;AAAA,EAClB;AAGA,SAAO,EAAE,MAAM,OAAO,cAAc,CAAC,CAAC,GAAG,aAAa,cAAc,CAAC,EAAE;AACzE;;;ACtGA;;;AxByEA,IAAM,iBAA+B;AAAA,EACnC,OAAO;AAAA,EACP,QAAQ;AAAA,IACN,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AACF;AAEO,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EACA;AAAA,EACA,aAAgC;AAAA,EAChC,SAAwB;AAAA,EACxB,SAA+B;AAAA,EAC/B,gBAAwB;AAAA,EACxB,oBAA4B;AAAA,EAC5B;AAAA,EACA;AAAA,EAER,YAAY,UAAiC,CAAC,GAAG;AAC/C,SAAK,YAAY,QAAQ,iBAAa,uBAAK,oBAAQ,GAAG,WAAW;AACjE,SAAK,SAAS,KAAK,WAAW;AAE9B,SAAK,iBAAiB,QAAQ,kBAAkB,KAAK,OAAO;AAC5D,SAAK,kBAAkB,QAAQ;AAC/B,SAAK,aAAa,KAAK,WAAW;AAClC,SAAK,aAAa;AAElB,QAAI,KAAK,YAAY;AACnB,WAAK,SAAS,IAAI,sBAAO,KAAK,WAAW,UAAU;AAGnD,YAAM,YAAY,KAAK;AACvB,WAAK,SAAS,IAAI,WAAW,KAAK,QAAQ;AAAA,QACxC,kBAAkB,MAAM,iBAAiB,SAAS;AAAA,MACpD,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,gBAAyB;AAC3B,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAyB;AAC3B,WAAO,KAAK,QAAQ,WAAW;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,YAA2B;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,YAA0B;AACxB,WAAO,EAAE,GAAG,KAAK,OAAO;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,SAAgD;AAC3D,QAAI,QAAQ,aAAa,QAAW;AAClC,WAAK,OAAO,OAAO,WAAW,QAAQ;AAAA,IACxC;AACA,QAAI,QAAQ,cAAc,QAAW;AACnC,WAAK,OAAO,OAAO,YAAY,QAAQ;AAAA,IACzC;AACA,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,WAA8C;AAE9D,UAAM,gBAAgB,UAAU,QAAQ,qDAAqD,EAAE;AAG/F,UAAM,YAAY,CAAC,aAAa,iBAAiB,oBAAoB;AAErE,eAAW,YAAY,WAAW;AAChC,UAAI;AACF,cAAM,MAAM,MAAM,MAAM,GAAG,aAAa,GAAG,QAAQ,EAAE;AACrD,YAAI,CAAC,IAAI,GAAI;AAEb,cAAM,cAAc,IAAI,QAAQ,IAAI,cAAc,KAAK;AACvD,YAAI,CAAC,YAAY,SAAS,kBAAkB,EAAG;AAE/C,eAAO,MAAM,IAAI,KAAK;AAAA,MACxB,QAAQ;AACN;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI,MAAM,sDAAsD,aAAa,EAAE;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,IACJ,WACA,SACA,QACA,UAAsB,CAAC,GACO;AAI9B,QAAI,QAAQ,SAAS,aAAa;AAChC,aAAO,KAAK,aAAa,WAAW,SAAS,QAAQ,OAAO;AAAA,IAC9D;AAEA,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,YAAY;AACpC,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AAGA,YAAQ,IAAI,kCAAkC,OAAO,EAAE;AACvD,QAAI,aAAa,GAAG,SAAS;AAE7B,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,YAAY,SAAS;AACjD,YAAM,MAAM,SAAS,UAAU,KAAK,CAAC,MAAW,EAAE,OAAO,OAAO;AAChE,UAAI,KAAK,UAAU;AAEjB,qBAAa,GAAG,SAAS,GAAG,IAAI,QAAQ;AACxC,gBAAQ,IAAI,sCAAsC,IAAI,QAAQ,EAAE;AAAA,MAClE;AAAA,IACF,QAAQ;AAAA,IAER;AAGA,QAAI;AACJ,QAAI,QAAQ,SAAS;AAEnB,oBAAc,EAAE,SAAS,GAAG,OAAO;AAAA,IACrC,OAAO;AAEL,oBAAc,EAAE,SAAS,OAAO;AAAA,IAClC;AACA,QAAI,QAAQ,OAAO;AACjB,kBAAY,QAAQ,QAAQ;AAAA,IAC9B;AACA,UAAM,aAAa,MAAM,MAAM,YAAY;AAAA,MACzC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,WAAW;AAAA,IAClC,CAAC;AAGD,QAAI,WAAW,WAAW,KAAK;AAC7B,YAAM,OAAO,MAAM,WAAW,KAAK;AACnC,UAAI,WAAW,MAAM,KAAK,QAAQ;AAChC,eAAO,KAAK;AAAA,MACd;AACA,YAAM,IAAI,MAAM,KAAK,SAAS,qBAAqB;AAAA,IACrD;AAIA,UAAM,gBAAgB,WAAW,QAAQ,IAAI,kBAAkB;AAC/D,UAAM,wBAAwB,WAAW,QAAQ,IAAI,uBAAuB;AAG5E,QAAI,iBAAiB,cAAc,YAAY,EAAE,SAAS,SAAS,GAAG;AACpE,cAAQ,IAAI,uDAAuD;AACnE,aAAO,MAAM,KAAK,iBAAiB,YAAY,SAAS,QAAQ,eAAe,OAAO;AAAA,IACxF;AAEA,QAAI,CAAC,uBAAuB;AAC1B,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AAEA,QAAI;AACJ,QAAI;AACF,YAAM,UAAU,OAAO,KAAK,uBAAuB,QAAQ,EAAE,SAAS,OAAO;AAC7E,YAAM,SAAS,KAAK,MAAM,OAAO;AAGjC,UAAI,MAAM,QAAQ,MAAM,GAAG;AAEzB,uBAAe;AAAA,MACjB,WAAW,OAAO,WAAW,MAAM,QAAQ,OAAO,OAAO,GAAG;AAE1D,uBAAe,OAAO;AAAA,MACxB,OAAO;AAEL,uBAAe,CAAC,MAAM;AAAA,MACxB;AAAA,IACF,QAAQ;AACN,YAAM,IAAI,MAAM,mCAAmC;AAAA,IACrD;AAGA,UAAM,eAAe,aAClB,IAAI,OAAK,mBAAuB,EAAE,OAAO,CAAC,EAC1C,OAAO,CAAC,MAA0B,MAAM,IAAI;AAG/C,UAAM,qBAAqB,QAAQ;AACnC,QAAI;AAEJ,QAAI,oBAAoB;AAEtB,UAAI,CAAC,aAAa,SAAS,kBAAkB,GAAG;AAC9C,cAAM,IAAI;AAAA,UACR,0BAA0B,kBAAkB;AAAA,kBACzB,aAAa,KAAK,IAAI,CAAC;AAAA,QAC5C;AAAA,MACF;AACA,sBAAgB;AAAA,IAClB,OAAO;AAEL,UAAI,aAAa,WAAW,KAAK,aAAa,CAAC,MAAM,QAAQ;AAE3D,wBAAgB;AAAA,MAClB,OAAO;AACL,cAAM,IAAI;AAAA,UACR,mBAAmB,aAAa,KAAK,IAAI,CAAC;AAAA;AAAA,QAE5C;AAAA,MACF;AAAA,IACF;AAGA,QAAI,kBAAkB,YAAY,kBAAkB,iBAAiB;AACnE,YAAM,cAAc;AACpB,YAAMC,WAAU,gBAAgB,WAAW,mBAAmB;AAC9D,YAAMC,OAAM,aAAa,KAAK,OAAK,EAAE,YAAYD,QAAO;AAExD,UAAI,CAACC,MAAK;AACR,cAAM,IAAI,MAAM,0CAA0C,aAAa,EAAE;AAAA,MAC3E;AAEA,aAAO,MAAM,KAAK,oBAAoB,YAAY,SAAS,QAAQA,MAAK,aAAa,OAAO;AAAA,IAC9F;AAGA,UAAM,YAAY;AAClB,UAAM,QAAQ,SAAS,SAAS;AAChC,UAAM,UAAU,UAAU,MAAM,OAAO;AACvC,UAAM,MAAM,aAAa,KAAK,OAAK,EAAE,WAAW,WAAW,EAAE,YAAY,OAAO;AAEhF,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,0CAA0C,SAAS,EAAE;AAAA,IACvE;AAIA,UAAM,YAAY,IAAI,UAAU,IAAI;AACpC,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AACA,UAAM,SAAS,OAAO,SAAS,IAAI;AACnC,SAAK,YAAY,MAAM;AAGvB,QAAI,QAAqB,QAAQ,SAAS;AAG1C,QAAI,QAAQ,YAAY;AACtB,YAAM,WAAW,MAAM,KAAK,WAAW;AACvC,UAAI,SAAS,QAAQ,QAAQ;AAC3B,gBAAQ;AAAA,MACV,WAAW,SAAS,QAAQ,QAAQ;AAClC,gBAAQ;AAAA,MACV,OAAO;AACL,cAAM,IAAI,MAAM,+BAA+B,MAAM,UAAU,SAAS,IAAI,WAAW,SAAS,IAAI,OAAO;AAAA,MAC7G;AAAA,IACF;AAIA,QAAI,UAAU,QAAQ;AACpB,YAAM,WAAW,MAAM,KAAK,WAAW;AACvC,UAAI,SAAS,SAAS,MAAQ;AAC5B,cAAM,IAAI;AAAA,UACR,iEACqB,SAAS,OAAO,QAAQ,CAAC,CAAC;AAAA,QAEjD;AAAA,MACF;AACA,cAAQ,IAAI,iFAAuE;AAAA,IACrF,OAAO;AACL,cAAQ,IAAI,gCAAgC,MAAM,IAAI,KAAK,YAAY;AAAA,IACzE;AAGA,QAAI,cAAc,SAAS,cAAc,eAAe;AACtD,cAAQ,IAAI,mDAAmD;AAC/D,YAAMC,SAAQ,IAAI,SAAS,IAAI;AAC/B,UAAI,CAACA,QAAO;AACV,cAAM,IAAI,MAAM,+CAA+C;AAAA,MACjE;AAEA,YAAM,aAAc,IAAI,OAAe;AACvC,UAAI,CAAC,YAAY;AACf,cAAM,IAAI,MAAM,iFAAiF;AAAA,MACnG;AACA,aAAO,MAAM,KAAK,iBAAiB,YAAY,SAAS,QAAQ;AAAA,QAC9D,IAAIA;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MACX,GAAG,OAAO;AAAA,IACZ;AAIA,UAAM,QAAQ,IAAI,SAAS,IAAI;AAC/B,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AAGA,UAAM,iBAAkB,IAAI,SAAS,OAAO,IAAI,UAAU,YAAY,IAAI,MAAM,OAC5E,EAAE,MAAM,IAAI,MAAM,MAAgB,SAAU,IAAI,MAAM,WAAsB,IAAI,IAChF;AAEJ,UAAM,gBAAgB,MAAM,KAAK,YAAY,OAAO,QAAQ,OAAO,OAAO,cAAc;AAGxF,UAAM,cAAc,MAAM,OAAO,KAAK;AAKtC,UAAM,QAAS,IAAI,SAAS,OAAO,IAAI,UAAU,WAC7C,IAAI,QACJ;AAAA,MACE,MAAO,YAAoB,cAAc;AAAA,MACzC,SAAS;AAAA,IACX;AAEJ,UAAM,UAAU;AAAA,MACd,aAAa;AAAA,MACb,QAAQ;AAAA,MACR;AAAA,MACA,SAAS;AAAA;AAAA,MACT,UAAU;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,QACA,OAAO,YAAY;AAAA,QACnB,QAAQ;AAAA,QACR;AAAA,QACA,mBAAmB,IAAI,qBAAqB;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AACA,UAAM,gBAAgB,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,SAAS,QAAQ;AAG5E,YAAQ,IAAI,4CAA4C;AACxD,UAAM,kBAAuB,QAAQ,UACjC,EAAE,SAAS,GAAG,OAAO,IACrB,EAAE,SAAS,OAAO;AACtB,QAAI,QAAQ,OAAO;AACjB,sBAAgB,QAAQ,QAAQ;AAAA,IAClC;AACA,UAAM,UAAU,MAAM,MAAM,YAAY;AAAA,MACtC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,CAAC,cAAc,GAAG;AAAA,MACpB;AAAA,MACA,MAAM,KAAK,UAAU,eAAe;AAAA,IACtC,CAAC;AAED,UAAM,SAAS,MAAM,QAAQ,KAAK;AAElC,QAAI,CAAC,QAAQ,IAAI;AACf,YAAM,IAAI,MAAM,OAAO,SAAS,0BAA0B;AAAA,IAC5D;AAGA,SAAK,eAAe,MAAM;AAE1B,YAAQ,IAAI,gCAAgC,OAAO,SAAS,UAAU,SAAS,EAAE;AAGjF,WAAO,OAAO,UAAU;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,aACZ,WACA,SACA,QACA,SAC8B;AAE9B,UAAM,OAAO,KAAK;AAGlB,QAAI,aAAa,GAAG,SAAS;AAC7B,QAAI;AACF,YAAM,WAAW,MAAM;AAAA,QAAS;AAAA,QAAqB;AAAA,QAAM,MACzD,KAAK,YAAY,SAAS;AAAA,MAC5B;AACA,YAAM,MAAM,SAAS,UAAU,KAAK,CAAC,MAAW,EAAE,OAAO,OAAO;AAChE,UAAI,KAAK,SAAU,cAAa,GAAG,SAAS,GAAG,IAAI,QAAQ;AAAA,IAC7D,QAAQ;AAAA,IAER;AAEA,UAAM,cAAmB,QAAQ,UAAU,EAAE,SAAS,GAAG,OAAO,IAAI,EAAE,SAAS,OAAO;AACtF,UAAM,WAAW,KAAK,UAAU,WAAW;AAG3C,UAAM,MAAM,MAAM;AAAA,MAAS;AAAA,MAAiB;AAAA,MAAM,MAChD,MAAM,YAAY;AAAA,QAChB,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,QAAI,IAAI,WAAW,KAAK;AACtB,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC9C,UAAI,IAAI,MAAO,KAAa,OAAQ,QAAQ,KAAa;AACzD,YAAM,IAAI,MAAO,KAAa,SAAS,qBAAqB,IAAI,MAAM,EAAE;AAAA,IAC1E;AAEA,UAAM,SAAS,IAAI,QAAQ,IAAI,uBAAuB;AACtD,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,0CAA0C;AACvE,UAAM,SAAS,KAAK,MAAM,OAAO,KAAK,QAAQ,QAAQ,EAAE,SAAS,OAAO,CAAC;AACzE,UAAM,UAAqC,MAAM,QAAQ,MAAM,IAC3D,SACA,OAAO,WAAW,CAAC,MAAM;AAG7B,UAAM,EAAE,YAAY,IAAI,WAAW;AAAA,MACjC,eAAe;AAAA,MACf,cAAc;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,cAAc,EAAE,UAAU,KAAK,cAAc;AAAA,IAC/C,CAAC;AAED,UAAM,SAAS,QAAQ,WAAW,CAAC,SAAiB,QAAQ,OAAO,MAAM,OAAO,IAAI;AACpF,UAAM,SAAS,IAAI,aAAa;AAAA,MAC9B,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,IAClB,CAAC;AACD,UAAM,SAAS,MAAM,OAAO,OAAO;AAAA,MACjC,aAAa;AAAA,MACb;AAAA,MACA,QAAQ;AAAA,MACR,MAAM;AAAA,MACN;AAAA,MACA,kBAAkB,QAAQ;AAAA,MAC1B,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAGD,QAAI;AACF,YAAM,OAAO,KAAK,MAAM,OAAO,IAAI;AACnC,aAAO,KAAK,UAAU;AAAA,IACxB,QAAQ;AACN,aAAO,EAAE,MAAM,OAAO,MAAM,SAAS,OAAO,SAAS,OAAO,OAAO,MAAM;AAAA,IAC3E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,iBACZ,YACA,SACA,QACA,eACA,UAAsB,CAAC,GACO;AAE9B,UAAM,EAAE,qBAAAC,qBAAoB,IAAI,MAAM,OAAO,eAAe;AAC5D,UAAM,EAAE,oBAAoB,oBAAoB,KAAK,IAAI,MAAM,OAAO,MAAM;AAC5E,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,aAAa;AACpD,UAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,YAAY;AAG7C,UAAM,aAAa,KAAK,WAAY;AACpC,UAAM,UAAUA,qBAAoB,UAAU;AAE9C,YAAQ,IAAI,wCAAwC;AACpD,YAAQ,IAAI,uBAAuB,QAAQ,OAAO,EAAE;AAGpD,UAAM,iBAAiB,CAAC,QAAgB,QAA+B;AACrE,YAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,GAAG,GAAG,cAAc,GAAG,CAAC;AAC9D,aAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,IAC5B;AAEA,UAAM,cAAc,eAAe,eAAe,IAAI;AACtD,UAAM,SAAS,eAAe,eAAe,QAAQ;AACrD,UAAM,QAAQ,eAAe,eAAe,OAAO;AACnD,UAAM,aAAa,eAAe,eAAe,SAAS;AAE1D,QAAI,WAAW,SAAS;AACtB,YAAM,IAAI,MAAM,+BAA+B,MAAM,EAAE;AAAA,IACzD;AAEA,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAGA,UAAM,cAAc,OAAO,KAAK,YAAY,QAAQ,EAAE,SAAS,OAAO;AACtE,UAAM,iBAAiB,KAAK,MAAM,WAAW;AAE7C,UAAM,EAAE,QAAQ,UAAU,WAAW,cAAc,IAAI;AACvD,UAAM,UAAU,eAAe,WAAW;AAC1C,UAAM,gBAAgB,OAAO,MAAM,IAAI;AAEvC,YAAQ,IAAI,wBAAwB,aAAa,OAAO,SAAS,EAAE;AAGnE,SAAK,YAAY,aAAa;AAG9B,YAAQ,IAAI,4CAA4C;AAExD,UAAM,aAAa,EAAE,GAAG,eAAe,UAAU,SAA0B;AAE3E,UAAM,eAAe,mBAAmB;AAAA,MACtC,OAAO;AAAA,MACP,WAAW,KAAK,gCAAgC;AAAA,IAClD,CAAC;AAED,UAAM,eAAe,mBAAmB;AAAA,MACtC;AAAA,MACA,OAAO;AAAA,MACP,WAAW,KAAK,gCAAgC;AAAA,IAClD,CAAC;AAGD,UAAM,SAAS,MAAM,QAAQ,MAAM,SAAS,cAAc;AAAA,MACxD,IAAI;AAAA,MACJ,QAAQ,OAAO,MAAM;AAAA,MACrB,OAAO;AAAA,IACT,CAAC;AAED,YAAQ,IAAI,2BAA2B,MAAM,EAAE;AAG/C,UAAM,aAAa,0BAA0B,EAAE,MAAM,OAAO,CAAC;AAC7D,YAAQ,IAAI,mDAAmD;AAG/D,UAAM,aAAa;AAAA,MACjB,WAAW;AAAA,QACT,IAAI;AAAA,QACJ;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,SAAS;AAAA,MACX;AAAA,MACA,SAAS,EAAE,MAAM,QAAQ,MAAM,OAAO;AAAA,MACtC,QAAQ,kBAAkB,OAAO,IAAI,QAAQ,OAAO;AAAA,IACtD;AAEA,UAAM,gBAAgB,OAAO,KAAK,KAAK,UAAU,UAAU,CAAC,EACzD,SAAS,QAAQ,EACjB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,EAAE;AAGpB,UAAM,YAAY,QAAQ,UACtB,EAAE,SAAS,GAAG,QAAQ,OAAO,iBAAiB,IAC9C,EAAE,SAAS,QAAQ,OAAO,iBAAiB;AAE/C,UAAM,UAAU,MAAM,MAAM,YAAY;AAAA,MACtC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB,WAAW,aAAa;AAAA,MAC3C;AAAA,MACA,MAAM,KAAK,UAAU,SAAS;AAAA,IAChC,CAAC;AAED,UAAM,SAAS,MAAM,QAAQ,KAAK;AAElC,QAAI,CAAC,QAAQ,IAAI;AACf,YAAM,IAAI,MAAM,OAAO,SAAS,6BAA6B;AAAA,IAC/D;AAGA,SAAK,eAAe,aAAa;AAEjC,YAAQ,IAAI,qBAAqB;AACjC,WAAO,OAAO,UAAU;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAc,iBACZ,YACA,SACA,QACA,gBAQA,UAAsB,CAAC,GACO;AAC9B,UAAM,EAAE,IAAI,QAAQ,OAAO,WAAW,OAAO,QAAQ,IAAI;AACzD,UAAM,cAAc,MAAM,OAAO,KAAK;AAGtC,UAAM,WAAW,IAAI,sBAAO,gBAAgB,MAAM,GAAG;AACrD,UAAM,YAAY,MAAM,KAAK,eAAe,YAAY,SAAS,SAAS,QAAQ;AAClF,UAAM,iBAAiB,OAAO,KAAK,MAAM,SAAU,MAAM,YAAY,QAAS,CAAC;AAE/E,QAAI,YAAY,gBAAgB;AAE9B,YAAM,gBAAgB,MAAM,SAAS,WAAW,KAAK,OAAQ,OAAO;AACpE,YAAM,gBAAgB,sBAAO,WAAW,QAAQ;AAEhD,UAAI,gBAAgB,eAAe;AACjC,cAAM,YAAY,WAAW,sBAAO,YAAY,aAAa,CAAC,EAAE,QAAQ,CAAC;AACzE,cAAM,YAAY,cAAc;AAEhC,YAAI,WAAW;AACb,gBAAM,IAAI;AAAA,YACR;AAAA;AAAA,mBACoB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,UAI/B;AAAA,QACF,OAAO;AACL,gBAAM,IAAI;AAAA,YACR;AAAA;AAAA,kBACmB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAMO,SAAS,cAAc,OAAO;AAAA,UACnE;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI;AAAA,QACR,8BAA8B,QAAQ,MAAM,GAAG,EAAE,CAAC;AAAA,oCACb,SAAS,cAAc,OAAO;AAAA,MACrE;AAAA,IACF;AAGA,UAAM,YAAY,OAAO,KAAK,MAAM,SAAU,MAAM,YAAY,QAAS,CAAC,EAAE,SAAS;AAGrF,UAAM,cAAc,KAAK,IAAI;AAC7B,UAAM,iBAAiB,KAAK,IAAI,IAAI;AACpC,UAAM,WAAW,wBAAwB;AAAA,MACvC,MAAM,KAAK,OAAQ;AAAA,MACnB;AAAA,MACA,QAAQ;AAAA,MACR,cAAc,YAAY;AAAA,MAC1B;AAAA,MACA,OAAO;AAAA,MACP,UAAU;AAAA,MACV,SAAS,MAAM;AAAA,IACjB,CAAC;AAED,YAAQ,IAAI,0CAA0C;AACtD,UAAM,YAAY,MAAM,KAAK,OAAQ,cAAc,QAAQ;AAC3D,UAAM,SAAS,SAAS;AAGxB,UAAM,UAAU,UAAU,MAAM,OAAO;AACvC,UAAM,UAAU;AAAA,MACd,aAAa;AAAA,MACb,QAAQ;AAAA,MACR;AAAA,MACA,SAAS;AAAA,QACP,QAAQ;AAAA,UACN,GAAG;AAAA,UACH;AAAA,QACF;AAAA,QACA,SAAS,MAAM;AAAA,MACjB;AAAA,MACA,UAAU;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,QACA,OAAO,YAAY;AAAA,QACnB,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,mBAAmB;AAAA,MACrB;AAAA,IACF;AAEA,UAAM,gBAAgB,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,SAAS,QAAQ;AAG5E,YAAQ,IAAI,2CAA2C;AACvD,UAAM,iBAAiB,QAAQ,UAC3B,EAAE,SAAS,GAAG,QAAQ,OAAO,UAAU,IACvC,EAAE,SAAS,QAAQ,OAAO,UAAU;AACxC,UAAM,UAAU,MAAM,MAAM,YAAY;AAAA,MACtC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,aAAa;AAAA,MACf;AAAA,MACA,MAAM,KAAK,UAAU,cAAc;AAAA,IACrC,CAAC;AAED,UAAM,SAAS,MAAM,QAAQ,KAAK;AAElC,QAAI,CAAC,QAAQ,IAAI;AACf,YAAM,IAAI,MAAM,OAAO,SAAS,oBAAoB;AAAA,IACtD;AAGA,SAAK,eAAe,MAAM;AAE1B,YAAQ,IAAI,0CAA0C;AACtD,WAAO,OAAO,UAAU;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,oBACZ,YACA,SACA,QACA,cACA,OACA,UAAsB,CAAC,GACO;AAE9B,UAAM,eAAe,iBAAiB,KAAK,SAAS;AACpD,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,sEAAsE;AAAA,IACxF;AAEA,UAAM,SAAS,OAAO,aAAa,MAAM;AACzC,UAAM,aAAa,SAAS;AAG5B,SAAK,YAAY,UAAU;AAE3B,YAAQ,IAAI,wCAAwC,UAAU,OAAO;AAGrE,QAAI,CAAC,aAAa,OAAO;AACvB,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AAGA,UAAM,iBAAkB,aAAa,OAAe;AACpD,UAAM,iBAAiB,iBAAiB,IAAI,uBAAU,cAAc,IAAI;AAExE,QAAI,gBAAgB;AAClB,cAAQ,IAAI,2CAA2C;AAAA,IACzD;AAGA,UAAM,kBAAkB,IAAI,uBAAU,aAAa,KAAK;AACxD,UAAM,cAAc,MAAM;AAAA,MACxB,aAAa;AAAA,MACb;AAAA,MACA,OAAO,MAAM;AAAA,MACb;AAAA,MACA;AAAA;AAAA,IACF;AAKA,UAAM,iBAAiB,YACpB,UAAU,EAAE,sBAAsB,OAAO,kBAAkB,MAAM,CAAC,EAClE,SAAS,QAAQ;AACpB,UAAM,WAAW,MAAM,KAAK,OAAQ,sBAAuB;AAAA,MACzD,mBAAmB;AAAA,MACnB,aAAa,CAAC,CAAC;AAAA,IACjB,CAAC;AAED,YAAQ,IAAI,qDAAqD;AAGjE,UAAM,UAAU,UAAU,WAAW,mBAAmB;AACxD,UAAM,UAAU;AAAA,MACd,aAAa;AAAA,MACb,QAAQ;AAAA,MACR;AAAA,MACA,SAAS;AAAA,QACP,mBAAmB;AAAA,QACnB,QAAQ,aAAa,UAAU,SAAS;AAAA,QACxC;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,QACA,OAAO,aAAa;AAAA,QACpB,QAAQ,aAAa;AAAA,QACrB,OAAO,aAAa;AAAA,QACpB,mBAAmB;AAAA,MACrB;AAAA,IACF;AAEA,UAAM,gBAAgB,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,SAAS,QAAQ;AAG5E,UAAM,oBAAoB,QAAQ,UAC9B,EAAE,SAAS,GAAG,QAAQ,MAAM,IAC5B,EAAE,SAAS,QAAQ,MAAM;AAC7B,UAAM,UAAU,MAAM,MAAM,YAAY;AAAA,MACtC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,aAAa;AAAA,MACf;AAAA,MACA,MAAM,KAAK,UAAU,iBAAiB;AAAA,IACxC,CAAC;AAED,UAAM,SAAS,MAAM,QAAQ,KAAK;AAElC,QAAI,CAAC,QAAQ,IAAI;AACf,YAAM,IAAI,MAAM,OAAO,SAAS,uBAAuB;AAAA,IACzD;AAGA,SAAK,eAAe,UAAU;AAE9B,YAAQ,IAAI,6CAA6C;AACzD,QAAI,OAAO,SAAS,aAAa;AAC/B,YAAM,cAAc,UAAU,WAC1B,yBAAyB,OAAO,QAAQ,WAAW,KACnD,yBAAyB,OAAO,QAAQ,WAAW;AACvD,cAAQ,IAAI,2BAA2B,WAAW,EAAE;AAAA,IACtD;AAEA,WAAO,OAAO,UAAU;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,eACZ,cACA,SACA,UACiB;AACjB,UAAM,WAAW,IAAI,sBAAO;AAAA,MAC1B;AAAA,MACA,CAAC,2EAA2E;AAAA,MAC5E;AAAA,IACF;AACA,WAAO,MAAM,SAAS,UAAU,KAAK,OAAQ,SAAS,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,YACZ,IACA,QACA,OACA,QAAqB,QACrB,gBACqE;AACrE,UAAM,cAAc,MAAM,OAAO,KAAK;AACtC,UAAM,QAAQ,OAAO,KAAK,MAAM,SAAU,MAAM,YAAY,QAAS,CAAC,EAAE,SAAS;AACjF,UAAM,QAAQ,sBAAO,QAAQ,sBAAO,YAAY,EAAE,CAAC;AAInD,UAAM,YAAY,gBAAgB,QAAS,YAAoB,eAAe,UAAU,SAAS,aAAa;AAC9G,UAAM,eAAe,gBAAgB,WAAW;AAEhD,UAAM,WAAW,sBAAsB;AAAA,MACrC,MAAM,KAAK,OAAQ;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,MAAM;AAAA,MACf,cAAc,YAAY;AAAA,MAC1B;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,YAAY,MAAM,KAAK,OAAQ,cAAc,QAAQ;AAC3D,WAAO,EAAE,eAAe,SAAS,SAAS,UAAU;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,QAAsB;AAExC,QAAI,SAAS,KAAK,OAAO,OAAO,UAAU;AACxC,YAAM,IAAI;AAAA,QACR,WAAW,MAAM,kCAAkC,KAAK,OAAO,OAAO,QAAQ;AAAA,MAChF;AAAA,IACF;AAGA,UAAM,SAAQ,oBAAI,KAAK,GAAE,SAAS,GAAG,GAAG,GAAG,CAAC;AAC5C,QAAI,QAAQ,KAAK,mBAAmB;AAClC,WAAK,gBAAgB;AACrB,WAAK,oBAAoB;AACzB,WAAK,aAAa;AAAA,IACpB;AAGA,QAAI,KAAK,gBAAgB,SAAS,KAAK,OAAO,OAAO,WAAW;AAC9D,YAAM,IAAI;AAAA,QACR,8BAA8B,KAAK,aAAa,OAAO,MAAM,OAAO,KAAK,OAAO,OAAO,SAAS;AAAA,MAClG;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,QAAsB;AAC3C,SAAK,iBAAiB;AACtB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA,EAIQ,aAA2B;AACjC,UAAM,iBAAa,mBAAK,KAAK,WAAW,aAAa;AACrD,YAAI,uBAAW,UAAU,GAAG;AAC1B,YAAM,cAAU,yBAAa,YAAY,OAAO;AAChD,aAAO,EAAE,GAAG,gBAAgB,GAAG,KAAK,MAAM,OAAO,EAAE;AAAA,IACrD;AACA,WAAO,EAAE,GAAG,eAAe;AAAA,EAC7B;AAAA,EAEQ,aAAmB;AACzB,8BAAU,KAAK,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,iBAAa,mBAAK,KAAK,WAAW,aAAa;AACrD,kCAAc,YAAY,KAAK,UAAU,KAAK,QAAQ,MAAM,CAAC,CAAC;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,UAAM,mBAAe,mBAAK,KAAK,WAAW,eAAe;AACzD,YAAI,uBAAW,YAAY,GAAG;AAC5B,UAAI;AACF,cAAM,OAAO,KAAK,UAAM,yBAAa,cAAc,OAAO,CAAC;AAC3D,cAAM,SAAQ,oBAAI,KAAK,GAAE,SAAS,GAAG,GAAG,GAAG,CAAC;AAG5C,YAAI,KAAK,QAAQ,KAAK,SAAS,OAAO;AACpC,eAAK,gBAAgB,KAAK,UAAU;AACpC,eAAK,oBAAoB,KAAK;AAAA,QAChC,OAAO;AAEL,eAAK,gBAAgB;AACrB,eAAK,oBAAoB;AAAA,QAC3B;AAAA,MACF,QAAQ;AAEN,aAAK,gBAAgB;AACrB,aAAK,qBAAoB,oBAAI,KAAK,GAAE,SAAS,GAAG,GAAG,GAAG,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,8BAAU,KAAK,WAAW,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,mBAAe,mBAAK,KAAK,WAAW,eAAe;AACzD,UAAM,OAAO;AAAA,MACX,MAAM,KAAK,sBAAqB,oBAAI,KAAK,GAAE,SAAS,GAAG,GAAG,GAAG,CAAC;AAAA,MAC9D,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK,IAAI;AAAA,IACtB;AACA,kCAAc,cAAc,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,EAC3D;AAAA,EAEQ,aAAgC;AACtC,UAAM,iBAAa,mBAAK,KAAK,WAAW,aAAa;AACrD,YAAI,uBAAW,UAAU,GAAG;AAG1B,UAAI,QAAQ,aAAa,SAAS;AAChC,YAAI;AACF,gBAAM,YAAQ,qBAAS,UAAU;AACjC,gBAAM,OAAO,MAAM,OAAO;AAC1B,cAAI,SAAS,KAAO;AAClB,oBAAQ,KAAK,6DAA6D,KAAK,SAAS,CAAC,CAAC,GAAG;AAC7F,oBAAQ,KAAK,0CAA0C;AACvD,sCAAU,YAAY,GAAK;AAAA,UAC7B;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,YAAM,cAAU,yBAAa,YAAY,OAAO;AAChD,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,KACL,WACA,SACwC;AACxC,8BAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAGxC,UAAM,SAAS,sBAAO,aAAa;AACnC,UAAM,aAAyB;AAAA,MAC7B,SAAS,OAAO;AAAA,MAChB,YAAY,OAAO;AAAA,MACnB,WAAW,KAAK,IAAI;AAAA,IACtB;AAGA,UAAM,iBAAa,mBAAK,WAAW,aAAa;AAChD,kCAAc,YAAY,KAAK,UAAU,YAAY,MAAM,CAAC,GAAG,EAAE,MAAM,IAAM,CAAC;AAG9E,UAAM,SAAuB;AAAA,MAC3B,OAAO,QAAQ;AAAA,MACf,QAAQ;AAAA,QACN,UAAU,QAAQ;AAAA,QAClB,WAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AACA,UAAM,iBAAa,mBAAK,WAAW,aAAa;AAChD,kCAAc,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAEzD,WAAO,EAAE,SAAS,OAAO,SAAS,UAAU;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAsE;AAC1E,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAEA,QAAI;AACJ,QAAI;AACF,cAAQ,SAAS,KAAK,OAAO,KAAqB;AAAA,IACpD,QAAQ;AACN,YAAM,IAAI,MAAM,kBAAkB,KAAK,OAAO,KAAK,EAAE;AAAA,IACvD;AAEA,UAAM,WAAW,IAAI,sBAAO,gBAAgB,MAAM,GAAG;AACrD,UAAM,WAAW,CAAC,oDAAoD;AAGtE,UAAM,CAAC,eAAe,aAAa,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,MAClE,SAAS,WAAW,KAAK,OAAO,OAAO;AAAA,MACvC,IAAI,sBAAO,SAAS,MAAM,OAAO,KAAK,SAAS,UAAU,QAAQ,EAAE,UAAU,KAAK,OAAO,OAAO;AAAA,MAChG,IAAI,sBAAO,SAAS,MAAM,OAAO,KAAK,SAAS,UAAU,QAAQ,EAAE,UAAU,KAAK,OAAO,OAAO;AAAA,IAClG,CAAC;AAED,WAAO;AAAA,MACL,MAAM,WAAW,sBAAO,YAAY,aAAa,MAAM,OAAO,KAAK,QAAQ,CAAC;AAAA,MAC5E,MAAM,WAAW,sBAAO,YAAY,aAAa,MAAM,OAAO,KAAK,QAAQ,CAAC;AAAA,MAC5E,QAAQ,WAAW,sBAAO,YAAY,aAAa,CAAC;AAAA,IACtD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAA4K;AAChL,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAEA,UAAM,kBAAkC,CAAC,QAAQ,WAAW,gBAAgB,kBAAkB,OAAO,aAAa;AAClH,UAAM,WAAW,CAAC,oDAAoD;AACtE,UAAM,UAA4J,CAAC;AAGnK,UAAM,cAAc;AAAA,MAClB,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AAGA,UAAM,QAAQ;AAAA,MACZ,gBAAgB,IAAI,OAAO,cAAc;AACvC,YAAI;AACF,gBAAM,QAAQ,SAAS,SAAS;AAChC,gBAAM,WAAW,IAAI,sBAAO,gBAAgB,MAAM,GAAG;AAErD,cAAI,cAAc,kBAAkB;AAElC,kBAAM,CAAC,eAAe,SAAS,UAAU,SAAS,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,cAC9E,SAAS,WAAW,KAAK,OAAQ,OAAO;AAAA,cACxC,IAAI,sBAAO,SAAS,YAAY,SAAS,UAAU,QAAQ,EAAE,UAAU,KAAK,OAAQ,OAAO;AAAA,cAC3F,IAAI,sBAAO,SAAS,YAAY,UAAU,UAAU,QAAQ,EAAE,UAAU,KAAK,OAAQ,OAAO;AAAA,cAC5F,IAAI,sBAAO,SAAS,YAAY,SAAS,UAAU,QAAQ,EAAE,UAAU,KAAK,OAAQ,OAAO;AAAA,cAC3F,IAAI,sBAAO,SAAS,YAAY,UAAU,UAAU,QAAQ,EAAE,UAAU,KAAK,OAAQ,OAAO;AAAA,YAC9F,CAAC;AAED,oBAAQ,SAAS,IAAI;AAAA,cACnB,MAAM,WAAW,sBAAO,YAAY,SAAS,CAAC,CAAC;AAAA;AAAA,cAC/C,MAAM,WAAW,sBAAO,YAAY,UAAU,CAAC,CAAC;AAAA;AAAA,cAChD,QAAQ,WAAW,sBAAO,YAAY,aAAa,CAAC;AAAA,cACpD,OAAO;AAAA,gBACL,SAAS,WAAW,sBAAO,YAAY,SAAS,CAAC,CAAC;AAAA,gBAClD,UAAU,WAAW,sBAAO,YAAY,UAAU,CAAC,CAAC;AAAA,gBACpD,SAAS,WAAW,sBAAO,YAAY,SAAS,CAAC,CAAC;AAAA,gBAClD,UAAU,WAAW,sBAAO,YAAY,UAAU,CAAC,CAAC;AAAA,cACtD;AAAA,YACF;AAAA,UACF,OAAO;AAEL,kBAAM,CAAC,eAAe,aAAa,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,cAClE,SAAS,WAAW,KAAK,OAAQ,OAAO;AAAA,cACxC,IAAI,sBAAO,SAAS,MAAM,OAAO,KAAK,SAAS,UAAU,QAAQ,EAAE,UAAU,KAAK,OAAQ,OAAO;AAAA,cACjG,IAAI,sBAAO,SAAS,MAAM,OAAO,KAAK,SAAS,UAAU,QAAQ,EAAE,UAAU,KAAK,OAAQ,OAAO;AAAA,YACnG,CAAC;AAED,oBAAQ,SAAS,IAAI;AAAA,cACnB,MAAM,WAAW,sBAAO,YAAY,aAAa,MAAM,OAAO,KAAK,QAAQ,CAAC;AAAA,cAC5E,MAAM,WAAW,sBAAO,YAAY,aAAa,MAAM,OAAO,KAAK,QAAQ,CAAC;AAAA,cAC5E,QAAQ,WAAW,sBAAO,YAAY,aAAa,CAAC;AAAA,YACtD;AAAA,UACF;AAAA,QACF,SAAS,KAAK;AAEZ,kBAAQ,SAAS,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,EAAE;AAAA,QACrD;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,WACJ,KACA,UAGI,CAAC,GACS;AACd,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,YAAY;AACpC,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AAGA,UAAM,EAAE,qBAAAA,qBAAoB,IAAI,MAAM,OAAO,eAAe;AAC5D,UAAM,EAAE,oBAAoB,oBAAoB,KAAK,IAAI,MAAM,OAAO,MAAM;AAC5E,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,aAAa;AACpD,UAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,YAAY;AAG7C,UAAM,aAAa,KAAK,WAAW;AACnC,UAAM,UAAUA,qBAAoB,UAAU;AAE9C,YAAQ,IAAI,qCAAqC,GAAG,EAAE;AACtD,YAAQ,IAAI,6BAA6B,QAAQ,OAAO,EAAE;AAG1D,UAAM,eAAe,MAAM,MAAM,KAAK;AAAA,MACpC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAG,QAAQ;AAAA,MACb;AAAA,MACA,MAAM,QAAQ,OAAO,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,IACtD,CAAC;AAGD,QAAI,aAAa,WAAW,KAAK;AAC/B,UAAI,aAAa,IAAI;AACnB,eAAO,aAAa,KAAK;AAAA,MAC3B;AACA,YAAM,YAAY,MAAM,aAAa,KAAK;AAC1C,YAAM,IAAI,MAAM,mBAAmB,aAAa,MAAM,MAAM,SAAS,EAAE;AAAA,IACzE;AAGA,UAAM,UAAU,aAAa,QAAQ,IAAI,kBAAkB;AAC3D,QAAI,CAAC,WAAW,CAAC,QAAQ,YAAY,EAAE,SAAS,SAAS,GAAG;AAC1D,YAAM,IAAI,MAAM,uDAAuD;AAAA,IACzE;AAEA,YAAQ,IAAI,kDAAkD;AAG9D,UAAM,iBAAiB,CAAC,QAAgB,QAA+B;AACrE,YAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,GAAG,GAAG,cAAc,GAAG,CAAC;AAC9D,aAAO,QAAQ,MAAM,CAAC,IAAI;AAAA,IAC5B;AAEA,UAAM,cAAc,eAAe,SAAS,IAAI;AAChD,UAAM,SAAS,eAAe,SAAS,QAAQ;AAC/C,UAAM,QAAQ,eAAe,SAAS,OAAO;AAC7C,UAAM,aAAa,eAAe,SAAS,SAAS;AAEpD,QAAI,WAAW,SAAS;AACtB,YAAM,IAAI,MAAM,+BAA+B,MAAM,EAAE;AAAA,IACzD;AAEA,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAGA,UAAM,cAAc,OAAO,KAAK,YAAY,QAAQ,EAAE,SAAS,OAAO;AACtE,UAAM,iBAAiB,KAAK,MAAM,WAAW;AAE7C,YAAQ,IAAI,+BAA+B,cAAc;AAEzD,UAAM,EAAE,QAAQ,UAAU,WAAW,cAAc,IAAI;AACvD,UAAM,UAAU,eAAe,WAAW;AAG1C,YAAQ,IAAI,oDAAoD,OAAO,MAAM;AAC7E,YAAQ,IAAI,sBAAsB,MAAM,SAAS,SAAS,EAAE;AAG5D,UAAM,aAAa,EAAE,GAAG,eAAe,UAAU,SAA0B;AAE3E,UAAM,eAAe,mBAAmB;AAAA,MACtC,OAAO;AAAA,MACP,WAAW,KAAK,gCAAgC;AAAA,IAClD,CAAC;AAED,UAAM,eAAe,mBAAmB;AAAA,MACtC;AAAA,MACA,OAAO;AAAA,MACP,WAAW,KAAK,gCAAgC;AAAA,IAClD,CAAC;AAGD,UAAM,SAAS,MAAM,QAAQ,MAAM,SAAS,cAAc;AAAA,MACxD,IAAI;AAAA,MACJ,QAAQ,OAAO,MAAM;AAAA,MACrB,OAAO;AAAA,IACT,CAAC;AAED,YAAQ,IAAI,gCAAgC,MAAM,EAAE;AAGpD,YAAQ,IAAI,wCAAwC;AACpD,UAAM,aAAa,0BAA0B,EAAE,MAAM,OAAO,CAAC;AAC7D,YAAQ,IAAI,mCAAmC;AAG/C,UAAM,YAAY;AAAA,MAChB,IAAI;AAAA,MACJ;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAEA,UAAM,aAAa;AAAA,MACjB;AAAA,MACA,SAAS,EAAE,MAAM,QAAQ,MAAM,OAAO;AAAA,MACtC,QAAQ,kBAAkB,OAAO,IAAI,QAAQ,OAAO;AAAA,IACtD;AAEA,UAAM,gBAAgB,OAAO,KAAK,KAAK,UAAU,UAAU,CAAC,EACzD,SAAS,QAAQ,EACjB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,GAAG,EAClB,QAAQ,OAAO,EAAE;AAEpB,YAAQ,IAAI,gDAAgD;AAG5D,UAAM,eAAe,MAAM,MAAM,KAAK;AAAA,MACpC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB,WAAW,aAAa;AAAA,QACzC,GAAG,QAAQ;AAAA,MACb;AAAA,MACA,MAAM,QAAQ,OAAO,KAAK,UAAU,QAAQ,IAAI,IAAI;AAAA,IACtD,CAAC;AAED,QAAI,CAAC,aAAa,IAAI;AACpB,YAAM,YAAY,MAAM,aAAa,KAAK;AAC1C,YAAM,IAAI,MAAM,gCAAgC,aAAa,MAAM,MAAM,SAAS,EAAE;AAAA,IACtF;AAEA,YAAQ,IAAI,iDAAiD;AAC7D,WAAO,aAAa,KAAK;AAAA,EAC3B;AACF;;;AyB95CA;AAgBA,IAAAC,aAAyC;AACzC,kBAA8D;AAC9D,IAAAC,QAAsB;;;AClBtB;;;ACAA;AAcA,IAAAC,aAAyC;AACzC,WAAsB;AAatB,IAAMC,gBAAe;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,YAAI,uBAAW,OAAO,GAAG;AACvB,UAAI;AACF,cAAM,cAAU,yBAAa,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,aAAaA;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,aAAaA;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;;;AC3TA;AAOA,IAAAC,iBAAuB;AAYvB,IAAM,uBAAuB;AAyB7B,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AACF;AAOO,IAAM,mBAAN,cAA+B,gBAAgB;AAAA,EAC3C,OAAO;AAAA,EACP,cAAc;AAAA,EACd,oBAAoB,CAAC,cAAc;AAAA;AAAA,EAEpC;AAAA,EACA,gBAAsC;AAAA,EAE9C,cAAc;AACZ,UAAM;AACN,SAAK,SAAS,OAAO,eAAe;AAKpC,UAAM,aAAa,QAAQ,IAAI;AAC/B,QAAI,YAAY;AACd,UAAI;AACF,cAAM,WAAW,IAAI,sBAAO,gBAAgB,KAAK,MAAM;AACvD,aAAK,gBAAgB,IAAI,sBAAO,OAAO,YAAY,QAAQ;AAAA,MAC7D,SAAS,KAAK;AACZ,gBAAQ,KAAK,6EAA6E,GAAG;AAC7F,aAAK,gBAAgB;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAmC;AACjC,WAAO,KAAK,eAAe,WAAW;AAAA,EACxC;AAAA,EAEA,MAAM,cAA0C;AAC9C,UAAM,QAAQ,KAAK,IAAI;AACvB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,QAAQ;AAAA,QACxC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU;AAAA,UACnB,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,CAAC;AAAA,UACT,IAAI;AAAA,QACN,CAAC;AAAA,MACH,CAAC;AAED,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,UAAU,SAAS,KAAK,QAAQ,EAAE;AAExC,UAAI,YAAY,OAAO;AACrB,eAAO,EAAE,SAAS,OAAO,OAAO,kBAAkB,OAAO,GAAG;AAAA,MAC9D;AAEA,aAAO,EAAE,SAAS,MAAM,WAAW,KAAK,IAAI,IAAI,MAAM;AAAA,IACxD,SAAS,OAAO;AACd,aAAO,EAAE,SAAS,OAAO,OAAO,OAAO,KAAK,EAAE;AAAA,IAChD;AAAA,EACF;AAAA,EAEA,MAAM,OACJ,gBACA,cACuB;AAIvB,UAAM,QAAQ,eAAe;AAC7B,QAAI,SAAS,YAAY,SAAS,MAAM,QAAQ;AAC9C,aAAO,KAAK,aAAa,OAA6B,YAAY;AAAA,IACpE;AACA,WAAO,KAAK,aAAa,gBAAgB,YAAY;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,aACZ,SACA,cACuB;AACvB,QAAI,CAAC,KAAK,eAAe;AACvB,aAAO,EAAE,OAAO,OAAO,OAAO,+DAA+D;AAAA,IAC/F;AACA,UAAM,IAAI,QAAQ;AAClB,QAAI,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,EAAE,WAAW,CAAC,EAAE,SAAS,CAAC,EAAE,UAAU;AAC3D,aAAO,EAAE,OAAO,OAAO,OAAO,yCAAyC;AAAA,IACzE;AAGA,QAAI,EAAE,QAAQ,YAAY,MAAM,KAAK,cAAc,QAAQ,YAAY,GAAG;AACxE,aAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,kBAAkB,EAAE,OAAO,sCAAsC,KAAK,cAAc,OAAO;AAAA,MACpG;AAAA,IACF;AAEA,UAAM,WAAW,OAAO,EAAE,QAAQ;AAClC,UAAM,MAAM,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,CAAC;AAChD,QAAI,YAAY,KAAK;AACnB,aAAO,EAAE,OAAO,OAAO,OAAO,8BAA8B;AAAA,IAC9D;AAEA,QAAI,OAAO,EAAE,KAAK,IAAI,OAAO,aAAa,UAAU,GAAG,GAAG;AACxD,aAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,gBAAgB,EAAE,KAAK,0BAA0B,aAAa,MAAM;AAAA,MAC7E;AAAA,IACF;AACA,WAAO,EAAE,OAAO,MAAM,SAAS,EAAE,QAAQ,UAAU,OAAO,EAAE,MAAM,EAAE;AAAA,EACtE;AAAA,EAEA,MAAc,aACZ,gBACA,cACuB;AACvB,QAAI;AAEF,YAAM,eAAe,eAAe;AAEpC,UAAI,CAAC,cAAc,QAAQ;AACzB,eAAO,EAAE,OAAO,OAAO,OAAO,oCAAoC;AAAA,MACpE;AAGA,YAAM,UAAU,MAAM,KAAK,sBAAsB,aAAa,MAAM;AAEpE,UAAI,CAAC,SAAS;AACZ,eAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB;AAAA,MACxD;AAEA,UAAI,QAAQ,WAAW,OAAO;AAC5B,eAAO,EAAE,OAAO,OAAO,OAAO,qBAAqB;AAAA,MACrD;AAGA,YAAM,cAAc,QAAQ,KAAK;AAAA,QAAK,CAAC,QACrC,IAAI,OAAO,CAAC,MAAM;AAAA,MACpB;AAEA,UAAI,CAAC,aAAa;AAChB,eAAO,EAAE,OAAO,OAAO,OAAO,0BAA0B;AAAA,MAC1D;AAGA,YAAM,YAAY,OAAO,YAAY,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,YAAY;AACrE,YAAM,aAAa,aAAa,MAAM,YAAY;AAElD,UAAI,cAAc,YAAY;AAC5B,eAAO;AAAA,UACL,OAAO;AAAA,UACP,OAAO,oBAAoB,SAAS,cAAc,UAAU;AAAA,QAC9D;AAAA,MACF;AAGA,YAAM,SAAS,OAAO,YAAY,IAAI;AACtC,YAAM,iBAAiB,OAAO,aAAa,MAAM;AAEjD,UAAI,SAAS,gBAAgB;AAC3B,eAAO;AAAA,UACL,OAAO;AAAA,UACP,OAAO,wBAAwB,MAAM,cAAc,cAAc;AAAA,QACnE;AAAA,MACF;AAGA,YAAM,eAAe,YAAY,QAAQ,YAAY;AACrD,YAAM,gBAAgB,aAAa,MAAM,YAAY;AAErD,UAAI,iBAAiB,eAAe;AAClC,eAAO;AAAA,UACL,OAAO;AAAA,UACP,OAAO,gBAAgB,YAAY,cAAc,aAAa;AAAA,QAChE;AAAA,MACF;AAEA,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,UACP,QAAQ,aAAa;AAAA,UACrB,MAAM,OAAO,YAAY,OAAO,CAAC,EAAE,MAAM,EAAE;AAAA,UAC3C,IAAI;AAAA,UACJ,QAAQ,OAAO,SAAS;AAAA,UACxB,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB,KAAK,GAAG;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,MAAM,OACJ,gBACA,cACuB;AAEvB,UAAM,QAAQ,eAAe;AAC7B,QAAI,SAAS,YAAY,SAAS,MAAM,QAAQ;AAC9C,aAAO,KAAK,aAAa,OAA6B,YAAY;AAAA,IACpE;AAGA,UAAM,eAAe,MAAM,KAAK,aAAa,gBAAgB,YAAY;AACzE,QAAI,CAAC,aAAa,OAAO;AACvB,aAAO,EAAE,SAAS,OAAO,OAAO,aAAa,MAAM;AAAA,IACrD;AACA,UAAM,eAAe,eAAe;AACpC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa,aAAa;AAAA,MAC1B,QAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,aACZ,SACA,cACuB;AACvB,QAAI,CAAC,KAAK,eAAe;AACvB,aAAO,EAAE,SAAS,OAAO,OAAO,+DAA+D;AAAA,IACjG;AACA,QAAI,CAAC,aAAa,SAAS,CAAC,aAAa,OAAO;AAC9C,aAAO,EAAE,SAAS,OAAO,OAAO,yCAAyC;AAAA,IAC3E;AAEA,UAAM,eAAe,MAAM,KAAK,aAAa,SAAS,YAAY;AAClE,QAAI,CAAC,aAAa,OAAO;AACvB,aAAO,EAAE,SAAS,OAAO,OAAO,aAAa,MAAM;AAAA,IACrD;AAEA,UAAM,QAAQ,IAAI,sBAAO,SAAS,aAAa,OAAO,kBAAkB,KAAK,aAAa;AAC1F,UAAM,IAAI,QAAQ;AAElB,QAAI;AACF,YAAM,WAAW,MAAM,MAAM;AAAA,QAC3B,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,MACJ;AACA,YAAM,SAAS,KAAK;AAEpB,YAAM,aAAa,MAAM,MAAM,aAAa,EAAE,OAAO,aAAa,OAAO,EAAE,KAAK;AAChF,YAAM,WAAW,KAAK;AAEtB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa,WAAW;AAAA,QACxB,QAAQ;AAAA,MACV;AAAA,IACF,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,mCAAoC,IAAc,OAAO;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,sBAAsB,QAA8B;AAChE,UAAM,WAAW,MAAM,MAAM,KAAK,QAAQ;AAAA,MACxC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU;AAAA,QACnB,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,CAAC,MAAM;AAAA,QACf,IAAI;AAAA,MACN,CAAC;AAAA,IACH,CAAC;AAED,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,WAAO,KAAK;AAAA,EACd;AACF;;;ACvVA;AA2BA,sBAAoC;AAGpC,IAAMC,wBAAuB;AAG7B,IAAM,gBAAgB;AAAA,EACpB,MAAM;AAAA,EACN,SAAS;AACX;AAGA,IAAM,eAAe;AAAA,EACnB,eAAe;AAAA,IACb,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,IAChC,EAAE,MAAM,MAAM,MAAM,UAAU;AAAA,IAC9B,EAAE,MAAM,UAAU,MAAM,UAAU;AAAA,IAClC,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,IACjC,EAAE,MAAM,WAAW,MAAM,SAAS;AAAA,IAClC,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,IACjC,EAAE,MAAM,YAAY,MAAM,UAAU;AAAA,EACtC;AACF;AAuCO,IAAM,iBAAN,cAA6B,gBAAgB;AAAA,EACzC,OAAO;AAAA,EACP,cAAc;AAAA,EACd,oBAAoB,CAAC,aAAa,WAAW;AAAA;AAAA,EAE9C;AAAA,EACA,iBAAgC;AAAA,EAChC;AAAA,EAER,YAAY,kBAA2B;AACrC,UAAM;AACN,SAAK,mBAAmB,oBAAoB,QAAQ,IAAI,0BAA0B;AAGlF,QAAI,KAAK,kBAAkB;AACzB,YAAM,MAAM,KAAK,iBAAiB,WAAW,IAAI,IAC7C,KAAK,mBACL,KAAK,KAAK,gBAAgB;AAC9B,YAAM,cAAU,qCAAoB,GAAG;AACvC,WAAK,iBAAiB,QAAQ;AAAA,IAChC;AAEA,SAAK,eAAe;AAAA,MAClB,IAAI,EAAE,KAAK,OAAO,IAAI,KAAK,OAAO,OAAO,IAAI;AAAA,MAC7C,IAAI,EAAE,KAAK,OAAO,YAAY,KAAK,OAAO,OAAO,YAAY;AAAA,IAC/D;AAAA,EACF;AAAA,EAEA,MAAM,cAA0C;AAC9C,UAAM,QAAQ,KAAK,IAAI;AACvB,QAAI;AAEF,YAAM,WAAW,MAAM,MAAM,KAAK,aAAa,EAAE,EAAE,KAAK;AAAA,QACtD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU;AAAA,UACnB,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,QAAQ,CAAC;AAAA,UACT,IAAI;AAAA,QACN,CAAC;AAAA,MACH,CAAC;AAED,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,UAAU,SAAS,KAAK,QAAQ,EAAE;AAExC,UAAI,YAAY,IAAI;AAClB,eAAO,EAAE,SAAS,OAAO,OAAO,kBAAkB,OAAO,GAAG;AAAA,MAC9D;AAEA,aAAO,EAAE,SAAS,MAAM,WAAW,KAAK,IAAI,IAAI,MAAM;AAAA,IACxD,SAAS,OAAO;AACd,aAAO,EAAE,SAAS,OAAO,OAAO,OAAO,KAAK,EAAE;AAAA,IAChD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OACJ,gBACA,cACuB;AACvB,QAAI;AACF,YAAM,aAAa,eAAe;AAElC,UAAI,CAAC,YAAY,QAAQ;AACvB,eAAO,EAAE,OAAO,OAAO,OAAO,oCAAoC;AAAA,MACpE;AAEA,YAAM,EAAE,QAAQ,QAAQ,IAAI;AAC5B,YAAM,SAAS,KAAK,aAAa,OAAO;AAExC,UAAI,CAAC,QAAQ;AACX,eAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB,OAAO,GAAG;AAAA,MAClE;AAGA,UAAI,OAAO,WAAW,KAAK,IAAI,GAAG;AAChC,eAAO,EAAE,OAAO,OAAO,OAAO,iBAAiB;AAAA,MACjD;AAGA,YAAM,mBAAmB,MAAM,KAAK,oBAAoB,QAAQ,OAAO;AACvE,UAAI,iBAAiB,YAAY,MAAM,OAAO,KAAK,YAAY,GAAG;AAChE,eAAO,EAAE,OAAO,OAAO,OAAO,oBAAoB;AAAA,MACpD;AAGA,UAAI,OAAO,GAAG,YAAY,MAAM,aAAa,MAAM,YAAY,GAAG;AAChE,eAAO,EAAE,OAAO,OAAO,OAAO,oBAAoB,OAAO,EAAE,GAAG;AAAA,MAChE;AAGA,UAAI,OAAO,OAAO,MAAM,IAAI,OAAO,aAAa,MAAM,GAAG;AACvD,eAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB,OAAO,MAAM,GAAG;AAAA,MACxE;AAGA,UAAI,OAAO,MAAM,YAAY,MAAM,aAAa,MAAM,YAAY,GAAG;AACnE,eAAO,EAAE,OAAO,OAAO,OAAO,gBAAgB,OAAO,KAAK,GAAG;AAAA,MAC/D;AAGA,YAAM,gBAAgB,MAAM,KAAK,iBAAiB;AAClD,YAAM,YAAY,MAAM,KAAK,aAAa,OAAO,MAAM,eAAe,OAAO,OAAO,OAAO,GAAG;AAE9F,UAAI,OAAO,SAAS,IAAI,OAAO,OAAO,MAAM,GAAG;AAC7C,eAAO,EAAE,OAAO,OAAO,OAAO,6DAA6D;AAAA,MAC7F;AAGA,YAAM,UAAU,MAAM,KAAK,WAAW,OAAO,MAAM,OAAO,OAAO,OAAO,GAAG;AAC3E,UAAI,OAAO,OAAO,IAAI,OAAO,OAAO,MAAM,GAAG;AAC3C,eAAO,EAAE,OAAO,OAAO,OAAO,uBAAuB;AAAA,MACvD;AAEA,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,UACP,MAAM,OAAO;AAAA,UACb,IAAI,OAAO;AAAA,UACX,QAAQ,OAAO;AAAA,UACf,OAAO,OAAO;AAAA,UACd,SAAS,OAAO;AAAA,UAChB,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,QACnB;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB,KAAK,GAAG;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OACJ,gBACA,cACuB;AACvB,QAAI,CAAC,KAAK,kBAAkB;AAC1B,aAAO,EAAE,SAAS,OAAO,OAAO,wDAAwD;AAAA,IAC1F;AAEA,QAAI;AAEF,YAAM,eAAe,MAAM,KAAK,OAAO,gBAAgB,YAAY;AACnE,UAAI,CAAC,aAAa,OAAO;AACvB,eAAO,EAAE,SAAS,OAAO,OAAO,aAAa,MAAM;AAAA,MACrD;AAEA,YAAM,aAAa,eAAe;AAClC,YAAM,EAAE,QAAQ,QAAQ,IAAI;AAC5B,YAAM,SAAS,KAAK,aAAa,OAAO;AAGxC,YAAM,SAAS,MAAM,KAAK;AAAA,QACxB,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,QAAQ;AAAA,MACV;AAAA,IACF,SAAS,OAAO;AACd,aAAO,EAAE,SAAS,OAAO,OAAO,sBAAsB,KAAK,GAAG;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cACJ,eACA,OACA,SACmD;AACnD,UAAM,SAAS,KAAK,aAAa,OAAO;AACxC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,wBAAwB,OAAO,EAAE;AAAA,IACnD;AAEA,UAAM,gBAAgB,MAAM,KAAK,iBAAiB;AAClD,UAAM,YAAY,MAAM,KAAK,aAAa,eAAe,eAAe,OAAO,OAAO,GAAG;AAGzF,UAAM,eAAe,OAAO,wBAAwB;AAEpD,WAAO;AAAA,MACL,UAAU,OAAO,SAAS,KAAK;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBACJ,QACA,UACA,SACuB;AACvB,UAAM,SAAS,KAAK,aAAa,OAAO;AACxC,QAAI,CAAC,QAAQ;AACX,aAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB,OAAO,GAAG;AAAA,IAClE;AAEA,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,sBAAsB,QAAQ,OAAO,GAAG;AAEnE,UAAI,CAAC,SAAS;AACZ,eAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB;AAAA,MACxD;AAEA,UAAI,QAAQ,WAAW,OAAO;AAC5B,eAAO,EAAE,OAAO,OAAO,OAAO,qBAAqB;AAAA,MACrD;AAGA,YAAM,cAAc,QAAQ,KAAK;AAAA,QAAK,CAAC,QACrC,IAAI,OAAO,CAAC,MAAMC,yBAClB,IAAI,QAAQ,YAAY,MAAM,SAAS,MAAM,YAAY;AAAA,MAC3D;AAEA,UAAI,CAAC,aAAa;AAChB,eAAO,EAAE,OAAO,OAAO,OAAO,0BAA0B;AAAA,MAC1D;AAGA,YAAM,YAAY,OAAO,YAAY,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,YAAY;AACrE,UAAI,cAAc,SAAS,GAAG,YAAY,GAAG;AAC3C,eAAO,EAAE,OAAO,OAAO,OAAO,oBAAoB,SAAS,GAAG;AAAA,MAChE;AAGA,YAAM,SAAS,OAAO,YAAY,IAAI;AACtC,UAAI,SAAS,OAAO,SAAS,MAAM,GAAG;AACpC,eAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB,MAAM,GAAG;AAAA,MACjE;AAEA,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,UACP;AAAA,UACA,MAAM,OAAO,YAAY,OAAO,CAAC,EAAE,MAAM,EAAE;AAAA,UAC3C,IAAI;AAAA,UACJ,QAAQ,OAAO,SAAS;AAAA,UACxB,OAAO,YAAY;AAAA,QACrB;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB,KAAK,GAAG;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,mBAAoC;AAEhD,UAAM,EAAE,QAAAC,QAAO,IAAI,MAAM,OAAO,QAAQ;AACxC,UAAM,SAAS,IAAIA,QAAO,OAAO,KAAK,gBAAgB;AACtD,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAc,oBAAoB,QAA0B,SAAkC;AAE5F,UAAM,EAAE,QAAAA,QAAO,IAAI,MAAM,OAAO,QAAQ;AAExC,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH;AAAA,IACF;AAEA,UAAM,UAAU;AAAA,MACd,MAAM,OAAO;AAAA,MACb,IAAI,OAAO;AAAA,MACX,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,OAAO,OAAO;AAAA,MACd,UAAU,OAAO;AAAA,IACnB;AAEA,UAAM,mBAAmBA,QAAO;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,aAAa,OAAe,SAAiB,OAAe,QAAiC;AAEzG,UAAM,WAAW;AACjB,UAAM,cAAc,MAAM,YAAY,EAAE,QAAQ,MAAM,EAAE,EAAE,SAAS,IAAI,GAAG;AAC1E,UAAM,gBAAgB,QAAQ,YAAY,EAAE,QAAQ,MAAM,EAAE,EAAE,SAAS,IAAI,GAAG;AAC9E,UAAM,OAAO,WAAW,cAAc;AAEtC,UAAM,WAAW,MAAM,MAAM,QAAQ;AAAA,MACnC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU;AAAA,QACnB,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,CAAC,EAAE,IAAI,OAAO,KAAK,GAAG,QAAQ;AAAA,QACtC,IAAI;AAAA,MACN,CAAC;AAAA,IACH,CAAC;AAED,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO,OAAO,UAAU;AAAA,EAC1B;AAAA,EAEA,MAAc,WAAW,SAAiB,OAAe,QAAiC;AAExF,UAAM,WAAW;AACjB,UAAM,gBAAgB,QAAQ,YAAY,EAAE,QAAQ,MAAM,EAAE,EAAE,SAAS,IAAI,GAAG;AAC9E,UAAM,OAAO,WAAW;AAExB,UAAM,WAAW,MAAM,MAAM,QAAQ;AAAA,MACnC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU;AAAA,QACnB,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,CAAC,EAAE,IAAI,OAAO,KAAK,GAAG,QAAQ;AAAA,QACtC,IAAI;AAAA,MACN,CAAC;AAAA,IACH,CAAC;AAED,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO,OAAO,UAAU;AAAA,EAC1B;AAAA,EAEA,MAAc,oBACZ,MACA,IACA,QACA,OACA,QACiB;AACjB,UAAM,EAAE,QAAAA,QAAO,IAAI,MAAM,OAAO,QAAQ;AAExC,UAAM,WAAW,IAAIA,QAAO,gBAAgB,MAAM;AAClD,UAAM,SAAS,IAAIA,QAAO,OAAO,KAAK,kBAAkB,QAAQ;AAEhE,UAAM,gBAAgB,IAAIA,QAAO,SAAS,OAAO;AAAA,MAC/C;AAAA,IACF,GAAG,MAAM;AAET,UAAM,KAAK,MAAM,cAAc,aAAa,MAAM,IAAI,MAAM;AAC5D,UAAM,UAAU,MAAM,GAAG,KAAK;AAE9B,WAAO,QAAQ;AAAA,EACjB;AAAA,EAEA,MAAc,sBAAsB,QAAgB,QAA8B;AAChF,UAAM,WAAW,MAAM,MAAM,QAAQ;AAAA,MACnC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU;AAAA,QACnB,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,CAAC,MAAM;AAAA,QACf,IAAI;AAAA,MACN,CAAC;AAAA,IACH,CAAC;AAED,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,WAAO,KAAK;AAAA,EACd;AACF;;;ACpeA;AA0BA,IAAAC,sBAAmB;;;AC1BnB;AAaA,IAAAC,sBAAmB;AAUZ,SAAS,SAAS,MAAc,eAA+B;AACpE,QAAM,SAAS,oBAAAC,QAAO,WAAW,YAAY;AAC7C,SAAO,OAAO,MAAM,OAAO;AAC3B,SAAO,IAAI;AACX,SAAO,OAAO,KAAK,eAAe,QAAQ;AAC5C;;;AC5BA;AAeO,SAAS,UAAU,OAAuB;AAC/C,SAAO,OAAO,KAAK,OAAO,OAAO,EAAE,SAAS,WAAW;AACzD;AAYO,SAAS,0BAA0B,OAAuB;AAC/D,QAAM,aAAa,MAAM,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AAC7D,QAAM,SAAS,aAAa,IAAI,QAAQ,IAAK,WAAW,SAAS,KAAM,CAAC;AACxE,SAAO,OAAO,KAAK,QAAQ,QAAQ,EAAE,SAAS,OAAO;AACvD;AAcO,SAAS,MAAM,KAAa,MAAoC;AACrE,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,QAAQ,SAAS,YAAY,EAAG,QAAO;AAC3C,QAAM,QAAQ,SAAS,YAAY,gBAAgB;AACnD,QAAM,OAAO,QAAQ,QAAQ,QAAQ,EAAE,EAAE,MAAM,UAAU,GAAG,KAAK,IAAI,KAAK;AAC1E,SAAO,cAAc,KAAK;AAAA,EAAU,IAAI;AAAA,WAAc,KAAK;AAAA;AAC7D;;;ACrDA;AA8DO,SAAS,sBAAsB,IAAU,oBAAI,KAAK,GAAW;AAClE,QAAM,MAAM,CAAC,MAAsB,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG;AAC5D,SACE,GAAG,EAAE,YAAY,CAAC,IAAI,IAAI,EAAE,SAAS,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,QAAQ,CAAC,CAAC,IAC5D,IAAI,EAAE,SAAS,CAAC,CAAC,IAAI,IAAI,EAAE,WAAW,CAAC,CAAC,IAAI,IAAI,EAAE,WAAW,CAAC,CAAC;AAEtE;AASO,SAAS,mBAAmB,QAAwC;AACzE,SAAO,OAAO,KAAK,MAAM,EACtB,KAAK,EACL,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,EAC9B,KAAK,GAAG;AACb;AAUO,SAAS,mBAAmB,QAAwB;AACzD,SAAO,GAAG,OAAO,QAAQ,OAAO,GAAG,CAAC;AACtC;AAeA,eAAsB,kBACpB,QACA,YACA,QACgC;AAChC,QAAM,eAAuC;AAAA,IAC3C,QAAQ,OAAO;AAAA,IACf;AAAA,IACA,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW,OAAO,aAAa;AAAA,IAC/B,WAAW,sBAAsB;AAAA,IACjC,SAAS;AAAA,IACT,aAAa,KAAK,UAAU,UAAU;AAAA,EACxC;AAEA,QAAM,gBAAgB,mBAAmB,YAAY;AACrD,QAAM,OAAO,SAAS,eAAe,OAAO,eAAe;AAE3D,QAAM,OAAO,IAAI,gBAAgB,EAAE,GAAG,cAAc,KAAK,CAAC,EAAE,SAAS;AAErE,QAAM,WAAW,MAAM,MAAM,OAAO,aAAa;AAAA,IAC/C,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,IAClB;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,cAAc;AAC7D,UAAM,IAAI;AAAA,MACR,wBAAwB,SAAS,MAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC;AAAA,IAC9E;AAAA,EACF;AAEA,QAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,QAAM,aAAa,mBAAmB,MAAM;AAC5C,QAAM,WAAW,KAAK,UAAU;AAEhC,MAAI,aAAa,UAAa,aAAa,QAAQ,OAAO,aAAa,UAAU;AAC/E,UAAM,IAAI;AAAA,MACR,qCAAqC,UAAU,iBAAiB,MAAM,KACjE,KAAK,UAAU,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC;AAAA,IACzC;AAAA,EACF;AAEA,SAAO;AACT;;;AHrHO,IAAM,iBAAiB;AAGvB,IAAM,gBAAgB;AAGtB,IAAM,sBAAsB;AAM5B,IAAM,sBAAsB;AAG5B,IAAM,uBAAuB,KAAK,KAAK;AAMvC,IAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAiFO,IAAM,oBAAN,cAAgC,gBAAgB;AAAA,EAC5C,OAAO;AAAA,EACP,cAAc;AAAA,EACd,oBAAoB,CAAC,cAAc;AAAA,EAE3B;AAAA,EAEjB,YAAY,QAAiC;AAC3C,UAAM;AACN,SAAK,SAAS;AAAA,MACZ,aAAa;AAAA,MACb,WAAW;AAAA,MACX,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,0BACJ,MACoC;AACpC,QAAI,CAAC,oBAAoB,KAAK,KAAK,QAAQ,GAAG;AAC5C,YAAM,IAAI;AAAA,QACR,0DAA0D,KAAK,QAAQ;AAAA,MAEzE;AAAA,IACF;AAEA,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,aAAa,KAAK,cAAc,mBAAmB;AACzD,UAAM,YAAY,gBAAgB,GAAG;AAGrC,UAAM,eAAe;AAAA,MACnB,QAAQ,KAAK;AAAA,MACb,UAAU;AAAA,MACV,YAAY,KAAK;AAAA,MACjB,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK,OAAO;AAAA,MACvB,YAAY,KAAK;AAAA,IACnB;AAEA,UAAM,gBAAgB,sBACnB,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,CAAC,EAAE,EACpC,KAAK,GAAG;AACX,UAAM,mBAAmB,SAAS,eAAe,KAAK,OAAO,eAAe;AAE5E,UAAM,YAAY;AAAA,MAChB,UAAU;AAAA,QACR,cAAc;AAAA,QACd,QAAQ,aAAa;AAAA,QACrB,UAAU,aAAa;AAAA,QACvB,aAAa,aAAa;AAAA,QAC1B,YAAY;AAAA,QACZ;AAAA,QACA,kBAAkB,KAAK,OAAO,aAAa;AAAA,QAC3C,kBAAkB,KAAK,OAAO;AAAA,MAChC;AAAA,MACA,QAAQ;AAAA,QACN,aAAa,KAAK,OAAO;AAAA,QACzB,WAAW,KAAK,OAAO;AAAA,QACvB,eAAe,KAAK,OAAO;AAAA,QAC3B,YAAY,aAAa;AAAA,QACzB,sBAAsB;AAAA,QACtB,YAAY,aAAa;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,sBAAsB,UAAU,KAAK,UAAU,SAAS,CAAC;AAE/D,UAAM,cAAuC;AAAA,MAC3C,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK,OAAO;AAAA,MACnB,mBAAmB,uBAAuB;AAAA,MAC1C,OAAO;AAAA,QACL,uBAAuB;AAAA,QACvB,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,YAAY,aAAa;AAAA,MAC3B;AAAA,IACF;AAEA,WAAO,EAAE,aAAa,oBAAoB;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,OACJ,gBACA,eACuB;AACvB,QAAI;AACF,YAAM,cAAc,mBAAmB,eAAe,OAAO;AAC7D,YAAM,UAAU,YAAY,WAAW;AAEvC,YAAM,WAAW,MAAM;AAAA,QACrB;AAAA,QACA;AAAA,UACE,eAAe,QAAQ,SAAS;AAAA,UAChC,UAAU,QAAQ,SAAS;AAAA,UAC3B,gBAAgB,QAAQ,OAAO;AAAA,QACjC;AAAA,QACA,KAAK,iBAAiB;AAAA,MACxB;AAEA,UAAI,SAAS,SAAS,SAAS;AAC7B,eAAO;AAAA,UACL,OAAO;AAAA,UACP,OAAO,iBAAiB,SAAS,IAAI,KAAK,SAAS,WAAW,SAAS,OAAO,SAAS;AAAA,UACvF,SAAS;AAAA,YACP,MAAM,SAAS;AAAA,YACf,UAAU,SAAS;AAAA,YACnB,SAAS,SAAS;AAAA,UACpB;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,UACP,UAAW,SAAS,YAAuB,QAAQ,SAAS;AAAA,UAC5D,QAAQ,SAAS;AAAA,UACjB,cAAc,SAAS;AAAA,UACvB,aAAa,SAAS;AAAA,UACtB,QAAQ,SAAS;AAAA,QACnB;AAAA,MACF;AAAA,IACF,SAAS,GAAY;AACnB,aAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,OACJ,gBACA,eACuB;AACvB,QAAI;AACF,YAAM,cAAc,mBAAmB,eAAe,OAAO;AAC7D,YAAM,UAAU,YAAY,WAAW;AACvC,YAAM,UAAU,QAAQ,SAAS;AAEjC,YAAM,WAAW,MAAM;AAAA,QACrB;AAAA,QACA,EAAE,UAAU,QAAQ;AAAA,QACpB,KAAK,iBAAiB;AAAA,MACxB;AAEA,UAAI,SAAS,SAAS,SAAS;AAC7B,eAAO;AAAA,UACL,SAAS;AAAA,UACT,aAAa;AAAA,UACb,OAAO,sBAAsB,SAAS,IAAI,KAAK,SAAS,WAAW,SAAS,OAAO,SAAS;AAAA,UAC5F,QAAQ;AAAA,QACV;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,QAAQ;AAAA,MACV;AAAA,IACF,SAAS,GAAY;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAA0C;AAC9C,UAAM,QAAQ,KAAK,IAAI;AAEvB,QAAI;AACF,0BAAAC,QAAO,iBAAiB,KAAK,OAAO,eAAe;AAAA,IACrD,SAAS,GAAY;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,0CAA0C,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,MAC7F;AAAA,IACF;AACA,QAAI;AACF,0BAAAA,QAAO,gBAAgB,KAAK,OAAO,qBAAqB;AAAA,IAC1D,SAAS,GAAY;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,uCAAuC,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,MAC1F;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,OAAO,eAAe;AAC9C,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,GAAI;AACzD,UAAM,WAAW,MAAM,MAAM,YAAY;AAAA,MACvC,QAAQ;AAAA,MACR,QAAQ,WAAW;AAAA,IACrB,CAAC,EAAE,MAAM,MAAM,IAAI;AACnB,iBAAa,OAAO;AAEpB,UAAM,YAAY,KAAK,IAAI,IAAI;AAE/B,QAAI,CAAC,UAAU;AACb,aAAO,EAAE,SAAS,OAAO,OAAO,wBAAwB,UAAU,IAAI,UAAU;AAAA,IAClF;AACA,WAAO,EAAE,SAAS,MAAM,UAAU;AAAA,EACpC;AAAA;AAAA,EAGQ,mBAAwC;AAC9C,WAAO;AAAA,MACL,aAAa,KAAK,OAAO,eAAe;AAAA,MACxC,QAAQ,KAAK,OAAO;AAAA,MACpB,iBAAiB,KAAK,OAAO;AAAA,MAC7B,uBAAuB,KAAK,OAAO;AAAA,MACnC,WAAW,KAAK,OAAO;AAAA,IACzB;AAAA,EACF;AACF;AAUO,SAAS,qBAA6B;AAE3C,SAAO,QAAQ,oBAAAA,QAAO,YAAY,EAAE,EAAE,SAAS,WAAW,EAAE,MAAM,GAAG,EAAE;AACzE;AASO,SAAS,gBAAgB,KAAmB;AACjD,QAAM,SAAS,IAAI,KAAK,IAAI,QAAQ,IAAI,oBAAoB;AAE5D,SAAO,OAAO,YAAY,EAAE,QAAQ,aAAa,GAAG;AACtD;AASO,SAAS,mBAAmB,SAA0B;AAC3D,MAAI,OAAO,YAAY,UAAU;AAC/B,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,IAAI,MAAM,+BAA+B;AAAA,IACjD;AACA,WAAO;AAAA,EACT;AACA,MAAI,YAAY,QAAQ,OAAO,YAAY,UAAU;AACnD,UAAM,MAAM;AACZ,UAAM,YAAY,IAAI,gBAAgB,IAAI;AAC1C,QAAI,OAAO,cAAc,YAAY,UAAU,SAAS,GAAG;AACzD,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EAEF;AACF;AAUO,SAAS,YAAY,aAAyC;AACnE,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,0BAA0B,WAAW,CAAC;AAAA,EAC5D,SAAS,GAAY;AACnB,UAAM,IAAI;AAAA,MACR,mCAAmC,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IAC/E;AAAA,EACF;AACA,MAAI,WAAW,QAAQ,OAAO,WAAW,UAAU;AACjD,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,QAAM,MAAM;AACZ,QAAM,WAAW,IAAI;AACrB,QAAM,SAAS,IAAI;AACnB,MAAI,CAAC,YAAY,OAAO,SAAS,kBAAkB,UAAU;AAC3D,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AACA,MAAI,OAAO,SAAS,aAAa,UAAU;AACzC,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AACA,MAAI,CAAC,UAAU,OAAO,OAAO,mBAAmB,UAAU;AACxD,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,SAAO;AACT;;;AI7eA;AAqBA,IAAAC,eAAwB;AACxB,IAAAC,eAAiB;AAoCV,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;AAC1F,SAAK,gBAAgB,SAAS,MAAM,IAAI,iBAAiB,CAAC;AAC1D,SAAK,gBAAgB,OAAO,CAAC,WAAW,IAAI,eAAe,QAAQ,gBAA0B,CAAC;AAC9F,SAAK,gBAAgB,UAAU,CAAC,WAAW;AAEzC,UAAI;AACJ,YAAM,cAAe,QAAgB,sBAAsB,QAAQ,IAAI;AAEvE,UAAI,aAAa;AACf,YAAI;AACF,4BAAkB,qBAAQ,cAAc,aAAAC,QAAK,OAAO,WAAW,CAAC;AAAA,QAClE,SAAS,GAAQ;AACf,kBAAQ,KAAK,8CAA8C,EAAE,OAAO,EAAE;AAAA,QACxE;AAAA,MACF;AAEA,aAAO,IAAI,kBAAkB,EAAE,gBAAgB,CAA4B;AAAA,IAC7E,CAAC;AACD,SAAK,gBAAgB,UAAU,CAAC,WAAW,IAAI,kBAAkB,MAA4C,CAAC;AAG9G,SAAK,YAAY,aAAa,EAAE,SAAS,OAAO,UAAU,CAAC,SAAS,OAAO,QAAQ,GAAG,UAAU,WAAW;AAAA,EAC7G;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;;;AC/VA;;;AV6CA,IAAMC,gBAAe;AACrB,IAAMC,2BAA0B;AAChC,IAAMC,kBAAiB;AACvB,IAAM,0BAA0B;AAGhC,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAC5B,IAAM,qBAAqB;AAK3B,IAAM,+BAA+B;AAIrC,IAAM,8BAA8B;AAYpC,SAAS,WAAW,OAAuB;AACzC,SAAO,OAAO,SAAS,EAAE,EACtB,QAAQ,iBAAiB,QAAM,mBAAmB,EAAE,CAAC,EACrD,QAAQ,MAAM,KAAK;AACxB;AAGA,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;AAAA,EACA,gBAAgB;AAAA;AAAA,IAEd,MAAM;AAAA;AAAA,IACN,MAAM;AAAA;AAAA,EACR;AAAA;AAAA,EAEA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA;AAAA,EAEA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA;AAAA,EAEA,kBAAkB;AAAA,IAChB,MAAM;AAAA;AAAA,EACR;AAAA,EACA,iBAAiB;AAAA,IACf,MAAM;AAAA;AAAA,EACR;AACF;AAGA,IAAMC,oBAA2C;AAAA,EAC/C,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,OAAO;AAAA,EACP,eAAe;AAAA,EACf,UAAU;AAAA,EACV,iBAAiB;AACnB;AAGA,SAAS,gBAAgB,SAA0B;AACjD,SAAO,QAAQ,WAAW,SAAS;AACrC;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB;AAAA,IACd,MAAM,EAAE,MAAM,WAAY,SAAS,IAAI;AAAA,IACvC,MAAM,EAAE,MAAM,YAAY,SAAS,IAAI;AAAA,EACzC;AAAA;AAAA,EAEA,aAAa;AAAA,IACX,MAAM,EAAE,MAAM,YAAY,SAAS,IAAI;AAAA,IACvC,MAAM,EAAE,MAAM,cAAc,SAAS,IAAI;AAAA,EAC3C;AAAA;AAAA,EAEA,aAAa;AAAA,IACX,MAAM,EAAE,MAAM,YAAY,SAAS,IAAI;AAAA,IACvC,MAAM,EAAE,MAAM,cAAc,SAAS,IAAI;AAAA,EAC3C;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,YAAI,uBAAW,OAAO,GAAG;AACvB,UAAI;AACF,cAAM,cAAU,yBAAa,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;AAAA,EAEA,oBAA8C;AAAA,EAEtD,YAAY,cAAsB,UAAyC,CAAC,GAAG;AAE7E,IAAAA,aAAY;AAGZ,UAAM,cAAU,yBAAa,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;AAInD,UAAM,kBAAkB,CAAC,SAAS,OAAO,QAAQ;AACjD,UAAM,cAAc,QAAQ,IAAI,sBAAsB,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/E,UAAM,oBAA0C,QAAQ,gBAAgB;AAAA,MACtE,SAAS,QAAQ,IAAI,uBAAuB;AAAA,MAC5C,UAAU,eAAe;AAAA,MACzB,UAAW,QAAQ,IAAI,wBAAgC;AAAA,MACvD,QAAQ;AAAA,QACN,KAAK,EAAE,YAAY,KAAK,WAAW;AAAA,MACrC;AAAA,IACF;AAQA,UAAM,iBAAiB,KAAK,SAAS,SAAS;AAC9C,QAAI,gBAAgB;AAClB,UAAI;AACF,cAAM,UAAe,cAAQ,YAAY;AAGzC,cAAM,aAAa,CAAC,GAAW,SAC7B,UAAM,yBAAkB,iBAAW,CAAC,IAAI,IAAS,cAAQ,SAAS,CAAC,GAAG,OAAO,GAAG,IAAI;AACtF,cAAM,0BAAmD;AAAA,UACvD,WAAW,eAAe;AAAA,UAC1B,QAAQ,eAAe;AAAA,UACvB,aAAa,eAAe;AAAA,UAC5B,oBAAoB,eAAe;AAAA,UACnC,iBAAiB,WAAW,eAAe,kBAAkB,SAAS;AAAA,UACtE,uBAAuB,WAAW,eAAe,wBAAwB,QAAQ;AAAA,UACjF,aAAa,eAAe;AAAA,UAC5B,WAAW,eAAe;AAAA,QAC5B;AACA,0BAAkB,SAAS;AAAA,UACzB,GAAG,kBAAkB;AAAA,UACrB,QAAQ;AAAA,QACV;AACA,0BAAkB,WAAW,kBAAkB,YAAY,CAAC;AAC5D,YAAI,kBAAkB,YAAY,YAAY,CAAC,kBAAkB,SAAS,SAAS,QAAQ,GAAG;AAC5F,4BAAkB,SAAS,KAAK,QAAQ;AAAA,QAC1C;AAAA,MACF,SAAS,KAAU;AACjB,cAAM,IAAI,MAAM,0DAA0D,IAAI,OAAO,EAAE;AAAA,MACzF;AAAA,IACF;AAEA,SAAK,WAAW,IAAI,oBAAoB,iBAAiB;AAEzD,QAAI,gBAAgB;AAClB,WAAK,oBAAoB,KAAK,SAAS,IAAI,QAAQ;AACnD,cAAQ,IAAI,oDAA+C,eAAe,SAAS,GAAG;AAAA,IACxF;AAGA,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;AAG/B,UAAM,oBAAoB,CAAC,WAAmB,mBAAoC;AAEhF,UAAI,eAAgB,QAAO;AAE3B,WAAK,cAAc,YAAY,cAAc,oBAAoB,SAAS,eAAe;AACvF,eAAO,SAAS;AAAA,MAClB;AAEA,aAAO,SAAS;AAAA,IAClB;AAIA,QAAI,SAAS,UAAU,SAAS,OAAO,SAAS,GAAG;AACjD,aAAO,SAAS,OAAO,IAAI,OAAK;AAC9B,cAAM,YAAY,OAAO,MAAM,WAAW,IAAI,EAAE;AAChD,cAAM,iBAAiB,OAAO,MAAM,WAAW,EAAE,SAAS;AAC1D,eAAO;AAAA,UACL,SAASD,kBAAiB,SAAS,KAAK;AAAA,UACxC,QAAQ,kBAAkB,WAAW,kBAAkB,MAAS;AAAA,UAChE,SAAS,OAAO,MAAM,WAAW,EAAE,SAAS,SAAS,CAAC,MAAM;AAAA,QAC9D;AAAA,MACF,CAAC;AAAA,IACH;AAGA,UAAM,QAAQ,SAAS,SAAS;AAChC,UAAM,UAAUA,kBAAiB,KAAK,KAAK,KAAK;AAChD,WAAO,CAAC;AAAA,MACN;AAAA,MACA,QAAQ,kBAAkB,KAAK;AAAA,MAC/B,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,aAAS,0BAAa,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeQ,iBAAiB,KAAsB,KAA2B;AACxE,UAAM,OAAQ,KAAK,QAAkC;AAGrD,QAAI,SAAS,OAAO;AAClB;AAAA,IACF;AAEA,UAAM,gBAAiB,IAAI,QAAQ,UAAiC;AAGpE,QAAI,SAAS,UAAa,SAAS,MAAM;AACvC,WAAK,iBAAiB,KAAK,GAAG;AAC9B;AAAA,IACF;AAGA,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAI,KAAK,SAAS,aAAa,GAAG;AAChC,aAAK,iBAAiB,KAAK,aAAa;AACxC,YAAI,UAAU,QAAQ,QAAQ;AAAA,MAChC;AAEA;AAAA,IACF;AAGA,UAAM,MAAM;AACZ,UAAM,YACJ,OAAO,IAAI,YAAY,aACnB,IAAI,QAAQ,aAAa,IACzB,IAAI,QAAQ,SAAS,aAAa;AACxC,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AACA,SAAK,iBAAiB,KAAK,aAAa;AACxC,QAAI,UAAU,QAAQ,QAAQ;AAC9B,QAAI,IAAI,aAAa;AACnB,UAAI,UAAU,oCAAoC,MAAM;AAAA,IAC1D;AACA,UAAM,SAAS,IAAI,UAAU;AAC7B,QAAI,UAAU,0BAA0B,OAAO,MAAM,CAAC;AAAA,EACxD;AAAA,EAEQ,iBAAiB,KAAqB,QAAsB;AAClE,QAAI,UAAU,+BAA+B,MAAM;AACnD,QAAI,UAAU,gCAAgC,oBAAoB;AAClE,QAAI,UAAU,gCAAgC,uDAAuD;AACrG,QAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAc,KAAsB,KAAoC;AAEpF,SAAK,iBAAiB,KAAK,GAAG;AAE9B,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,QAAQD,eAAc;AAChD,cAAM,cAAc,IAAI,QAAQ,2BAA2B;AAC3D,eAAO,MAAM,KAAK,cAAc,MAAM,eAAe,KAAK,WAAW;AAAA,MACvE;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,QAAQA,eAAc;AAChD,cAAM,aAAa,IAAI,QAAQ,eAAe;AAC9C,eAAO,MAAM,KAAK,YAAY,MAAM,eAAe,YAAY,GAAG;AAAA,MACpE;AAIA,YAAM,cAAc,IAAI,SAAS,QAAQ,OAAO,EAAE;AAClD,YAAM,QAAQ,KAAK,OAAO,IAAI,WAAW;AACzC,UAAI,UAAU,IAAI,WAAW,UAAU,IAAI,WAAW,QAAQ;AAC5D,cAAM,OAAO,IAAI,WAAW,SAAS,MAAM,KAAK,SAAS,GAAG,IAAI,CAAC;AACjE,cAAM,aAAa,IAAI,QAAQ,eAAe;AAC9C,cAAM,aAAa,IAAI,QAAQA,eAAc;AAC7C,cAAM,cAAc,IAAI,QAAQ,2BAA2B;AAC3D,eAAO,MAAM,KAAK,iBAAiB,OAAO,MAAM,YAAY,YAAY,KAAK,WAAW;AAAA,MAC1F;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,QACvC,eAAe,KAAK,SAAS,SAAS;AAAA,QACtC,QAAQ,KAAK,SAAS,SAAS;AAAA,MACjC;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT,UAAU;AAAA,QACV,SAAS;AAAA,QACT,QAAQ;AAAA,MACV;AAAA,MACA,SAAS;AAAA,QACP,UAAU;AAAA,QACV,SAASF;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,KACA,aACe;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;AAMA,QAAI,aAAa;AACf,YAAM,gBAAoC;AAAA,QACxC,aAAaA;AAAA,QACb,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,SAAS;AAAA,MACX;AACA,aAAO,KAAK,oBAAoB,OAAO,UAAU,CAAC,GAAG,eAAe,GAAG;AAAA,IACzE;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;AAKA,UAAM,YAAY,QAAQ,UAAU,UAAU,QAAQ;AACtD,UAAM,aAAa,QAAQ,UAAU,WAAW,QAAQ;AACxD,QAAI,cAAc,kBAAkB,aAAa,gBAAgB,UAAU,IAAI,QAAQ;AACrF,aAAO,KAAK,oBAAoB,OAAO,UAAU,CAAC,GAAG,SAAS,GAAG;AAAA,IACnE;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;AAIhE,UAAM,WAAW,gBAAgB,cAAc;AAC/C,QAAI,aAAkB;AAEtB,QAAI,UAAU;AACZ,cAAQ,IAAI,mFAAmF;AAC/F,UAAI;AACF,qBAAa,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AAC7D,gBAAQ,IAAI,iCAAiC,WAAW,WAAW,KAAK,WAAW,eAAe,SAAS,EAAE;AAAA,MAC/G,SAAS,KAAU;AACjB,gBAAQ,MAAM,wCAAwC,IAAI,OAAO;AACjE,eAAO,KAAK,SAAS,KAAK,KAAK;AAAA,UAC7B,OAAO;AAAA,UACP,SAAS,IAAI;AAAA,QACf,CAAC;AAAA,MACH;AAAA,IACF;AAGA,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;AAG/D,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,OAAO;AAAA,QACP,SAAS,IAAI;AAAA,QACb,gBAAgB,WAAW,OAAO;AAAA,QAClC,MAAM,WAAW,sEAAsE;AAAA,MACzF,CAAC;AAAA,IACH;AAGA,QAAI,CAAC,UAAU;AACb,cAAQ,IAAI,iDAAiD;AAC7D,UAAI;AACF,qBAAa,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AAC7D,gBAAQ,IAAI,iCAAiC,WAAW,WAAW,KAAK,WAAW,eAAe,SAAS,EAAE;AAAA,MAC/G,SAAS,KAAU;AACjB,gBAAQ,MAAM,iCAAiC,IAAI,OAAO;AAC1D,qBAAa,EAAE,SAAS,OAAO,OAAO,IAAI,SAAS,aAAa,OAAO;AAAA,MACzE;AAIA,UAAI,CAAC,YAAY,SAAS;AACxB,eAAO,KAAK,SAAS,KAAK,KAAK;AAAA,UAC7B,OAAO;AAAA,UACP,SAAS,YAAY,SAAS;AAAA,UAC9B,aAAa,YAAY;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF;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;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,oBACZ,OACA,QACA,SACA,KACe;AACf,QAAI,CAAC,KAAK,mBAAmB;AAC3B,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,4CAA4C,CAAC;AAAA,IACvF;AAIA,UAAM,eAAwC;AAAA,MAC5C,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ,MAAM,OAAO,QAAQ,aAAa;AAAA,MAC1C,OAAO,KAAK,SAAS,SAAS,QAAQ,aAAa;AAAA,MACnD,mBAAmB;AAAA,IACrB;AAEA,YAAQ,IAAI,wCAAwC;AACpD,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,yCAAyC,aAAa,WAAW,EAAE;AAG/E,UAAM,iBAAiB,SAAS,QAAQ,IAAI,yBAAyB,MAAM;AAC3E,YAAQ,IAAI,+BAA+B,MAAM,EAAE,cAAc,cAAc,IAAI;AACnF,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,QAAQ,KAAK;AAAA,QAC1B,MAAM,QAAQ,MAAM;AAAA,QACpB,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,QAAI;AACJ,QAAI;AACF,mBAAa,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AAC7D,UAAI,WAAW,SAAS;AACtB,gBAAQ,IAAI,4CAA4C,WAAW,WAAW,EAAE;AAAA,MAClF,OAAO;AACL,gBAAQ,MAAM,6DAA6D,WAAW,KAAK,EAAE;AAAA,MAC/F;AAAA,IACF,SAAS,KAAU;AACjB,cAAQ,MAAM,4DAA4D,IAAI,OAAO,EAAE;AACvF,mBAAa,EAAE,SAAS,OAAO,OAAO,IAAI,SAAS,aAAa,SAAS;AAAA,IAC3E;AAEA,UAAM,kBAA0C,CAAC;AACjD,QAAI,WAAW,SAAS;AACtB,sBAAgB,uBAAuB,IAAI,OAAO,KAAK,KAAK,UAAU;AAAA,QACpE,SAAS;AAAA,QACT,aAAa,WAAW;AAAA,QACxB,SAAS;AAAA,QACT,aAAa,WAAW;AAAA,MAC1B,CAAC,CAAC,EAAE,SAAS,QAAQ;AAAA,IACvB;AAEA,SAAK,SAAS,KAAK,KAAK;AAAA,MACtB,SAAS;AAAA,MACT;AAAA,MACA,SAAS,WAAW,UAChB,EAAE,aAAa,WAAW,aAAa,QAAQ,aAAa,aAAa,WAAW,YAAY,IAChG,EAAE,QAAQ,yBAAyB,OAAO,WAAW,MAAM;AAAA,IACjE,GAAG,eAAe;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,qBACZ,QACmF;AACnF,QAAI,CAAC,KAAK,qBAAqB,CAAC,OAAO,OAAQ,QAAO;AACtD,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,kBAAkB,0BAA0B;AAAA,QACjE,WAAW,OAAO,OAAO,cAAc,KAAK,SAAS,SAAS,OAAQ;AAAA,QACtE,UAAU,OAAO,OAAO;AAAA,QACxB,WAAW,OAAO,OAAO;AAAA,QACzB,YAAY,oBAAoB,OAAO,EAAE;AAAA,MAC3C,CAAC;AACD,aAAO,EAAE,SAAS,IAAI,aAAa,qBAAqB,IAAI,oBAAoB;AAAA,IAClF,SAAS,KAAU;AACjB,cAAQ,MAAM,gDAAgD,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE;AACzF,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,iBACZ,OACA,MACA,YACA,YACA,KACA,aACe;AACf,UAAM,SAAS,MAAM;AACrB,UAAM,SAAS,QAAQ,CAAC;AAGxB,QAAI,aAAa;AACf,aAAO,MAAM,KAAK,cAAc,EAAE,SAAS,OAAO,IAAI,OAAO,GAAG,QAAW,KAAK,WAAW;AAAA,IAC7F;AAGA,QAAI,YAAY;AACd,aAAO,MAAM,KAAK,cAAc,EAAE,SAAS,OAAO,IAAI,OAAO,GAAG,YAAY,GAAG;AAAA,IACjF;AAGA,QAAI,cAAc,WAAW,YAAY,EAAE,WAAW,UAAU,GAAG;AACjE,aAAO,MAAM,KAAK,iBAAiB,OAAO,QAAQ,YAAY,GAAG;AAAA,IACnE;AAGA,WAAO,KAAK,uBAAuB,QAAQ,GAAG;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBACZ,OACA,QACA,YACA,KACe;AACf,UAAM,SAAS,MAAM;AAGrB,UAAM,kBAAkB,WAAW,MAAM,iBAAiB;AAC1D,QAAI,CAAC,iBAAiB;AACpB,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,sCAAsC,CAAC;AAAA,IACjF;AAEA,QAAI;AAgBJ,QAAI;AAEF,YAAM,SAAS,gBAAgB,CAAC,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AACtE,YAAM,UAAU,OAAO,KAAK,QAAQ,QAAQ,EAAE,SAAS,OAAO;AAC9D,sBAAgB,KAAK,MAAM,OAAO;AAAA,IACpC,SAAS,KAAK;AACZ,cAAQ,MAAM,8CAA8C,GAAG;AAC/D,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,sCAAsC,CAAC;AAAA,IACjF;AAGA,QAAI;AACJ,QAAI,cAAc,SAAS,SAAS,UAAU,cAAc,SAAS,MAAM;AACzE,eAAS,cAAc,QAAQ;AAAA,IACjC,WAAW,cAAc,SAAS,SAAS,eAAe;AAGxD,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,QAAQ;AACX,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,yCAAyC,CAAC;AAAA,IACpF;AAGA,QAAI,UAAU,cAAc,WAAW,SAAS,eAAe;AAC/D,QAAI,CAAC,WAAW,cAAc,QAAQ;AACpC,YAAM,aAAa,cAAc,OAAO,MAAM,cAAc;AAC5D,UAAI,WAAY,WAAU,SAAS,WAAW,CAAC,GAAG,EAAE;AAAA,IACtD;AACA,cAAU,WAAW;AAGrB,UAAM,UAAU,UAAU,OAAO;AAEjC,QAAI,CAAC,KAAK,kBAAkB,OAAO,GAAG;AACpC,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,OAAO,yBAAyB,OAAO;AAAA,MACzC,CAAC;AAAA,IACH;AAGA,UAAM,eAAe,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,MACA,KAAK,oBAAoB,OAAO;AAAA,MAChC;AAAA,IACF;AAGA,UAAM,iBAAqC;AAAA,MACzC,aAAaA;AAAA,MACb,QAAQ;AAAA,MACR;AAAA,MACA,SAAS;AAAA,QACP;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,IAAI,4CAA4C,MAAM,aAAa,OAAO,EAAE;AAGpF,UAAM,eAAe,MAAM,KAAK,SAAS,OAAO,gBAAgB,YAAY;AAE5E,QAAI,CAAC,aAAa,OAAO;AACvB,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,OAAO,gCAAgC,aAAa,KAAK;AAAA,MAC3D,CAAC;AAAA,IACH;AAEA,YAAQ,IAAI,mDAAmD,OAAO,EAAE,EAAE;AAG1E,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,MAAM,QAAQ,MAAM;AAAA,IACrC,SAAS,KAAU;AACjB,cAAQ,MAAM,qCAAqC,GAAG;AACtD,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,OAAO,6BAA6B,IAAI,OAAO;AAAA,MACjD,CAAC;AAAA,IACH;AAGA,UAAM,UAAU;AAAA,MACd,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,aAAa,aAAa;AAAA,IAC5B;AACA,UAAM,iBAAiB,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,SAAS,QAAQ;AAG7E,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,CAAC,kBAAkB,GAAG;AAAA,IACxB,CAAC;AACD,QAAI,IAAI,KAAK,UAAU;AAAA,MACrB,SAAS;AAAA,MACT;AAAA,MACA,SAAS;AAAA,QACP;AAAA,QACA,QAAQ;AAAA,QACR,aAAa,aAAa;AAAA,MAC5B;AAAA,IACF,GAAG,MAAM,CAAC,CAAC;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,uBAAuB,QAAuB,KAAoC;AAC9F,UAAM,iBAAiB,sBAAsB,MAAM;AACnD,UAAM,iBAAiB,KAAK,kBAAkB;AAG9C,UAAM,UAAqC,CAAC;AAC5C,eAAW,eAAe,gBAAgB;AACxC,iBAAW,SAAS,gBAAgB;AAClC,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,kBAAkB,MAAM,KAAK,qBAAqB,MAAM;AAC9D,QAAI,iBAAiB;AACnB,cAAQ,KAAK,gBAAgB,OAAO;AAAA,IACtC;AAEA,UAAM,sBAAsB;AAAA,MAC1B,aAAaA;AAAA,MACb;AAAA,MACA,oBAAoB;AAAA,MACpB,UAAU;AAAA,QACR,KAAK,IAAI,OAAO,EAAE;AAAA,QAClB,aAAa,GAAG,OAAO,IAAI,OAAO,OAAO,KAAK,IAAI,OAAO,QAAQ;AAAA,MACnE;AAAA,IACF;AACA,UAAM,cAAc,OAAO,KAAK,KAAK,UAAU,mBAAmB,CAAC,EAAE,SAAS,QAAQ;AAItF,UAAM,aAAa,eAAe,KAAK,OAAK,EAAE,YAAY,cAAc;AAExE,QAAI,aAAa;AACjB,QAAI,YAAY;AACd,YAAM,cAAc,KAAK,oBAAoB;AAC7C,YAAM,gBAAgB,KAAK,MAAM,OAAO,QAAQ,GAAG,EAAE,SAAS;AAC9D,YAAM,eAAe,gBAAgB,cAAc,GAAG,QAAQ;AAE9D,YAAM,aAAa;AAAA,QACjB,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,eAAe;AAAA,UACb,SAAS;AAAA,UACT,UAAU;AAAA,QACZ;AAAA,QACA,WAAW,WAAW;AAAA,MACxB;AACA,YAAM,oBAAoB,OAAO,KAAK,KAAK,UAAU,UAAU,CAAC,EAAE,SAAS,QAAQ;AAEnF,YAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,GAAI,EAAE,YAAY;AAEnE,mBAAa,eAAe,WAAW,aAAa,WAAW,KAAK,SAAS,SAAS,IAAI,CAAC,gDAAgD,iBAAiB,mBAAmB,WAAW,OAAO,IAAI,CAAC,eAAe,SAAS;AAAA,IAChO;AAGA,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,CAACC,wBAAuB,GAAG;AAAA,IAC7B;AAEA,QAAI,YAAY;AACd,cAAQ,mBAAmB,IAAI;AAAA,IACjC;AAEA,QAAI,iBAAiB;AACnB,cAAQ,4BAA4B,IAAI,gBAAgB;AAAA,IAC1D;AAEA,QAAI,UAAU,KAAK,OAAO;AAC1B,QAAI,IAAI,KAAK,UAAU;AAAA,MACrB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ,wBAAwB,OAAO,IAAI;AAAA,MAC3C,SAAS,OAAO;AAAA,MAChB,OAAO,OAAO;AAAA,MACd,UAAU,OAAO;AAAA,MACjB,oBAAoB;AAAA,IACtB,GAAG,MAAM,CAAC,CAAC;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAA8B;AACpC,UAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,CAAC,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAAA,IAC3C;AACA,WAAO,OAAO,KAAK,KAAK,EAAE,SAAS,WAAW;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,oBAAoB,QAAuB,KAAoC;AAC3F,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,kBAAkB,MAAM,KAAK,qBAAqB,MAAM;AAC9D,QAAI,iBAAiB;AACnB,cAAQ,KAAK,gBAAgB,OAAO;AAAA,IACtC;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,aAAaD;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,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,CAACC,wBAAuB,GAAG;AAAA,IAC7B;AAKA,QAAI,iBAAiB;AACnB,cAAQ,4BAA4B,IAAI,gBAAgB;AAAA,IAC1D;AAEA,QAAI,UAAU,KAAK,OAAO;AAC1B,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,gBAAgBD,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;AAKrE,QAAI,WAAW,WAAW,WAAW,UAAU;AAC7C,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;AAIjE,UAAM,UAAU,oBAAoB;AACpC,UAAM,SAAS,UAAU,WAAW;AAEpC,UAAM,eAAwC;AAAA,MAC5C;AAAA,MACA,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,mBAAmB;AAAA,MACnB,OAAO;AAAA,IACT;AAGA,QAAI,oBAAoB,oBAAoB,oBAAoB,iBAAiB;AAC/E,YAAM,oBAAoB,KAAK,SAAS,IAAI,QAAQ;AACpD,YAAM,iBAAiB,mBAAmB,oBAAoB;AAC9D,UAAI,gBAAgB;AAClB,QAAC,aAAa,QAAgB;AAAA,UAC5B,GAAI,aAAa,SAAS,CAAC;AAAA,UAC3B,gBAAgB;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAGA,QAAI,oBAAoB,eAAe,oBAAoB,aAAa;AACtE,YAAM,iBAAiB,KAAK,SAAS,IAAI,KAAK;AAC9C,YAAM,iBAAiB,gBAAgB,oBAAoB;AAC3D,UAAI,gBAAgB;AAClB,QAAC,aAAa,QAAgB;AAAA,UAC5B,GAAI,aAAa,SAAS,CAAC;AAAA,UAC3B,YAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAKA,QAAI,SAAS;AACX,YAAM,mBAAmB,KAAK,SAAS,IAAI,OAAO;AAClD,YAAM,eAAe,kBAAkB,oBAAoB;AAC3D,UAAI,cAAc;AAChB,QAAC,aAAa,QAAgB;AAAA,UAC5B,GAAI,aAAa,SAAS,CAAC;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;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,CAACK,UAAS,WAAW;AACtC,UAAI,OAAO;AACX,UAAI,GAAG,QAAQ,WAAS,QAAQ,KAAK;AACrC,UAAI,GAAG,OAAO,MAAM;AAClB,YAAI;AACF,UAAAA,SAAQ,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,aAAO;AAAA,IACT;AAGA,QAAI,WAAW,SAAS,GAAG,GAAG;AAC5B,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;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAc,YACZ,MACA,eACA,YACA,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,UAAM,kBAAkB,CAAC,QAAQ,WAAW,gBAAgB,kBAAkB,OAAO,eAAe,UAAU,eAAe;AAC7H,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,gBAAgB,UAAU,YAAY,UAAU;AACtD,UAAM,oBAAoB,sBAAsB,KAAK,MAAM;AAC3D,UAAMC,wBAAuB,gCAAgC,KAAK,MAAM;AAExE,QAAI,iBAAiB,CAACA,uBAAsB;AAC1C,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,uCAAuC,CAAC;AAAA,IAClF;AACA,QAAI,CAAC,iBAAiB,CAAC,mBAAmB;AACxC,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,oCAAoC,CAAC;AAAA,IAC/E;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,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,QAAI,UAAU,kBAAkB;AAC9B,aAAO,MAAM,KAAK,eAAe,MAAM,aAAa,YAAY,GAAG;AAAA,IACrE;AAIA,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,gBAAgBN,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,WAAW,WAAW,UAAU;AAC7C,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,uBAAuB,MAAM,GAAG,CAAC;AAAA,IAC3E;AAGA,UAAM,kBAAkB,QAASG,kBAAiB,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,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;AAIA,YAAM,WAAW,gBAAgB,OAAO;AACxC,UAAII,cAAkB;AAEtB,UAAI,UAAU;AACZ,gBAAQ,IAAI,6DAA6D;AACzE,YAAI;AACF,UAAAA,cAAa,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AAC7D,kBAAQ,IAAI,yCAAyCA,YAAW,WAAW,KAAKA,YAAW,eAAe,SAAS,EAAE;AAGrH,cAAI,CAACA,YAAW,SAAS;AACvB,oBAAQ,MAAM,gDAAgDA,YAAW,KAAK,EAAE;AAChF,mBAAO,KAAK,SAAS,KAAK,KAAK;AAAA,cAC7B,SAAS;AAAA,cACT,gBAAgB;AAAA,cAChB,OAAO,8BAA8BA,YAAW,SAAS,eAAe;AAAA,YAC1E,CAAC;AAAA,UACH;AAAA,QACF,SAAS,KAAU;AACjB,kBAAQ,MAAM,gDAAgD,IAAI,OAAO;AACzE,iBAAO,KAAK,SAAS,KAAK,KAAK;AAAA,YAC7B,SAAS;AAAA,YACT,gBAAgB;AAAA,YAChB,OAAO,8BAA8B,IAAI,OAAO;AAAA,UAClD,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL,gBAAQ,IAAI,8DAA8D,OAAO,EAAE;AAAA,MACrF;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,oCAAoC;AAAA,MAClD,SAAS,KAAU;AAEjB,gBAAQ,MAAM,oCAAoC,IAAI,OAAO,EAAE;AAG/D,eAAO,KAAK,SAAS,KAAK,KAAK;AAAA,UAC7B,SAAS;AAAA,UACT,gBAAgB,WAAW,OAAO;AAAA,UAClC,OAAO,6BAA6B,IAAI,OAAO;AAAA,UAC/C,MAAM,WAAW,sEAAsE;AAAA,QACzF,CAAC;AAAA,MACH;AAGA,UAAI,CAAC,UAAU;AACb,gBAAQ,IAAI,wCAAwC;AACpD,YAAI;AACF,UAAAA,cAAa,MAAM,KAAK,SAAS,OAAO,SAAS,YAAY;AAC7D,kBAAQ,IAAI,yCAAyCA,YAAW,WAAW,KAAKA,YAAW,eAAe,SAAS,EAAE;AAAA,QACvH,SAAS,KAAU;AACjB,kBAAQ,MAAM,yCAAyC,IAAI,OAAO;AAElE,iBAAO,KAAK,SAAS,KAAK,KAAK;AAAA,YAC7B,SAAS;AAAA,YACT,UAAU;AAAA,YACV,SAAS;AAAA,YACT,iBAAiB,IAAI;AAAA,YACrB,MAAO,QAAQ,SAAiB,eAAe;AAAA,YAC/C,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,UAAU,YAAY;AAAA,YACtB;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;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,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,EAKA,MAAc,eACZ,MACA,QACA,YACA,KACe;AACf,UAAM,EAAE,QAAQ,QAAQ,MAAM,UAAU,IAAI;AAC5C,UAAM,YAAY,WAAW,MAAM;AACnC,UAAM,gBAAgB,KAAK,MAAM,YAAY,GAAG,EAAE,SAAS;AAG3D,QAAI,CAAC,cAAc,CAAC,WAAW,YAAY,EAAE,WAAW,UAAU,GAAG;AACnE,YAAM,cAAc,KAAK,oBAAoB;AAC7C,YAAM,eAAe,gBAAgB,cAAc,GAAG,QAAQ;AAE9D,YAAM,aAAa;AAAA,QACjB,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,eAAe;AAAA,UACb,SAAS;AAAA,UACT,UAAU;AAAA,QACZ;AAAA,QACA,WAAW;AAAA,MACb;AACA,YAAM,oBAAoB,OAAO,KAAK,KAAK,UAAU,UAAU,CAAC,EAAE,SAAS,QAAQ;AAEnF,YAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,GAAI,EAAE,YAAY;AAEnE,YAAM,UAAU,eAAe,WAAW,wEAAwE,iBAAiB,mBAAmB,WAAW,OAAO,IAAI,CAAC,eAAe,SAAS;AAErM,UAAI,UAAU,KAAK;AAAA,QACjB,gBAAgB;AAAA,QAChB,CAAC,mBAAmB,GAAG;AAAA,MACzB,CAAC;AACD,UAAI,IAAI,KAAK,UAAU;AAAA,QACrB,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,wBAAwB,OAAO,IAAI;AAAA,QAC3C,SAAS,aAAa;AAAA,QACtB,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,GAAG,MAAM,CAAC,CAAC;AACX;AAAA,IACF;AAGA,UAAM,kBAAkB,WAAW,MAAM,iBAAiB;AAC1D,QAAI,CAAC,iBAAiB;AACpB,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,sCAAsC,CAAC;AAAA,IACjF;AAEA,QAAI;AAMJ,QAAI;AACF,YAAM,SAAS,gBAAgB,CAAC,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AACtE,YAAM,UAAU,OAAO,KAAK,QAAQ,QAAQ,EAAE,SAAS,OAAO;AAC9D,sBAAgB,KAAK,MAAM,OAAO;AAAA,IACpC,SAAS,KAAK;AACZ,cAAQ,MAAM,sDAAsD,GAAG;AACvE,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,sCAAsC,CAAC;AAAA,IACjF;AAGA,QAAI;AACJ,QAAI,cAAc,SAAS,SAAS,UAAU,cAAc,SAAS,MAAM;AACzE,eAAS,cAAc,QAAQ;AAAA,IACjC,OAAO;AACL,aAAO,KAAK,SAAS,KAAK,KAAK,EAAE,OAAO,yCAAyC,CAAC;AAAA,IACpF;AAEA,YAAQ,IAAI,uCAAuC,MAAM,cAAc;AAGvE,UAAM,eAAe,KAAK,yBAAyB,QAAQ,gBAAgB,QAAQ,MAAM;AAGzF,UAAM,iBAAqC;AAAA,MACzC,aAAaP;AAAA,MACb,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,SAAS,EAAE,QAAQ,SAAS,MAAM;AAAA,IACpC;AAGA,UAAM,eAAe,MAAM,KAAK,SAAS,OAAO,gBAAgB,YAAY;AAE5E,QAAI,CAAC,aAAa,OAAO;AACvB,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,OAAO,gCAAgC,aAAa,KAAK;AAAA,MAC3D,CAAC;AAAA,IACH;AAEA,YAAQ,IAAI,8CAA8C,aAAa,WAAW,EAAE;AAGpF,UAAM,EAAE,SAAS,SAAS,OAAO,IAAI;AAErC,QAAI,WAAW,SAAS;AACtB,cAAQ,IAAI,2CAA2C,OAAO,EAAE;AAChE,YAAM,QAAQ,KAAK,OAAO,IAAI,OAAO;AACrC,UAAI,CAAC,OAAO;AACV,eAAO,KAAK,SAAS,KAAK,KAAK;AAAA,UAC7B,SAAS;AAAA,UACT,gBAAgB;AAAA;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;AAAA,MACH,SAAS,KAAU;AACjB,gBAAQ,MAAM,wCAAwC,IAAI,OAAO,EAAE;AACnE,eAAO,KAAK,SAAS,KAAK,KAAK;AAAA,UAC7B,SAAS;AAAA,UACT,gBAAgB;AAAA,UAChB,OAAO,6BAA6B,IAAI,OAAO;AAAA,QACjD,CAAC;AAAA,MACH;AAEA,aAAO,KAAK,SAAS,KAAK,KAAK;AAAA,QAC7B,SAAS;AAAA,QACT,UAAU;AAAA,QACV;AAAA,QACA,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,aAAa,aAAa;AAAA,QAC1B;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAGA,SAAK,SAAS,KAAK,KAAK;AAAA,MACtB,SAAS;AAAA,MACT,UAAU;AAAA,MACV;AAAA,MACA,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa,aAAa;AAAA,MAC1B;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,QAASG,kBAAiB,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,UAAM,eAAwC;AAAA,MAC5C,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA;AAAA,MACP,mBAAmB;AAAA,MACnB,OAAO;AAAA,IACT;AAGA,QAAI,cAAc,eAAe,cAAc,aAAa;AAC1D,YAAM,iBAAiB,KAAK,SAAS,IAAI,KAAK;AAC9C,YAAM,iBAAiB,gBAAgB,oBAAoB;AAC3D,UAAI,gBAAgB;AAClB,QAAC,aAAa,QAAgB;AAAA,UAC5B,GAAI,aAAa,SAAS,CAAC;AAAA,UAC3B,YAAY;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;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,aAAaH;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,CAACC,wBAAuB,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;;;AW58DA;AAmLA,eAAsB,YAAY,KAA4B;AAC5D,QAAM,eAAe,MAAM,OAAO,iBAAiB;AACnD,QAAM,SAAS,aAAa,WAAW;AAEvC,SAAO,IAAI,QAAQ,CAACO,aAAY;AAC9B,WAAO,SAAS,KAAK,EAAE,OAAO,KAAK,GAAG,CAAC,OAAe;AACpD,cAAQ,IAAI,EAAE;AACd,MAAAA,SAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;;;AtCpJA,eAA0B;AAzB1B,IAAI,CAAC,WAAW,QAAQ;AACtB,EAAC,WAAmB,SAAS;AAC/B;AA0BA,SAAS,aAAqB;AAE5B,QAAM,YAAY;AAAA,QAChB,mBAAK,WAAW,oBAAoB;AAAA,QACpC,mBAAK,WAAW,iBAAiB;AAAA,QACjC,mBAAK,QAAQ,IAAI,GAAG,oCAAoC;AAAA,EAC1D;AACA,aAAW,OAAO,WAAW;AAC3B,QAAI;AACF,cAAI,uBAAW,GAAG,GAAG;AACnB,cAAM,MAAM,KAAK,UAAM,yBAAa,KAAK,OAAO,CAAC;AACjD,YAAI,IAAI,SAAS,WAAY,QAAO,IAAI;AAAA,MAC1C;AAAA,IACF,QAAQ;AAAA,IAAe;AAAA,EACzB;AACA,SAAO;AACT;AAGA,IAAM,kBAAkB,QAAQ,IAAI;AAEpC,IAAM,sBAAsB,QAAQ,IAAI,wBAAwB;AAEhE,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AACF;AAMA,eAAe,kBACb,QACA,OACA,gBACA,aAAsB,OACP;AACf,QAAM,cAAc,OAAO,KAAK;AAChC,QAAM,WAAW,IAAI,sBAAO,gBAAgB,YAAY,GAAG;AAG3D,QAAM,SAAS,OAAO,UAAU;AAChC,MAAI,CAAC,QAAQ;AACX,YAAQ,IAAI,2BAAsB;AAClC;AAAA,EACF;AACA,QAAM,SAAS,OAAO,QAAQ,QAAQ;AAEtC,UAAQ,IAAI,eAAe,cAAc,EAAE;AAG3C,MAAI,aAAa,MAAM,SAAS,WAAW,OAAO,OAAO;AACzD,QAAM,iBAAiB,sBAAO,WAAW,QAAQ;AAEjD,MAAI,aAAa,gBAAgB;AAC/B,QAAI,cAAc,iBAAiB;AACjC,cAAQ,IAAI,+CAA0C;AACtD,UAAI;AACF,cAAM,gBAAgB,IAAI,sBAAO,OAAO,iBAAiB,QAAQ;AACjE,cAAM,KAAK,MAAM,cAAc,gBAAgB;AAAA,UAC7C,IAAI,OAAO;AAAA,UACX,OAAO,sBAAO,WAAW,OAAO;AAAA,QAClC,CAAC;AACD,cAAM,GAAG,KAAK;AACd,gBAAQ,IAAI,sCAAiC,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC,MAAM;AACvE,qBAAa,MAAM,SAAS,WAAW,OAAO,OAAO;AAAA,MACvD,SAAS,KAAU;AACjB,gBAAQ,IAAI,4CAAkC,IAAI,OAAO,EAAE;AAC3D,gBAAQ,IAAI,yEAAkE;AAC9E;AAAA,MACF;AAAA,IACF,OAAO;AACL,cAAQ,IAAI,iDAAuC;AACnD,cAAQ,IAAI,2DAAoD;AAChE,cAAQ,IAAI,6CAA6C,KAAK,cAAc,cAAc,EAAE;AAC5F;AAAA,IACF;AAAA,EACF;AAGA,aAAW,eAAe,CAAC,QAAQ,MAAM,GAAY;AACnD,UAAM,cAAc,YAAY,OAAO,WAAW;AAClD,UAAM,gBAAgB,IAAI,sBAAO,SAAS,YAAY,SAAS,mBAAmB,MAAM;AAGxF,UAAM,YAAY,MAAM,cAAc,UAAU,OAAO,SAAS,cAAc;AAC9E,QAAI,YAAY,IAAI;AAClB,cAAQ,IAAI,aAAQ,WAAW,0BAA0B,eAAe,MAAM,GAAG,EAAE,CAAC,KAAK;AACzF;AAAA,IACF;AAEA,YAAQ,IAAI,uBAAkB,WAAW,KAAK;AAC9C,QAAI;AACF,YAAM,KAAK,MAAM,cAAc,QAAQ,gBAAgB,sBAAO,UAAU;AACxE,YAAM,GAAG,KAAK;AACd,cAAQ,IAAI,aAAQ,WAAW,mBAAmB,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC,MAAM;AAAA,IAC9E,SAAS,KAAU;AACjB,cAAQ,IAAI,aAAQ,WAAW,uBAAuB,IAAI,OAAO,EAAE;AAAA,IACrE;AAAA,EACF;AAEA,UAAQ,IAAI,EAAE;AAChB;AAKA,eAAe,kBACb,SACA,OACA,YAAoBC,qBAC+C;AACnE,QAAM,cAAc,OAAO,KAAK;AAChC,QAAM,WAAW,IAAI,sBAAO,gBAAgB,YAAY,GAAG;AAG3D,MAAI,iBAAgC;AACpC,MAAI;AACF,UAAM,iBAAa,mBAAK,WAAW,aAAa;AAChD,UAAM,aAAa,KAAK,UAAM,yBAAa,YAAY,OAAO,CAAC;AAC/D,qBAAiB,WAAW,YAAY,KAAK,KAAK;AAAA,EACpD,QAAQ;AAAA,EAER;AAEA,QAAM,SAAS,EAAE,MAAM,OAAO,MAAM,OAAO,SAAS,eAAe;AAEnE,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,EACT;AAEA,aAAW,eAAe,CAAC,QAAQ,MAAM,GAAY;AACnD,UAAM,cAAc,YAAY,OAAO,WAAW;AAClD,UAAM,gBAAgB,IAAI,sBAAO,SAAS,YAAY,SAAS,mBAAmB,QAAQ;AAC1F,UAAM,YAAY,MAAM,cAAc,UAAU,SAAS,cAAc;AACvE,WAAO,YAAY,YAAY,CAAoB,IAAI,YAAY;AAAA,EACrE;AAEA,SAAO;AACT;AAEA,IAAM,UAAU,IAAI,yBAAQ;AAC5B,IAAMA,0BAAqB,uBAAK,oBAAQ,GAAG,WAAW;AACtD,IAAM,eAAW,mBAAKA,qBAAoB,YAAY;AAGtD,IAAI,KAAC,uBAAWA,mBAAkB,GAAG;AACnC,4BAAUA,qBAAoB,EAAE,WAAW,KAAK,CAAC;AACnD;AAEA,SAAS,OAAO,UAAmC;AACjD,QAAM,KAAc,yBAAgB;AAAA,IAClC,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ;AAAA,EAClB,CAAC;AACD,SAAO,IAAI,QAAQ,CAAAC,aAAW;AAC5B,OAAG,SAAS,UAAU,YAAU;AAC9B,SAAG,MAAM;AACT,MAAAA,SAAQ,OAAO,KAAK,CAAC;AAAA,IACvB,CAAC;AAAA,EACH,CAAC;AACH;AAEA,QACG,KAAK,UAAU,EACf,YAAY,iDAAiD,EAC7D,QAAQ,WAAW,CAAC;AAKvB,QACG,QAAQ,MAAM,EACd,YAAY,wDAAwD,EACpE,OAAO,mBAAmB,qBAAqB,MAAM,EACrD,OAAO,yBAAyB,4BAA4B,EAC5D,OAAO,0BAA0B,oBAAoB,EACrD,OAAO,sBAAsB,oBAAoBD,mBAAkB,EACnE,OAAO,OAAO,YAAY;AAEzB,MAAI,QAAQ,QAAQ;AAGpB,QAAM,qBAAqB,CAAC,QAAQ,WAAW,gBAAgB,kBAAkB,OAAO,aAAa;AACrG,QAAM,wBAAwB,CAAC,UAAU,eAAe;AACxD,QAAM,kBAAkB,CAAC,GAAG,oBAAoB,GAAG,qBAAqB;AAExE,MAAI,CAAC,gBAAgB,SAAS,KAAK,GAAG;AACpC,YAAQ,MAAM,yBAAoB,KAAK,gBAAgB,gBAAgB,KAAK,IAAI,CAAC,EAAE;AACnF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,sBAAsB,SAAS,KAAK,GAAG;AACzC,YAAQ,IAAI,mCAA4B;AAExC,QAAI,mBAAmB,QAAQ,SAAS,GAAG;AACzC,YAAM,kBAAkB,iBAAiB,QAAQ,SAAS;AAC1D,cAAQ,IAAI,+CAAqC,eAAe,EAAE;AAClE,cAAQ,IAAI,kBAAkB,QAAQ,SAAS,EAAE;AACjD;AAAA,IACF;AAEA,YAAQ,IAAI,2BAA2B;AACvC,UAAM,UAAU,mBAAmB,QAAQ,SAAS;AACpD,UAAM,UAAU,QAAQ,UAAU,SAAS;AAE3C,YAAQ,IAAI;AAAA,gCAA8B,OAAO,EAAE;AACnD,YAAQ,IAAI;AAAA,iCAAyB,mBAAK,QAAQ,WAAW,oBAAoB,CAAC,EAAE;AACpF,YAAQ,IAAI;AAAA,mDAA4C;AACxD,YAAQ,IAAI;AAAA,CAA2C;AAEvD,QAAI,UAAU,iBAAiB;AAC7B,cAAQ,IAAI,+BAAwB;AACpC,cAAQ,IAAI,gDAAgD;AAAA,IAC9D,OAAO;AACL,cAAQ,IAAI;AAAA,CAA+E;AAAA,IAC7F;AAEA;AAAA,EACF;AAGA,UAAQ,IAAI,qCAA8B;AAE1C,UAAI,2BAAW,mBAAK,QAAQ,WAAW,aAAa,CAAC,GAAG;AACtD,YAAQ,IAAI,yFAA+E;AAC3F,YAAQ,IAAI,kBAAkB,QAAQ,SAAS,EAAE;AACjD;AAAA,EACF;AAEA,MAAI,WAAW,QAAQ,WAAW,WAAW,QAAQ,QAAQ,IAAI;AACjE,MAAI,YAAY,QAAQ,YAAY,WAAW,QAAQ,SAAS,IAAI;AAEpE,MAAI,CAAC,UAAU;AACb,UAAM,SAAS,MAAM,OAAO,mCAAmC;AAC/D,eAAW,SAAS,WAAW,MAAM,IAAI;AAAA,EAC3C;AAEA,MAAI,CAAC,WAAW;AACd,UAAM,SAAS,MAAM,OAAO,4BAA4B;AACxD,gBAAY,SAAS,WAAW,MAAM,IAAI;AAAA,EAC5C;AAEA,UAAQ,IAAI,sBAAsB;AAElC,QAAM,SAAS,eAAe,KAAK,QAAQ,WAAW;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,UAAQ,IAAI;AAAA,yBAAuB,OAAO,OAAO,EAAE;AACnD,UAAQ,IAAI;AAAA,6BAAyB,OAAO,SAAS,EAAE;AACvD,UAAQ,IAAI;AAAA,uCAA4B,mBAAK,OAAO,WAAW,aAAa,CAAC,EAAE;AAC/E,UAAQ,IAAI;AAAA,CAA2C;AAGvD,MAAI,UAAU,SAAS,UAAU,eAAe;AAC9C,YAAQ,IAAI,+CAAwC;AACpD,YAAQ,IAAI,kEAAwD;AACpE,YAAQ,IAAI,mCAAmC,KAAK;AAAA,CAAwB;AAC5E,UAAM,SAAS,IAAI,eAAe,EAAE,WAAW,QAAQ,UAAU,CAAC;AAClE,UAAM,kBAAkB,QAAQ,OAAO,qBAAqB,IAAI;AAAA,EAClE;AAEA,UAAQ,IAAI,2CAAoC,KAAK;AAAA,CAA6B;AACpF,CAAC;AAKH,QACG,QAAQ,QAAQ,EAChB,YAAY,0BAA0B,EACtC,OAAO,yBAAyB,4BAA4B,EAC5D,OAAO,0BAA0B,oBAAoB,EACrD,OAAO,sBAAsB,oBAAoBA,mBAAkB,EACnE,OAAO,OAAO,YAAY;AACzB,QAAM,SAAS,IAAI,eAAe,EAAE,WAAW,QAAQ,UAAU,CAAC;AAElE,MAAI,CAAC,OAAO,eAAe;AACzB,YAAQ,IAAI,gDAA2C;AACvD;AAAA,EACF;AAEA,QAAM,gBAAgB,OAAO,UAAU;AAGvC,MAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,WAAW;AAC3C,YAAQ,IAAI,iCAA0B;AACtC,YAAQ,IAAI,cAAc,OAAO,OAAO,EAAE;AAC1C,YAAQ,IAAI,aAAa,cAAc,KAAK,EAAE;AAC9C,YAAQ,IAAI,mBAAmB,cAAc,OAAO,QAAQ,EAAE;AAC9D,YAAQ,IAAI,oBAAoB,cAAc,OAAO,SAAS,EAAE;AAChE,YAAQ,IAAI,EAAE;AAEd,UAAM,iBAAiB,MAAM,OAAO,yBAAyB,cAAc,OAAO,QAAQ,KAAK;AAC/F,UAAM,kBAAkB,MAAM,OAAO,0BAA0B,cAAc,OAAO,SAAS,KAAK;AAElG,QAAI,gBAAgB;AAClB,aAAO,aAAa,EAAE,UAAU,WAAW,cAAc,EAAE,CAAC;AAC5D,cAAQ,IAAI,iCAA4B,cAAc,EAAE;AAAA,IAC1D;AAEA,QAAI,iBAAiB;AACnB,aAAO,aAAa,EAAE,WAAW,WAAW,eAAe,EAAE,CAAC;AAC9D,cAAQ,IAAI,kCAA6B,eAAe,EAAE;AAAA,IAC5D;AAAA,EACF,OAAO;AAEL,QAAI,QAAQ,UAAU;AACpB,aAAO,aAAa,EAAE,UAAU,WAAW,QAAQ,QAAQ,EAAE,CAAC;AAC9D,cAAQ,IAAI,iCAA4B,QAAQ,QAAQ,EAAE;AAAA,IAC5D;AACA,QAAI,QAAQ,WAAW;AACrB,aAAO,aAAa,EAAE,WAAW,WAAW,QAAQ,SAAS,EAAE,CAAC;AAChE,cAAQ,IAAI,kCAA6B,QAAQ,SAAS,EAAE;AAAA,IAC9D;AAAA,EACF;AACF,CAAC;AAQH,QACG,QAAQ,eAAe,EACvB,YAAY,gEAAgE,EAC5E,OAAO,mBAAmB,4EAA4E,MAAM,EAC5G,OAAO,sBAAsB,oBAAoBA,mBAAkB,EACnE,OAAO,OAAO,WAAW,YAAY;AACpC,QAAM,SAAS,IAAI,eAAe,EAAE,WAAW,QAAQ,UAAU,CAAC;AAElE,QAAM,SAAS,WAAW,SAAS;AACnC,MAAI,MAAM,MAAM,KAAK,SAAS,GAAG;AAC/B,YAAQ,IAAI,oBAAe;AAC3B;AAAA,EACF;AAEA,QAAM,QAAS,QAAQ,OAAO,YAAY,KAAK;AAC/C,MAAI,CAAC,CAAC,QAAQ,WAAW,gBAAgB,UAAU,OAAO,aAAa,EAAE,SAAS,KAAK,GAAG;AACxF,YAAQ,IAAI,qFAAgF;AAC5F;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,UAAU,UAAU;AAEtB,UAAM,eAAe,iBAAiB,QAAQ,aAAaA,mBAAkB;AAC7E,QAAI,CAAC,cAAc;AACjB,cAAQ,IAAI,sEAAiE;AAC7E;AAAA,IACF;AACA,oBAAgB,iBAAiB,QAAQ,aAAaA,mBAAkB,KAAK;AAC7E,QAAI,CAAC,eAAe;AAClB,cAAQ,IAAI,6CAAwC;AACpD;AAAA,IACF;AAAA,EACF,OAAO;AAEL,QAAI,CAAC,OAAO,eAAe;AACzB,cAAQ,IAAI,gDAA2C;AACvD;AAAA,IACF;AACA,oBAAgB,OAAO;AAAA,EACzB;AAGA,MAAI,UAAU,gBAAgB;AAC5B,YAAQ,IAAI,+BAAwB;AACpC,YAAQ,IAAI,cAAc,aAAa,EAAE;AACzC,YAAQ,IAAI;AAAA,CAAoC;AAChD,YAAQ,IAAI,+DAAwD;AACpE,YAAQ,IAAI,0BAA0B;AACtC,YAAQ,IAAI,4DAA4D;AACxE;AAAA,EACF;AAGA,MAAI,UAAU,eAAe;AAC3B,YAAQ,IAAI,mCAA4B;AACxC,YAAQ,IAAI,cAAc,aAAa,EAAE;AACzC,YAAQ,IAAI;AAAA,CAAyB;AACrC,YAAQ,IAAI,iEAA0D;AACtE,YAAQ,IAAI,8CAA8C;AAC1D,YAAQ,IAAI,sBAAsB;AAClC,YAAQ,IAAI,yCAAoC;AAChD,YAAQ,IAAI,oDAA+C;AAC3D;AAAA,EACF;AAGA,MAAI,UAAU,OAAO;AACnB,YAAQ,IAAI,iCAA0B;AACtC,YAAQ,IAAI,cAAc,aAAa;AAAA,CAAI;AAC3C,YAAQ,IAAI,8CAA8C;AAC1D,YAAQ,IAAI,yBAAyB;AACrC,YAAQ,IAAI,sEAAiE;AAC7E,YAAQ,IAAI,yDAAyD;AACrE,YAAQ,IAAI,sDAAiD;AAC7D,YAAQ,IAAI,yDAAoD;AAChE,YAAQ,IAAI,oFAA6E;AACzF,YAAQ,IAAI,mXAAkE;AAC9E,YAAQ,IAAI,uDAAuD;AACnE;AAAA,EACF;AAEA,UAAQ,IAAI,sCAA+B;AAC3C,UAAQ,IAAI,cAAc,aAAa,EAAE;AACzC,UAAQ,IAAI,aAAa,UAAU,WAAW,WAAW,KAAK,EAAE;AAChE,UAAQ,IAAI,eAAe,OAAO,QAAQ,CAAC,CAAC;AAAA,CAAI;AAEhD,MAAI;AAEF,UAAM,aAAa,QAAQ,IAAI,uBAAuB;AAEtD,UAAM,WAAW,MAAM,MAAM,GAAG,UAAU,WAAW;AAAA,MACnD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU;AAAA,QACnB,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,EAAE,OAAO,eAAe,EAAE;AAC/E,YAAM,IAAI,MAAM,UAAU,SAAS,mBAAmB,SAAS,MAAM,EAAE;AAAA,IACzE;AAEA,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,UAAM,EAAE,IAAI,IAAI;AAEhB,YAAQ,IAAI,+CAA+C;AAC3D,UAAM,YAAY,GAAG;AACrB,YAAQ,IAAI,mDAAyC;AAAA,EACvD,SAAS,OAAO;AACd,YAAQ,IAAI,UAAM,MAAgB,OAAO,EAAE;AAAA,EAC7C;AACF,CAAC;AAOH,QACG,QAAQ,SAAS,EACjB,YAAY,kDAAkD,EAC9D,eAAe,uBAAuB,uDAAuD,EAC7F,OAAO,mBAAmB,kCAAkC,aAAa,EACzE,OAAO,sBAAsB,oBAAoBA,mBAAkB,EACnE,OAAO,OAAO,YAAY;AACzB,QAAM,QAAQ,QAAQ;AAEtB,MAAI,UAAU,SAAS,UAAU,eAAe;AAC9C,YAAQ,IAAI,oEAA+D;AAC3E;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,QAAQ,MAAM,qBAAqB,GAAG;AACjD,YAAQ,IAAI,uCAAkC;AAC9C;AAAA,EACF;AAEA,QAAM,SAAS,IAAI,eAAe,EAAE,WAAW,QAAQ,UAAU,CAAC;AAClE,MAAI,CAAC,OAAO,eAAe;AACzB,YAAQ,IAAI,mEAA8D,KAAK;AAC/E;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,kCAA8B,KAAK;AAAA,CAAO;AACtD,QAAM,kBAAkB,QAAQ,OAAO,QAAQ,SAAS,KAAK;AAG7D,QAAM,iBAAa,mBAAK,QAAQ,aAAaA,qBAAoB,aAAa;AAC9E,MAAI;AACF,UAAM,aAAa,KAAK,UAAM,yBAAa,YAAY,OAAO,CAAC;AAC/D,eAAW,YAAY,WAAW,aAAa,CAAC;AAChD,eAAW,UAAU,KAAK,IAAI,QAAQ;AACtC,kCAAc,YAAY,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAC7D,YAAQ,IAAI,+CAA0C,KAAK;AAAA,CAAK;AAAA,EAClE,SAAS,KAAK;AACZ,YAAQ,IAAI,6BAAwB;AACpC,YAAQ,IAAI,uDAA6C;AAAA,EAC3D;AACF,CAAC;AAOH,QACG,QAAQ,QAAQ,EAChB,YAAY,kGAAkG,EAC9G,OAAO,mBAAmB,wFAAwF,cAAc,EAChI,OAAO,uBAAuB,0CAA0C,EACxE,OAAO,sBAAsB,oBAAoBA,mBAAkB,EACnE,OAAO,OAAO,YAAY;AACzB,MAAI,UAAU,QAAQ;AACtB,QAAM,QAAQ,QAAQ,OAAO,YAAY,KAAK;AAG9C,MAAI,CAAC,CAAC,gBAAgB,kBAAkB,eAAe,eAAe,EAAE,SAAS,KAAK,GAAG;AACvF,YAAQ,IAAI,wFAAmF;AAC/F;AAAA,EACF;AAGA,MAAI,UAAU,iBAAiB;AAE7B,QAAI,CAAC,SAAS;AACZ,gBAAU,iBAAiB,QAAQ,SAAS;AAC5C,UAAI,CAAC,SAAS;AACZ,gBAAQ,IAAI,6EAAwE;AACpF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,CAAC,qBAAqB,OAAO,GAAG;AAClC,cAAQ,IAAI,+BAA0B;AACtC;AAAA,IACF;AAEA,YAAQ,IAAI,mDAA4C;AACxD,YAAQ,IAAI,eAAe,OAAO;AAAA,CAAI;AAEtC,QAAI,cAAc;AAGlB,QAAI;AACF,cAAQ,IAAI,4CAAuC;AACnD,YAAM,aAAa,QAAQ,IAAI,uBAAuB;AAEtD,YAAM,WAAW,MAAM,MAAM,YAAY;AAAA,QACvC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,gBAAgB,CAAC;AAAA,MAC1D,CAAC;AAED,YAAM,SAAS,MAAM,SAAS,KAAK;AAWnC,UAAI,CAAC,SAAS,IAAI;AAChB,gBAAQ,IAAI,iCAAuB,OAAO,SAAS,gBAAgB,EAAE;AACrE,YAAI,OAAO,KAAM,SAAQ,IAAI,SAAS,OAAO,IAAI,EAAE;AACnD,YAAI,OAAO,YAAa,SAAQ,IAAI,sBAAsB,OAAO,WAAW,EAAE;AAAA,MAChF,OAAO;AACL,gBAAQ,IAAI,sBAAiB,OAAO,MAAM,QAAQ;AAClD,gBAAQ,IAAI,mBAAmB,OAAO,QAAQ,EAAE;AAChD,YAAI,OAAO,gBAAgB;AACzB,kBAAQ,IAAI,sBAAsB,OAAO,cAAc,iBAAiB;AAAA,QAC1E;AACA,sBAAc;AAAA,MAChB;AAAA,IACF,SAAS,OAAY;AACnB,cAAQ,IAAI,uCAA6B,MAAM,OAAO,EAAE;AAAA,IAC1D;AAEA,YAAQ,IAAI,EAAE;AACd,QAAI,aAAa;AACf,cAAQ,IAAI,+BAAwB;AACpC,cAAQ,IAAI,0BAA0B;AAAA,IACxC,OAAO;AACL,cAAQ,IAAI,6DAAwD;AAAA,IACtE;AACA;AAAA,EACF;AAGA,MAAI,CAAC,SAAS;AACZ,UAAM,SAAS,IAAI,eAAe,EAAE,WAAW,QAAQ,UAAU,CAAC;AAClE,QAAI,OAAO,eAAe;AACxB,gBAAU,OAAO;AAAA,IACnB,OAAO;AACL,cAAQ,IAAI,6EAAwE;AACpF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,MAAM,qBAAqB,GAAG;AACzC,YAAQ,IAAI,iCAA4B;AACxC;AAAA,EACF;AAEA,UAAQ,IAAI,uCAAgC;AAE5C,MAAI,UAAU,kBAAkB;AAE9B,YAAQ,IAAI,mDAAmD;AAC/D,YAAQ,IAAI,eAAe,OAAO;AAAA,CAAI;AAEtC,QAAI;AAEF,YAAM,mBAAmB;AAEzB,YAAM,WAAW,MAAM,MAAM,kBAAkB;AAAA,QAC7C,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,QAAQ,CAAC;AAAA,MAClC,CAAC;AAED,YAAM,SAAS,MAAM,SAAS,KAAK;AAEnC,UAAI,SAAS,MAAM,OAAO,QAAQ,OAAO,KAAK,SAAS,GAAG;AACxD,gBAAQ,IAAI;AAAA,CAA8B;AAC1C,gBAAQ,IAAI,2DAA2D;AACvE,gBAAQ,IAAI,kBAAkB;AAC9B,mBAAW,MAAM,OAAO,MAAM;AAC5B,kBAAQ,IAAI,6CAA6C,GAAG,IAAI,EAAE;AAAA,QACpE;AACA,gBAAQ,IAAI,oDAA6C;AACzD,gBAAQ,IAAI;AAAA,CAAyE;AAAA,MACvF,OAAO;AACL,gBAAQ,IAAI,UAAK,OAAO,SAAS,uBAAuB,EAAE;AAC1D,gBAAQ,IAAI,sEAAsE;AAAA,MACpF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,IAAI,UAAM,MAAgB,OAAO,EAAE;AAC3C,cAAQ,IAAI,2DAA2D;AAAA,IACzE;AAAA,EACF,WAAW,UAAU,eAAe;AAElC,YAAQ,IAAI,wCAAwC;AACpD,YAAQ,IAAI,eAAe,OAAO;AAAA,CAAI;AAEtC,QAAI;AACF,YAAM,aAAa,QAAQ,IAAI,uBAAuB;AAEtD,YAAM,WAAW,MAAM,MAAM,YAAY;AAAA,QACvC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,cAAc,CAAC;AAAA,MACxD,CAAC;AAED,YAAM,SAAS,MAAM,SAAS,KAAK;AAanC,UAAI,CAAC,SAAS,IAAI;AAChB,gBAAQ,IAAI,UAAK,OAAO,SAAS,gBAAgB,EAAE;AACnD,YAAI,OAAO,KAAM,SAAQ,IAAI,MAAM,OAAO,IAAI,EAAE;AAChD,YAAI,OAAO,YAAa,SAAQ,IAAI,mBAAmB,OAAO,WAAW,EAAE;AAG3E,gBAAQ,IAAI,iDAA0C;AACtD,gBAAQ,IAAI,gEAAgE;AAC5E,gBAAQ,IAAI,qCAAqC;AACjD,gBAAQ,IAAI,gBAAgB,OAAO;AAAA,CAAI;AACvC;AAAA,MACF;AAEA,cAAQ,IAAI,mBAAc,OAAO,MAAM,IAAI,OAAO,SAAS,MAAM,OAAO,OAAO,cAAc,aAAa;AAAA,CAAK;AAC/G,cAAQ,IAAI,mBAAmB,OAAO,YAAY,kCAAkC,OAAO,WAAW,EAAE,EAAE;AAC1G,UAAI,OAAO,gBAAgB;AACzB,gBAAQ,IAAI,sBAAsB,OAAO,cAAc,OAAO;AAAA,MAChE;AACA,cAAQ,IAAI,4CAAqC;AACjD,cAAQ,IAAI;AAAA,CAAsE;AAAA,IACpF,SAAS,OAAO;AACd,cAAQ,IAAI,UAAM,MAAgB,OAAO,EAAE;AAC3C,cAAQ,IAAI,kCAA2B;AACvC,cAAQ,IAAI,gEAAgE;AAC5E,cAAQ,IAAI,qCAAqC;AACjD,cAAQ,IAAI,gBAAgB,OAAO;AAAA,CAAI;AAAA,IACzC;AAAA,EACF,OAAO;AAEL,YAAQ,IAAI,yCAAyC;AACrD,YAAQ,IAAI,eAAe,OAAO;AAAA,CAAI;AAEtC,QAAI;AACF,YAAM,aAAa,QAAQ,IAAI,uBAAuB;AAEtD,YAAM,WAAW,MAAM,MAAM,YAAY;AAAA,QACvC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,eAAe,CAAC;AAAA,MACzD,CAAC;AAED,YAAM,SAAS,MAAM,SAAS,KAAK;AAWnC,UAAI,CAAC,SAAS,IAAI;AAChB,gBAAQ,IAAI,UAAK,OAAO,SAAS,gBAAgB,EAAE;AACnD,YAAI,OAAO,KAAM,SAAQ,IAAI,MAAM,OAAO,IAAI,EAAE;AAChD,YAAI,OAAO,YAAa,SAAQ,IAAI,mBAAmB,OAAO,WAAW,EAAE;AAC3E;AAAA,MACF;AAEA,cAAQ,IAAI,mBAAc,OAAO,MAAM;AAAA,CAAU;AACjD,cAAQ,IAAI,mBAAmB,OAAO,WAAW,EAAE;AACnD,cAAQ,IAAI,gBAAgB,OAAO,QAAQ,EAAE;AAC7C,cAAQ,IAAI,sBAAsB,OAAO,cAAc;AAAA,CAAmB;AAC1E,cAAQ,IAAI,gDAAyC;AACrD,cAAQ,IAAI;AAAA,CAAuE;AAAA,IACrF,SAAS,OAAO;AACd,cAAQ,IAAI,UAAM,MAAgB,OAAO,EAAE;AAAA,IAC7C;AAAA,EACF;AACF,CAAC;AAKH,QACG,QAAQ,QAAQ,EAChB,YAAY,gCAAgC,EAC5C,OAAO,sBAAsB,oBAAoBA,mBAAkB,EACnE,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,YAAY;AACzB,QAAM,SAAS,IAAI,eAAe,EAAE,WAAW,QAAQ,UAAU,CAAC;AAElE,MAAI,CAAC,OAAO,eAAe;AACzB,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,kBAAkB,CAAC,CAAC;AAAA,IAC1D,OAAO;AACL,cAAQ,IAAI,gDAA2C;AAAA,IACzD;AACA;AAAA,EACF;AAEA,QAAM,SAAS,OAAO,UAAU;AAGhC,MAAI,cAA8E,CAAC;AACnF,MAAI;AACF,kBAAc,MAAM,OAAO,eAAe;AAAA,EAC5C,SAAS,KAAU;AACjB,YAAQ,MAAM,sCAAsC,IAAI,OAAO;AAAA,EACjE;AAGA,QAAM,gBAAgB,iBAAiB,QAAQ,SAAS;AACxD,MAAI,iBAAsG,CAAC;AAE3G,MAAI,eAAe;AACjB,QAAI;AACF,qBAAe,SAAS,MAAM,kBAAkB,eAAe,eAAe;AAAA,IAChF,QAAQ;AAAA,IAAe;AACvB,QAAI;AACF,qBAAe,UAAU,MAAM,kBAAkB,eAAe,QAAQ;AAAA,IAC1E,QAAQ;AAAA,IAAe;AAAA,EACzB;AAEA,MAAI,QAAQ,MAAM;AAChB,UAAM,SAAc;AAAA,MAClB,SAAS,OAAO;AAAA,MAChB,UAAU;AAAA,MACV,QAAQ,OAAO;AAAA,IACjB;AACA,QAAI,eAAe;AACjB,aAAO,SAAS;AAAA,QACd,SAAS;AAAA,QACT,UAAU;AAAA,MACZ;AAAA,IACF;AACA,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,EAC7C,OAAO;AACL,YAAQ,IAAI,sCAA+B;AAC3C,YAAQ,IAAI,eAAe,OAAO,OAAO,EAAE;AAC3C,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,cAAc;AAC1B,eAAW,CAAC,WAAW,OAAO,KAAK,OAAO,QAAQ,WAAW,GAAG;AAE9D,UAAI;AACJ,UAAI,cAAc,gBAAgB;AAChC,qBAAa;AAAA,MACf,WAAW,cAAc,kBAAkB;AACzC,qBAAa;AAAA,MACf,OAAO;AACL,qBAAa,UAAU,OAAO,CAAC,EAAE,YAAY,IAAI,UAAU,MAAM,CAAC;AAAA,MACpE;AAGA,UAAI,cAAc,oBAAqB,QAAgB,OAAO;AAC5D,cAAM,QAAS,QAAgB;AAE/B,cAAM,YAAY,QAAQ,SAAS,OAC/B,QAAQ,OAAO,cAAc,CAAC,IAC9B,QAAQ,OAAO,QAAQ,CAAC;AAC5B,gBAAQ,IAAI,QAAQ,UAAU,GAAG;AACjC,gBAAQ,IAAI,qBAAqB,SAAS,kBAAkB;AAC5D,gBAAQ,IAAI,qBAAqB,MAAM,QAAQ,QAAQ,CAAC,CAAC,EAAE;AAC3D,gBAAQ,IAAI,qBAAqB,MAAM,SAAS,QAAQ,CAAC,CAAC,EAAE;AAC5D,gBAAQ,IAAI,qBAAqB,MAAM,QAAQ,QAAQ,CAAC,CAAC,EAAE;AAC3D,gBAAQ,IAAI,qBAAqB,MAAM,SAAS,QAAQ,CAAC,CAAC,EAAE;AAAA,MAC9D,WAAW,cAAc,SAAS,cAAc,eAAe;AAE7D,cAAM,aAAa,QAAQ;AAC3B,cAAM,aAAa,aAAa,OAAS,0BAAgB;AACzD,gBAAQ,IAAI,QAAQ,WAAW,OAAO,EAAE,CAAC,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC,WAAW,QAAQ,KAAK,QAAQ,CAAC,CAAC,WAAW,WAAW,QAAQ,CAAC,CAAC,OAAO,UAAU,EAAE;AAAA,MAC3J,OAAO;AAEL,gBAAQ,IAAI,QAAQ,WAAW,OAAO,EAAE,CAAC,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC,WAAW,QAAQ,KAAK,QAAQ,CAAC,CAAC,OAAO;AAAA,MAC/G;AAAA,IACF;AAGA,UAAM,UAAU,OAAO;AACvB,QAAI,oBAAqF;AACzF,QAAI,2BAA4F;AAEhG,QAAI;AACF,UAAI,YAAY,KAAK,GAAG;AACtB,4BAAoB,MAAM,kBAAkB,SAAS,OAAO,QAAQ,SAAS;AAAA,MAC/E;AACA,UAAI,YAAY,aAAa,GAAG;AAC9B,mCAA2B,MAAM,kBAAkB,SAAS,eAAe,QAAQ,SAAS;AAAA,MAC9F;AAAA,IACF,QAAQ;AAAA,IAAqC;AAE7C,QAAI,qBAAqB,0BAA0B;AACjD,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,qCAAqC;AACjD,UAAI,mBAAmB;AACrB,YAAI,CAAC,kBAAkB,SAAS;AAC9B,kBAAQ,IAAI,uDAA6C;AACzD,kBAAQ,IAAI,iGAAuF;AAAA,QACrG,OAAO;AACL,gBAAM,SAAS,kBAAkB,QAAQ,kBAAkB,OAAO,WAAM;AACxE,gBAAM,SAAS;AAAA,YACb,kBAAkB,OAAO,eAAU;AAAA,YACnC,kBAAkB,OAAO,eAAU;AAAA,UACrC,EAAE,KAAK,IAAI;AACX,kBAAQ,IAAI,sBAAsB,MAAM,IAAI,MAAM,EAAE;AAGpD,gBAAM,YAAY,YAAY,KAAK,GAAG,UAAU;AAChD,cAAI,CAAC,kBAAkB,QAAQ,CAAC,kBAAkB,QAAQ,YAAY,MAAQ;AAC5E,oBAAQ,IAAI,8EAAoE;AAAA,UAClF;AAAA,QACF;AAAA,MACF;AACA,UAAI,0BAA0B;AAC5B,YAAI,CAAC,yBAAyB,SAAS;AACrC,kBAAQ,IAAI,uDAA6C;AACzD,kBAAQ,IAAI,yGAA+F;AAAA,QAC7G,OAAO;AACL,gBAAM,SAAS,yBAAyB,QAAQ,yBAAyB,OAAO,WAAM;AACtF,gBAAM,SAAS;AAAA,YACb,yBAAyB,OAAO,eAAU;AAAA,YAC1C,yBAAyB,OAAO,eAAU;AAAA,UAC5C,EAAE,KAAK,IAAI;AACX,kBAAQ,IAAI,sBAAsB,MAAM,IAAI,MAAM,EAAE;AAGpD,gBAAM,aAAa,YAAY,aAAa,GAAG,UAAU;AACzD,cAAI,CAAC,yBAAyB,QAAQ,CAAC,yBAAyB,QAAQ,aAAa,MAAQ;AAC3F,oBAAQ,IAAI,yFAA+E;AAAA,UAC7F;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,qBAAqB;AACjC,YAAQ,IAAI,0BAA0B,OAAO,OAAO,QAAQ,EAAE;AAC9D,YAAQ,IAAI,0BAA0B,OAAO,OAAO,SAAS,EAAE;AAG/D,UAAME,iBAAgB,iBAAiB,QAAQ,SAAS;AACxD,QAAIA,gBAAe;AACjB,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,2MAAsC;AAClD,cAAQ,IAAI,wBAAiBA,cAAa,EAAE;AAE5C,UAAI;AAEF,cAAM,iBAAiB,MAAM,kBAAkBA,gBAAe,eAAe;AAC7E,gBAAQ,IAAI,mBAAmB,eAAe,IAAI,QAAQ,CAAC,CAAC,UAAU,eAAe,KAAK,QAAQ,CAAC,CAAC,OAAO;AAAA,MAC7G,SAAS,KAAU;AACjB,gBAAQ,IAAI,mCAAmC;AAAA,MACjD;AAEA,UAAI;AAEF,cAAM,kBAAkB,MAAM,kBAAkBA,gBAAe,QAAQ;AACvE,gBAAQ,IAAI,mBAAmB,gBAAgB,IAAI,QAAQ,CAAC,CAAC,UAAU,gBAAgB,KAAK,QAAQ,CAAC,CAAC,OAAO;AAAA,MAC/G,SAAS,KAAU;AACjB,gBAAQ,IAAI,mCAAmC;AAAA,MACjD;AAAA,IACF;AAEA,YAAQ,IAAI,EAAE;AAAA,EAChB;AACF,CAAC;AAOH,QACG,QAAQ,MAAM,EACd,YAAY,0BAA0B,EACtC,OAAO,cAAc,+BAA+B,GAAG,EACvD,OAAO,mBAAmB,wDAAwD,KAAK,EACvF,OAAO,eAAe,4BAA4B,IAAI,EACtD,OAAO,sBAAsB,oBAAoBF,mBAAkB,EACnE,OAAO,OAAO,YAAY;AACzB,QAAM,SAAS,IAAI,eAAe,EAAE,WAAW,QAAQ,UAAU,CAAC;AAElE,MAAI,CAAC,OAAO,eAAe;AACzB,YAAQ,IAAI,gDAA2C;AACvD;AAAA,EACF;AAEA,QAAM,OAAO,SAAS,QAAQ,IAAI,KAAK;AACvC,QAAM,QAAQ,SAAS,QAAQ,KAAK,KAAK;AACzC,QAAM,QAAQ,QAAQ,OAAO,YAAY,KAAK;AAE9C,MAAI,CAAC,CAAC,QAAQ,WAAW,gBAAgB,kBAAkB,KAAK,EAAE,SAAS,KAAK,GAAG;AACjF,YAAQ,IAAI,gFAA2E;AACvF;AAAA,EACF;AAEA,QAAM,SAAS,OAAO;AACtB,QAAM,aAAa,KAAK,IAAI,IAAK,OAAO,KAAK,KAAK,KAAK;AAGvD,QAAM,YAAyE;AAAA,IAC7E,MAAM;AAAA,MACJ,KAAK;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA,SAAS;AAAA,MACP,KAAK;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA,cAAc;AAAA,MACZ,KAAK;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA;AAAA,IAEA,gBAAgB;AAAA,MACd,KAAK;AAAA;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,gBAAgB,UAAU,QAAQ,CAAC,QAAQ,WAAW,gBAAgB,gBAAgB,IAAI,CAAC,KAAK;AAEtG,UAAQ,IAAI;AAAA,+BAA2B,IAAI,OAAO,OAAO,IAAI,MAAM,EAAE;AAAA,CAAK;AAY1E,MAAI,UAAqB,CAAC;AAE1B,aAAW,KAAK,eAAe;AAC7B,UAAM,WAAW,UAAU,CAAC;AAE5B,QAAI;AACF,UAAI,MAAM,kBAAkB;AAE1B,cAAM,cAAc;AAAA,UAClB,EAAE,SAAS,8CAA8C,MAAM,UAAU;AAAA,UACzE,EAAE,SAAS,8CAA8C,MAAM,WAAW;AAAA,UAC1E,EAAE,SAAS,8CAA8C,MAAM,UAAU;AAAA,UACzE,EAAE,SAAS,8CAA8C,MAAM,WAAW;AAAA,QAC5E;AAGA,cAAM,gBAAgB;AACtB,cAAM,cAAc,+BAA+B,OAAO,YAAY,EAAE,MAAM,CAAC;AAG/E,YAAI,cAAc;AAClB,iBAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC5C,cAAI;AACF,kBAAM,WAAW,MAAM,MAAM,kCAAkC;AAAA,cAC7D,QAAQ;AAAA,cACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,cAC9C,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,QAAQ,mBAAmB,QAAQ,CAAC,GAAG,IAAI,EAAE,CAAC;AAAA,YACvF,CAAC;AACD,kBAAM,YAAY,MAAM,SAAS,KAAK;AACtC,gBAAI,UAAU,QAAQ;AACpB,4BAAc,SAAS,UAAU,QAAQ,EAAE;AAC3C;AAAA,YACF;AAAA,UACF,SAAS,GAAG;AACV,gBAAI,YAAY,EAAG,OAAM;AACzB,kBAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AAAA,UAC3C;AAAA,QACF;AAEA,YAAI,gBAAgB,GAAG;AACrB,kBAAQ,IAAI,6DAAmD;AAC/D;AAAA,QACF;AAIA,cAAM,YAAY;AAClB,cAAM,eAAe;AACrB,cAAM,kBAAkB,eAAe;AACvC,cAAM,eAAe,KAAK,IAAI,iBAAiB,SAAS;AACxD,cAAM,YAAY,OAAO,KAAK,IAAI,GAAG,cAAc,YAAY,EAAE,SAAS,EAAE;AAC5E,cAAM,UAAU,OAAO,YAAY,SAAS,EAAE;AAG9C,YAAI,kBAAkB,WAAW;AAC/B,kBAAQ,IAAI,0EAAgE;AAAA,QAC9E;AAEA,mBAAW,SAAS,aAAa;AAC/B,cAAI;AAEF,kBAAM,QAAQ,MAAM,MAAM,kCAAkC;AAAA,cAC1D,QAAQ;AAAA,cACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,cAC9C,MAAM,KAAK,UAAU;AAAA,gBACnB,SAAS;AAAA,gBACT,QAAQ;AAAA,gBACR,QAAQ,CAAC,EAAE,WAAW,SAAS,SAAS,MAAM,SAAS,QAAQ,CAAC,eAAe,MAAM,WAAW,EAAE,CAAC;AAAA,gBACnG,IAAI;AAAA,cACN,CAAC;AAAA,YACH,CAAC;AACD,kBAAM,SAAS,MAAM,MAAM,KAAK;AAEhC,gBAAI,OAAO,OAAO;AAChB,sBAAQ,IAAI,oBAAU,MAAM,IAAI,KAAK,OAAO,MAAM,OAAO,EAAE;AAC3D;AAAA,YACF;AAEA,gBAAI,OAAO,UAAU,MAAM,QAAQ,OAAO,MAAM,GAAG;AACjD,yBAAW,OAAO,OAAO,QAAQ;AAC/B,sBAAM,YAAY,SAAS,IAAI,gBAAgB,EAAE,IAAI;AACrD,oBAAI,YAAY,WAAY;AAC5B,sBAAM,SAAS,SAAS,IAAI,MAAM,EAAE,IAAI;AACxC,sBAAM,OAAO,OAAO,IAAI,OAAO,CAAC,EAAE,MAAM,EAAE;AAC1C,wBAAQ,KAAK;AAAA,kBACX,OAAO;AAAA,kBACP;AAAA,kBACA,MAAM;AAAA,kBACN;AAAA,kBACA,OAAO;AAAA,kBACP,MAAM,IAAI;AAAA,kBACV,OAAO,MAAM;AAAA,gBACf,CAAC;AAAA,cACH;AAAA,YACF;AAGA,kBAAM,SAAS,MAAM,MAAM,kCAAkC;AAAA,cAC3D,QAAQ;AAAA,cACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,cAC9C,MAAM,KAAK,UAAU;AAAA,gBACnB,SAAS;AAAA,gBACT,QAAQ;AAAA,gBACR,QAAQ,CAAC,EAAE,WAAW,SAAS,SAAS,MAAM,SAAS,QAAQ,CAAC,eAAe,aAAa,IAAI,EAAE,CAAC;AAAA,gBACnG,IAAI;AAAA,cACN,CAAC;AAAA,YACH,CAAC;AACD,kBAAM,UAAU,MAAM,OAAO,KAAK;AAElC,gBAAI,QAAQ,UAAU,MAAM,QAAQ,QAAQ,MAAM,GAAG;AACnD,yBAAW,OAAO,QAAQ,QAAQ;AAChC,sBAAM,YAAY,SAAS,IAAI,gBAAgB,EAAE,IAAI;AACrD,oBAAI,YAAY,WAAY;AAC5B,sBAAM,SAAS,SAAS,IAAI,MAAM,EAAE,IAAI;AACxC,sBAAM,KAAK,OAAO,IAAI,OAAO,CAAC,EAAE,MAAM,EAAE;AACxC,wBAAQ,KAAK;AAAA,kBACX,OAAO;AAAA,kBACP;AAAA,kBACA,MAAM;AAAA,kBACN;AAAA,kBACA,OAAO;AAAA,kBACP,MAAM,IAAI;AAAA,kBACV,OAAO,MAAM;AAAA,gBACf,CAAC;AAAA,cACH;AAAA,YACF;AAAA,UACF,SAAS,YAAY;AAEnB;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,cAAM,MAAM,GAAG,SAAS,GAAG,cAAc,MAAM,sCAAsC,SAAS,IAAI;AAClG,cAAM,WAAW,MAAM,MAAM,GAAG;AAChC,cAAM,OAAO,MAAM,SAAS,KAAK;AAUjC,YAAI,KAAK,SAAS,MAAM,QAAQ,KAAK,KAAK,GAAG;AAC3C,qBAAW,MAAM,KAAK,OAAO;AAC3B,kBAAM,YAAY,IAAI,KAAK,GAAG,SAAS,EAAE,QAAQ;AACjD,gBAAI,YAAY,WAAY;AAE5B,kBAAM,aAAa,GAAG,GAAG,KAAK,YAAY,MAAM,OAAO,YAAY;AACnE,kBAAM,WAAW,SAAS,GAAG,MAAM,QAAQ,KAAK;AAChD,oBAAQ,KAAK;AAAA,cACX,OAAO;AAAA,cACP;AAAA,cACA,MAAM,aAAa,OAAO;AAAA,cAC1B,QAAQ,SAAS,GAAG,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI,QAAQ;AAAA,cACxD,OAAO,aAAa,GAAG,KAAK,OAAO,GAAG,GAAG;AAAA,cACzC,MAAM,GAAG;AAAA,YACX,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AAEd,YAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACpE,cAAQ,IAAI,oBAAU,SAAS,IAAI,KAAK,MAAM,EAAE;AAAA,IAClD;AAAA,EACF;AAGA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAGhD,YAAU,QAAQ,MAAM,GAAG,KAAK;AAEhC,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,8BAA8B;AAAA,EAC5C,OAAO;AACL,eAAW,MAAM,SAAS;AACxB,YAAM,OAAO,GAAG,SAAS,OAAO,MAAM;AACtC,YAAM,QAAQ,GAAG,SAAS,OAAO,aAAa;AAC9C,YAAM,QAAQ;AACd,YAAM,OAAO,IAAI,KAAK,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,EAAE,QAAQ,KAAK,GAAG;AAC/E,UAAI,aAAa,GAAG,MAAM,YAAY;AACtC,UAAI,GAAG,UAAU,iBAAkB,cAAa;AAAA,eACvC,GAAG,UAAU,eAAgB,cAAa;AACnD,YAAM,WAAW,UAAU,QAAQ,IAAI,UAAU,OAAO;AAExD,YAAM,YAAY,GAAG,SAAS;AAC9B,cAAQ,IAAI,MAAM,KAAK,GAAG,IAAI,GAAG,GAAG,OAAO,QAAQ,CAAC,CAAC,IAAI,SAAS,GAAG,KAAK,MAAM,QAAQ,GAAG,GAAG,SAAS,OAAO,SAAS,IAAI,IAAI,GAAG,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC,MAAM,IAAI,EAAE;AAAA,IAC1L;AAGA,UAAM,UAAU,QAAQ,OAAO,OAAK,EAAE,SAAS,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AACrF,UAAM,WAAW,QAAQ,OAAO,OAAK,EAAE,SAAS,KAAK,EAAE,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AACvF,YAAQ,IAAI;AAAA,eAAW,QAAQ,MAAM,+BAA+B,QAAQ,QAAQ,CAAC,CAAC,0BAA0B,SAAS,QAAQ,CAAC,CAAC;AAAA,CAAe;AAAA,EACpJ;AACF,CAAC;AAKH,QACG,QAAQ,gBAAgB,EACxB,YAAY,oDAAoD,EAChE,OAAO,yBAAyB,6CAA6C,EAC7E,OAAO,uBAAuB,sBAAsB,EACpD,OAAO,iBAAiB,6CAA6C,EACrE,OAAO,eAAe,eAAe,EACrC,OAAO,UAAU,gBAAgB,EACjC,OAAO,OAAO,KAAK,YAAY;AAC9B,QAAM,oBAAoB;AAE1B,MAAI;AACF,QAAI;AACJ,QAAI,aAAa;AAEjB,QAAI,KAAK;AAEP,YAAM,SAAS,IAAI,eAAe;AAClC,iBAAW,MAAM,OAAO,YAAY,GAAG;AAAA,IACzC,OAAO;AAEL,mBAAa;AACb,YAAM,SAAS,IAAI,gBAAgB;AACnC,UAAI,QAAQ,MAAO,QAAO,IAAI,KAAK,QAAQ,KAAK;AAChD,UAAI,QAAQ,SAAU,QAAO,IAAI,YAAY,QAAQ,QAAQ;AAC7D,UAAI,QAAQ,KAAM,QAAO,IAAI,QAAQ,QAAQ,IAAI;AACjD,UAAI,QAAQ,IAAK,QAAO,IAAI,OAAO,QAAQ,GAAG;AAE9C,YAAM,cAAc,OAAO,SAAS;AACpC,YAAM,cAAc,GAAG,iBAAiB,qBAAqB,cAAc,MAAM,cAAc,EAAE;AAEjG,YAAM,MAAM,MAAM,MAAM,WAAW;AACnC,UAAI,CAAC,IAAI,IAAI;AACX,cAAM,IAAI,MAAM,4BAA4B,IAAI,MAAM,EAAE;AAAA,MAC1D;AACA,iBAAW,MAAM,IAAI,KAAK;AAAA,IAC5B;AAEA,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,IAC/C,OAAO;AACL,YAAM,cAAc,SAAS,YAAY,CAAC;AAE1C,UAAI,YAAY;AAEd,YAAI,QAAQ,OAAO;AACjB,kBAAQ,IAAI;AAAA,qBAAiB,QAAQ,KAAK,MAAM,YAAY,MAAM;AAAA,CAAa;AAAA,QACjF,OAAO;AACL,gBAAM,UAAU,CAAC;AACjB,cAAI,QAAQ,SAAU,SAAQ,KAAK,QAAQ,QAAQ,QAAQ,EAAE;AAC7D,cAAI,QAAQ,KAAM,SAAQ,KAAK,QAAQ,IAAI;AAC3C,cAAI,QAAQ,IAAK,SAAQ,KAAK,IAAI,QAAQ,GAAG,EAAE;AAC/C,gBAAM,YAAY,QAAQ,SAAS,IAAI,KAAK,QAAQ,KAAK,IAAI,CAAC,MAAM;AACpE,kBAAQ,IAAI;AAAA,6BAAyB,SAAS,MAAM,YAAY,MAAM;AAAA,CAAa;AAAA,QACrF;AAGA,mBAAW,OAAO,aAAa;AAC7B,gBAAM,QAAQ,IAAI,QAAQ,IAAI,IAAI,MAAM,GAAG,EAAE,EAAE,OAAO,EAAE;AACxD,gBAAM,QAAQ,IAAI,IAAI,KAAK,GAAG,OAAO,CAAC;AACtC,gBAAM,QAAQ,IAAI,QAAQ,WAAW,OAAO,EAAE;AAC9C,gBAAM,WAAW,IAAI,IAAI,UAAU,YAAY,SAAS;AACxD,kBAAQ,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,QAAQ,EAAE;AAAA,QACvD;AAEA,YAAI,YAAY,SAAS,GAAG;AAC1B,kBAAQ,IAAI;AAAA;AAAA,CAAyD;AAAA,QACvE;AAAA,MACF,OAAO;AAEL,YAAI,SAAS,UAAU;AACrB,kBAAQ,IAAI;AAAA,YAAQ,SAAS,SAAS,IAAI;AAAA,CAAI;AAC9C,kBAAQ,IAAI,MAAM,SAAS,SAAS,eAAe,EAAE,EAAE;AACvD,kBAAQ,IAAI,cAAc,SAAS,SAAS,MAAM,EAAE;AAEpD,gBAAM,SAAS,SAAS,SAAS,SAC5B,MAAM,QAAQ,SAAS,SAAS,MAAM,IACnC,SAAS,SAAS,OAAO,IAAI,CAAC,MAAW,OAAO,MAAM,WAAW,IAAI,EAAE,KAAK,EAAE,KAAK,IAAI,IACvF,SAAS,SAAS,SACtB,SAAS,SAAS,SAAS;AAC/B,kBAAQ,IAAI,cAAc,MAAM,EAAE;AAAA,QACpC,OAAO;AACL,kBAAQ,IAAI;AAAA;AAAA,CAA0B;AACtC,kBAAQ,IAAI,MAAM,YAAY,MAAM,qBAAqB;AAAA,QAC3D;AAEA,gBAAQ,IAAI,yBAAkB;AAE9B,mBAAW,OAAO,aAAa;AAC7B,gBAAM,SAAS,IAAI,cAAc,QAAQ,WAAM;AAC/C,kBAAQ,IAAI,MAAM,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI,EAAE;AAChD,kBAAQ,IAAI,SAAS,IAAI,IAAI,OAAO,IAAI,KAAK,IAAI,IAAI,QAAQ,EAAE;AAC/D,cAAI,IAAI,aAAa;AACnB,oBAAQ,IAAI,SAAS,IAAI,WAAW,EAAE;AAAA,UACxC;AACA,cAAI,IAAI,YAAY,CAAC,SAAS,UAAU;AACtC,oBAAQ,IAAI,mBAAmB,IAAI,SAAS,QAAQ,IAAI,SAAS,QAAQ,EAAE;AAAA,UAC7E;AACA,kBAAQ,IAAI,EAAE;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAU;AACjB,YAAQ,MAAM,iBAAY,IAAI,OAAO;AAAA,EACvC;AACF,CAAC;AAeH,QACG,QAAQ,kBAAkB,EAC1B,YAAY,gEAAgE,EAC5E,OAAO,qBAAqB,qBAAqB,MAAM,EACvD,OAAO,iBAAiB,gBAAgB,SAAS,EACjD,OAAO,uBAAuB,8DAA8D,EAC5F,OAAO,OAAO,OAAO,YAAY;AAChC,QAAM,OAAO,SAAS,QAAQ,MAAM,EAAE;AACtC,QAAM,OAAO,QAAQ;AACrB,QAAM,iBAAiB,QAAQ;AAG/B,QAAM,WAAW,MAAM,QAAQ,CAAC,MAAc,EAAE,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,OAAO;AAE7F,UAAQ,IAAI;AAAA;AAAA,CAAiD;AAG7D,QAAM,cAAqB,CAAC;AAC5B,QAAM,WAAuD,oBAAI,IAAI;AACrE,MAAI,WAAgB;AAEpB,aAAW,aAAa,UAAU;AAChC,UAAM,mBAAe,sBAAQ,SAAS;AAGtC,QAAI;AACJ,QAAI;AACJ,QAAI,aAAa;AAEjB,YAAI,2BAAW,mBAAK,cAAc,wBAAwB,CAAC,GAAG;AAE5D,yBAAe,mBAAK,cAAc,wBAAwB;AAC1D,iBAAW;AACX,mBAAa;AAAA,IACf,eAAW,uBAAW,YAAY,KAAK,aAAa,SAAS,OAAO,GAAG;AAErE,qBAAe;AACf,qBAAW,sBAAQ,YAAY;AAAA,IACjC,eAAW,uBAAW,YAAY,GAAG;AAEnC,cAAQ,MAAM,8CAAyC,YAAY,EAAE;AACrE;AAAA,IACF,OAAO;AACL,cAAQ,MAAM,0BAAqB,YAAY,EAAE;AACjD;AAAA,IACF;AAEA,YAAQ,IAAI,sBAAe,YAAY,EAAE;AAEzC,QAAI;AACF,YAAM,kBAAkB,KAAK,UAAM,yBAAa,cAAc,OAAO,CAAC;AAGtE,UAAI,CAAC,UAAU;AACb,mBAAW,gBAAgB;AAAA,MAC7B;AAGA,UAAI,cAAmB;AACvB,UAAI,YAAY;AAEd,YAAI,aAAa;AACjB,cAAM,kBAAc,mBAAK,UAAU,cAAc;AACjD,gBAAI,uBAAW,WAAW,GAAG;AAC3B,cAAI;AACF,kBAAM,UAAU,KAAK,UAAM,yBAAa,aAAa,OAAO,CAAC;AAC7D,gBAAI,QAAQ,MAAM;AAChB,2BAAa,QAAQ;AAAA,YACvB;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAEA,cAAM,iBAAa,mBAAK,UAAU,UAAU;AAC5C,gBAAI,uBAAW,UAAU,GAAG;AAC1B,cAAI;AACF,0BAAc,MAAM,OAAO;AAC3B,oBAAQ,IAAI,4BAAuB,UAAU,EAAE;AAAA,UACjD,SAAS,KAAU;AACjB,oBAAQ,MAAM,2CAAiC,IAAI,OAAO,EAAE;AAAA,UAC9D;AAAA,QACF,OAAO;AACL,kBAAQ,MAAM,2CAAiC,UAAU,EAAE;AAAA,QAC7D;AAAA,MACF;AAGA,iBAAW,WAAW,gBAAgB,UAAU;AAC9C,oBAAY,KAAK,OAAO;AAGxB,YAAI,QAAQ,YAAY,aAAa;AAEnC,gBAAM,KAAK,YAAY,QAAQ,QAAQ,KAAK,YAAY,UAAU,QAAQ,QAAQ;AAClF,cAAI,MAAM,OAAO,OAAO,YAAY;AAClC,qBAAS,IAAI,QAAQ,IAAI,EAAE;AAC3B,oBAAQ,IAAI,aAAQ,QAAQ,EAAE,WAAM,QAAQ,QAAQ,IAAI;AAAA,UAC1D,OAAO;AACL,oBAAQ,MAAM,uBAAkB,QAAQ,QAAQ,yBAAyB;AAAA,UAC3E;AAAA,QACF,WAAW,QAAQ,SAAS;AAE1B,gBAAM,UAAU;AAChB,mBAAS,IAAI,QAAQ,IAAI,OAAO,WAAW;AACzC,mBAAO,IAAI,QAAQ,CAAC,gBAAgB,WAAW;AAC7C,oBAAM,WAAO,6BAAM,MAAM,CAAC,MAAM,QAAQ,OAAO,GAAG;AAAA,gBAChD,KAAK;AAAA,gBACL,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,cAChC,CAAC;AAED,kBAAI,SAAS;AACb,kBAAI,SAAS;AAEb,mBAAK,OAAO,GAAG,QAAQ,CAAC,SAAS;AAC/B,0BAAU,KAAK,SAAS;AAAA,cAC1B,CAAC;AAED,mBAAK,OAAO,GAAG,QAAQ,CAAC,SAAS;AAC/B,0BAAU,KAAK,SAAS;AACxB,wBAAQ,OAAO,MAAM,IAAI;AAAA,cAC3B,CAAC;AAED,mBAAK,MAAM,MAAM,KAAK,UAAU,MAAM,CAAC;AACvC,mBAAK,MAAM,IAAI;AAEf,mBAAK,GAAG,SAAS,CAAC,SAAS;AACzB,oBAAI,SAAS,GAAG;AACd,yBAAO,IAAI,MAAM,wBAAwB,IAAI,MAAM,UAAU,eAAe,EAAE,CAAC;AAC/E;AAAA,gBACF;AACA,oBAAI;AACF,iCAAe,KAAK,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,gBAC1C,QAAQ;AACN,iCAAe,EAAE,QAAQ,OAAO,KAAK,EAAE,CAAC;AAAA,gBAC1C;AAAA,cACF,CAAC;AAED,mBAAK,GAAG,SAAS,CAAC,QAAQ;AACxB,uBAAO,IAAI,MAAM,4BAA4B,IAAI,OAAO,EAAE,CAAC;AAAA,cAC7D,CAAC;AAAA,YACH,CAAC;AAAA,UACH,CAAC;AACD,kBAAQ,IAAI,aAAQ,QAAQ,EAAE,iBAAY;AAAA,QAC5C,OAAO;AACL,kBAAQ,KAAK,oBAAU,QAAQ,EAAE,kCAAkC;AAAA,QACrE;AAAA,MACF;AAAA,IACF,SAAS,KAAU;AACjB,cAAQ,MAAM,yBAAoB,YAAY,KAAK,IAAI,OAAO,EAAE;AAChE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,WAAW,GAAG;AAC5B,YAAQ,MAAM,uCAAkC;AAChD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,UAAU;AACb,YAAQ,MAAM,6CAAwC;AACtD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACA,UAAU;AAAA,EACZ;AAGA,QAAM,uBAAmB,mBAAKA,qBAAoB,wBAAwB;AAC1E,gCAAc,kBAAkB,KAAK,UAAU,kBAAkB,MAAM,CAAC,CAAC;AAEzE,UAAQ,IAAI;AAAA,+BAA2B,YAAY,MAAM,WAAW;AACpE,UAAQ,IAAI,gBAAgB,SAAS,IAAI,EAAE;AAC3C,UAAQ,IAAI,cAAc,SAAS,MAAM,EAAE;AAC3C,UAAQ,IAAI,YAAY,IAAI,EAAE;AAC9B,UAAQ,IAAI,EAAE;AAEd,MAAI;AACF,UAAM,SAAS,IAAI,eAAe,kBAAkB,EAAE,MAAM,MAAM,eAAe,CAAC;AAGlF,eAAW,CAAC,WAAW,OAAO,KAAK,UAAU;AAC3C,aAAO,MAAM,WAAW,OAAO;AAAA,IACjC;AAGA,UAAM,UAAU,EAAE,KAAK,QAAQ,KAAK,MAAM,OAAO,SAAS;AAC1D,kCAAc,UAAU,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAGxD,WAAO,OAAO,IAAI;AAGlB,UAAM,UAAU,MAAM;AACpB,UAAI;AACF,gBAAI,uBAAW,QAAQ,EAAG,4BAAW,QAAQ;AAC7C,gBAAI,uBAAW,gBAAgB,EAAG,4BAAW,gBAAgB;AAAA,MAC/D,QAAQ;AAAA,MAAC;AAAA,IACX;AAEA,YAAQ,GAAG,UAAU,MAAM;AACzB,cAAQ,IAAI,gCAAyB;AACrC,cAAQ;AACR,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AAED,YAAQ,GAAG,WAAW,MAAM;AAC1B,cAAQ,IAAI,gCAAyB;AACrC,cAAQ;AACR,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AAED,YAAQ,GAAG,QAAQ,OAAO;AAAA,EAE5B,SAAS,KAAU;AACjB,YAAQ,MAAM,kCAA6B,IAAI,OAAO,EAAE;AACxD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAOH,QACG,QAAQ,MAAM,EACd,YAAY,kCAAkC,EAC9C,OAAO,YAAY;AAClB,MAAI,KAAC,uBAAW,QAAQ,GAAG;AACzB,YAAQ,IAAI,8CAAyC;AACrD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI;AACF,UAAM,UAAU,KAAK,UAAM,yBAAa,UAAU,OAAO,CAAC;AAC1D,UAAM,EAAE,KAAK,MAAM,SAAS,IAAI;AAEhC,YAAQ,IAAI;AAAA;AAAA,CAAiC;AAC7C,YAAQ,IAAI,WAAW,GAAG,EAAE;AAC5B,YAAQ,IAAI,YAAY,IAAI,EAAE;AAC9B,YAAQ,IAAI,gBAAgB,QAAQ,EAAE;AACtC,YAAQ,IAAI,EAAE;AAGd,QAAI;AACF,cAAQ,KAAK,KAAK,CAAC;AAAA,IACrB,QAAQ;AACN,cAAQ,IAAI,4DAAkD;AAC9D,iCAAW,QAAQ;AACnB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,YAAQ,KAAK,KAAK,SAAS;AAC3B,YAAQ,IAAI,+BAA0B;AAGtC,UAAM,IAAI,QAAQ,CAAAC,aAAW,WAAWA,UAAS,GAAI,CAAC;AAEtD,QAAI;AACF,cAAQ,KAAK,KAAK,CAAC;AACnB,cAAQ,IAAI,wDAA8C;AAC1D,cAAQ,KAAK,KAAK,SAAS;AAAA,IAC7B,QAAQ;AAAA,IAER;AAGA,YAAI,uBAAW,QAAQ,GAAG;AACxB,iCAAW,QAAQ;AAAA,IACrB;AAEA,YAAQ,IAAI,yBAAoB;AAAA,EAElC,SAAS,KAAU;AACjB,YAAQ,MAAM,iCAA4B,IAAI,OAAO,EAAE;AACvD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAcH,QACG,QAAQ,iCAAiC,EACzC,YAAY,sCAAsC,EAClD,OAAO,mBAAmB,wBAAwB,EAClD,OAAO,kBAAkB,8BAA8B,EACvD,OAAO,iBAAiB,kDAAkD,EAC1E,OAAO,mBAAmB,oCAAoC,MAAM,EACpE,OAAO,mBAAmB,0FAA0F,EACpH,OAAO,iBAAiB,uFAAuF,EAC/G,OAAO,sBAAsB,qCAAqCD,mBAAkB,EACpF,OAAO,UAAU,sBAAsB,EACvC,OAAO,OAAO,QAAQ,SAAS,YAAY,YAAY;AACtD,QAAM,SAAS,IAAI,eAAe,EAAE,WAAW,QAAQ,UAAU,CAAC;AAClE,QAAM,YAAY,QAAQ,MAAM,YAAY,MAAM;AAGlD,MAAI,CAAC,aAAa,CAAC,OAAO,eAAe;AACvC,YAAQ,MAAM,uDAAkD;AAChE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,SAA8B,CAAC;AACnC,MAAI,aAAa;AAGjB,MAAI,QAAQ,MAAM;AAChB,QAAI;AACF,eAAS,KAAK,MAAM,QAAQ,IAAI;AAChC,mBAAa;AAAA,IACf,QAAQ;AACN,cAAQ,MAAM,oCAA+B;AAC7C,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,WAAW,YAAY;AACrB,QAAI;AACF,eAAS,KAAK,MAAM,UAAU;AAAA,IAChC,QAAQ;AACN,cAAQ,MAAM,4BAAuB;AACrC,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,MAAI,CAAC,cAAc,QAAQ,OAAQ,QAAO,SAAS,QAAQ;AAG3D,MAAI,QAAQ,OAAO;AACjB,UAAM,YAAY,QAAQ;AAE1B,QAAI,UAAU,WAAW,SAAS,KAAK,UAAU,WAAW,UAAU,GAAG;AAEvE,aAAO,YAAY;AAAA,IACrB,OAAO;AAEL,YAAM,eAAW,sBAAQ,SAAS;AAElC,UAAI,KAAC,uBAAW,QAAQ,GAAG;AACzB,gBAAQ,MAAM,gCAA2B,QAAQ,EAAE;AACnD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,gBAAY,yBAAa,QAAQ;AACvC,aAAO,eAAe,UAAU,SAAS,QAAQ;AAAA,IACnD;AAAA,EACF;AAGA,QAAM,qBAAqB,CAAC,QAAQ,WAAW,gBAAgB,kBAAkB,OAAO,eAAe,UAAU,eAAe;AAChI,QAAM,QAAQ,QAAQ,OAAO,YAAY;AACzC,MAAI,SAAS,CAAC,mBAAmB,SAAS,KAAK,GAAG;AAChD,YAAQ,MAAM,yBAAoB,KAAK,gBAAgB,mBAAmB,KAAK,IAAI,CAAC,EAAE;AACtF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,eAAe,OAAO,cAAc,OAAO,eAAe,gBAAgB,QAAQ,KAAK,MAAM;AACnG,QAAM,SAAS,QAAQ,SAAS,QAAQ,YAAY;AAGpD,MAAI,CAAC,aAAa,UAAU,QAAQ;AAClC,UAAM,UAAU,MAAM,OAAO,WAAW;AACxC,QAAI,QAAQ,SAAS,MAAQ;AAC3B,cAAQ,IAAI,sEAA4D;AACxE,cAAQ,IAAI,wBAAwB,QAAQ,OAAO,QAAQ,CAAC,CAAC,MAAM;AACnE,cAAQ,IAAI,sDAAsD;AAClE,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,QAAI,CAAC,QAAQ,MAAM;AACjB,cAAQ,IAAI,kEAAwD;AAAA,IACtE;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,MAAM;AACjB,YAAQ,IAAI;AAAA;AAAA,CAAsC;AAClD,YAAQ,IAAI,cAAc,MAAM,EAAE;AAClC,YAAQ,IAAI,eAAe,OAAO,EAAE;AACpC,QAAI,YAAY;AACd,cAAQ,IAAI,YAAY,KAAK,UAAU,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,UAAU,MAAM,EAAE,SAAS,KAAK,QAAQ,EAAE,EAAE;AAAA,IACjH,OAAO;AACL,cAAQ,IAAI,cAAc,OAAO,MAAM,EAAE;AAAA,IAC3C;AACA,QAAI,aAAc,SAAQ,IAAI,aAAa,YAAY,EAAE;AACzD,QAAI,WAAW;AACb,cAAQ,IAAI,sCAAsC;AAAA,IACpD,OAAO;AACL,cAAQ,IAAI,aAAa,SAAS,QAAQ,EAAE;AAC5C,cAAQ,IAAI,aAAa,KAAK,EAAE;AAChC,cAAQ,IAAI,cAAc,OAAO,OAAO,EAAE;AAAA,IAC5C;AACA,YAAQ,IAAI,EAAE;AAAA,EAChB;AAEA,MAAI;AAIF,UAAM,SAAS,MAAM,OAAO,IAAI,QAAQ,SAAS,QAAQ,YAAY;AAAA,MACnE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,kBAAkB,CAAC,EAAE,YAAY,WAAW,MAAM;AAChD,YAAI,CAAC,QAAQ,MAAM;AACjB,kBAAQ,OAAO,MAAM;AAAA,8EAAmB,cAAc,UAAU;AAAA;AAAA,CAAM;AAAA,QACxE;AAAA,MACF;AAAA,MACA,QAAQ,CAAC,SAAS;AAAE,YAAI,CAAC,QAAQ,KAAM,SAAQ,OAAO,MAAM,OAAO,IAAI;AAAA,MAAG;AAAA,IAC5E,IAAI;AAAA,MACF;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAED,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,MAAM,CAAC;AAAA,IACpC,OAAO;AACL,cAAQ,IAAI,mBAAc;AAC1B,cAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C,cAAQ,IAAI,EAAE;AAAA,IAChB;AAAA,EACF,SAAS,KAAU;AACjB,QAAI,QAAQ,MAAM;AAChB,cAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,IACpD,OAAO;AACL,cAAQ,MAAM,iBAAY,IAAI,OAAO,EAAE;AAAA,IACzC;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAUH,QACG,QAAQ,2BAA2B,EACnC,YAAY,0DAA0D,EACtE,mBAAmB,EACnB,OAAO,OAAO,QAAgB,SAAmB;AAEhD,QAAM,MAA8B;AAAA,IAClC,OAAO;AAAA,IAAgB,OAAO;AAAA,IAAgB,MAAM;AAAA,EACtD;AACA,QAAM,MAAM,IAAI,MAAM,KAAK;AAC3B,QAAM,YAAQ,6BAAM,cAAc,CAAC,KAAK,GAAI,QAAQ,CAAC,CAAE,GAAG;AAAA,IACxD,OAAO;AAAA,IACP,KAAK,UAAgB,QAAQ,GAAG;AAAA,EAClC,CAAC;AACD,QAAM,GAAG,SAAS,CAAC,MAAW;AAC5B,QAAI,GAAG,SAAS,UAAU;AACxB,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF,OAAO;AACL,cAAQ,MAAM,UAAK,EAAE,OAAO,EAAE;AAAA,IAChC;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACD,QAAM,GAAG,QAAQ,CAAC,SAAS,QAAQ,KAAK,QAAQ,CAAC,CAAC;AACpD,CAAC;AAKH,QACG,QAAQ,iBAAiB,EACzB,YAAY,2DAA2D,EACvE,OAAO,OAAO,cAAc;AAC3B,QAAM,mBAAe,sBAAQ,SAAS;AAGtC,MAAI;AACJ,UAAI,2BAAW,mBAAK,cAAc,wBAAwB,CAAC,GAAG;AAC5D,uBAAe,mBAAK,cAAc,wBAAwB;AAAA,EAC5D,WAAW,aAAa,SAAS,OAAO,SAAK,uBAAW,YAAY,GAAG;AACrE,mBAAe;AAAA,EACjB,OAAO;AACL,YAAQ,MAAM,qBAAgB,YAAY,EAAE;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAI;AAAA,wBAAoB,YAAY;AAAA,CAAI;AAEhD,MAAI;AACF,UAAM,UAAU,KAAK,UAAM,yBAAa,cAAc,OAAO,CAAC;AAC9D,UAAM,SAAmB,CAAC;AAG1B,QAAI,CAAC,QAAQ,UAAU;AACrB,aAAO,KAAK,kCAAkC;AAAA,IAChD,OAAO;AACL,UAAI,CAAC,QAAQ,SAAS,KAAM,QAAO,KAAK,uBAAuB;AAC/D,UAAI,CAAC,QAAQ,SAAS,OAAQ,QAAO,KAAK,yBAAyB;AAAA,eAC1D,CAAC,sBAAsB,KAAK,QAAQ,SAAS,MAAM,GAAG;AAC7D,eAAO,KAAK,oDAAoD;AAAA,MAClE;AAAA,IACF;AAGA,QAAI,CAAC,QAAQ,YAAY,CAAC,MAAM,QAAQ,QAAQ,QAAQ,GAAG;AACzD,aAAO,KAAK,0CAA0C;AAAA,IACxD,WAAW,QAAQ,SAAS,WAAW,GAAG;AACxC,aAAO,KAAK,+CAA+C;AAAA,IAC7D,OAAO;AACL,cAAQ,SAAS,QAAQ,CAAC,KAAU,MAAc;AAChD,cAAM,SAAS,YAAY,CAAC;AAC5B,YAAI,CAAC,IAAI,GAAI,QAAO,KAAK,GAAG,MAAM,cAAc;AAAA,iBACvC,CAAC,eAAe,KAAK,IAAI,EAAE,GAAG;AACrC,iBAAO,KAAK,GAAG,MAAM,0CAA0C;AAAA,QACjE;AACA,YAAI,OAAO,IAAI,UAAU,SAAU,QAAO,KAAK,GAAG,MAAM,4BAA4B;AACpF,YAAI,CAAC,IAAI,SAAU,QAAO,KAAK,GAAG,MAAM,oBAAoB;AAC5D,YAAI,CAAC,IAAI,YAAY,CAAC,IAAI,SAAS;AACjC,iBAAO,KAAK,GAAG,MAAM,4CAA4C;AAAA,QACnE;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,OAAO,SAAS,GAAG;AACrB,cAAQ,IAAI,6BAAwB;AACpC,aAAO,QAAQ,OAAK,QAAQ,IAAI,aAAQ,CAAC,EAAE,CAAC;AAC5C,cAAQ,IAAI,EAAE;AACd,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,IAAI,iBAAY;AACxB,YAAQ,IAAI,gBAAgB,QAAQ,SAAS,IAAI,EAAE;AACnD,YAAQ,IAAI,cAAc,QAAQ,SAAS,MAAM,EAAE;AACnD,YAAQ,IAAI,gBAAgB,QAAQ,SAAS,MAAM,EAAE;AACrD,YAAQ,SAAS,QAAQ,CAAC,QAAa;AACrC,cAAQ,IAAI,UAAU,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,IAAI,QAAQ,GAAG;AAAA,IAChE,CAAC;AACD,YAAQ,IAAI,EAAE;AAAA,EAEhB,SAAS,KAAU;AACjB,YAAQ,MAAM,uBAAkB,IAAI,OAAO,EAAE;AAC7C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QAAQ,MAAM;","names":["import_os","import_path","import_fs","import_child_process","import_ethers","import_fs","import_os","import_path","import_ethers","import_web3","bs58","import_web3","import_spl_token","config","import_web3","import_web3","import_os","import_path","resolve","import_child_process","getVersion","getVersion","resolve","inflight","network","req","payTo","privateKeyToAccount","import_fs","path","import_fs","X402_VERSION","import_ethers","TRANSFER_EVENT_TOPIC","TRANSFER_EVENT_TOPIC","ethers","import_node_crypto","import_node_crypto","crypto","crypto","import_web3","import_bs58","bs58","X402_VERSION","PAYMENT_REQUIRED_HEADER","PAYMENT_HEADER","CHAIN_TO_NETWORK","loadEnvFile","resolve","isValidSolanaAddress","settlement","resolve","DEFAULT_CONFIG_DIR","resolve","solanaAddress"]}