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.mjs CHANGED
@@ -30802,16 +30802,24 @@ var X402_VERSION2 = 2;
30802
30802
  var PAYMENT_REQUIRED_HEADER = "x-payment-required";
30803
30803
  var PAYMENT_HEADER = "x-payment";
30804
30804
  var PAYMENT_RESPONSE_HEADER = "x-payment-response";
30805
- var USDC_ADDRESSES = {
30806
- "eip155:8453": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
30807
- // Base mainnet
30808
- "eip155:84532": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
30809
- // Base Sepolia
30805
+ var TOKEN_ADDRESSES = {
30806
+ "eip155:8453": {
30807
+ USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
30808
+ USDT: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2"
30809
+ },
30810
+ "eip155:84532": {
30811
+ USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
30812
+ USDT: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
30813
+ // Same as USDC on testnet
30814
+ }
30810
30815
  };
30811
- var USDC_DOMAIN = {
30812
- name: "USD Coin",
30813
- version: "2"
30816
+ var TOKEN_DOMAINS = {
30817
+ USDC: { name: "USD Coin", version: "2" },
30818
+ USDT: { name: "Tether USD", version: "2" }
30814
30819
  };
30820
+ function getAcceptedCurrencies(config) {
30821
+ return config.acceptedCurrencies ?? [config.currency];
30822
+ }
30815
30823
  function loadEnvFile2() {
30816
30824
  const envPaths = [
30817
30825
  path3.join(process.cwd(), ".env"),
@@ -30959,6 +30967,7 @@ var MoltsPayServer = class {
30959
30967
  description: s.description,
30960
30968
  price: s.price,
30961
30969
  currency: s.currency,
30970
+ acceptedCurrencies: getAcceptedCurrencies(s),
30962
30971
  input: s.input,
30963
30972
  output: s.output,
30964
30973
  available: this.skills.has(s.id)
@@ -30996,6 +31005,7 @@ var MoltsPayServer = class {
30996
31005
  description: s.description,
30997
31006
  price: s.price,
30998
31007
  currency: s.currency,
31008
+ acceptedCurrencies: getAcceptedCurrencies(s),
30999
31009
  input: s.input,
31000
31010
  output: s.output,
31001
31011
  available: this.skills.has(s.id)
@@ -31062,7 +31072,14 @@ var MoltsPayServer = class {
31062
31072
  if (!validation.valid) {
31063
31073
  return this.sendJson(res, 402, { error: validation.error });
31064
31074
  }
31065
- const requirements = this.buildPaymentRequirements(skill.config);
31075
+ const paymentToken = this.detectPaymentToken(payment);
31076
+ if (paymentToken && !this.isTokenAccepted(skill.config, paymentToken)) {
31077
+ const accepted = getAcceptedCurrencies(skill.config);
31078
+ return this.sendJson(res, 402, {
31079
+ error: `Token ${paymentToken} not accepted. Accepted: ${accepted.join(", ")}`
31080
+ });
31081
+ }
31082
+ const requirements = this.buildPaymentRequirements(skill.config, paymentToken);
31066
31083
  console.log(`[MoltsPay] Verifying payment...`);
31067
31084
  const verifyResult = await this.registry.verify(payment, requirements);
31068
31085
  if (!verifyResult.valid) {
@@ -31117,12 +31134,15 @@ var MoltsPayServer = class {
31117
31134
  }
31118
31135
  /**
31119
31136
  * Return 402 with x402 payment requirements (v2 format)
31137
+ * Includes requirements for all accepted currencies
31120
31138
  */
31121
31139
  sendPaymentRequired(config, res) {
31122
- const requirements = this.buildPaymentRequirements(config);
31140
+ const acceptedTokens = getAcceptedCurrencies(config);
31141
+ const accepts = acceptedTokens.map((token) => this.buildPaymentRequirements(config, token));
31123
31142
  const paymentRequired = {
31124
31143
  x402Version: X402_VERSION2,
31125
- accepts: [requirements],
31144
+ accepts,
31145
+ acceptedCurrencies: acceptedTokens,
31126
31146
  resource: {
31127
31147
  url: `/execute?service=${config.id}`,
31128
31148
  description: `${config.name} - $${config.price} ${config.currency}`,
@@ -31137,6 +31157,7 @@ var MoltsPayServer = class {
31137
31157
  res.end(JSON.stringify({
31138
31158
  error: "Payment required",
31139
31159
  message: `Service requires $${config.price} ${config.currency}`,
31160
+ acceptedCurrencies: acceptedTokens,
31140
31161
  x402: paymentRequired
31141
31162
  }, null, 2));
31142
31163
  }
@@ -31159,20 +31180,47 @@ var MoltsPayServer = class {
31159
31180
  }
31160
31181
  /**
31161
31182
  * Build payment requirements for facilitator
31183
+ * Returns requirements for the primary currency (USDC by default)
31184
+ * Server accepts any of the acceptedCurrencies
31162
31185
  */
31163
- buildPaymentRequirements(config) {
31186
+ buildPaymentRequirements(config, token) {
31164
31187
  const amountInUnits = Math.floor(config.price * 1e6).toString();
31165
- const usdcAddress = USDC_ADDRESSES[this.networkId];
31188
+ const acceptedTokens = getAcceptedCurrencies(config);
31189
+ const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
31190
+ const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
31191
+ const tokenAddress = tokenAddresses[selectedToken];
31192
+ const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
31166
31193
  return {
31167
31194
  scheme: "exact",
31168
31195
  network: this.networkId,
31169
- asset: usdcAddress,
31196
+ asset: tokenAddress,
31170
31197
  amount: amountInUnits,
31171
31198
  payTo: this.manifest.provider.wallet,
31172
31199
  maxTimeoutSeconds: 300,
31173
- extra: USDC_DOMAIN
31200
+ extra: tokenDomain
31174
31201
  };
31175
31202
  }
31203
+ /**
31204
+ * Detect which token is being used in the payment
31205
+ */
31206
+ detectPaymentToken(payment) {
31207
+ const asset = payment.accepted?.asset || payment.payload?.asset;
31208
+ if (!asset) return void 0;
31209
+ const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
31210
+ for (const [symbol, address] of Object.entries(tokenAddresses)) {
31211
+ if (address.toLowerCase() === asset.toLowerCase()) {
31212
+ return symbol;
31213
+ }
31214
+ }
31215
+ return void 0;
31216
+ }
31217
+ /**
31218
+ * Check if payment token is accepted for service
31219
+ */
31220
+ isTokenAccepted(config, token) {
31221
+ const accepted = getAcceptedCurrencies(config);
31222
+ return accepted.includes(token);
31223
+ }
31176
31224
  async readBody(req) {
31177
31225
  return new Promise((resolve, reject) => {
31178
31226
  let body = "";
@@ -31372,18 +31420,22 @@ var MoltsPayServer = class {
31372
31420
  /**
31373
31421
  * Build payment requirements for proxy endpoint (uses provided wallet)
31374
31422
  */
31375
- buildProxyPaymentRequirements(config, wallet) {
31423
+ buildProxyPaymentRequirements(config, wallet, token) {
31376
31424
  const amountInUnits = Math.floor(config.price * 1e6).toString();
31377
- const usdcAddress = USDC_ADDRESSES[this.networkId];
31425
+ const acceptedTokens = getAcceptedCurrencies(config);
31426
+ const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
31427
+ const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
31428
+ const tokenAddress = tokenAddresses[selectedToken];
31429
+ const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
31378
31430
  return {
31379
31431
  scheme: "exact",
31380
31432
  network: this.networkId,
31381
- asset: usdcAddress,
31433
+ asset: tokenAddress,
31382
31434
  amount: amountInUnits,
31383
31435
  payTo: wallet,
31384
31436
  // Use provided wallet, not manifest
31385
31437
  maxTimeoutSeconds: 300,
31386
- extra: USDC_DOMAIN
31438
+ extra: tokenDomain
31387
31439
  };
31388
31440
  }
31389
31441
  /**
@@ -31429,7 +31481,20 @@ var CHAINS = {
31429
31481
  name: "Base",
31430
31482
  chainId: 8453,
31431
31483
  rpc: "https://mainnet.base.org",
31484
+ tokens: {
31485
+ USDC: {
31486
+ address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
31487
+ decimals: 6,
31488
+ symbol: "USDC"
31489
+ },
31490
+ USDT: {
31491
+ address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
31492
+ decimals: 6,
31493
+ symbol: "USDT"
31494
+ }
31495
+ },
31432
31496
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
31497
+ // deprecated, for backward compat
31433
31498
  explorer: "https://basescan.org/address/",
31434
31499
  explorerTx: "https://basescan.org/tx/",
31435
31500
  avgBlockTime: 2
@@ -31438,6 +31503,18 @@ var CHAINS = {
31438
31503
  name: "Polygon",
31439
31504
  chainId: 137,
31440
31505
  rpc: "https://polygon-rpc.com",
31506
+ tokens: {
31507
+ USDC: {
31508
+ address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
31509
+ decimals: 6,
31510
+ symbol: "USDC"
31511
+ },
31512
+ USDT: {
31513
+ address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
31514
+ decimals: 6,
31515
+ symbol: "USDT"
31516
+ }
31517
+ },
31441
31518
  usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
31442
31519
  explorer: "https://polygonscan.com/address/",
31443
31520
  explorerTx: "https://polygonscan.com/tx/",
@@ -31447,6 +31524,18 @@ var CHAINS = {
31447
31524
  name: "Ethereum",
31448
31525
  chainId: 1,
31449
31526
  rpc: "https://eth.llamarpc.com",
31527
+ tokens: {
31528
+ USDC: {
31529
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
31530
+ decimals: 6,
31531
+ symbol: "USDC"
31532
+ },
31533
+ USDT: {
31534
+ address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
31535
+ decimals: 6,
31536
+ symbol: "USDT"
31537
+ }
31538
+ },
31450
31539
  usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
31451
31540
  explorer: "https://etherscan.io/address/",
31452
31541
  explorerTx: "https://etherscan.io/tx/",
@@ -31457,6 +31546,19 @@ var CHAINS = {
31457
31546
  name: "Base Sepolia",
31458
31547
  chainId: 84532,
31459
31548
  rpc: "https://sepolia.base.org",
31549
+ tokens: {
31550
+ USDC: {
31551
+ address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31552
+ decimals: 6,
31553
+ symbol: "USDC"
31554
+ },
31555
+ USDT: {
31556
+ address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31557
+ // Same as USDC on testnet (no official USDT)
31558
+ decimals: 6,
31559
+ symbol: "USDT"
31560
+ }
31561
+ },
31460
31562
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31461
31563
  explorer: "https://sepolia.basescan.org/address/",
31462
31564
  explorerTx: "https://sepolia.basescan.org/tx/",
@@ -31466,6 +31568,19 @@ var CHAINS = {
31466
31568
  name: "Sepolia",
31467
31569
  chainId: 11155111,
31468
31570
  rpc: "https://rpc.sepolia.org",
31571
+ tokens: {
31572
+ USDC: {
31573
+ address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31574
+ decimals: 6,
31575
+ symbol: "USDC"
31576
+ },
31577
+ USDT: {
31578
+ address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31579
+ // Same as USDC on testnet
31580
+ decimals: 6,
31581
+ symbol: "USDT"
31582
+ }
31583
+ },
31469
31584
  usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31470
31585
  explorer: "https://sepolia.etherscan.io/address/",
31471
31586
  explorerTx: "https://sepolia.etherscan.io/tx/",
@@ -31574,8 +31689,13 @@ var MoltsPayClient = class {
31574
31689
  *
31575
31690
  * This is GASLESS for the client - server pays gas to claim payment.
31576
31691
  * This is PAY-FOR-SUCCESS - payment only claimed if service succeeds.
31692
+ *
31693
+ * @param serverUrl - Server URL
31694
+ * @param service - Service ID
31695
+ * @param params - Service parameters
31696
+ * @param options - Payment options (token selection)
31577
31697
  */
31578
- async pay(serverUrl, service, params) {
31698
+ async pay(serverUrl, service, params, options = {}) {
31579
31699
  if (!this.wallet || !this.walletData) {
31580
31700
  throw new Error("Client not initialized. Run: npx moltspay init");
31581
31701
  }
@@ -31622,12 +31742,35 @@ var MoltsPayClient = class {
31622
31742
  }
31623
31743
  const amount = Number(amountRaw) / 1e6;
31624
31744
  this.checkLimits(amount);
31625
- console.log(`[MoltsPay] Signing payment: $${amount} USDC (gasless)`);
31745
+ let token = options.token || "USDC";
31746
+ if (options.autoSelect) {
31747
+ const balances = await this.getBalance();
31748
+ if (balances.usdc >= amount) {
31749
+ token = "USDC";
31750
+ } else if (balances.usdt >= amount) {
31751
+ token = "USDT";
31752
+ } else {
31753
+ throw new Error(`Insufficient balance: need $${amount}, have ${balances.usdc} USDC / ${balances.usdt} USDT`);
31754
+ }
31755
+ }
31756
+ if (token === "USDT") {
31757
+ const balances = await this.getBalance();
31758
+ if (balances.native < 1e-4) {
31759
+ throw new Error(
31760
+ `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).`
31761
+ );
31762
+ }
31763
+ console.log(`[MoltsPay] \u26A0\uFE0F USDT requires gas (~$0.01). Proceeding with payment...`);
31764
+ } else {
31765
+ console.log(`[MoltsPay] Signing payment: $${amount} ${token} (gasless)`);
31766
+ }
31626
31767
  const payTo = req.payTo || req.resource;
31627
31768
  if (!payTo) {
31628
31769
  throw new Error("Missing payTo address in payment requirements");
31629
31770
  }
31630
- const authorization = await this.signEIP3009(payTo, amount, chain2);
31771
+ const authorization = await this.signEIP3009(payTo, amount, chain2, token);
31772
+ const tokenConfig = chain2.tokens[token];
31773
+ const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31631
31774
  const payload = {
31632
31775
  x402Version: X402_VERSION3,
31633
31776
  payload: authorization,
@@ -31635,11 +31778,11 @@ var MoltsPayClient = class {
31635
31778
  accepted: {
31636
31779
  scheme: "exact",
31637
31780
  network,
31638
- asset: req.asset || chain2.usdc,
31781
+ asset: tokenConfig.address,
31639
31782
  amount: amountRaw,
31640
31783
  payTo,
31641
31784
  maxTimeoutSeconds: req.maxTimeoutSeconds || 300,
31642
- extra: req.extra || { name: "USD Coin", version: "2" }
31785
+ extra: req.extra || { name: tokenName, version: "2" }
31643
31786
  }
31644
31787
  };
31645
31788
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
@@ -31663,12 +31806,14 @@ var MoltsPayClient = class {
31663
31806
  /**
31664
31807
  * Sign EIP-3009 transferWithAuthorization (GASLESS)
31665
31808
  * This only signs - no on-chain transaction, no gas needed.
31809
+ * Supports both USDC and USDT.
31666
31810
  */
31667
- async signEIP3009(to, amount, chain2) {
31811
+ async signEIP3009(to, amount, chain2, token = "USDC") {
31668
31812
  const validAfter = 0;
31669
31813
  const validBefore = Math.floor(Date.now() / 1e3) + 3600;
31670
31814
  const nonce = ethers.hexlify(ethers.randomBytes(32));
31671
- const value = BigInt(Math.floor(amount * 1e6)).toString();
31815
+ const tokenConfig = chain2.tokens[token];
31816
+ const value = BigInt(Math.floor(amount * 10 ** tokenConfig.decimals)).toString();
31672
31817
  const authorization = {
31673
31818
  from: this.wallet.address,
31674
31819
  to,
@@ -31677,11 +31822,12 @@ var MoltsPayClient = class {
31677
31822
  validBefore: validBefore.toString(),
31678
31823
  nonce
31679
31824
  };
31825
+ const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31680
31826
  const domain = {
31681
- name: "USD Coin",
31827
+ name: tokenName,
31682
31828
  version: "2",
31683
31829
  chainId: chain2.chainId,
31684
- verifyingContract: chain2.usdc
31830
+ verifyingContract: tokenConfig.address
31685
31831
  };
31686
31832
  const types = {
31687
31833
  TransferWithAuthorization: [
@@ -31816,7 +31962,7 @@ var MoltsPayClient = class {
31816
31962
  return { address: wallet.address, configDir };
31817
31963
  }
31818
31964
  /**
31819
- * Get wallet balance
31965
+ * Get wallet balance (USDC, USDT, and native token)
31820
31966
  */
31821
31967
  async getBalance() {
31822
31968
  if (!this.wallet) {
@@ -31829,12 +31975,15 @@ var MoltsPayClient = class {
31829
31975
  throw new Error(`Unknown chain: ${this.config.chain}`);
31830
31976
  }
31831
31977
  const provider = new ethers.JsonRpcProvider(chain2.rpc);
31832
- const nativeBalance = await provider.getBalance(this.wallet.address);
31833
- const usdcAbi = ["function balanceOf(address) view returns (uint256)"];
31834
- const usdc = new ethers.Contract(chain2.usdc, usdcAbi, provider);
31835
- const usdcBalance = await usdc.balanceOf(this.wallet.address);
31978
+ const tokenAbi = ["function balanceOf(address) view returns (uint256)"];
31979
+ const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([
31980
+ provider.getBalance(this.wallet.address),
31981
+ new ethers.Contract(chain2.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),
31982
+ new ethers.Contract(chain2.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address)
31983
+ ]);
31836
31984
  return {
31837
- usdc: parseFloat(ethers.formatUnits(usdcBalance, 6)),
31985
+ usdc: parseFloat(ethers.formatUnits(usdcBalance, chain2.tokens.USDC.decimals)),
31986
+ usdt: parseFloat(ethers.formatUnits(usdtBalance, chain2.tokens.USDT.decimals)),
31838
31987
  native: parseFloat(ethers.formatEther(nativeBalance))
31839
31988
  };
31840
31989
  }
@@ -31970,7 +32119,7 @@ init_esm_shims();
31970
32119
  import { ethers as ethers4 } from "ethers";
31971
32120
  var TRANSFER_EVENT_TOPIC = ethers4.id("Transfer(address,address,uint256)");
31972
32121
  async function verifyPayment(params) {
31973
- const { txHash, expectedAmount, expectedTo } = params;
32122
+ const { txHash, expectedAmount, expectedTo, expectedToken } = params;
31974
32123
  let chain2;
31975
32124
  try {
31976
32125
  if (typeof params.chain === "number") {
@@ -31993,12 +32142,20 @@ async function verifyPayment(params) {
31993
32142
  if (receipt.status !== 1) {
31994
32143
  return { verified: false, error: "Transaction failed" };
31995
32144
  }
31996
- const usdcAddress = chain2.usdc?.toLowerCase();
31997
- if (!usdcAddress) {
31998
- return { verified: false, error: `Chain ${chain2.name} USDC address not configured` };
32145
+ const tokenAddresses = {};
32146
+ if (!expectedToken || expectedToken === "USDC") {
32147
+ tokenAddresses[chain2.tokens.USDC.address.toLowerCase()] = "USDC";
32148
+ }
32149
+ if (!expectedToken || expectedToken === "USDT") {
32150
+ tokenAddresses[chain2.tokens.USDT.address.toLowerCase()] = "USDT";
32151
+ }
32152
+ if (Object.keys(tokenAddresses).length === 0) {
32153
+ return { verified: false, error: `No token addresses configured for ${chain2.name}` };
31999
32154
  }
32000
32155
  for (const log of receipt.logs) {
32001
- if (log.address.toLowerCase() !== usdcAddress) {
32156
+ const logAddress = log.address.toLowerCase();
32157
+ const detectedToken = tokenAddresses[logAddress];
32158
+ if (!detectedToken) {
32002
32159
  continue;
32003
32160
  }
32004
32161
  if (log.topics.length < 3 || log.topics[0] !== TRANSFER_EVENT_TOPIC) {
@@ -32007,15 +32164,17 @@ async function verifyPayment(params) {
32007
32164
  const from = "0x" + log.topics[1].slice(-40);
32008
32165
  const to = "0x" + log.topics[2].slice(-40);
32009
32166
  const amountRaw = BigInt(log.data);
32010
- const amount = Number(amountRaw) / 1e6;
32167
+ const tokenConfig = chain2.tokens[detectedToken];
32168
+ const amount = Number(amountRaw) / 10 ** tokenConfig.decimals;
32011
32169
  if (expectedTo && to.toLowerCase() !== expectedTo.toLowerCase()) {
32012
32170
  continue;
32013
32171
  }
32014
32172
  if (amount < expectedAmount) {
32015
32173
  return {
32016
32174
  verified: false,
32017
- error: `Insufficient amount: received ${amount} USDC, expected ${expectedAmount} USDC`,
32175
+ error: `Insufficient amount: received ${amount} ${detectedToken}, expected ${expectedAmount}`,
32018
32176
  amount,
32177
+ token: detectedToken,
32019
32178
  from,
32020
32179
  to,
32021
32180
  txHash,
@@ -32025,13 +32184,15 @@ async function verifyPayment(params) {
32025
32184
  return {
32026
32185
  verified: true,
32027
32186
  amount,
32187
+ token: detectedToken,
32028
32188
  from,
32029
32189
  to,
32030
32190
  txHash,
32031
32191
  blockNumber: receipt.blockNumber
32032
32192
  };
32033
32193
  }
32034
- return { verified: false, error: "No USDC transfer found" };
32194
+ const tokenList = expectedToken ? expectedToken : "USDC/USDT";
32195
+ return { verified: false, error: `No ${tokenList} transfer found` };
32035
32196
  } catch (e) {
32036
32197
  return { verified: false, error: e.message || String(e) };
32037
32198
  }