moltspay 0.9.5 → 0.9.6

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 (50) hide show
  1. package/dist/cdp/index.d.mts +1 -1
  2. package/dist/cdp/index.d.ts +1 -1
  3. package/dist/cdp/index.js +63 -0
  4. package/dist/cdp/index.js.map +1 -1
  5. package/dist/cdp/index.mjs +63 -0
  6. package/dist/cdp/index.mjs.map +1 -1
  7. package/dist/chains/index.d.mts +9 -5
  8. package/dist/chains/index.d.ts +9 -5
  9. package/dist/chains/index.js +85 -0
  10. package/dist/chains/index.js.map +1 -1
  11. package/dist/chains/index.mjs +83 -0
  12. package/dist/chains/index.mjs.map +1 -1
  13. package/dist/cli/index.js +179 -38
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/index.mjs +179 -38
  16. package/dist/cli/index.mjs.map +1 -1
  17. package/dist/client/index.d.mts +18 -3
  18. package/dist/client/index.d.ts +18 -3
  19. package/dist/client/index.js +102 -15
  20. package/dist/client/index.js.map +1 -1
  21. package/dist/client/index.mjs +102 -15
  22. package/dist/client/index.mjs.map +1 -1
  23. package/dist/{index-Dg8n6wdW.d.mts → index-B3v8IWjM.d.mts} +11 -1
  24. package/dist/{index-Dg8n6wdW.d.ts → index-B3v8IWjM.d.ts} +11 -1
  25. package/dist/index.d.mts +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +193 -42
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +193 -42
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/server/index.d.mts +19 -1
  32. package/dist/server/index.d.ts +19 -1
  33. package/dist/server/index.js +71 -19
  34. package/dist/server/index.js.map +1 -1
  35. package/dist/server/index.mjs +71 -19
  36. package/dist/server/index.mjs.map +1 -1
  37. package/dist/verify/index.d.mts +7 -0
  38. package/dist/verify/index.d.ts +7 -0
  39. package/dist/verify/index.js +83 -8
  40. package/dist/verify/index.js.map +1 -1
  41. package/dist/verify/index.mjs +83 -8
  42. package/dist/verify/index.mjs.map +1 -1
  43. package/dist/wallet/index.d.mts +16 -8
  44. package/dist/wallet/index.d.ts +16 -8
  45. package/dist/wallet/index.js +114 -18
  46. package/dist/wallet/index.js.map +1 -1
  47. package/dist/wallet/index.mjs +114 -18
  48. package/dist/wallet/index.mjs.map +1 -1
  49. package/package.json +1 -1
  50. package/schemas/moltspay.services.schema.json +13 -3
package/dist/index.js CHANGED
@@ -30844,16 +30844,24 @@ var X402_VERSION2 = 2;
30844
30844
  var PAYMENT_REQUIRED_HEADER = "x-payment-required";
30845
30845
  var PAYMENT_HEADER = "x-payment";
30846
30846
  var PAYMENT_RESPONSE_HEADER = "x-payment-response";
