moltspay 0.9.5 → 0.9.7

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 (51) hide show
  1. package/README.md +68 -45
  2. package/dist/cdp/index.d.mts +1 -1
  3. package/dist/cdp/index.d.ts +1 -1
  4. package/dist/cdp/index.js +63 -0
  5. package/dist/cdp/index.js.map +1 -1
  6. package/dist/cdp/index.mjs +63 -0
  7. package/dist/cdp/index.mjs.map +1 -1
  8. package/dist/chains/index.d.mts +9 -5
  9. package/dist/chains/index.d.ts +9 -5
  10. package/dist/chains/index.js +85 -0
  11. package/dist/chains/index.js.map +1 -1
  12. package/dist/chains/index.mjs +83 -0
  13. package/dist/chains/index.mjs.map +1 -1
  14. package/dist/cli/index.js +201 -38
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/cli/index.mjs +201 -38
  17. package/dist/cli/index.mjs.map +1 -1
  18. package/dist/client/index.d.mts +18 -3
  19. package/dist/client/index.d.ts +18 -3
  20. package/dist/client/index.js +112 -15
  21. package/dist/client/index.js.map +1 -1
  22. package/dist/client/index.mjs +112 -15
  23. package/dist/client/index.mjs.map +1 -1
  24. package/dist/{index-Dg8n6wdW.d.mts → index-B3v8IWjM.d.mts} +11 -1
  25. package/dist/{index-Dg8n6wdW.d.ts → index-B3v8IWjM.d.ts} +11 -1
  26. package/dist/index.d.mts +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +203 -42
  29. package/dist/index.js.map +1 -1
  30. package/dist/index.mjs +203 -42
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/server/index.d.mts +19 -1
  33. package/dist/server/index.d.ts +19 -1
  34. package/dist/server/index.js +71 -19
  35. package/dist/server/index.js.map +1 -1
  36. package/dist/server/index.mjs +71 -19
  37. package/dist/server/index.mjs.map +1 -1
  38. package/dist/verify/index.d.mts +7 -0
  39. package/dist/verify/index.d.ts +7 -0
  40. package/dist/verify/index.js +83 -8
  41. package/dist/verify/index.js.map +1 -1
  42. package/dist/verify/index.mjs +83 -8
  43. package/dist/verify/index.mjs.map +1 -1
  44. package/dist/wallet/index.d.mts +16 -8
  45. package/dist/wallet/index.d.ts +16 -8
  46. package/dist/wallet/index.js +114 -18
  47. package/dist/wallet/index.js.map +1 -1
  48. package/dist/wallet/index.mjs +114 -18
  49. package/dist/wallet/index.mjs.map +1 -1
  50. package/package.json +1 -1
  51. 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,35 @@ 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
+ if (token === "USDT") {
31799
+ const balances = await this.getBalance();
31800
+ if (balances.native < 1e-4) {
31801
+ throw new Error(
31802
+ `USDT requires ETH for gas (~$0.01 on Base). Your ETH balance: ${balances.native.toFixed(6)} ETH. Please add a small amount of ETH to your wallet, or use USDC (gasless).`
31803
+ );
31804
+ }
31805
+ console.log(`[MoltsPay] \u26A0\uFE0F USDT requires gas (~$0.01). Proceeding with payment...`);
31806
+ } else {
31807
+ console.log(`[MoltsPay] Signing payment: $${amount} ${token} (gasless)`);
31808
+ }
31668
31809
  const payTo = req.payTo || req.resource;
31669
31810
  if (!payTo) {
31670
31811
  throw new Error("Missing payTo address in payment requirements");
31671
31812
  }
