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/.env.example +14 -0
- package/README.md +185 -93
- package/dist/cli/index.js +69 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +69 -33
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/index.d.mts +3 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.js +46 -26
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +46 -26
- package/dist/client/index.mjs.map +1 -1
- package/dist/index.js +50 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -28
- package/dist/index.mjs.map +1 -1
- package/dist/mcp/index.d.mts +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +1498 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/index.mjs +1492 -0
- package/dist/mcp/index.mjs.map +1 -0
- package/dist/server/index.js +4 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +4 -2
- package/dist/server/index.mjs.map +1 -1
- package/package.json +12 -4
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
|
-
|
|
2215
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
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);
|