30847
- var USDC_ADDRESSES = {
30848
- "eip155:8453": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
30849
- // Base mainnet
30850
- "eip155:84532": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
30851
- // Base Sepolia
30847
+ var TOKEN_ADDRESSES = {
30848
+ "eip155:8453": {
30849
+ USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
30850
+ USDT: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2"
30851
+ },
30852
+ "eip155:84532": {
30853
+ USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
30854
+ USDT: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
30855
+ // Same as USDC on testnet
30856
+ }
30852
30857
  };
30853
- var USDC_DOMAIN = {
30854
- name: "USD Coin",
30855
- version: "2"
30858
+ var TOKEN_DOMAINS = {
30859
+ USDC: { name: "USD Coin", version: "2" },
30860
+ USDT: { name: "Tether USD", version: "2" }
30856
30861
  };
30862
+ function getAcceptedCurrencies(config) {
30863
+ return config.acceptedCurrencies ?? [config.currency];
30864
+ }
30857
30865
  function loadEnvFile2() {
30858
30866
  const envPaths = [
30859
30867
  path2.join(process.cwd(), ".env"),
@@ -31001,6 +31009,7 @@ var MoltsPayServer = class {
31001
31009
  description: s.description,
31002
31010
  price: s.price,
31003
31011
  currency: s.currency,
31012
+ acceptedCurrencies: getAcceptedCurrencies(s),
31004
31013
  input: s.input,
31005
31014
  output: s.output,
31006
31015
  available: this.skills.has(s.id)
@@ -31038,6 +31047,7 @@ var MoltsPayServer = class {
31038
31047
  description: s.description,
31039
31048
  price: s.price,
31040
31049
  currency: s.currency,
31050
+ acceptedCurrencies: getAcceptedCurrencies(s),
31041
31051
  input: s.input,
31042
31052
  output: s.output,
31043
31053
  available: this.skills.has(s.id)
@@ -31104,7 +31114,14 @@ var MoltsPayServer = class {
31104
31114
  if (!validation.valid) {
31105
31115
  return this.sendJson(res, 402, { error: validation.error });
31106
31116
  }
31107
- const requirements = this.buildPaymentRequirements(skill.config);
31117
+ const paymentToken = this.detectPaymentToken(payment);
31118
+ if (paymentToken && !this.isTokenAccepted(skill.config, paymentToken)) {
31119
+ const accepted = getAcceptedCurrencies(skill.config);
31120
+ return this.sendJson(res, 402, {
31121
+ error: `Token ${paymentToken} not accepted. Accepted: ${accepted.join(", ")}`
31122
+ });
31123
+ }
31124
+ const requirements = this.buildPaymentRequirements(skill.config, paymentToken);
31108
31125
  console.log(`[MoltsPay] Verifying payment...`);
31109
31126
  const verifyResult = await this.registry.verify(payment, requirements);
31110
31127
  if (!verifyResult.valid) {
@@ -31159,12 +31176,15 @@ var MoltsPayServer = class {
31159
31176
  }
31160
31177
  /**
31161
31178
  * Return 402 with x402 payment requirements (v2 format)
31179
+ * Includes requirements for all accepted currencies
31162
31180
  */
31163
31181
  sendPaymentRequired(config, res) {
31164
- const requirements = this.buildPaymentRequirements(config);
31182
+ const acceptedTokens = getAcceptedCurrencies(config);
31183
+ const accepts = acceptedTokens.map((token) => this.buildPaymentRequirements(config, token));
31165
31184
  const paymentRequired = {
31166
31185
  x402Version: X402_VERSION2,
31167
- accepts: [requirements],
31186
+ accepts,
31187
+ acceptedCurrencies: acceptedTokens,
31168
31188
  resource: {
31169
31189
  url: `/execute?service=${config.id}`,
31170
31190
  description: `${config.name} - $${config.price} ${config.currency}`,
@@ -31179,6 +31199,7 @@ var MoltsPayServer = class {
31179
31199
  res.end(JSON.stringify({
31180
31200
  error: "Payment required",
31181
31201
  message: `Service requires $${config.price} ${config.currency}`,
31202
+ acceptedCurrencies: acceptedTokens,
31182
31203
  x402: paymentRequired
31183
31204
  }, null, 2));
31184
31205
  }
@@ -31201,20 +31222,47 @@ var MoltsPayServer = class {
31201
31222
  }
31202
31223
  /**
31203
31224
  * Build payment requirements for facilitator
31225
+ * Returns requirements for the primary currency (USDC by default)
31226
+ * Server accepts any of the acceptedCurrencies
31204
31227
  */
31205
- buildPaymentRequirements(config) {
31228
+ buildPaymentRequirements(config, token) {
31206
31229
  const amountInUnits = Math.floor(config.price * 1e6).toString();
31207
- const usdcAddress = USDC_ADDRESSES[this.networkId];
31230
+ const acceptedTokens = getAcceptedCurrencies(config);
31231
+ const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
31232
+ const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
31233
+ const tokenAddress = tokenAddresses[selectedToken];
31234
+ const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
31208
31235
  return {
31209
31236
  scheme: "exact",
31210
31237
  network: this.networkId,
31211
- asset: usdcAddress,
31238
+ asset: tokenAddress,
31212
31239
  amount: amountInUnits,
31213
31240
  payTo: this.manifest.provider.wallet,
31214
31241
  maxTimeoutSeconds: 300,
31215
- extra: USDC_DOMAIN
31242
+ extra: tokenDomain
31216
31243
  };
31217
31244
  }
31245
+ /**
31246
+ * Detect which token is being used in the payment
31247
+ */
31248
+ detectPaymentToken(payment) {
31249
+ const asset = payment.accepted?.asset || payment.payload?.asset;
31250
+ if (!asset) return void 0;
31251
+ const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
31252
+ for (const [symbol, address] of Object.entries(tokenAddresses)) {
31253
+ if (address.toLowerCase() === asset.toLowerCase()) {
31254
+ return symbol;
31255
+ }
31256
+ }
31257
+ return void 0;
31258
+ }
31259
+ /**
31260
+ * Check if payment token is accepted for service
31261
+ */
31262
+ isTokenAccepted(config, token) {
31263
+ const accepted = getAcceptedCurrencies(config);
31264
+ return accepted.includes(token);
31265
+ }
31218
31266
  async readBody(req) {
31219
31267
  return new Promise((resolve, reject) => {
31220
31268
  let body = "";
@@ -31414,18 +31462,22 @@ var MoltsPayServer = class {
31414
31462
  /**
31415
31463
  * Build payment requirements for proxy endpoint (uses provided wallet)
31416
31464
  */
31417
- buildProxyPaymentRequirements(config, wallet) {
31465
+ buildProxyPaymentRequirements(config, wallet, token) {
31418
31466
  const amountInUnits = Math.floor(config.price * 1e6).toString();
31419
- const usdcAddress = USDC_ADDRESSES[this.networkId];
31467
+ const acceptedTokens = getAcceptedCurrencies(config);
31468
+ const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
31469
+ const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
31470
+ const tokenAddress = tokenAddresses[selectedToken];
31471
+ const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
31420
31472
  return {
31421
31473
  scheme: "exact",
31422
31474
  network: this.networkId,
31423
- asset: usdcAddress,
31475
+ asset: tokenAddress,
31424
31476
  amount: amountInUnits,
31425
31477
  payTo: wallet,
31426
31478
  // Use provided wallet, not manifest
31427
31479
  maxTimeoutSeconds: 300,
31428
- extra: USDC_DOMAIN
31480
+ extra: tokenDomain
31429
31481
  };
31430
31482
  }
31431
31483
  /**
@@ -31471,7 +31523,20 @@ var CHAINS = {
31471
31523
  name: "Base",
31472
31524
  chainId: 8453,
31473
31525
  rpc: "https://mainnet.base.org",
31526
+ tokens: {
31527
+ USDC: {
31528
+ address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
31529
+ decimals: 6,
31530
+ symbol: "USDC"
31531
+ },
31532
+ USDT: {
31533
+ address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
31534
+ decimals: 6,
31535
+ symbol: "USDT"
31536
+ }
31537
+ },
31474
31538
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
31539
+ // deprecated, for backward compat
31475
31540
  explorer: "https://basescan.org/address/",
31476
31541
  explorerTx: "https://basescan.org/tx/",
31477
31542
  avgBlockTime: 2
@@ -31480,6 +31545,18 @@ var CHAINS = {
31480
31545
  name: "Polygon",
31481
31546
  chainId: 137,
31482
31547
  rpc: "https://polygon-rpc.com",
31548
+ tokens: {
31549
+ USDC: {
31550
+ address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
31551
+ decimals: 6,
31552
+ symbol: "USDC"
31553
+ },
31554
+ USDT: {
31555
+ address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
31556
+ decimals: 6,
31557
+ symbol: "USDT"
31558
+ }
31559
+ },
31483
31560
  usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
31484
31561
  explorer: "https://polygonscan.com/address/",
31485
31562
  explorerTx: "https://polygonscan.com/tx/",
@@ -31489,6 +31566,18 @@ var CHAINS = {
31489
31566
  name: "Ethereum",
31490
31567
  chainId: 1,
31491
31568
  rpc: "https://eth.llamarpc.com",
31569
+ tokens: {
31570
+ USDC: {
31571
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
31572
+ decimals: 6,
31573
+ symbol: "USDC"
31574
+ },
31575
+ USDT: {
31576
+ address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
31577
+ decimals: 6,
31578
+ symbol: "USDT"
31579
+ }
31580
+ },
31492
31581
  usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
31493
31582
  explorer: "https://etherscan.io/address/",
31494
31583
  explorerTx: "https://etherscan.io/tx/",
@@ -31499,6 +31588,19 @@ var CHAINS = {
31499
31588
  name: "Base Sepolia",
31500
31589
  chainId: 84532,
31501
31590
  rpc: "https://sepolia.base.org",
31591
+ tokens: {
31592
+ USDC: {
31593
+ address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31594
+ decimals: 6,
31595
+ symbol: "USDC"
31596
+ },
31597
+ USDT: {
31598
+ address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31599
+ // Same as USDC on testnet (no official USDT)
31600
+ decimals: 6,
31601
+ symbol: "USDT"
31602
+ }
31603
+ },
31502
31604
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31503
31605
  explorer: "https://sepolia.basescan.org/address/",
31504
31606
  explorerTx: "https://sepolia.basescan.org/tx/",
@@ -31508,6 +31610,19 @@ var CHAINS = {
31508
31610
  name: "Sepolia",
31509
31611
  chainId: 11155111,
31510
31612
  rpc: "https://rpc.sepolia.org",
31613
+ tokens: {
31614
+ USDC: {
31615
+ address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31616
+ decimals: 6,
31617
+ symbol: "USDC"
31618
+ },
31619
+ USDT: {
31620
+ address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31621
+ // Same as USDC on testnet
31622
+ decimals: 6,
31623
+ symbol: "USDT"
31624
+ }
31625
+ },
31511
31626
  usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31512
31627
  explorer: "https://sepolia.etherscan.io/address/",
31513
31628
  explorerTx: "https://sepolia.etherscan.io/tx/",
@@ -31616,8 +31731,13 @@ var MoltsPayClient = class {
31616
31731
  *
31617
31732
  * This is GASLESS for the client - server pays gas to claim payment.
31618
31733
  * This is PAY-FOR-SUCCESS - payment only claimed if service succeeds.
31734
+ *
31735
+ * @param serverUrl - Server URL
31736
+ * @param service - Service ID
31737
+ * @param params - Service parameters
31738
+ * @param options - Payment options (token selection)
31619
31739
  */
31620
- async pay(serverUrl, service, params) {
31740
+ async pay(serverUrl, service, params, options = {}) {
31621
31741
  if (!this.wallet || !this.walletData) {
31622
31742
  throw new Error("Client not initialized. Run: npx moltspay init");
31623
31743
  }
@@ -31664,12 +31784,25 @@ var MoltsPayClient = class {
31664
31784
  }
31665
31785
  const amount = Number(amountRaw) / 1e6;
31666
31786
  this.checkLimits(amount);
31667
- console.log(`[MoltsPay] Signing payment: $${amount} USDC (gasless)`);
31787
+ let token = options.token || "USDC";
31788
+ if (options.autoSelect) {
31789
+ const balances = await this.getBalance();
31790
+ if (balances.usdc >= amount) {
31791
+ token = "USDC";
31792
+ } else if (balances.usdt >= amount) {
31793
+ token = "USDT";
31794
+ } else {
31795
+ throw new Error(`Insufficient balance: need $${amount}, have ${balances.usdc} USDC / ${balances.usdt} USDT`);
31796
+ }
31797
+ }
31798
+ console.log(`[MoltsPay] Signing payment: $${amount} ${token} (gasless)`);
31668
31799
  const payTo = req.payTo || req.resource;
31669
31800
  if (!payTo) {
31670
31801
  throw new Error("Missing payTo address in payment requirements");
31671
31802
  }
31672
- const authorization = await this.signEIP3009(payTo, amount, chain2);
31803
+ const authorization = await this.signEIP3009(payTo, amount, chain2, token);
31804
+ const tokenConfig = chain2.tokens[token];
31805
+ const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31673
31806
  const payload = {
31674
31807
  x402Version: X402_VERSION3,
31675
31808
  payload: authorization,
@@ -31677,11 +31810,11 @@ var MoltsPayClient = class {
31677
31810
  accepted: {
31678
31811
  scheme: "exact",
31679
31812
  network,
31680
- asset: req.asset || chain2.usdc,
31813
+ asset: tokenConfig.address,
31681
31814
  amount: amountRaw,
31682
31815
  payTo,
31683
31816
  maxTimeoutSeconds: req.maxTimeoutSeconds || 300,
31684
- extra: req.extra || { name: "USD Coin", version: "2" }
31817
+ extra: req.extra || { name: tokenName, version: "2" }
31685
31818
  }
31686
31819
  };
31687
31820
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
@@ -31705,12 +31838,14 @@ var MoltsPayClient = class {
31705
31838
  /**
31706
31839
  * Sign EIP-3009 transferWithAuthorization (GASLESS)
31707
31840
  * This only signs - no on-chain transaction, no gas needed.
31841
+ * Supports both USDC and USDT.
31708
31842
  */
31709
- async signEIP3009(to, amount, chain2) {
31843
+ async signEIP3009(to, amount, chain2, token = "USDC") {
31710
31844
  const validAfter = 0;
31711
31845
  const validBefore = Math.floor(Date.now() / 1e3) + 3600;
31712
31846
  const nonce = import_ethers.ethers.hexlify(import_ethers.ethers.randomBytes(32));
31713
- const value = BigInt(Math.floor(amount * 1e6)).toString();
31847
+ const tokenConfig = chain2.tokens[token];
31848
+ const value = BigInt(Math.floor(amount * 10 ** tokenConfig.decimals)).toString();
31714
31849
  const authorization = {
31715
31850
  from: this.wallet.address,
31716
31851
  to,
@@ -31719,11 +31854,12 @@ var MoltsPayClient = class {
31719
31854
  validBefore: validBefore.toString(),
31720
31855
  nonce
31721
31856
  };
31857
+ const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31722
31858
  const domain = {
31723
- name: "USD Coin",
31859
+ name: tokenName,
31724
31860
  version: "2",
31725
31861
  chainId: chain2.chainId,
31726
- verifyingContract: chain2.usdc
31862
+ verifyingContract: tokenConfig.address
31727
31863
  };
31728
31864
  const types = {
31729
31865
  TransferWithAuthorization: [
@@ -31858,7 +31994,7 @@ var MoltsPayClient = class {
31858
31994
  return { address: wallet.address, configDir };
31859
31995
  }
31860
31996
  /**
31861
- * Get wallet balance
31997
+ * Get wallet balance (USDC, USDT, and native token)
31862
31998
  */
31863
31999
  async getBalance() {
31864
32000
  if (!this.wallet) {
@@ -31871,12 +32007,15 @@ var MoltsPayClient = class {
31871
32007
  throw new Error(`Unknown chain: ${this.config.chain}`);
31872
32008
  }
31873
32009
  const provider = new import_ethers.ethers.JsonRpcProvider(chain2.rpc);
31874
- const nativeBalance = await provider.getBalance(this.wallet.address);
31875
- const usdcAbi = ["function balanceOf(address) view returns (uint256)"];
31876
- const usdc = new import_ethers.ethers.Contract(chain2.usdc, usdcAbi, provider);
31877
- const usdcBalance = await usdc.balanceOf(this.wallet.address);
32010
+ const tokenAbi = ["function balanceOf(address) view returns (uint256)"];
32011
+ const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([
32012
+ provider.getBalance(this.wallet.address),
32013
+ new import_ethers.ethers.Contract(chain2.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),
32014
+ new import_ethers.ethers.Contract(chain2.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address)
32015
+ ]);
31878
32016
  return {
31879
- usdc: parseFloat(import_ethers.ethers.formatUnits(usdcBalance, 6)),
32017
+ usdc: parseFloat(import_ethers.ethers.formatUnits(usdcBalance, chain2.tokens.USDC.decimals)),
32018
+ usdt: parseFloat(import_ethers.ethers.formatUnits(usdtBalance, chain2.tokens.USDT.decimals)),
31880
32019
  native: parseFloat(import_ethers.ethers.formatEther(nativeBalance))
31881
32020
  };
31882
32021
  }
@@ -32012,7 +32151,7 @@ init_cjs_shims();
32012
32151
  var import_ethers4 = require("ethers");
32013
32152
  var TRANSFER_EVENT_TOPIC = import_ethers4.ethers.id("Transfer(address,address,uint256)");
32014
32153
  async function verifyPayment(params) {
32015
- const { txHash, expectedAmount, expectedTo } = params;
32154
+ const { txHash, expectedAmount, expectedTo, expectedToken } = params;
32016
32155
  let chain2;
32017
32156
  try {
32018
32157
  if (typeof params.chain === "number") {
@@ -32035,12 +32174,20 @@ async function verifyPayment(params) {
32035
32174
  if (receipt.status !== 1) {
32036
32175
  return { verified: false, error: "Transaction failed" };
32037
32176
  }
32038
- const usdcAddress = chain2.usdc?.toLowerCase();
32039
- if (!usdcAddress) {
32040
- return { verified: false, error: `Chain ${chain2.name} USDC address not configured` };
32177
+ const tokenAddresses = {};
32178
+ if (!expectedToken || expectedToken === "USDC") {
32179
+ tokenAddresses[chain2.tokens.USDC.address.toLowerCase()] = "USDC";
32180
+ }
32181
+ if (!expectedToken || expectedToken === "USDT") {
32182
+ tokenAddresses[chain2.tokens.USDT.address.toLowerCase()] = "USDT";
32183
+ }
32184
+ if (Object.keys(tokenAddresses).length === 0) {
32185
+ return { verified: false, error: `No token addresses configured for ${chain2.name}` };
32041
32186
  }
32042
32187
  for (const log of receipt.logs) {
32043
- if (log.address.toLowerCase() !== usdcAddress) {
32188
+ const logAddress = log.address.toLowerCase();
32189
+ const detectedToken = tokenAddresses[logAddress];
32190
+ if (!detectedToken) {
32044
32191
  continue;
32045
32192
  }
32046
32193
  if (log.topics.length < 3 || log.topics[0] !== TRANSFER_EVENT_TOPIC) {
@@ -32049,15 +32196,17 @@ async function verifyPayment(params) {
32049
32196
  const from = "0x" + log.topics[1].slice(-40);
32050
32197
  const to = "0x" + log.topics[2].slice(-40);
32051
32198
  const amountRaw = BigInt(log.data);
32052
- const amount = Number(amountRaw) / 1e6;
32199
+ const tokenConfig = chain2.tokens[detectedToken];
32200
+ const amount = Number(amountRaw) / 10 ** tokenConfig.decimals;
32053
32201
  if (expectedTo && to.toLowerCase() !== expectedTo.toLowerCase()) {
32054
32202
  continue;
32055
32203
  }
32056
32204
  if (amount < expectedAmount) {
32057
32205
  return {
32058
32206
  verified: false,
32059
- error: `Insufficient amount: received ${amount} USDC, expected ${expectedAmount} USDC`,
32207
+ error: `Insufficient amount: received ${amount} ${detectedToken}, expected ${expectedAmount}`,
32060
32208
  amount,
32209
+ token: detectedToken,
32061
32210
  from,
32062
32211
  to,
32063
32212
  txHash,
@@ -32067,13 +32216,15 @@ async function verifyPayment(params) {
32067
32216
  return {
32068
32217
  verified: true,
32069
32218
  amount,
32219
+ token: detectedToken,
32070
32220
  from,
32071
32221
  to,
32072
32222
  txHash,
32073
32223
  blockNumber: receipt.blockNumber
32074
32224
  };
32075
32225
  }
32076
- return { verified: false, error: "No USDC transfer found" };
32226
+ const tokenList = expectedToken ? expectedToken : "USDC/USDT";
32227
+ return { verified: false, error: `No ${tokenList} transfer found` };
32077
32228
  } catch (e) {
32078
32229
  return { verified: false, error: e.message || String(e) };
32079
32230
  }