31672
- const authorization = await this.signEIP3009(payTo, amount, chain2);
31813
+ const authorization = await this.signEIP3009(payTo, amount, chain2, token);
31814
+ const tokenConfig = chain2.tokens[token];
31815
+ const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31673
31816
  const payload = {
31674
31817
  x402Version: X402_VERSION3,
31675
31818
  payload: authorization,
@@ -31677,11 +31820,11 @@ var MoltsPayClient = class {
31677
31820
  accepted: {
31678
31821
  scheme: "exact",
31679
31822
  network,
31680
- asset: req.asset || chain2.usdc,
31823
+ asset: tokenConfig.address,
31681
31824
  amount: amountRaw,
31682
31825
  payTo,
31683
31826
  maxTimeoutSeconds: req.maxTimeoutSeconds || 300,
31684
- extra: req.extra || { name: "USD Coin", version: "2" }
31827
+ extra: req.extra || { name: tokenName, version: "2" }
31685
31828
  }
31686
31829
  };
31687
31830
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
@@ -31705,12 +31848,14 @@ var MoltsPayClient = class {
31705
31848
  /**
31706
31849
  * Sign EIP-3009 transferWithAuthorization (GASLESS)
31707
31850
  * This only signs - no on-chain transaction, no gas needed.
31851
+ * Supports both USDC and USDT.
31708
31852
  */
31709
- async signEIP3009(to, amount, chain2) {
31853
+ async signEIP3009(to, amount, chain2, token = "USDC") {
31710
31854
  const validAfter = 0;
31711
31855
  const validBefore = Math.floor(Date.now() / 1e3) + 3600;
31712
31856
  const nonce = import_ethers.ethers.hexlify(import_ethers.ethers.randomBytes(32));
31713
- const value = BigInt(Math.floor(amount * 1e6)).toString();
31857
+ const tokenConfig = chain2.tokens[token];
31858
+ const value = BigInt(Math.floor(amount * 10 ** tokenConfig.decimals)).toString();
31714
31859
  const authorization = {
31715
31860
  from: this.wallet.address,
31716
31861
  to,
@@ -31719,11 +31864,12 @@ var MoltsPayClient = class {
31719
31864
  validBefore: validBefore.toString(),
31720
31865
  nonce
31721
31866
  };
31867
+ const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31722
31868
  const domain = {
31723
- name: "USD Coin",
31869
+ name: tokenName,
31724
31870
  version: "2",
31725
31871
  chainId: chain2.chainId,
31726
- verifyingContract: chain2.usdc
31872
+ verifyingContract: tokenConfig.address
31727
31873
  };
31728
31874
  const types = {
31729
31875
  TransferWithAuthorization: [
@@ -31858,7 +32004,7 @@ var MoltsPayClient = class {
31858
32004
  return { address: wallet.address, configDir };
31859
32005
  }
31860
32006
  /**
31861
- * Get wallet balance
32007
+ * Get wallet balance (USDC, USDT, and native token)
31862
32008
  */
31863
32009
  async getBalance() {
31864
32010
  if (!this.wallet) {
@@ -31871,12 +32017,15 @@ var MoltsPayClient = class {
31871
32017
  throw new Error(`Unknown chain: ${this.config.chain}`);
31872
32018
  }
31873
32019
  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);
32020
+ const tokenAbi = ["function balanceOf(address) view returns (uint256)"];
32021
+ const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([
32022
+ provider.getBalance(this.wallet.address),
32023
+ new import_ethers.ethers.Contract(chain2.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),
32024
+ new import_ethers.ethers.Contract(chain2.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address)
32025
+ ]);
31878
32026
  return {
31879
- usdc: parseFloat(import_ethers.ethers.formatUnits(usdcBalance, 6)),
32027
+ usdc: parseFloat(import_ethers.ethers.formatUnits(usdcBalance, chain2.tokens.USDC.decimals)),
32028
+ usdt: parseFloat(import_ethers.ethers.formatUnits(usdtBalance, chain2.tokens.USDT.decimals)),
31880
32029
  native: parseFloat(import_ethers.ethers.formatEther(nativeBalance))
31881
32030
  };
31882
32031
  }
@@ -32012,7 +32161,7 @@ init_cjs_shims();
32012
32161
  var import_ethers4 = require("ethers");
32013
32162
  var TRANSFER_EVENT_TOPIC = import_ethers4.ethers.id("Transfer(address,address,uint256)");
32014
32163
  async function verifyPayment(params) {
32015
- const { txHash, expectedAmount, expectedTo } = params;
32164
+ const { txHash, expectedAmount, expectedTo, expectedToken } = params;
32016
32165
  let chain2;
32017
32166
  try {
32018
32167
  if (typeof params.chain === "number") {
@@ -32035,12 +32184,20 @@ async function verifyPayment(params) {
32035
32184
  if (receipt.status !== 1) {
32036
32185
  return { verified: false, error: "Transaction failed" };
32037
32186
  }
32038
- const usdcAddress = chain2.usdc?.toLowerCase();
32039
- if (!usdcAddress) {
32040
- return { verified: false, error: `Chain ${chain2.name} USDC address not configured` };
32187
+ const tokenAddresses = {};
32188
+ if (!expectedToken || expectedToken === "USDC") {
32189
+ tokenAddresses[chain2.tokens.USDC.address.toLowerCase()] = "USDC";
32190
+ }
32191
+ if (!expectedToken || expectedToken === "USDT") {
32192
+ tokenAddresses[chain2.tokens.USDT.address.toLowerCase()] = "USDT";
32193
+ }
32194
+ if (Object.keys(tokenAddresses).length === 0) {
32195
+ return { verified: false, error: `No token addresses configured for ${chain2.name}` };
32041
32196
  }
32042
32197
  for (const log of receipt.logs) {
32043
- if (log.address.toLowerCase() !== usdcAddress) {
32198
+ const logAddress = log.address.toLowerCase();
32199
+ const detectedToken = tokenAddresses[logAddress];
32200
+ if (!detectedToken) {
32044
32201
  continue;
32045
32202
  }
32046
32203
  if (log.topics.length < 3 || log.topics[0] !== TRANSFER_EVENT_TOPIC) {
@@ -32049,15 +32206,17 @@ async function verifyPayment(params) {
32049
32206
  const from = "0x" + log.topics[1].slice(-40);
32050
32207
  const to = "0x" + log.topics[2].slice(-40);
32051
32208
  const amountRaw = BigInt(log.data);
32052
- const amount = Number(amountRaw) / 1e6;
32209
+ const tokenConfig = chain2.tokens[detectedToken];
32210
+ const amount = Number(amountRaw) / 10 ** tokenConfig.decimals;
32053
32211
  if (expectedTo && to.toLowerCase() !== expectedTo.toLowerCase()) {
32054
32212
  continue;
32055
32213
  }
32056
32214
  if (amount < expectedAmount) {
32057
32215
  return {
32058
32216
  verified: false,
32059
- error: `Insufficient amount: received ${amount} USDC, expected ${expectedAmount} USDC`,
32217
+ error: `Insufficient amount: received ${amount} ${detectedToken}, expected ${expectedAmount}`,
32060
32218
  amount,
32219
+ token: detectedToken,
32061
32220
  from,
32062
32221
  to,
32063
32222
  txHash,
@@ -32067,13 +32226,15 @@ async function verifyPayment(params) {
32067
32226
  return {
32068
32227
  verified: true,
32069
32228
  amount,
32229
+ token: detectedToken,
32070
32230
  from,
32071
32231
  to,
32072
32232
  txHash,
32073
32233
  blockNumber: receipt.blockNumber
32074
32234
  };
32075
32235
  }
32076
- return { verified: false, error: "No USDC transfer found" };
32236
+ const tokenList = expectedToken ? expectedToken : "USDC/USDT";
32237
+ return { verified: false, error: `No ${tokenList} transfer found` };
32077
32238
  } catch (e) {
32078
32239
  return { verified: false, error: e.message || String(e) };
32079
32240
  }