moltspay 1.2.0 → 1.2.1

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 (54) hide show
  1. package/README.md +78 -9
  2. package/dist/cdp/index.d.mts +1 -1
  3. package/dist/cdp/index.d.ts +1 -1
  4. package/dist/cdp/index.js +16 -49
  5. package/dist/cdp/index.js.map +1 -1
  6. package/dist/cdp/index.mjs +16 -49
  7. package/dist/cdp/index.mjs.map +1 -1
  8. package/dist/chains/index.d.mts +1 -1
  9. package/dist/chains/index.d.ts +1 -1
  10. package/dist/chains/index.js +16 -49
  11. package/dist/chains/index.js.map +1 -1
  12. package/dist/chains/index.mjs +16 -49
  13. package/dist/chains/index.mjs.map +1 -1
  14. package/dist/cli/index.js +180 -111
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/cli/index.mjs +180 -111
  17. package/dist/cli/index.mjs.map +1 -1
  18. package/dist/client/index.d.mts +3 -3
  19. package/dist/client/index.d.ts +3 -3
  20. package/dist/client/index.js +32 -58
  21. package/dist/client/index.js.map +1 -1
  22. package/dist/client/index.mjs +32 -58
  23. package/dist/client/index.mjs.map +1 -1
  24. package/dist/facilitators/index.d.mts +12 -6
  25. package/dist/facilitators/index.d.ts +12 -6
  26. package/dist/facilitators/index.js +39 -33
  27. package/dist/facilitators/index.js.map +1 -1
  28. package/dist/facilitators/index.mjs +39 -33
  29. package/dist/facilitators/index.mjs.map +1 -1
  30. package/dist/{index-B3v8IWjM.d.mts → index-DgJPZMBG.d.mts} +2 -1
  31. package/dist/{index-B3v8IWjM.d.ts → index-DgJPZMBG.d.ts} +2 -1
  32. package/dist/index.d.mts +1 -1
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.js +102 -101
  35. package/dist/index.js.map +1 -1
  36. package/dist/index.mjs +102 -101
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/server/index.js +70 -43
  39. package/dist/server/index.js.map +1 -1
  40. package/dist/server/index.mjs +70 -43
  41. package/dist/server/index.mjs.map +1 -1
  42. package/dist/verify/index.d.mts +1 -1
  43. package/dist/verify/index.d.ts +1 -1
  44. package/dist/verify/index.js +16 -49
  45. package/dist/verify/index.js.map +1 -1
  46. package/dist/verify/index.mjs +16 -49
  47. package/dist/verify/index.mjs.map +1 -1
  48. package/dist/wallet/index.d.mts +1 -1
  49. package/dist/wallet/index.d.ts +1 -1
  50. package/dist/wallet/index.js +16 -49
  51. package/dist/wallet/index.js.map +1 -1
  52. package/dist/wallet/index.mjs +16 -49
  53. package/dist/wallet/index.mjs.map +1 -1
  54. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -30350,8 +30350,8 @@ init_esm_shims();
30350
30350
  import { readFileSync, existsSync } from "fs";
30351
30351
  import * as path2 from "path";
30352
30352
  var X402_VERSION = 2;
