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/cli/index.mjs
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
1152
|
+
body: JSON.stringify(solanaRequestBody)
|
|
1135
1153
|
});
|
|
1136
1154
|
const result = await paidRes.json();
|
|
1137
1155
|
if (!paidRes.ok) {
|
|
@@ -1276,15 +1294,17 @@ Run: npx moltspay approve --chain ${chainName} --spender ${spender}`
|
|
|
1276
1294
|
loadWallet() {
|
|
1277
1295
|
const walletPath = join2(this.configDir, "wallet.json");
|
|
1278
1296
|
if (existsSync2(walletPath)) {
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1297
|
+
if (process.platform !== "win32") {
|
|
1298
|
+
try {
|
|
1299
|
+
const stats = statSync(walletPath);
|
|
1300
|
+
const mode = stats.mode & 511;
|
|
1301
|
+
if (mode !== 384) {
|
|
1302
|
+
console.warn(`[MoltsPay] WARNING: wallet.json has insecure permissions (${mode.toString(8)})`);
|
|
1303
|
+
console.warn(`[MoltsPay] Fixing permissions to 0600...`);
|
|
1304
|
+
chmodSync(walletPath, 384);
|
|
1305
|
+
}
|
|
1306
|
+
} catch {
|
|
1286
1307
|
}
|
|
1287
|
-
} catch (err) {
|
|
1288
1308
|
}
|
|
1289
1309
|
const content = readFileSync2(walletPath, "utf-8");
|
|
1290
1310
|
return JSON.parse(content);
|
|
@@ -3267,8 +3287,10 @@ var MoltsPayServer = class {
|
|
|
3267
3287
|
isProxyAllowed(clientIP) {
|
|
3268
3288
|
const allowedIPs = process.env.PROXY_ALLOWED_IPS?.split(",").map((ip) => ip.trim()) || [];
|
|
3269
3289
|
if (allowedIPs.length === 0) {
|
|
3270
|
-
|
|
3271
|
-
|
|
3290
|
+
return true;
|
|
3291
|
+
}
|
|
3292
|
+
if (allowedIPs.includes("*")) {
|
|
3293
|
+
return true;
|
|
3272
3294
|
}
|
|
3273
3295
|
const normalizedIP = clientIP === "::1" ? "127.0.0.1" : clientIP.replace("::ffff:", "");
|
|
3274
3296
|
const allowed = allowedIPs.includes(normalizedIP) || allowedIPs.includes(clientIP);
|
|
@@ -4864,14 +4886,23 @@ program.command("stop").description("Stop the running MoltsPay server").action(a
|
|
|
4864
4886
|
process.exit(1);
|
|
4865
4887
|
}
|
|
4866
4888
|
});
|
|
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) => {
|
|
4889
|
+
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
4890
|
const client = new MoltsPayClient({ configDir: options.configDir });
|
|
4869
4891
|
if (!client.isInitialized) {
|
|
4870
4892
|
console.error("\u274C Wallet not initialized. Run: npx moltspay init");
|
|
4871
4893
|
process.exit(1);
|
|
4872
4894
|
}
|
|
4873
4895
|
let params = {};
|
|
4874
|
-
|
|
4896
|
+
let useRawData = false;
|
|
4897
|
+
if (options.data) {
|
|
4898
|
+
try {
|
|
4899
|
+
params = JSON.parse(options.data);
|
|
4900
|
+
useRawData = true;
|
|
4901
|
+
} catch {
|
|
4902
|
+
console.error("\u274C Invalid JSON in --data flag");
|
|
4903
|
+
process.exit(1);
|
|
4904
|
+
}
|
|
4905
|
+
} else if (paramsJson) {
|
|
4875
4906
|
try {
|
|
4876
4907
|
params = JSON.parse(paramsJson);
|
|
4877
4908
|
} catch {
|
|
@@ -4879,7 +4910,7 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
|
|
|
4879
4910
|
process.exit(1);
|
|
4880
4911
|
}
|
|
4881
4912
|
}
|
|
4882
|
-
if (options.prompt) params.prompt = options.prompt;
|
|
4913
|
+
if (!useRawData && options.prompt) params.prompt = options.prompt;
|
|
4883
4914
|
if (options.image) {
|
|
4884
4915
|
const imagePath = options.image;
|
|
4885
4916
|
if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
|
|
@@ -4920,7 +4951,11 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
|
|
|
4920
4951
|
`);
|
|
4921
4952
|
console.log(` Server: ${server}`);
|
|
4922
4953
|
console.log(` Service: ${service}`);
|
|
4923
|
-
|
|
4954
|
+
if (useRawData) {
|
|
4955
|
+
console.log(` Data: ${JSON.stringify(params).slice(0, 50)}${JSON.stringify(params).length > 50 ? "..." : ""}`);
|
|
4956
|
+
} else {
|
|
4957
|
+
console.log(` Prompt: ${params.prompt}`);
|
|
4958
|
+
}
|
|
4924
4959
|
if (imageDisplay) console.log(` Image: ${imageDisplay}`);
|
|
4925
4960
|
console.log(` Chain: ${chain || "(auto)"}`);
|
|
4926
4961
|
console.log(` Token: ${token}`);
|
|
@@ -4930,7 +4965,8 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
|
|
|
4930
4965
|
try {
|
|
4931
4966
|
const result = await client.pay(server, service, params, {
|
|
4932
4967
|
token,
|
|
4933
|
-
chain
|
|
4968
|
+
chain,
|
|
4969
|
+
rawData: useRawData
|
|
4934
4970
|
});
|
|
4935
4971
|
if (options.json) {
|
|
4936
4972
|
console.log(JSON.stringify(result));
|