moltspay 0.9.7 → 1.0.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/README.md +42 -3
- package/dist/cdp/index.js +1 -1
- package/dist/cdp/index.js.map +1 -1
- package/dist/cdp/index.mjs +1 -1
- package/dist/cdp/index.mjs.map +1 -1
- package/dist/chains/index.js +1 -1
- package/dist/chains/index.js.map +1 -1
- package/dist/chains/index.mjs +1 -1
- package/dist/chains/index.mjs.map +1 -1
- package/dist/cli/index.js +206 -47
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +206 -47
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/index.d.mts +11 -1
- package/dist/client/index.d.ts +11 -1
- package/dist/client/index.js +76 -6
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +76 -6
- package/dist/client/index.mjs.map +1 -1
- package/dist/facilitators/index.js +1 -1
- package/dist/facilitators/index.js.map +1 -1
- package/dist/facilitators/index.mjs +1 -1
- package/dist/facilitators/index.mjs.map +1 -1
- package/dist/index.js +180 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +180 -32
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +25 -5
- package/dist/server/index.d.ts +25 -5
- package/dist/server/index.js +104 -26
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +104 -26
- package/dist/server/index.mjs.map +1 -1
- package/dist/verify/index.js +1 -1
- package/dist/verify/index.js.map +1 -1
- package/dist/verify/index.mjs +1 -1
- package/dist/verify/index.mjs.map +1 -1
- package/dist/wallet/index.js +1 -1
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +1 -1
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
- package/schemas/moltspay.services.schema.json +58 -2
package/dist/cli/index.mjs
CHANGED
|
@@ -41,7 +41,7 @@ var CHAINS = {
|
|
|
41
41
|
polygon: {
|
|
42
42
|
name: "Polygon",
|
|
43
43
|
chainId: 137,
|
|
44
|
-
rpc: "https://polygon-rpc.com",
|
|
44
|
+
rpc: "https://polygon-bor-rpc.publicnode.com",
|
|
45
45
|
tokens: {
|
|
46
46
|
USDC: {
|
|
47
47
|
address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
@@ -217,10 +217,14 @@ var MoltsPayClient = class {
|
|
|
217
217
|
throw new Error("Client not initialized. Run: npx moltspay init");
|
|
218
218
|
}
|
|
219
219
|
console.log(`[MoltsPay] Requesting service: ${service}`);
|
|
220
|
+
const requestBody = { service, params };
|
|
221
|
+
if (options.chain) {
|
|
222
|
+
requestBody.chain = options.chain;
|
|
223
|
+
}
|
|
220
224
|
const initialRes = await fetch(`${serverUrl}/execute`, {
|
|
221
225
|
method: "POST",
|
|
222
226
|
headers: { "Content-Type": "application/json" },
|
|
223
|
-
body: JSON.stringify(
|
|
227
|
+
body: JSON.stringify(requestBody)
|
|
224
228
|
});
|
|
225
229
|
if (initialRes.status !== 402) {
|
|
226
230
|
const data = await initialRes.json();
|
|
@@ -247,11 +251,41 @@ var MoltsPayClient = class {
|
|
|
247
251
|
} catch {
|
|
248
252
|
throw new Error("Invalid x-payment-required header");
|
|
249
253
|
}
|
|
250
|
-
const
|
|
254
|
+
const networkToChainName = (network2) => {
|
|
255
|
+
const match = network2.match(/^eip155:(\d+)$/);
|
|
256
|
+
if (!match) return null;
|
|
257
|
+
const chainId = parseInt(match[1]);
|
|
258
|
+
if (chainId === 8453) return "base";
|
|
259
|
+
if (chainId === 137) return "polygon";
|
|
260
|
+
if (chainId === 84532) return "base_sepolia";
|
|
261
|
+
return null;
|
|
262
|
+
};
|
|
263
|
+
const serverChains = requirements.map((r) => networkToChainName(r.network)).filter((c) => c !== null);
|
|
264
|
+
let chainName;
|
|
265
|
+
const userSpecifiedChain = options.chain;
|
|
266
|
+
if (userSpecifiedChain) {
|
|
267
|
+
if (!serverChains.includes(userSpecifiedChain)) {
|
|
268
|
+
throw new Error(
|
|
269
|
+
`Server doesn't accept '${userSpecifiedChain}'.
|
|
270
|
+
Server accepts: ${serverChains.join(", ")}`
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
chainName = userSpecifiedChain;
|
|
274
|
+
} else {
|
|
275
|
+
if (serverChains.length === 1 && serverChains[0] === "base") {
|
|
276
|
+
chainName = "base";
|
|
277
|
+
} else {
|
|
278
|
+
throw new Error(
|
|
279
|
+
`Server accepts: ${serverChains.join(", ")}
|
|
280
|
+
Please specify: --chain base or --chain polygon`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const chain = getChain(chainName);
|
|
251
285
|
const network = `eip155:${chain.chainId}`;
|
|
252
286
|
const req = requirements.find((r) => r.scheme === "exact" && r.network === network);
|
|
253
287
|
if (!req) {
|
|
254
|
-
throw new Error(`
|
|
288
|
+
throw new Error(`Failed to find payment requirement for ${chainName}`);
|
|
255
289
|
}
|
|
256
290
|
const amountRaw = req.amount || req.maxAmountRequired;
|
|
257
291
|
if (!amountRaw) {
|
|
@@ -304,13 +338,17 @@ var MoltsPayClient = class {
|
|
|
304
338
|
};
|
|
305
339
|
const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
|
|
306
340
|
console.log(`[MoltsPay] Sending request with payment...`);
|
|
341
|
+
const paidRequestBody = { service, params };
|
|
342
|
+
if (options.chain) {
|
|
343
|
+
paidRequestBody.chain = options.chain;
|
|
344
|
+
}
|
|
307
345
|
const paidRes = await fetch(`${serverUrl}/execute`, {
|
|
308
346
|
method: "POST",
|
|
309
347
|
headers: {
|
|
310
348
|
"Content-Type": "application/json",
|
|
311
349
|
[PAYMENT_HEADER]: paymentHeader
|
|
312
350
|
},
|
|
313
|
-
body: JSON.stringify(
|
|
351
|
+
body: JSON.stringify(paidRequestBody)
|
|
314
352
|
});
|
|
315
353
|
const result = await paidRes.json();
|
|
316
354
|
if (!paidRes.ok) {
|
|
@@ -479,7 +517,7 @@ var MoltsPayClient = class {
|
|
|
479
517
|
return { address: wallet.address, configDir };
|
|
480
518
|
}
|
|
481
519
|
/**
|
|
482
|
-
* Get wallet balance (USDC, USDT, and native token)
|
|
520
|
+
* Get wallet balance (USDC, USDT, and native token) on default chain
|
|
483
521
|
*/
|
|
484
522
|
async getBalance() {
|
|
485
523
|
if (!this.wallet) {
|
|
@@ -504,6 +542,38 @@ var MoltsPayClient = class {
|
|
|
504
542
|
native: parseFloat(ethers.formatEther(nativeBalance))
|
|
505
543
|
};
|
|
506
544
|
}
|
|
545
|
+
/**
|
|
546
|
+
* Get wallet balances on all supported chains (Base + Polygon)
|
|
547
|
+
*/
|
|
548
|
+
async getAllBalances() {
|
|
549
|
+
if (!this.wallet) {
|
|
550
|
+
throw new Error("Client not initialized");
|
|
551
|
+
}
|
|
552
|
+
const supportedChains = ["base", "polygon"];
|
|
553
|
+
const tokenAbi = ["function balanceOf(address) view returns (uint256)"];
|
|
554
|
+
const results = {};
|
|
555
|
+
await Promise.all(
|
|
556
|
+
supportedChains.map(async (chainName) => {
|
|
557
|
+
try {
|
|
558
|
+
const chain = getChain(chainName);
|
|
559
|
+
const provider = new ethers.JsonRpcProvider(chain.rpc);
|
|
560
|
+
const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([
|
|
561
|
+
provider.getBalance(this.wallet.address),
|
|
562
|
+
new ethers.Contract(chain.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),
|
|
563
|
+
new ethers.Contract(chain.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address)
|
|
564
|
+
]);
|
|
565
|
+
results[chainName] = {
|
|
566
|
+
usdc: parseFloat(ethers.formatUnits(usdcBalance, chain.tokens.USDC.decimals)),
|
|
567
|
+
usdt: parseFloat(ethers.formatUnits(usdtBalance, chain.tokens.USDT.decimals)),
|
|
568
|
+
native: parseFloat(ethers.formatEther(nativeBalance))
|
|
569
|
+
};
|
|
570
|
+
} catch (err) {
|
|
571
|
+
results[chainName] = { usdc: 0, usdt: 0, native: 0 };
|
|
572
|
+
}
|
|
573
|
+
})
|
|
574
|
+
);
|
|
575
|
+
return results;
|
|
576
|
+
}
|
|
507
577
|
};
|
|
508
578
|
|
|
509
579
|
// src/server/index.ts
|
|
@@ -568,7 +638,7 @@ var CDPFacilitator = class extends BaseFacilitator {
|
|
|
568
638
|
this.apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;
|
|
569
639
|
this.apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;
|
|
570
640
|
this.endpoint = this.useMainnet ? CDP_MAINNET_URL : CDP_TESTNET_URL;
|
|
571
|
-
this.supportedNetworks = this.useMainnet ? ["eip155:8453"] : ["eip155:8453", "eip155:84532"];
|
|
641
|
+
this.supportedNetworks = this.useMainnet ? ["eip155:8453", "eip155:137"] : ["eip155:8453", "eip155:84532", "eip155:137"];
|
|
572
642
|
if (this.useMainnet && (!this.apiKeyId || !this.apiKeySecret)) {
|
|
573
643
|
console.warn("[CDPFacilitator] WARNING: Mainnet mode but missing CDP credentials!");
|
|
574
644
|
console.warn("[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET");
|
|
@@ -969,8 +1039,17 @@ var TOKEN_ADDRESSES = {
|
|
|
969
1039
|
USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
970
1040
|
USDT: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
971
1041
|
// Same as USDC on testnet
|
|
1042
|
+
},
|
|
1043
|
+
"eip155:137": {
|
|
1044
|
+
USDC: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
1045
|
+
USDT: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F"
|
|
972
1046
|
}
|
|
973
1047
|
};
|
|
1048
|
+
var CHAIN_TO_NETWORK = {
|
|
1049
|
+
"base": "eip155:8453",
|
|
1050
|
+
"base_sepolia": "eip155:84532",
|
|
1051
|
+
"polygon": "eip155:137"
|
|
1052
|
+
};
|
|
974
1053
|
var TOKEN_DOMAINS = {
|
|
975
1054
|
USDC: { name: "USD Coin", version: "2" },
|
|
976
1055
|
USDT: { name: "Tether USD", version: "2" }
|
|
@@ -1036,11 +1115,17 @@ var MoltsPayServer = class {
|
|
|
1036
1115
|
};
|
|
1037
1116
|
this.registry = new FacilitatorRegistry(facilitatorConfig);
|
|
1038
1117
|
const primaryFacilitator = this.registry.get(facilitatorConfig.primary);
|
|
1039
|
-
const networkName = this.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
|
|
1040
1118
|
console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);
|
|
1041
1119
|
console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);
|
|
1042
1120
|
console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);
|
|
1043
|
-
|
|
1121
|
+
const chains = this.manifest.provider.chains;
|
|
1122
|
+
if (chains && chains.length > 0) {
|
|
1123
|
+
const chainNames = chains.map((c) => c.chain || c.network).join(", ");
|
|
1124
|
+
console.log(`[MoltsPay] Chains: ${chainNames} (multi-chain enabled)`);
|
|
1125
|
+
} else {
|
|
1126
|
+
const networkName = this.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
|
|
1127
|
+
console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);
|
|
1128
|
+
}
|
|
1044
1129
|
console.log(`[MoltsPay] Facilitator: ${primaryFacilitator.displayName} (${facilitatorConfig.strategy || "failover"})`);
|
|
1045
1130
|
console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);
|
|
1046
1131
|
}
|
|
@@ -1055,6 +1140,42 @@ var MoltsPayServer = class {
|
|
|
1055
1140
|
this.skills.set(serviceId, { id: serviceId, config, handler });
|
|
1056
1141
|
return this;
|
|
1057
1142
|
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Get all configured chains for this provider
|
|
1145
|
+
* Returns array of { network, wallet, tokens } for each chain
|
|
1146
|
+
*/
|
|
1147
|
+
getProviderChains() {
|
|
1148
|
+
const provider = this.manifest.provider;
|
|
1149
|
+
if (provider.chains && provider.chains.length > 0) {
|
|
1150
|
+
return provider.chains.map((c) => ({
|
|
1151
|
+
network: c.network || CHAIN_TO_NETWORK[c.chain] || "eip155:8453",
|
|
1152
|
+
wallet: c.wallet || provider.wallet,
|
|
1153
|
+
tokens: c.tokens || ["USDC"]
|
|
1154
|
+
}));
|
|
1155
|
+
}
|
|
1156
|
+
const chain = provider.chain || "base";
|
|
1157
|
+
const network = CHAIN_TO_NETWORK[chain] || this.networkId;
|
|
1158
|
+
return [{
|
|
1159
|
+
network,
|
|
1160
|
+
wallet: provider.wallet,
|
|
1161
|
+
tokens: ["USDC"]
|
|
1162
|
+
}];
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Get wallet address for a specific network
|
|
1166
|
+
*/
|
|
1167
|
+
getWalletForNetwork(network) {
|
|
1168
|
+
const chains = this.getProviderChains();
|
|
1169
|
+
const chain = chains.find((c) => c.network === network);
|
|
1170
|
+
return chain?.wallet || this.manifest.provider.wallet;
|
|
1171
|
+
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Check if a network is accepted by this provider
|
|
1174
|
+
*/
|
|
1175
|
+
isNetworkAccepted(network) {
|
|
1176
|
+
const chains = this.getProviderChains();
|
|
1177
|
+
return chains.some((c) => c.network === network);
|
|
1178
|
+
}
|
|
1058
1179
|
/**
|
|
1059
1180
|
* Start HTTP server
|
|
1060
1181
|
*/
|
|
@@ -1237,7 +1358,9 @@ var MoltsPayServer = class {
|
|
|
1237
1358
|
error: `Token ${paymentToken} not accepted. Accepted: ${accepted.join(", ")}`
|
|
1238
1359
|
});
|
|
1239
1360
|
}
|
|
1240
|
-
const
|
|
1361
|
+
const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;
|
|
1362
|
+
const paymentWallet = this.getWalletForNetwork(paymentNetwork);
|
|
1363
|
+
const requirements = this.buildPaymentRequirements(skill.config, paymentNetwork, paymentWallet, paymentToken);
|
|
1241
1364
|
console.log(`[MoltsPay] Verifying payment...`);
|
|
1242
1365
|
const verifyResult = await this.registry.verify(payment, requirements);
|
|
1243
1366
|
if (!verifyResult.valid) {
|
|
@@ -1292,15 +1415,29 @@ var MoltsPayServer = class {
|
|
|
1292
1415
|
}
|
|
1293
1416
|
/**
|
|
1294
1417
|
* Return 402 with x402 payment requirements (v2 format)
|
|
1295
|
-
* Includes requirements for all accepted currencies
|
|
1418
|
+
* Includes requirements for all chains and all accepted currencies
|
|
1296
1419
|
*/
|
|
1297
1420
|
sendPaymentRequired(config, res) {
|
|
1298
1421
|
const acceptedTokens = getAcceptedCurrencies(config);
|
|
1299
|
-
const
|
|
1422
|
+
const providerChains = this.getProviderChains();
|
|
1423
|
+
const accepts = [];
|
|
1424
|
+
for (const chainConfig of providerChains) {
|
|
1425
|
+
for (const token of acceptedTokens) {
|
|
1426
|
+
if (chainConfig.tokens.includes(token)) {
|
|
1427
|
+
accepts.push(this.buildPaymentRequirements(config, chainConfig.network, chainConfig.wallet, token));
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
const acceptedChains = providerChains.map((c) => {
|
|
1432
|
+
if (c.network === "eip155:8453") return "base";
|
|
1433
|
+
if (c.network === "eip155:137") return "polygon";
|
|
1434
|
+
return c.network;
|
|
1435
|
+
});
|
|
1300
1436
|
const paymentRequired = {
|
|
1301
1437
|
x402Version: X402_VERSION3,
|
|
1302
1438
|
accepts,
|
|
1303
1439
|
acceptedCurrencies: acceptedTokens,
|
|
1440
|
+
acceptedChains,
|
|
1304
1441
|
resource: {
|
|
1305
1442
|
url: `/execute?service=${config.id}`,
|
|
1306
1443
|
description: `${config.name} - $${config.price} ${config.currency}`,
|
|
@@ -1316,6 +1453,7 @@ var MoltsPayServer = class {
|
|
|
1316
1453
|
error: "Payment required",
|
|
1317
1454
|
message: `Service requires $${config.price} ${config.currency}`,
|
|
1318
1455
|
acceptedCurrencies: acceptedTokens,
|
|
1456
|
+
acceptedChains,
|
|
1319
1457
|
x402: paymentRequired
|
|
1320
1458
|
}, null, 2));
|
|
1321
1459
|
}
|
|
@@ -1327,46 +1465,50 @@ var MoltsPayServer = class {
|
|
|
1327
1465
|
return { valid: false, error: `Unsupported x402 version: ${payment.x402Version}` };
|
|
1328
1466
|
}
|
|
1329
1467
|
const scheme = payment.accepted?.scheme || payment.scheme;
|
|
1330
|
-
const network = payment.accepted?.network || payment.network;
|
|
1468
|
+
const network = payment.accepted?.network || payment.network || this.networkId;
|
|
1331
1469
|
if (scheme !== "exact") {
|
|
1332
1470
|
return { valid: false, error: `Unsupported scheme: ${scheme}` };
|
|
1333
1471
|
}
|
|
1334
|
-
if (
|
|
1335
|
-
|
|
1472
|
+
if (!this.isNetworkAccepted(network)) {
|
|
1473
|
+
const acceptedChains = this.getProviderChains().map((c) => c.network).join(", ");
|
|
1474
|
+
return { valid: false, error: `Network not accepted: ${network}. Accepted: ${acceptedChains}` };
|
|
1336
1475
|
}
|
|
1337
1476
|
return { valid: true };
|
|
1338
1477
|
}
|
|
1339
1478
|
/**
|
|
1340
1479
|
* Build payment requirements for facilitator
|
|
1341
|
-
*
|
|
1342
|
-
* Server accepts any of the acceptedCurrencies
|
|
1480
|
+
* Now supports multi-chain: takes network and wallet as parameters
|
|
1343
1481
|
*/
|
|
1344
|
-
buildPaymentRequirements(config, token) {
|
|
1482
|
+
buildPaymentRequirements(config, network, wallet, token) {
|
|
1345
1483
|
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
1346
1484
|
const acceptedTokens = getAcceptedCurrencies(config);
|
|
1485
|
+
const selectedNetwork = network || this.networkId;
|
|
1486
|
+
const selectedWallet = wallet || this.manifest.provider.wallet;
|
|
1347
1487
|
const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
|
|
1348
|
-
const tokenAddresses = TOKEN_ADDRESSES[
|
|
1488
|
+
const tokenAddresses = TOKEN_ADDRESSES[selectedNetwork] || {};
|
|
1349
1489
|
const tokenAddress = tokenAddresses[selectedToken];
|
|
1350
1490
|
const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
|
|
1351
1491
|
return {
|
|
1352
1492
|
scheme: "exact",
|
|
1353
|
-
network:
|
|
1493
|
+
network: selectedNetwork,
|
|
1354
1494
|
asset: tokenAddress,
|
|
1355
1495
|
amount: amountInUnits,
|
|
1356
|
-
payTo:
|
|
1496
|
+
payTo: selectedWallet,
|
|
1357
1497
|
maxTimeoutSeconds: 300,
|
|
1358
1498
|
extra: tokenDomain
|
|
1359
1499
|
};
|
|
1360
1500
|
}
|
|
1361
1501
|
/**
|
|
1362
1502
|
* Detect which token is being used in the payment
|
|
1503
|
+
* Checks across all supported networks
|
|
1363
1504
|
*/
|
|
1364
1505
|
detectPaymentToken(payment) {
|
|
1365
1506
|
const asset = payment.accepted?.asset || payment.payload?.asset;
|
|
1366
1507
|
if (!asset) return void 0;
|
|
1367
|
-
const
|
|
1508
|
+
const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;
|
|
1509
|
+
const tokenAddresses = TOKEN_ADDRESSES[paymentNetwork] || {};
|
|
1368
1510
|
for (const [symbol, address] of Object.entries(tokenAddresses)) {
|
|
1369
|
-
if (address.toLowerCase() === asset.toLowerCase()) {
|
|
1511
|
+
if (address && address.toLowerCase() === asset.toLowerCase()) {
|
|
1370
1512
|
return symbol;
|
|
1371
1513
|
}
|
|
1372
1514
|
}
|
|
@@ -1441,6 +1583,10 @@ var MoltsPayServer = class {
|
|
|
1441
1583
|
if (isNaN(amountNum) || amountNum <= 0) {
|
|
1442
1584
|
return this.sendJson(res, 400, { error: "Invalid amount" });
|
|
1443
1585
|
}
|
|
1586
|
+
const supportedChains = ["base", "polygon", "base_sepolia"];
|
|
1587
|
+
if (chain && !supportedChains.includes(chain)) {
|
|
1588
|
+
return this.sendJson(res, 400, { error: `Unsupported chain: ${chain}. Supported: ${supportedChains.join(", ")}` });
|
|
1589
|
+
}
|
|
1444
1590
|
const proxyConfig = {
|
|
1445
1591
|
id: serviceId || "proxy",
|
|
1446
1592
|
name: description || "Proxy Payment",
|
|
@@ -1452,9 +1598,9 @@ var MoltsPayServer = class {
|
|
|
1452
1598
|
input: {},
|
|
1453
1599
|
output: {}
|
|
1454
1600
|
};
|
|
1455
|
-
const requirements = this.buildProxyPaymentRequirements(proxyConfig, wallet);
|
|
1601
|
+
const requirements = this.buildProxyPaymentRequirements(proxyConfig, wallet, currency, chain);
|
|
1456
1602
|
if (!paymentHeader) {
|
|
1457
|
-
return this.sendProxyPaymentRequired(proxyConfig, wallet, memo, res);
|
|
1603
|
+
return this.sendProxyPaymentRequired(proxyConfig, wallet, memo, chain, res);
|
|
1458
1604
|
}
|
|
1459
1605
|
let payment;
|
|
1460
1606
|
try {
|
|
@@ -1471,8 +1617,9 @@ var MoltsPayServer = class {
|
|
|
1471
1617
|
if (scheme !== "exact") {
|
|
1472
1618
|
return this.sendJson(res, 402, { error: `Unsupported scheme: ${scheme}` });
|
|
1473
1619
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1620
|
+
const expectedNetwork = chain ? CHAIN_TO_NETWORK[chain] || this.networkId : this.networkId;
|
|
1621
|
+
if (network !== expectedNetwork) {
|
|
1622
|
+
return this.sendJson(res, 402, { error: `Network mismatch: expected ${expectedNetwork}, got ${network}` });
|
|
1476
1623
|
}
|
|
1477
1624
|
console.log(`[MoltsPay] /proxy: Verifying payment for ${wallet}...`);
|
|
1478
1625
|
const verifyResult = await this.registry.verify(payment, requirements);
|
|
@@ -1578,16 +1725,17 @@ var MoltsPayServer = class {
|
|
|
1578
1725
|
/**
|
|
1579
1726
|
* Build payment requirements for proxy endpoint (uses provided wallet)
|
|
1580
1727
|
*/
|
|
1581
|
-
buildProxyPaymentRequirements(config, wallet, token) {
|
|
1728
|
+
buildProxyPaymentRequirements(config, wallet, token, chain) {
|
|
1582
1729
|
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
1583
1730
|
const acceptedTokens = getAcceptedCurrencies(config);
|
|
1731
|
+
const networkId = chain ? CHAIN_TO_NETWORK[chain] || this.networkId : this.networkId;
|
|
1584
1732
|
const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
|
|
1585
|
-
const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
|
|
1733
|
+
const tokenAddresses = TOKEN_ADDRESSES[networkId] || TOKEN_ADDRESSES[this.networkId] || {};
|
|
1586
1734
|
const tokenAddress = tokenAddresses[selectedToken];
|
|
1587
1735
|
const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
|
|
1588
1736
|
return {
|
|
1589
1737
|
scheme: "exact",
|
|
1590
|
-
network:
|
|
1738
|
+
network: networkId,
|
|
1591
1739
|
asset: tokenAddress,
|
|
1592
1740
|
amount: amountInUnits,
|
|
1593
1741
|
payTo: wallet,
|
|
@@ -1599,8 +1747,8 @@ var MoltsPayServer = class {
|
|
|
1599
1747
|
/**
|
|
1600
1748
|
* Return 402 with x402 payment requirements for proxy endpoint
|
|
1601
1749
|
*/
|
|
1602
|
-
sendProxyPaymentRequired(config, wallet, memo, res) {
|
|
1603
|
-
const requirements = this.buildProxyPaymentRequirements(config, wallet);
|
|
1750
|
+
sendProxyPaymentRequired(config, wallet, memo, chain, res) {
|
|
1751
|
+
const requirements = this.buildProxyPaymentRequirements(config, wallet, config.currency, chain);
|
|
1604
1752
|
const paymentRequired = {
|
|
1605
1753
|
x402Version: X402_VERSION3,
|
|
1606
1754
|
accepts: [requirements],
|
|
@@ -1726,29 +1874,31 @@ program.command("status").description("Show wallet status and balance").option("
|
|
|
1726
1874
|
return;
|
|
1727
1875
|
}
|
|
1728
1876
|
const config = client.getConfig();
|
|
1729
|
-
let
|
|
1877
|
+
let allBalances = {};
|
|
1730
1878
|
try {
|
|
1731
|
-
|
|
1879
|
+
allBalances = await client.getAllBalances();
|
|
1732
1880
|
} catch (err) {
|
|
1733
|
-
console.error("Warning: Could not fetch
|
|
1881
|
+
console.error("Warning: Could not fetch balances:", err.message);
|
|
1734
1882
|
}
|
|
1735
1883
|
if (options.json) {
|
|
1736
1884
|
console.log(JSON.stringify({
|
|
1737
1885
|
address: client.address,
|
|
1738
|
-
|
|
1739
|
-
balance,
|
|
1886
|
+
balances: allBalances,
|
|
1740
1887
|
limits: config.limits
|
|
1741
1888
|
}, null, 2));
|
|
1742
1889
|
} else {
|
|
1743
|
-
console.log("\n\u{1F4CA} MoltsPay Status\n");
|
|
1744
|
-
console.log(`
|
|
1745
|
-
console.log(
|
|
1746
|
-
console.log(
|
|
1747
|
-
|
|
1890
|
+
console.log("\n\u{1F4CA} MoltsPay Wallet Status\n");
|
|
1891
|
+
console.log(` Address: ${client.address}`);
|
|
1892
|
+
console.log("");
|
|
1893
|
+
console.log(" Balances:");
|
|
1894
|
+
for (const [chainName, balance] of Object.entries(allBalances)) {
|
|
1895
|
+
const chainLabel = chainName.charAt(0).toUpperCase() + chainName.slice(1);
|
|
1896
|
+
console.log(` ${chainLabel.padEnd(10)} ${balance.usdc.toFixed(2)} USDC | ${balance.usdt.toFixed(2)} USDT`);
|
|
1897
|
+
}
|
|
1748
1898
|
console.log("");
|
|
1749
|
-
console.log(" Limits:");
|
|
1750
|
-
console.log(`
|
|
1751
|
-
console.log(`
|
|
1899
|
+
console.log(" Spending Limits:");
|
|
1900
|
+
console.log(` Per Transaction: $${config.limits.maxPerTx}`);
|
|
1901
|
+
console.log(` Daily: $${config.limits.maxPerDay}`);
|
|
1752
1902
|
console.log("");
|
|
1753
1903
|
}
|
|
1754
1904
|
});
|
|
@@ -1987,7 +2137,7 @@ program.command("stop").description("Stop the running MoltsPay server").action(a
|
|
|
1987
2137
|
process.exit(1);
|
|
1988
2138
|
}
|
|
1989
2139
|
});
|
|
1990
|
-
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("--json", "Output raw JSON only").action(async (server, service, paramsJson, options) => {
|
|
2140
|
+
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 or polygon). Required if server accepts multiple chains.").option("--json", "Output raw JSON only").action(async (server, service, paramsJson, options) => {
|
|
1991
2141
|
const client = new MoltsPayClient();
|
|
1992
2142
|
if (!client.isInitialized) {
|
|
1993
2143
|
console.error("\u274C Wallet not initialized. Run: npx moltspay init");
|
|
@@ -2021,6 +2171,11 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
|
|
|
2021
2171
|
console.error("\u274C Missing prompt. Use --prompt or pass JSON params");
|
|
2022
2172
|
process.exit(1);
|
|
2023
2173
|
}
|
|
2174
|
+
const chain = options.chain?.toLowerCase();
|
|
2175
|
+
if (chain && !["base", "polygon"].includes(chain)) {
|
|
2176
|
+
console.error(`\u274C Unknown chain: ${chain}. Supported: base, polygon`);
|
|
2177
|
+
process.exit(1);
|
|
2178
|
+
}
|
|
2024
2179
|
const imageDisplay = params.image_url || (params.image_base64 ? `[local file: ${options.image}]` : null);
|
|
2025
2180
|
const token = (options.token || "USDC").toUpperCase();
|
|
2026
2181
|
if (token === "USDT") {
|
|
@@ -2043,12 +2198,16 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
|
|
|
2043
2198
|
console.log(` Service: ${service}`);
|
|
2044
2199
|
console.log(` Prompt: ${params.prompt}`);
|
|
2045
2200
|
if (imageDisplay) console.log(` Image: ${imageDisplay}`);
|
|
2201
|
+
console.log(` Chain: ${chain || "(auto)"}`);
|
|
2046
2202
|
console.log(` Token: ${token}`);
|
|
2047
2203
|
console.log(` Wallet: ${client.address}`);
|
|
2048
2204
|
console.log("");
|
|
2049
2205
|
}
|
|
2050
2206
|
try {
|
|
2051
|
-
const result = await client.pay(server, service, params, {
|
|
2207
|
+
const result = await client.pay(server, service, params, {
|
|
2208
|
+
token,
|
|
2209
|
+
chain
|
|
2210
|
+
});
|
|
2052
2211
|
if (options.json) {
|
|
2053
2212
|
console.log(JSON.stringify(result));
|
|
2054
2213
|
} else {
|