moltspay 0.9.7 → 1.1.0

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 (43) hide show
  1. package/README.md +42 -3
  2. package/dist/cdp/index.js +1 -1
  3. package/dist/cdp/index.js.map +1 -1
  4. package/dist/cdp/index.mjs +1 -1
  5. package/dist/cdp/index.mjs.map +1 -1
  6. package/dist/chains/index.js +1 -1
  7. package/dist/chains/index.js.map +1 -1
  8. package/dist/chains/index.mjs +1 -1
  9. package/dist/chains/index.mjs.map +1 -1
  10. package/dist/cli/index.js +5028 -109
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/cli/index.mjs +5019 -96
  13. package/dist/cli/index.mjs.map +1 -1
  14. package/dist/client/index.d.mts +18 -3
  15. package/dist/client/index.d.ts +18 -3
  16. package/dist/client/index.js +89 -10
  17. package/dist/client/index.js.map +1 -1
  18. package/dist/client/index.mjs +89 -10
  19. package/dist/client/index.mjs.map +1 -1
  20. package/dist/facilitators/index.js +1 -1
  21. package/dist/facilitators/index.js.map +1 -1
  22. package/dist/facilitators/index.mjs +1 -1
  23. package/dist/facilitators/index.mjs.map +1 -1
  24. package/dist/index.js +193 -36
  25. package/dist/index.js.map +1 -1
  26. package/dist/index.mjs +193 -36
  27. package/dist/index.mjs.map +1 -1
  28. package/dist/server/index.d.mts +25 -5
  29. package/dist/server/index.d.ts +25 -5
  30. package/dist/server/index.js +104 -26
  31. package/dist/server/index.js.map +1 -1
  32. package/dist/server/index.mjs +104 -26
  33. package/dist/server/index.mjs.map +1 -1
  34. package/dist/verify/index.js +1 -1
  35. package/dist/verify/index.js.map +1 -1
  36. package/dist/verify/index.mjs +1 -1
  37. package/dist/verify/index.mjs.map +1 -1
  38. package/dist/wallet/index.js +1 -1
  39. package/dist/wallet/index.js.map +1 -1
  40. package/dist/wallet/index.mjs +1 -1
  41. package/dist/wallet/index.mjs.map +1 -1
  42. package/package.json +3 -2
  43. package/schemas/moltspay.services.schema.json +58 -2
@@ -32,11 +32,18 @@ interface OutputField {
32
32
  type: 'string' | 'number' | 'boolean' | 'object';
33
33
  description?: string;
34
34
  }
35
+ interface ChainConfig {
36
+ chain: string;
37
+ network: string;
38
+ wallet?: string;
39
+ tokens?: TokenSymbol[];
40
+ }
35
41
  interface ProviderConfig {
36
42
  name: string;
37
43
  description?: string;
38
44
  wallet: string;
39
- chain: string;
45
+ chain?: string;
46
+ chains?: ChainConfig[];
40
47
  }
