moltspay 0.9.3 → 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 (51) hide show
  1. package/.env.example +7 -0
  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 +234 -41
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/cli/index.mjs +234 -41
  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 +102 -15
  21. package/dist/client/index.js.map +1 -1
  22. package/dist/client/index.mjs +102 -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 +248 -45
  29. package/dist/index.js.map +1 -1
  30. package/dist/index.mjs +248 -45
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/server/index.d.mts +23 -1
  33. package/dist/server/index.d.ts +23 -1
  34. package/dist/server/index.js +126 -22
  35. package/dist/server/index.js.map +1 -1
  36. package/dist/server/index.mjs +126 -22
  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"),
@@ -30965,6 +30973,9 @@ var MoltsPayServer = class {
30965
30973
  if (url.pathname === "/services" && req.method === "GET") {
30966
30974
  return this.handleGetServices(res);
30967
30975
  }
30976
+ if (url.pathname === "/.well-known/agent-services.json" && req.method === "GET") {
30977
+ return this.handleAgentServicesDiscovery(res);
30978
+ }
30968
30979
  if (url.pathname === "/health" && req.method === "GET") {
30969
30980
  return await this.handleHealthCheck(res);
30970
30981
  }
@@ -30988,6 +30999,44 @@ var MoltsPayServer = class {
30988
30999
  this.sendJson(res, 500, { error: err.message || "Internal error" });
30989
31000
  }
30990
31001
  }
31002
+ /**
31003
+ * GET /.well-known/agent-services.json - Standard discovery endpoint
31004
+ */
31005
+ handleAgentServicesDiscovery(res) {
31006
+ const services = this.manifest.services.map((s) => ({
31007
+ id: s.id,
31008
+ name: s.name,
31009
+ description: s.description,
31010
+ price: s.price,
31011
+ currency: s.currency,
31012
+ acceptedCurrencies: getAcceptedCurrencies(s),
31013
+ input: s.input,
31014
+ output: s.output,
31015
+ available: this.skills.has(s.id)
31016
+ }));
31017
+ this.sendJson(res, 200, {
31018
+ version: "1.0",
31019
+ provider: {
31020
+ name: this.manifest.provider.name,
31021
+ description: this.manifest.provider.description,
31022
+ wallet: this.manifest.provider.wallet,
31023
+ chain: this.manifest.provider.chain || "base"
31024
+ },
31025
+ services,
31026
+ endpoints: {
31027
+ services: "/services",
31028
+ execute: "/execute",
31029
+ health: "/health"
31030
+ },
31031
+ payment: {
31032
+ protocol: "x402",
31033
+ version: X402_VERSION2,
31034
+ network: this.networkId,
31035
+ schemes: ["exact"],
31036
+ mainnet: this.useMainnet
31037
+ }
31038
+ });
31039
+ }
30991
31040
  /**
30992
31041
  * GET /services - List available services
30993
31042
  */
@@ -30998,6 +31047,7 @@ var MoltsPayServer = class {
30998
31047
  description: s.description,
30999
31048
  price: s.price,
31000
31049
  currency: s.currency,
31050
+ acceptedCurrencies: getAcceptedCurrencies(s),
31001
31051
  input: s.input,
31002
31052
  output: s.output,
31003
31053
  available: this.skills.has(s.id)
@@ -31064,7 +31114,14 @@ var MoltsPayServer = class {
31064
31114
  if (!validation.valid) {
31065
31115
  return this.sendJson(res, 402, { error: validation.error });
31066
31116
  }
31067
- 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);
31068
31125
  console.log(`[MoltsPay] Verifying payment...`);
31069
31126
  const verifyResult = await this.registry.verify(payment, requirements);
31070
31127
  if (!verifyResult.valid) {
@@ -31074,10 +31131,16 @@ var MoltsPayServer = class {
31074
31131
  });
31075
31132
  }
31076
31133
  console.log(`[MoltsPay] Verified by ${verifyResult.facilitator}`);
31077
- console.log(`[MoltsPay] Executing skill: ${service}`);
31134
+ const timeoutSeconds = parseInt(process.env.SKILL_TIMEOUT_SECONDS || "1200");
31135
+ console.log(`[MoltsPay] Executing skill: ${service} (timeout: ${timeoutSeconds}s)`);
31078
31136
  let result;
