moltspay 0.8.0 → 0.8.2
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 +207 -98
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +226 -111
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.js +321 -211
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +338 -228
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +23 -11
- package/dist/server/index.d.ts +23 -11
- package/dist/server/index.js +213 -153
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +211 -154
- 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,87 +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
|
-
import
|
|
30336
|
-
|
|
30337
|
-
// src/chains/index.ts
|
|
30338
|
-
init_esm_shims();
|
|
30339
|
-
var CHAINS = {
|
|
30340
|
-
// ============ Mainnet ============
|
|
30341
|
-
base: {
|
|
30342
|
-
name: "Base",
|
|
30343
|
-
chainId: 8453,
|
|
30344
|
-
rpc: "https://mainnet.base.org",
|
|
30345
|
-
usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
30346
|
-
explorer: "https://basescan.org/address/",
|
|
30347
|
-
explorerTx: "https://basescan.org/tx/",
|
|
30348
|
-
avgBlockTime: 2
|
|
30349
|
-
},
|
|
30350
|
-
polygon: {
|
|
30351
|
-
name: "Polygon",
|
|
30352
|
-
chainId: 137,
|
|
30353
|
-
rpc: "https://polygon-rpc.com",
|
|
30354
|
-
usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
30355
|
-
explorer: "https://polygonscan.com/address/",
|
|
30356
|
-
explorerTx: "https://polygonscan.com/tx/",
|
|
30357
|
-
avgBlockTime: 2
|
|
30358
|
-
},
|
|
30359
|
-
ethereum: {
|
|
30360
|
-
name: "Ethereum",
|
|
30361
|
-
chainId: 1,
|
|
30362
|
-
rpc: "https://eth.llamarpc.com",
|
|
30363
|
-
usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
30364
|
-
explorer: "https://etherscan.io/address/",
|
|
30365
|
-
explorerTx: "https://etherscan.io/tx/",
|
|
30366
|
-
avgBlockTime: 12
|
|
30367
|
-
},
|
|
30368
|
-
// ============ Testnet ============
|
|
30369
|
-
base_sepolia: {
|
|
30370
|
-
name: "Base Sepolia",
|
|
30371
|
-
chainId: 84532,
|
|
30372
|
-
rpc: "https://sepolia.base.org",
|
|
30373
|
-
usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
30374
|
-
explorer: "https://sepolia.basescan.org/address/",
|
|
30375
|
-
explorerTx: "https://sepolia.basescan.org/tx/",
|
|
30376
|
-
avgBlockTime: 2
|
|
30377
|
-
},
|
|
30378
|
-
sepolia: {
|
|
30379
|
-
name: "Sepolia",
|
|
30380
|
-
chainId: 11155111,
|
|
30381
|
-
rpc: "https://rpc.sepolia.org",
|
|
30382
|
-
usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
30383
|
-
explorer: "https://sepolia.etherscan.io/address/",
|
|
30384
|
-
explorerTx: "https://sepolia.etherscan.io/tx/",
|
|
30385
|
-
avgBlockTime: 12
|
|
30386
|
-
}
|
|
30387
|
-
};
|
|
30388
|
-
function getChain(name) {
|
|
30389
|
-
const config = CHAINS[name];
|
|
30390
|
-
if (!config) {
|
|
30391
|
-
throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(", ")}`);
|
|
30392
|
-
}
|
|
30393
|
-
return config;
|
|
30394
|
-
}
|
|
30395
|
-
function listChains() {
|
|
30396
|
-
return Object.keys(CHAINS);
|
|
30397
|
-
}
|
|
30398
|
-
function getChainById(chainId) {
|
|
30399
|
-
return Object.values(CHAINS).find((c) => c.chainId === chainId);
|
|
30400
|
-
}
|
|
30401
|
-
var ERC20_ABI = [
|
|
30402
|
-
"function balanceOf(address owner) view returns (uint256)",
|
|
30403
|
-
"function transfer(address to, uint256 amount) returns (bool)",
|
|
30404
|
-
"function approve(address spender, uint256 amount) returns (bool)",
|
|
30405
|
-
"function allowance(address owner, address spender) view returns (uint256)",
|
|
30406
|
-
"function decimals() view returns (uint8)",
|
|
30407
|
-
"function symbol() view returns (string)",
|
|
30408
|
-
"function name() view returns (string)",
|
|
30409
|
-
"function nonces(address owner) view returns (uint256)",
|
|
30410
|
-
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
|
|
30411
|
-
"event Transfer(address indexed from, address indexed to, uint256 value)",
|
|
30412
|
-
"event Approval(address indexed owner, address indexed spender, uint256 value)"
|
|
30413
|
-
];
|
|
30335
|
+
import * as path2 from "path";
|
|
30414
30336
|
|
|
30415
30337
|
// src/server/types.ts
|
|
30416
30338
|
init_esm_shims();
|
|
@@ -30419,34 +30341,92 @@ init_esm_shims();
|
|
|
30419
30341
|
var X402_VERSION = 2;
|
|
30420
30342
|
var PAYMENT_REQUIRED_HEADER = "x-payment-required";
|
|
30421
30343
|
var PAYMENT_HEADER = "x-payment";
|
|
30344
|
+
var PAYMENT_RESPONSE_HEADER = "x-payment-response";
|
|
30345
|
+
var FACILITATOR_TESTNET = "https://www.x402.org/facilitator";
|
|
30346
|
+
var FACILITATOR_MAINNET = "https://api.cdp.coinbase.com/platform/v2/x402";
|
|
30347
|
+
function loadEnvFiles() {
|
|
30348
|
+
try {
|
|
30349
|
+
const dotenv = __require("dotenv");
|
|
30350
|
+
const envPaths = [
|
|
30351
|
+
path2.join(process.cwd(), ".env"),
|
|
30352
|
+
path2.join(process.env.HOME || "", ".moltspay", ".env")
|
|
30353
|
+
];
|
|
30354
|
+
for (const envPath of envPaths) {
|
|
30355
|
+
if (existsSync(envPath)) {
|
|
30356
|
+
dotenv.config({ path: envPath });
|
|
30357
|
+
console.log(`[MoltsPay] Loaded config from ${envPath}`);
|
|
30358
|
+
break;
|
|
30359
|
+
}
|
|
30360
|
+
}
|
|
30361
|
+
} catch {
|
|
30362
|
+
}
|
|
30363
|
+
}
|
|
30364
|
+
function getCDPConfig() {
|
|
30365
|
+
loadEnvFiles();
|
|
30366
|
+
return {
|
|
30367
|
+
useMainnet: process.env.USE_MAINNET?.toLowerCase() === "true",
|
|
30368
|
+
apiKeyId: process.env.CDP_API_KEY_ID,
|
|
30369
|
+
apiKeySecret: process.env.CDP_API_KEY_SECRET
|
|
30370
|
+
};
|
|
30371
|
+
}
|
|
30372
|
+
async function getCDPAuthHeaders(method, urlPath, body) {
|
|
30373
|
+
const config = getCDPConfig();
|
|
30374
|
+
if (!config.apiKeyId || !config.apiKeySecret) {
|
|
30375
|
+
throw new Error("CDP_API_KEY_ID and CDP_API_KEY_SECRET required for mainnet");
|
|
30376
|
+
}
|
|
30377
|
+
try {
|
|
30378
|
+
const { getAuthHeaders } = await import("@coinbase/cdp-sdk/auth");
|
|
30379
|
+
const headers = await getAuthHeaders({
|
|
30380
|
+
apiKeyId: config.apiKeyId,
|
|
30381
|
+
apiKeySecret: config.apiKeySecret,
|
|
30382
|
+
requestMethod: method,
|
|
30383
|
+
requestHost: "api.cdp.coinbase.com",
|
|
30384
|
+
requestPath: urlPath,
|
|
30385
|
+
requestBody: body
|
|
30386
|
+
});
|
|
30387
|
+
return headers;
|
|
30388
|
+
} catch (err) {
|
|
30389
|
+
console.error("[MoltsPay] Failed to generate CDP auth headers:", err.message);
|
|
30390
|
+
throw err;
|
|
30391
|
+
}
|
|
30392
|
+
}
|
|
30422
30393
|
var MoltsPayServer = class {
|
|
30423
30394
|
manifest;
|
|
30424
30395
|
skills = /* @__PURE__ */ new Map();
|
|
30425
30396
|
options;
|
|
30426
|
-
|
|
30427
|
-
|
|
30397
|
+
cdpConfig;
|
|
30398
|
+
facilitatorUrl;
|
|
30399
|
+
networkId;
|
|
30428
30400
|
constructor(servicesPath, options = {}) {
|
|
30401
|
+
this.cdpConfig = getCDPConfig();
|
|
30429
30402
|
const content = readFileSync(servicesPath, "utf-8");
|
|
30430
30403
|
this.manifest = JSON.parse(content);
|
|
30431
30404
|
this.options = {
|
|
30432
30405
|
port: options.port || 3e3,
|
|
30433
|
-
host: options.host || "0.0.0.0"
|
|
30434
|
-
privateKey: options.privateKey || process.env.MOLTSPAY_PRIVATE_KEY
|
|
30406
|
+
host: options.host || "0.0.0.0"
|
|
30435
30407
|
};
|
|
30436
|
-
if (this.
|
|
30437
|
-
|
|
30438
|
-
|
|
30439
|
-
|
|
30440
|
-
this.wallet = new ethers.Wallet(this.options.privateKey, this.provider);
|
|
30441
|
-
console.log(`[MoltsPay] Payment wallet: ${this.wallet.address}`);
|
|
30442
|
-
} catch (err) {
|
|
30443
|
-
console.warn("[MoltsPay] Warning: Could not initialize wallet for payment claims");
|
|
30408
|
+
if (this.cdpConfig.useMainnet) {
|
|
30409
|
+
if (!this.cdpConfig.apiKeyId || !this.cdpConfig.apiKeySecret) {
|
|
30410
|
+
console.warn("[MoltsPay] WARNING: USE_MAINNET=true but CDP keys not set!");
|
|
30411
|
+
console.warn("[MoltsPay] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET in ~/.moltspay/.env");
|
|
30444
30412
|
}
|
|
30413
|
+
this.facilitatorUrl = FACILITATOR_MAINNET;
|
|
30414
|
+
this.networkId = "eip155:8453";
|
|
30415
|
+
} else {
|
|
30416
|
+
this.facilitatorUrl = options.facilitatorUrl || FACILITATOR_TESTNET;
|
|
30417
|
+
this.networkId = "eip155:84532";
|
|
30445
30418
|
}
|
|
30419
|
+
const networkName = this.cdpConfig.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
|
|
30420
|
+
const facilitatorName = this.cdpConfig.useMainnet ? "CDP" : "x402.org";
|
|
30446
30421
|
console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);
|
|
30447
30422
|
console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);
|
|
30448
30423
|
console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);
|
|
30449
|
-
console.log(`[MoltsPay]
|
|
30424
|
+
console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);
|
|
30425
|
+
console.log(`[MoltsPay] Facilitator: ${facilitatorName} (${this.facilitatorUrl})`);
|
|
30426
|
+
if (this.cdpConfig.useMainnet && this.cdpConfig.apiKeyId) {
|
|
30427
|
+
console.log(`[MoltsPay] CDP API Key: ${this.cdpConfig.apiKeyId.slice(0, 8)}...`);
|
|
30428
|
+
}
|
|
30429
|
+
console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);
|
|
30450
30430
|
}
|
|
30451
30431
|
/**
|
|
30452
30432
|
* Register a skill handler for a service
|
|
@@ -30456,48 +30436,45 @@ var MoltsPayServer = class {
|
|
|
30456
30436
|
if (!config) {
|
|
30457
30437
|
throw new Error(`Service '${serviceId}' not found in manifest`);
|
|
30458
30438
|
}
|
|
30459
|
-
this.skills.set(serviceId, {
|
|
30460
|
-
id: serviceId,
|
|
30461
|
-
config,
|
|
30462
|
-
handler
|
|
30463
|
-
});
|
|
30464
|
-
console.log(`[MoltsPay] Registered skill: ${serviceId} ($${config.price} ${config.currency})`);
|
|
30439
|
+
this.skills.set(serviceId, { id: serviceId, config, handler });
|
|
30465
30440
|
return this;
|
|
30466
30441
|
}
|
|
30467
30442
|
/**
|
|
30468
|
-
* Start
|
|
30443
|
+
* Start HTTP server
|
|
30469
30444
|
*/
|
|
30470
30445
|
listen(port) {
|
|
30471
|
-
const p = port || this.options.port;
|
|
30446
|
+
const p = port || this.options.port || 3e3;
|
|
30447
|
+
const host = this.options.host || "0.0.0.0";
|
|
30472
30448
|
const server = createServer((req, res) => this.handleRequest(req, res));
|
|
30473
|
-
server.listen(p,
|
|
30474
|
-
console.log(`[MoltsPay] Server listening on http://${
|
|
30449
|
+
server.listen(p, host, () => {
|
|
30450
|
+
console.log(`[MoltsPay] Server listening on http://${host}:${p}`);
|
|
30475
30451
|
console.log(`[MoltsPay] Endpoints:`);
|
|
30476
30452
|
console.log(` GET /services - List available services`);
|
|
30477
30453
|
console.log(` POST /execute - Execute service (x402 payment)`);
|
|
30478
30454
|
});
|
|
30479
30455
|
}
|
|
30456
|
+
/**
|
|
30457
|
+
* Handle incoming request
|
|
30458
|
+
*/
|
|
30480
30459
|
async handleRequest(req, res) {
|
|
30481
|
-
const url = new URL(req.url || "/", `http://${req.headers.host}`);
|
|
30482
|
-
const path3 = url.pathname;
|
|
30483
|
-
const method = req.method || "GET";
|
|
30484
30460
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
30485
30461
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
30486
30462
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Payment");
|
|
30487
30463
|
res.setHeader("Access-Control-Expose-Headers", "X-Payment-Required, X-Payment-Response");
|
|
30488
|
-
if (method === "OPTIONS") {
|
|
30464
|
+
if (req.method === "OPTIONS") {
|
|
30489
30465
|
res.writeHead(204);
|
|
30490
30466
|
res.end();
|
|
30491
30467
|
return;
|
|
30492
30468
|
}
|
|
30493
30469
|
try {
|
|
30494
|
-
|
|
30470
|
+
const url = new URL(req.url || "/", `http://${req.headers.host}`);
|
|
30471
|
+
if (url.pathname === "/services" && req.method === "GET") {
|
|
30495
30472
|
return this.handleGetServices(res);
|
|
30496
30473
|
}
|
|
30497
|
-
if (
|
|
30474
|
+
if (url.pathname === "/execute" && req.method === "POST") {
|
|
30498
30475
|
const body = await this.readBody(req);
|
|
30499
30476
|
const paymentHeader = req.headers[PAYMENT_HEADER];
|
|
30500
|
-
return this.handleExecute(body, paymentHeader, res);
|
|
30477
|
+
return await this.handleExecute(body, paymentHeader, res);
|
|
30501
30478
|
}
|
|
30502
30479
|
this.sendJson(res, 404, { error: "Not found" });
|
|
30503
30480
|
} catch (err) {
|
|
@@ -30509,7 +30486,6 @@ var MoltsPayServer = class {
|
|
|
30509
30486
|
* GET /services - List available services
|
|
30510
30487
|
*/
|
|
30511
30488
|
handleGetServices(res) {
|
|
30512
|
-
const chain2 = getChain(this.manifest.provider.chain);
|
|
30513
30489
|
const services = this.manifest.services.map((s) => ({
|
|
30514
30490
|
id: s.id,
|
|
30515
30491
|
name: s.name,
|
|
@@ -30525,15 +30501,15 @@ var MoltsPayServer = class {
|
|
|
30525
30501
|
services,
|
|
30526
30502
|
x402: {
|
|
30527
30503
|
version: X402_VERSION,
|
|
30528
|
-
network:
|
|
30529
|
-
schemes: ["exact"]
|
|
30504
|
+
network: this.networkId,
|
|
30505
|
+
schemes: ["exact"],
|
|
30506
|
+
facilitator: this.cdpConfig.useMainnet ? "cdp" : "x402.org",
|
|
30507
|
+
mainnet: this.cdpConfig.useMainnet
|
|
30530
30508
|
}
|
|
30531
30509
|
});
|
|
30532
30510
|
}
|
|
30533
30511
|
/**
|
|
30534
30512
|
* POST /execute - Execute service with x402 payment
|
|
30535
|
-
* Body: { service: string, params: object }
|
|
30536
|
-
* Header: X-Payment (optional - if missing, returns 402)
|
|
30537
30513
|
*/
|
|
30538
30514
|
async handleExecute(body, paymentHeader, res) {
|
|
30539
30515
|
const { service, params } = body;
|
|
@@ -30563,6 +30539,11 @@ var MoltsPayServer = class {
|
|
|
30563
30539
|
if (!validation.valid) {
|
|
30564
30540
|
return this.sendJson(res, 402, { error: validation.error });
|
|
30565
30541
|
}
|
|
30542
|
+
console.log(`[MoltsPay] Verifying payment with facilitator...`);
|
|
30543
|
+
const verifyResult = await this.verifyWithFacilitator(payment, skill.config);
|
|
30544
|
+
if (!verifyResult.valid) {
|
|
30545
|
+
return this.sendJson(res, 402, { error: `Payment verification failed: ${verifyResult.error}` });
|
|
30546
|
+
}
|
|
30566
30547
|
console.log(`[MoltsPay] Executing skill: ${service}`);
|
|
30567
30548
|
let result;
|
|
30568
30549
|
try {
|
|
@@ -30574,32 +30555,46 @@ var MoltsPayServer = class {
|
|
|
30574
30555
|
message: err.message
|
|
30575
30556
|
});
|
|
30576
30557
|
}
|
|
30577
|
-
console.log(`[MoltsPay] Skill succeeded,
|
|
30578
|
-
let
|
|
30558
|
+
console.log(`[MoltsPay] Skill succeeded, settling payment...`);
|
|
30559
|
+
let settlement = null;
|
|
30579
30560
|
try {
|
|
30580
|
-
|
|
30581
|
-
console.log(`[MoltsPay] Payment
|
|
30561
|
+
settlement = await this.settleWithFacilitator(payment, skill.config);
|
|
30562
|
+
console.log(`[MoltsPay] Payment settled: ${settlement.transaction || "pending"}`);
|
|
30582
30563
|
} catch (err) {
|
|
30583
|
-
console.error("[MoltsPay]
|
|
30564
|
+
console.error("[MoltsPay] Settlement failed:", err.message);
|
|
30565
|
+
}
|
|
30566
|
+
const responseHeaders = {};
|
|
30567
|
+
if (settlement) {
|
|
30568
|
+
const responsePayload = {
|
|
30569
|
+
success: true,
|
|
30570
|
+
transaction: settlement.transaction,
|
|
30571
|
+
network: payment.network
|
|
30572
|
+
};
|
|
30573
|
+
responseHeaders[PAYMENT_RESPONSE_HEADER] = Buffer.from(
|
|
30574
|
+
JSON.stringify(responsePayload)
|
|
30575
|
+
).toString("base64");
|
|
30584
30576
|
}
|
|
30585
30577
|
this.sendJson(res, 200, {
|
|
30586
30578
|
success: true,
|
|
30587
30579
|
result,
|
|
30588
|
-
payment:
|
|
30589
|
-
});
|
|
30580
|
+
payment: settlement ? { transaction: settlement.transaction, status: "settled" } : { status: "pending" }
|
|
30581
|
+
}, responseHeaders);
|
|
30590
30582
|
}
|
|
30591
30583
|
/**
|
|
30592
30584
|
* Return 402 with x402 payment requirements
|
|
30593
30585
|
*/
|
|
30594
30586
|
sendPaymentRequired(config, res) {
|
|
30595
|
-
const chain2 = getChain(this.manifest.provider.chain);
|
|
30596
30587
|
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
30597
30588
|
const requirements = [{
|
|
30598
30589
|
scheme: "exact",
|
|
30599
|
-
network:
|
|
30590
|
+
network: this.networkId,
|
|
30600
30591
|
maxAmountRequired: amountInUnits,
|
|
30601
30592
|
resource: this.manifest.provider.wallet,
|
|
30602
|
-
description: `${config.name} - $${config.price} ${config.currency}
|
|
30593
|
+
description: `${config.name} - $${config.price} ${config.currency}`,
|
|
30594
|
+
extra: JSON.stringify({
|
|
30595
|
+
facilitator: this.cdpConfig.useMainnet ? "cdp" : "x402.org",
|
|
30596
|
+
mainnet: this.cdpConfig.useMainnet
|
|
30597
|
+
})
|
|
30603
30598
|
}];
|
|
30604
30599
|
const encoded = Buffer.from(JSON.stringify(requirements)).toString("base64");
|
|
30605
30600
|
res.writeHead(402, {
|
|
@@ -30613,7 +30608,7 @@ var MoltsPayServer = class {
|
|
|
30613
30608
|
}, null, 2));
|
|
30614
30609
|
}
|
|
30615
30610
|
/**
|
|
30616
|
-
*
|
|
30611
|
+
* Basic payment validation
|
|
30617
30612
|
*/
|
|
30618
30613
|
validatePayment(payment, config) {
|
|
30619
30614
|
if (payment.x402Version !== X402_VERSION) {
|
|
@@ -30622,56 +30617,89 @@ var MoltsPayServer = class {
|
|
|
30622
30617
|
if (payment.scheme !== "exact") {
|
|
30623
30618
|
return { valid: false, error: `Unsupported scheme: ${payment.scheme}` };
|
|
30624
30619
|
}
|
|
30625
|
-
|
|
30626
|
-
|
|
30627
|
-
if (payment.network !== expectedNetwork) {
|
|
30628
|
-
return { valid: false, error: `Network mismatch: expected ${expectedNetwork}` };
|
|
30629
|
-
}
|
|
30630
|
-
const auth = payment.payload.authorization;
|
|
30631
|
-
if (auth.to.toLowerCase() !== this.manifest.provider.wallet.toLowerCase()) {
|
|
30632
|
-
return { valid: false, error: "Payment recipient mismatch" };
|
|
30633
|
-
}
|
|
30634
|
-
const amount = Number(auth.value) / 1e6;
|
|
30635
|
-
if (amount < config.price) {
|
|
30636
|
-
return { valid: false, error: `Insufficient amount: $${amount} < $${config.price}` };
|
|
30637
|
-
}
|
|
30638
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
30639
|
-
if (Number(auth.validBefore) < now) {
|
|
30640
|
-
return { valid: false, error: "Payment authorization expired" };
|
|
30641
|
-
}
|
|
30642
|
-
if (Number(auth.validAfter) > now) {
|
|
30643
|
-
return { valid: false, error: "Payment authorization not yet valid" };
|
|
30620
|
+
if (payment.network !== this.networkId) {
|
|
30621
|
+
return { valid: false, error: `Network mismatch: expected ${this.networkId}, got ${payment.network}` };
|
|
30644
30622
|
}
|
|
30645
30623
|
return { valid: true };
|
|
30646
30624
|
}
|
|
30647
30625
|
/**
|
|
30648
|
-
*
|
|
30626
|
+
* Verify payment with facilitator (testnet or CDP)
|
|
30649
30627
|
*/
|
|
30650
|
-
async
|
|
30651
|
-
|
|
30652
|
-
|
|
30628
|
+
async verifyWithFacilitator(payment, config) {
|
|
30629
|
+
try {
|
|
30630
|
+
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
30631
|
+
const requirements = {
|
|
30632
|
+
scheme: "exact",
|
|
30633
|
+
network: this.networkId,
|
|
30634
|
+
maxAmountRequired: amountInUnits,
|
|
30635
|
+
resource: this.manifest.provider.wallet,
|
|
30636
|
+
payTo: this.manifest.provider.wallet
|
|
30637
|
+
};
|
|
30638
|
+
const requestBody = {
|
|
30639
|
+
paymentPayload: payment,
|
|
30640
|
+
paymentRequirements: requirements
|
|
30641
|
+
};
|
|
30642
|
+
let headers = { "Content-Type": "application/json" };
|
|
30643
|
+
if (this.cdpConfig.useMainnet) {
|
|
30644
|
+
const authHeaders = await getCDPAuthHeaders(
|
|
30645
|
+
"POST",
|
|
30646
|
+
"/platform/v2/x402/verify",
|
|
30647
|
+
requestBody
|
|
30648
|
+
);
|
|
30649
|
+
headers = { ...headers, ...authHeaders };
|
|
30650
|
+
}
|
|
30651
|
+
const response = await fetch(`${this.facilitatorUrl}/verify`, {
|
|
30652
|
+
method: "POST",
|
|
30653
|
+
headers,
|
|
30654
|
+
body: JSON.stringify(requestBody)
|
|
30655
|
+
});
|
|
30656
|
+
const result = await response.json();
|
|
30657
|
+
if (!response.ok || !result.isValid) {
|
|
30658
|
+
return { valid: false, error: result.invalidReason || result.error || "Verification failed" };
|
|
30659
|
+
}
|
|
30660
|
+
return { valid: true };
|
|
30661
|
+
} catch (err) {
|
|
30662
|
+
return { valid: false, error: `Facilitator error: ${err.message}` };
|
|
30653
30663
|
}
|
|
30654
|
-
|
|
30655
|
-
|
|
30656
|
-
|
|
30657
|
-
|
|
30658
|
-
|
|
30659
|
-
|
|
30660
|
-
|
|
30661
|
-
|
|
30662
|
-
|
|
30663
|
-
|
|
30664
|
-
|
|
30665
|
-
|
|
30666
|
-
|
|
30667
|
-
|
|
30668
|
-
|
|
30669
|
-
|
|
30670
|
-
|
|
30671
|
-
|
|
30672
|
-
)
|
|
30673
|
-
|
|
30674
|
-
|
|
30664
|
+
}
|
|
30665
|
+
/**
|
|
30666
|
+
* Settle payment with facilitator (execute on-chain transfer)
|
|
30667
|
+
*/
|
|
30668
|
+
async settleWithFacilitator(payment, config) {
|
|
30669
|
+
const amountInUnits = Math.floor(config.price * 1e6).toString();
|
|
30670
|
+
const requirements = {
|
|
30671
|
+
scheme: "exact",
|
|
30672
|
+
network: this.networkId,
|
|
30673
|
+
maxAmountRequired: amountInUnits,
|
|
30674
|
+
resource: this.manifest.provider.wallet,
|
|
30675
|
+
payTo: this.manifest.provider.wallet
|
|
30676
|
+
};
|
|
30677
|
+
const requestBody = {
|
|
30678
|
+
paymentPayload: payment,
|
|
30679
|
+
paymentRequirements: requirements
|
|
30680
|
+
};
|
|
30681
|
+
let headers = { "Content-Type": "application/json" };
|
|
30682
|
+
if (this.cdpConfig.useMainnet) {
|
|
30683
|
+
const authHeaders = await getCDPAuthHeaders(
|
|
30684
|
+
"POST",
|
|
30685
|
+
"/platform/v2/x402/settle",
|
|
30686
|
+
requestBody
|
|
30687
|
+
);
|
|
30688
|
+
headers = { ...headers, ...authHeaders };
|
|
30689
|
+
}
|
|
30690
|
+
const response = await fetch(`${this.facilitatorUrl}/settle`, {
|
|
30691
|
+
method: "POST",
|
|
30692
|
+
headers,
|
|
30693
|
+
body: JSON.stringify(requestBody)
|
|
30694
|
+
});
|
|
30695
|
+
const result = await response.json();
|
|
30696
|
+
if (!response.ok || !result.success) {
|
|
30697
|
+
throw new Error(result.error || result.errorReason || "Settlement failed");
|
|
30698
|
+
}
|
|
30699
|
+
return {
|
|
30700
|
+
transaction: result.transaction,
|
|
30701
|
+
status: result.status || "settled"
|
|
30702
|
+
};
|
|
30675
30703
|
}
|
|
30676
30704
|
async readBody(req) {
|
|
30677
30705
|
return new Promise((resolve, reject) => {
|
|
@@ -30687,18 +30715,100 @@ var MoltsPayServer = class {
|
|
|
30687
30715
|
req.on("error", reject);
|
|
30688
30716
|
});
|
|
30689
30717
|
}
|
|
30690
|
-
sendJson(res, status, data) {
|
|
30691
|
-
|
|
30718
|
+
sendJson(res, status, data, extraHeaders) {
|
|
30719
|
+
const headers = { "Content-Type": "application/json" };
|
|
30720
|
+
if (extraHeaders) {
|
|
30721
|
+
Object.assign(headers, extraHeaders);
|
|
30722
|
+
}
|
|
30723
|
+
res.writeHead(status, headers);
|
|
30692
30724
|
res.end(JSON.stringify(data, null, 2));
|
|
30693
30725
|
}
|
|
30694
30726
|
};
|
|
30695
30727
|
|
|
30696
30728
|
// src/client/index.ts
|
|
30697
30729
|
init_esm_shims();
|
|
30698
|
-
import { existsSync, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
30730
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
30699
30731
|
import { homedir } from "os";
|
|
30700
|
-
import { join } from "path";
|
|
30701
|
-
import { Wallet, ethers
|
|
30732
|
+
import { join as join2 } from "path";
|
|
30733
|
+
import { Wallet, ethers } from "ethers";
|
|
30734
|
+
|
|
30735
|
+
// src/chains/index.ts
|
|
30736
|
+
init_esm_shims();
|
|
30737
|
+
var CHAINS = {
|
|
30738
|
+
// ============ Mainnet ============
|
|
30739
|
+
base: {
|
|
30740
|
+
name: "Base",
|
|
30741
|
+
chainId: 8453,
|
|
30742
|
+
rpc: "https://mainnet.base.org",
|
|
30743
|
+
usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
30744
|
+
explorer: "https://basescan.org/address/",
|
|
30745
|
+
explorerTx: "https://basescan.org/tx/",
|
|
30746
|
+
avgBlockTime: 2
|
|
30747
|
+
},
|
|
30748
|
+
polygon: {
|
|
30749
|
+
name: "Polygon",
|
|
30750
|
+
chainId: 137,
|
|
30751
|
+
rpc: "https://polygon-rpc.com",
|
|
30752
|
+
usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
30753
|
+
explorer: "https://polygonscan.com/address/",
|
|
30754
|
+
explorerTx: "https://polygonscan.com/tx/",
|
|
30755
|
+
avgBlockTime: 2
|
|
30756
|
+
},
|
|
30757
|
+
ethereum: {
|
|
30758
|
+
name: "Ethereum",
|
|
30759
|
+
chainId: 1,
|
|
30760
|
+
rpc: "https://eth.llamarpc.com",
|
|
30761
|
+
usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
30762
|
+
explorer: "https://etherscan.io/address/",
|
|
30763
|
+
explorerTx: "https://etherscan.io/tx/",
|
|
30764
|
+
avgBlockTime: 12
|
|
30765
|
+
},
|
|
30766
|
+
// ============ Testnet ============
|
|
30767
|
+
base_sepolia: {
|
|
30768
|
+
name: "Base Sepolia",
|
|
30769
|
+
chainId: 84532,
|
|
30770
|
+
rpc: "https://sepolia.base.org",
|
|
30771
|
+
usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
30772
|
+
explorer: "https://sepolia.basescan.org/address/",
|
|
30773
|
+
explorerTx: "https://sepolia.basescan.org/tx/",
|
|
30774
|
+
avgBlockTime: 2
|
|
30775
|
+
},
|
|
30776
|
+
sepolia: {
|
|
30777
|
+
name: "Sepolia",
|
|
30778
|
+
chainId: 11155111,
|
|
30779
|
+
rpc: "https://rpc.sepolia.org",
|
|
30780
|
+
usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
30781
|
+
explorer: "https://sepolia.etherscan.io/address/",
|
|
30782
|
+
explorerTx: "https://sepolia.etherscan.io/tx/",
|
|
30783
|
+
avgBlockTime: 12
|
|
30784
|
+
}
|
|
30785
|
+
};
|
|
30786
|
+
function getChain(name) {
|
|
30787
|
+
const config = CHAINS[name];
|
|
30788
|
+
if (!config) {
|
|
30789
|
+
throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(", ")}`);
|
|
30790
|
+
}
|
|
30791
|
+
return config;
|
|
30792
|
+
}
|
|
30793
|
+
function listChains() {
|
|
30794
|
+
return Object.keys(CHAINS);
|
|
30795
|
+
}
|
|
30796
|
+
function getChainById(chainId) {
|
|
30797
|
+
return Object.values(CHAINS).find((c) => c.chainId === chainId);
|
|
30798
|
+
}
|
|
30799
|
+
var ERC20_ABI = [
|
|
30800
|
+
"function balanceOf(address owner) view returns (uint256)",
|
|
30801
|
+
"function transfer(address to, uint256 amount) returns (bool)",
|
|
30802
|
+
"function approve(address spender, uint256 amount) returns (bool)",
|
|
30803
|
+
"function allowance(address owner, address spender) view returns (uint256)",
|
|
30804
|
+
"function decimals() view returns (uint8)",
|
|
30805
|
+
"function symbol() view returns (string)",
|
|
30806
|
+
"function name() view returns (string)",
|
|
30807
|
+
"function nonces(address owner) view returns (uint256)",
|
|
30808
|
+
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
|
|
30809
|
+
"event Transfer(address indexed from, address indexed to, uint256 value)",
|
|
30810
|
+
"event Approval(address indexed owner, address indexed spender, uint256 value)"
|
|
30811
|
+
];
|
|
30702
30812
|
|
|
30703
30813
|
// src/client/types.ts
|
|
30704
30814
|
init_esm_shims();
|
|
@@ -30722,7 +30832,7 @@ var MoltsPayClient = class {
|
|
|
30722
30832
|
todaySpending = 0;
|
|
30723
30833
|
lastSpendingReset = 0;
|
|
30724
30834
|
constructor(options = {}) {
|
|
30725
|
-
this.configDir = options.configDir ||
|
|
30835
|
+
this.configDir = options.configDir || join2(homedir(), ".moltspay");
|
|
30726
30836
|
this.config = this.loadConfig();
|
|
30727
30837
|
this.walletData = this.loadWallet();
|
|
30728
30838
|
if (this.walletData) {
|
|
@@ -30847,7 +30957,7 @@ var MoltsPayClient = class {
|
|
|
30847
30957
|
async signEIP3009(to, amount, chain2) {
|
|
30848
30958
|
const validAfter = 0;
|
|
30849
30959
|
const validBefore = Math.floor(Date.now() / 1e3) + 3600;
|
|
30850
|
-
const nonce =
|
|
30960
|
+
const nonce = ethers.hexlify(ethers.randomBytes(32));
|
|
30851
30961
|
const value = BigInt(Math.floor(amount * 1e6)).toString();
|
|
30852
30962
|
const authorization = {
|
|
30853
30963
|
from: this.wallet.address,
|
|
@@ -30904,8 +31014,8 @@ var MoltsPayClient = class {
|
|
|
30904
31014
|
}
|
|
30905
31015
|
// --- Config & Wallet Management ---
|
|
30906
31016
|
loadConfig() {
|
|
30907
|
-
const configPath =
|
|
30908
|
-
if (
|
|
31017
|
+
const configPath = join2(this.configDir, "config.json");
|
|
31018
|
+
if (existsSync2(configPath)) {
|
|
30909
31019
|
const content = readFileSync2(configPath, "utf-8");
|
|
30910
31020
|
return { ...DEFAULT_CONFIG, ...JSON.parse(content) };
|
|
30911
31021
|
}
|
|
@@ -30913,12 +31023,12 @@ var MoltsPayClient = class {
|
|
|
30913
31023
|
}
|
|
30914
31024
|
saveConfig() {
|
|
30915
31025
|
mkdirSync(this.configDir, { recursive: true });
|
|
30916
|
-
const configPath =
|
|
31026
|
+
const configPath = join2(this.configDir, "config.json");
|
|
30917
31027
|
writeFileSync(configPath, JSON.stringify(this.config, null, 2));
|
|
30918
31028
|
}
|
|
30919
31029
|
loadWallet() {
|
|
30920
|
-
const walletPath =
|
|
30921
|
-
if (
|
|
31030
|
+
const walletPath = join2(this.configDir, "wallet.json");
|
|
31031
|
+
if (existsSync2(walletPath)) {
|
|
30922
31032
|
const content = readFileSync2(walletPath, "utf-8");
|
|
30923
31033
|
return JSON.parse(content);
|
|
30924
31034
|
}
|
|
@@ -30935,7 +31045,7 @@ var MoltsPayClient = class {
|
|
|
30935
31045
|
privateKey: wallet.privateKey,
|
|
30936
31046
|
createdAt: Date.now()
|
|
30937
31047
|
};
|
|
30938
|
-
const walletPath =
|
|
31048
|
+
const walletPath = join2(configDir, "wallet.json");
|
|
30939
31049
|
writeFileSync(walletPath, JSON.stringify(walletData, null, 2));
|
|
30940
31050
|
const config = {
|
|
30941
31051
|
chain: options.chain,
|
|
@@ -30944,7 +31054,7 @@ var MoltsPayClient = class {
|
|
|
30944
31054
|
maxPerDay: options.maxPerDay
|
|
30945
31055
|
}
|
|
30946
31056
|
};
|
|
30947
|
-
const configPath =
|
|
31057
|
+
const configPath = join2(configDir, "config.json");
|
|
30948
31058
|
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
30949
31059
|
return { address: wallet.address, configDir };
|
|
30950
31060
|
}
|
|
@@ -30961,14 +31071,14 @@ var MoltsPayClient = class {
|
|
|
30961
31071
|
} catch {
|
|
30962
31072
|
throw new Error(`Unknown chain: ${this.config.chain}`);
|
|
30963
31073
|
}
|
|
30964
|
-
const provider = new
|
|
31074
|
+
const provider = new ethers.JsonRpcProvider(chain2.rpc);
|
|
30965
31075
|
const nativeBalance = await provider.getBalance(this.wallet.address);
|
|
30966
31076
|
const usdcAbi = ["function balanceOf(address) view returns (uint256)"];
|
|
30967
|
-
const usdc = new
|
|
31077
|
+
const usdc = new ethers.Contract(chain2.usdc, usdcAbi, provider);
|
|
30968
31078
|
const usdcBalance = await usdc.balanceOf(this.wallet.address);
|
|
30969
31079
|
return {
|
|
30970
|
-
usdc: parseFloat(
|
|
30971
|
-
native: parseFloat(
|
|
31080
|
+
usdc: parseFloat(ethers.formatUnits(usdcBalance, 6)),
|
|
31081
|
+
native: parseFloat(ethers.formatEther(nativeBalance))
|
|
30972
31082
|
};
|
|
30973
31083
|
}
|
|
30974
31084
|
};
|
|
@@ -30978,15 +31088,15 @@ init_esm_shims();
|
|
|
30978
31088
|
|
|
30979
31089
|
// src/wallet/Wallet.ts
|
|
30980
31090
|
init_esm_shims();
|
|
30981
|
-
import { ethers as
|
|
31091
|
+
import { ethers as ethers2 } from "ethers";
|
|
30982
31092
|
|
|
30983
31093
|
// src/wallet/createWallet.ts
|
|
30984
31094
|
init_esm_shims();
|
|
30985
|
-
import { ethers as
|
|
30986
|
-
import { writeFileSync as writeFileSync2, readFileSync as readFileSync3, existsSync as
|
|
30987
|
-
import { join as
|
|
31095
|
+
import { ethers as ethers3 } from "ethers";
|
|
31096
|
+
import { writeFileSync as writeFileSync2, readFileSync as readFileSync3, existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
31097
|
+
import { join as join3, dirname } from "path";
|
|
30988
31098
|
import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from "crypto";
|
|
30989
|
-
var DEFAULT_STORAGE_DIR =
|
|
31099
|
+
var DEFAULT_STORAGE_DIR = join3(process.env.HOME || "~", ".moltspay");
|
|
30990
31100
|
var DEFAULT_STORAGE_FILE = "wallet.json";
|
|
30991
31101
|
function encryptPrivateKey(privateKey, password) {
|
|
30992
31102
|
const salt = randomBytes(16);
|
|
@@ -31009,8 +31119,8 @@ function decryptPrivateKey(encrypted, password, iv, salt) {
|
|
|
31009
31119
|
return decrypted;
|
|
31010
31120
|
}
|
|
31011
31121
|
function createWallet(options = {}) {
|
|
31012
|
-
const storagePath = options.storagePath ||
|
|
31013
|
-
if (
|
|
31122
|
+
const storagePath = options.storagePath || join3(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
31123
|
+
if (existsSync3(storagePath) && !options.overwrite) {
|
|
31014
31124
|
try {
|
|
31015
31125
|
const existing = JSON.parse(readFileSync3(storagePath, "utf8"));
|
|
31016
31126
|
return {
|
|
@@ -31027,7 +31137,7 @@ function createWallet(options = {}) {
|
|
|
31027
31137
|
}
|
|
31028
31138
|
}
|
|
31029
31139
|
try {
|
|
31030
|
-
const wallet =
|
|
31140
|
+
const wallet = ethers3.Wallet.createRandom();
|
|
31031
31141
|
const walletData = {
|
|
31032
31142
|
address: wallet.address,
|
|
31033
31143
|
label: options.label,
|
|
@@ -31044,7 +31154,7 @@ function createWallet(options = {}) {
|
|
|
31044
31154
|
walletData.privateKey = wallet.privateKey;
|
|
31045
31155
|
}
|
|
31046
31156
|
const dir = dirname(storagePath);
|
|
31047
|
-
if (!
|
|
31157
|
+
if (!existsSync3(dir)) {
|
|
31048
31158
|
mkdirSync2(dir, { recursive: true });
|
|
31049
31159
|
}
|
|
31050
31160
|
writeFileSync2(storagePath, JSON.stringify(walletData, null, 2), { mode: 384 });
|
|
@@ -31062,8 +31172,8 @@ function createWallet(options = {}) {
|
|
|
31062
31172
|
}
|
|
31063
31173
|
}
|
|
31064
31174
|
function loadWallet(options = {}) {
|
|
31065
|
-
const storagePath = options.storagePath ||
|
|
31066
|
-
if (!
|
|
31175
|
+
const storagePath = options.storagePath || join3(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
31176
|
+
if (!existsSync3(storagePath)) {
|
|
31067
31177
|
return { success: false, error: "Wallet not found. Run createWallet() first." };
|
|
31068
31178
|
}
|
|
31069
31179
|
try {
|
|
@@ -31082,26 +31192,26 @@ function loadWallet(options = {}) {
|
|
|
31082
31192
|
}
|
|
31083
31193
|
}
|
|
31084
31194
|
function getWalletAddress(storagePath) {
|
|
31085
|
-
const
|
|
31086
|
-
if (!
|
|
31195
|
+
const path4 = storagePath || join3(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
31196
|
+
if (!existsSync3(path4)) {
|
|
31087
31197
|
return null;
|
|
31088
31198
|
}
|
|
31089
31199
|
try {
|
|
31090
|
-
const data = JSON.parse(readFileSync3(
|
|
31200
|
+
const data = JSON.parse(readFileSync3(path4, "utf8"));
|
|
31091
31201
|
return data.address;
|
|
31092
31202
|
} catch {
|
|
31093
31203
|
return null;
|
|
31094
31204
|
}
|
|
31095
31205
|
}
|
|
31096
31206
|
function walletExists(storagePath) {
|
|
31097
|
-
const
|
|
31098
|
-
return
|
|
31207
|
+
const path4 = storagePath || join3(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
31208
|
+
return existsSync3(path4);
|
|
31099
31209
|
}
|
|
31100
31210
|
|
|
31101
31211
|
// src/verify/index.ts
|
|
31102
31212
|
init_esm_shims();
|
|
31103
|
-
import { ethers as
|
|
31104
|
-
var TRANSFER_EVENT_TOPIC =
|
|
31213
|
+
import { ethers as ethers4 } from "ethers";
|
|
31214
|
+
var TRANSFER_EVENT_TOPIC = ethers4.id("Transfer(address,address,uint256)");
|
|
31105
31215
|
async function verifyPayment(params) {
|
|
31106
31216
|
const { txHash, expectedAmount, expectedTo } = params;
|
|
31107
31217
|
let chain2;
|
|
@@ -31118,7 +31228,7 @@ async function verifyPayment(params) {
|
|
|
31118
31228
|
return { verified: false, error: `Unsupported chain: ${params.chain}` };
|
|
31119
31229
|
}
|
|
31120
31230
|
try {
|
|
31121
|
-
const provider = new
|
|
31231
|
+
const provider = new ethers4.JsonRpcProvider(chain2.rpc);
|
|
31122
31232
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
31123
31233
|
if (!receipt) {
|
|
31124
31234
|
return { verified: false, error: "Transaction not found or not confirmed" };
|
|
@@ -31178,7 +31288,7 @@ async function getTransactionStatus(txHash, chain2 = "base") {
|
|
|
31178
31288
|
return { status: "not_found" };
|
|
31179
31289
|
}
|
|
31180
31290
|
try {
|
|
31181
|
-
const provider = new
|
|
31291
|
+
const provider = new ethers4.JsonRpcProvider(chainConfig.rpc);
|
|
31182
31292
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
31183
31293
|
if (!receipt) {
|
|
31184
31294
|
const tx = await provider.getTransaction(txHash);
|
|
@@ -31215,7 +31325,7 @@ async function waitForTransaction(txHash, chain2 = "base", confirmations = 1, ti
|
|
|
31215
31325
|
} catch (e) {
|
|
31216
31326
|
return { verified: false, confirmed: false, error: `Unsupported chain: ${chain2}` };
|
|
31217
31327
|
}
|
|
31218
|
-
const provider = new
|
|
31328
|
+
const provider = new ethers4.JsonRpcProvider(chainConfig.rpc);
|
|
31219
31329
|
try {
|
|
31220
31330
|
const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);
|
|
31221
31331
|
if (!receipt) {
|
|
@@ -31238,8 +31348,8 @@ async function waitForTransaction(txHash, chain2 = "base", confirmations = 1, ti
|
|
|
31238
31348
|
// src/cdp/index.ts
|
|
31239
31349
|
init_esm_shims();
|
|
31240
31350
|
import * as fs from "fs";
|
|
31241
|
-
import * as
|
|
31242
|
-
var DEFAULT_STORAGE_DIR2 =
|
|
31351
|
+
import * as path3 from "path";
|
|
31352
|
+
var DEFAULT_STORAGE_DIR2 = path3.join(process.env.HOME || ".", ".moltspay");
|
|
31243
31353
|
var CDP_CONFIG_FILE = "cdp-wallet.json";
|
|
31244
31354
|
function isCDPAvailable() {
|
|
31245
31355
|
try {
|
|
@@ -31261,7 +31371,7 @@ function getCDPCredentials(config) {
|
|
|
31261
31371
|
async function initCDPWallet(config = {}) {
|
|
31262
31372
|
const storageDir = config.storageDir || DEFAULT_STORAGE_DIR2;
|
|
31263
31373
|
const chain2 = config.chain || "base";
|
|
31264
|
-
const storagePath =
|
|
31374
|
+
const storagePath = path3.join(storageDir, CDP_CONFIG_FILE);
|
|
31265
31375
|
if (fs.existsSync(storagePath)) {
|
|
31266
31376
|
try {
|
|
31267
31377
|
const data = JSON.parse(fs.readFileSync(storagePath, "utf-8"));
|
|
@@ -31323,7 +31433,7 @@ async function initCDPWallet(config = {}) {
|
|
|
31323
31433
|
}
|
|
31324
31434
|
function loadCDPWallet(config = {}) {
|
|
31325
31435
|
const storageDir = config.storageDir || DEFAULT_STORAGE_DIR2;
|
|
31326
|
-
const storagePath =
|
|
31436
|
+
const storagePath = path3.join(storageDir, CDP_CONFIG_FILE);
|
|
31327
31437
|
if (!fs.existsSync(storagePath)) {
|
|
31328
31438
|
return null;
|
|
31329
31439
|
}
|
|
@@ -31356,9 +31466,9 @@ var CDPWallet = class {
|
|
|
31356
31466
|
* Get USDC balance
|
|
31357
31467
|
*/
|
|
31358
31468
|
async getBalance() {
|
|
31359
|
-
const { ethers:
|
|
31360
|
-
const provider = new
|
|
31361
|
-
const usdcContract = new
|
|
31469
|
+
const { ethers: ethers5 } = await import("ethers");
|
|
31470
|
+
const provider = new ethers5.JsonRpcProvider(this.chainConfig.rpc);
|
|
31471
|
+
const usdcContract = new ethers5.Contract(
|
|
31362
31472
|
this.chainConfig.usdc,
|
|
31363
31473
|
["function balanceOf(address) view returns (uint256)"],
|
|
31364
31474
|
provider
|
|
@@ -31369,7 +31479,7 @@ var CDPWallet = class {
|
|
|
31369
31479
|
]);
|
|
31370
31480
|
return {
|
|
31371
31481
|
usdc: (Number(usdcBalance) / 1e6).toFixed(2),
|
|
31372
|
-
eth:
|
|
31482
|
+
eth: ethers5.formatEther(ethBalance)
|
|
31373
31483
|
};
|
|
31374
31484
|
}
|
|
31375
31485
|
/**
|
|
@@ -31387,7 +31497,7 @@ var CDPWallet = class {
|
|
|
31387
31497
|
}
|
|
31388
31498
|
try {
|
|
31389
31499
|
const { CdpClient } = await import("@coinbase/cdp-sdk");
|
|
31390
|
-
const { ethers:
|
|
31500
|
+
const { ethers: ethers5 } = await import("ethers");
|
|
31391
31501
|
const cdp = new CdpClient({
|
|
31392
31502
|
apiKeyId: creds.apiKeyId,
|
|
31393
31503
|
apiKeySecret: creds.apiKeySecret,
|
|
@@ -31395,7 +31505,7 @@ var CDPWallet = class {
|
|
|
31395
31505
|
});
|
|
31396
31506
|
const account = await cdp.evm.getAccount({ address: this.address });
|
|
31397
31507
|
const amountWei = BigInt(Math.floor(params.amount * 1e6));
|
|
31398
|
-
const iface = new
|
|
31508
|
+
const iface = new ethers5.Interface([
|
|
31399
31509
|
"function transfer(address to, uint256 amount) returns (bool)"
|
|
31400
31510
|
]);
|
|
31401
31511
|
const callData = iface.encodeFunctionData("transfer", [params.to, amountWei]);
|