moltspay 0.8.1 → 0.8.3
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 +10 -0
- package/dist/cli/index.js +141 -52
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +160 -65
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.js +237 -148
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +256 -167
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +14 -5
- package/dist/server/index.d.ts +14 -5
- package/dist/server/index.js +151 -112
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +149 -113
- package/dist/server/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.mjs
CHANGED
|
@@ -2891,7 +2891,7 @@ function alphabet(letters) {
|
|
|
2891
2891
|
};
|
|
2892
2892
|
}
|
|
2893
2893
|
// @__NO_SIDE_EFFECTS__
|
|
2894
|
-
function
|
|
2894
|
+
function join4(separator = "") {
|
|
2895
2895
|
astr("join", separator);
|
|
2896
2896
|
return {
|
|
2897
2897
|
encode: (from) => {
|
|
@@ -3098,10 +3098,10 @@ var init_esm = __esm({
|
|
|
3098
3098
|
convertRadix2,
|
|
3099
3099
|
radix,
|
|
3100
3100
|
radix2,
|
|
3101
|
-
join:
|
|
3101
|
+
join: join4,
|
|
3102
3102
|
padding
|
|
3103
3103
|
};
|
|
3104
|
-
genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */
|
|
3104
|
+
genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join4(""));
|
|
3105
3105
|
base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
|
|
3106
3106
|
createBase58check = (sha2566) => /* @__PURE__ */ chain(checksum(4, (data) => sha2566(sha2566(data))), base58);
|
|
3107
3107
|
}
|
|
@@ -3249,14 +3249,14 @@ var init_esm2 = __esm({
|
|
|
3249
3249
|
}
|
|
3250
3250
|
this.pubHash = hash160(this.pubKey);
|
|
3251
3251
|
}
|
|
3252
|
-
derive(
|
|
3253
|
-
if (!/^[mM]'?/.test(
|
|
3252
|
+
derive(path4) {
|
|
3253
|
+
if (!/^[mM]'?/.test(path4)) {
|
|
3254
3254
|
throw new Error('Path must start with "m" or "M"');
|
|
3255
3255
|
}
|
|
3256
|
-
if (/^[mM]'?$/.test(
|
|
3256
|
+
if (/^[mM]'?$/.test(path4)) {
|
|
3257
3257
|
return this;
|
|
3258
3258
|
}
|
|
3259
|
-
const parts =
|
|
3259
|
+
const parts = path4.replace(/^[mM]'?\//, "").split("/");
|
|
3260
3260
|
let child = this;
|
|
3261
3261
|
for (const c of parts) {
|
|
3262
3262
|
const m = /^(\d+)('?)$/.exec(c);
|
|
@@ -9617,8 +9617,8 @@ var init_privateKeyToAccount = __esm({
|
|
|
9617
9617
|
});
|
|
9618
9618
|
|
|
9619
9619
|
// node_modules/viem/_esm/accounts/hdKeyToAccount.js
|
|
9620
|
-
function hdKeyToAccount(hdKey_, { accountIndex = 0, addressIndex = 0, changeIndex = 0, path:
|
|
9621
|
-
const hdKey = hdKey_.derive(
|
|
9620
|
+
function hdKeyToAccount(hdKey_, { accountIndex = 0, addressIndex = 0, changeIndex = 0, path: path4, ...options } = {}) {
|
|
9621
|
+
const hdKey = hdKey_.derive(path4 || `m/44'/60'/${accountIndex}'/${changeIndex}/${addressIndex}`);
|
|
9622
9622
|
const account = privateKeyToAccount(toHex(hdKey.privateKey), options);
|
|
9623
9623
|
return {
|
|
9624
9624
|
...account,
|
|
@@ -30330,86 +30330,9 @@ init_esm_shims();
|
|
|
30330
30330
|
|
|
30331
30331
|
// src/server/index.ts
|
|
30332
30332
|
init_esm_shims();
|
|
30333
|
-
import { readFileSync } from "fs";
|
|
30333
|
+
import { readFileSync, existsSync } from "fs";
|
|
30334
30334
|
import { createServer } from "http";
|
|
30335
|
-
|
|
30336
|
-
// src/chains/index.ts
|
|
30337
|
-
init_esm_shims();
|
|
30338
|
-
var CHAINS = {
|
|
30339
|
-
// ============ Mainnet ============
|
|
30340
|
-
base: {
|
|
30341
|
-
name: "Base",
|
|
30342
|
-
chainId: 8453,
|
|
30343
|
-
rpc: "https://mainnet.base.org",
|
|
30344
|
-
usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
30345
|
-
explorer: "https://basescan.org/address/",
|
|
30346
|
-
explorerTx: "https://basescan.org/tx/",
|
|
30347
|
-
avgBlockTime: 2
|
|
30348
|
-
},
|
|
30349
|
-
polygon: {
|
|
30350
|
-
name: "Polygon",
|
|
30351
|
-
chainId: 137,
|
|
30352
|
-
rpc: "https://polygon-rpc.com",
|
|
30353
|
-
usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
30354
|
-
explorer: "https://polygonscan.com/address/",
|
|
30355
|
-
explorerTx: "https://polygonscan.com/tx/",
|
|
30356
|
-
avgBlockTime: 2
|
|
30357
|
-
},
|
|
30358
|
-
ethereum: {
|
|
30359
|
-
name: "Ethereum",
|
|
30360
|
-
chainId: 1,
|
|
30361
|
-
rpc: "https://eth.llamarpc.com",
|
|
30362
|
-
usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
30363
|
-
explorer: "https://etherscan.io/address/",
|
|
30364
|
-
explorerTx: "https://etherscan.io/tx/",
|
|
30365
|
-
avgBlockTime: 12
|
|
30366
|
-
},
|
|
30367
|
-
// ============ Testnet ============
|
|
30368
|
-
base_sepolia: {
|
|
30369
|
-
name: "Base Sepolia",
|
|
30370
|
-
chainId: 84532,
|
|
30371
|
-
rpc: "https://sepolia.base.org",
|
|
30372
|
-
usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
30373
|
-
explorer: "https://sepolia.basescan.org/address/",
|
|
30374
|
-
explorerTx: "https://sepolia.basescan.org/tx/",
|
|
30375
|
-
avgBlockTime: 2
|
|
30376
|
-
},
|
|
30377
|
-
sepolia: {
|
|
30378
|
-
name: "Sepolia",
|
|
30379
|
-
chainId: 11155111,
|
|
30380
|
-
rpc: "https://rpc.sepolia.org",
|
|
30381
|
-
usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
30382
|
-
explorer: "https://sepolia.etherscan.io/address/",
|
|
30383
|
-
explorerTx: "https://sepolia.etherscan.io/tx/",
|
|
30384
|
-
avgBlockTime: 12
|
|
30385
|
-
}
|
|
30386
|
-
};
|
|
30387
|
-
function getChain(name) {
|
|
30388
|
-
const config = CHAINS[name];
|
|
30389
|
-
if (!config) {
|
|
30390
|
-
throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(", ")}`);
|
|
30391
|
-
}
|
|
30392
|
-
return config;
|
|
30393
|
-
}
|
|
30394
|
-
function listChains() {
|
|
30395
|
-
return Object.keys(CHAINS);
|
|
30396
|
-
}
|
|
30397
|
-
function getChainById(chainId) {
|
|
30398
|
-
return Object.values(CHAINS).find((c) => c.chainId === chainId);
|
|
30399
|
-
}
|
|
30400
|
-
var ERC20_ABI = [
|
|
30401
|
-
"function balanceOf(address owner) view returns (uint256)",
|
|
30402
|
-
"function transfer(address to, uint256 amount) returns (bool)",
|
|
30403
|
-
"function approve(address spender, uint256 amount) returns (bool)",
|
|
30404
|
-
"function allowance(address owner, address spender) view returns (uint256)",
|
|
30405
|
-
"function decimals() view returns (uint8)",
|
|
30406
|
-
"function symbol() view returns (string)",
|
|
30407
|
-
"function name() view returns (string)",
|
|
30408
|
-
"function nonces(address owner) view returns (uint256)",
|
|
30409
|
-
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
|
|
30410
|
-
"event Transfer(address indexed from, address indexed to, uint256 value)",
|
|
30411
|
-
"event Approval(address indexed owner, address indexed spender, uint256 value)"
|
|
30412
|
-
];
|
|
30335
|
+
import * as path2 from "path";
|
|
30413
30336
|
|
|
30414
30337
|
// src/server/types.ts
|
|
30415
30338
|
init_esm_shims();
|
|
@@ -30419,24 +30342,100 @@ var X402_VERSION = 2;
|
|
|
30419
30342
|
var PAYMENT_REQUIRED_HEADER = "x-payment-required";
|
|
30420
30343
|
var PAYMENT_HEADER = "x-payment";
|
|
30421
30344
|
var PAYMENT_RESPONSE_HEADER = "x-payment-response";
|
|
30422
|
-
var
|
|
30345
|
+
var FACILITATOR_TESTNET = "https://www.x402.org/facilitator";
|
|
30346
|
+
var FACILITATOR_MAINNET = "https://api.cdp.coinbase.com/platform/v2/x402";
|
|
30347
|
+
var USDC_ADDRESSES = {
|
|
30348
|
+
"eip155:8453": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
30349
|
+
// Base mainnet
|
|
30350
|
+
"eip155:84532": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
30351
|
+
// Base Sepolia
|
|
30352
|
+
};
|
|
30353
|
+
var USDC_DOMAIN = {
|
|
30354
|
+
name: "USD Coin",
|
|
30355
|
+
version: "2"
|
|
30356
|
+
};
|
|
30357
|
+
function loadEnvFiles() {
|
|
30358
|
+
try {
|
|
30359
|
+
const dotenv = __require("dotenv");
|
|
30360
|
+
const envPaths = [
|
|
30361
|
+
path2.join(process.cwd(), ".env"),
|
|
30362
|
+
path2.join(process.env.HOME || "", ".moltspay", ".env")
|
|
30363
|
+
];
|
|
30364
|
+
for (const envPath of envPaths) {
|
|
30365
|
+
if (existsSync(envPath)) {
|
|
30366
|
+
dotenv.config({ path: envPath });
|
|
30367
|
+
console.log(`[MoltsPay] Loaded config from ${envPath}`);
|
|
30368
|
+
break;
|
|
30369
|
+
}
|
|
30370
|
+
}
|
|
30371
|
+
} catch {
|
|
30372
|
+
}
|
|
30373
|
+
}
|
|
30374
|
+
function getCDPConfig() {
|
|
30375
|
+
loadEnvFiles();
|
|
30376
|
+
return {
|
|
30377
|
+
useMainnet: process.env.USE_MAINNET?.toLowerCase() === "true",
|
|
30378
|
+
apiKeyId: process.env.CDP_API_KEY_ID,
|
|
30379
|
+
apiKeySecret: process.env.CDP_API_KEY_SECRET
|
|
30380
|
+
};
|
|
30381
|
+
}
|
|
30382
|
+
async function getCDPAuthHeaders(method, urlPath, body) {
|
|
30383
|
+
const config = getCDPConfig();
|
|
30384
|
+
if (!config.apiKeyId || !config.apiKeySecret) {
|
|
30385
|
+
throw new Error("CDP_API_KEY_ID and CDP_API_KEY_SECRET required for mainnet");
|
|
30386
|
+
}
|
|
30387
|
+
try {
|
|
30388
|
+
const { getAuthHeaders } = await import("@coinbase/cdp-sdk/auth");
|
|
30389
|
+
const headers = await getAuthHeaders({
|
|
30390
|
+
apiKeyId: config.apiKeyId,
|
|
30391
|
+
apiKeySecret: config.apiKeySecret,
|
|
30392
|
+
requestMethod: method,
|
|
30393
|
+
requestHost: "api.cdp.coinbase.com",
|
|
30394
|
+
requestPath: urlPath,
|
|
30395
|
+
requestBody: body
|
|
30396
|
+
});
|
|
30397
|
+
return headers;
|
|
30398
|
+
} catch (err) {
|
|
30399
|
+
console.error("[MoltsPay] Failed to generate CDP auth headers:", err.message);
|
|
30400
|
+
throw err;
|
|
30401
|
+
}
|
|
30402
|
+
}
|
|
30423
30403
|
var MoltsPayServer = class {
|
|
30424
30404
|
manifest;
|
|
30425
30405
|
skills = /* @__PURE__ */ new Map();
|
|
30426
30406
|
options;
|
|
30407
|
+
cdpConfig;
|
|
30427
30408
|
facilitatorUrl;
|
|
30409
|
+
networkId;
|
|
30428
30410
|
constructor(servicesPath, options = {}) {
|
|
30411
|
+
this.cdpConfig = getCDPConfig();
|
|
30429
30412
|
const content = readFileSync(servicesPath, "utf-8");
|
|
30430
30413
|
this.manifest = JSON.parse(content);
|
|
30431
30414
|
this.options = {
|
|
30432
30415
|
port: options.port || 3e3,
|
|
30433
30416
|
host: options.host || "0.0.0.0"
|
|
30434
30417
|
};
|
|
30435
|
-
this.
|
|
30418
|
+
if (this.cdpConfig.useMainnet) {
|
|
30419
|
+
if (!this.cdpConfig.apiKeyId || !this.cdpConfig.apiKeySecret) {
|
|
30420
|
+
console.warn("[MoltsPay] WARNING: USE_MAINNET=true but CDP keys not set!");
|
|
30421
|
+
console.warn("[MoltsPay] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET in ~/.moltspay/.env");
|
|
30422
|
+
}
|
|
30423
|
+
this.facilitatorUrl = FACILITATOR_MAINNET;
|
|
30424
|
+
this.networkId = "eip155:8453";
|
|
30425
|
+
} else {
|
|
30426
|
+
this.facilitatorUrl = options.facilitatorUrl || FACILITATOR_TESTNET;
|
|
30427
|
+
this.networkId = "eip155:84532";
|
|
30428
|
+
}
|
|
30429
|
+
const networkName = this.cdpConfig.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
|
|
30430
|
+
const facilitatorName = this.cdpConfig.useMainnet ? "CDP" : "x402.org";
|
|
30436
30431
|
console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);
|
|
30437
30432
|
console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);
|
|
30438
30433
|
console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);
|
|
30439
|
-
console.log(`[MoltsPay]
|
|
30434
|
+
console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);
|
|
30435
|
+
console.log(`[MoltsPay] Facilitator: ${facilitatorName} (${this.facilitatorUrl})`);
|
|
30436
|
+
if (this.cdpConfig.useMainnet && this.cdpConfig.apiKeyId) {
|
|
30437
|
+
console.log(`[MoltsPay] CDP API Key: ${this.cdpConfig.apiKeyId.slice(0, 8)}...`);
|
|
30438
|
+
}
|
|
30440
30439
|
console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);
|
|
30441
30440
|
}
|
|
30442
30441
|
/**
|
|
@@ -30497,7 +30496,6 @@ var MoltsPayServer = class {
|
|
|
30497
30496
|
* GET /services - List available services
|
|
30498
30497
|
*/
|
|
30499
30498
|
handleGetServices(res) {
|
|
30500
|
-
const chain2 = getChain(this.manifest.provider.chain);
|
|
30501
30499
|
const services = this.manifest.services.map((s) => ({
|
|
30502
30500
|
id: s.id,
|
|
30503
30501
|
name: s.name,
|
|
@@ -30513,16 +30511,15 @@ var MoltsPayServer = class {
|
|
|
30513
30511
|
services,
|
|
30514
30512
|
x402: {
|
|
30515
30513
|
version: X402_VERSION,
|
|
30516
|
-
network:
|
|
30514
|
+
network: this.networkId,
|
|
30517
30515
|
schemes: ["exact"],
|
|
30518
|
-
facilitator: this.
|
|
30516
|
+
facilitator: this.cdpConfig.useMainnet ? "cdp" : "x402.org",
|
|
30517
|
+
mainnet: this.cdpConfig.useMainnet
|
|
30519
30518
|
}
|
|
30520
30519
|
});
|
|
30521
30520
|
}
|
|
30522
30521
|
/**
|
|
30523
30522
|
* POST /execute - Execute service with x402 payment
|
|
30524
|
-
* Body: { service: string, params: object }
|
|
30525
|
-
* Header: X-Payment (optional - if missing, returns 402)
|
|
30526
30523
|
*/
|
|
30527
30524
|
async handleExecute(body, paymentHeader, res) {
|
|
30528
30525
|
const { service, params } = body;
|
|
@@ -30597,17 +30594,8 @@ var MoltsPayServer = class {
|
|
|
30597
30594
|
* Return 402 with x402 payment requirements
|
|
30598
30595
|
*/
|
|
30599
30596
|
sendPaymentRequired(config, res) {
|
|
30600
|
-
const
|
|
30601
|
-
|
|
30602
|
-
const requirements = [{
|
|
30603
|
-
scheme: "exact",
|
|
30604
|
-
network: `eip155:${chain2.chainId}`,
|
|
30605
|
-
maxAmountRequired: amountInUnits,
|
|
30606
|
-
resource: this.manifest.provider.wallet,
|
|
30607
|
-
description: `${config.name} - $${config.price} ${config.currency}`,
|
|
30608
|
-
// Include facilitator info for client
|
|
30609
|
-
extra: JSON.stringify({ facilitator: this.facilitatorUrl })
|
|
30610
|
-
}];
|
|
30597
|
+
const requirements = [this.buildPaymentRequirements(config)];
|
|
30598
|
+
requirements[0].description = `${config.name} - $${config.price} ${config.currency}`;
|
|
30611
30599
|
const encoded = Buffer.from(JSON.stringify(requirements)).toString("base64");
|
|
30612
30600
|
res.writeHead(402, {
|
|
30613
30601
|
"Content-Type": "application/json",
|
|
@@ -30620,7 +30608,7 @@ var MoltsPayServer = class {
|
|
|
30620
30608
|
}, null, 2));
|
|
30621
30609
|
}
|
|
30622
30610
|
/**
|
|
30623
|
-
* Basic payment validation
|
|
30611
|
+
* Basic payment validation
|
|
30624
30612
|
*/
|
|
30625
30613
|
validatePayment(payment, config) {
|
|
30626
30614
|
if (payment.x402Version !== X402_VERSION) {
|
|
@@ -30629,37 +30617,57 @@ var MoltsPayServer = class {
|
|
|
30629
30617
|
if (payment.scheme !== "exact") {
|
|
30630
30618
|
return { valid: false, error: `Unsupported scheme: ${payment.scheme}` };
|
|
30631
30619
|
}
|
|
30632
|
-
|
|
30633
|
-
|
|
30634
|
-
if (payment.network !== expectedNetwork) {
|
|
30635
|
-
return { valid: false, error: `Network mismatch: expected ${expectedNetwork}` };
|
|
30620
|
+
if (payment.network !== this.networkId) {
|
|
30621
|
+
return { valid: false, error: `Network mismatch: expected ${this.networkId}, got ${payment.network}` };
|
|
30636
30622
|
}
|
|
30637
30623
|
return { valid: true };
|
|
30638
30624
|
}
|
|
30639
30625
|
/**
|
|
30640
|
-
*
|
|
30626
|
+
* Build complete payment requirements for facilitator
|
|
30627
|
+
*/
|
|
30628
|
+
buildPaymentRequirements(config) {
|
|
30629
|
+
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
30630
|
+
const usdcAddress = USDC_ADDRESSES[this.networkId];
|
|
30631
|
+
return {
|
|
30632
|
+
scheme: "exact",
|
|
30633
|
+
network: this.networkId,
|
|
30634
|
+
maxAmountRequired: amountInUnits,
|
|
30635
|
+
amount: amountInUnits,
|
|
30636
|
+
asset: usdcAddress,
|
|
30637
|
+
payTo: this.manifest.provider.wallet,
|
|
30638
|
+
maxTimeoutSeconds: 300,
|
|
30639
|
+
extra: USDC_DOMAIN
|
|
30640
|
+
};
|
|
30641
|
+
}
|
|
30642
|
+
/**
|
|
30643
|
+
* Verify payment with facilitator (testnet or CDP)
|
|
30641
30644
|
*/
|
|
30642
30645
|
async verifyWithFacilitator(payment, config) {
|
|
30643
30646
|
try {
|
|
30644
|
-
const
|
|
30645
|
-
const
|
|
30646
|
-
|
|
30647
|
-
|
|
30648
|
-
network: `eip155:${chain2.chainId}`,
|
|
30649
|
-
maxAmountRequired: amountInUnits,
|
|
30650
|
-
resource: this.manifest.provider.wallet
|
|
30647
|
+
const requirements = this.buildPaymentRequirements(config);
|
|
30648
|
+
const requestBody = {
|
|
30649
|
+
paymentPayload: payment,
|
|
30650
|
+
paymentRequirements: requirements
|
|
30651
30651
|
};
|
|
30652
|
+
console.log("[MoltsPay] Verify request:", JSON.stringify(requestBody, null, 2));
|
|
30653
|
+
let headers = { "Content-Type": "application/json" };
|
|
30654
|
+
if (this.cdpConfig.useMainnet) {
|
|
30655
|
+
const authHeaders = await getCDPAuthHeaders(
|
|
30656
|
+
"POST",
|
|
30657
|
+
"/platform/v2/x402/verify",
|
|
30658
|
+
requestBody
|
|
30659
|
+
);
|
|
30660
|
+
headers = { ...headers, ...authHeaders };
|
|
30661
|
+
}
|
|
30652
30662
|
const response = await fetch(`${this.facilitatorUrl}/verify`, {
|
|
30653
30663
|
method: "POST",
|
|
30654
|
-
headers
|
|
30655
|
-
body: JSON.stringify(
|
|
30656
|
-
paymentPayload: payment,
|
|
30657
|
-
paymentRequirements: requirements
|
|
30658
|
-
})
|
|
30664
|
+
headers,
|
|
30665
|
+
body: JSON.stringify(requestBody)
|
|
30659
30666
|
});
|
|
30660
30667
|
const result = await response.json();
|
|
30668
|
+
console.log("[MoltsPay] Verify response:", JSON.stringify(result, null, 2));
|
|
30661
30669
|
if (!response.ok || !result.isValid) {
|
|
30662
|
-
return { valid: false, error: result.invalidReason || "Verification failed" };
|
|
30670
|
+
return { valid: false, error: result.invalidReason || result.error || "Verification failed" };
|
|
30663
30671
|
}
|
|
30664
30672
|
return { valid: true };
|
|
30665
30673
|
} catch (err) {
|
|
@@ -30670,25 +30678,28 @@ var MoltsPayServer = class {
|
|
|
30670
30678
|
* Settle payment with facilitator (execute on-chain transfer)
|
|
30671
30679
|
*/
|
|
30672
30680
|
async settleWithFacilitator(payment, config) {
|
|
30673
|
-
const
|
|
30674
|
-
const
|
|
30675
|
-
|
|
30676
|
-
|
|
30677
|
-
network: `eip155:${chain2.chainId}`,
|
|
30678
|
-
maxAmountRequired: amountInUnits,
|
|
30679
|
-
resource: this.manifest.provider.wallet
|
|
30681
|
+
const requirements = this.buildPaymentRequirements(config);
|
|
30682
|
+
const requestBody = {
|
|
30683
|
+
paymentPayload: payment,
|
|
30684
|
+
paymentRequirements: requirements
|
|
30680
30685
|
};
|
|
30686
|
+
let headers = { "Content-Type": "application/json" };
|
|
30687
|
+
if (this.cdpConfig.useMainnet) {
|
|
30688
|
+
const authHeaders = await getCDPAuthHeaders(
|
|
30689
|
+
"POST",
|
|
30690
|
+
"/platform/v2/x402/settle",
|
|
30691
|
+
requestBody
|
|
30692
|
+
);
|
|
30693
|
+
headers = { ...headers, ...authHeaders };
|
|
30694
|
+
}
|
|
30681
30695
|
const response = await fetch(`${this.facilitatorUrl}/settle`, {
|
|
30682
30696
|
method: "POST",
|
|
30683
|
-
headers
|
|
30684
|
-
body: JSON.stringify(
|
|
30685
|
-
paymentPayload: payment,
|
|
30686
|
-
paymentRequirements: requirements
|
|
30687
|
-
})
|
|
30697
|
+
headers,
|
|
30698
|
+
body: JSON.stringify(requestBody)
|
|
30688
30699
|
});
|
|
30689
30700
|
const result = await response.json();
|
|
30690
|
-
if (!response.ok) {
|
|
30691
|
-
throw new Error(result.error || "Settlement failed");
|
|
30701
|
+
if (!response.ok || !result.success) {
|
|
30702
|
+
throw new Error(result.error || result.errorReason || "Settlement failed");
|
|
30692
30703
|
}
|
|
30693
30704
|
return {
|
|
30694
30705
|
transaction: result.transaction,
|
|
@@ -30721,11 +30732,89 @@ var MoltsPayServer = class {
|
|
|
30721
30732
|
|
|
30722
30733
|
// src/client/index.ts
|
|
30723
30734
|
init_esm_shims();
|
|
30724
|
-
import { existsSync, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
30735
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
30725
30736
|
import { homedir } from "os";
|
|
30726
|
-
import { join } from "path";
|
|
30737
|
+
import { join as join2 } from "path";
|
|
30727
30738
|
import { Wallet, ethers } from "ethers";
|
|
30728
30739
|
|
|
30740
|
+
// src/chains/index.ts
|
|
30741
|
+
init_esm_shims();
|
|
30742
|
+
var CHAINS = {
|
|
30743
|
+
// ============ Mainnet ============
|
|
30744
|
+
base: {
|
|
30745
|
+
name: "Base",
|
|
30746
|
+
chainId: 8453,
|
|
30747
|
+
rpc: "https://mainnet.base.org",
|
|
30748
|
+
usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
30749
|
+
explorer: "https://basescan.org/address/",
|
|
30750
|
+
explorerTx: "https://basescan.org/tx/",
|
|
30751
|
+
avgBlockTime: 2
|
|
30752
|
+
},
|
|
30753
|
+
polygon: {
|
|
30754
|
+
name: "Polygon",
|
|
30755
|
+
chainId: 137,
|
|
30756
|
+
rpc: "https://polygon-rpc.com",
|
|
30757
|
+
usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
30758
|
+
explorer: "https://polygonscan.com/address/",
|
|
30759
|
+
explorerTx: "https://polygonscan.com/tx/",
|
|
30760
|
+
avgBlockTime: 2
|
|
30761
|
+
},
|
|
30762
|
+
ethereum: {
|
|
30763
|
+
name: "Ethereum",
|
|
30764
|
+
chainId: 1,
|
|
30765
|
+
rpc: "https://eth.llamarpc.com",
|
|
30766
|
+
usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
30767
|
+
explorer: "https://etherscan.io/address/",
|
|
30768
|
+
explorerTx: "https://etherscan.io/tx/",
|
|
30769
|
+
avgBlockTime: 12
|
|
30770
|
+
},
|
|
30771
|
+
// ============ Testnet ============
|
|
30772
|
+
base_sepolia: {
|
|
30773
|
+
name: "Base Sepolia",
|
|
30774
|
+
chainId: 84532,
|
|
30775
|
+
rpc: "https://sepolia.base.org",
|
|
30776
|
+
usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
30777
|
+
explorer: "https://sepolia.basescan.org/address/",
|
|
30778
|
+
explorerTx: "https://sepolia.basescan.org/tx/",
|
|
30779
|
+
avgBlockTime: 2
|
|
30780
|
+
},
|
|
30781
|
+
sepolia: {
|
|
30782
|
+
name: "Sepolia",
|
|
30783
|
+
chainId: 11155111,
|
|
30784
|
+
rpc: "https://rpc.sepolia.org",
|
|
30785
|
+
usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
30786
|
+
explorer: "https://sepolia.etherscan.io/address/",
|
|
30787
|
+
explorerTx: "https://sepolia.etherscan.io/tx/",
|
|
30788
|
+
avgBlockTime: 12
|
|
30789
|
+
}
|
|
30790
|
+
};
|
|
30791
|
+
function getChain(name) {
|
|
30792
|
+
const config = CHAINS[name];
|
|
30793
|
+
if (!config) {
|
|
30794
|
+
throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(", ")}`);
|
|
30795
|
+
}
|
|
30796
|
+
return config;
|
|
30797
|
+
}
|
|
30798
|
+
function listChains() {
|
|
30799
|
+
return Object.keys(CHAINS);
|
|
30800
|
+
}
|
|
30801
|
+
function getChainById(chainId) {
|
|
30802
|
+
return Object.values(CHAINS).find((c) => c.chainId === chainId);
|
|
30803
|
+
}
|
|
30804
|
+
var ERC20_ABI = [
|
|
30805
|
+
"function balanceOf(address owner) view returns (uint256)",
|
|
30806
|
+
"function transfer(address to, uint256 amount) returns (bool)",
|
|
30807
|
+
"function approve(address spender, uint256 amount) returns (bool)",
|
|
30808
|
+
"function allowance(address owner, address spender) view returns (uint256)",
|
|
30809
|
+
"function decimals() view returns (uint8)",
|
|
30810
|
+
"function symbol() view returns (string)",
|
|
30811
|
+
"function name() view returns (string)",
|
|
30812
|
+
"function nonces(address owner) view returns (uint256)",
|
|
30813
|
+
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
|
|
30814
|
+
"event Transfer(address indexed from, address indexed to, uint256 value)",
|
|
30815
|
+
"event Approval(address indexed owner, address indexed spender, uint256 value)"
|
|
30816
|
+
];
|
|
30817
|
+
|
|
30729
30818
|
// src/client/types.ts
|
|
30730
30819
|
init_esm_shims();
|
|
30731
30820
|
|
|
@@ -30748,7 +30837,7 @@ var MoltsPayClient = class {
|
|
|
30748
30837
|
todaySpending = 0;
|
|
30749
30838
|
lastSpendingReset = 0;
|
|
30750
30839
|
constructor(options = {}) {
|
|
30751
|
-
this.configDir = options.configDir ||
|
|
30840
|
+
this.configDir = options.configDir || join2(homedir(), ".moltspay");
|
|
30752
30841
|
this.config = this.loadConfig();
|
|
30753
30842
|
this.walletData = this.loadWallet();
|
|
30754
30843
|
if (this.walletData) {
|
|
@@ -30930,8 +31019,8 @@ var MoltsPayClient = class {
|
|
|
30930
31019
|
}
|
|
30931
31020
|
// --- Config & Wallet Management ---
|
|
30932
31021
|
loadConfig() {
|
|
30933
|
-
const configPath =
|
|
30934
|
-
if (
|
|
31022
|
+
const configPath = join2(this.configDir, "config.json");
|
|
31023
|
+
if (existsSync2(configPath)) {
|
|
30935
31024
|
const content = readFileSync2(configPath, "utf-8");
|
|
30936
31025
|
return { ...DEFAULT_CONFIG, ...JSON.parse(content) };
|
|
30937
31026
|
}
|
|
@@ -30939,12 +31028,12 @@ var MoltsPayClient = class {
|
|
|
30939
31028
|
}
|
|
30940
31029
|
saveConfig() {
|
|
30941
31030
|
mkdirSync(this.configDir, { recursive: true });
|
|
30942
|
-
const configPath =
|
|
31031
|
+
const configPath = join2(this.configDir, "config.json");
|
|
30943
31032
|
writeFileSync(configPath, JSON.stringify(this.config, null, 2));
|
|
30944
31033
|
}
|
|
30945
31034
|
loadWallet() {
|
|
30946
|
-
const walletPath =
|
|
30947
|
-
if (
|
|
31035
|
+
const walletPath = join2(this.configDir, "wallet.json");
|
|
31036
|
+
if (existsSync2(walletPath)) {
|
|
30948
31037
|
const content = readFileSync2(walletPath, "utf-8");
|
|
30949
31038
|
return JSON.parse(content);
|
|
30950
31039
|
}
|
|
@@ -30961,7 +31050,7 @@ var MoltsPayClient = class {
|
|
|
30961
31050
|
privateKey: wallet.privateKey,
|
|
30962
31051
|
createdAt: Date.now()
|
|
30963
31052
|
};
|
|
30964
|
-
const walletPath =
|
|
31053
|
+
const walletPath = join2(configDir, "wallet.json");
|
|
30965
31054
|
writeFileSync(walletPath, JSON.stringify(walletData, null, 2));
|
|
30966
31055
|
const config = {
|
|
30967
31056
|
chain: options.chain,
|
|
@@ -30970,7 +31059,7 @@ var MoltsPayClient = class {
|
|
|
30970
31059
|
maxPerDay: options.maxPerDay
|
|
30971
31060
|
}
|
|
30972
31061
|
};
|
|
30973
|
-
const configPath =
|
|
31062
|
+
const configPath = join2(configDir, "config.json");
|
|
30974
31063
|
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
30975
31064
|
return { address: wallet.address, configDir };
|
|
30976
31065
|
}
|
|
@@ -31009,10 +31098,10 @@ import { ethers as ethers2 } from "ethers";
|
|
|
31009
31098
|
// src/wallet/createWallet.ts
|
|
31010
31099
|
init_esm_shims();
|
|
31011
31100
|
import { ethers as ethers3 } from "ethers";
|
|
31012
|
-
import { writeFileSync as writeFileSync2, readFileSync as readFileSync3, existsSync as
|
|
31013
|
-
import { join as
|
|
31101
|
+
import { writeFileSync as writeFileSync2, readFileSync as readFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
31102
|
+
import { join as join3, dirname } from "path";
|
|
31014
31103
|
import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from "crypto";
|
|
31015
|
-
var DEFAULT_STORAGE_DIR =
|
|
31104
|
+
var DEFAULT_STORAGE_DIR = join3(process.env.HOME || "~", ".moltspay");
|
|
31016
31105
|
var DEFAULT_STORAGE_FILE = "wallet.json";
|
|
31017
31106
|
function encryptPrivateKey(privateKey, password) {
|
|
31018
31107
|
const salt = randomBytes(16);
|
|
@@ -31035,8 +31124,8 @@ function decryptPrivateKey(encrypted, password, iv, salt) {
|
|
|
31035
31124
|
return decrypted;
|
|
31036
31125
|
}
|
|
31037
31126
|
function createWallet(options = {}) {
|
|
31038
|
-
const storagePath = options.storagePath ||
|
|
31039
|
-
if (
|
|
31127
|
+
const storagePath = options.storagePath || join3(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
31128
|
+
if (existsSync3(storagePath) && !options.overwrite) {
|
|
31040
31129
|
try {
|
|
31041
31130
|
const existing = JSON.parse(readFileSync3(storagePath, "utf8"));
|
|
31042
31131
|
return {
|
|
@@ -31070,7 +31159,7 @@ function createWallet(options = {}) {
|
|
|
31070
31159
|
walletData.privateKey = wallet.privateKey;
|
|
31071
31160
|
}
|
|
31072
31161
|
const dir = dirname(storagePath);
|
|
31073
|
-
if (!
|
|
31162
|
+
if (!existsSync3(dir)) {
|
|
31074
31163
|
mkdirSync2(dir, { recursive: true });
|
|
31075
31164
|
}
|
|
31076
31165
|
writeFileSync2(storagePath, JSON.stringify(walletData, null, 2), { mode: 384 });
|
|
@@ -31088,8 +31177,8 @@ function createWallet(options = {}) {
|
|
|
31088
31177
|
}
|
|
31089
31178
|
}
|
|
31090
31179
|
function loadWallet(options = {}) {
|
|
31091
|
-
const storagePath = options.storagePath ||
|
|
31092
|
-
if (!
|
|
31180
|
+
const storagePath = options.storagePath || join3(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
31181
|
+
if (!existsSync3(storagePath)) {
|
|
31093
31182
|
return { success: false, error: "Wallet not found. Run createWallet() first." };
|
|
31094
31183
|
}
|
|
31095
31184
|
try {
|
|
@@ -31108,20 +31197,20 @@ function loadWallet(options = {}) {
|
|
|
31108
31197
|
}
|
|
31109
31198
|
}
|
|
31110
31199
|
function getWalletAddress(storagePath) {
|
|
31111
|
-
const
|
|
31112
|
-
if (!
|
|
31200
|
+
const path4 = storagePath || join3(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
31201
|
+
if (!existsSync3(path4)) {
|
|
31113
31202
|
return null;
|
|
31114
31203
|
}
|
|
31115
31204
|
try {
|
|
31116
|
-
const data = JSON.parse(readFileSync3(
|
|
31205
|
+
const data = JSON.parse(readFileSync3(path4, "utf8"));
|
|
31117
31206
|
return data.address;
|
|
31118
31207
|
} catch {
|
|
31119
31208
|
return null;
|
|
31120
31209
|
}
|
|
31121
31210
|
}
|
|
31122
31211
|
function walletExists(storagePath) {
|
|
31123
|
-
const
|
|
31124
|
-
return
|
|
31212
|
+
const path4 = storagePath || join3(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
31213
|
+
return existsSync3(path4);
|
|
31125
31214
|
}
|
|
31126
31215
|
|
|
31127
31216
|
// src/verify/index.ts
|
|
@@ -31264,8 +31353,8 @@ async function waitForTransaction(txHash, chain2 = "base", confirmations = 1, ti
|
|
|
31264
31353
|
// src/cdp/index.ts
|
|
31265
31354
|
init_esm_shims();
|
|
31266
31355
|
import * as fs from "fs";
|
|
31267
|
-
import * as
|
|
31268
|
-
var DEFAULT_STORAGE_DIR2 =
|
|
31356
|
+
import * as path3 from "path";
|
|
31357
|
+
var DEFAULT_STORAGE_DIR2 = path3.join(process.env.HOME || ".", ".moltspay");
|
|
31269
31358
|
var CDP_CONFIG_FILE = "cdp-wallet.json";
|
|
31270
31359
|
function isCDPAvailable() {
|
|
31271
31360
|
try {
|
|
@@ -31287,7 +31376,7 @@ function getCDPCredentials(config) {
|
|
|
31287
31376
|
async function initCDPWallet(config = {}) {
|
|
31288
31377
|
const storageDir = config.storageDir || DEFAULT_STORAGE_DIR2;
|
|
31289
31378
|
const chain2 = config.chain || "base";
|
|
31290
|
-
const storagePath =
|
|
31379
|
+
const storagePath = path3.join(storageDir, CDP_CONFIG_FILE);
|
|
31291
31380
|
if (fs.existsSync(storagePath)) {
|
|
31292
31381
|
try {
|
|
31293
31382
|
const data = JSON.parse(fs.readFileSync(storagePath, "utf-8"));
|
|
@@ -31349,7 +31438,7 @@ async function initCDPWallet(config = {}) {
|
|
|
31349
31438
|
}
|
|
31350
31439
|
function loadCDPWallet(config = {}) {
|
|
31351
31440
|
const storageDir = config.storageDir || DEFAULT_STORAGE_DIR2;
|
|
31352
|
-
const storagePath =
|
|
31441
|
+
const storagePath = path3.join(storageDir, CDP_CONFIG_FILE);
|
|
31353
31442
|
if (!fs.existsSync(storagePath)) {
|
|
31354
31443
|
return null;
|
|
31355
31444
|
}
|