moltspay 0.9.6 → 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 +110 -48
- 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 +229 -48
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +229 -48
- 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 +87 -7
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +87 -7
- 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 +191 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +191 -33
- 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/index.mjs
CHANGED
|
@@ -30396,7 +30396,7 @@ var CDPFacilitator = class extends BaseFacilitator {
|
|
|
30396
30396
|
this.apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;
|
|
30397
30397
|
this.apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;
|
|
30398
30398
|
this.endpoint = this.useMainnet ? CDP_MAINNET_URL : CDP_TESTNET_URL;
|
|
30399
|
-
this.supportedNetworks = this.useMainnet ? ["eip155:8453"] : ["eip155:8453", "eip155:84532"];
|
|
30399
|
+
this.supportedNetworks = this.useMainnet ? ["eip155:8453", "eip155:137"] : ["eip155:8453", "eip155:84532", "eip155:137"];
|
|
30400
30400
|
if (this.useMainnet && (!this.apiKeyId || !this.apiKeySecret)) {
|
|
30401
30401
|
console.warn("[CDPFacilitator] WARNING: Mainnet mode but missing CDP credentials!");
|
|
30402
30402
|
console.warn("[CDPFacilitator] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET");
|
|
@@ -30811,8 +30811,17 @@ var TOKEN_ADDRESSES = {
|
|
|
30811
30811
|
USDC: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
30812
30812
|
USDT: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
30813
30813
|
// Same as USDC on testnet
|
|
30814
|
+
},
|
|
30815
|
+
"eip155:137": {
|
|
30816
|
+
USDC: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
30817
|
+
USDT: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F"
|
|
30814
30818
|
}
|
|
30815
30819
|
};
|
|
30820
|
+
var CHAIN_TO_NETWORK = {
|
|
30821
|
+
"base": "eip155:8453",
|
|
30822
|
+
"base_sepolia": "eip155:84532",
|
|
30823
|
+
"polygon": "eip155:137"
|
|
30824
|
+
};
|
|
30816
30825
|
var TOKEN_DOMAINS = {
|
|
30817
30826
|
USDC: { name: "USD Coin", version: "2" },
|
|
30818
30827
|
USDT: { name: "Tether USD", version: "2" }
|
|
@@ -30878,11 +30887,17 @@ var MoltsPayServer = class {
|
|
|
30878
30887
|
};
|
|
30879
30888
|
this.registry = new FacilitatorRegistry(facilitatorConfig);
|
|
30880
30889
|
const primaryFacilitator = this.registry.get(facilitatorConfig.primary);
|
|
30881
|
-
const networkName = this.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
|
|
30882
30890
|
console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);
|
|
30883
30891
|
console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);
|
|
30884
30892
|
console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);
|
|
30885
|
-
|
|
30893
|
+
const chains = this.manifest.provider.chains;
|
|
30894
|
+
if (chains && chains.length > 0) {
|
|
30895
|
+
const chainNames = chains.map((c) => c.chain || c.network).join(", ");
|
|
30896
|
+
console.log(`[MoltsPay] Chains: ${chainNames} (multi-chain enabled)`);
|
|
30897
|
+
} else {
|
|
30898
|
+
const networkName = this.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
|
|
30899
|
+
console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);
|
|
30900
|
+
}
|
|
30886
30901
|
console.log(`[MoltsPay] Facilitator: ${primaryFacilitator.displayName} (${facilitatorConfig.strategy || "failover"})`);
|
|
30887
30902
|
console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);
|
|
30888
30903
|
}
|
|
@@ -30897,6 +30912,42 @@ var MoltsPayServer = class {
|
|
|
30897
30912
|
this.skills.set(serviceId, { id: serviceId, config, handler });
|
|
30898
30913
|
return this;
|
|
30899
30914
|
}
|
|
30915
|
+
/**
|
|
30916
|
+
* Get all configured chains for this provider
|
|
30917
|
+
* Returns array of { network, wallet, tokens } for each chain
|
|
30918
|
+
*/
|
|
30919
|
+
getProviderChains() {
|
|
30920
|
+
const provider = this.manifest.provider;
|
|
30921
|
+
if (provider.chains && provider.chains.length > 0) {
|
|
30922
|
+
return provider.chains.map((c) => ({
|
|
30923
|
+
network: c.network || CHAIN_TO_NETWORK[c.chain] || "eip155:8453",
|
|
30924
|
+
wallet: c.wallet || provider.wallet,
|
|
30925
|
+
tokens: c.tokens || ["USDC"]
|
|
30926
|
+
}));
|
|
30927
|
+
}
|
|
30928
|
+
const chain2 = provider.chain || "base";
|
|
30929
|
+
const network = CHAIN_TO_NETWORK[chain2] || this.networkId;
|
|
30930
|
+
return [{
|
|
30931
|
+
network,
|
|
30932
|
+
wallet: provider.wallet,
|
|
30933
|
+
tokens: ["USDC"]
|
|
30934
|
+
}];
|
|
30935
|
+
}
|
|
30936
|
+
/**
|
|
30937
|
+
* Get wallet address for a specific network
|
|
30938
|
+
*/
|
|
30939
|
+
getWalletForNetwork(network) {
|
|
30940
|
+
const chains = this.getProviderChains();
|
|
30941
|
+
const chain2 = chains.find((c) => c.network === network);
|
|
30942
|
+
return chain2?.wallet || this.manifest.provider.wallet;
|
|
30943
|
+
}
|
|
30944
|
+
/**
|
|
30945
|
+
* Check if a network is accepted by this provider
|
|
30946
|
+
*/
|
|
30947
|
+
isNetworkAccepted(network) {
|
|
30948
|
+
const chains = this.getProviderChains();
|
|
30949
|
+
return chains.some((c) => c.network === network);
|
|
30950
|
+
}
|
|
30900
30951
|
/**
|
|
30901
30952
|
* Start HTTP server
|
|
30902
30953
|
*/
|
|
@@ -31079,7 +31130,9 @@ var MoltsPayServer = class {
|
|
|
31079
31130
|
error: `Token ${paymentToken} not accepted. Accepted: ${accepted.join(", ")}`
|
|
31080
31131
|
});
|
|
31081
31132
|
}
|
|
31082
|
-
const
|
|
31133
|
+
const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;
|
|
31134
|
+
const paymentWallet = this.getWalletForNetwork(paymentNetwork);
|
|
31135
|
+
const requirements = this.buildPaymentRequirements(skill.config, paymentNetwork, paymentWallet, paymentToken);
|
|
31083
31136
|
console.log(`[MoltsPay] Verifying payment...`);
|
|
31084
31137
|
const verifyResult = await this.registry.verify(payment, requirements);
|
|
31085
31138
|
if (!verifyResult.valid) {
|
|
@@ -31134,15 +31187,29 @@ var MoltsPayServer = class {
|
|
|
31134
31187
|
}
|
|
31135
31188
|
/**
|
|
31136
31189
|
* Return 402 with x402 payment requirements (v2 format)
|
|
31137
|
-
* Includes requirements for all accepted currencies
|
|
31190
|
+
* Includes requirements for all chains and all accepted currencies
|
|
31138
31191
|
*/
|
|
31139
31192
|
sendPaymentRequired(config, res) {
|
|
31140
31193
|
const acceptedTokens = getAcceptedCurrencies(config);
|
|
31141
|
-
const
|
|
31194
|
+
const providerChains = this.getProviderChains();
|
|
31195
|
+
const accepts = [];
|
|
31196
|
+
for (const chainConfig of providerChains) {
|
|
31197
|
+
for (const token of acceptedTokens) {
|
|
31198
|
+
if (chainConfig.tokens.includes(token)) {
|
|
31199
|
+
accepts.push(this.buildPaymentRequirements(config, chainConfig.network, chainConfig.wallet, token));
|
|
31200
|
+
}
|
|
31201
|
+
}
|
|
31202
|
+
}
|
|
31203
|
+
const acceptedChains = providerChains.map((c) => {
|
|
31204
|
+
if (c.network === "eip155:8453") return "base";
|
|
31205
|
+
if (c.network === "eip155:137") return "polygon";
|
|
31206
|
+
return c.network;
|
|
31207
|
+
});
|
|
31142
31208
|
const paymentRequired = {
|
|
31143
31209
|
x402Version: X402_VERSION2,
|
|
31144
31210
|
accepts,
|
|
31145
31211
|
acceptedCurrencies: acceptedTokens,
|
|
31212
|
+
acceptedChains,
|
|
31146
31213
|
resource: {
|
|
31147
31214
|
url: `/execute?service=${config.id}`,
|
|
31148
31215
|
description: `${config.name} - $${config.price} ${config.currency}`,
|
|
@@ -31158,6 +31225,7 @@ var MoltsPayServer = class {
|
|
|
31158
31225
|
error: "Payment required",
|
|
31159
31226
|
message: `Service requires $${config.price} ${config.currency}`,
|
|
31160
31227
|
acceptedCurrencies: acceptedTokens,
|
|
31228
|
+
acceptedChains,
|
|
31161
31229
|
x402: paymentRequired
|
|
31162
31230
|
}, null, 2));
|
|
31163
31231
|
}
|
|
@@ -31169,46 +31237,50 @@ var MoltsPayServer = class {
|
|
|
31169
31237
|
return { valid: false, error: `Unsupported x402 version: ${payment.x402Version}` };
|
|
31170
31238
|
}
|
|
31171
31239
|
const scheme = payment.accepted?.scheme || payment.scheme;
|
|
31172
|
-
const network = payment.accepted?.network || payment.network;
|
|
31240
|
+
const network = payment.accepted?.network || payment.network || this.networkId;
|
|
31173
31241
|
if (scheme !== "exact") {
|
|
31174
31242
|
return { valid: false, error: `Unsupported scheme: ${scheme}` };
|
|
31175
31243
|
}
|
|
31176
|
-
if (
|
|
31177
|
-
|
|
31244
|
+
if (!this.isNetworkAccepted(network)) {
|
|
31245
|
+
const acceptedChains = this.getProviderChains().map((c) => c.network).join(", ");
|
|
31246
|
+
return { valid: false, error: `Network not accepted: ${network}. Accepted: ${acceptedChains}` };
|
|
31178
31247
|
}
|
|
31179
31248
|
return { valid: true };
|
|
31180
31249
|
}
|
|
31181
31250
|
/**
|
|
31182
31251
|
* Build payment requirements for facilitator
|
|
31183
|
-
*
|
|
31184
|
-
* Server accepts any of the acceptedCurrencies
|
|
31252
|
+
* Now supports multi-chain: takes network and wallet as parameters
|
|
31185
31253
|
*/
|
|
31186
|
-
buildPaymentRequirements(config, token) {
|
|
31254
|
+
buildPaymentRequirements(config, network, wallet, token) {
|
|
31187
31255
|
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
31188
31256
|
const acceptedTokens = getAcceptedCurrencies(config);
|
|
31257
|
+
const selectedNetwork = network || this.networkId;
|
|
31258
|
+
const selectedWallet = wallet || this.manifest.provider.wallet;
|
|
31189
31259
|
const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
|
|
31190
|
-
const tokenAddresses = TOKEN_ADDRESSES[
|
|
31260
|
+
const tokenAddresses = TOKEN_ADDRESSES[selectedNetwork] || {};
|
|
31191
31261
|
const tokenAddress = tokenAddresses[selectedToken];
|
|
31192
31262
|
const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
|
|
31193
31263
|
return {
|
|
31194
31264
|
scheme: "exact",
|
|
31195
|
-
network:
|
|
31265
|
+
network: selectedNetwork,
|
|
31196
31266
|
asset: tokenAddress,
|
|
31197
31267
|
amount: amountInUnits,
|
|
31198
|
-
payTo:
|
|
31268
|
+
payTo: selectedWallet,
|
|
31199
31269
|
maxTimeoutSeconds: 300,
|
|
31200
31270
|
extra: tokenDomain
|
|
31201
31271
|
};
|
|
31202
31272
|
}
|
|
31203
31273
|
/**
|
|
31204
31274
|
* Detect which token is being used in the payment
|
|
31275
|
+
* Checks across all supported networks
|
|
31205
31276
|
*/
|
|
31206
31277
|
detectPaymentToken(payment) {
|
|
31207
31278
|
const asset = payment.accepted?.asset || payment.payload?.asset;
|
|
31208
31279
|
if (!asset) return void 0;
|
|
31209
|
-
const
|
|
31280
|
+
const paymentNetwork = payment.accepted?.network || payment.network || this.networkId;
|
|
31281
|
+
const tokenAddresses = TOKEN_ADDRESSES[paymentNetwork] || {};
|
|
31210
31282
|
for (const [symbol, address] of Object.entries(tokenAddresses)) {
|
|
31211
|
-
if (address.toLowerCase() === asset.toLowerCase()) {
|
|
31283
|
+
if (address && address.toLowerCase() === asset.toLowerCase()) {
|
|
31212
31284
|
return symbol;
|
|
31213
31285
|
}
|
|
31214
31286
|
}
|
|
@@ -31283,6 +31355,10 @@ var MoltsPayServer = class {
|
|
|
31283
31355
|
if (isNaN(amountNum) || amountNum <= 0) {
|
|
31284
31356
|
return this.sendJson(res, 400, { error: "Invalid amount" });
|
|
31285
31357
|
}
|
|
31358
|
+
const supportedChains = ["base", "polygon", "base_sepolia"];
|
|
31359
|
+
if (chain2 && !supportedChains.includes(chain2)) {
|
|
31360
|
+
return this.sendJson(res, 400, { error: `Unsupported chain: ${chain2}. Supported: ${supportedChains.join(", ")}` });
|
|
31361
|
+
}
|
|
31286
31362
|
const proxyConfig = {
|
|
31287
31363
|
id: serviceId || "proxy",
|
|
31288
31364
|
name: description || "Proxy Payment",
|
|
@@ -31294,9 +31370,9 @@ var MoltsPayServer = class {
|
|
|
31294
31370
|
input: {},
|
|
31295
31371
|
output: {}
|
|
31296
31372
|
};
|
|
31297
|
-
const requirements = this.buildProxyPaymentRequirements(proxyConfig, wallet);
|
|
31373
|
+
const requirements = this.buildProxyPaymentRequirements(proxyConfig, wallet, currency, chain2);
|
|
31298
31374
|
if (!paymentHeader) {
|
|
31299
|
-
return this.sendProxyPaymentRequired(proxyConfig, wallet, memo, res);
|
|
31375
|
+
return this.sendProxyPaymentRequired(proxyConfig, wallet, memo, chain2, res);
|
|
31300
31376
|
}
|
|
31301
31377
|
let payment;
|
|
31302
31378
|
try {
|
|
@@ -31313,8 +31389,9 @@ var MoltsPayServer = class {
|
|
|
31313
31389
|
if (scheme !== "exact") {
|
|
31314
31390
|
return this.sendJson(res, 402, { error: `Unsupported scheme: ${scheme}` });
|
|
31315
31391
|
}
|
|
31316
|
-
|
|
31317
|
-
|
|
31392
|
+
const expectedNetwork = chain2 ? CHAIN_TO_NETWORK[chain2] || this.networkId : this.networkId;
|
|
31393
|
+
if (network !== expectedNetwork) {
|
|
31394
|
+
return this.sendJson(res, 402, { error: `Network mismatch: expected ${expectedNetwork}, got ${network}` });
|
|
31318
31395
|
}
|
|
31319
31396
|
console.log(`[MoltsPay] /proxy: Verifying payment for ${wallet}...`);
|
|
31320
31397
|
const verifyResult = await this.registry.verify(payment, requirements);
|
|
@@ -31420,16 +31497,17 @@ var MoltsPayServer = class {
|
|
|
31420
31497
|
/**
|
|
31421
31498
|
* Build payment requirements for proxy endpoint (uses provided wallet)
|
|
31422
31499
|
*/
|
|
31423
|
-
buildProxyPaymentRequirements(config, wallet, token) {
|
|
31500
|
+
buildProxyPaymentRequirements(config, wallet, token, chain2) {
|
|
31424
31501
|
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
31425
31502
|
const acceptedTokens = getAcceptedCurrencies(config);
|
|
31503
|
+
const networkId = chain2 ? CHAIN_TO_NETWORK[chain2] || this.networkId : this.networkId;
|
|
31426
31504
|
const selectedToken = token && acceptedTokens.includes(token) ? token : acceptedTokens[0];
|
|
31427
|
-
const tokenAddresses = TOKEN_ADDRESSES[this.networkId] || {};
|
|
31505
|
+
const tokenAddresses = TOKEN_ADDRESSES[networkId] || TOKEN_ADDRESSES[this.networkId] || {};
|
|
31428
31506
|
const tokenAddress = tokenAddresses[selectedToken];
|
|
31429
31507
|
const tokenDomain = TOKEN_DOMAINS[selectedToken] || TOKEN_DOMAINS.USDC;
|
|
31430
31508
|
return {
|
|
31431
31509
|
scheme: "exact",
|
|
31432
|
-
network:
|
|
31510
|
+
network: networkId,
|
|
31433
31511
|
asset: tokenAddress,
|
|
31434
31512
|
amount: amountInUnits,
|
|
31435
31513
|
payTo: wallet,
|
|
@@ -31441,8 +31519,8 @@ var MoltsPayServer = class {
|
|
|
31441
31519
|
/**
|
|
31442
31520
|
* Return 402 with x402 payment requirements for proxy endpoint
|
|
31443
31521
|
*/
|
|
31444
|
-
sendProxyPaymentRequired(config, wallet, memo, res) {
|
|
31445
|
-
const requirements = this.buildProxyPaymentRequirements(config, wallet);
|
|
31522
|
+
sendProxyPaymentRequired(config, wallet, memo, chain2, res) {
|
|
31523
|
+
const requirements = this.buildProxyPaymentRequirements(config, wallet, config.currency, chain2);
|
|
31446
31524
|
const paymentRequired = {
|
|
31447
31525
|
x402Version: X402_VERSION2,
|
|
31448
31526
|
accepts: [requirements],
|
|
@@ -31502,7 +31580,7 @@ var CHAINS = {
|
|
|
31502
31580
|
polygon: {
|
|
31503
31581
|
name: "Polygon",
|
|
31504
31582
|
chainId: 137,
|
|
31505
|
-
rpc: "https://polygon-rpc.com",
|
|
31583
|
+
rpc: "https://polygon-bor-rpc.publicnode.com",
|
|
31506
31584
|
tokens: {
|
|
31507
31585
|
USDC: {
|
|
31508
31586
|
address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
@@ -31700,10 +31778,14 @@ var MoltsPayClient = class {
|
|
|
31700
31778
|
throw new Error("Client not initialized. Run: npx moltspay init");
|
|
31701
31779
|
}
|
|
31702
31780
|
console.log(`[MoltsPay] Requesting service: ${service}`);
|
|
31781
|
+
const requestBody = { service, params };
|
|
31782
|
+
if (options.chain) {
|
|
31783
|
+
requestBody.chain = options.chain;
|
|
31784
|
+
}
|
|
31703
31785
|
const initialRes = await fetch(`${serverUrl}/execute`, {
|
|
31704
31786
|
method: "POST",
|
|
31705
31787
|
headers: { "Content-Type": "application/json" },
|
|
31706
|
-
body: JSON.stringify(
|
|
31788
|
+
body: JSON.stringify(requestBody)
|
|
31707
31789
|
});
|
|
31708
31790
|
if (initialRes.status !== 402) {
|
|
31709
31791
|
const data = await initialRes.json();
|
|
@@ -31730,11 +31812,41 @@ var MoltsPayClient = class {
|
|
|
31730
31812
|
} catch {
|
|
31731
31813
|
throw new Error("Invalid x-payment-required header");
|
|
31732
31814
|
}
|
|
31733
|
-
const
|
|
31815
|
+
const networkToChainName = (network2) => {
|
|
31816
|
+
const match = network2.match(/^eip155:(\d+)$/);
|
|
31817
|
+
if (!match) return null;
|
|
31818
|
+
const chainId = parseInt(match[1]);
|
|
31819
|
+
if (chainId === 8453) return "base";
|
|
31820
|
+
if (chainId === 137) return "polygon";
|
|
31821
|
+
if (chainId === 84532) return "base_sepolia";
|
|
31822
|
+
return null;
|
|
31823
|
+
};
|
|
31824
|
+
const serverChains = requirements.map((r) => networkToChainName(r.network)).filter((c) => c !== null);
|
|
31825
|
+
let chainName;
|
|
31826
|
+
const userSpecifiedChain = options.chain;
|
|
31827
|
+
if (userSpecifiedChain) {
|
|
31828
|
+
if (!serverChains.includes(userSpecifiedChain)) {
|
|
31829
|
+
throw new Error(
|
|
31830
|
+
`Server doesn't accept '${userSpecifiedChain}'.
|
|
31831
|
+
Server accepts: ${serverChains.join(", ")}`
|
|
31832
|
+
);
|
|
31833
|
+
}
|
|
31834
|
+
chainName = userSpecifiedChain;
|
|
31835
|
+
} else {
|
|
31836
|
+
if (serverChains.length === 1 && serverChains[0] === "base") {
|
|
31837
|
+
chainName = "base";
|
|
31838
|
+
} else {
|
|
31839
|
+
throw new Error(
|
|
31840
|
+
`Server accepts: ${serverChains.join(", ")}
|
|
31841
|
+
Please specify: --chain base or --chain polygon`
|
|
31842
|
+
);
|
|
31843
|
+
}
|
|
31844
|
+
}
|
|
31845
|
+
const chain2 = getChain(chainName);
|
|
31734
31846
|
const network = `eip155:${chain2.chainId}`;
|
|
31735
31847
|
const req = requirements.find((r) => r.scheme === "exact" && r.network === network);
|
|
31736
31848
|
if (!req) {
|
|
31737
|
-
throw new Error(`
|
|
31849
|
+
throw new Error(`Failed to find payment requirement for ${chainName}`);
|
|
31738
31850
|
}
|
|
31739
31851
|
const amountRaw = req.amount || req.maxAmountRequired;
|
|
31740
31852
|
if (!amountRaw) {
|
|
@@ -31753,7 +31865,17 @@ var MoltsPayClient = class {
|
|
|
31753
31865
|
throw new Error(`Insufficient balance: need $${amount}, have ${balances.usdc} USDC / ${balances.usdt} USDT`);
|
|
31754
31866
|
}
|
|
31755
31867
|
}
|
|
31756
|
-
|
|
31868
|
+
if (token === "USDT") {
|
|
31869
|
+
const balances = await this.getBalance();
|
|
31870
|
+
if (balances.native < 1e-4) {
|
|
31871
|
+
throw new Error(
|
|
31872
|
+
`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).`
|
|
31873
|
+
);
|
|
31874
|
+
}
|
|
31875
|
+
console.log(`[MoltsPay] \u26A0\uFE0F USDT requires gas (~$0.01). Proceeding with payment...`);
|
|
31876
|
+
} else {
|
|
31877
|
+
console.log(`[MoltsPay] Signing payment: $${amount} ${token} (gasless)`);
|
|
31878
|
+
}
|
|
31757
31879
|
const payTo = req.payTo || req.resource;
|
|
31758
31880
|
if (!payTo) {
|
|
31759
31881
|
throw new Error("Missing payTo address in payment requirements");
|
|
@@ -31777,13 +31899,17 @@ var MoltsPayClient = class {
|
|
|
31777
31899
|
};
|
|
31778
31900
|
const paymentHeader = Buffer.from(JSON.stringify(payload)).toString("base64");
|
|
31779
31901
|
console.log(`[MoltsPay] Sending request with payment...`);
|
|
31902
|
+
const paidRequestBody = { service, params };
|
|
31903
|
+
if (options.chain) {
|
|
31904
|
+
paidRequestBody.chain = options.chain;
|
|
31905
|
+
}
|
|
31780
31906
|
const paidRes = await fetch(`${serverUrl}/execute`, {
|
|
31781
31907
|
method: "POST",
|
|
31782
31908
|
headers: {
|
|
31783
31909
|
"Content-Type": "application/json",
|
|
31784
31910
|
[PAYMENT_HEADER2]: paymentHeader
|
|
31785
31911
|
},
|
|
31786
|
-
body: JSON.stringify(
|
|
31912
|
+
body: JSON.stringify(paidRequestBody)
|
|
31787
31913
|
});
|
|
31788
31914
|
const result = await paidRes.json();
|
|
31789
31915
|
if (!paidRes.ok) {
|
|
@@ -31952,7 +32078,7 @@ var MoltsPayClient = class {
|
|
|
31952
32078
|
return { address: wallet.address, configDir };
|
|
31953
32079
|
}
|
|
31954
32080
|
/**
|
|
31955
|
-
* Get wallet balance (USDC, USDT, and native token)
|
|
32081
|
+
* Get wallet balance (USDC, USDT, and native token) on default chain
|
|
31956
32082
|
*/
|
|
31957
32083
|
async getBalance() {
|
|
31958
32084
|
if (!this.wallet) {
|
|
@@ -31977,6 +32103,38 @@ var MoltsPayClient = class {
|
|
|
31977
32103
|
native: parseFloat(ethers.formatEther(nativeBalance))
|
|
31978
32104
|
};
|
|
31979
32105
|
}
|
|
32106
|
+
/**
|
|
32107
|
+
* Get wallet balances on all supported chains (Base + Polygon)
|
|
32108
|
+
*/
|
|
32109
|
+
async getAllBalances() {
|
|
32110
|
+
if (!this.wallet) {
|
|
32111
|
+
throw new Error("Client not initialized");
|
|
32112
|
+
}
|
|
32113
|
+
const supportedChains = ["base", "polygon"];
|
|
32114
|
+
const tokenAbi = ["function balanceOf(address) view returns (uint256)"];
|
|
32115
|
+
const results = {};
|
|
32116
|
+
await Promise.all(
|
|
32117
|
+
supportedChains.map(async (chainName) => {
|
|
32118
|
+
try {
|
|
32119
|
+
const chain2 = getChain(chainName);
|
|
32120
|
+
const provider = new ethers.JsonRpcProvider(chain2.rpc);
|
|
32121
|
+
const [nativeBalance, usdcBalance, usdtBalance] = await Promise.all([
|
|
32122
|
+
provider.getBalance(this.wallet.address),
|
|
32123
|
+
new ethers.Contract(chain2.tokens.USDC.address, tokenAbi, provider).balanceOf(this.wallet.address),
|
|
32124
|
+
new ethers.Contract(chain2.tokens.USDT.address, tokenAbi, provider).balanceOf(this.wallet.address)
|
|
32125
|
+
]);
|
|
32126
|
+
results[chainName] = {
|
|
32127
|
+
usdc: parseFloat(ethers.formatUnits(usdcBalance, chain2.tokens.USDC.decimals)),
|
|
32128
|
+
usdt: parseFloat(ethers.formatUnits(usdtBalance, chain2.tokens.USDT.decimals)),
|
|
32129
|
+
native: parseFloat(ethers.formatEther(nativeBalance))
|
|
32130
|
+
};
|
|
32131
|
+
} catch (err) {
|
|
32132
|
+
results[chainName] = { usdc: 0, usdt: 0, native: 0 };
|
|
32133
|
+
}
|
|
32134
|
+
})
|
|
32135
|
+
);
|
|
32136
|
+
return results;
|
|
32137
|
+
}
|
|
31980
32138
|
};
|
|
31981
32139
|
|
|
31982
32140
|
// src/wallet/index.ts
|