30353
- var CDP_MAINNET_URL = "https://api.cdp.coinbase.com/platform/v2/x402";
30354
- var CDP_TESTNET_URL = "https://www.x402.org/facilitator";
30353
+ var CDP_URL = "https://api.cdp.coinbase.com/platform/v2/x402";
30354
+ var TESTNET_CHAIN_IDS = [84532];
30355
30355
  function loadEnvFile() {
30356
30356
  const envPaths = [
30357
30357
  path2.join(process.cwd(), ".env"),
@@ -30386,31 +30386,33 @@ var CDPFacilitator = class extends BaseFacilitator {
30386
30386
  displayName = "Coinbase CDP";
30387
30387
  supportedNetworks;
30388
30388
  endpoint;
30389
- useMainnet;
30390
30389
  apiKeyId;
30391
30390
  apiKeySecret;
30392
30391
  constructor(config = {}) {
30393
30392
  super();
30394
30393
  loadEnvFile();
30395
- this.useMainnet = config.useMainnet ?? process.env.USE_MAINNET?.toLowerCase() === "true";
30396
30394
  this.apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;
30397
30395
  this.apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;
30398
- this.endpoint = this.useMainnet ? CDP_MAINNET_URL : CDP_TESTNET_URL;
30399
- this.supportedNetworks = this.useMainnet ? ["eip155:8453", "eip155:137"] : ["eip155:8453", "eip155:84532", "eip155:137"];
30400
- if (this.useMainnet && (!this.apiKeyId || !this.apiKeySecret)) {
30401
- console.warn("[CDPFacilitator] WARNING: Mainnet mode but missing CDP credentials!");
30402
- console.warn("[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET");
30396
+ this.endpoint = CDP_URL;
30397
+ this.supportedNetworks = [
30398
+ "eip155:8453",
30399
+ // Base mainnet
30400
+ "eip155:137",
30401
+ // Polygon mainnet
30402
+ "eip155:84532"
30403
+ // Base Sepolia (testnet)
30404
+ ];
30405
+ if (!this.apiKeyId || !this.apiKeySecret) {
30406
+ console.warn("[CDPFacilitator] WARNING: Missing CDP credentials!");
30407
+ console.warn("[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET in ~/.moltspay/.env");
30403
30408
  }
30404
30409
  }
30405
30410
  /**
30406
30411
  * Get auth headers for CDP API requests
30407
30412
  */
30408
30413
  async getAuthHeaders(method, urlPath, body) {
30409
- if (!this.useMainnet) {
30410
- return {};
30411
- }
30412
30414
  if (!this.apiKeyId || !this.apiKeySecret) {
30413
- throw new Error("CDP credentials required for mainnet");
30415
+ throw new Error("CDP credentials required. Set CDP_API_KEY_ID and CDP_API_KEY_SECRET");
30414
30416
  }
30415
30417
  try {
30416
30418
  const { getAuthHeaders } = await import("@coinbase/cdp-sdk/auth");
@@ -30462,23 +30464,23 @@ var CDPFacilitator = class extends BaseFacilitator {
30462
30464
  paymentPayload,
30463
30465
  paymentRequirements: requirements
30464
30466
  };
30467
+ console.log("[CDP Verify] Payload:", JSON.stringify(paymentPayload, null, 2));
30468
+ const authHeaders = await this.getAuthHeaders(
30469
+ "POST",
30470
+ "/platform/v2/x402/verify",
30471
+ requestBody
30472
+ );
30465
30473
  const headers = {
30466
- "Content-Type": "application/json"
30474
+ "Content-Type": "application/json",
30475
+ ...authHeaders
30467
30476
  };
30468
- if (this.useMainnet) {
30469
- const authHeaders = await this.getAuthHeaders(
30470
- "POST",
30471
- "/platform/v2/x402/verify",
30472
- requestBody
30473
- );
30474
- Object.assign(headers, authHeaders);
30475
- }
30476
30477
  const response = await fetch(`${this.endpoint}/verify`, {
30477
30478
  method: "POST",
30478
30479
  headers,
30479
30480
  body: JSON.stringify(requestBody)
30480
30481
  });
30481
30482
  const result = await response.json();
30483
+ console.log("[CDP Verify] Response:", response.status, JSON.stringify(result));
30482
30484
  if (!response.ok || !result.isValid) {
30483
30485
  return {
30484
30486
  valid: false,
@@ -30504,17 +30506,15 @@ var CDPFacilitator = class extends BaseFacilitator {
30504
30506
  paymentPayload,
30505
30507
  paymentRequirements: requirements
30506
30508
  };
30509
+ const authHeaders = await this.getAuthHeaders(
30510
+ "POST",
30511
+ "/platform/v2/x402/settle",
30512
+ requestBody
30513
+ );
30507
30514
  const headers = {
30508
- "Content-Type": "application/json"
30515
+ "Content-Type": "application/json",
30516
+ ...authHeaders
30509
30517
  };
30510
- if (this.useMainnet) {
30511
- const authHeaders = await this.getAuthHeaders(
30512
- "POST",
30513
- "/platform/v2/x402/settle",
30514
- requestBody
30515
- );
30516
- Object.assign(headers, authHeaders);
30517
- }
30518
30518
  const response = await fetch(`${this.endpoint}/settle`, {
30519
30519
  method: "POST",
30520
30520
  headers,
@@ -30549,13 +30549,19 @@ var CDPFacilitator = class extends BaseFacilitator {
30549
30549
  freeQuota: 1e3
30550
30550
  };
30551
30551
  }
30552
+ /**
30553
+ * Check if a chain ID is testnet
30554
+ */
30555
+ static isTestnet(chainId) {
30556
+ return TESTNET_CHAIN_IDS.includes(chainId);
30557
+ }
30552
30558
  /**
30553
30559
  * Get configuration summary (for logging)
30554
30560
  */
30555
30561
  getConfigSummary() {
30556
- const mode = this.useMainnet ? "mainnet" : "testnet";
30557
30562
  const hasCredentials = !!(this.apiKeyId && this.apiKeySecret);
30558
- return `CDP Facilitator (${mode}, credentials: ${hasCredentials ? "yes" : "no"})`;
30563
+ const networks = this.supportedNetworks.join(", ");
30564
+ return `CDP Facilitator (networks: ${networks}, credentials: ${hasCredentials ? "yes" : "no"})`;
30559
30565
  }
30560
30566
  };
30561
30567
 
@@ -30823,9 +30829,27 @@ var CHAIN_TO_NETWORK = {
30823
30829
  "polygon": "eip155:137"
30824
30830
  };
30825
30831
  var TOKEN_DOMAINS = {
30826
- USDC: { name: "USD Coin", version: "2" },
30827
- USDT: { name: "Tether USD", version: "2" }
30832
+ // Base mainnet
30833
+ "eip155:8453": {
30834
+ USDC: { name: "USD Coin", version: "2" },
30835
+ USDT: { name: "Tether USD", version: "2" }
30836
+ },
30837
+ // Base Sepolia testnet - USDC uses 'USDC' not 'USD Coin'
30838
+ "eip155:84532": {
30839
+ USDC: { name: "USDC", version: "2" },
30840
+ USDT: { name: "USDC", version: "2" }
30841
+ // Same contract as USDC on testnet
30842
+ },
30843
+ // Polygon mainnet
30844
+ "eip155:137": {
30845
+ USDC: { name: "USD Coin", version: "2" },
30846
+ USDT: { name: "(PoS) Tether USD", version: "2" }
30847
+ }
30828
30848
  };
30849
+ function getTokenDomain(network, token) {
30850
+ const networkDomains = TOKEN_DOMAINS[network] || TOKEN_DOMAINS["eip155:8453"];
30851
+ return networkDomains[token] || { name: "USD Coin", version: "2" };
30852
+ }
30829
30853
  function getAcceptedCurrencies(config) {
30830
30854
  return config.acceptedCurrencies ?? [config.currency];
30831
30855
  }
@@ -30919,11 +30943,14 @@ var MoltsPayServer = class {
30919
30943
  getProviderChains() {
30920
30944
  const provider = this.manifest.provider;
30921
30945
  if (provider.chains && provider.chains.length > 0) {
30922
- return provider.chains.map((c) => ({
30923
- network: c.network || CHAIN_TO_NETWORK[c.chain] || "eip155:8453",
30924
- wallet: c.wallet || provider.wallet,
30925
- tokens: c.tokens || ["USDC"]
30926
- }));
30946
+ return provider.chains.map((c) => {
30947
+ const chainName = typeof c === "string" ? c : c.chain;
30948
+ return {
30949
+ network: CHAIN_TO_NETWORK[chainName] || "eip155:8453",
30950
+ wallet: (typeof c === "object" ? c.wallet : null) || provider.wallet,
30951
+ tokens: (typeof c === "object" ? c.tokens : null) || ["USDC"]
30952
+ };
30953
+ });
30927
30954
  }
30928
30955
  const chain2 = provider.chain || "base";
30929
30956
  const network = CHAIN_TO_NETWORK[chain2] || this.networkId;
@@ -31133,7 +31160,7 @@ var MoltsPayServer = class {
31133
31160
  const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;
31134
31161
  const paymentWallet = this.getWalletForNetwork(paymentNetwork);
31135
31162
  const requirements = this.buildPaymentRequirements(skill.config, paymentNetwork, paymentWallet, paymentToken);
31136
- console.log(`[MoltsPay] Verifying payment...`);
31163
+ console.log(`[MoltsPay] Verifying payment on ${paymentNetwork}...`);
31137
31164
  const verifyResult = await this.registry.verify(payment, requirements);
31138
31165
  if (!verifyResult.valid) {
31139
31166
  return this.sendJson(res, 402, {
@@ -31259,7 +31286,7 @@ var MoltsPayServer = class {
31259
31286
  const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
31260
31287
  const tokenAddresses = TOKEN_ADDRESSES[selectedNetwork] || {};
31261
31288
  const tokenAddress = tokenAddresses[selectedToken];
31262
- const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
31289
+ const tokenDomain = getTokenDomain(selectedNetwork, selectedToken);
31263
31290
  return {
31264
31291
  scheme: "exact",
31265
31292
  network: selectedNetwork,
@@ -31504,7 +31531,7 @@ var MoltsPayServer = class {
31504
31531
  const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
31505
31532
  const tokenAddresses = TOKEN_ADDRESSES[networkId] || TOKEN_ADDRESSES[this.networkId] || {};
31506
31533
  const tokenAddress = tokenAddresses[selectedToken];
31507
- const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
31534
+ const tokenDomain = getTokenDomain(networkId, selectedToken);
31508
31535
  return {
31509
31536
  scheme: "exact",
31510
31537
  network: networkId,
@@ -31563,12 +31590,15 @@ var CHAINS = {
31563
31590
  USDC: {
31564
31591
  address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
31565
31592
  decimals: 6,
31566
- symbol: "USDC"
31593
+ symbol: "USDC",
31594
+ eip712Name: "USD Coin"
31595
+ // EIP-712 domain name
31567
31596
  },
31568
31597
  USDT: {
31569
31598
  address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
31570
31599
  decimals: 6,
31571
- symbol: "USDT"
31600
+ symbol: "USDT",
31601
+ eip712Name: "Tether USD"
31572
31602
  }
31573
31603
  },
31574
31604
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
@@ -31585,12 +31615,15 @@ var CHAINS = {
31585
31615
  USDC: {
31586
31616
  address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
31587
31617
  decimals: 6,
31588
- symbol: "USDC"
31618
+ symbol: "USDC",
31619
+ eip712Name: "USD Coin"
31589
31620
  },
31590
31621
  USDT: {
31591
31622
  address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
31592
31623
  decimals: 6,
31593
- symbol: "USDT"
31624
+ symbol: "USDT",
31625
+ eip712Name: "(PoS) Tether USD"
31626
+ // Polygon uses this name
31594
31627
  }
31595
31628
  },
31596
31629
  usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
@@ -31598,27 +31631,6 @@ var CHAINS = {
31598
31631
  explorerTx: "https://polygonscan.com/tx/",
31599
31632
  avgBlockTime: 2
31600
31633
  },
31601
- ethereum: {
31602
- name: "Ethereum",
31603
- chainId: 1,
31604
- rpc: "https://eth.llamarpc.com",
31605
- tokens: {
31606
- USDC: {
31607
- address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
31608
- decimals: 6,
31609
- symbol: "USDC"
31610
- },
31611
- USDT: {
31612
- address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
31613
- decimals: 6,
31614
- symbol: "USDT"
31615
- }
31616
- },
31617
- usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
31618
- explorer: "https://etherscan.io/address/",
31619
- explorerTx: "https://etherscan.io/tx/",
31620
- avgBlockTime: 12
31621
- },
31622
31634
  // ============ Testnet ============
31623
31635
  base_sepolia: {
31624
31636
  name: "Base Sepolia",
@@ -31628,41 +31640,23 @@ var CHAINS = {
31628
31640
  USDC: {
31629
31641
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31630
31642
  decimals: 6,
31631
- symbol: "USDC"
31643
+ symbol: "USDC",
31644
+ eip712Name: "USDC"
31645
+ // Testnet USDC uses 'USDC' not 'USD Coin'
31632
31646
  },
31633
31647
  USDT: {
31634
31648
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31635
31649
  // Same as USDC on testnet (no official USDT)
31636
31650
  decimals: 6,
31637
- symbol: "USDT"
31651
+ symbol: "USDT",
31652
+ eip712Name: "USDC"
31653
+ // Uses same contract as USDC
31638
31654
  }
31639
31655
  },
31640
31656
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31641
31657
  explorer: "https://sepolia.basescan.org/address/",
31642
31658
  explorerTx: "https://sepolia.basescan.org/tx/",
31643
31659
  avgBlockTime: 2
31644
- },
31645
- sepolia: {
31646
- name: "Sepolia",
31647
- chainId: 11155111,
31648
- rpc: "https://rpc.sepolia.org",
31649
- tokens: {
31650
- USDC: {
31651
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31652
- decimals: 6,
31653
- symbol: "USDC"
31654
- },
31655
- USDT: {
31656
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31657
- // Same as USDC on testnet
31658
- decimals: 6,
31659
- symbol: "USDT"
31660
- }
31661
- },
31662
- usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31663
- explorer: "https://sepolia.etherscan.io/address/",
31664
- explorerTx: "https://sepolia.etherscan.io/tx/",
31665
- avgBlockTime: 12
31666
31660
  }
31667
31661
  };
31668
31662
  function getChain(name) {
@@ -31847,7 +31841,7 @@ Server accepts: ${serverChains.join(", ")}`
31847
31841
  } else {
31848
31842
  throw new Error(
31849
31843
  `Server accepts: ${serverChains.join(", ")}
31850
- Please specify: --chain base or --chain polygon`
31844
+ Please specify: --chain base, --chain polygon, or --chain base_sepolia`
31851
31845
  );
31852
31846
  }
31853
31847
  }
@@ -31889,13 +31883,19 @@ Please specify: --chain base or --chain polygon`
31889
31883
  if (!payTo) {
31890
31884
  throw new Error("Missing payTo address in payment requirements");
31891
31885
  }
31892
- const authorization = await this.signEIP3009(payTo, amount, chain2, token);
31886
+ const domainOverride = req.extra && typeof req.extra === "object" && req.extra.name ? { name: req.extra.name, version: req.extra.version || "2" } : void 0;
31887
+ const authorization = await this.signEIP3009(payTo, amount, chain2, token, domainOverride);
31893
31888
  const tokenConfig = chain2.tokens[token];
31894
- const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31889
+ const extra = req.extra && typeof req.extra === "object" ? req.extra : {
31890
+ name: tokenConfig.eip712Name || "USD Coin",
31891
+ version: "2"
31892
+ };
31895
31893
  const payload = {
31896
31894
  x402Version: X402_VERSION3,
31895
+ scheme: "exact",
31896
+ network,
31897
31897
  payload: authorization,
31898
- // v2 requires 'accepted' field with the requirements being fulfilled
31898
+ // { authorization: {...}, signature: "0x..." }
31899
31899
  accepted: {
31900
31900
  scheme: "exact",
31901
31901
  network,
@@ -31903,7 +31903,7 @@ Please specify: --chain base or --chain polygon`
31903
31903
  amount: amountRaw,
31904
31904
  payTo,
31905
31905
  maxTimeoutSeconds: req.maxTimeoutSeconds || 300,
31906
- extra: req.extra || { name: tokenName, version: "2" }
31906
+ extra
31907
31907
  }
31908
31908
  };
31909
31909
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
@@ -31933,7 +31933,7 @@ Please specify: --chain base or --chain polygon`
31933
31933
  * This only signs - no on-chain transaction, no gas needed.
31934
31934
  * Supports both USDC and USDT.
31935
31935
  */
31936
- async signEIP3009(to, amount, chain2, token = "USDC") {
31936
+ async signEIP3009(to, amount, chain2, token = "USDC", domainOverride) {
31937
31937
  const validAfter = 0;
31938
31938
  const validBefore = Math.floor(Date.now() / 1e3) + 3600;
31939
31939
  const nonce = ethers.hexlify(ethers.randomBytes(32));
@@ -31947,10 +31947,11 @@ Please specify: --chain base or --chain polygon`
31947
31947
  validBefore: validBefore.toString(),
31948
31948
  nonce
31949
31949
  };
31950
- const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31950
+ const tokenName = domainOverride?.name || tokenConfig.eip712Name || (token === "USDC" ? "USD Coin" : "Tether USD");
31951
+ const tokenVersion = domainOverride?.version || "2";
31951
31952
  const domain = {
31952
31953
  name: tokenName,
31953
- version: "2",
31954
+ version: tokenVersion,
31954
31955
  chainId: chain2.chainId,
31955
31956
  verifyingContract: tokenConfig.address
31956
31957
  };
@@ -32119,7 +32120,7 @@ Please specify: --chain base or --chain polygon`
32119
32120
  if (!this.wallet) {
32120
32121
  throw new Error("Client not initialized");
32121
32122
  }
32122
- const supportedChains = ["base", "polygon"];
32123
+ const supportedChains = ["base", "polygon", "base_sepolia"];
32123
32124
  const tokenAbi = ["function balanceOf(address) view returns (uint256)"];
32124
32125
  const results = {};
32125
32126
  await Promise.all(