moltspay 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +161 -17
  2. package/dist/cdp/index.d.mts +1 -1
  3. package/dist/cdp/index.d.ts +1 -1
  4. package/dist/cdp/index.js +60 -30408
  5. package/dist/cdp/index.js.map +1 -1
  6. package/dist/cdp/index.mjs +44 -30400
  7. package/dist/cdp/index.mjs.map +1 -1
  8. package/dist/cdp-DeohBe1o.d.ts +66 -0
  9. package/dist/cdp-p_eHuQpb.d.mts +66 -0
  10. package/dist/chains/index.d.mts +1 -1
  11. package/dist/chains/index.d.ts +1 -1
  12. package/dist/chains/index.js +36 -40
  13. package/dist/chains/index.js.map +1 -1
  14. package/dist/chains/index.mjs +36 -40
  15. package/dist/chains/index.mjs.map +1 -1
  16. package/dist/cli/index.js +997 -174
  17. package/dist/cli/index.js.map +1 -1
  18. package/dist/cli/index.mjs +1001 -174
  19. package/dist/cli/index.mjs.map +1 -1
  20. package/dist/client/index.d.mts +27 -4
  21. package/dist/client/index.d.ts +27 -4
  22. package/dist/client/index.js +217 -60
  23. package/dist/client/index.js.map +1 -1
  24. package/dist/client/index.mjs +207 -60
  25. package/dist/client/index.mjs.map +1 -1
  26. package/dist/facilitators/index.d.mts +15 -47
  27. package/dist/facilitators/index.d.ts +15 -47
  28. package/dist/facilitators/index.js +273 -34
  29. package/dist/facilitators/index.js.map +1 -1
  30. package/dist/facilitators/index.mjs +272 -34
  31. package/dist/facilitators/index.mjs.map +1 -1
  32. package/dist/{index-B3v8IWjM.d.mts → index-On9ZaGDW.d.mts} +2 -1
  33. package/dist/{index-B3v8IWjM.d.ts → index-On9ZaGDW.d.ts} +2 -1
  34. package/dist/index.d.mts +2 -2
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.js +792 -30657
  37. package/dist/index.js.map +1 -1
  38. package/dist/index.mjs +782 -30657
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/server/index.d.mts +17 -0
  41. package/dist/server/index.d.ts +17 -0
  42. package/dist/server/index.js +513 -48
  43. package/dist/server/index.js.map +1 -1
  44. package/dist/server/index.mjs +513 -48
  45. package/dist/server/index.mjs.map +1 -1
  46. package/dist/verify/index.d.mts +1 -1
  47. package/dist/verify/index.d.ts +1 -1
  48. package/dist/verify/index.js +36 -40
  49. package/dist/verify/index.js.map +1 -1
  50. package/dist/verify/index.mjs +36 -40
  51. package/dist/verify/index.mjs.map +1 -1
  52. package/dist/wallet/index.d.mts +1 -1
  53. package/dist/wallet/index.d.ts +1 -1
  54. package/dist/wallet/index.js +36 -40
  55. package/dist/wallet/index.js.map +1 -1
  56. package/dist/wallet/index.mjs +36 -40
  57. package/dist/wallet/index.mjs.map +1 -1
  58. package/package.json +5 -2
@@ -38,12 +38,15 @@ var CHAINS = {
38
38
  USDC: {
39
39
  address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
40
40
  decimals: 6,
41
- symbol: "USDC"
41
+ symbol: "USDC",
42
+ eip712Name: "USD Coin"
43
+ // EIP-712 domain name
42
44
  },
43
45
  USDT: {
44
46
  address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
45
47
  decimals: 6,
46
- symbol: "USDT"
48
+ symbol: "USDT",
49
+ eip712Name: "Tether USD"
47
50
  }
48
51
  },
49
52
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
@@ -60,12 +63,15 @@ var CHAINS = {
60
63
  USDC: {
61
64
  address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
62
65
  decimals: 6,
63
- symbol: "USDC"
66
+ symbol: "USDC",
67
+ eip712Name: "USD Coin"
64
68
  },
65
69
  USDT: {
66
70
  address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
67
71
  decimals: 6,
68
- symbol: "USDT"
72
+ symbol: "USDT",
73
+ eip712Name: "(PoS) Tether USD"
74
+ // Polygon uses this name
69
75
  }
70
76
  },
71
77
  usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
@@ -73,27 +79,6 @@ var CHAINS = {
73
79
  explorerTx: "https://polygonscan.com/tx/",
74
80
  avgBlockTime: 2
75
81
  },
76
- ethereum: {
77
- name: "Ethereum",
78
- chainId: 1,
79
- rpc: "https://eth.llamarpc.com",
80
- tokens: {
81
- USDC: {
82
- address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
83
- decimals: 6,
84
- symbol: "USDC"
85
- },
86
- USDT: {
87
- address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
88
- decimals: 6,
89
- symbol: "USDT"
90
- }
91
- },
92
- usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
93
- explorer: "https://etherscan.io/address/",
94
- explorerTx: "https://etherscan.io/tx/",
95
- avgBlockTime: 12
96
- },
97
82
  // ============ Testnet ============
