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.js CHANGED
@@ -30392,8 +30392,8 @@ init_cjs_shims();
30392
30392
  var import_fs = require("fs");
30393
30393
  var path = __toESM(require("path"));
30394
30394
  var X402_VERSION = 2;
30395
- var CDP_MAINNET_URL = "https://api.cdp.coinbase.com/platform/v2/x402";
30396
- var CDP_TESTNET_URL = "https://www.x402.org/facilitator";
30395
+ var CDP_URL = "https://api.cdp.coinbase.com/platform/v2/x402";
30396
+ var TESTNET_CHAIN_IDS = [84532];
30397
30397
  function loadEnvFile() {
30398
30398
  const envPaths = [
30399
30399
  path.join(process.cwd(), ".env"),
@@ -30428,31 +30428,33 @@ var CDPFacilitator = class extends BaseFacilitator {
30428
30428
  displayName = "Coinbase CDP";
30429
30429
  supportedNetworks;
30430
30430
  endpoint;
30431
- useMainnet;
30432
30431
  apiKeyId;
30433
30432
  apiKeySecret;
30434
30433
  constructor(config = {}) {
30435
30434
  super();
30436
30435
  loadEnvFile();
30437
- this.useMainnet = config.useMainnet ?? process.env.USE_MAINNET?.toLowerCase() === "true";
30438
30436
  this.apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;
30439
30437
  this.apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;
30440
- this.endpoint = this.useMainnet ? CDP_MAINNET_URL : CDP_TESTNET_URL;
30441
- this.supportedNetworks = this.useMainnet ? ["eip155:8453", "eip155:137"] : ["eip155:8453", "eip155:84532", "eip155:137"];
30442
- if (this.useMainnet && (!this.apiKeyId || !this.apiKeySecret)) {
30443
- console.warn("[CDPFacilitator] WARNING: Mainnet mode but missing CDP credentials!");
30444
- console.warn("[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET");
30438
+ this.endpoint = CDP_URL;
30439
+ this.supportedNetworks = [
30440
+ "eip155:8453",
30441
+ // Base mainnet
30442
+ "eip155:137",
30443
+ // Polygon mainnet
30444
+ "eip155:84532"
30445
+ // Base Sepolia (testnet)
30446
+ ];
30447
+ if (!this.apiKeyId || !this.apiKeySecret) {
30448
+ console.warn("[CDPFacilitator] WARNING: Missing CDP credentials!");
30449
+ console.warn("[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET in ~/.moltspay/.env");
30445
30450
  }
30446
30451
  }
30447
30452
  /**
30448
30453
  * Get auth headers for CDP API requests
30449
30454
  */
30450
30455
  async getAuthHeaders(method, urlPath, body) {
30451
- if (!this.useMainnet) {
30452
- return {};
30453
- }
30454
30456
  if (!this.apiKeyId || !this.apiKeySecret) {
30455
- throw new Error("CDP credentials required for mainnet");
30457
+ throw new Error("CDP credentials required. Set CDP_API_KEY_ID and CDP_API_KEY_SECRET");
30456
30458
  }
30457
30459
  try {
30458
30460
  const { getAuthHeaders } = await import("@coinbase/cdp-sdk/auth");
@@ -30504,23 +30506,23 @@ var CDPFacilitator = class extends BaseFacilitator {
30504
30506
  paymentPayload,
30505
30507
  paymentRequirements: requirements
30506
30508
  };
30509
+ console.log("[CDP Verify] Payload:", JSON.stringify(paymentPayload, null, 2));
30510
+ const authHeaders = await this.getAuthHeaders(
30511
+ "POST",
30512
+ "/platform/v2/x402/verify",
30513
+ requestBody
30514
+ );
30507
30515
  const headers = {
30508
- "Content-Type": "application/json"
30516
+ "Content-Type": "application/json",
30517
+ ...authHeaders
30509
30518
  };
30510
- if (this.useMainnet) {
30511
- const authHeaders = await this.getAuthHeaders(
30512
- "POST",
30513
- "/platform/v2/x402/verify",
30514
- requestBody
30515
- );
30516
- Object.assign(headers, authHeaders);
30517
- }
30518
30519
  const response = await fetch(`${this.endpoint}/verify`, {
30519
30520
  method: "POST",
30520
30521
  headers,
30521
30522
  body: JSON.stringify(requestBody)
30522
30523
  });
30523
30524
  const result = await response.json();
30525
+ console.log("[CDP Verify] Response:", response.status, JSON.stringify(result));
30524
30526
  if (!response.ok || !result.isValid) {
30525
30527
  return {
30526
30528
  valid: false,
@@ -30546,17 +30548,15 @@ var CDPFacilitator = class extends BaseFacilitator {
30546
30548
  paymentPayload,
30547
30549
  paymentRequirements: requirements
30548
30550
  };
30551
+ const authHeaders = await this.getAuthHeaders(
30552
+ "POST",
30553
+ "/platform/v2/x402/settle",
30554
+ requestBody
30555
+ );
30549
30556
  const headers = {
30550
- "Content-Type": "application/json"
30557
+ "Content-Type": "application/json",
30558
+ ...authHeaders
30551
30559
  };
30552
- if (this.useMainnet) {
30553
- const authHeaders = await this.getAuthHeaders(
30554
- "POST",
30555
- "/platform/v2/x402/settle",
30556
- requestBody
30557
- );
30558
- Object.assign(headers, authHeaders);
30559
- }
30560
30560
  const response = await fetch(`${this.endpoint}/settle`, {
30561
30561
  method: "POST",
30562
30562
  headers,
@@ -30591,13 +30591,19 @@ var CDPFacilitator = class extends BaseFacilitator {
30591
30591
  freeQuota: 1e3
30592
30592
  };
30593
30593
  }
30594
+ /**
30595
+ * Check if a chain ID is testnet
30596
+ */
30597
+ static isTestnet(chainId) {
30598
+ return TESTNET_CHAIN_IDS.includes(chainId);
30599
+ }
30594
30600
  /**
30595
30601
  * Get configuration summary (for logging)
30596
30602
  */
30597
30603
  getConfigSummary() {
30598
- const mode = this.useMainnet ? "mainnet" : "testnet";
30599
30604
  const hasCredentials = !!(this.apiKeyId && this.apiKeySecret);
30600
- return `CDP Facilitator (${mode}, credentials: ${hasCredentials ? "yes" : "no"})`;
30605
+ const networks = this.supportedNetworks.join(", ");
30606
+ return `CDP Facilitator (networks: ${networks}, credentials: ${hasCredentials ? "yes" : "no"})`;
30601
30607
  }
30602
30608
  };
30603
30609
 
@@ -30865,9 +30871,27 @@ var CHAIN_TO_NETWORK = {
30865
30871
  "polygon": "eip155:137"
30866
30872
  };
30867
30873
  var TOKEN_DOMAINS = {
30868
- USDC: { name: "USD Coin", version: "2" },
30869
- USDT: { name: "Tether USD", version: "2" }
30874
+ // Base mainnet
30875
+ "eip155:8453": {
30876
+ USDC: { name: "USD Coin", version: "2" },
30877
+ USDT: { name: "Tether USD", version: "2" }
30878
+ },
30879
+ // Base Sepolia testnet - USDC uses 'USDC' not 'USD Coin'
30880
+ "eip155:84532": {
30881
+ USDC: { name: "USDC", version: "2" },
30882
+ USDT: { name: "USDC", version: "2" }
30883
+ // Same contract as USDC on testnet
30884
+ },
30885
+ // Polygon mainnet
30886
+ "eip155:137": {
30887
+ USDC: { name: "USD Coin", version: "2" },
30888
+ USDT: { name: "(PoS) Tether USD", version: "2" }
30889
+ }
30870
30890
  };
30891
+ function getTokenDomain(network, token) {
30892
+ const networkDomains = TOKEN_DOMAINS[network] || TOKEN_DOMAINS["eip155:8453"];
30893
+ return networkDomains[token] || { name: "USD Coin", version: "2" };
30894
+ }
30871
30895
  function getAcceptedCurrencies(config) {
30872
30896
  return config.acceptedCurrencies ?? [config.currency];
30873
30897
  }
@@ -30961,11 +30985,14 @@ var MoltsPayServer = class {
30961
30985
  getProviderChains() {
30962
30986
  const provider = this.manifest.provider;
30963
30987
  if (provider.chains && provider.chains.length > 0) {
30964
- return provider.chains.map((c) => ({
30965
- network: c.network || CHAIN_TO_NETWORK[c.chain] || "eip155:8453",
30966
- wallet: c.wallet || provider.wallet,
30967
- tokens: c.tokens || ["USDC"]
30968
- }));
30988
+ return provider.chains.map((c) => {
30989
+ const chainName = typeof c === "string" ? c : c.chain;
30990
+ return {
30991
+ network: CHAIN_TO_NETWORK[chainName] || "eip155:8453",
30992
+ wallet: (typeof c === "object" ? c.wallet : null) || provider.wallet,
30993
+ tokens: (typeof c === "object" ? c.tokens : null) || ["USDC"]
30994
+ };
30995
+ });
30969
30996
  }
30970
30997
  const chain2 = provider.chain || "base";
30971
30998
  const network = CHAIN_TO_NETWORK[chain2] || this.networkId;
@@ -31175,7 +31202,7 @@ var MoltsPayServer = class {
31175
31202
  const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;
31176
31203
  const paymentWallet = this.getWalletForNetwork(paymentNetwork);
31177
31204
  const requirements = this.buildPaymentRequirements(skill.config, paymentNetwork, paymentWallet, paymentToken);
31178
- console.log(`[MoltsPay] Verifying payment...`);
31205
+ console.log(`[MoltsPay] Verifying payment on ${paymentNetwork}...`);
31179
31206
  const verifyResult = await this.registry.verify(payment, requirements);
31180
31207
  if (!verifyResult.valid) {
31181
31208
  return this.sendJson(res, 402, {
@@ -31301,7 +31328,7 @@ var MoltsPayServer = class {
31301
31328
  const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
31302
31329
  const tokenAddresses = TOKEN_ADDRESSES[selectedNetwork] || {};
31303
31330
  const tokenAddress = tokenAddresses[selectedToken];
31304
- const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
31331
+ const tokenDomain = getTokenDomain(selectedNetwork, selectedToken);
31305
31332
  return {
31306
31333
  scheme: "exact",
31307
31334
  network: selectedNetwork,
@@ -31546,7 +31573,7 @@ var MoltsPayServer = class {
31546
31573
  const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
31547
31574
  const tokenAddresses = TOKEN_ADDRESSES[networkId] || TOKEN_ADDRESSES[this.networkId] || {};
31548
31575
  const tokenAddress = tokenAddresses[selectedToken];
31549
- const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
31576
+ const tokenDomain = getTokenDomain(networkId, selectedToken);
31550
31577
  return {
31551
31578
  scheme: "exact",
31552
31579
  network: networkId,
@@ -31605,12 +31632,15 @@ var CHAINS = {
31605
31632
  USDC: {
31606
31633
  address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
31607
31634
  decimals: 6,
31608
- symbol: "USDC"
31635
+ symbol: "USDC",
31636
+ eip712Name: "USD Coin"
31637
+ // EIP-712 domain name
31609
31638
  },
31610
31639
  USDT: {
31611
31640
  address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
31612
31641
  decimals: 6,
31613
- symbol: "USDT"
31642
+ symbol: "USDT",
31643
+ eip712Name: "Tether USD"
31614
31644
  }
31615
31645
  },
31616
31646
  usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
@@ -31627,12 +31657,15 @@ var CHAINS = {
31627
31657
  USDC: {
31628
31658
  address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
31629
31659
  decimals: 6,
31630
- symbol: "USDC"
31660
+ symbol: "USDC",
31661
+ eip712Name: "USD Coin"
31631
31662
  },
31632
31663
  USDT: {
31633
31664
  address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
31634
31665
  decimals: 6,
31635
- symbol: "USDT"
31666
+ symbol: "USDT",
31667
+ eip712Name: "(PoS) Tether USD"
31668
+ // Polygon uses this name
31636
31669
  }
31637
31670
  },
31638
31671
  usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
@@ -31640,27 +31673,6 @@ var CHAINS = {
31640
31673
  explorerTx: "https://polygonscan.com/tx/",
31641
31674
  avgBlockTime: 2
31642
31675
  },
31643
- ethereum: {
31644
- name: "Ethereum",
31645
- chainId: 1,
31646
- rpc: "https://eth.llamarpc.com",
31647
- tokens: {
31648
- USDC: {
31649
- address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
31650
- decimals: 6,
31651
- symbol: "USDC"
31652
- },
31653
- USDT: {
31654
- address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
31655
- decimals: 6,
31656
- symbol: "USDT"
31657
- }
31658
- },
31659
- usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
31660
- explorer: "https://etherscan.io/address/",
31661
- explorerTx: "https://etherscan.io/tx/",
31662
- avgBlockTime: 12
31663
- },
31664
31676
  // ============ Testnet ============
31665
31677
  base_sepolia: {
31666
31678
  name: "Base Sepolia",
@@ -31670,41 +31682,23 @@ var CHAINS = {
31670
31682
  USDC: {
31671
31683
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31672
31684
  decimals: 6,
31673
- symbol: "USDC"
31685
+ symbol: "USDC",
31686
+ eip712Name: "USDC"
31687
+ // Testnet USDC uses 'USDC' not 'USD Coin'
31674
31688
  },
31675
31689
  USDT: {
31676
31690
  address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31677
31691
  // Same as USDC on testnet (no official USDT)
31678
31692
  decimals: 6,
31679
- symbol: "USDT"
31693
+ symbol: "USDT",
31694
+ eip712Name: "USDC"
31695
+ // Uses same contract as USDC
31680
31696
  }
31681
31697
  },
31682
31698
  usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
31683
31699
  explorer: "https://sepolia.basescan.org/address/",
31684
31700
  explorerTx: "https://sepolia.basescan.org/tx/",
31685
31701
  avgBlockTime: 2
31686
- },
31687
- sepolia: {
31688
- name: "Sepolia",
31689
- chainId: 11155111,
31690
- rpc: "https://rpc.sepolia.org",
31691
- tokens: {
31692
- USDC: {
31693
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31694
- decimals: 6,
31695
- symbol: "USDC"
31696
- },
31697
- USDT: {
31698
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31699
- // Same as USDC on testnet
31700
- decimals: 6,
31701
- symbol: "USDT"
31702
- }
31703
- },
31704
- usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
31705
- explorer: "https://sepolia.etherscan.io/address/",
31706
- explorerTx: "https://sepolia.etherscan.io/tx/",
31707
- avgBlockTime: 12
31708
31702
  }
31709
31703
  };
31710
31704
  function getChain(name) {
@@ -31889,7 +31883,7 @@ Server accepts: ${serverChains.join(", ")}`
31889
31883
  } else {
31890
31884
  throw new Error(
31891
31885
  `Server accepts: ${serverChains.join(", ")}
31892
- Please specify: --chain base or --chain polygon`
31886
+ Please specify: --chain base, --chain polygon, or --chain base_sepolia`
31893
31887
  );
31894
31888
  }
31895
31889
  }
@@ -31931,13 +31925,19 @@ Please specify: --chain base or --chain polygon`
31931
31925
  if (!payTo) {
31932
31926
  throw new Error("Missing payTo address in payment requirements");
31933
31927
  }
31934
- const authorization = await this.signEIP3009(payTo, amount, chain2, token);
31928
+ const domainOverride = req.extra && typeof req.extra === "object" && req.extra.name ? { name: req.extra.name, version: req.extra.version || "2" } : void 0;
31929
+ const authorization = await this.signEIP3009(payTo, amount, chain2, token, domainOverride);
31935
31930
  const tokenConfig = chain2.tokens[token];
31936
- const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31931
+ const extra = req.extra && typeof req.extra === "object" ? req.extra : {
31932
+ name: tokenConfig.eip712Name || "USD Coin",
31933
+ version: "2"
31934
+ };
31937
31935
  const payload = {
31938
31936
  x402Version: X402_VERSION3,
31937
+ scheme: "exact",
31938
+ network,
31939
31939
  payload: authorization,
31940
- // v2 requires 'accepted' field with the requirements being fulfilled
31940
+ // { authorization: {...}, signature: "0x..." }
31941
31941
  accepted: {
31942
31942
  scheme: "exact",
31943
31943
  network,
@@ -31945,7 +31945,7 @@ Please specify: --chain base or --chain polygon`
31945
31945
  amount: amountRaw,
31946
31946
  payTo,
31947
31947
  maxTimeoutSeconds: req.maxTimeoutSeconds || 300,
31948
- extra: req.extra || { name: tokenName, version: "2" }
31948
+ extra
31949
31949
  }
31950
31950
  };
31951
31951
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
@@ -31975,7 +31975,7 @@ Please specify: --chain base or --chain polygon`
31975
31975
  * This only signs - no on-chain transaction, no gas needed.
31976
31976
  * Supports both USDC and USDT.
31977
31977
  */
31978
- async signEIP3009(to, amount, chain2, token = "USDC") {
31978
+ async signEIP3009(to, amount, chain2, token = "USDC", domainOverride) {
31979
31979
  const validAfter = 0;
31980
31980
  const validBefore = Math.floor(Date.now() / 1e3) + 3600;
31981
31981
  const nonce = import_ethers.ethers.hexlify(import_ethers.ethers.randomBytes(32));
@@ -31989,10 +31989,11 @@ Please specify: --chain base or --chain polygon`
31989
31989
  validBefore: validBefore.toString(),
31990
31990
  nonce
31991
31991
  };
31992
- const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
31992
+ const tokenName = domainOverride?.name || tokenConfig.eip712Name || (token === "USDC" ? "USD Coin" : "Tether USD");
31993
+ const tokenVersion = domainOverride?.version || "2";
31993
31994
  const domain = {
31994
31995
  name: tokenName,
31995
- version: "2",
31996
+ version: tokenVersion,
31996
31997
  chainId: chain2.chainId,
31997
31998
  verifyingContract: tokenConfig.address
31998
31999
  };
@@ -32161,7 +32162,7 @@ Please specify: --chain base or --chain polygon`
32161
32162
  if (!this.wallet) {
32162
32163
  throw new Error("Client not initialized");
32163
32164
  }
32164
- const supportedChains = ["base", "polygon"];
32165
+ const supportedChains = ["base", "polygon", "base_sepolia"];
32165
32166
  const tokenAbi = ["function balanceOf(address) view returns (uint256)"];
32166
32167
  const results = {};
32167
32168
  await Promise.all(