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.
@@ -76,9 +76,14 @@ interface MoltsPayServerOptions {
76
76
  /**
77
77
  * MoltsPay Server - Payment infrastructure for AI Agents
78
78
  *
79
- * Uses x402 protocol with public facilitator (https://x402.org/facilitator).
79
+ * Supports both testnet (x402.org) and mainnet (CDP) facilitators.
80
80
  * Server does NOT need private key - facilitator handles on-chain settlement.
81
81
  *
82
+ * Environment variables (from ~/.moltspay/.env or process.env):
83
+ * USE_MAINNET=true - Use Base mainnet (requires CDP keys)
84
+ * CDP_API_KEY_ID=xxx - Coinbase Developer Platform API key ID
85
+ * CDP_API_KEY_SECRET=xxx - CDP API key secret
86
+ *
82
87
  * Usage:
83
88
  * const server = new MoltsPayServer('./moltspay.services.json');
84
89
  * server.skill('text-to-video', async (params) => { ... });
@@ -89,7 +94,9 @@ declare class MoltsPayServer {
89
94
  private manifest;
90
95
  private skills;
91
96
  private options;
97
+ private cdpConfig;
92
98
  private facilitatorUrl;
99
+ private networkId;
93
100
  constructor(servicesPath: string, options?: MoltsPayServerOptions);
94
101
  /**
95
102
  * Register a skill handler for a service
@@ -109,8 +116,6 @@ declare class MoltsPayServer {
109
116
  private handleGetServices;
110
117
  /**
111
118
  * POST /execute - Execute service with x402 payment
112
- * Body: { service: string, params: object }
113
- * Header: X-Payment (optional - if missing, returns 402)
114
119
  */
115
120
  private handleExecute;
116
121
  /**
@@ -118,11 +123,15 @@ declare class MoltsPayServer {
118
123
  */
119
124
  private sendPaymentRequired;
120
125
  /**
121
- * Basic payment validation (before calling facilitator)
126
+ * Basic payment validation
122
127
  */
123
128
  private validatePayment;
124
129
  /**
125
- * Verify payment with facilitator
130
+ * Build complete payment requirements for facilitator
131
+ */
132
+ private buildPaymentRequirements;
133
+ /**
134
+ * Verify payment with facilitator (testnet or CDP)
126
135
  */
127
136
  private verifyWithFacilitator;
128
137
  /**
@@ -76,9 +76,14 @@ interface MoltsPayServerOptions {
76
76
  /**
77
77
  * MoltsPay Server - Payment infrastructure for AI Agents
78
78
  *
79
- * Uses x402 protocol with public facilitator (https://x402.org/facilitator).
79
+ * Supports both testnet (x402.org) and mainnet (CDP) facilitators.
80
80
  * Server does NOT need private key - facilitator handles on-chain settlement.
81
81
  *
82
+ * Environment variables (from ~/.moltspay/.env or process.env):
83
+ * USE_MAINNET=true - Use Base mainnet (requires CDP keys)
84
+ * CDP_API_KEY_ID=xxx - Coinbase Developer Platform API key ID
85
+ * CDP_API_KEY_SECRET=xxx - CDP API key secret
86
+ *
82
87
  * Usage:
83
88
  * const server = new MoltsPayServer('./moltspay.services.json');
84
89
  * server.skill('text-to-video', async (params) => { ... });
@@ -89,7 +94,9 @@ declare class MoltsPayServer {
89
94
  private manifest;
90
95
  private skills;
91
96
  private options;
97
+ private cdpConfig;
92
98
  private facilitatorUrl;
99
+ private networkId;
93
100
  constructor(servicesPath: string, options?: MoltsPayServerOptions);
94
101
  /**
95
102
  * Register a skill handler for a service
@@ -109,8 +116,6 @@ declare class MoltsPayServer {
109
116
  private handleGetServices;
110
117
  /**
111
118
  * POST /execute - Execute service with x402 payment
112
- * Body: { service: string, params: object }
113
- * Header: X-Payment (optional - if missing, returns 402)
114
119
  */
115
120
  private handleExecute;
116
121
  /**
@@ -118,11 +123,15 @@ declare class MoltsPayServer {
118
123
  */
119
124
  private sendPaymentRequired;
120
125
  /**
121
- * Basic payment validation (before calling facilitator)
126
+ * Basic payment validation
122
127
  */
123
128
  private validatePayment;
124
129
  /**
125
- * Verify payment with facilitator
130
+ * Build complete payment requirements for facilitator
131
+ */
132
+ private buildPaymentRequirements;
133
+ /**
134
+ * Verify payment with facilitator (testnet or CDP)
126
135
  */
127
136
  private verifyWithFacilitator;
128
137
  /**
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/server/index.ts
@@ -25,88 +35,105 @@ __export(server_exports, {
25
35
  module.exports = __toCommonJS(server_exports);
26
36
  var import_fs = require("fs");
27
37
  var import_http = require("http");
28
-
29
- // src/chains/index.ts
30
- var CHAINS = {
31
- // ============ Mainnet ============
32
- base: {
33
- name: "Base",
34
- chainId: 8453,
35
- rpc: "https://mainnet.base.org",
36
- usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
37
- explorer: "https://basescan.org/address/",
38
- explorerTx: "https://basescan.org/tx/",
39
- avgBlockTime: 2
40
- },
41
- polygon: {
42
- name: "Polygon",
43
- chainId: 137,
44
- rpc: "https://polygon-rpc.com",
45
- usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
46
- explorer: "https://polygonscan.com/address/",
47
- explorerTx: "https://polygonscan.com/tx/",
48
- avgBlockTime: 2
49
- },
50
- ethereum: {
51
- name: "Ethereum",
52
- chainId: 1,
53
- rpc: "https://eth.llamarpc.com",
54
- usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
55
- explorer: "https://etherscan.io/address/",
56
- explorerTx: "https://etherscan.io/tx/",
57
- avgBlockTime: 12
58
- },
59
- // ============ Testnet ============
60
- base_sepolia: {
61
- name: "Base Sepolia",
62
- chainId: 84532,
63
- rpc: "https://sepolia.base.org",
64
- usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
65
- explorer: "https://sepolia.basescan.org/address/",
66
- explorerTx: "https://sepolia.basescan.org/tx/",
67
- avgBlockTime: 2
68
- },
69
- sepolia: {
70
- name: "Sepolia",
71
- chainId: 11155111,
72
- rpc: "https://rpc.sepolia.org",
73
- usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
74
- explorer: "https://sepolia.etherscan.io/address/",
75
- explorerTx: "https://sepolia.etherscan.io/tx/",
76
- avgBlockTime: 12
77
- }
78
- };
79
- function getChain(name) {
80
- const config = CHAINS[name];
81
- if (!config) {
82
- throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(", ")}`);
83
- }
84
- return config;
85
- }
86
-
87
- // src/server/index.ts
38
+ var path = __toESM(require("path"));
88
39
  var X402_VERSION = 2;
89
40
  var PAYMENT_REQUIRED_HEADER = "x-payment-required";
90
41
  var PAYMENT_HEADER = "x-payment";
91
42
  var PAYMENT_RESPONSE_HEADER = "x-payment-response";
92
- var DEFAULT_FACILITATOR_URL = "https://x402.org/facilitator";
43
+ var FACILITATOR_TESTNET = "https://www.x402.org/facilitator";
44
+ var FACILITATOR_MAINNET = "https://api.cdp.coinbase.com/platform/v2/x402";
45
+ var USDC_ADDRESSES = {
46
+ "eip155:8453": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
47
+ // Base mainnet
48
+ "eip155:84532": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
49
+ // Base Sepolia
50
+ };
51
+ var USDC_DOMAIN = {
52
+ name: "USD Coin",
53
+ version: "2"
54
+ };
55
+ function loadEnvFiles() {
56
+ try {
57
+ const dotenv = require("dotenv");
58
+ const envPaths = [
59
+ path.join(process.cwd(), ".env"),
60
+ path.join(process.env.HOME || "", ".moltspay", ".env")
61
+ ];
62
+ for (const envPath of envPaths) {
63
+ if ((0, import_fs.existsSync)(envPath)) {
64
+ dotenv.config({ path: envPath });
65
+ console.log(`[MoltsPay] Loaded config from ${envPath}`);
66
+ break;
67
+ }
68
+ }
69
+ } catch {
70
+ }
71
+ }
72
+ function getCDPConfig() {
73
+ loadEnvFiles();
74
+ return {
75
+ useMainnet: process.env.USE_MAINNET?.toLowerCase() === "true",
76
+ apiKeyId: process.env.CDP_API_KEY_ID,
77
+ apiKeySecret: process.env.CDP_API_KEY_SECRET
78
+ };
79
+ }
80
+ async function getCDPAuthHeaders(method, urlPath, body) {
81
+ const config = getCDPConfig();
82
+ if (!config.apiKeyId || !config.apiKeySecret) {
83
+ throw new Error("CDP_API_KEY_ID and CDP_API_KEY_SECRET required for mainnet");
84
+ }
85
+ try {
86
+ const { getAuthHeaders } = await import("@coinbase/cdp-sdk/auth");
87
+ const headers = await getAuthHeaders({
88
+ apiKeyId: config.apiKeyId,
89
+ apiKeySecret: config.apiKeySecret,
90
+ requestMethod: method,
91
+ requestHost: "api.cdp.coinbase.com",
92
+ requestPath: urlPath,
93
+ requestBody: body
94
+ });
95
+ return headers;
96
+ } catch (err) {
97
+ console.error("[MoltsPay] Failed to generate CDP auth headers:", err.message);
98
+ throw err;
99
+ }
100
+ }
93
101
  var MoltsPayServer = class {
94
102
  manifest;
95
103
  skills = /* @__PURE__ */ new Map();
96
104
  options;
105
+ cdpConfig;
97
106
  facilitatorUrl;
107
+ networkId;
98
108
  constructor(servicesPath, options = {}) {
109
+ this.cdpConfig = getCDPConfig();
99
110
  const content = (0, import_fs.readFileSync)(servicesPath, "utf-8");
100
111
  this.manifest = JSON.parse(content);
101
112
  this.options = {
102
113
  port: options.port || 3e3,
103
114
  host: options.host || "0.0.0.0"
104
115
  };
105
- this.facilitatorUrl = options.facilitatorUrl || DEFAULT_FACILITATOR_URL;
116
+ if (this.cdpConfig.useMainnet) {
117
+ if (!this.cdpConfig.apiKeyId || !this.cdpConfig.apiKeySecret) {
118
+ console.warn("[MoltsPay] WARNING: USE_MAINNET=true but CDP keys not set!");
119
+ console.warn("[MoltsPay] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET in ~/.moltspay/.env");
120
+ }
121
+ this.facilitatorUrl = FACILITATOR_MAINNET;
122
+ this.networkId = "eip155:8453";
123
+ } else {
124
+ this.facilitatorUrl = options.facilitatorUrl || FACILITATOR_TESTNET;
125
+ this.networkId = "eip155:84532";
126
+ }
127
+ const networkName = this.cdpConfig.useMainnet ? "Base mainnet" : "Base Sepolia (testnet)";
128
+ const facilitatorName = this.cdpConfig.useMainnet ? "CDP" : "x402.org";
106
129
  console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);
107
130
  console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);