98
83
  base_sepolia: {
99
84
  name: "Base Sepolia",
@@ -103,13 +88,17 @@ var CHAINS = {
103
88
  USDC: {
104
89
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
105
90
  decimals: 6,
106
- symbol: "USDC"
91
+ symbol: "USDC",
92
+ eip712Name: "USDC"
93
+ // Testnet USDC uses 'USDC' not 'USD Coin'
107
94
  },
108
95
  USDT: {
109
96
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
110
97
  // Same as USDC on testnet (no official USDT)
111
98
  decimals: 6,
112
- symbol: "USDT"
99
+ symbol: "USDT",
100
+ eip712Name: "USDC"
101
+ // Uses same contract as USDC
113
102
  }
114
103
  },
115
104
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
@@ -117,27 +106,34 @@ var CHAINS = {
117
106
  explorerTx: "https://sepolia.basescan.org/tx/",
118
107
  avgBlockTime: 2
119
108
  },
120
- sepolia: {
121
- name: "Sepolia",
122
- chainId: 11155111,
123
- rpc: "https://rpc.sepolia.org",
109
+ // ============ Tempo Testnet (Moderato) ============
110
+ tempo_moderato: {
111
+ name: "Tempo Moderato",
112
+ chainId: 42431,
113
+ rpc: "https://rpc.moderato.tempo.xyz",
124
114
  tokens: {
115
+ // TIP-20 stablecoins on Tempo testnet (from mppx SDK)
116
+ // Note: Tempo uses USD as native gas token, not ETH
125
117
  USDC: {
126
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
118
+ address: "0x20c0000000000000000000000000000000000000",
119
+ // pathUSD - primary testnet stablecoin
127
120
  decimals: 6,
128
- symbol: "USDC"
121
+ symbol: "USDC",
122
+ eip712Name: "pathUSD"
129
123
  },
130
124
  USDT: {
131
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
132
- // Same as USDC on testnet
125
+ address: "0x20c0000000000000000000000000000000000001",
126
+ // alphaUSD
133
127
  decimals: 6,
134
- symbol: "USDT"
128
+ symbol: "USDT",
129
+ eip712Name: "alphaUSD"
135
130
  }
136
131
  },
137
- usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
138
- explorer: "https://sepolia.etherscan.io/address/",
139
- explorerTx: "https://sepolia.etherscan.io/tx/",
140
- avgBlockTime: 12
132
+ usdc: "0x20c0000000000000000000000000000000000000",
133
+ explorer: "https://explore.testnet.tempo.xyz/address/",
134
+ explorerTx: "https://explore.testnet.tempo.xyz/tx/",
135
+ avgBlockTime: 0.5
136
+ // ~500ms finality
141
137
  }
142
138
  };
143
139
  function getChain(name) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/verify/index.ts","../../src/chains/index.ts"],"sourcesContent":["/**\n * On-chain Payment Verification Module\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, getChainById, type ChainConfig, type ChainName, type TokenSymbol } from '../chains';\n\n// ERC20 Transfer event signature\nconst TRANSFER_EVENT_TOPIC = ethers.id('Transfer(address,address,uint256)');\n\nexport interface VerifyPaymentParams {\n txHash: string;\n expectedAmount: number;\n expectedTo?: string;\n chain?: string | number;\n /** Expected token (if not specified, accepts both USDC and USDT) */\n expectedToken?: TokenSymbol;\n}\n\nexport interface VerifyPaymentResult {\n verified: boolean;\n amount?: number;\n token?: TokenSymbol;\n from?: string;\n to?: string;\n txHash?: string;\n blockNumber?: number;\n error?: string;\n}\n\n/**\n * Verify on-chain payment\n * Supports both USDC and USDT transfers\n */\nexport async function verifyPayment(params: VerifyPaymentParams): Promise<VerifyPaymentResult> {\n const { txHash, expectedAmount, expectedTo, expectedToken } = params;\n \n // Get chain config\n let chain: ChainConfig | undefined;\n try {\n if (typeof params.chain === 'number') {\n chain = getChainById(params.chain);\n } else {\n chain = getChain((params.chain || 'base') as ChainName);\n }\n if (!chain) {\n return { verified: false, error: `Unsupported chain: ${params.chain}` };\n }\n } catch (e) {\n return { verified: false, error: `Unsupported chain: ${params.chain}` };\n }\n\n try {\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n \n // Get transaction receipt\n const receipt = await provider.getTransactionReceipt(txHash);\n \n if (!receipt) {\n return { verified: false, error: 'Transaction not found or not confirmed' };\n }\n\n if (receipt.status !== 1) {\n return { verified: false, error: 'Transaction failed' };\n }\n\n // Build map of accepted token addresses\n const tokenAddresses: Record<string, TokenSymbol> = {};\n \n if (!expectedToken || expectedToken === 'USDC') {\n tokenAddresses[chain.tokens.USDC.address.toLowerCase()] = 'USDC';\n }\n if (!expectedToken || expectedToken === 'USDT') {\n tokenAddresses[chain.tokens.USDT.address.toLowerCase()] = 'USDT';\n }\n\n if (Object.keys(tokenAddresses).length === 0) {\n return { verified: false, error: `No token addresses configured for ${chain.name}` };\n }\n\n for (const log of receipt.logs) {\n const logAddress = log.address.toLowerCase();\n \n // Check if this is one of our accepted tokens\n const detectedToken = tokenAddresses[logAddress];\n if (!detectedToken) {\n continue;\n }\n\n // Check if Transfer event\n if (log.topics.length < 3 || log.topics[0] !== TRANSFER_EVENT_TOPIC) {\n continue;\n }\n\n // Parse Transfer event params\n const from = '0x' + log.topics[1].slice(-40);\n const to = '0x' + log.topics[2].slice(-40);\n const amountRaw = BigInt(log.data);\n const tokenConfig = chain.tokens[detectedToken];\n const amount = Number(amountRaw) / (10 ** tokenConfig.decimals);\n\n // Verify recipient address\n if (expectedTo && to.toLowerCase() !== expectedTo.toLowerCase()) {\n continue;\n }\n\n // Verify amount\n if (amount < expectedAmount) {\n return {\n verified: false,\n error: `Insufficient amount: received ${amount} ${detectedToken}, expected ${expectedAmount}`,\n amount,\n token: detectedToken,\n from,\n to,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n }\n\n // Verification successful\n return {\n verified: true,\n amount,\n token: detectedToken,\n from,\n to,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n }\n\n const tokenList = expectedToken ? expectedToken : 'USDC/USDT';\n return { verified: false, error: `No ${tokenList} transfer found` };\n\n } catch (e: any) {\n return { verified: false, error: e.message || String(e) };\n }\n}\n\n/**\n * Get transaction status\n */\nexport async function getTransactionStatus(\n txHash: string,\n chain: string | number = 'base'\n): Promise<{\n status: 'pending' | 'confirmed' | 'failed' | 'not_found';\n blockNumber?: number;\n confirmations?: number;\n}> {\n let chainConfig: ChainConfig | undefined;\n try {\n chainConfig = typeof chain === 'number' ? getChainById(chain) : getChain(chain as ChainName);\n if (!chainConfig) return { status: 'not_found' };\n } catch {\n return { status: 'not_found' };\n }\n\n try {\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n const receipt = await provider.getTransactionReceipt(txHash);\n\n if (!receipt) {\n // Check if in pending pool\n const tx = await provider.getTransaction(txHash);\n if (tx) {\n return { status: 'pending' };\n }\n return { status: 'not_found' };\n }\n\n const currentBlock = await provider.getBlockNumber();\n const confirmations = currentBlock - receipt.blockNumber;\n\n if (receipt.status === 1) {\n return {\n status: 'confirmed',\n blockNumber: receipt.blockNumber,\n confirmations,\n };\n } else {\n return {\n status: 'failed',\n blockNumber: receipt.blockNumber,\n };\n }\n } catch {\n return { status: 'not_found' };\n }\n}\n\n/**\n * Wait for transaction confirmation\n */\nexport async function waitForTransaction(\n txHash: string,\n chain: string | number = 'base',\n confirmations = 1,\n timeoutMs = 60000\n): Promise<VerifyPaymentResult & { confirmed: boolean }> {\n let chainConfig: ChainConfig | undefined;\n try {\n chainConfig = typeof chain === 'number' ? getChainById(chain) : getChain(chain as ChainName);\n if (!chainConfig) {\n return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };\n }\n } catch (e) {\n return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };\n }\n\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n \n try {\n const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);\n \n if (!receipt) {\n return { verified: false, confirmed: false, error: 'Timeout waiting' };\n }\n\n if (receipt.status !== 1) {\n return { verified: false, confirmed: true, error: 'Transaction failed' };\n }\n\n return {\n verified: true,\n confirmed: true,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n } catch (e: any) {\n return { verified: false, confirmed: false, error: e.message || String(e) };\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName, TokenSymbol } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n tokens: {\n USDC: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n symbol: 'USDC',\n },\n USDT: {\n address: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',\n decimals: 6,\n symbol: 'USDT',\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 },\n USDT: {\n address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',\n decimals: 6,\n symbol: 'USDT',\n },\n },\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n rpc: 'https://eth.llamarpc.com',\n tokens: {\n USDC: {\n address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n decimals: 6,\n symbol: 'USDC',\n },\n USDT: {\n address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',\n decimals: 6,\n symbol: 'USDT',\n },\n },\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n explorer: 'https://etherscan.io/address/',\n explorerTx: 'https://etherscan.io/tx/',\n avgBlockTime: 12,\n },\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 },\n USDT: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Same as USDC on testnet (no official USDT)\n decimals: 6,\n symbol: 'USDT',\n },\n },\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n sepolia: {\n name: 'Sepolia',\n chainId: 11155111,\n rpc: 'https://rpc.sepolia.org',\n tokens: {\n USDC: {\n address: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n decimals: 6,\n symbol: 'USDC',\n },\n USDT: {\n address: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', // Same as USDC on testnet\n decimals: 6,\n symbol: 'USDT',\n },\n },\n usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n explorer: 'https://sepolia.etherscan.io/address/',\n explorerTx: 'https://sepolia.etherscan.io/tx/',\n avgBlockTime: 12,\n },\n};\n\n/**\n * Get token address for a chain\n */\nexport function getTokenAddress(chainName: ChainName, token: TokenSymbol): string {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n const tokenConfig = chain.tokens[token];\n if (!tokenConfig) {\n throw new Error(`Token ${token} not supported on ${chainName}`);\n }\n return tokenConfig.address;\n}\n\n/**\n * Get token config for a chain\n */\nexport function getTokenConfig(chainName: ChainName, token: TokenSymbol) {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n return chain.tokens[token];\n}\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * List all supported chains\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * Get chain config by chainId\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI (minimal, only required methods)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName, TokenSymbol };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/verify/index.ts","../../src/chains/index.ts"],"sourcesContent":["/**\n * On-chain Payment Verification Module\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, getChainById, type ChainConfig, type ChainName, type TokenSymbol } from '../chains';\n\n// ERC20 Transfer event signature\nconst TRANSFER_EVENT_TOPIC = ethers.id('Transfer(address,address,uint256)');\n\nexport interface VerifyPaymentParams {\n txHash: string;\n expectedAmount: number;\n expectedTo?: string;\n chain?: string | number;\n /** Expected token (if not specified, accepts both USDC and USDT) */\n expectedToken?: TokenSymbol;\n}\n\nexport interface VerifyPaymentResult {\n verified: boolean;\n amount?: number;\n token?: TokenSymbol;\n from?: string;\n to?: string;\n txHash?: string;\n blockNumber?: number;\n error?: string;\n}\n\n/**\n * Verify on-chain payment\n * Supports both USDC and USDT transfers\n */\nexport async function verifyPayment(params: VerifyPaymentParams): Promise<VerifyPaymentResult> {\n const { txHash, expectedAmount, expectedTo, expectedToken } = params;\n \n // Get chain config\n let chain: ChainConfig | undefined;\n try {\n if (typeof params.chain === 'number') {\n chain = getChainById(params.chain);\n } else {\n chain = getChain((params.chain || 'base') as ChainName);\n }\n if (!chain) {\n return { verified: false, error: `Unsupported chain: ${params.chain}` };\n }\n } catch (e) {\n return { verified: false, error: `Unsupported chain: ${params.chain}` };\n }\n\n try {\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n \n // Get transaction receipt\n const receipt = await provider.getTransactionReceipt(txHash);\n \n if (!receipt) {\n return { verified: false, error: 'Transaction not found or not confirmed' };\n }\n\n if (receipt.status !== 1) {\n return { verified: false, error: 'Transaction failed' };\n }\n\n // Build map of accepted token addresses\n const tokenAddresses: Record<string, TokenSymbol> = {};\n \n if (!expectedToken || expectedToken === 'USDC') {\n tokenAddresses[chain.tokens.USDC.address.toLowerCase()] = 'USDC';\n }\n if (!expectedToken || expectedToken === 'USDT') {\n tokenAddresses[chain.tokens.USDT.address.toLowerCase()] = 'USDT';\n }\n\n if (Object.keys(tokenAddresses).length === 0) {\n return { verified: false, error: `No token addresses configured for ${chain.name}` };\n }\n\n for (const log of receipt.logs) {\n const logAddress = log.address.toLowerCase();\n \n // Check if this is one of our accepted tokens\n const detectedToken = tokenAddresses[logAddress];\n if (!detectedToken) {\n continue;\n }\n\n // Check if Transfer event\n if (log.topics.length < 3 || log.topics[0] !== TRANSFER_EVENT_TOPIC) {\n continue;\n }\n\n // Parse Transfer event params\n const from = '0x' + log.topics[1].slice(-40);\n const to = '0x' + log.topics[2].slice(-40);\n const amountRaw = BigInt(log.data);\n const tokenConfig = chain.tokens[detectedToken];\n const amount = Number(amountRaw) / (10 ** tokenConfig.decimals);\n\n // Verify recipient address\n if (expectedTo && to.toLowerCase() !== expectedTo.toLowerCase()) {\n continue;\n }\n\n // Verify amount\n if (amount < expectedAmount) {\n return {\n verified: false,\n error: `Insufficient amount: received ${amount} ${detectedToken}, expected ${expectedAmount}`,\n amount,\n token: detectedToken,\n from,\n to,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n }\n\n // Verification successful\n return {\n verified: true,\n amount,\n token: detectedToken,\n from,\n to,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n }\n\n const tokenList = expectedToken ? expectedToken : 'USDC/USDT';\n return { verified: false, error: `No ${tokenList} transfer found` };\n\n } catch (e: any) {\n return { verified: false, error: e.message || String(e) };\n }\n}\n\n/**\n * Get transaction status\n */\nexport async function getTransactionStatus(\n txHash: string,\n chain: string | number = 'base'\n): Promise<{\n status: 'pending' | 'confirmed' | 'failed' | 'not_found';\n blockNumber?: number;\n confirmations?: number;\n}> {\n let chainConfig: ChainConfig | undefined;\n try {\n chainConfig = typeof chain === 'number' ? getChainById(chain) : getChain(chain as ChainName);\n if (!chainConfig) return { status: 'not_found' };\n } catch {\n return { status: 'not_found' };\n }\n\n try {\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n const receipt = await provider.getTransactionReceipt(txHash);\n\n if (!receipt) {\n // Check if in pending pool\n const tx = await provider.getTransaction(txHash);\n if (tx) {\n return { status: 'pending' };\n }\n return { status: 'not_found' };\n }\n\n const currentBlock = await provider.getBlockNumber();\n const confirmations = currentBlock - receipt.blockNumber;\n\n if (receipt.status === 1) {\n return {\n status: 'confirmed',\n blockNumber: receipt.blockNumber,\n confirmations,\n };\n } else {\n return {\n status: 'failed',\n blockNumber: receipt.blockNumber,\n };\n }\n } catch {\n return { status: 'not_found' };\n }\n}\n\n/**\n * Wait for transaction confirmation\n */\nexport async function waitForTransaction(\n txHash: string,\n chain: string | number = 'base',\n confirmations = 1,\n timeoutMs = 60000\n): Promise<VerifyPaymentResult & { confirmed: boolean }> {\n let chainConfig: ChainConfig | undefined;\n try {\n chainConfig = typeof chain === 'number' ? getChainById(chain) : getChain(chain as ChainName);\n if (!chainConfig) {\n return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };\n }\n } catch (e) {\n return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };\n }\n\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n \n try {\n const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);\n \n if (!receipt) {\n return { verified: false, confirmed: false, error: 'Timeout waiting' };\n }\n\n if (receipt.status !== 1) {\n return { verified: false, confirmed: true, error: 'Transaction failed' };\n }\n\n return {\n verified: true,\n confirmed: true,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n } catch (e: any) {\n return { verified: false, confirmed: false, error: e.message || String(e) };\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName, TokenSymbol } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n tokens: {\n USDC: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin', // EIP-712 domain name\n },\n USDT: {\n address: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // deprecated, for backward compat\n explorer: 'https://basescan.org/address/',\n explorerTx: 'https://basescan.org/tx/',\n avgBlockTime: 2,\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n rpc: 'https://polygon-bor-rpc.publicnode.com',\n tokens: {\n USDC: {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: '(PoS) Tether USD', // Polygon uses this name\n },\n },\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n // ============ Testnet ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n tokens: {\n USDC: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USDC', // Testnet USDC uses 'USDC' not 'USD Coin'\n },\n USDT: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Same as USDC on testnet (no official USDT)\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'USDC', // Uses same contract as USDC\n },\n },\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n // ============ Tempo Testnet (Moderato) ============\n tempo_moderato: {\n name: 'Tempo Moderato',\n chainId: 42431,\n rpc: 'https://rpc.moderato.tempo.xyz',\n tokens: {\n // TIP-20 stablecoins on Tempo testnet (from mppx SDK)\n // Note: Tempo uses USD as native gas token, not ETH\n USDC: {\n address: '0x20c0000000000000000000000000000000000000', // pathUSD - primary testnet stablecoin\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'pathUSD',\n },\n USDT: {\n address: '0x20c0000000000000000000000000000000000001', // alphaUSD\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'alphaUSD',\n },\n },\n usdc: '0x20c0000000000000000000000000000000000000',\n explorer: 'https://explore.testnet.tempo.xyz/address/',\n explorerTx: 'https://explore.testnet.tempo.xyz/tx/',\n avgBlockTime: 0.5, // ~500ms finality\n },\n};\n\n/**\n * Get token address for a chain\n */\nexport function getTokenAddress(chainName: ChainName, token: TokenSymbol): string {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n const tokenConfig = chain.tokens[token];\n if (!tokenConfig) {\n throw new Error(`Token ${token} not supported on ${chainName}`);\n }\n return tokenConfig.address;\n}\n\n/**\n * Get token config for a chain\n */\nexport function getTokenConfig(chainName: ChainName, token: TokenSymbol) {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n return chain.tokens[token];\n}\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * List all supported chains\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * Get chain config by chainId\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI (minimal, only required methods)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName, TokenSymbol };\n"],"mappings":"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","names":[]}
@@ -12,12 +12,15 @@ var CHAINS = {
12
12
  USDC: {
13
13
  address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
14
14
  decimals: 6,
15
- symbol: "USDC"
15
+ symbol: "USDC",
16
+ eip712Name: "USD Coin"
17
+ // EIP-712 domain name
16
18
  },
17
19
  USDT: {
18
20
  address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
19
21
  decimals: 6,
20
- symbol: "USDT"
22
+ symbol: "USDT",
23
+ eip712Name: "Tether USD"
21
24
  }
22
25
  },
23
26
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
@@ -34,12 +37,15 @@ var CHAINS = {
34
37
  USDC: {
35
38
  address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
36
39
  decimals: 6,
37
- symbol: "USDC"
40
+ symbol: "USDC",
41
+ eip712Name: "USD Coin"
38
42
  },
39
43
  USDT: {
40
44
  address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
41
45
  decimals: 6,
42
- symbol: "USDT"
46
+ symbol: "USDT",
47
+ eip712Name: "(PoS) Tether USD"
48
+ // Polygon uses this name
43
49
  }
44
50
  },
45
51
  usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
@@ -47,27 +53,6 @@ var CHAINS = {
47
53
  explorerTx: "https://polygonscan.com/tx/",
48
54
  avgBlockTime: 2
49
55
  },
50
- ethereum: {
51
- name: "Ethereum",
52
- chainId: 1,
53
- rpc: "https://eth.llamarpc.com",
54
- tokens: {
55
- USDC: {
56
- address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
57
- decimals: 6,
58
- symbol: "USDC"
59
- },
60
- USDT: {
61
- address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
62
- decimals: 6,
63
- symbol: "USDT"
64
- }
65
- },
66
- usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
67
- explorer: "https://etherscan.io/address/",
68
- explorerTx: "https://etherscan.io/tx/",
69
- avgBlockTime: 12
70
- },
71
56
  // ============ Testnet ============
72
57
  base_sepolia: {
73
58
  name: "Base Sepolia",
@@ -77,13 +62,17 @@ var CHAINS = {
77
62
  USDC: {
78
63
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
79
64
  decimals: 6,
80
- symbol: "USDC"
65
+ symbol: "USDC",
66
+ eip712Name: "USDC"
67
+ // Testnet USDC uses 'USDC' not 'USD Coin'
81
68
  },
82
69
  USDT: {
83
70
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
84
71
  // Same as USDC on testnet (no official USDT)
85
72
  decimals: 6,
86
- symbol: "USDT"
73
+ symbol: "USDT",
74
+ eip712Name: "USDC"
75
+ // Uses same contract as USDC
87
76
  }
88
77
  },
89
78
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
@@ -91,27 +80,34 @@ var CHAINS = {
91
80
  explorerTx: "https://sepolia.basescan.org/tx/",
92
81
  avgBlockTime: 2
93
82
  },
94
- sepolia: {
95
- name: "Sepolia",
96
- chainId: 11155111,
97
- rpc: "https://rpc.sepolia.org",
83
+ // ============ Tempo Testnet (Moderato) ============
84
+ tempo_moderato: {
85
+ name: "Tempo Moderato",
86
+ chainId: 42431,
87
+ rpc: "https://rpc.moderato.tempo.xyz",
98
88
  tokens: {
89
+ // TIP-20 stablecoins on Tempo testnet (from mppx SDK)
90
+ // Note: Tempo uses USD as native gas token, not ETH
99
91
  USDC: {
100
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
92
+ address: "0x20c0000000000000000000000000000000000000",
93
+ // pathUSD - primary testnet stablecoin
101
94
  decimals: 6,
102
- symbol: "USDC"
95
+ symbol: "USDC",
96
+ eip712Name: "pathUSD"
103
97
  },
104
98
  USDT: {
105
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
106
- // Same as USDC on testnet
99
+ address: "0x20c0000000000000000000000000000000000001",
100
+ // alphaUSD
107
101
  decimals: 6,
108
- symbol: "USDT"
102
+ symbol: "USDT",
103
+ eip712Name: "alphaUSD"
109
104
  }
110
105
  },
111
- usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
112
- explorer: "https://sepolia.etherscan.io/address/",
113
- explorerTx: "https://sepolia.etherscan.io/tx/",
114
- avgBlockTime: 12
106
+ usdc: "0x20c0000000000000000000000000000000000000",
107
+ explorer: "https://explore.testnet.tempo.xyz/address/",
108
+ explorerTx: "https://explore.testnet.tempo.xyz/tx/",
109
+ avgBlockTime: 0.5
110
+ // ~500ms finality
115
111
  }
116
112
  };
117
113
  function getChain(name) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/verify/index.ts","../../src/chains/index.ts"],"sourcesContent":["/**\n * On-chain Payment Verification Module\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, getChainById, type ChainConfig, type ChainName, type TokenSymbol } from '../chains';\n\n// ERC20 Transfer event signature\nconst TRANSFER_EVENT_TOPIC = ethers.id('Transfer(address,address,uint256)');\n\nexport interface VerifyPaymentParams {\n txHash: string;\n expectedAmount: number;\n expectedTo?: string;\n chain?: string | number;\n /** Expected token (if not specified, accepts both USDC and USDT) */\n expectedToken?: TokenSymbol;\n}\n\nexport interface VerifyPaymentResult {\n verified: boolean;\n amount?: number;\n token?: TokenSymbol;\n from?: string;\n to?: string;\n txHash?: string;\n blockNumber?: number;\n error?: string;\n}\n\n/**\n * Verify on-chain payment\n * Supports both USDC and USDT transfers\n */\nexport async function verifyPayment(params: VerifyPaymentParams): Promise<VerifyPaymentResult> {\n const { txHash, expectedAmount, expectedTo, expectedToken } = params;\n \n // Get chain config\n let chain: ChainConfig | undefined;\n try {\n if (typeof params.chain === 'number') {\n chain = getChainById(params.chain);\n } else {\n chain = getChain((params.chain || 'base') as ChainName);\n }\n if (!chain) {\n return { verified: false, error: `Unsupported chain: ${params.chain}` };\n }\n } catch (e) {\n return { verified: false, error: `Unsupported chain: ${params.chain}` };\n }\n\n try {\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n \n // Get transaction receipt\n const receipt = await provider.getTransactionReceipt(txHash);\n \n if (!receipt) {\n return { verified: false, error: 'Transaction not found or not confirmed' };\n }\n\n if (receipt.status !== 1) {\n return { verified: false, error: 'Transaction failed' };\n }\n\n // Build map of accepted token addresses\n const tokenAddresses: Record<string, TokenSymbol> = {};\n \n if (!expectedToken || expectedToken === 'USDC') {\n tokenAddresses[chain.tokens.USDC.address.toLowerCase()] = 'USDC';\n }\n if (!expectedToken || expectedToken === 'USDT') {\n tokenAddresses[chain.tokens.USDT.address.toLowerCase()] = 'USDT';\n }\n\n if (Object.keys(tokenAddresses).length === 0) {\n return { verified: false, error: `No token addresses configured for ${chain.name}` };\n }\n\n for (const log of receipt.logs) {\n const logAddress = log.address.toLowerCase();\n \n // Check if this is one of our accepted tokens\n const detectedToken = tokenAddresses[logAddress];\n if (!detectedToken) {\n continue;\n }\n\n // Check if Transfer event\n if (log.topics.length < 3 || log.topics[0] !== TRANSFER_EVENT_TOPIC) {\n continue;\n }\n\n // Parse Transfer event params\n const from = '0x' + log.topics[1].slice(-40);\n const to = '0x' + log.topics[2].slice(-40);\n const amountRaw = BigInt(log.data);\n const tokenConfig = chain.tokens[detectedToken];\n const amount = Number(amountRaw) / (10 ** tokenConfig.decimals);\n\n // Verify recipient address\n if (expectedTo && to.toLowerCase() !== expectedTo.toLowerCase()) {\n continue;\n }\n\n // Verify amount\n if (amount < expectedAmount) {\n return {\n verified: false,\n error: `Insufficient amount: received ${amount} ${detectedToken}, expected ${expectedAmount}`,\n amount,\n token: detectedToken,\n from,\n to,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n }\n\n // Verification successful\n return {\n verified: true,\n amount,\n token: detectedToken,\n from,\n to,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n }\n\n const tokenList = expectedToken ? expectedToken : 'USDC/USDT';\n return { verified: false, error: `No ${tokenList} transfer found` };\n\n } catch (e: any) {\n return { verified: false, error: e.message || String(e) };\n }\n}\n\n/**\n * Get transaction status\n */\nexport async function getTransactionStatus(\n txHash: string,\n chain: string | number = 'base'\n): Promise<{\n status: 'pending' | 'confirmed' | 'failed' | 'not_found';\n blockNumber?: number;\n confirmations?: number;\n}> {\n let chainConfig: ChainConfig | undefined;\n try {\n chainConfig = typeof chain === 'number' ? getChainById(chain) : getChain(chain as ChainName);\n if (!chainConfig) return { status: 'not_found' };\n } catch {\n return { status: 'not_found' };\n }\n\n try {\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n const receipt = await provider.getTransactionReceipt(txHash);\n\n if (!receipt) {\n // Check if in pending pool\n const tx = await provider.getTransaction(txHash);\n if (tx) {\n return { status: 'pending' };\n }\n return { status: 'not_found' };\n }\n\n const currentBlock = await provider.getBlockNumber();\n const confirmations = currentBlock - receipt.blockNumber;\n\n if (receipt.status === 1) {\n return {\n status: 'confirmed',\n blockNumber: receipt.blockNumber,\n confirmations,\n };\n } else {\n return {\n status: 'failed',\n blockNumber: receipt.blockNumber,\n };\n }\n } catch {\n return { status: 'not_found' };\n }\n}\n\n/**\n * Wait for transaction confirmation\n */\nexport async function waitForTransaction(\n txHash: string,\n chain: string | number = 'base',\n confirmations = 1,\n timeoutMs = 60000\n): Promise<VerifyPaymentResult & { confirmed: boolean }> {\n let chainConfig: ChainConfig | undefined;\n try {\n chainConfig = typeof chain === 'number' ? getChainById(chain) : getChain(chain as ChainName);\n if (!chainConfig) {\n return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };\n }\n } catch (e) {\n return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };\n }\n\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n \n try {\n const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);\n \n if (!receipt) {\n return { verified: false, confirmed: false, error: 'Timeout waiting' };\n }\n\n if (receipt.status !== 1) {\n return { verified: false, confirmed: true, error: 'Transaction failed' };\n }\n\n return {\n verified: true,\n confirmed: true,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n } catch (e: any) {\n return { verified: false, confirmed: false, error: e.message || String(e) };\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName, TokenSymbol } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n tokens: {\n USDC: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n symbol: 'USDC',\n },\n USDT: {\n address: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',\n decimals: 6,\n symbol: 'USDT',\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 },\n USDT: {\n address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',\n decimals: 6,\n symbol: 'USDT',\n },\n },\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n rpc: 'https://eth.llamarpc.com',\n tokens: {\n USDC: {\n address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n decimals: 6,\n symbol: 'USDC',\n },\n USDT: {\n address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',\n decimals: 6,\n symbol: 'USDT',\n },\n },\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n explorer: 'https://etherscan.io/address/',\n explorerTx: 'https://etherscan.io/tx/',\n avgBlockTime: 12,\n },\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 },\n USDT: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Same as USDC on testnet (no official USDT)\n decimals: 6,\n symbol: 'USDT',\n },\n },\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n sepolia: {\n name: 'Sepolia',\n chainId: 11155111,\n rpc: 'https://rpc.sepolia.org',\n tokens: {\n USDC: {\n address: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n decimals: 6,\n symbol: 'USDC',\n },\n USDT: {\n address: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', // Same as USDC on testnet\n decimals: 6,\n symbol: 'USDT',\n },\n },\n usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n explorer: 'https://sepolia.etherscan.io/address/',\n explorerTx: 'https://sepolia.etherscan.io/tx/',\n avgBlockTime: 12,\n },\n};\n\n/**\n * Get token address for a chain\n */\nexport function getTokenAddress(chainName: ChainName, token: TokenSymbol): string {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n const tokenConfig = chain.tokens[token];\n if (!tokenConfig) {\n throw new Error(`Token ${token} not supported on ${chainName}`);\n }\n return tokenConfig.address;\n}\n\n/**\n * Get token config for a chain\n */\nexport function getTokenConfig(chainName: ChainName, token: TokenSymbol) {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n return chain.tokens[token];\n}\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * List all supported chains\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * Get chain config by chainId\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI (minimal, only required methods)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName, TokenSymbol };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/verify/index.ts","../../src/chains/index.ts"],"sourcesContent":["/**\n * On-chain Payment Verification Module\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, getChainById, type ChainConfig, type ChainName, type TokenSymbol } from '../chains';\n\n// ERC20 Transfer event signature\nconst TRANSFER_EVENT_TOPIC = ethers.id('Transfer(address,address,uint256)');\n\nexport interface VerifyPaymentParams {\n txHash: string;\n expectedAmount: number;\n expectedTo?: string;\n chain?: string | number;\n /** Expected token (if not specified, accepts both USDC and USDT) */\n expectedToken?: TokenSymbol;\n}\n\nexport interface VerifyPaymentResult {\n verified: boolean;\n amount?: number;\n token?: TokenSymbol;\n from?: string;\n to?: string;\n txHash?: string;\n blockNumber?: number;\n error?: string;\n}\n\n/**\n * Verify on-chain payment\n * Supports both USDC and USDT transfers\n */\nexport async function verifyPayment(params: VerifyPaymentParams): Promise<VerifyPaymentResult> {\n const { txHash, expectedAmount, expectedTo, expectedToken } = params;\n \n // Get chain config\n let chain: ChainConfig | undefined;\n try {\n if (typeof params.chain === 'number') {\n chain = getChainById(params.chain);\n } else {\n chain = getChain((params.chain || 'base') as ChainName);\n }\n if (!chain) {\n return { verified: false, error: `Unsupported chain: ${params.chain}` };\n }\n } catch (e) {\n return { verified: false, error: `Unsupported chain: ${params.chain}` };\n }\n\n try {\n const provider = new ethers.JsonRpcProvider(chain.rpc);\n \n // Get transaction receipt\n const receipt = await provider.getTransactionReceipt(txHash);\n \n if (!receipt) {\n return { verified: false, error: 'Transaction not found or not confirmed' };\n }\n\n if (receipt.status !== 1) {\n return { verified: false, error: 'Transaction failed' };\n }\n\n // Build map of accepted token addresses\n const tokenAddresses: Record<string, TokenSymbol> = {};\n \n if (!expectedToken || expectedToken === 'USDC') {\n tokenAddresses[chain.tokens.USDC.address.toLowerCase()] = 'USDC';\n }\n if (!expectedToken || expectedToken === 'USDT') {\n tokenAddresses[chain.tokens.USDT.address.toLowerCase()] = 'USDT';\n }\n\n if (Object.keys(tokenAddresses).length === 0) {\n return { verified: false, error: `No token addresses configured for ${chain.name}` };\n }\n\n for (const log of receipt.logs) {\n const logAddress = log.address.toLowerCase();\n \n // Check if this is one of our accepted tokens\n const detectedToken = tokenAddresses[logAddress];\n if (!detectedToken) {\n continue;\n }\n\n // Check if Transfer event\n if (log.topics.length < 3 || log.topics[0] !== TRANSFER_EVENT_TOPIC) {\n continue;\n }\n\n // Parse Transfer event params\n const from = '0x' + log.topics[1].slice(-40);\n const to = '0x' + log.topics[2].slice(-40);\n const amountRaw = BigInt(log.data);\n const tokenConfig = chain.tokens[detectedToken];\n const amount = Number(amountRaw) / (10 ** tokenConfig.decimals);\n\n // Verify recipient address\n if (expectedTo && to.toLowerCase() !== expectedTo.toLowerCase()) {\n continue;\n }\n\n // Verify amount\n if (amount < expectedAmount) {\n return {\n verified: false,\n error: `Insufficient amount: received ${amount} ${detectedToken}, expected ${expectedAmount}`,\n amount,\n token: detectedToken,\n from,\n to,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n }\n\n // Verification successful\n return {\n verified: true,\n amount,\n token: detectedToken,\n from,\n to,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n }\n\n const tokenList = expectedToken ? expectedToken : 'USDC/USDT';\n return { verified: false, error: `No ${tokenList} transfer found` };\n\n } catch (e: any) {\n return { verified: false, error: e.message || String(e) };\n }\n}\n\n/**\n * Get transaction status\n */\nexport async function getTransactionStatus(\n txHash: string,\n chain: string | number = 'base'\n): Promise<{\n status: 'pending' | 'confirmed' | 'failed' | 'not_found';\n blockNumber?: number;\n confirmations?: number;\n}> {\n let chainConfig: ChainConfig | undefined;\n try {\n chainConfig = typeof chain === 'number' ? getChainById(chain) : getChain(chain as ChainName);\n if (!chainConfig) return { status: 'not_found' };\n } catch {\n return { status: 'not_found' };\n }\n\n try {\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n const receipt = await provider.getTransactionReceipt(txHash);\n\n if (!receipt) {\n // Check if in pending pool\n const tx = await provider.getTransaction(txHash);\n if (tx) {\n return { status: 'pending' };\n }\n return { status: 'not_found' };\n }\n\n const currentBlock = await provider.getBlockNumber();\n const confirmations = currentBlock - receipt.blockNumber;\n\n if (receipt.status === 1) {\n return {\n status: 'confirmed',\n blockNumber: receipt.blockNumber,\n confirmations,\n };\n } else {\n return {\n status: 'failed',\n blockNumber: receipt.blockNumber,\n };\n }\n } catch {\n return { status: 'not_found' };\n }\n}\n\n/**\n * Wait for transaction confirmation\n */\nexport async function waitForTransaction(\n txHash: string,\n chain: string | number = 'base',\n confirmations = 1,\n timeoutMs = 60000\n): Promise<VerifyPaymentResult & { confirmed: boolean }> {\n let chainConfig: ChainConfig | undefined;\n try {\n chainConfig = typeof chain === 'number' ? getChainById(chain) : getChain(chain as ChainName);\n if (!chainConfig) {\n return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };\n }\n } catch (e) {\n return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };\n }\n\n const provider = new ethers.JsonRpcProvider(chainConfig.rpc);\n \n try {\n const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);\n \n if (!receipt) {\n return { verified: false, confirmed: false, error: 'Timeout waiting' };\n }\n\n if (receipt.status !== 1) {\n return { verified: false, confirmed: true, error: 'Transaction failed' };\n }\n\n return {\n verified: true,\n confirmed: true,\n txHash,\n blockNumber: receipt.blockNumber,\n };\n } catch (e: any) {\n return { verified: false, confirmed: false, error: e.message || String(e) };\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName, TokenSymbol } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n tokens: {\n USDC: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin', // EIP-712 domain name\n },\n USDT: {\n address: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // deprecated, for backward compat\n explorer: 'https://basescan.org/address/',\n explorerTx: 'https://basescan.org/tx/',\n avgBlockTime: 2,\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n rpc: 'https://polygon-bor-rpc.publicnode.com',\n tokens: {\n USDC: {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: '(PoS) Tether USD', // Polygon uses this name\n },\n },\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n // ============ Testnet ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n tokens: {\n USDC: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USDC', // Testnet USDC uses 'USDC' not 'USD Coin'\n },\n USDT: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Same as USDC on testnet (no official USDT)\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'USDC', // Uses same contract as USDC\n },\n },\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n // ============ Tempo Testnet (Moderato) ============\n tempo_moderato: {\n name: 'Tempo Moderato',\n chainId: 42431,\n rpc: 'https://rpc.moderato.tempo.xyz',\n tokens: {\n // TIP-20 stablecoins on Tempo testnet (from mppx SDK)\n // Note: Tempo uses USD as native gas token, not ETH\n USDC: {\n address: '0x20c0000000000000000000000000000000000000', // pathUSD - primary testnet stablecoin\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'pathUSD',\n },\n USDT: {\n address: '0x20c0000000000000000000000000000000000001', // alphaUSD\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'alphaUSD',\n },\n },\n usdc: '0x20c0000000000000000000000000000000000000',\n explorer: 'https://explore.testnet.tempo.xyz/address/',\n explorerTx: 'https://explore.testnet.tempo.xyz/tx/',\n avgBlockTime: 0.5, // ~500ms finality\n },\n};\n\n/**\n * Get token address for a chain\n */\nexport function getTokenAddress(chainName: ChainName, token: TokenSymbol): string {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n const tokenConfig = chain.tokens[token];\n if (!tokenConfig) {\n throw new Error(`Token ${token} not supported on ${chainName}`);\n }\n return tokenConfig.address;\n}\n\n/**\n * Get token config for a chain\n */\nexport function getTokenConfig(chainName: ChainName, token: TokenSymbol) {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n return chain.tokens[token];\n}\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * List all supported chains\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * Get chain config by chainId\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI (minimal, only required methods)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName, TokenSymbol };\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- import { C as ChainName, a as ChainConfig, W as WalletBalance, T as TokenSymbol, c as TransferResult } from '../index-B3v8IWjM.mjs';
1
+ import { C as ChainName, a as ChainConfig, W as WalletBalance, T as TokenSymbol, c as TransferResult } from '../index-On9ZaGDW.mjs';
2
2
  export { C as CreateWalletOptions, a as CreateWalletResult, W as WalletData, c as createWallet, g as getWalletAddress, l as loadWallet, w as walletExists } from '../createWallet-D53qu7ie.mjs';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { C as ChainName, a as ChainConfig, W as WalletBalance, T as TokenSymbol, c as TransferResult } from '../index-B3v8IWjM.js';
1
+ import { C as ChainName, a as ChainConfig, W as WalletBalance, T as TokenSymbol, c as TransferResult } from '../index-On9ZaGDW.js';
2
2
  export { C as CreateWalletOptions, a as CreateWalletResult, W as WalletData, c as createWallet, g as getWalletAddress, l as loadWallet, w as walletExists } from '../createWallet-D53qu7ie.js';
3
3
 
4
4
  /**
@@ -42,12 +42,15 @@ var CHAINS = {
42
42
  USDC: {
43
43
  address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
44
44
  decimals: 6,
45
- symbol: "USDC"
45
+ symbol: "USDC",
46
+ eip712Name: "USD Coin"
47
+ // EIP-712 domain name
46
48
  },
47
49
  USDT: {
48
50
  address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
49
51
  decimals: 6,
50
- symbol: "USDT"
52
+ symbol: "USDT",
53
+ eip712Name: "Tether USD"
51
54
  }
52
55
  },
53
56
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
@@ -64,12 +67,15 @@ var CHAINS = {
64
67
  USDC: {
65
68
  address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
66
69
  decimals: 6,
67
- symbol: "USDC"
70
+ symbol: "USDC",
71
+ eip712Name: "USD Coin"
68
72
  },
69
73
  USDT: {
70
74
  address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
71
75
  decimals: 6,
72
- symbol: "USDT"
76
+ symbol: "USDT",
77
+ eip712Name: "(PoS) Tether USD"
78
+ // Polygon uses this name
73
79
  }
74
80
  },
75
81
  usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
@@ -77,27 +83,6 @@ var CHAINS = {
77
83
  explorerTx: "https://polygonscan.com/tx/",
78
84
  avgBlockTime: 2
79
85
  },
80
- ethereum: {
81
- name: "Ethereum",
82
- chainId: 1,
83
- rpc: "https://eth.llamarpc.com",
84
- tokens: {
85
- USDC: {
86
- address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
87
- decimals: 6,
88
- symbol: "USDC"
89
- },
90
- USDT: {
91
- address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
92
- decimals: 6,
93
- symbol: "USDT"
94
- }
95
- },
96
- usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
97
- explorer: "https://etherscan.io/address/",
98
- explorerTx: "https://etherscan.io/tx/",
99
- avgBlockTime: 12
100
- },
101
86
  // ============ Testnet ============
102
87
  base_sepolia: {
103
88
  name: "Base Sepolia",
@@ -107,13 +92,17 @@ var CHAINS = {
107
92
  USDC: {
108
93
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
109
94
  decimals: 6,
110
- symbol: "USDC"
95
+ symbol: "USDC",
96
+ eip712Name: "USDC"
97
+ // Testnet USDC uses 'USDC' not 'USD Coin'
111
98
  },
112
99
  USDT: {
113
100
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
114
101
  // Same as USDC on testnet (no official USDT)
115
102
  decimals: 6,
116
- symbol: "USDT"
103
+ symbol: "USDT",
104
+ eip712Name: "USDC"
105
+ // Uses same contract as USDC
117
106
  }
118
107
  },
119
108
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
@@ -121,27 +110,34 @@ var CHAINS = {
121
110
  explorerTx: "https://sepolia.basescan.org/tx/",
122
111
  avgBlockTime: 2
123
112
  },
124
- sepolia: {
125
- name: "Sepolia",
126
- chainId: 11155111,
127
- rpc: "https://rpc.sepolia.org",
113
+ // ============ Tempo Testnet (Moderato) ============
114
+ tempo_moderato: {
115
+ name: "Tempo Moderato",
116
+ chainId: 42431,
117
+ rpc: "https://rpc.moderato.tempo.xyz",
128
118
  tokens: {
119
+ // TIP-20 stablecoins on Tempo testnet (from mppx SDK)
120
+ // Note: Tempo uses USD as native gas token, not ETH
129
121
  USDC: {
130
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
122
+ address: "0x20c0000000000000000000000000000000000000",
123
+ // pathUSD - primary testnet stablecoin
131
124
  decimals: 6,
132
- symbol: "USDC"
125
+ symbol: "USDC",
126
+ eip712Name: "pathUSD"
133
127
  },
134
128
  USDT: {
135
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
136
- // Same as USDC on testnet
129
+ address: "0x20c0000000000000000000000000000000000001",
130
+ // alphaUSD
137
131
  decimals: 6,
138
- symbol: "USDT"
132
+ symbol: "USDT",
133
+ eip712Name: "alphaUSD"
139
134
  }
140
135
  },
141
- usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
142
- explorer: "https://sepolia.etherscan.io/address/",
143
- explorerTx: "https://sepolia.etherscan.io/tx/",
144
- avgBlockTime: 12
136
+ usdc: "0x20c0000000000000000000000000000000000000",
137
+ explorer: "https://explore.testnet.tempo.xyz/address/",
138
+ explorerTx: "https://explore.testnet.tempo.xyz/tx/",
139
+ avgBlockTime: 0.5
140
+ // ~500ms finality
145
141
  }
146
142
  };
147
143
  function getChain(name) {