moltspay 1.4.0 → 1.5.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.
package/dist/index.mjs CHANGED
@@ -2211,8 +2211,10 @@ var MoltsPayServer = class {
2211
2211
  isProxyAllowed(clientIP) {
2212
2212
  const allowedIPs = process.env.PROXY_ALLOWED_IPS?.split(",").map((ip) => ip.trim()) || [];
2213
2213
  if (allowedIPs.length === 0) {
2214
- console.log(`[MoltsPay] /proxy denied: no PROXY_ALLOWED_IPS configured`);
2215
- return false;
2214
+ return true;
2215
+ }
2216
+ if (allowedIPs.includes("*")) {
2217
+ return true;
2216
2218
  }
2217
2219
  const normalizedIP = clientIP === "::1" ? "127.0.0.1" : clientIP.replace("::ffff:", "");
2218
2220
  const allowed = allowedIPs.includes(normalizedIP) || allowedIPs.includes(clientIP);
@@ -2742,11 +2744,26 @@ var MoltsPayClient = class {
2742
2744
  throw new Error("Client not initialized. Run: npx moltspay init");
2743
2745
  }
2744
2746
  console.log(`[MoltsPay] Requesting service: ${service}`);
2745
- const requestBody = { service, params };
2747
+ let executeUrl = `${serverUrl}/execute`;
2748
+ try {
2749
+ const services = await this.getServices(serverUrl);
2750
+ const svc = services.services?.find((s) => s.id === service);
2751
+ if (svc?.endpoint) {
2752
+ executeUrl = `${serverUrl}${svc.endpoint}`;
2753
+ console.log(`[MoltsPay] Using service endpoint: ${svc.endpoint}`);
2754
+ }
2755
+ } catch {
2756
+ }
2757
+ let requestBody;
2758
+ if (options.rawData) {
2759
+ requestBody = { service, ...params };
2760
+ } else {
2761
+ requestBody = { service, params };
2762
+ }
2746
2763
  if (options.chain) {
2747
2764
  requestBody.chain = options.chain;
2748
2765
  }
2749
- const initialRes = await fetch(`${serverUrl}/execute`, {
2766
+ const initialRes = await fetch(executeUrl, {
2750
2767
  method: "POST",
2751
2768
  headers: { "Content-Type": "application/json" },
2752
2769
  body: JSON.stringify(requestBody)
@@ -2762,7 +2779,7 @@ var MoltsPayClient = class {
2762
2779
  const paymentRequiredHeader = initialRes.headers.get(PAYMENT_REQUIRED_HEADER2);
2763
2780
  if (wwwAuthHeader && wwwAuthHeader.toLowerCase().includes("payment")) {
2764
2781
  console.log("[MoltsPay] Detected MPP protocol, using Tempo flow...");
2765
- return await this.handleMPPPayment(serverUrl, service, params, wwwAuthHeader);
2782
+ return await this.handleMPPPayment(executeUrl, service, params, wwwAuthHeader, options);
2766
2783
  }
2767
2784
  if (!paymentRequiredHeader) {
2768
2785
  throw new Error("Missing payment header (x-payment-required or www-authenticate)");
@@ -2823,7 +2840,7 @@ Please specify: --chain <chain_name>`
2823
2840
  if (!req2) {
2824
2841
  throw new Error(`Failed to find payment requirement for ${selectedChain}`);
2825
2842
  }
2826
- return await this.handleSolanaPayment(serverUrl, service, params, req2, solanaChain);
2843
+ return await this.handleSolanaPayment(executeUrl, service, params, req2, solanaChain, options);
2827
2844
  }
2828
2845
  const chainName = selectedChain;
2829
2846
  const chain = getChain(chainName);
@@ -2870,14 +2887,14 @@ Please specify: --chain <chain_name>`
2870
2887
  if (!bnbSpender) {
2871
2888
  throw new Error("Server did not provide bnbSpender address. Server may not support BNB payments.");
2872
2889
  }
2873
- return await this.handleBNBPayment(serverUrl, service, params, {
2890
+ return await this.handleBNBPayment(executeUrl, service, params, {
2874
2891
  to: payTo2,
2875
2892
  amount,
2876
2893
  token,
2877
2894
  chainName,
2878
2895
  chain,
2879
2896
  spender: bnbSpender
2880
- });
2897
+ }, options);
2881
2898
  }
2882
2899
  const payTo = req.payTo || req.resource;
2883
2900
  if (!payTo) {
@@ -2908,11 +2925,11 @@ Please specify: --chain <chain_name>`
2908
2925
  };
2909
2926
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
2910
2927
  console.log(`[MoltsPay] Sending request with payment...`);
2911
- const paidRequestBody = { service, params };
2928
+ const paidRequestBody = options.rawData ? { service, ...params } : { service, params };
2912
2929
  if (options.chain) {
2913
2930
  paidRequestBody.chain = options.chain;
2914
2931
  }
2915
- const paidRes = await fetch(`${serverUrl}/execute`, {
2932
+ const paidRes = await fetch(executeUrl, {
2916
2933
  method: "POST",
2917
2934
  headers: {
2918
2935
  "Content-Type": "application/json",
@@ -2926,13 +2943,13 @@ Please specify: --chain <chain_name>`
2926
2943
  }
2927
2944
  this.recordSpending(amount);
2928
2945
  console.log(`[MoltsPay] Success! Payment: ${result.payment?.status || "claimed"}`);
2929
- return result.result;
2946
+ return result.result || result;
2930
2947
  }
2931
2948
  /**
2932
2949
  * Handle MPP (Machine Payments Protocol) payment flow
2933
2950
  * Called when pay() detects WWW-Authenticate header in 402 response
2934
2951
  */
2935
- async handleMPPPayment(serverUrl, service, params, wwwAuthHeader) {
2952
+ async handleMPPPayment(executeUrl, service, params, wwwAuthHeader, options = {}) {
2936
2953
  const { privateKeyToAccount: privateKeyToAccount2 } = await import("viem/accounts");
2937
2954
  const { createWalletClient, createPublicClient, http } = await import("viem");
2938
2955
  const { tempoModerato } = await import("viem/chains");
@@ -2993,13 +3010,14 @@ Please specify: --chain <chain_name>`
2993
3010
  source: `did:pkh:eip155:${chainId}:${account.address}`
2994
3011
  };
2995
3012
  const credentialB64 = Buffer.from(JSON.stringify(credential)).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
2996
- const paidRes = await fetch(`${serverUrl}/execute`, {
3013
+ const retryBody = options.rawData ? { service, ...params, chain: "tempo_moderato" } : { service, params, chain: "tempo_moderato" };
3014
+ const paidRes = await fetch(executeUrl, {
2997
3015
  method: "POST",
2998
3016
  headers: {
2999
3017
  "Content-Type": "application/json",
3000
3018
  "Authorization": `Payment ${credentialB64}`
3001
3019
  },
3002
- body: JSON.stringify({ service, params, chain: "tempo_moderato" })
3020
+ body: JSON.stringify(retryBody)
3003
3021
  });
3004
3022
  const result = await paidRes.json();
3005
3023
  if (!paidRes.ok) {
@@ -3019,7 +3037,7 @@ Please specify: --chain <chain_name>`
3019
3037
  * 4. Server executes service
3020
3038
  * 5. Server calls transferFrom if successful (pay-for-success)
3021
3039
  */
3022
- async handleBNBPayment(serverUrl, service, params, paymentDetails) {
3040
+ async handleBNBPayment(executeUrl, service, params, paymentDetails, options = {}) {
3023
3041
  const { to, amount, token, chainName, chain, spender } = paymentDetails;
3024
3042
  const tokenConfig = chain.tokens[token];
3025
3043
  const provider = new ethers.JsonRpcProvider(chain.rpc);
@@ -3115,13 +3133,14 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
3115
3133
  };
3116
3134
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
3117
3135
  console.log(`[MoltsPay] Sending BNB payment request...`);
3118
- const paidRes = await fetch(`${serverUrl}/execute`, {
3136
+ const bnbRequestBody = options.rawData ? { service, ...params, chain: chainName } : { service, params, chain: chainName };
3137
+ const paidRes = await fetch(executeUrl, {
3119
3138
  method: "POST",
3120
3139
  headers: {
3121
3140
  "Content-Type": "application/json",
3122
3141
  "X-Payment": paymentHeader
3123
3142
  },
3124
- body: JSON.stringify({ service, params, chain: chainName })
3143
+ body: JSON.stringify(bnbRequestBody)
3125
3144
  });
3126
3145
  const result = await paidRes.json();
3127
3146
  if (!paidRes.ok) {
@@ -3138,7 +3157,7 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
3138
3157
  * 1. Client creates and signs a transfer transaction
3139
3158
  * 2. Server submits the transaction after service completes
3140
3159
  */
3141
- async handleSolanaPayment(serverUrl, service, params, requirements, chain) {
3160
+ async handleSolanaPayment(executeUrl, service, params, requirements, chain, options = {}) {
3142
3161
  const solanaWallet = loadSolanaWallet(this.configDir);
3143
3162
  if (!solanaWallet) {
3144
3163
  throw new Error("No Solana wallet found. Run: npx moltspay init --chain solana_devnet");
@@ -3191,13 +3210,14 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
3191
3210
  }
3192
3211
  };
3193
3212
  const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
3194
- const paidRes = await fetch(`${serverUrl}/execute`, {
3213
+ const solanaRequestBody = options.rawData ? { service, ...params, chain } : { service, params, chain };
3214
+ const paidRes = await fetch(executeUrl, {
3195
3215
  method: "POST",
3196
3216
  headers: {
3197
3217
  "Content-Type": "application/json",
3198
3218
  "X-Payment": paymentHeader
3199
3219
  },
3200
- body: JSON.stringify({ service, params, chain })
3220
+ body: JSON.stringify(solanaRequestBody)
3201
3221
  });
3202
3222
  const result = await paidRes.json();
3203
3223
  if (!paidRes.ok) {
@@ -3342,15 +3362,17 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
3342
3362
  loadWallet() {
3343
3363
  const walletPath = join4(this.configDir, "wallet.json");
3344
3364
  if (existsSync4(walletPath)) {
3345
- try {
3346
- const stats = statSync(walletPath);
3347
- const mode = stats.mode & 511;
3348
- if (mode !== 384) {
3349
- console.warn(`[MoltsPay] WARNING: wallet.json has insecure permissions (${mode.toString(8)})`);
3350
- console.warn(`[MoltsPay] Fixing permissions to 0600...`);
3351
- chmodSync(walletPath, 384);
3365
+ if (process.platform !== "win32") {
3366
+ try {
3367
+ const stats = statSync(walletPath);
3368
+ const mode = stats.mode & 511;
3369
+ if (mode !== 384) {
3370
+ console.warn(`[MoltsPay] WARNING: wallet.json has insecure permissions (${mode.toString(8)})`);
3371
+ console.warn(`[MoltsPay] Fixing permissions to 0600...`);
3372
+ chmodSync(walletPath, 384);
3373
+ }
3374
+ } catch {
3352
3375
  }
3353
- } catch (err) {
3354
3376
  }
3355
3377
  const content = readFileSync4(walletPath, "utf-8");
3356
3378
  return JSON.parse(content);