moltspay 1.4.0 → 1.4.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.
@@ -676,11 +676,26 @@ var MoltsPayClient = class {
676
676
  throw new Error("Client not initialized. Run: npx moltspay init");
677
677
  }
678
678
  console.log(`[MoltsPay] Requesting service: ${service}`);
679
- const requestBody = { service, params };
679
+ let executeUrl = `${serverUrl}/execute`;
680
+ try {
681
+ const services = await this.getServices(serverUrl);
682
+ const svc = services.services?.find((s) => s.id === service);
683
+ if (svc?.endpoint) {
684
+ executeUrl = `${serverUrl}${svc.endpoint}`;
685
+ console.log(`[MoltsPay] Using service endpoint: ${svc.endpoint}`);
686
+ }
687
+ } catch {
688
+ }
689
+ let requestBody;
690
+ if (options.rawData) {
691
+ requestBody = { service, ...params };
692
+ } else {
693
+ requestBody = { service, params };
694
+ }
680
695
  if (options.chain) {
681
696
  requestBody.chain = options.chain;
682
697
  }
683
- const initialRes = await fetch(`${serverUrl}/execute`, {
698
+ const initialRes = await fetch(executeUrl, {
684
699
  method: "POST",
685
700
  headers: { "Content-Type": "application/json" },
686
701
  body: JSON.stringify(requestBody)
@@ -696,7 +711,7 @@ var MoltsPayClient = class {
696
711
  const paymentRequiredHeader = initialRes.headers.get(PAYMENT_REQUIRED_HEADER);
697
712
  if (wwwAuthHeader && wwwAuthHeader.toLowerCase().includes("payment")) {
698
713
  console.log("[MoltsPay] Detected MPP protocol, using Tempo flow...");
699
- return await this.handleMPPPayment(serverUrl, service, params, wwwAuthHeader);
714
+ return await this.handleMPPPayment(executeUrl, service, params, wwwAuthHeader, options);
700
715
  }
701
716
  if (!paymentRequiredHeader) {
702
717
  throw new Error("Missing payment header (x-payment-required or www-authenticate)");
@@ -757,7 +772,7 @@ Please specify: --chain <chain_name>`
757
772
  if (!req2) {
758
773
  throw new Error(`Failed to find payment requirement for ${selectedChain}`);
759
774
  }
760
- return await this.handleSolanaPayment(serverUrl, service, params, req2, solanaChain);
775
+ return await this.handleSolanaPayment(executeUrl, service, params, req2, solanaChain, options);
761
776
  }
762
777
  const chainName = selectedChain;
763
778
  const chain = getChain(chainName);
@@ -804,14 +819,14 @@ Please specify: --chain <chain_name>`
804
819
  if (!bnbSpender) {
805
820
  throw new Error("Server did not provide bnbSpender address. Server may not support BNB payments.");
806
821
  }
807
- return await this.handleBNBPayment(serverUrl, service, params, {
822
+ return await this.handleBNBPayment(executeUrl, service, params, {
808
823
  to: payTo2,
809
824
  amount,
810
825
  token,
811
826
  chainName,
812
827
  chain,
813
828
  spender: bnbSpender
814
- });
829
+ }, options);
815
830
  }
816
831
  const payTo = req.payTo || req.resource;
817
832
  if (!payTo) {
@@ -842,11 +857,11 @@ Please specify: --chain <chain_name>`
842
857
  };
843
858
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
844
859
  console.log(`[MoltsPay] Sending request with payment...`);
845
- const paidRequestBody = { service, params };
860
+ const paidRequestBody = options.rawData ? { service, ...params } : { service, params };
846
861
  if (options.chain) {
847
862
  paidRequestBody.chain = options.chain;
848
863
  }
849
- const paidRes = await fetch(`${serverUrl}/execute`, {
864
+ const paidRes = await fetch(executeUrl, {
850
865
  method: "POST",
851
866
  headers: {
852
867
  "Content-Type": "application/json",
@@ -860,13 +875,13 @@ Please specify: --chain <chain_name>`
860
875
  }
861
876
  this.recordSpending(amount);
862
877
  console.log(`[MoltsPay] Success! Payment: ${result.payment?.status || "claimed"}`);
863
- return result.result;
878
+ return result.result || result;
864
879
  }
865
880
  /**
866
881
  * Handle MPP (Machine Payments Protocol) payment flow
867
882
  * Called when pay() detects WWW-Authenticate header in 402 response
868
883
  */
869
- async handleMPPPayment(serverUrl, service, params, wwwAuthHeader) {
884
+ async handleMPPPayment(executeUrl, service, params, wwwAuthHeader, options = {}) {
870
885
  const { privateKeyToAccount: privateKeyToAccount2 } = await import("viem/accounts");
871
886
  const { createWalletClient, createPublicClient, http } = await import("viem");
872
887
  const { tempoModerato } = await import("viem/chains");
@@ -927,13 +942,14 @@ Please specify: --chain <chain_name>`
927
942
  source: `did:pkh:eip155:${chainId}:${account.address}`
928
943
  };
929
944
  const credentialB64 = Buffer.from(JSON.stringify(credential)).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
930
- const paidRes = await fetch(`${serverUrl}/execute`, {
945
+ const retryBody = options.rawData ? { service, ...params, chain: "tempo_moderato" } : { service, params, chain: "tempo_moderato" };
946
+ const paidRes = await fetch(executeUrl, {
931
947
  method: "POST",
932
948
  headers: {
933
949
  "Content-Type": "application/json",
934
950
  "Authorization": `Payment ${credentialB64}`
935
951
  },
936
- body: JSON.stringify({ service, params, chain: "tempo_moderato" })
952
+ body: JSON.stringify(retryBody)
937
953
  });
938
954
  const result = await paidRes.json();
939
955
  if (!paidRes.ok) {
@@ -953,7 +969,7 @@ Please specify: --chain <chain_name>`
953
969
  * 4. Server executes service
954
970
  * 5. Server calls transferFrom if successful (pay-for-success)
955
971
  */
956
- async handleBNBPayment(serverUrl, service, params, paymentDetails) {
972
+ async handleBNBPayment(executeUrl, service, params, paymentDetails, options = {}) {
957
973
  const { to, amount, token, chainName, chain, spender } = paymentDetails;
958
974
  const tokenConfig = chain.tokens[token];
959
975
  const provider = new ethers.JsonRpcProvider(chain.rpc);
@@ -1049,13 +1065,14 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
1049
1065
  };
1050
1066
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
1051
1067
  console.log(`[MoltsPay] Sending BNB payment request...`);
1052
- const paidRes = await fetch(`${serverUrl}/execute`, {
1068
+ const bnbRequestBody = options.rawData ? { service, ...params, chain: chainName } : { service, params, chain: chainName };
1069
+ const paidRes = await fetch(executeUrl, {
1053
1070
  method: "POST",
1054
1071
  headers: {
1055
1072
  "Content-Type": "application/json",
1056
1073
  "X-Payment": paymentHeader
1057
1074
  },
1058
- body: JSON.stringify({ service, params, chain: chainName })
1075
+ body: JSON.stringify(bnbRequestBody)
1059
1076
  });
1060
1077
  const result = await paidRes.json();
1061
1078
  if (!paidRes.ok) {
@@ -1072,7 +1089,7 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
1072
1089
  * 1. Client creates and signs a transfer transaction
1073
1090
  * 2. Server submits the transaction after service completes
1074
1091
  */
1075
- async handleSolanaPayment(serverUrl, service, params, requirements, chain) {
1092
+ async handleSolanaPayment(executeUrl, service, params, requirements, chain, options = {}) {
1076
1093
  const solanaWallet = loadSolanaWallet(this.configDir);
1077
1094
  if (!solanaWallet) {
1078
1095
  throw new Error("No Solana wallet found. Run: npx moltspay init --chain solana_devnet");
@@ -1125,13 +1142,14 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
1125
1142
  }
1126
1143
  };
1127
1144
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
1128
- const paidRes = await fetch(`${serverUrl}/execute`, {
1145
+ const solanaRequestBody = options.rawData ? { service, ...params, chain } : { service, params, chain };
1146
+ const paidRes = await fetch(executeUrl, {
1129
1147
  method: "POST",
1130
1148
  headers: {
1131
1149
  "Content-Type": "application/json",
1132
1150
  "X-Payment": paymentHeader
1133
1151
  },
1134
- body: JSON.stringify({ service, params, chain })
1152
+ body: JSON.stringify(solanaRequestBody)
1135
1153
  });
1136
1154
  const result = await paidRes.json();
1137
1155
  if (!paidRes.ok) {
@@ -3267,8 +3285,10 @@ var MoltsPayServer = class {
3267
3285
  isProxyAllowed(clientIP) {
3268
3286
  const allowedIPs = process.env.PROXY_ALLOWED_IPS?.split(",").map((ip) => ip.trim()) || [];
3269
3287
  if (allowedIPs.length === 0) {
3270
- console.log(`[MoltsPay] /proxy denied: no PROXY_ALLOWED_IPS configured`);
3271
- return false;
3288
+ return true;
3289
+ }
3290
+ if (allowedIPs.includes("*")) {
3291
+ return true;
3272
3292
  }
3273
3293
  const normalizedIP = clientIP === "::1" ? "127.0.0.1" : clientIP.replace("::ffff:", "");
3274
3294
  const allowed = allowedIPs.includes(normalizedIP) || allowedIPs.includes(clientIP);
@@ -4864,14 +4884,23 @@ program.command("stop").description("Stop the running MoltsPay server").action(a
4864
4884
  process.exit(1);
4865
4885
  }
4866
4886
  });
4867
- program.command("pay <server> <service> [params]").description("Pay for a service and get the result").option("--prompt <text>", "Prompt for the service").option("--image <path>", "Image URL or local file path").option("--token <token>", "Token to pay with (USDC or USDT)", "USDC").option("--chain <chain>", "Chain to pay on (base, polygon, base_sepolia, tempo_moderato, solana, or solana_devnet).").option("--config-dir <dir>", "Config directory with wallet.json", DEFAULT_CONFIG_DIR2).option("--json", "Output raw JSON only").action(async (server, service, paramsJson, options) => {
4887
+ program.command("pay <server> <service> [params]").description("Pay for a service and get the result").option("--prompt <text>", "Prompt for the service").option("--image <path>", "Image URL or local file path").option("--data <json>", "Raw JSON data to send (for custom input formats)").option("--token <token>", "Token to pay with (USDC or USDT)", "USDC").option("--chain <chain>", "Chain to pay on (base, polygon, base_sepolia, tempo_moderato, solana, or solana_devnet).").option("--config-dir <dir>", "Config directory with wallet.json", DEFAULT_CONFIG_DIR2).option("--json", "Output raw JSON only").action(async (server, service, paramsJson, options) => {
4868
4888
  const client = new MoltsPayClient({ configDir: options.configDir });
4869
4889
  if (!client.isInitialized) {
4870
4890
  console.error("\u274C Wallet not initialized. Run: npx moltspay init");
4871
4891
  process.exit(1);
4872
4892
  }
4873
4893
  let params = {};
4874
- if (paramsJson) {
4894
+ let useRawData = false;
4895
+ if (options.data) {
4896
+ try {
4897
+ params = JSON.parse(options.data);
4898
+ useRawData = true;
4899
+ } catch {
4900
+ console.error("\u274C Invalid JSON in --data flag");
4901
+ process.exit(1);
4902
+ }
4903
+ } else if (paramsJson) {
4875
4904
  try {
4876
4905
  params = JSON.parse(paramsJson);
4877
4906
  } catch {
@@ -4879,7 +4908,7 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
4879
4908
  process.exit(1);
4880
4909
  }
4881
4910
  }
4882
- if (options.prompt) params.prompt = options.prompt;
4911
+ if (!useRawData && options.prompt) params.prompt = options.prompt;
4883
4912
  if (options.image) {
4884
4913
  const imagePath = options.image;
4885
4914
  if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
@@ -4920,7 +4949,11 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
4920
4949
  `);
4921
4950
  console.log(` Server: ${server}`);
4922
4951
  console.log(` Service: ${service}`);
4923
- console.log(` Prompt: ${params.prompt}`);
4952
+ if (useRawData) {
4953
+ console.log(` Data: ${JSON.stringify(params).slice(0, 50)}${JSON.stringify(params).length > 50 ? "..." : ""}`);
4954
+ } else {
4955
+ console.log(` Prompt: ${params.prompt}`);
4956
+ }
4924
4957
  if (imageDisplay) console.log(` Image: ${imageDisplay}`);
4925
4958
  console.log(` Chain: ${chain || "(auto)"}`);
4926
4959
  console.log(` Token: ${token}`);
@@ -4930,7 +4963,8 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
4930
4963
  try {
4931
4964
  const result = await client.pay(server, service, params, {
4932
4965
  token,
4933
- chain
4966
+ chain,
4967
+ rawData: useRawData
4934
4968
  });
4935
4969
  if (options.json) {
4936
4970
  console.log(JSON.stringify(result));