41
48
  interface ServicesManifest {
42
49
  provider: ProviderConfig;
@@ -119,6 +126,19 @@ declare class MoltsPayServer {
119
126
  * Register a skill handler for a service
120
127
  */
121
128
  skill(serviceId: string, handler: SkillFunction): this;
129
+ /**
130
+ * Get all configured chains for this provider
131
+ * Returns array of { network, wallet, tokens } for each chain
132
+ */
133
+ private getProviderChains;
134
+ /**
135
+ * Get wallet address for a specific network
136
+ */
137
+ private getWalletForNetwork;
138
+ /**
139
+ * Check if a network is accepted by this provider
140
+ */
141
+ private isNetworkAccepted;
122
142
  /**
123
143
  * Start HTTP server
124
144
  */
@@ -145,7 +165,7 @@ declare class MoltsPayServer {
145
165
  private handleExecute;
146
166
  /**
147
167
  * Return 402 with x402 payment requirements (v2 format)
148
- * Includes requirements for all accepted currencies
168
+ * Includes requirements for all chains and all accepted currencies
149
169
  */
150
170
  private sendPaymentRequired;
151
171
  /**
@@ -154,12 +174,12 @@ declare class MoltsPayServer {
154
174
  private validatePayment;
155
175
  /**
156
176
  * Build payment requirements for facilitator
157
- * Returns requirements for the primary currency (USDC by default)
158
- * Server accepts any of the acceptedCurrencies
177
+ * Now supports multi-chain: takes network and wallet as parameters
159
178
  */
160
179
  private buildPaymentRequirements;
161
180
  /**
162
181
  * Detect which token is being used in the payment
182
+ * Checks across all supported networks
163
183
  */
164
184
  private detectPaymentToken;
165
185
  /**
@@ -195,4 +215,4 @@ declare class MoltsPayServer {
195
215
  private sendProxyPaymentRequired;
196
216
  }
197
217
 
198
- export { type Charge, type ChargeStatus, type InputField, MoltsPayServer, type MoltsPayServerOptions, type MoltsPayServerOptionsExtended, type OutputField, type PaymentRequest, type ProviderConfig, type RegisteredSkill, type ServiceConfig, type ServicesManifest, type SkillFunction, type TokenSymbol, type VerifyRequest };
218
+ export { type ChainConfig, type Charge, type ChargeStatus, type InputField, MoltsPayServer, type MoltsPayServerOptions, type MoltsPayServerOptionsExtended, type OutputField, type PaymentRequest, type ProviderConfig, type RegisteredSkill, type ServiceConfig, type ServicesManifest, type SkillFunction, type TokenSymbol, type VerifyRequest };
@@ -32,11 +32,18 @@ interface OutputField {
32
32
  type: 'string' | 'number' | 'boolean' | 'object';
33
33
  description?: string;
34
34
  }
35
+ interface ChainConfig {
36
+ chain: string;
37
+ network: string;
38
+ wallet?: string;
39
+ tokens?: TokenSymbol[];
40
+ }
35
41
  interface ProviderConfig {
36
42
  name: string;
37
43
  description?: string;
38
44
  wallet: string;
39
- chain: string;
45
+ chain?: string;
46
+ chains?: ChainConfig[];
40
47
  }
41
48
  interface ServicesManifest {
42
49
  provider: ProviderConfig;
@@ -119,6 +126,19 @@ declare class MoltsPayServer {
119
126
  * Register a skill handler for a service
120
127
  */
121
128
  skill(serviceId: string, handler: SkillFunction): this;
129
+ /**
130
+ * Get all configured chains for this provider
131
+ * Returns array of { network, wallet, tokens } for each chain
132
+ */
133
+ private getProviderChains;
134
+ /**
135
+ * Get wallet address for a specific network
136
+ */
137
+ private getWalletForNetwork;
138
+ /**
139
+ * Check if a network is accepted by this provider
140
+ */
141
+ private isNetworkAccepted;
122
142
  /**
123
143
  * Start HTTP server
124
144
  */
@@ -145,7 +165,7 @@ declare class MoltsPayServer {
145
165
  private handleExecute;
146
166
  /**
147
167
  * Return 402 with x402 payment requirements (v2 format)
148
- * Includes requirements for all accepted currencies
168
+ * Includes requirements for all chains and all accepted currencies
149
169
  */
150
170
  private sendPaymentRequired;
151
171
  /**
@@ -154,12 +174,12 @@ declare class MoltsPayServer {
154
174
  private validatePayment;
155
175
  /**
156
176
  * Build payment requirements for facilitator
157
- * Returns requirements for the primary currency (USDC by default)
158
- * Server accepts any of the acceptedCurrencies
177
+ * Now supports multi-chain: takes network and wallet as parameters
159
178
  */
160
179
  private buildPaymentRequirements;
161
180
  /**
162
181
  * Detect which token is being used in the payment
182
+ * Checks across all supported networks
163
183
  */
164
184
  private detectPaymentToken;
165
185
  /**
@@ -195,4 +215,4 @@ declare class MoltsPayServer {
195
215
  private sendProxyPaymentRequired;
196
216
  }
197
217
 
198
- export { type Charge, type ChargeStatus, type InputField, MoltsPayServer, type MoltsPayServerOptions, type MoltsPayServerOptionsExtended, type OutputField, type PaymentRequest, type ProviderConfig, type RegisteredSkill, type ServiceConfig, type ServicesManifest, type SkillFunction, type TokenSymbol, type VerifyRequest };
218
+ export { type ChainConfig, type Charge, type ChargeStatus, type InputField, MoltsPayServer, type MoltsPayServerOptions, type MoltsPayServerOptionsExtended, type OutputField, type PaymentRequest, type ProviderConfig, type RegisteredSkill, type ServiceConfig, type ServicesManifest, type SkillFunction, type TokenSymbol, type VerifyRequest };
@@ -94,7 +94,7 @@ var CDPFacilitator = class extends BaseFacilitator {
94
94
  this.apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;
95
95
  this.apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;
96
96
  this.endpoint = this.useMainnet ? CDP_MAINNET_URL : CDP_TESTNET_URL;
97
- this.supportedNetworks = this.useMainnet ? ["eip155:8453"] : ["eip155:8453", "eip155:84532"];
97
+ this.supportedNetworks = this.useMainnet ? ["eip155:8453", "eip155:137"] : ["eip155:8453", "eip155:84532", "eip155:137"];
98
98
  if (this.useMainnet && (!this.apiKeyId || !this.apiKeySecret)) {
99
99
  console.warn("[CDPFacilitator] WARNING: Mainnet mode but missing CDP credentials!");
100
100
  console.warn("[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET");
@@ -495,8 +495,17 @@ var TOKEN_ADDRESSES = {
495
495
  USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
496
496
  USDT: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
497
497
  // Same as USDC on testnet
498
+ },
499
+ "eip155:137": {
500
+ USDC: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
501
+ USDT: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F"
498
502
  }
499
503
  };
504
+ var CHAIN_TO_NETWORK = {
505
+ "base": "eip155:8453",
506
+ "base_sepolia": "eip155:84532",
507
+ "polygon": "eip155:137"
508
+ };
500
509
  var TOKEN_DOMAINS = {
501
510
  USDC: { name: "USD Coin", version: "2" },
502
511
  USDT: { name: "Tether USD", version: "2" }
@@ -562,11 +571,17 @@ var MoltsPayServer = class {
562
571
  };
563
572
  this.registry = new FacilitatorRegistry(facilitatorConfig);
564
573
  const primaryFacilitator = this.registry.get(facilitatorConfig.primary);
565
- const networkName = this.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
566
574
  console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);
567
575
  console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);
568
576
  console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);
569
- console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);
577
+ const chains = this.manifest.provider.chains;
578
+ if (chains && chains.length > 0) {
579
+ const chainNames = chains.map((c) => c.chain || c.network).join(", ");
580
+ console.log(`[MoltsPay] Chains: ${chainNames} (multi-chain enabled)`);
581
+ } else {
582
+ const networkName = this.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
583
+ console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);
584
+ }
570
585
  console.log(`[MoltsPay] Facilitator: ${primaryFacilitator.displayName} (${facilitatorConfig.strategy || "failover"})`);
571
586
  console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);
572
587
  }
@@ -581,6 +596,42 @@ var MoltsPayServer = class {
581
596
  this.skills.set(serviceId, { id: serviceId, config, handler });
582
597
  return this;
583
598
  }
599
+ /**
600
+ * Get all configured chains for this provider
601
+ * Returns array of { network, wallet, tokens } for each chain
602
+ */
603
+ getProviderChains() {
604
+ const provider = this.manifest.provider;
605
+ if (provider.chains && provider.chains.length > 0) {
606
+ return provider.chains.map((c) => ({
607
+ network: c.network || CHAIN_TO_NETWORK[c.chain] || "eip155:8453",
608
+ wallet: c.wallet || provider.wallet,
609
+ tokens: c.tokens || ["USDC"]
610
+ }));
611
+ }
612
+ const chain = provider.chain || "base";
613
+ const network = CHAIN_TO_NETWORK[chain] || this.networkId;
614
+ return [{
615
+ network,
616
+ wallet: provider.wallet,
617
+ tokens: ["USDC"]
618
+ }];
619
+ }
620
+ /**
621
+ * Get wallet address for a specific network
622
+ */
623
+ getWalletForNetwork(network) {
624
+ const chains = this.getProviderChains();
625
+ const chain = chains.find((c) => c.network === network);
626
+ return chain?.wallet || this.manifest.provider.wallet;
627
+ }
628
+ /**
629
+ * Check if a network is accepted by this provider
630
+ */
631
+ isNetworkAccepted(network) {
632
+ const chains = this.getProviderChains();
633
+ return chains.some((c) => c.network === network);
634
+ }
584
635
  /**
585
636
  * Start HTTP server
586
637
  */
@@ -763,7 +814,9 @@ var MoltsPayServer = class {
763
814
  error: `Token ${paymentToken} not accepted. Accepted: ${accepted.join(", ")}`
764
815
  });
765
816
  }
766
- const requirements = this.buildPaymentRequirements(skill.config, paymentToken);
817
+ const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;
818
+ const paymentWallet = this.getWalletForNetwork(paymentNetwork);
819
+ const requirements = this.buildPaymentRequirements(skill.config, paymentNetwork, paymentWallet, paymentToken);
767
820
  console.log(`[MoltsPay] Verifying payment...`);
768
821
  const verifyResult = await this.registry.verify(payment, requirements);
769
822
  if (!verifyResult.valid) {
@@ -818,15 +871,29 @@ var MoltsPayServer = class {
818
871
  }
819
872
  /**
820
873
  * Return 402 with x402 payment requirements (v2 format)
821
- * Includes requirements for all accepted currencies
874
+ * Includes requirements for all chains and all accepted currencies
822
875
  */
823
876
  sendPaymentRequired(config, res) {
824
877
  const acceptedTokens = getAcceptedCurrencies(config);
825
- const accepts = acceptedTokens.map((token) => this.buildPaymentRequirements(config, token));
878
+ const providerChains = this.getProviderChains();
879
+ const accepts = [];
880
+ for (const chainConfig of providerChains) {
881
+ for (const token of acceptedTokens) {
882
+ if (chainConfig.tokens.includes(token)) {
883
+ accepts.push(this.buildPaymentRequirements(config, chainConfig.network, chainConfig.wallet, token));
884
+ }
885
+ }
886
+ }
887
+ const acceptedChains = providerChains.map((c) => {
888
+ if (c.network === "eip155:8453") return "base";
889
+ if (c.network === "eip155:137") return "polygon";
890
+ return c.network;
891
+ });
826
892
  const paymentRequired = {
827
893
  x402Version: X402_VERSION2,
828
894
  accepts,
829
895
  acceptedCurrencies: acceptedTokens,
896
+ acceptedChains,
830
897
  resource: {
831
898
  url: `/execute?service=${config.id}`,
832
899
  description: `${config.name} - $${config.price} ${config.currency}`,
@@ -842,6 +909,7 @@ var MoltsPayServer = class {
842
909
  error: "Payment required",
843
910
  message: `Service requires $${config.price} ${config.currency}`,
844
911
  acceptedCurrencies: acceptedTokens,
912
+ acceptedChains,
845
913
  x402: paymentRequired
846
914
  }, null, 2));
847
915
  }
@@ -853,46 +921,50 @@ var MoltsPayServer = class {
853
921
  return { valid: false, error: `Unsupported x402 version: ${payment.x402Version}` };
854
922
  }
855
923
  const scheme = payment.accepted?.scheme || payment.scheme;
856
- const network = payment.accepted?.network || payment.network;
924
+ const network = payment.accepted?.network || payment.network || this.networkId;
857
925
  if (scheme !== "exact") {
858
926
  return { valid: false, error: `Unsupported scheme: ${scheme}` };
859
927
  }
860
- if (network !== this.networkId) {
861
- return { valid: false, error: `Network mismatch: expected ${this.networkId}, got ${network}` };
928
+ if (!this.isNetworkAccepted(network)) {
929
+ const acceptedChains = this.getProviderChains().map((c) => c.network).join(", ");
930
+ return { valid: false, error: `Network not accepted: ${network}. Accepted: ${acceptedChains}` };
862
931
  }
863
932
  return { valid: true };
864
933
  }
865
934
  /**
866
935
  * Build payment requirements for facilitator
867
- * Returns requirements for the primary currency (USDC by default)
868
- * Server accepts any of the acceptedCurrencies
936
+ * Now supports multi-chain: takes network and wallet as parameters
869
937
  */
870
- buildPaymentRequirements(config, token) {
938
+ buildPaymentRequirements(config, network, wallet, token) {
871
939
  const amountInUnits = Math.floor(config.price * 1e6).toString();
872
940
  const acceptedTokens = getAcceptedCurrencies(config);
941
+ const selectedNetwork = network || this.networkId;
942
+ const selectedWallet = wallet || this.manifest.provider.wallet;
873
943
  const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
874
- const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
944
+ const tokenAddresses = TOKEN_ADDRESSES[selectedNetwork] || {};
875
945
  const tokenAddress = tokenAddresses[selectedToken];
876
946
  const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
877
947
  return {
878
948
  scheme: "exact",
879
- network: this.networkId,
949
+ network: selectedNetwork,
880
950
  asset: tokenAddress,
881
951
  amount: amountInUnits,
882
- payTo: this.manifest.provider.wallet,
952
+ payTo: selectedWallet,
883
953
  maxTimeoutSeconds: 300,
884
954
  extra: tokenDomain
885
955
  };
886
956
  }
887
957
  /**
888
958
  * Detect which token is being used in the payment
959
+ * Checks across all supported networks
889
960
  */
890
961
  detectPaymentToken(payment) {
891
962
  const asset = payment.accepted?.asset || payment.payload?.asset;
892
963
  if (!asset) return void 0;
893
- const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
964
+ const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;
965
+ const tokenAddresses = TOKEN_ADDRESSES[paymentNetwork] || {};
894
966
  for (const [symbol, address] of Object.entries(tokenAddresses)) {
895
- if (address.toLowerCase() === asset.toLowerCase()) {
967
+ if (address && address.toLowerCase() === asset.toLowerCase()) {
896
968
  return symbol;
897
969
  }
898
970
  }
@@ -967,6 +1039,10 @@ var MoltsPayServer = class {
967
1039
  if (isNaN(amountNum) || amountNum <= 0) {
968
1040
  return this.sendJson(res, 400, { error: "Invalid amount" });
969
1041
  }
1042
+ const supportedChains = ["base", "polygon", "base_sepolia"];
1043
+ if (chain && !supportedChains.includes(chain)) {
1044
+ return this.sendJson(res, 400, { error: `Unsupported chain: ${chain}. Supported: ${supportedChains.join(", ")}` });
1045
+ }
970
1046
  const proxyConfig = {
971
1047
  id: serviceId || "proxy",
972
1048
  name: description || "Proxy Payment",
@@ -978,9 +1054,9 @@ var MoltsPayServer = class {
978
1054
  input: {},
979
1055
  output: {}
980
1056
  };
981
- const requirements = this.buildProxyPaymentRequirements(proxyConfig, wallet);
1057
+ const requirements = this.buildProxyPaymentRequirements(proxyConfig, wallet, currency, chain);
982
1058
  if (!paymentHeader) {
983
- return this.sendProxyPaymentRequired(proxyConfig, wallet, memo, res);
1059
+ return this.sendProxyPaymentRequired(proxyConfig, wallet, memo, chain, res);
984
1060
  }
985
1061
  let payment;
986
1062
  try {
@@ -997,8 +1073,9 @@ var MoltsPayServer = class {
997
1073
  if (scheme !== "exact") {
998
1074
  return this.sendJson(res, 402, { error: `Unsupported scheme: ${scheme}` });
999
1075
  }
1000
- if (network !== this.networkId) {
1001
- return this.sendJson(res, 402, { error: `Network mismatch: expected ${this.networkId}, got ${network}` });
1076
+ const expectedNetwork = chain ? CHAIN_TO_NETWORK[chain] || this.networkId : this.networkId;
1077
+ if (network !== expectedNetwork) {
1078
+ return this.sendJson(res, 402, { error: `Network mismatch: expected ${expectedNetwork}, got ${network}` });
1002
1079
  }
1003
1080
  console.log(`[MoltsPay] /proxy: Verifying payment for ${wallet}...`);
1004
1081
  const verifyResult = await this.registry.verify(payment, requirements);
@@ -1104,16 +1181,17 @@ var MoltsPayServer = class {
1104
1181
  /**
1105
1182
  * Build payment requirements for proxy endpoint (uses provided wallet)
1106
1183
  */
1107
- buildProxyPaymentRequirements(config, wallet, token) {
1184
+ buildProxyPaymentRequirements(config, wallet, token, chain) {
1108
1185
  const amountInUnits = Math.floor(config.price * 1e6).toString();
1109
1186
  const acceptedTokens = getAcceptedCurrencies(config);
1187
+ const networkId = chain ? CHAIN_TO_NETWORK[chain] || this.networkId : this.networkId;
1110
1188
  const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
1111
- const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
1189
+ const tokenAddresses = TOKEN_ADDRESSES[networkId] || TOKEN_ADDRESSES[this.networkId] || {};
1112
1190
  const tokenAddress = tokenAddresses[selectedToken];
1113
1191
  const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
1114
1192
  return {
1115
1193
  scheme: "exact",
1116
- network: this.networkId,
1194
+ network: networkId,
1117
1195
  asset: tokenAddress,
1118
1196
  amount: amountInUnits,
1119
1197
  payTo: wallet,
@@ -1125,8 +1203,8 @@ var MoltsPayServer = class {
1125
1203
  /**
1126
1204
  * Return 402 with x402 payment requirements for proxy endpoint
1127
1205
  */
1128
- sendProxyPaymentRequired(config, wallet, memo, res) {
1129
- const requirements = this.buildProxyPaymentRequirements(config, wallet);
1206
+ sendProxyPaymentRequired(config, wallet, memo, chain, res) {
1207
+ const requirements = this.buildProxyPaymentRequirements(config, wallet, config.currency, chain);
1130
1208
  const paymentRequired = {
1131
1209
  x402Version: X402_VERSION2,
1132
1210
  accepts: [requirements],