31079
31137
  try {
31080
- result = await skill.handler(params || {});
31138
+ result = await Promise.race([
31139
+ skill.handler(params || {}),
31140
+ new Promise(
31141
+ (_, reject) => setTimeout(() => reject(new Error(`Skill timeout after ${timeoutSeconds}s`)), timeoutSeconds * 1e3)
31142
+ )
31143
+ ]);
31081
31144
  } catch (err) {
31082
31145
  console.error("[MoltsPay] Skill execution failed:", err.message);
31083
31146
  return this.sendJson(res, 500, {
@@ -31113,12 +31176,15 @@ var MoltsPayServer = class {
31113
31176
  }
31114
31177
  /**
31115
31178
  * Return 402 with x402 payment requirements (v2 format)
31179
+ * Includes requirements for all accepted currencies
31116
31180
  */
31117
31181
  sendPaymentRequired(config, res) {
31118
- const requirements = this.buildPaymentRequirements(config);
31182
+ const acceptedTokens = getAcceptedCurrencies(config);
31183
+ const accepts = acceptedTokens.map((token) => this.buildPaymentRequirements(config, token));
31119
31184
  const paymentRequired = {
31120
31185
  x402Version: X402_VERSION2,
31121
- accepts: [requirements],
31186
+ accepts,
31187
+ acceptedCurrencies: acceptedTokens,
31122
31188
  resource: {
31123
31189
  url: `/execute?service=${config.id}`,
31124
31190
  description: `${config.name} - $${config.price} ${config.currency}`,
@@ -31133,6 +31199,7 @@ var MoltsPayServer = class {
31133
31199
  res.end(JSON.stringify({
31134
31200
  error: "Payment required",
31135
31201
  message: `Service requires $${config.price} ${config.currency}`,
31202
+ acceptedCurrencies: acceptedTokens,
31136
31203
  x402: paymentRequired
31137
31204
  }, null, 2));
31138
31205
  }
@@ -31155,20 +31222,47 @@ var MoltsPayServer = class {
31155
31222
  }
31156
31223
  /**
31157
31224
  * Build payment requirements for facilitator
31225
+ * Returns requirements for the primary currency (USDC by default)
31226
+ * Server accepts any of the acceptedCurrencies
31158
31227
  */
31159
- buildPaymentRequirements(config) {
31228
+ buildPaymentRequirements(config, token) {
31160
31229
  const amountInUnits = Math.floor(config.price * 1e6).toString();
31161
- 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;
31162
31235
  return {
31163
31236
  scheme: "exact",
31164
31237
  network: this.networkId,
31165
- asset: usdcAddress,
31238
+ asset: tokenAddress,
31166
31239
  amount: amountInUnits,
31167
31240
  payTo: this.manifest.provider.wallet,
31168
31241
  maxTimeoutSeconds: 300,
31169
- extra: USDC_DOMAIN
31242
+ extra: tokenDomain
31170
31243
  };
31171
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
+ }
31172
31266
  async readBody(req) {
31173
31267
  return new Promise((resolve, reject) => {
31174
31268
  let body = "";
@@ -31286,9 +31380,15 @@ var MoltsPayServer = class {
31286
31380
  error: `Service not found: ${service}`
31287
31381
  });
31288
31382
  }
31383
+ const timeoutSeconds = parseInt(process.env.SKILL_TIMEOUT_SECONDS || "1200");
31289
31384
  let result;
31290
31385
  try {
31291
- result = await skill.handler(params || {});
31386
+ result = await Promise.race([
31387
+ skill.handler(params || {}),
31388
+ new Promise(
31389
+ (_, reject) => setTimeout(() => reject(new Error(`Skill timeout after ${timeoutSeconds}s`)), timeoutSeconds * 1e3)
31390
+ )
31391
+ ]);
31292
31392
  console.log(`[MoltsPay] /proxy: Skill succeeded, now settling payment...`);
31293
31393
  } catch (err) {
31294
31394
  console.error(`[MoltsPay] /proxy: Skill failed: ${err.message} - NOT settling`);
@@ -31362,18 +31462,22 @@ var MoltsPayServer = class {
31362
31462
  /**
31363
31463
  * Build payment requirements for proxy endpoint (uses provided wallet)
31364
31464
  */
31365
- buildProxyPaymentRequirements(config, wallet) {
31465
+ buildProxyPaymentRequirements(config, wallet, token) {
31366
31466
  const amountInUnits = Math.floor(config.price * 1e6).toString();
31367
- 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;
31368
31472
  return {
31369
31473
  scheme: "exact",
31370
31474
  network: this.networkId,
31371
- asset: usdcAddress,
31475
+ asset: tokenAddress,
31372
31476
  amount: amountInUnits,
31373
31477
  payTo: wallet,
31374
31478
  // Use provided wallet, not manifest
31375
31479
  maxTimeoutSeconds: 300,
31376
- extra: USDC_DOMAIN
31480
+ extra: tokenDomain
31377
31481
  };
31378
31482
  }
31379
31483
  /**
@@ -31419,7 +31523,20 @@ var CHAINS = {
31419
31523
  name: "Base",
31420
31524
  chainId: 8453,
31421
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
+ },
31422
31538
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
31539
+ // deprecated, for backward compat
31423
31540
  explorer: "https://basescan.org/address/",
31424
31541
  explorerTx: "https://basescan.org/tx/",
31425
31542
  avgBlockTime: 2
@@ -31428,6 +31545,18 @@ var CHAINS = {
31428
31545
  name: "Polygon",
31429
31546
  chainId: 137,
31430
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
+ },
31431
31560
  usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
31432
31561
  explorer: "https://polygonscan.com/address/",
31433
31562
  explorerTx: "https://polygonscan.com/tx/",
@@ -31437,6 +31566,18 @@ var CHAINS = {
31437
31566
  name: "Ethereum",
31438
31567
  chainId: 1,
31439
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
+ },
31440
31581
  usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
31441
31582
  explorer: "https://etherscan.io/address/",
31442
31583
  explorerTx: "https://etherscan.io/tx/",
@@ -31447,6 +31588,19 @@ var CHAINS = {
31447
31588
  name: "Base Sepolia",
31448
31589
  chainId: 84532,
31449
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
+ },
31450
31604
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31451
31605
  explorer: "https://sepolia.basescan.org/address/",
31452
31606
  explorerTx: "https://sepolia.basescan.org/tx/",
@@ -31456,6 +31610,19 @@ var CHAINS = {
31456
31610
  name: "Sepolia",
31457
31611
  chainId: 11155111,
31458
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
+ },
31459
31626
  usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31460
31627
  explorer: "https://sepolia.etherscan.io/address/",
31461
31628
  explorerTx: "https://sepolia.etherscan.io/tx/",
@@ -31564,8 +31731,13 @@ var MoltsPayClient = class {
31564
31731
  *
31565
31732
  * This is GASLESS for the client - server pays gas to claim payment.
31566
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)
31567
31739
  */
31568
- async pay(serverUrl, service, params) {
31740
+ async pay(serverUrl, service, params, options = {}) {
31569
31741
  if (!this.wallet || !this.walletData) {
31570
31742
  throw new Error("Client not initialized. Run: npx moltspay init");
31571
31743
  }
@@ -31612,12 +31784,25 @@ var MoltsPayClient = class {
31612
31784
  }
31613
31785
  const amount = Number(amountRaw) / 1e6;
31614
31786
  this.checkLimits(amount);
31615
- 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)`);
31616
31799
  const payTo = req.payTo || req.resource;
31617
31800
  if (!payTo) {
31618
31801
  throw new Error("Missing payTo address in payment requirements");
31619
31802
  }
31620
- 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";
31621
31806
  const payload = {
31622
31807
  x402Version: X402_VERSION3,
31623
31808
  payload: authorization,
@@ -31625,11 +31810,11 @@ var MoltsPayClient = class {
31625
31810
  accepted: {
31626
31811
  scheme: "exact",
31627
31812
  network,
31628
- asset: req.asset || chain2.usdc,
31813
+ asset: tokenConfig.address,
31629
31814
  amount: amountRaw,
31630
31815
  payTo,
31631
31816
  maxTimeoutSeconds: req.maxTimeoutSeconds || 300,
31632
- extra: req.extra || { name: "USD Coin", version: "2" }
31817
+ extra: req.extra || { name: tokenName, version: "2" }
31633
31818
  }
31634
31819
  };
31635
31820
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
@@ -31653,12 +31838,14 @@ var MoltsPayClient = class {
31653
31838
  /**
31654
31839
  * Sign EIP-3009 transferWithAuthorization (GASLESS)
31655
31840
  * This only signs - no on-chain transaction, no gas needed.
31841
+ * Supports both USDC and USDT.
31656
31842
  */
31657
- async signEIP3009(to, amount, chain2) {
31843
+ async signEIP3009(to, amount, chain2, token = "USDC") {
31658
31844
  const validAfter = 0;
31659
31845
  const validBefore = Math.floor(Date.now() / 1e3) + 3600;
31660
31846
  const nonce = import_ethers.ethers.hexlify(import_ethers.ethers.randomBytes(32));
31661
- 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();
31662
31849
  const authorization = {
31663
31850
  from: this.wallet.address,
31664
31851
  to,
@@ -31667,11 +31854,12 @@ var MoltsPayClient = class {
31667
31854
  validBefore: validBefore.toString(),
31668
31855
  nonce
31669
31856
  };
31857
+ const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31670
31858
  const domain = {
31671
- name: "USD Coin",
31859
+ name: tokenName,
31672
31860
  version: "2",
31673
31861
  chainId: chain2.chainId,
31674
- verifyingContract: chain2.usdc
31862
+ verifyingContract: tokenConfig.address
31675
31863
  };
31676
31864
  const types = {
31677
31865
  TransferWithAuthorization: [
@@ -31806,7 +31994,7 @@ var MoltsPayClient = class {
31806
31994
  return { address: wallet.address, configDir };
31807
31995
  }
31808
31996
  /**
31809
- * Get wallet balance
31997
+ * Get wallet balance (USDC, USDT, and native token)
31810
31998
  */
31811
31999
  async getBalance() {
31812
32000
  if (!this.wallet) {
@@ -31819,12 +32007,15 @@ var MoltsPayClient = class {
31819
32007
  throw new Error(`Unknown chain: ${this.config.chain}`);
31820
32008
  }
31821
32009
  const provider = new import_ethers.ethers.JsonRpcProvider(chain2.rpc);
31822
- const nativeBalance = await provider.getBalance(this.wallet.address);
31823
- const usdcAbi = ["function balanceOf(address) view returns (uint256)"];
31824
- const usdc = new import_ethers.ethers.Contract(chain2.usdc, usdcAbi, provider);
31825
- 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
+ ]);
31826
32016
  return {
31827
- 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)),
31828
32019
  native: parseFloat(import_ethers.ethers.formatEther(nativeBalance))
31829
32020
  };
31830
32021
  }
@@ -31960,7 +32151,7 @@ init_cjs_shims();
31960
32151
  var import_ethers4 = require("ethers");
31961
32152
  var TRANSFER_EVENT_TOPIC = import_ethers4.ethers.id("Transfer(address,address,uint256)");
31962
32153
  async function verifyPayment(params) {
31963
- const { txHash, expectedAmount, expectedTo } = params;
32154
+ const { txHash, expectedAmount, expectedTo, expectedToken } = params;
31964
32155
  let chain2;
31965
32156
  try {
31966
32157
  if (typeof params.chain === "number") {
@@ -31983,12 +32174,20 @@ async function verifyPayment(params) {
31983
32174
  if (receipt.status !== 1) {
31984
32175
  return { verified: false, error: "Transaction failed" };
31985
32176
  }
31986
- const usdcAddress = chain2.usdc?.toLowerCase();
31987
- if (!usdcAddress) {
31988
- 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}` };
31989
32186
  }
31990
32187
  for (const log of receipt.logs) {
31991
- if (log.address.toLowerCase() !== usdcAddress) {
32188
+ const logAddress = log.address.toLowerCase();
32189
+ const detectedToken = tokenAddresses[logAddress];
32190
+ if (!detectedToken) {
31992
32191
  continue;
31993
32192
  }
31994
32193
  if (log.topics.length < 3 || log.topics[0] !== TRANSFER_EVENT_TOPIC) {
@@ -31997,15 +32196,17 @@ async function verifyPayment(params) {
31997
32196
  const from = "0x" + log.topics[1].slice(-40);
31998
32197
  const to = "0x" + log.topics[2].slice(-40);
31999
32198
  const amountRaw = BigInt(log.data);
32000
- const amount = Number(amountRaw) / 1e6;
32199
+ const tokenConfig = chain2.tokens[detectedToken];
32200
+ const amount = Number(amountRaw) / 10 ** tokenConfig.decimals;
32001
32201
  if (expectedTo && to.toLowerCase() !== expectedTo.toLowerCase()) {
32002
32202
  continue;
32003
32203
  }
32004
32204
  if (amount < expectedAmount) {
32005
32205
  return {
32006
32206
  verified: false,
32007
- error: `Insufficient amount: received ${amount} USDC, expected ${expectedAmount} USDC`,
32207
+ error: `Insufficient amount: received ${amount} ${detectedToken}, expected ${expectedAmount}`,
32008
32208
  amount,
32209
+ token: detectedToken,
32009
32210
  from,
32010
32211
  to,
32011
32212
  txHash,
@@ -32015,13 +32216,15 @@ async function verifyPayment(params) {
32015
32216
  return {
32016
32217
  verified: true,
32017
32218
  amount,
32219
+ token: detectedToken,
32018
32220
  from,
32019
32221
  to,
32020
32222
  txHash,
32021
32223
  blockNumber: receipt.blockNumber
32022
32224
  };
32023
32225
  }
32024
- return { verified: false, error: "No USDC transfer found" };
32226
+ const tokenList = expectedToken ? expectedToken : "USDC/USDT";
32227
+ return { verified: false, error: `No ${tokenList} transfer found` };
32025
32228
  } catch (e) {
32026
32229
  return { verified: false, error: e.message || String(e) };
32027
32230
  }