moltspay 0.9.5 → 0.9.7
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 +68 -45
- package/dist/cdp/index.d.mts +1 -1
- package/dist/cdp/index.d.ts +1 -1
- package/dist/cdp/index.js +63 -0
- package/dist/cdp/index.js.map +1 -1
- package/dist/cdp/index.mjs +63 -0
- package/dist/cdp/index.mjs.map +1 -1
- package/dist/chains/index.d.mts +9 -5
- package/dist/chains/index.d.ts +9 -5
- package/dist/chains/index.js +85 -0
- package/dist/chains/index.js.map +1 -1
- package/dist/chains/index.mjs +83 -0
- package/dist/chains/index.mjs.map +1 -1
- package/dist/cli/index.js +201 -38
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +201 -38
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/index.d.mts +18 -3
- package/dist/client/index.d.ts +18 -3
- package/dist/client/index.js +112 -15
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +112 -15
- package/dist/client/index.mjs.map +1 -1
- package/dist/{index-Dg8n6wdW.d.mts → index-B3v8IWjM.d.mts} +11 -1
- package/dist/{index-Dg8n6wdW.d.ts → index-B3v8IWjM.d.ts} +11 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +203 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +203 -42
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +19 -1
- package/dist/server/index.d.ts +19 -1
- package/dist/server/index.js +71 -19
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +71 -19
- package/dist/server/index.mjs.map +1 -1
- package/dist/verify/index.d.mts +7 -0
- package/dist/verify/index.d.ts +7 -0
- package/dist/verify/index.js +83 -8
- package/dist/verify/index.js.map +1 -1
- package/dist/verify/index.mjs +83 -8
- package/dist/verify/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +16 -8
- package/dist/wallet/index.d.ts +16 -8
- package/dist/wallet/index.js +114 -18
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +114 -18
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
- package/schemas/moltspay.services.schema.json +13 -3
package/dist/cli/index.js
CHANGED
|
@@ -43,7 +43,20 @@ var CHAINS = {
|
|
|
43
43
|
name: "Base",
|
|
44
44
|
chainId: 8453,
|
|
45
45
|
rpc: "https://mainnet.base.org",
|
|
46
|
+
tokens: {
|
|
47
|
+
USDC: {
|
|
48
|
+
address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
49
|
+
decimals: 6,
|
|
50
|
+
symbol: "USDC"
|
|
51
|
+
},
|
|
52
|
+
USDT: {
|
|
53
|
+
address: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
|
|
54
|
+
decimals: 6,
|
|
55
|
+
symbol: "USDT"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
46
58
|
usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
59
|
+
// deprecated, for backward compat
|
|
47
60
|
explorer: "https://basescan.org/address/",
|
|
48
61
|
explorerTx: "https://basescan.org/tx/",
|
|
49
62
|
avgBlockTime: 2
|
|
@@ -52,6 +65,18 @@ var CHAINS = {
|
|
|
52
65
|
name: "Polygon",
|
|
53
66
|
chainId: 137,
|
|
54
67
|
rpc: "https://polygon-rpc.com",
|
|
68
|
+
tokens: {
|
|
69
|
+
USDC: {
|
|
70
|
+
address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
71
|
+
decimals: 6,
|
|
72
|
+
symbol: "USDC"
|
|
73
|
+
},
|
|
74
|
+
USDT: {
|
|
75
|
+
address: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
|
|
76
|
+
decimals: 6,
|
|
77
|
+
symbol: "USDT"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
55
80
|
usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
56
81
|
explorer: "https://polygonscan.com/address/",
|
|
57
82
|
explorerTx: "https://polygonscan.com/tx/",
|
|
@@ -61,6 +86,18 @@ var CHAINS = {
|
|
|
61
86
|
name: "Ethereum",
|
|
62
87
|
chainId: 1,
|
|
63
88
|
rpc: "https://eth.llamarpc.com",
|
|
89
|
+
tokens: {
|
|
90
|
+
USDC: {
|
|
91
|
+
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
92
|
+
decimals: 6,
|
|
93
|
+
symbol: "USDC"
|
|
94
|
+
},
|
|
95
|
+
USDT: {
|
|
96
|
+
address: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
97
|
+
decimals: 6,
|
|
98
|
+
symbol: "USDT"
|
|
99
|
+
}
|
|
100
|
+
},
|
|
64
101
|
usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
65
102
|
explorer: "https://etherscan.io/address/",
|
|
66
103
|
explorerTx: "https://etherscan.io/tx/",
|
|
@@ -71,6 +108,19 @@ var CHAINS = {
|
|
|
71
108
|
name: "Base Sepolia",
|
|
72
109
|
chainId: 84532,
|
|
73
110
|
rpc: "https://sepolia.base.org",
|
|
111
|
+
tokens: {
|
|
112
|
+
USDC: {
|
|
113
|
+
address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
114
|
+
decimals: 6,
|
|
115
|
+
symbol: "USDC"
|
|
116
|
+
},
|
|
117
|
+
USDT: {
|
|
118
|
+
address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
119
|
+
// Same as USDC on testnet (no official USDT)
|
|
120
|
+
decimals: 6,
|
|
121
|
+
symbol: "USDT"
|
|
122
|
+
}
|
|
123
|
+
},
|
|
74
124
|
usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
75
125
|
explorer: "https://sepolia.basescan.org/address/",
|
|
76
126
|
explorerTx: "https://sepolia.basescan.org/tx/",
|
|
@@ -80,6 +130,19 @@ var CHAINS = {
|
|
|
80
130
|
name: "Sepolia",
|
|
81
131
|
chainId: 11155111,
|
|
82
132
|
rpc: "https://rpc.sepolia.org",
|
|
133
|
+
tokens: {
|
|
134
|
+
USDC: {
|
|
135
|
+
address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
136
|
+
decimals: 6,
|
|
137
|
+
symbol: "USDC"
|
|
138
|
+
},
|
|
139
|
+
USDT: {
|
|
140
|
+
address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
141
|
+
// Same as USDC on testnet
|
|
142
|
+
decimals: 6,
|
|
143
|
+
symbol: "USDT"
|
|
144
|
+
}
|
|
145
|
+
},
|
|
83
146
|
usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
84
147
|
explorer: "https://sepolia.etherscan.io/address/",
|
|
85
148
|
explorerTx: "https://sepolia.etherscan.io/tx/",
|
|
@@ -166,8 +229,13 @@ var MoltsPayClient = class {
|
|
|
166
229
|
*
|
|
167
230
|
* This is GASLESS for the client - server pays gas to claim payment.
|
|
168
231
|
* This is PAY-FOR-SUCCESS - payment only claimed if service succeeds.
|
|
232
|
+
*
|
|
233
|
+
* @param serverUrl - Server URL
|
|
234
|
+
* @param service - Service ID
|
|
235
|
+
* @param params - Service parameters
|
|
236
|
+
* @param options - Payment options (token selection)
|
|
169
237
|
*/
|
|
170
|
-
async pay(serverUrl, service, params) {
|
|
238
|
+
async pay(serverUrl, service, params, options = {}) {
|
|
171
239
|
if (!this.wallet || !this.walletData) {
|
|
172
240
|
throw new Error("Client not initialized. Run: npx moltspay init");
|
|
173
241
|
}
|
|
@@ -214,12 +282,35 @@ var MoltsPayClient = class {
|
|
|
214
282
|
}
|
|
215
283
|
const amount = Number(amountRaw) / 1e6;
|
|
216
284
|
this.checkLimits(amount);
|
|
217
|
-
|
|
285
|
+
let token = options.token || "USDC";
|
|
286
|
+
if (options.autoSelect) {
|
|
287
|
+
const balances = await this.getBalance();
|
|
288
|
+
if (balances.usdc >= amount) {
|
|
289
|
+
token = "USDC";
|
|
290
|
+
} else if (balances.usdt >= amount) {
|
|
291
|
+
token = "USDT";
|
|
292
|
+
} else {
|
|
293
|
+
throw new Error(`Insufficient balance: need $${amount}, have ${balances.usdc} USDC / ${balances.usdt} USDT`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
if (token === "USDT") {
|
|
297
|
+
const balances = await this.getBalance();
|
|
298
|
+
if (balances.native < 1e-4) {
|
|
299
|
+
throw new Error(
|
|
300
|
+
`USDT requires ETH for gas (~$0.01 on Base). Your ETH balance: ${balances.native.toFixed(6)} ETH. Please add a small amount of ETH to your wallet, or use USDC (gasless).`
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
console.log(`[MoltsPay] \u26A0\uFE0F USDT requires gas (~$0.01). Proceeding with payment...`);
|
|
304
|
+
} else {
|
|
305
|
+
console.log(`[MoltsPay] Signing payment: $${amount} ${token} (gasless)`);
|
|
306
|
+
}
|
|
218
307
|
const payTo = req.payTo || req.resource;
|
|
219
308
|
if (!payTo) {
|
|
220
309
|
throw new Error("Missing payTo address in payment requirements");
|
|
221
310
|
}
|
|
222
|
-
const authorization = await this.signEIP3009(payTo, amount, chain);
|
|
311
|
+
const authorization = await this.signEIP3009(payTo, amount, chain, token);
|
|
312
|
+
const tokenConfig = chain.tokens[token];
|
|
313
|
+
const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
|
|
223
314
|
const payload = {
|
|
224
315
|
x402Version: X402_VERSION,
|
|
225
316
|
payload: authorization,
|
|
@@ -227,11 +318,11 @@ var MoltsPayClient = class {
|
|
|
227
318
|
accepted: {
|
|
228
319
|
scheme: "exact",
|
|
229
320
|
network,
|
|
230
|
-
asset:
|
|
321
|
+
asset: tokenConfig.address,
|
|
231
322
|
amount: amountRaw,
|
|
232
323
|
payTo,
|
|
233
324
|
maxTimeoutSeconds: req.maxTimeoutSeconds || 300,
|
|
234
|
-
extra: req.extra || { name:
|
|
325
|
+
extra: req.extra || { name: tokenName, version: "2" }
|
|
235
326
|
}
|
|
236
327
|
};
|
|
237
328
|
const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
|
|
@@ -255,12 +346,14 @@ var MoltsPayClient = class {
|
|
|
255
346
|
/**
|
|
256
347
|
* Sign EIP-3009 transferWithAuthorization (GASLESS)
|
|
257
348
|
* This only signs - no on-chain transaction, no gas needed.
|
|
349
|
+
* Supports both USDC and USDT.
|
|
258
350
|
*/
|
|
259
|
-
async signEIP3009(to, amount, chain) {
|
|
351
|
+
async signEIP3009(to, amount, chain, token = "USDC") {
|
|
260
352
|
const validAfter = 0;
|
|
261
353
|
const validBefore = Math.floor(Date.now() / 1e3) + 3600;
|
|
262
354
|
const nonce = import_ethers.ethers.hexlify(import_ethers.ethers.randomBytes(32));
|
|
263
|
-
const
|
|
355
|
+
const tokenConfig = chain.tokens[token];
|
|
356
|
+
const value = BigInt(Math.floor(amount * 10 ** tokenConfig.decimals)).toString();
|
|
264
357
|
const authorization = {
|
|
265
358
|
from: this.wallet.address,
|
|
266
359
|
to,
|
|
@@ -269,11 +362,12 @@ var MoltsPayClient = class {
|
|
|
269
362
|
validBefore: validBefore.toString(),
|
|
270
363
|
nonce
|
|
271
364
|
};
|
|
365
|
+
const tokenName = token === "USDC" ? "USD Coin" : "Tether USD";
|
|
272
366
|
const domain = {
|
|
273
|
-
name:
|
|
367
|
+
name: tokenName,
|
|
274
368
|
version: "2",
|
|
275
369
|
chainId: chain.chainId,
|
|
276
|
-
verifyingContract:
|
|
370
|
+
verifyingContract: tokenConfig.address
|
|
277
371
|
};
|
|
278
372
|
const types = {
|
|
279
373
|
TransferWithAuthorization: [
|
|
@@ -408,7 +502,7 @@ var MoltsPayClient = class {
|
|
|
408
502
|
return { address: wallet.address, configDir };
|
|
409
503
|
}
|
|
410
504
|
/**
|
|
411
|
-
* Get wallet balance
|
|
505
|
+
* Get wallet balance (USDC, USDT, and native token)
|
|
412
506
|
*/
|
|
413
507
|
async getBalance() {
|
|
414
508
|
if (!this.wallet) {
|
|
@@ -421,12 +515,15 @@ var MoltsPayClient = class {
|
|
|
421
515
|
throw new Error(`Unknown chain: ${this.config.chain}`);
|
|
422
516
|
}
|
|
423
517
|
const provider = new import_ethers.ethers.JsonRpcProvider(chain.rpc);
|
|
424
|
-
const
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
518
|
+
const tokenAbi = ["function balanceOf(address) view returns (uint256)"];
|
|
519
|
+
const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([
|
|
520
|
+
provider.getBalance(this.wallet.address),
|
|
521
|
+
new import_ethers.ethers.Contract(chain.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),
|
|
522
|
+
new import_ethers.ethers.Contract(chain.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address)
|
|
523
|
+
]);
|
|
428
524
|
return {
|
|
429
|
-
usdc: parseFloat(import_ethers.ethers.formatUnits(usdcBalance,
|
|
525
|
+
usdc: parseFloat(import_ethers.ethers.formatUnits(usdcBalance, chain.tokens.USDC.decimals)),
|
|
526
|
+
usdt: parseFloat(import_ethers.ethers.formatUnits(usdtBalance, chain.tokens.USDT.decimals)),
|
|
430
527
|
native: parseFloat(import_ethers.ethers.formatEther(nativeBalance))
|
|
431
528
|
};
|
|
432
529
|
}
|
|
@@ -886,16 +983,24 @@ var X402_VERSION3 = 2;
|
|
|
886
983
|
var PAYMENT_REQUIRED_HEADER2 = "x-payment-required";
|
|
887
984
|
var PAYMENT_HEADER2 = "x-payment";
|
|
888
985
|
var PAYMENT_RESPONSE_HEADER = "x-payment-response";
|
|
889
|
-
var
|
|
890
|
-
"eip155:8453":
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
986
|
+
var TOKEN_ADDRESSES = {
|
|
987
|
+
"eip155:8453": {
|
|
988
|
+
USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
989
|
+
USDT: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2"
|
|
990
|
+
},
|
|
991
|
+
"eip155:84532": {
|
|
992
|
+
USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
993
|
+
USDT: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
994
|
+
// Same as USDC on testnet
|
|
995
|
+
}
|
|
894
996
|
};
|
|
895
|
-
var
|
|
896
|
-
name: "USD Coin",
|
|
897
|
-
version: "2"
|
|
997
|
+
var TOKEN_DOMAINS = {
|
|
998
|
+
USDC: { name: "USD Coin", version: "2" },
|
|
999
|
+
USDT: { name: "Tether USD", version: "2" }
|
|
898
1000
|
};
|
|
1001
|
+
function getAcceptedCurrencies(config) {
|
|
1002
|
+
return config.acceptedCurrencies ?? [config.currency];
|
|
1003
|
+
}
|
|
899
1004
|
function loadEnvFile2() {
|
|
900
1005
|
const envPaths = [
|
|
901
1006
|
path2.join(process.cwd(), ".env"),
|
|
@@ -1043,6 +1148,7 @@ var MoltsPayServer = class {
|
|
|
1043
1148
|
description: s.description,
|
|
1044
1149
|
price: s.price,
|
|
1045
1150
|
currency: s.currency,
|
|
1151
|
+
acceptedCurrencies: getAcceptedCurrencies(s),
|
|
1046
1152
|
input: s.input,
|
|
1047
1153
|
output: s.output,
|
|
1048
1154
|
available: this.skills.has(s.id)
|
|
@@ -1080,6 +1186,7 @@ var MoltsPayServer = class {
|
|
|
1080
1186
|
description: s.description,
|
|
1081
1187
|
price: s.price,
|
|
1082
1188
|
currency: s.currency,
|
|
1189
|
+
acceptedCurrencies: getAcceptedCurrencies(s),
|
|
1083
1190
|
input: s.input,
|
|
1084
1191
|
output: s.output,
|
|
1085
1192
|
available: this.skills.has(s.id)
|
|
@@ -1146,7 +1253,14 @@ var MoltsPayServer = class {
|
|
|
1146
1253
|
if (!validation.valid) {
|
|
1147
1254
|
return this.sendJson(res, 402, { error: validation.error });
|
|
1148
1255
|
}
|
|
1149
|
-
const
|
|
1256
|
+
const paymentToken = this.detectPaymentToken(payment);
|
|
1257
|
+
if (paymentToken && !this.isTokenAccepted(skill.config, paymentToken)) {
|
|
1258
|
+
const accepted = getAcceptedCurrencies(skill.config);
|
|
1259
|
+
return this.sendJson(res, 402, {
|
|
1260
|
+
error: `Token ${paymentToken} not accepted. Accepted: ${accepted.join(", ")}`
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
const requirements = this.buildPaymentRequirements(skill.config, paymentToken);
|
|
1150
1264
|
console.log(`[MoltsPay] Verifying payment...`);
|
|
1151
1265
|
const verifyResult = await this.registry.verify(payment, requirements);
|
|
1152
1266
|
if (!verifyResult.valid) {
|
|
@@ -1201,12 +1315,15 @@ var MoltsPayServer = class {
|
|
|
1201
1315
|
}
|
|
1202
1316
|
/**
|
|
1203
1317
|
* Return 402 with x402 payment requirements (v2 format)
|
|
1318
|
+
* Includes requirements for all accepted currencies
|
|
1204
1319
|
*/
|
|
1205
1320
|
sendPaymentRequired(config, res) {
|
|
1206
|
-
const
|
|
1321
|
+
const acceptedTokens = getAcceptedCurrencies(config);
|
|
1322
|
+
const accepts = acceptedTokens.map((token) => this.buildPaymentRequirements(config, token));
|
|
1207
1323
|
const paymentRequired = {
|
|
1208
1324
|
x402Version: X402_VERSION3,
|
|
1209
|
-
accepts
|
|
1325
|
+
accepts,
|
|
1326
|
+
acceptedCurrencies: acceptedTokens,
|
|
1210
1327
|
resource: {
|
|
1211
1328
|
url: `/execute?service=${config.id}`,
|
|
1212
1329
|
description: `${config.name} - $${config.price} ${config.currency}`,
|
|
@@ -1221,6 +1338,7 @@ var MoltsPayServer = class {
|
|
|
1221
1338
|
res.end(JSON.stringify({
|
|
1222
1339
|
error: "Payment required",
|
|
1223
1340
|
message: `Service requires $${config.price} ${config.currency}`,
|
|
1341
|
+
acceptedCurrencies: acceptedTokens,
|
|
1224
1342
|
x402: paymentRequired
|
|
1225
1343
|
}, null, 2));
|
|
1226
1344
|
}
|
|
@@ -1243,20 +1361,47 @@ var MoltsPayServer = class {
|
|
|
1243
1361
|
}
|
|
1244
1362
|
/**
|
|
1245
1363
|
* Build payment requirements for facilitator
|
|
1364
|
+
* Returns requirements for the primary currency (USDC by default)
|
|
1365
|
+
* Server accepts any of the acceptedCurrencies
|
|
1246
1366
|
*/
|
|
1247
|
-
buildPaymentRequirements(config) {
|
|
1367
|
+
buildPaymentRequirements(config, token) {
|
|
1248
1368
|
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
1249
|
-
const
|
|
1369
|
+
const acceptedTokens = getAcceptedCurrencies(config);
|
|
1370
|
+
const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
|
|
1371
|
+
const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
|
|
1372
|
+
const tokenAddress = tokenAddresses[selectedToken];
|
|
1373
|
+
const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
|
|
1250
1374
|
return {
|
|
1251
1375
|
scheme: "exact",
|
|
1252
1376
|
network: this.networkId,
|
|
1253
|
-
asset:
|
|
1377
|
+
asset: tokenAddress,
|
|
1254
1378
|
amount: amountInUnits,
|
|
1255
1379
|
payTo: this.manifest.provider.wallet,
|
|
1256
1380
|
maxTimeoutSeconds: 300,
|
|
1257
|
-
extra:
|
|
1381
|
+
extra: tokenDomain
|
|
1258
1382
|
};
|
|
1259
1383
|
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Detect which token is being used in the payment
|
|
1386
|
+
*/
|
|
1387
|
+
detectPaymentToken(payment) {
|
|
1388
|
+
const asset = payment.accepted?.asset || payment.payload?.asset;
|
|
1389
|
+
if (!asset) return void 0;
|
|
1390
|
+
const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
|
|
1391
|
+
for (const [symbol, address] of Object.entries(tokenAddresses)) {
|
|
1392
|
+
if (address.toLowerCase() === asset.toLowerCase()) {
|
|
1393
|
+
return symbol;
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
return void 0;
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Check if payment token is accepted for service
|
|
1400
|
+
*/
|
|
1401
|
+
isTokenAccepted(config, token) {
|
|
1402
|
+
const accepted = getAcceptedCurrencies(config);
|
|
1403
|
+
return accepted.includes(token);
|
|
1404
|
+
}
|
|
1260
1405
|
async readBody(req) {
|
|
1261
1406
|
return new Promise((resolve2, reject) => {
|
|
1262
1407
|
let body = "";
|
|
@@ -1456,18 +1601,22 @@ var MoltsPayServer = class {
|
|
|
1456
1601
|
/**
|
|
1457
1602
|
* Build payment requirements for proxy endpoint (uses provided wallet)
|
|
1458
1603
|
*/
|
|
1459
|
-
buildProxyPaymentRequirements(config, wallet) {
|
|
1604
|
+
buildProxyPaymentRequirements(config, wallet, token) {
|
|
1460
1605
|
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
1461
|
-
const
|
|
1606
|
+
const acceptedTokens = getAcceptedCurrencies(config);
|
|
1607
|
+
const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
|
|
1608
|
+
const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
|
|
1609
|
+
const tokenAddress = tokenAddresses[selectedToken];
|
|
1610
|
+
const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
|
|
1462
1611
|
return {
|
|
1463
1612
|
scheme: "exact",
|
|
1464
1613
|
network: this.networkId,
|
|
1465
|
-
asset:
|
|
1614
|
+
asset: tokenAddress,
|
|
1466
1615
|
amount: amountInUnits,
|
|
1467
1616
|
payTo: wallet,
|
|
1468
1617
|
// Use provided wallet, not manifest
|
|
1469
1618
|
maxTimeoutSeconds: 300,
|
|
1470
|
-
extra:
|
|
1619
|
+
extra: tokenDomain
|
|
1471
1620
|
};
|
|
1472
1621
|
}
|
|
1473
1622
|
/**
|
|
@@ -1600,7 +1749,7 @@ program.command("status").description("Show wallet status and balance").option("
|
|
|
1600
1749
|
return;
|
|
1601
1750
|
}
|
|
1602
1751
|
const config = client.getConfig();
|
|
1603
|
-
let balance = { usdc: 0, native: 0 };
|
|
1752
|
+
let balance = { usdc: 0, usdt: 0, native: 0 };
|
|
1604
1753
|
try {
|
|
1605
1754
|
balance = await client.getBalance();
|
|
1606
1755
|
} catch (err) {
|
|
@@ -1617,7 +1766,7 @@ program.command("status").description("Show wallet status and balance").option("
|
|
|
1617
1766
|
console.log("\n\u{1F4CA} MoltsPay Status\n");
|
|
1618
1767
|
console.log(` Wallet: ${client.address}`);
|
|
1619
1768
|
console.log(` Chain: ${config.chain}`);
|
|
1620
|
-
console.log(` Balance: ${balance.usdc.toFixed(2)} USDC`);
|
|
1769
|
+
console.log(` Balance: ${balance.usdc.toFixed(2)} USDC | ${balance.usdt.toFixed(2)} USDT`);
|
|
1621
1770
|
console.log(` Native: ${balance.native.toFixed(6)} ETH`);
|
|
1622
1771
|
console.log("");
|
|
1623
1772
|
console.log(" Limits:");
|
|
@@ -1861,7 +2010,7 @@ program.command("stop").description("Stop the running MoltsPay server").action(a
|
|
|
1861
2010
|
process.exit(1);
|
|
1862
2011
|
}
|
|
1863
2012
|
});
|
|
1864
|
-
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("--json", "Output raw JSON only").action(async (server, service, paramsJson, options) => {
|
|
2013
|
+
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) => {
|
|
1865
2014
|
const client = new MoltsPayClient();
|
|
1866
2015
|
if (!client.isInitialized) {
|
|
1867
2016
|
console.error("\u274C Wallet not initialized. Run: npx moltspay init");
|
|
@@ -1896,6 +2045,19 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
|
|
|
1896
2045
|
process.exit(1);
|
|
1897
2046
|
}
|
|
1898
2047
|
const imageDisplay = params.image_url || (params.image_base64 ? `[local file: ${options.image}]` : null);
|
|
2048
|
+
const token = (options.token || "USDC").toUpperCase();
|
|
2049
|
+
if (token === "USDT") {
|
|
2050
|
+
const balance = await client.getBalance();
|
|
2051
|
+
if (balance.native < 1e-4) {
|
|
2052
|
+
console.log("\n\u26A0\uFE0F USDT requires a small amount of ETH for gas (~$0.01)");
|
|
2053
|
+
console.log(` Your ETH balance: ${balance.native.toFixed(6)} ETH`);
|
|
2054
|
+
console.log(" Please add a tiny amount of ETH to your wallet.\n");
|
|
2055
|
+
process.exit(1);
|
|
2056
|
+
}
|
|
2057
|
+
if (!options.json) {
|
|
2058
|
+
console.log("\n\u26A0\uFE0F Note: USDT payments require gas (~$0.01 on Base)");
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
1899
2061
|
if (!options.json) {
|
|
1900
2062
|
console.log(`
|
|
1901
2063
|
\u{1F4B3} MoltsPay - Paying for service
|
|
@@ -1904,11 +2066,12 @@ program.command("pay <server> <service> [params]").description("Pay for a servic
|
|
|
1904
2066
|
console.log(` Service: ${service}`);
|
|
1905
2067
|
console.log(` Prompt: ${params.prompt}`);
|
|
1906
2068
|
if (imageDisplay) console.log(` Image: ${imageDisplay}`);
|
|
2069
|
+
console.log(` Token: ${token}`);
|
|
1907
2070
|
console.log(` Wallet: ${client.address}`);
|
|
1908
2071
|
console.log("");
|
|
1909
2072
|
}
|
|
1910
2073
|
try {
|
|
1911
|
-
const result = await client.pay(server, service, params);
|
|
2074
|
+
const result = await client.pay(server, service, params, { token });
|
|
1912
2075
|
if (options.json) {
|
|
1913
2076
|
console.log(JSON.stringify(result));
|
|
1914
2077
|
} else {
|