108
131
  console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);
109
- console.log(`[MoltsPay] Facilitator: ${this.facilitatorUrl}`);
132
+ console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);
133
+ console.log(`[MoltsPay] Facilitator: ${facilitatorName} (${this.facilitatorUrl})`);
134
+ if (this.cdpConfig.useMainnet && this.cdpConfig.apiKeyId) {
135
+ console.log(`[MoltsPay] CDP API Key: ${this.cdpConfig.apiKeyId.slice(0, 8)}...`);
136
+ }
110
137
  console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);
111
138
  }
112
139
  /**
@@ -167,7 +194,6 @@ var MoltsPayServer = class {
167
194
  * GET /services - List available services
168
195
  */
169
196
  handleGetServices(res) {
170
- const chain = getChain(this.manifest.provider.chain);
171
197
  const services = this.manifest.services.map((s) => ({
172
198
  id: s.id,
173
199
  name: s.name,
@@ -183,16 +209,15 @@ var MoltsPayServer = class {
183
209
  services,
184
210
  x402: {
185
211
  version: X402_VERSION,
186
- network: `eip155:${chain.chainId}`,
212
+ network: this.networkId,
187
213
  schemes: ["exact"],
188
- facilitator: this.facilitatorUrl
214
+ facilitator: this.cdpConfig.useMainnet ? "cdp" : "x402.org",
215
+ mainnet: this.cdpConfig.useMainnet
189
216
  }
190
217
  });
191
218
  }
192
219
  /**
193
220
  * POST /execute - Execute service with x402 payment
194
- * Body: { service: string, params: object }
195
- * Header: X-Payment (optional - if missing, returns 402)
196
221
  */
197
222
  async handleExecute(body, paymentHeader, res) {
198
223
  const { service, params } = body;
@@ -267,17 +292,8 @@ var MoltsPayServer = class {
267
292
  * Return 402 with x402 payment requirements
268
293
  */
269
294
  sendPaymentRequired(config, res) {
270
- const chain = getChain(this.manifest.provider.chain);
271
- const amountInUnits = Math.floor(config.price * 1e6).toString();
272
- const requirements = [{
273
- scheme: "exact",
274
- network: `eip155:${chain.chainId}`,
275
- maxAmountRequired: amountInUnits,
276
- resource: this.manifest.provider.wallet,
277
- description: `${config.name} - $${config.price} ${config.currency}`,
278
- // Include facilitator info for client
279
- extra: JSON.stringify({ facilitator: this.facilitatorUrl })
280
- }];
295
+ const requirements = [this.buildPaymentRequirements(config)];
296
+ requirements[0].description = `${config.name} - $${config.price} ${config.currency}`;
281
297
  const encoded = Buffer.from(JSON.stringify(requirements)).toString("base64");
282
298
  res.writeHead(402, {
283
299
  "Content-Type": "application/json",
@@ -290,7 +306,7 @@ var MoltsPayServer = class {
290
306
  }, null, 2));
291
307
  }
292
308
  /**
293
- * Basic payment validation (before calling facilitator)
309
+ * Basic payment validation
294
310
  */
295
311
  validatePayment(payment, config) {
296
312
  if (payment.x402Version !== X402_VERSION) {
@@ -299,37 +315,57 @@ var MoltsPayServer = class {
299
315
  if (payment.scheme !== "exact") {
300
316
  return { valid: false, error: `Unsupported scheme: ${payment.scheme}` };
301
317
  }
302
- const chain = getChain(this.manifest.provider.chain);
303
- const expectedNetwork = `eip155:${chain.chainId}`;
304
- if (payment.network !== expectedNetwork) {
305
- return { valid: false, error: `Network mismatch: expected ${expectedNetwork}` };
318
+ if (payment.network !== this.networkId) {
319
+ return { valid: false, error: `Network mismatch: expected ${this.networkId}, got ${payment.network}` };
306
320
  }
307
321
  return { valid: true };
308
322
  }
309
323
  /**
310
- * Verify payment with facilitator
324
+ * Build complete payment requirements for facilitator
325
+ */
326
+ buildPaymentRequirements(config) {
327
+ const amountInUnits = Math.floor(config.price * 1e6).toString();
328
+ const usdcAddress = USDC_ADDRESSES[this.networkId];
329
+ return {
330
+ scheme: "exact",
331
+ network: this.networkId,
332
+ maxAmountRequired: amountInUnits,
333
+ amount: amountInUnits,
334
+ asset: usdcAddress,
335
+ payTo: this.manifest.provider.wallet,
336
+ maxTimeoutSeconds: 300,
337
+ extra: USDC_DOMAIN
338
+ };
339
+ }
340
+ /**
341
+ * Verify payment with facilitator (testnet or CDP)
311
342
  */
312
343
  async verifyWithFacilitator(payment, config) {
313
344
  try {
314
- const chain = getChain(this.manifest.provider.chain);
315
- const amountInUnits = Math.floor(config.price * 1e6).toString();
316
- const requirements = {
317
- scheme: "exact",
318
- network: `eip155:${chain.chainId}`,
319
- maxAmountRequired: amountInUnits,
320
- resource: this.manifest.provider.wallet
345
+ const requirements = this.buildPaymentRequirements(config);
346
+ const requestBody = {
347
+ paymentPayload: payment,
348
+ paymentRequirements: requirements
321
349
  };
350
+ console.log("[MoltsPay] Verify request:", JSON.stringify(requestBody, null, 2));
351
+ let headers = { "Content-Type": "application/json" };
352
+ if (this.cdpConfig.useMainnet) {
353
+ const authHeaders = await getCDPAuthHeaders(
354
+ "POST",
355
+ "/platform/v2/x402/verify",
356
+ requestBody
357
+ );
358
+ headers = { ...headers, ...authHeaders };
359
+ }
322
360
  const response = await fetch(`${this.facilitatorUrl}/verify`, {
323
361
  method: "POST",
324
- headers: { "Content-Type": "application/json" },
325
- body: JSON.stringify({
326
- paymentPayload: payment,
327
- paymentRequirements: requirements
328
- })
362
+ headers,
363
+ body: JSON.stringify(requestBody)
329
364
  });
330
365
  const result = await response.json();
366
+ console.log("[MoltsPay] Verify response:", JSON.stringify(result, null, 2));
331
367
  if (!response.ok || !result.isValid) {
332
- return { valid: false, error: result.invalidReason || "Verification failed" };
368
+ return { valid: false, error: result.invalidReason || result.error || "Verification failed" };
333
369
  }
334
370
  return { valid: true };
335
371
  } catch (err) {
@@ -340,25 +376,28 @@ var MoltsPayServer = class {
340
376
  * Settle payment with facilitator (execute on-chain transfer)
341
377
  */
342
378
  async settleWithFacilitator(payment, config) {
343
- const chain = getChain(this.manifest.provider.chain);
344
- const amountInUnits = Math.floor(config.price * 1e6).toString();
345
- const requirements = {
346
- scheme: "exact",
347
- network: `eip155:${chain.chainId}`,
348
- maxAmountRequired: amountInUnits,
349
- resource: this.manifest.provider.wallet
379
+ const requirements = this.buildPaymentRequirements(config);
380
+ const requestBody = {
381
+ paymentPayload: payment,
382
+ paymentRequirements: requirements
350
383
  };
384
+ let headers = { "Content-Type": "application/json" };
385
+ if (this.cdpConfig.useMainnet) {
386
+ const authHeaders = await getCDPAuthHeaders(
387
+ "POST",
388
+ "/platform/v2/x402/settle",
389
+ requestBody
390
+ );
391
+ headers = { ...headers, ...authHeaders };
392
+ }
351
393
  const response = await fetch(`${this.facilitatorUrl}/settle`, {
352
394
  method: "POST",
353
- headers: { "Content-Type": "application/json" },
354
- body: JSON.stringify({
355
- paymentPayload: payment,
356
- paymentRequirements: requirements
357
- })
395
+ headers,
396
+ body: JSON.stringify(requestBody)
358
397
  });
359
398
  const result = await response.json();
360
- if (!response.ok) {
361
- throw new Error(result.error || "Settlement failed");
399
+ if (!response.ok || !result.success) {
400
+ throw new Error(result.error || result.errorReason || "Settlement failed");
362
401
  }
363
402
  return {
364
403
  transaction: result.transaction,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/index.ts","../../src/chains/index.ts"],"sourcesContent":["/**\n * MoltsPay Server - Payment infrastructure for AI Agents\n * \n * Uses x402 protocol with public facilitator (https://x402.org/facilitator).\n * Server does NOT need private key - facilitator handles on-chain settlement.\n * \n * Usage:\n * const server = new MoltsPayServer('./moltspay.services.json');\n * server.skill('text-to-video', async (params) => { ... });\n * server.listen(3000);\n */\n\nimport { readFileSync } from 'fs';\nimport { createServer, IncomingMessage, ServerResponse } from 'http';\nimport { getChain } from '../chains/index.js';\nimport type { ChainName } from '../chains/index.js';\nimport {\n ServicesManifest,\n ServiceConfig,\n SkillFunction,\n RegisteredSkill,\n MoltsPayServerOptions,\n} from './types.js';\n\nexport * from './types.js';\n\n// x402 constants\nconst X402_VERSION = 2;\nconst PAYMENT_REQUIRED_HEADER = 'x-payment-required';\nconst PAYMENT_HEADER = 'x-payment';\nconst PAYMENT_RESPONSE_HEADER = 'x-payment-response';\n\n// Default facilitator URL\nconst DEFAULT_FACILITATOR_URL = 'https://x402.org/facilitator';\n\ninterface X402PaymentPayload {\n x402Version: number;\n scheme: string;\n network: string;\n payload: any;\n}\n\nexport class MoltsPayServer {\n private manifest: ServicesManifest;\n private skills: Map<string, RegisteredSkill> = new Map();\n private options: MoltsPayServerOptions;\n private facilitatorUrl: string;\n\n constructor(servicesPath: string, options: MoltsPayServerOptions = {}) {\n // Load services manifest\n const content = readFileSync(servicesPath, 'utf-8');\n this.manifest = JSON.parse(content) as ServicesManifest;\n \n this.options = {\n port: options.port || 3000,\n host: options.host || '0.0.0.0',\n };\n\n this.facilitatorUrl = options.facilitatorUrl || DEFAULT_FACILITATOR_URL;\n\n console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);\n console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);\n console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);\n console.log(`[MoltsPay] Facilitator: ${this.facilitatorUrl}`);\n console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);\n }\n\n /**\n * Register a skill handler for a service\n */\n skill(serviceId: string, handler: SkillFunction): this {\n const config = this.manifest.services.find(s => s.id === serviceId);\n if (!config) {\n throw new Error(`Service '${serviceId}' not found in manifest`);\n }\n this.skills.set(serviceId, { id: serviceId, config, handler });\n return this;\n }\n\n /**\n * Start HTTP server\n */\n listen(port?: number): void {\n const p = port || this.options.port || 3000;\n const host = this.options.host || '0.0.0.0';\n\n const server = createServer((req, res) => this.handleRequest(req, res));\n server.listen(p, host, () => {\n console.log(`[MoltsPay] Server listening on http://${host}:${p}`);\n console.log(`[MoltsPay] Endpoints:`);\n console.log(` GET /services - List available services`);\n console.log(` POST /execute - Execute service (x402 payment)`);\n });\n }\n\n /**\n * Handle incoming request\n */\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // CORS\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Payment');\n res.setHeader('Access-Control-Expose-Headers', 'X-Payment-Required, X-Payment-Response');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n try {\n const url = new URL(req.url || '/', `http://${req.headers.host}`);\n \n if (url.pathname === '/services' && req.method === 'GET') {\n return this.handleGetServices(res);\n }\n\n if (url.pathname === '/execute' && req.method === 'POST') {\n const body = await this.readBody(req);\n const paymentHeader = req.headers[PAYMENT_HEADER] as string | undefined;\n return await this.handleExecute(body, paymentHeader, res);\n }\n\n // Not found\n this.sendJson(res, 404, { error: 'Not found' });\n } catch (err: any) {\n console.error('[MoltsPay] Error:', err);\n this.sendJson(res, 500, { error: err.message || 'Internal error' });\n }\n }\n\n /**\n * GET /services - List available services\n */\n private handleGetServices(res: ServerResponse): void {\n const chain = getChain(this.manifest.provider.chain as ChainName);\n \n const services = this.manifest.services.map(s => ({\n id: s.id,\n name: s.name,\n description: s.description,\n price: s.price,\n currency: s.currency,\n input: s.input,\n output: s.output,\n available: this.skills.has(s.id),\n }));\n\n this.sendJson(res, 200, {\n provider: this.manifest.provider,\n services,\n x402: {\n version: X402_VERSION,\n network: `eip155:${chain.chainId}`,\n schemes: ['exact'],\n facilitator: this.facilitatorUrl,\n },\n });\n }\n\n /**\n * POST /execute - Execute service with x402 payment\n * Body: { service: string, params: object }\n * Header: X-Payment (optional - if missing, returns 402)\n */\n private async handleExecute(\n body: any,\n paymentHeader: string | undefined,\n res: ServerResponse\n ): Promise<void> {\n const { service, params } = body;\n\n if (!service) {\n return this.sendJson(res, 400, { error: 'Missing service' });\n }\n\n const skill = this.skills.get(service);\n if (!skill) {\n return this.sendJson(res, 404, { error: `Service '${service}' not found or not registered` });\n }\n\n // Validate required params\n for (const [key, field] of Object.entries(skill.config.input)) {\n if (field.required && (!params || params[key] === undefined)) {\n return this.sendJson(res, 400, { error: `Missing required param: ${key}` });\n }\n }\n\n // If no payment header, return 402 with payment requirements\n if (!paymentHeader) {\n return this.sendPaymentRequired(skill.config, res);\n }\n\n // Parse payment payload\n let payment: X402PaymentPayload;\n try {\n const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');\n payment = JSON.parse(decoded);\n } catch {\n return this.sendJson(res, 400, { error: 'Invalid X-Payment header' });\n }\n\n // Validate basic payment fields\n const validation = this.validatePayment(payment, skill.config);\n if (!validation.valid) {\n return this.sendJson(res, 402, { error: validation.error });\n }\n\n // Verify payment with facilitator\n console.log(`[MoltsPay] Verifying payment with facilitator...`);\n const verifyResult = await this.verifyWithFacilitator(payment, skill.config);\n if (!verifyResult.valid) {\n return this.sendJson(res, 402, { error: `Payment verification failed: ${verifyResult.error}` });\n }\n\n // Execute skill FIRST (pay-for-success)\n console.log(`[MoltsPay] Executing skill: ${service}`);\n let result: any;\n try {\n result = await skill.handler(params || {});\n } catch (err: any) {\n console.error('[MoltsPay] Skill execution failed:', err.message);\n // Don't settle payment if skill fails\n return this.sendJson(res, 500, {\n error: 'Service execution failed',\n message: err.message,\n });\n }\n\n // Skill succeeded - now settle payment with facilitator\n console.log(`[MoltsPay] Skill succeeded, settling payment...`);\n let settlement: any = null;\n try {\n settlement = await this.settleWithFacilitator(payment, skill.config);\n console.log(`[MoltsPay] Payment settled: ${settlement.transaction || 'pending'}`);\n } catch (err: any) {\n console.error('[MoltsPay] Settlement failed:', err.message);\n // Still return result - facilitator may settle later\n }\n\n // Build response with settlement info\n const responseHeaders: Record<string, string> = {};\n if (settlement) {\n const responsePayload = {\n success: true,\n transaction: settlement.transaction,\n network: payment.network,\n };\n responseHeaders[PAYMENT_RESPONSE_HEADER] = Buffer.from(\n JSON.stringify(responsePayload)\n ).toString('base64');\n }\n\n this.sendJson(res, 200, {\n success: true,\n result,\n payment: settlement \n ? { transaction: settlement.transaction, status: 'settled' }\n : { status: 'pending' },\n }, responseHeaders);\n }\n\n /**\n * Return 402 with x402 payment requirements\n */\n private sendPaymentRequired(config: ServiceConfig, res: ServerResponse): void {\n const chain = getChain(this.manifest.provider.chain as ChainName);\n const amountInUnits = Math.floor(config.price * 1e6).toString();\n\n const requirements = [{\n scheme: 'exact',\n network: `eip155:${chain.chainId}`,\n maxAmountRequired: amountInUnits,\n resource: this.manifest.provider.wallet,\n description: `${config.name} - $${config.price} ${config.currency}`,\n // Include facilitator info for client\n extra: JSON.stringify({ facilitator: this.facilitatorUrl }),\n }];\n\n const encoded = Buffer.from(JSON.stringify(requirements)).toString('base64');\n\n res.writeHead(402, {\n 'Content-Type': 'application/json',\n [PAYMENT_REQUIRED_HEADER]: encoded,\n });\n res.end(JSON.stringify({\n error: 'Payment required',\n message: `Service requires $${config.price} ${config.currency}`,\n x402: requirements[0],\n }, null, 2));\n }\n\n /**\n * Basic payment validation (before calling facilitator)\n */\n private validatePayment(\n payment: X402PaymentPayload,\n config: ServiceConfig\n ): { valid: boolean; error?: string } {\n if (payment.x402Version !== X402_VERSION) {\n return { valid: false, error: `Unsupported x402 version: ${payment.x402Version}` };\n }\n\n if (payment.scheme !== 'exact') {\n return { valid: false, error: `Unsupported scheme: ${payment.scheme}` };\n }\n\n const chain = getChain(this.manifest.provider.chain as ChainName);\n const expectedNetwork = `eip155:${chain.chainId}`;\n if (payment.network !== expectedNetwork) {\n return { valid: false, error: `Network mismatch: expected ${expectedNetwork}` };\n }\n\n return { valid: true };\n }\n\n /**\n * Verify payment with facilitator\n */\n private async verifyWithFacilitator(\n payment: X402PaymentPayload,\n config: ServiceConfig\n ): Promise<{ valid: boolean; error?: string }> {\n try {\n const chain = getChain(this.manifest.provider.chain as ChainName);\n const amountInUnits = Math.floor(config.price * 1e6).toString();\n\n const requirements = {\n scheme: 'exact',\n network: `eip155:${chain.chainId}`,\n maxAmountRequired: amountInUnits,\n resource: this.manifest.provider.wallet,\n };\n\n const response = await fetch(`${this.facilitatorUrl}/verify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n paymentPayload: payment,\n paymentRequirements: requirements,\n }),\n });\n\n const result = await response.json() as any;\n\n if (!response.ok || !result.isValid) {\n return { valid: false, error: result.invalidReason || 'Verification failed' };\n }\n\n return { valid: true };\n } catch (err: any) {\n return { valid: false, error: `Facilitator error: ${err.message}` };\n }\n }\n\n /**\n * Settle payment with facilitator (execute on-chain transfer)\n */\n private async settleWithFacilitator(\n payment: X402PaymentPayload,\n config: ServiceConfig\n ): Promise<{ transaction?: string; status: string }> {\n const chain = getChain(this.manifest.provider.chain as ChainName);\n const amountInUnits = Math.floor(config.price * 1e6).toString();\n\n const requirements = {\n scheme: 'exact',\n network: `eip155:${chain.chainId}`,\n maxAmountRequired: amountInUnits,\n resource: this.manifest.provider.wallet,\n };\n\n const response = await fetch(`${this.facilitatorUrl}/settle`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n paymentPayload: payment,\n paymentRequirements: requirements,\n }),\n });\n\n const result = await response.json() as any;\n\n if (!response.ok) {\n throw new Error(result.error || 'Settlement failed');\n }\n\n return {\n transaction: result.transaction,\n status: result.status || 'settled',\n };\n }\n\n private async readBody(req: IncomingMessage): Promise<any> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', chunk => body += chunk);\n req.on('end', () => {\n try {\n resolve(body ? JSON.parse(body) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n }\n\n private sendJson(\n res: ServerResponse, \n status: number, \n data: any,\n extraHeaders?: Record<string, string>\n ): void {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (extraHeaders) {\n Object.assign(headers, extraHeaders);\n }\n res.writeHead(status, headers);\n res.end(JSON.stringify(data, null, 2));\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n explorer: 'https://basescan.org/address/',\n explorerTx: 'https://basescan.org/tx/',\n avgBlockTime: 2,\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n rpc: 'https://polygon-rpc.com',\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n rpc: 'https://eth.llamarpc.com',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n explorer: 'https://etherscan.io/address/',\n explorerTx: 'https://etherscan.io/tx/',\n avgBlockTime: 12,\n },\n\n // ============ Testnet ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n sepolia: {\n name: 'Sepolia',\n chainId: 11155111,\n rpc: 'https://rpc.sepolia.org',\n usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n explorer: 'https://sepolia.etherscan.io/address/',\n explorerTx: 'https://sepolia.etherscan.io/tx/',\n avgBlockTime: 12,\n },\n};\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * List all supported chains\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * Get chain config by chainId\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI (minimal, only required methods)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/server/index.ts"],"sourcesContent":["/**\n * MoltsPay Server - Payment infrastructure for AI Agents\n * \n * Supports both testnet (x402.org) and mainnet (CDP) facilitators.\n * Server does NOT need private key - facilitator handles on-chain settlement.\n * \n * Environment variables (from ~/.moltspay/.env or process.env):\n * USE_MAINNET=true - Use Base mainnet (requires CDP keys)\n * CDP_API_KEY_ID=xxx - Coinbase Developer Platform API key ID\n * CDP_API_KEY_SECRET=xxx - CDP API key secret\n * \n * Usage:\n * const server = new MoltsPayServer('./moltspay.services.json');\n * server.skill('text-to-video', async (params) => { ... });\n * server.listen(3000);\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { createServer, IncomingMessage, ServerResponse } from 'http';\nimport * as path from 'path';\nimport { getChain } from '../chains/index.js';\nimport type { ChainName } from '../chains/index.js';\nimport {\n ServicesManifest,\n ServiceConfig,\n SkillFunction,\n RegisteredSkill,\n MoltsPayServerOptions,\n} from './types.js';\n\nexport * from './types.js';\n\n// x402 constants\nconst X402_VERSION = 2;\nconst PAYMENT_REQUIRED_HEADER = 'x-payment-required';\nconst PAYMENT_HEADER = 'x-payment';\nconst PAYMENT_RESPONSE_HEADER = 'x-payment-response';\n\n// Facilitator URLs\nconst FACILITATOR_TESTNET = 'https://www.x402.org/facilitator';\nconst FACILITATOR_MAINNET = 'https://api.cdp.coinbase.com/platform/v2/x402';\n\n// USDC contract addresses\nconst USDC_ADDRESSES: Record<string, string> = {\n 'eip155:8453': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // Base mainnet\n 'eip155:84532': '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Base Sepolia\n};\n\n// EIP-712 domain info for USDC (required for signature verification)\nconst USDC_DOMAIN = {\n name: 'USD Coin',\n version: '2',\n};\n\ninterface X402PaymentPayload {\n x402Version: number;\n scheme: string;\n network: string;\n payload: any;\n}\n\ninterface CDPConfig {\n useMainnet: boolean;\n apiKeyId?: string;\n apiKeySecret?: string;\n}\n\n/**\n * Load environment from .env files\n */\nfunction loadEnvFiles(): void {\n // Try to load dotenv\n try {\n const dotenv = require('dotenv');\n \n // Priority: current dir > ~/.moltspay/\n const envPaths = [\n path.join(process.cwd(), '.env'),\n path.join(process.env.HOME || '', '.moltspay', '.env'),\n ];\n \n for (const envPath of envPaths) {\n if (existsSync(envPath)) {\n dotenv.config({ path: envPath });\n console.log(`[MoltsPay] Loaded config from ${envPath}`);\n break;\n }\n }\n } catch {\n // dotenv not installed, use process.env only\n }\n}\n\n/**\n * Get CDP configuration from environment\n */\nfunction getCDPConfig(): CDPConfig {\n loadEnvFiles();\n \n return {\n useMainnet: process.env.USE_MAINNET?.toLowerCase() === 'true',\n apiKeyId: process.env.CDP_API_KEY_ID,\n apiKeySecret: process.env.CDP_API_KEY_SECRET,\n };\n}\n\n/**\n * Generate CDP auth headers for API requests\n */\nasync function getCDPAuthHeaders(\n method: string,\n urlPath: string,\n body?: any\n): Promise<Record<string, string>> {\n const config = getCDPConfig();\n \n if (!config.apiKeyId || !config.apiKeySecret) {\n throw new Error('CDP_API_KEY_ID and CDP_API_KEY_SECRET required for mainnet');\n }\n \n try {\n // Import CDP SDK auth\n const { getAuthHeaders } = await import('@coinbase/cdp-sdk/auth');\n \n const headers = await getAuthHeaders({\n apiKeyId: config.apiKeyId,\n apiKeySecret: config.apiKeySecret,\n requestMethod: method,\n requestHost: 'api.cdp.coinbase.com',\n requestPath: urlPath,\n requestBody: body,\n });\n \n return headers;\n } catch (err: any) {\n console.error('[MoltsPay] Failed to generate CDP auth headers:', err.message);\n throw err;\n }\n}\n\nexport class MoltsPayServer {\n private manifest: ServicesManifest;\n private skills: Map<string, RegisteredSkill> = new Map();\n private options: MoltsPayServerOptions;\n private cdpConfig: CDPConfig;\n private facilitatorUrl: string;\n private networkId: string;\n\n constructor(servicesPath: string, options: MoltsPayServerOptions = {}) {\n // Load CDP config first\n this.cdpConfig = getCDPConfig();\n \n // Load services manifest\n const content = readFileSync(servicesPath, 'utf-8');\n this.manifest = JSON.parse(content) as ServicesManifest;\n \n this.options = {\n port: options.port || 3000,\n host: options.host || '0.0.0.0',\n };\n\n // Determine facilitator and network based on config\n if (this.cdpConfig.useMainnet) {\n if (!this.cdpConfig.apiKeyId || !this.cdpConfig.apiKeySecret) {\n console.warn('[MoltsPay] WARNING: USE_MAINNET=true but CDP keys not set!');\n console.warn('[MoltsPay] Set CDP_API_KEY_ID and CDP_API_KEY_SECRET in ~/.moltspay/.env');\n }\n this.facilitatorUrl = FACILITATOR_MAINNET;\n this.networkId = 'eip155:8453'; // Base mainnet\n } else {\n this.facilitatorUrl = options.facilitatorUrl || FACILITATOR_TESTNET;\n this.networkId = 'eip155:84532'; // Base Sepolia testnet\n }\n\n const networkName = this.cdpConfig.useMainnet ? 'Base mainnet' : 'Base Sepolia (testnet)';\n const facilitatorName = this.cdpConfig.useMainnet ? 'CDP' : 'x402.org';\n \n console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);\n console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);\n console.log(`[MoltsPay] Receive wallet: ${this.manifest.provider.wallet}`);\n console.log(`[MoltsPay] Network: ${this.networkId} (${networkName})`);\n console.log(`[MoltsPay] Facilitator: ${facilitatorName} (${this.facilitatorUrl})`);\n if (this.cdpConfig.useMainnet && this.cdpConfig.apiKeyId) {\n console.log(`[MoltsPay] CDP API Key: ${this.cdpConfig.apiKeyId.slice(0, 8)}...`);\n }\n console.log(`[MoltsPay] Protocol: x402 (gasless for both client AND server)`);\n }\n\n /**\n * Register a skill handler for a service\n */\n skill(serviceId: string, handler: SkillFunction): this {\n const config = this.manifest.services.find(s => s.id === serviceId);\n if (!config) {\n throw new Error(`Service '${serviceId}' not found in manifest`);\n }\n this.skills.set(serviceId, { id: serviceId, config, handler });\n return this;\n }\n\n /**\n * Start HTTP server\n */\n listen(port?: number): void {\n const p = port || this.options.port || 3000;\n const host = this.options.host || '0.0.0.0';\n\n const server = createServer((req, res) => this.handleRequest(req, res));\n server.listen(p, host, () => {\n console.log(`[MoltsPay] Server listening on http://${host}:${p}`);\n console.log(`[MoltsPay] Endpoints:`);\n console.log(` GET /services - List available services`);\n console.log(` POST /execute - Execute service (x402 payment)`);\n });\n }\n\n /**\n * Handle incoming request\n */\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // CORS\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Payment');\n res.setHeader('Access-Control-Expose-Headers', 'X-Payment-Required, X-Payment-Response');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n try {\n const url = new URL(req.url || '/', `http://${req.headers.host}`);\n \n if (url.pathname === '/services' && req.method === 'GET') {\n return this.handleGetServices(res);\n }\n\n if (url.pathname === '/execute' && req.method === 'POST') {\n const body = await this.readBody(req);\n const paymentHeader = req.headers[PAYMENT_HEADER] as string | undefined;\n return await this.handleExecute(body, paymentHeader, res);\n }\n\n // Not found\n this.sendJson(res, 404, { error: 'Not found' });\n } catch (err: any) {\n console.error('[MoltsPay] Error:', err);\n this.sendJson(res, 500, { error: err.message || 'Internal error' });\n }\n }\n\n /**\n * GET /services - List available services\n */\n private handleGetServices(res: ServerResponse): void {\n const services = this.manifest.services.map(s => ({\n id: s.id,\n name: s.name,\n description: s.description,\n price: s.price,\n currency: s.currency,\n input: s.input,\n output: s.output,\n available: this.skills.has(s.id),\n }));\n\n this.sendJson(res, 200, {\n provider: this.manifest.provider,\n services,\n x402: {\n version: X402_VERSION,\n network: this.networkId,\n schemes: ['exact'],\n facilitator: this.cdpConfig.useMainnet ? 'cdp' : 'x402.org',\n mainnet: this.cdpConfig.useMainnet,\n },\n });\n }\n\n /**\n * POST /execute - Execute service with x402 payment\n */\n private async handleExecute(\n body: any,\n paymentHeader: string | undefined,\n res: ServerResponse\n ): Promise<void> {\n const { service, params } = body;\n\n if (!service) {\n return this.sendJson(res, 400, { error: 'Missing service' });\n }\n\n const skill = this.skills.get(service);\n if (!skill) {\n return this.sendJson(res, 404, { error: `Service '${service}' not found or not registered` });\n }\n\n // Validate required params\n for (const [key, field] of Object.entries(skill.config.input)) {\n if (field.required && (!params || params[key] === undefined)) {\n return this.sendJson(res, 400, { error: `Missing required param: ${key}` });\n }\n }\n\n // If no payment header, return 402 with payment requirements\n if (!paymentHeader) {\n return this.sendPaymentRequired(skill.config, res);\n }\n\n // Parse payment payload\n let payment: X402PaymentPayload;\n try {\n const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');\n payment = JSON.parse(decoded);\n } catch {\n return this.sendJson(res, 400, { error: 'Invalid X-Payment header' });\n }\n\n // Validate basic payment fields\n const validation = this.validatePayment(payment, skill.config);\n if (!validation.valid) {\n return this.sendJson(res, 402, { error: validation.error });\n }\n\n // Verify payment with facilitator\n console.log(`[MoltsPay] Verifying payment with facilitator...`);\n const verifyResult = await this.verifyWithFacilitator(payment, skill.config);\n if (!verifyResult.valid) {\n return this.sendJson(res, 402, { error: `Payment verification failed: ${verifyResult.error}` });\n }\n\n // Execute skill FIRST (pay-for-success)\n console.log(`[MoltsPay] Executing skill: ${service}`);\n let result: any;\n try {\n result = await skill.handler(params || {});\n } catch (err: any) {\n console.error('[MoltsPay] Skill execution failed:', err.message);\n return this.sendJson(res, 500, {\n error: 'Service execution failed',\n message: err.message,\n });\n }\n\n // Skill succeeded - now settle payment with facilitator\n console.log(`[MoltsPay] Skill succeeded, settling payment...`);\n let settlement: any = null;\n try {\n settlement = await this.settleWithFacilitator(payment, skill.config);\n console.log(`[MoltsPay] Payment settled: ${settlement.transaction || 'pending'}`);\n } catch (err: any) {\n console.error('[MoltsPay] Settlement failed:', err.message);\n }\n\n // Build response\n const responseHeaders: Record<string, string> = {};\n if (settlement) {\n const responsePayload = {\n success: true,\n transaction: settlement.transaction,\n network: payment.network,\n };\n responseHeaders[PAYMENT_RESPONSE_HEADER] = Buffer.from(\n JSON.stringify(responsePayload)\n ).toString('base64');\n }\n\n this.sendJson(res, 200, {\n success: true,\n result,\n payment: settlement \n ? { transaction: settlement.transaction, status: 'settled' }\n : { status: 'pending' },\n }, responseHeaders);\n }\n\n /**\n * Return 402 with x402 payment requirements\n */\n private sendPaymentRequired(config: ServiceConfig, res: ServerResponse): void {\n const requirements = [this.buildPaymentRequirements(config)];\n requirements[0].description = `${config.name} - $${config.price} ${config.currency}`;\n\n const encoded = Buffer.from(JSON.stringify(requirements)).toString('base64');\n\n res.writeHead(402, {\n 'Content-Type': 'application/json',\n [PAYMENT_REQUIRED_HEADER]: encoded,\n });\n res.end(JSON.stringify({\n error: 'Payment required',\n message: `Service requires $${config.price} ${config.currency}`,\n x402: requirements[0],\n }, null, 2));\n }\n\n /**\n * Basic payment validation\n */\n private validatePayment(\n payment: X402PaymentPayload,\n config: ServiceConfig\n ): { valid: boolean; error?: string } {\n if (payment.x402Version !== X402_VERSION) {\n return { valid: false, error: `Unsupported x402 version: ${payment.x402Version}` };\n }\n\n if (payment.scheme !== 'exact') {\n return { valid: false, error: `Unsupported scheme: ${payment.scheme}` };\n }\n\n if (payment.network !== this.networkId) {\n return { valid: false, error: `Network mismatch: expected ${this.networkId}, got ${payment.network}` };\n }\n\n return { valid: true };\n }\n\n /**\n * Build complete payment requirements for facilitator\n */\n private buildPaymentRequirements(config: ServiceConfig): Record<string, any> {\n const amountInUnits = Math.floor(config.price * 1e6).toString();\n const usdcAddress = USDC_ADDRESSES[this.networkId];\n\n return {\n scheme: 'exact',\n network: this.networkId,\n maxAmountRequired: amountInUnits,\n amount: amountInUnits,\n asset: usdcAddress,\n payTo: this.manifest.provider.wallet,\n maxTimeoutSeconds: 300,\n extra: USDC_DOMAIN,\n };\n }\n\n /**\n * Verify payment with facilitator (testnet or CDP)\n */\n private async verifyWithFacilitator(\n payment: X402PaymentPayload,\n config: ServiceConfig\n ): Promise<{ valid: boolean; error?: string }> {\n try {\n const requirements = this.buildPaymentRequirements(config);\n\n const requestBody = {\n paymentPayload: payment,\n paymentRequirements: requirements,\n };\n\n console.log('[MoltsPay] Verify request:', JSON.stringify(requestBody, null, 2));\n\n // Build headers\n let headers: Record<string, string> = { 'Content-Type': 'application/json' };\n \n if (this.cdpConfig.useMainnet) {\n // Add CDP auth headers for mainnet\n const authHeaders = await getCDPAuthHeaders(\n 'POST',\n '/platform/v2/x402/verify',\n requestBody\n );\n headers = { ...headers, ...authHeaders };\n }\n\n const response = await fetch(`${this.facilitatorUrl}/verify`, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n });\n\n const result = await response.json() as any;\n console.log('[MoltsPay] Verify response:', JSON.stringify(result, null, 2));\n\n if (!response.ok || !result.isValid) {\n return { valid: false, error: result.invalidReason || result.error || 'Verification failed' };\n }\n\n return { valid: true };\n } catch (err: any) {\n return { valid: false, error: `Facilitator error: ${err.message}` };\n }\n }\n\n /**\n * Settle payment with facilitator (execute on-chain transfer)\n */\n private async settleWithFacilitator(\n payment: X402PaymentPayload,\n config: ServiceConfig\n ): Promise<{ transaction?: string; status: string }> {\n const requirements = this.buildPaymentRequirements(config);\n\n const requestBody = {\n paymentPayload: payment,\n paymentRequirements: requirements,\n };\n\n // Build headers\n let headers: Record<string, string> = { 'Content-Type': 'application/json' };\n \n if (this.cdpConfig.useMainnet) {\n // Add CDP auth headers for mainnet\n const authHeaders = await getCDPAuthHeaders(\n 'POST',\n '/platform/v2/x402/settle',\n requestBody\n );\n headers = { ...headers, ...authHeaders };\n }\n\n const response = await fetch(`${this.facilitatorUrl}/settle`, {\n method: 'POST',\n headers,\n body: JSON.stringify(requestBody),\n });\n\n const result = await response.json() as any;\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || result.errorReason || 'Settlement failed');\n }\n\n return {\n transaction: result.transaction,\n status: result.status || 'settled',\n };\n }\n\n private async readBody(req: IncomingMessage): Promise<any> {\n return new Promise((resolve, reject) => {\n let body = '';\n req.on('data', chunk => body += chunk);\n req.on('end', () => {\n try {\n resolve(body ? JSON.parse(body) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n }\n\n private sendJson(\n res: ServerResponse, \n status: number, \n data: any,\n extraHeaders?: Record<string, string>\n ): void {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (extraHeaders) {\n Object.assign(headers, extraHeaders);\n }\n res.writeHead(status, headers);\n res.end(JSON.stringify(data, null, 2));\n }\n}\n"],"mappings":"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","names":[]}