moltspay 0.5.4 → 0.7.1

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.
Files changed (68) hide show
  1. package/README.md +0 -124
  2. package/dist/cdp/index.d.mts +111 -0
  3. package/dist/cdp/index.d.ts +111 -0
  4. package/dist/cdp/index.js +30655 -0
  5. package/dist/cdp/index.js.map +1 -0
  6. package/dist/cdp/index.mjs +30631 -0
  7. package/dist/cdp/index.mjs.map +1 -0
  8. package/dist/chains/index.d.mts +1 -1
  9. package/dist/chains/index.d.ts +1 -1
  10. package/dist/cli/index.js +990 -0
  11. package/dist/cli/index.js.map +1 -0
  12. package/dist/cli/index.mjs +967 -0
  13. package/dist/cli/index.mjs.map +1 -0
  14. package/dist/client/index.d.mts +134 -0
  15. package/dist/client/index.d.ts +134 -0
  16. package/dist/client/index.js +331 -0
  17. package/dist/client/index.js.map +1 -0
  18. package/dist/client/index.mjs +296 -0
  19. package/dist/client/index.mjs.map +1 -0
  20. package/dist/createWallet-D53qu7ie.d.mts +77 -0
  21. package/dist/createWallet-D53qu7ie.d.ts +77 -0
  22. package/dist/index-Dg8n6wdW.d.mts +32 -0
  23. package/dist/index-Dg8n6wdW.d.ts +32 -0
  24. package/dist/index.d.mts +6 -1483
  25. package/dist/index.d.ts +6 -1483
  26. package/dist/index.js +31039 -4254
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.mjs +31042 -4203
  29. package/dist/index.mjs.map +1 -1
  30. package/dist/server/index.d.mts +120 -0
  31. package/dist/server/index.d.ts +120 -0
  32. package/dist/server/index.js +418 -0
  33. package/dist/server/index.js.map +1 -0
  34. package/dist/server/index.mjs +393 -0
  35. package/dist/server/index.mjs.map +1 -0
  36. package/dist/wallet/index.d.mts +3 -451
  37. package/dist/wallet/index.d.ts +3 -451
  38. package/dist/wallet/index.js +5 -1021
  39. package/dist/wallet/index.js.map +1 -1
  40. package/dist/wallet/index.mjs +16 -1015
  41. package/dist/wallet/index.mjs.map +1 -1
  42. package/package.json +19 -19
  43. package/dist/cli.js +0 -1984
  44. package/dist/cli.js.map +0 -1
  45. package/dist/cli.mjs +0 -1969
  46. package/dist/cli.mjs.map +0 -1
  47. package/dist/guide/index.d.mts +0 -39
  48. package/dist/guide/index.d.ts +0 -39
  49. package/dist/guide/index.js +0 -181
  50. package/dist/guide/index.js.map +0 -1
  51. package/dist/guide/index.mjs +0 -152
  52. package/dist/guide/index.mjs.map +0 -1
  53. package/dist/index-CyFg9s2m.d.mts +0 -161
  54. package/dist/index-CyFg9s2m.d.ts +0 -161
  55. package/dist/orders/index.d.mts +0 -97
  56. package/dist/orders/index.d.ts +0 -97
  57. package/dist/orders/index.js +0 -162
  58. package/dist/orders/index.js.map +0 -1
  59. package/dist/orders/index.mjs +0 -136
  60. package/dist/orders/index.mjs.map +0 -1
  61. package/dist/permit/index.d.mts +0 -49
  62. package/dist/permit/index.d.ts +0 -49
  63. package/dist/permit/index.js +0 -273
  64. package/dist/permit/index.js.map +0 -1
  65. package/dist/permit/index.mjs +0 -246
  66. package/dist/permit/index.mjs.map +0 -1
  67. /package/dist/{cli.d.mts → cli/index.d.mts} +0 -0
  68. /package/dist/{cli.d.ts → cli/index.d.ts} +0 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * MoltsPay Server Types
