moltspay 0.8.3 → 0.8.4
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/dist/cli/index.js +9 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +9 -5
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9 -5
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +9 -5
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +9 -5
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/server/index.d.mts
CHANGED
package/dist/server/index.d.ts
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -289,12 +289,16 @@ var MoltsPayServer = class {
|
|
|
289
289
|
}, responseHeaders);
|
|
290
290
|
}
|
|
291
291
|
/**
|
|
292
|
-
* Return 402 with x402 payment requirements
|
|
292
|
+
* Return 402 with x402 payment requirements (v2 format)
|
|
293
293
|
*/
|
|
294
294
|
sendPaymentRequired(config, res) {
|
|
295
|
-
const requirements =
|
|
296
|
-
requirements
|
|
297
|
-
const
|
|
295
|
+
const requirements = this.buildPaymentRequirements(config);
|
|
296
|
+
requirements.description = `${config.name} - $${config.price} ${config.currency}`;
|
|
297
|
+
const paymentRequired = {
|
|
298
|
+
x402Version: X402_VERSION,
|
|
299
|
+
accepts: [requirements]
|
|
300
|
+
};
|
|
301
|
+
const encoded = Buffer.from(JSON.stringify(paymentRequired)).toString("base64");
|
|
298
302
|
res.writeHead(402, {
|
|
299
303
|
"Content-Type": "application/json",
|
|
300
304
|
[PAYMENT_REQUIRED_HEADER]: encoded
|
|
@@ -302,7 +306,7 @@ var MoltsPayServer = class {
|
|
|
302
306
|
res.end(JSON.stringify({
|
|
303
307
|
error: "Payment required",
|
|
304
308
|
message: `Service requires $${config.price} ${config.currency}`,
|
|
305
|
-
x402:
|
|
309
|
+
x402: paymentRequired
|
|
306
310
|
}, null, 2));
|
|
307
311
|
}
|
|
308
312
|
/**
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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":[]}
|
|
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 (v2 format)\n */\n private sendPaymentRequired(config: ServiceConfig, res: ServerResponse): void {\n const requirements = this.buildPaymentRequirements(config);\n requirements.description = `${config.name} - $${config.price} ${config.currency}`;\n\n // x402 v2 format: PaymentRequired object with accepts array\n const paymentRequired = {\n x402Version: X402_VERSION,\n accepts: [requirements],\n };\n\n const encoded = Buffer.from(JSON.stringify(paymentRequired)).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: paymentRequired,\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":[]}
|
package/dist/server/index.mjs
CHANGED
|
@@ -262,12 +262,16 @@ var MoltsPayServer = class {
|
|
|
262
262
|
}, responseHeaders);
|
|
263
263
|
}
|
|
264
264
|
/**
|
|
265
|
-
* Return 402 with x402 payment requirements
|
|
265
|
+
* Return 402 with x402 payment requirements (v2 format)
|
|
266
266
|
*/
|
|
267
267
|
sendPaymentRequired(config, res) {
|
|
268
|
-
const requirements =
|
|
269
|
-
requirements
|
|
270
|
-
const
|
|
268
|
+
const requirements = this.buildPaymentRequirements(config);
|
|
269
|
+
requirements.description = `${config.name} - $${config.price} ${config.currency}`;
|
|
270
|
+
const paymentRequired = {
|
|
271
|
+
x402Version: X402_VERSION,
|
|
272
|
+
accepts: [requirements]
|
|
273
|
+
};
|
|
274
|
+
const encoded = Buffer.from(JSON.stringify(paymentRequired)).toString("base64");
|
|
271
275
|
res.writeHead(402, {
|
|
272
276
|
"Content-Type": "application/json",
|
|
273
277
|
[PAYMENT_REQUIRED_HEADER]: encoded
|
|
@@ -275,7 +279,7 @@ var MoltsPayServer = class {
|
|
|
275
279
|
res.end(JSON.stringify({
|
|
276
280
|
error: "Payment required",
|
|
277
281
|
message: `Service requires $${config.price} ${config.currency}`,
|
|
278
|
-
x402:
|
|
282
|
+
x402: paymentRequired
|
|
279
283
|
}, null, 2));
|
|
280
284
|
}
|
|
281
285
|
/**
|
|
@@ -1 +1 @@
|
|
|
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":[]}
|
|
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 (v2 format)\n */\n private sendPaymentRequired(config: ServiceConfig, res: ServerResponse): void {\n const requirements = this.buildPaymentRequirements(config);\n requirements.description = `${config.name} - $${config.price} ${config.currency}`;\n\n // x402 v2 format: PaymentRequired object with accepts array\n const paymentRequired = {\n x402Version: X402_VERSION,\n accepts: [requirements],\n };\n\n const encoded = Buffer.from(JSON.stringify(paymentRequired)).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: paymentRequired,\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":[]}
|