3
+ */
4
+ interface ServiceConfig {
5
+ id: string;
6
+ name: string;
7
+ description?: string;
8
+ price: number;
9
+ currency: string;
10
+ input: Record<string, InputField>;
11
+ output: Record<string, OutputField>;
12
+ /** Shell command to execute for this service. Params passed as JSON to stdin. */
13
+ command?: string;
14
+ }
15
+ interface InputField {
16
+ type: 'string' | 'number' | 'boolean' | 'object';
17
+ required?: boolean;
18
+ description?: string;
19
+ }
20
+ interface OutputField {
21
+ type: 'string' | 'number' | 'boolean' | 'object';
22
+ description?: string;
23
+ }
24
+ interface ProviderConfig {
25
+ name: string;
26
+ description?: string;
27
+ wallet: string;
28
+ chain: string;
29
+ }
30
+ interface ServicesManifest {
31
+ provider: ProviderConfig;
32
+ services: ServiceConfig[];
33
+ }
34
+ type SkillFunction = (params: Record<string, any>) => Promise<Record<string, any>>;
35
+ interface RegisteredSkill {
36
+ id: string;
37
+ config: ServiceConfig;
38
+ handler: SkillFunction;
39
+ }
40
+ interface PaymentRequest {
41
+ chargeId: string;
42
+ service: string;
43
+ amount: number;
44
+ currency: string;
45
+ wallet: string;
46
+ chain: string;
47
+ expiresAt: number;
48
+ }
49
+ interface VerifyRequest {
50
+ chargeId: string;
51
+ txHash: string;
52
+ }
53
+ type ChargeStatus = 'pending' | 'paid' | 'completed' | 'expired' | 'failed';
54
+ interface Charge {
55
+ id: string;
56
+ service: string;
57
+ params: Record<string, any>;
58
+ amount: number;
59
+ currency: string;
60
+ status: ChargeStatus;
61
+ txHash?: string;
62
+ result?: Record<string, any>;
63
+ createdAt: number;
64
+ expiresAt: number;
65
+ paidAt?: number;
66
+ completedAt?: number;
67
+ }
68
+ interface MoltsPayServerOptions {
69
+ port?: number;
70
+ host?: string;
71
+ chargeExpirySecs?: number;
72
+ }
73
+
74
+ /**
75
+ * MoltsPay Server - Payment infrastructure for AI Agents
76
+ *
77
+ * Usage:
78
+ * const server = new MoltsPayServer('./moltspay.services.json');
79
+ * server.skill('text-to-video', async (params) => { ... });
80
+ * server.listen(3000);
81
+ */
82
+
83
+ declare class MoltsPayServer {
84
+ private manifest;
85
+ private skills;
86
+ private charges;
87
+ private options;
88
+ constructor(servicesPath: string, options?: MoltsPayServerOptions);
89
+ /**
90
+ * Register a skill handler for a service
91
+ */
92
+ skill(serviceId: string, handler: SkillFunction): this;
93
+ /**
94
+ * Start the server
95
+ */
96
+ listen(port?: number): void;
97
+ private handleRequest;
98
+ /**
99
+ * GET /services - List available services
100
+ */
101
+ private handleGetServices;
102
+ /**
103
+ * POST /pay - Create payment request
104
+ * Body: { service: string, params: object }
105
+ */
106
+ private handlePay;
107
+ /**
108
+ * POST /verify - Verify payment and execute skill
109
+ * Body: { chargeId: string, txHash: string }
110
+ */
111
+ private handleVerify;
112
+ /**
113
+ * GET /status/:chargeId - Check charge status
114
+ */
115
+ private handleStatus;
116
+ private readBody;
117
+ private sendJson;
118
+ }
119
+
120
+ export { type Charge, type ChargeStatus, type InputField, MoltsPayServer, type MoltsPayServerOptions, type OutputField, type PaymentRequest, type ProviderConfig, type RegisteredSkill, type ServiceConfig, type ServicesManifest, type SkillFunction, type VerifyRequest };
@@ -0,0 +1,120 @@
1
+ /**
2
+ * MoltsPay Server Types
3
+ */
4
+ interface ServiceConfig {
5
+ id: string;
6
+ name: string;
7
+ description?: string;
8
+ price: number;
9
+ currency: string;
10
+ input: Record<string, InputField>;
11
+ output: Record<string, OutputField>;
12
+ /** Shell command to execute for this service. Params passed as JSON to stdin. */
13
+ command?: string;
14
+ }
15
+ interface InputField {
16
+ type: 'string' | 'number' | 'boolean' | 'object';
17
+ required?: boolean;
18
+ description?: string;
19
+ }
20
+ interface OutputField {
21
+ type: 'string' | 'number' | 'boolean' | 'object';
22
+ description?: string;
23
+ }
24
+ interface ProviderConfig {
25
+ name: string;
26
+ description?: string;
27
+ wallet: string;
28
+ chain: string;
29
+ }
30
+ interface ServicesManifest {
31
+ provider: ProviderConfig;
32
+ services: ServiceConfig[];
33
+ }
34
+ type SkillFunction = (params: Record<string, any>) => Promise<Record<string, any>>;
35
+ interface RegisteredSkill {
36
+ id: string;
37
+ config: ServiceConfig;
38
+ handler: SkillFunction;
39
+ }
40
+ interface PaymentRequest {
41
+ chargeId: string;
42
+ service: string;
43
+ amount: number;
44
+ currency: string;
45
+ wallet: string;
46
+ chain: string;
47
+ expiresAt: number;
48
+ }
49
+ interface VerifyRequest {
50
+ chargeId: string;
51
+ txHash: string;
52
+ }
53
+ type ChargeStatus = 'pending' | 'paid' | 'completed' | 'expired' | 'failed';
54
+ interface Charge {
55
+ id: string;
56
+ service: string;
57
+ params: Record<string, any>;
58
+ amount: number;
59
+ currency: string;
60
+ status: ChargeStatus;
61
+ txHash?: string;
62
+ result?: Record<string, any>;
63
+ createdAt: number;
64
+ expiresAt: number;
65
+ paidAt?: number;
66
+ completedAt?: number;
67
+ }
68
+ interface MoltsPayServerOptions {
69
+ port?: number;
70
+ host?: string;
71
+ chargeExpirySecs?: number;
72
+ }
73
+
74
+ /**
75
+ * MoltsPay Server - Payment infrastructure for AI Agents
76
+ *
77
+ * Usage:
78
+ * const server = new MoltsPayServer('./moltspay.services.json');
79
+ * server.skill('text-to-video', async (params) => { ... });
80
+ * server.listen(3000);
81
+ */
82
+
83
+ declare class MoltsPayServer {
84
+ private manifest;
85
+ private skills;
86
+ private charges;
87
+ private options;
88
+ constructor(servicesPath: string, options?: MoltsPayServerOptions);
89
+ /**
90
+ * Register a skill handler for a service
91
+ */
92
+ skill(serviceId: string, handler: SkillFunction): this;
93
+ /**
94
+ * Start the server
95
+ */
96
+ listen(port?: number): void;
97
+ private handleRequest;
98
+ /**
99
+ * GET /services - List available services
100
+ */
101
+ private handleGetServices;
102
+ /**
103
+ * POST /pay - Create payment request
104
+ * Body: { service: string, params: object }
105
+ */
106
+ private handlePay;
107
+ /**
108
+ * POST /verify - Verify payment and execute skill
109
+ * Body: { chargeId: string, txHash: string }
110
+ */
111
+ private handleVerify;
112
+ /**
113
+ * GET /status/:chargeId - Check charge status
114
+ */
115
+ private handleStatus;
116
+ private readBody;
117
+ private sendJson;
118
+ }
119
+
120
+ export { type Charge, type ChargeStatus, type InputField, MoltsPayServer, type MoltsPayServerOptions, type OutputField, type PaymentRequest, type ProviderConfig, type RegisteredSkill, type ServiceConfig, type ServicesManifest, type SkillFunction, type VerifyRequest };
@@ -0,0 +1,418 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/server/index.ts
21
+ var server_exports = {};
22
+ __export(server_exports, {
23
+ MoltsPayServer: () => MoltsPayServer
24
+ });
25
+ module.exports = __toCommonJS(server_exports);
26
+ var import_fs = require("fs");
27
+ var import_http = require("http");
28
+
29
+ // src/verify/index.ts
30
+ var import_ethers = require("ethers");
31
+
32
+ // src/chains/index.ts
33
+ var CHAINS = {
34
+ // ============ Mainnet ============
35
+ base: {
36
+ name: "Base",
37
+ chainId: 8453,
38
+ rpc: "https://mainnet.base.org",
39
+ usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
40
+ explorer: "https://basescan.org/address/",
41
+ explorerTx: "https://basescan.org/tx/",
42
+ avgBlockTime: 2
43
+ },
44
+ polygon: {
45
+ name: "Polygon",
46
+ chainId: 137,
47
+ rpc: "https://polygon-rpc.com",
48
+ usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
49
+ explorer: "https://polygonscan.com/address/",
50
+ explorerTx: "https://polygonscan.com/tx/",
51
+ avgBlockTime: 2
52
+ },
53
+ ethereum: {
54
+ name: "Ethereum",
55
+ chainId: 1,
56
+ rpc: "https://eth.llamarpc.com",
57
+ usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
58
+ explorer: "https://etherscan.io/address/",
59
+ explorerTx: "https://etherscan.io/tx/",
60
+ avgBlockTime: 12
61
+ },
62
+ // ============ Testnet ============
63
+ base_sepolia: {
64
+ name: "Base Sepolia",
65
+ chainId: 84532,
66
+ rpc: "https://sepolia.base.org",
67
+ usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
68
+ explorer: "https://sepolia.basescan.org/address/",
69
+ explorerTx: "https://sepolia.basescan.org/tx/",
70
+ avgBlockTime: 2
71
+ },
72
+ sepolia: {
73
+ name: "Sepolia",
74
+ chainId: 11155111,
75
+ rpc: "https://rpc.sepolia.org",
76
+ usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
77
+ explorer: "https://sepolia.etherscan.io/address/",
78
+ explorerTx: "https://sepolia.etherscan.io/tx/",
79
+ avgBlockTime: 12
80
+ }
81
+ };
82
+ function getChain(name) {
83
+ const config = CHAINS[name];
84
+ if (!config) {
85
+ throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(", ")}`);
86
+ }
87
+ return config;
88
+ }
89
+ function getChainById(chainId) {
90
+ return Object.values(CHAINS).find((c) => c.chainId === chainId);
91
+ }
92
+
93
+ // src/verify/index.ts
94
+ var TRANSFER_EVENT_TOPIC = import_ethers.ethers.id("Transfer(address,address,uint256)");
95
+ async function verifyPayment(params) {
96
+ const { txHash, expectedAmount, expectedTo } = params;
97
+ let chain;
98
+ try {
99
+ if (typeof params.chain === "number") {
100
+ chain = getChainById(params.chain);
101
+ } else {
102
+ chain = getChain(params.chain || "base");
103
+ }
104
+ if (!chain) {
105
+ return { verified: false, error: `Unsupported chain: ${params.chain}` };
106
+ }
107
+ } catch (e) {
108
+ return { verified: false, error: `Unsupported chain: ${params.chain}` };
109
+ }
110
+ try {
111
+ const provider = new import_ethers.ethers.JsonRpcProvider(chain.rpc);
112
+ const receipt = await provider.getTransactionReceipt(txHash);
113
+ if (!receipt) {
114
+ return { verified: false, error: "Transaction not found or not confirmed" };
115
+ }
116
+ if (receipt.status !== 1) {
117
+ return { verified: false, error: "Transaction failed" };
118
+ }
119
+ const usdcAddress = chain.usdc?.toLowerCase();
120
+ if (!usdcAddress) {
121
+ return { verified: false, error: `Chain ${chain.name} USDC address not configured` };
122
+ }
123
+ for (const log of receipt.logs) {
124
+ if (log.address.toLowerCase() !== usdcAddress) {
125
+ continue;
126
+ }
127
+ if (log.topics.length < 3 || log.topics[0] !== TRANSFER_EVENT_TOPIC) {
128
+ continue;
129
+ }
130
+ const from = "0x" + log.topics[1].slice(-40);
131
+ const to = "0x" + log.topics[2].slice(-40);
132
+ const amountRaw = BigInt(log.data);
133
+ const amount = Number(amountRaw) / 1e6;
134
+ if (expectedTo && to.toLowerCase() !== expectedTo.toLowerCase()) {
135
+ continue;
136
+ }
137
+ if (amount < expectedAmount) {
138
+ return {
139
+ verified: false,
140
+ error: `Insufficient amount: received ${amount} USDC, expected ${expectedAmount} USDC`,
141
+ amount,
142
+ from,
143
+ to,
144
+ txHash,
145
+ blockNumber: receipt.blockNumber
146
+ };
147
+ }
148
+ return {
149
+ verified: true,
150
+ amount,
151
+ from,
152
+ to,
153
+ txHash,
154
+ blockNumber: receipt.blockNumber
155
+ };
156
+ }
157
+ return { verified: false, error: "No USDC transfer found" };
158
+ } catch (e) {
159
+ return { verified: false, error: e.message || String(e) };
160
+ }
161
+ }
162
+
163
+ // src/server/index.ts
164
+ function generateChargeId() {
165
+ return "ch_" + Math.random().toString(36).substring(2, 15);
166
+ }
167
+ var MoltsPayServer = class {
168
+ manifest;
169
+ skills = /* @__PURE__ */ new Map();
170
+ charges = /* @__PURE__ */ new Map();
171
+ options;
172
+ constructor(servicesPath, options = {}) {
173
+ const content = (0, import_fs.readFileSync)(servicesPath, "utf-8");
174
+ this.manifest = JSON.parse(content);
175
+ this.options = {
176
+ port: options.port || 3e3,
177
+ host: options.host || "0.0.0.0",
178
+ chargeExpirySecs: options.chargeExpirySecs || 300
179
+ // 5 minutes
180
+ };
181
+ console.log(`[MoltsPay] Loaded ${this.manifest.services.length} services from ${servicesPath}`);
182
+ console.log(`[MoltsPay] Provider: ${this.manifest.provider.name}`);
183
+ console.log(`[MoltsPay] Wallet: ${this.manifest.provider.wallet}`);
184
+ }
185
+ /**
186
+ * Register a skill handler for a service
187
+ */
188
+ skill(serviceId, handler) {
189
+ const config = this.manifest.services.find((s) => s.id === serviceId);
190
+ if (!config) {
191
+ throw new Error(`Service '${serviceId}' not found in manifest`);
192
+ }
193
+ this.skills.set(serviceId, {
194
+ id: serviceId,
195
+ config,
196
+ handler
197
+ });
198
+ console.log(`[MoltsPay] Registered skill: ${serviceId} ($${config.price} ${config.currency})`);
199
+ return this;
200
+ }
201
+ /**
202
+ * Start the server
203
+ */
204
+ listen(port) {
205
+ const p = port || this.options.port;
206
+ const server = (0, import_http.createServer)((req, res) => this.handleRequest(req, res));
207
+ server.listen(p, this.options.host, () => {
208
+ console.log(`[MoltsPay] Server listening on http://${this.options.host}:${p}`);
209
+ console.log(`[MoltsPay] Endpoints:`);
210
+ console.log(` GET /services - List available services`);
211
+ console.log(` POST /pay - Create payment & execute service`);
212
+ console.log(` POST /verify - Verify payment & get result`);
213
+ console.log(` GET /status/:id - Check charge status`);
214
+ });
215
+ }
216
+ async handleRequest(req, res) {
217
+ const url = new URL(req.url || "/", `http://${req.headers.host}`);
218
+ const path = url.pathname;
219
+ const method = req.method || "GET";
220
+ res.setHeader("Access-Control-Allow-Origin", "*");
221
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
222
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
223
+ if (method === "OPTIONS") {
224
+ res.writeHead(204);
225
+ res.end();
226
+ return;
227
+ }
228
+ try {
229
+ if (method === "GET" && path === "/services") {
230
+ return this.handleGetServices(res);
231
+ }
232
+ if (method === "POST" && path === "/pay") {
233
+ const body = await this.readBody(req);
234
+ return this.handlePay(body, res);
235
+ }
236
+ if (method === "POST" && path === "/verify") {
237
+ const body = await this.readBody(req);
238
+ return this.handleVerify(body, res);
239
+ }
240
+ if (method === "GET" && path.startsWith("/status/")) {
241
+ const chargeId = path.replace("/status/", "");
242
+ return this.handleStatus(chargeId, res);
243
+ }
244
+ this.sendJson(res, 404, { error: "Not found" });
245
+ } catch (err) {
246
+ console.error("[MoltsPay] Error:", err);
247
+ this.sendJson(res, 500, { error: err.message || "Internal error" });
248
+ }
249
+ }
250
+ /**
251
+ * GET /services - List available services
252
+ */
253
+ handleGetServices(res) {
254
+ const services = this.manifest.services.map((s) => ({
255
+ id: s.id,
256
+ name: s.name,
257
+ description: s.description,
258
+ price: s.price,
259
+ currency: s.currency,
260
+ input: s.input,
261
+ output: s.output,
262
+ available: this.skills.has(s.id)
263
+ }));
264
+ this.sendJson(res, 200, {
265
+ provider: this.manifest.provider,
266
+ services
267
+ });
268
+ }
269
+ /**
270
+ * POST /pay - Create payment request
271
+ * Body: { service: string, params: object }
272
+ */
273
+ handlePay(body, res) {
274
+ const { service, params } = body;
275
+ if (!service) {
276
+ return this.sendJson(res, 400, { error: "Missing service" });
277
+ }
278
+ const skill = this.skills.get(service);
279
+ if (!skill) {
280
+ return this.sendJson(res, 404, { error: `Service '${service}' not found or not registered` });
281
+ }
282
+ for (const [key, field] of Object.entries(skill.config.input)) {
283
+ if (field.required && (!params || params[key] === void 0)) {
284
+ return this.sendJson(res, 400, { error: `Missing required param: ${key}` });
285
+ }
286
+ }
287
+ const chargeId = generateChargeId();
288
+ const now = Date.now();
289
+ const charge = {
290
+ id: chargeId,
291
+ service,
292
+ params: params || {},
293
+ amount: skill.config.price,
294
+ currency: skill.config.currency,
295
+ status: "pending",
296
+ createdAt: now,
297
+ expiresAt: now + this.options.chargeExpirySecs * 1e3
298
+ };
299
+ this.charges.set(chargeId, charge);
300
+ const paymentRequest = {
301
+ chargeId,
302
+ service,
303
+ amount: charge.amount,
304
+ currency: charge.currency,
305
+ wallet: this.manifest.provider.wallet,
306
+ chain: this.manifest.provider.chain,
307
+ expiresAt: charge.expiresAt
308
+ };
309
+ this.sendJson(res, 402, {
310
+ message: "Payment required",
311
+ payment: paymentRequest
312
+ });
313
+ }
314
+ /**
315
+ * POST /verify - Verify payment and execute skill
316
+ * Body: { chargeId: string, txHash: string }
317
+ */
318
+ async handleVerify(body, res) {
319
+ const { chargeId, txHash } = body;
320
+ if (!chargeId || !txHash) {
321
+ return this.sendJson(res, 400, { error: "Missing chargeId or txHash" });
322
+ }
323
+ const charge = this.charges.get(chargeId);
324
+ if (!charge) {
325
+ return this.sendJson(res, 404, { error: "Charge not found" });
326
+ }
327
+ if (Date.now() > charge.expiresAt) {
328
+ charge.status = "expired";
329
+ return this.sendJson(res, 400, { error: "Charge expired" });
330
+ }
331
+ if (charge.status === "completed") {
332
+ return this.sendJson(res, 200, {
333
+ status: "completed",
334
+ result: charge.result
335
+ });
336
+ }
337
+ try {
338
+ const verification = await verifyPayment({
339
+ txHash,
340
+ expectedTo: this.manifest.provider.wallet,
341
+ expectedAmount: charge.amount,
342
+ chain: this.manifest.provider.chain
343
+ });
344
+ if (!verification.verified) {
345
+ charge.status = "failed";
346
+ return this.sendJson(res, 400, {
347
+ error: "Payment verification failed",
348
+ reason: verification.error
349
+ });
350
+ }
351
+ charge.status = "paid";
352
+ charge.txHash = txHash;
353
+ charge.paidAt = Date.now();
354
+ const skill = this.skills.get(charge.service);
355
+ console.log(`[MoltsPay] Executing skill: ${charge.service}`);
356
+ const result = await skill.handler(charge.params);
357
+ charge.status = "completed";
358
+ charge.result = result;
359
+ charge.completedAt = Date.now();
360
+ this.sendJson(res, 200, {
361
+ status: "completed",
362
+ chargeId,
363
+ txHash,
364
+ result
365
+ });
366
+ } catch (err) {
367
+ console.error("[MoltsPay] Skill execution error:", err);
368
+ charge.status = "failed";
369
+ this.sendJson(res, 500, {
370
+ error: "Skill execution failed",
371
+ message: err.message
372
+ });
373
+ }
374
+ }
375
+ /**
376
+ * GET /status/:chargeId - Check charge status
377
+ */
378
+ handleStatus(chargeId, res) {
379
+ const charge = this.charges.get(chargeId);
380
+ if (!charge) {
381
+ return this.sendJson(res, 404, { error: "Charge not found" });
382
+ }
383
+ this.sendJson(res, 200, {
384
+ chargeId: charge.id,
385
+ service: charge.service,
386
+ amount: charge.amount,
387
+ currency: charge.currency,
388
+ status: charge.status,
389
+ txHash: charge.txHash,
390
+ result: charge.status === "completed" ? charge.result : void 0,
391
+ createdAt: charge.createdAt,
392
+ expiresAt: charge.expiresAt
393
+ });
394
+ }
395
+ async readBody(req) {
396
+ return new Promise((resolve, reject) => {
397
+ let body = "";
398
+ req.on("data", (chunk) => body += chunk);
399
+ req.on("end", () => {
400
+ try {
401
+ resolve(body ? JSON.parse(body) : {});
402
+ } catch {
403
+ reject(new Error("Invalid JSON"));
404
+ }
405
+ });
406
+ req.on("error", reject);
407
+ });
408
+ }
409
+ sendJson(res, status, data) {
410
+ res.writeHead(status, { "Content-Type": "application/json" });
411
+ res.end(JSON.stringify(data, null, 2));
412
+ }
413
+ };
414
+ // Annotate the CommonJS export names for ESM import in node:
415
+ 0 && (module.exports = {
416
+ MoltsPayServer
417
+ });
418
+ //# sourceMappingURL=index.js.map