x402z-server 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/dist/index.d.mts +21 -6
- package/dist/index.d.ts +21 -6
- package/dist/index.js +38 -1
- package/dist/index.mjs +38 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,11 +58,11 @@ const server = await createX402zServer({
|
|
|
58
58
|
accepts: buildAcceptsFromConfigs(allowedPayments),
|
|
59
59
|
description: "Demo content",
|
|
60
60
|
mimeType: "text/plain",
|
|
61
|
+
onPaid: async () => ({
|
|
62
|
+
body: "demo content from server",
|
|
63
|
+
}),
|
|
61
64
|
},
|
|
62
65
|
},
|
|
63
|
-
onPaid: async () => ({
|
|
64
|
-
body: "demo content from server",
|
|
65
|
-
}),
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
server.listen(8080);
|
|
@@ -76,7 +76,8 @@ server.listen(8080);
|
|
|
76
76
|
- `confidential.signer`: signer used to decrypt transfer amounts
|
|
77
77
|
- `confidential.relayer`: FHEVM relayer instance used for decryption
|
|
78
78
|
- `routes`: map of `METHOD /path` to payment requirements
|
|
79
|
-
- `
|
|
79
|
+
- `routes["METHOD /path"].onRequest`: optional pre-payment hook; return a response to short-circuit
|
|
80
|
+
- `routes["METHOD /path"].onPaid`: handler for successful payment (returns response body + optional headers)
|
|
80
81
|
|
|
81
82
|
## Examples
|
|
82
83
|
|
|
@@ -101,9 +102,9 @@ const server = await createX402zServer({
|
|
|
101
102
|
],
|
|
102
103
|
description: "Exact USDC payment demo",
|
|
103
104
|
mimeType: "text/plain",
|
|
105
|
+
onPaid: async () => ({ body: "paid content" }),
|
|
104
106
|
},
|
|
105
107
|
},
|
|
106
|
-
onPaid: async () => ({ body: "paid content" }),
|
|
107
108
|
});
|
|
108
109
|
|
|
109
110
|
server.listen(8090);
|
package/dist/index.d.mts
CHANGED
|
@@ -60,11 +60,6 @@ type X402zRouteAccept = {
|
|
|
60
60
|
type NoScheme = {
|
|
61
61
|
scheme?: never;
|
|
62
62
|
};
|
|
63
|
-
type X402zRouteOptions = NoScheme & {
|
|
64
|
-
accepts: X402zRouteAccept[];
|
|
65
|
-
description: string;
|
|
66
|
-
mimeType: string;
|
|
67
|
-
};
|
|
68
63
|
type X402zRouteHandler = (args: {
|
|
69
64
|
paymentRequirements: PaymentRequirements;
|
|
70
65
|
settleHeaders: Record<string, string>;
|
|
@@ -73,6 +68,27 @@ type X402zRouteHandler = (args: {
|
|
|
73
68
|
headers?: Record<string, string>;
|
|
74
69
|
body: string;
|
|
75
70
|
}>;
|
|
71
|
+
type X402zRequestHandler = (args: {
|
|
72
|
+
method: string;
|
|
73
|
+
path: string;
|
|
74
|
+
url: string;
|
|
75
|
+
headers: Record<string, string>;
|
|
76
|
+
}) => Promise<{
|
|
77
|
+
status?: number;
|
|
78
|
+
headers?: Record<string, string>;
|
|
79
|
+
body: string;
|
|
80
|
+
} | void> | {
|
|
81
|
+
status?: number;
|
|
82
|
+
headers?: Record<string, string>;
|
|
83
|
+
body: string;
|
|
84
|
+
} | void;
|
|
85
|
+
type X402zRouteOptions = NoScheme & {
|
|
86
|
+
accepts: X402zRouteAccept[];
|
|
87
|
+
description: string;
|
|
88
|
+
mimeType: string;
|
|
89
|
+
onRequest?: X402zRequestHandler;
|
|
90
|
+
onPaid: X402zRouteHandler;
|
|
91
|
+
};
|
|
76
92
|
type X402zBaseServerOptions = {
|
|
77
93
|
facilitatorUrl: string;
|
|
78
94
|
debug?: boolean;
|
|
@@ -101,7 +117,6 @@ type X402zConfidentialServerConfig = {
|
|
|
101
117
|
} & NoScheme;
|
|
102
118
|
type X402zServerOptions = X402zBaseServerOptions & {
|
|
103
119
|
routes: Record<string, X402zRouteOptions>;
|
|
104
|
-
onPaid: X402zRouteHandler;
|
|
105
120
|
confidential?: X402zConfidentialServerConfig;
|
|
106
121
|
} & NoScheme;
|
|
107
122
|
declare function createX402zServer(config: X402zServerOptions): Promise<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -60,11 +60,6 @@ type X402zRouteAccept = {
|
|
|
60
60
|
type NoScheme = {
|
|
61
61
|
scheme?: never;
|
|
62
62
|
};
|
|
63
|
-
type X402zRouteOptions = NoScheme & {
|
|
64
|
-
accepts: X402zRouteAccept[];
|
|
65
|
-
description: string;
|
|
66
|
-
mimeType: string;
|
|
67
|
-
};
|
|
68
63
|
type X402zRouteHandler = (args: {
|
|
69
64
|
paymentRequirements: PaymentRequirements;
|
|
70
65
|
settleHeaders: Record<string, string>;
|
|
@@ -73,6 +68,27 @@ type X402zRouteHandler = (args: {
|
|
|
73
68
|
headers?: Record<string, string>;
|
|
74
69
|
body: string;
|
|
75
70
|
}>;
|
|
71
|
+
type X402zRequestHandler = (args: {
|
|
72
|
+
method: string;
|
|
73
|
+
path: string;
|
|
74
|
+
url: string;
|
|
75
|
+
headers: Record<string, string>;
|
|
76
|
+
}) => Promise<{
|
|
77
|
+
status?: number;
|
|
78
|
+
headers?: Record<string, string>;
|
|
79
|
+
body: string;
|
|
80
|
+
} | void> | {
|
|
81
|
+
status?: number;
|
|
82
|
+
headers?: Record<string, string>;
|
|
83
|
+
body: string;
|
|
84
|
+
} | void;
|
|
85
|
+
type X402zRouteOptions = NoScheme & {
|
|
86
|
+
accepts: X402zRouteAccept[];
|
|
87
|
+
description: string;
|
|
88
|
+
mimeType: string;
|
|
89
|
+
onRequest?: X402zRequestHandler;
|
|
90
|
+
onPaid: X402zRouteHandler;
|
|
91
|
+
};
|
|
76
92
|
type X402zBaseServerOptions = {
|
|
77
93
|
facilitatorUrl: string;
|
|
78
94
|
debug?: boolean;
|
|
@@ -101,7 +117,6 @@ type X402zConfidentialServerConfig = {
|
|
|
101
117
|
} & NoScheme;
|
|
102
118
|
type X402zServerOptions = X402zBaseServerOptions & {
|
|
103
119
|
routes: Record<string, X402zRouteOptions>;
|
|
104
|
-
onPaid: X402zRouteHandler;
|
|
105
120
|
confidential?: X402zConfidentialServerConfig;
|
|
106
121
|
} & NoScheme;
|
|
107
122
|
declare function createX402zServer(config: X402zServerOptions): Promise<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>>;
|
package/dist/index.js
CHANGED
|
@@ -354,6 +354,35 @@ async function createX402zServer(config) {
|
|
|
354
354
|
const adapter = buildAdapter(req);
|
|
355
355
|
const method = adapter.getMethod();
|
|
356
356
|
const path = adapter.getPath();
|
|
357
|
+
const routeKey = `${method} ${path}`;
|
|
358
|
+
const routeConfig = config.routes[routeKey];
|
|
359
|
+
if (routeConfig?.onRequest) {
|
|
360
|
+
const headers = {};
|
|
361
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
362
|
+
if (value === void 0) continue;
|
|
363
|
+
headers[key.toLowerCase()] = Array.isArray(value) ? value.join(",") : value;
|
|
364
|
+
}
|
|
365
|
+
const response = await routeConfig.onRequest({
|
|
366
|
+
method,
|
|
367
|
+
path,
|
|
368
|
+
url: adapter.getUrl(),
|
|
369
|
+
headers
|
|
370
|
+
});
|
|
371
|
+
if (response) {
|
|
372
|
+
const status = response.status ?? 200;
|
|
373
|
+
const responseHeaders = {
|
|
374
|
+
...response.headers ?? {}
|
|
375
|
+
};
|
|
376
|
+
if (!responseHeaders["Content-Type"] && !responseHeaders["content-type"]) {
|
|
377
|
+
responseHeaders["Content-Type"] = "text/plain";
|
|
378
|
+
}
|
|
379
|
+
sendText(res, status, responseHeaders, response.body);
|
|
380
|
+
if (debugEnabled) {
|
|
381
|
+
console.debug(`[server] ${method} ${path} -> ${status} (onRequest)`);
|
|
382
|
+
}
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
357
386
|
const paymentHeader = adapter.getHeader("payment-signature") ?? adapter.getHeader("x402-payment") ?? adapter.getHeader("x-payment");
|
|
358
387
|
if (debugEnabled) {
|
|
359
388
|
console.debug(`[server] ${method} ${path}`);
|
|
@@ -470,7 +499,15 @@ async function createX402zServer(config) {
|
|
|
470
499
|
}
|
|
471
500
|
}
|
|
472
501
|
const settleHeaders = settle.headers ?? {};
|
|
473
|
-
|
|
502
|
+
if (!routeConfig) {
|
|
503
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
504
|
+
res.end(JSON.stringify({ error: "route_config_missing" }));
|
|
505
|
+
if (debugEnabled) {
|
|
506
|
+
console.debug(`[server] ${method} ${path} -> 500 route_config_missing`);
|
|
507
|
+
}
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
const payload = await routeConfig.onPaid({
|
|
474
511
|
paymentRequirements: result.paymentRequirements,
|
|
475
512
|
settleHeaders
|
|
476
513
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -318,6 +318,35 @@ async function createX402zServer(config) {
|
|
|
318
318
|
const adapter = buildAdapter(req);
|
|
319
319
|
const method = adapter.getMethod();
|
|
320
320
|
const path = adapter.getPath();
|
|
321
|
+
const routeKey = `${method} ${path}`;
|
|
322
|
+
const routeConfig = config.routes[routeKey];
|
|
323
|
+
if (routeConfig?.onRequest) {
|
|
324
|
+
const headers = {};
|
|
325
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
326
|
+
if (value === void 0) continue;
|
|
327
|
+
headers[key.toLowerCase()] = Array.isArray(value) ? value.join(",") : value;
|
|
328
|
+
}
|
|
329
|
+
const response = await routeConfig.onRequest({
|
|
330
|
+
method,
|
|
331
|
+
path,
|
|
332
|
+
url: adapter.getUrl(),
|
|
333
|
+
headers
|
|
334
|
+
});
|
|
335
|
+
if (response) {
|
|
336
|
+
const status = response.status ?? 200;
|
|
337
|
+
const responseHeaders = {
|
|
338
|
+
...response.headers ?? {}
|
|
339
|
+
};
|
|
340
|
+
if (!responseHeaders["Content-Type"] && !responseHeaders["content-type"]) {
|
|
341
|
+
responseHeaders["Content-Type"] = "text/plain";
|
|
342
|
+
}
|
|
343
|
+
sendText(res, status, responseHeaders, response.body);
|
|
344
|
+
if (debugEnabled) {
|
|
345
|
+
console.debug(`[server] ${method} ${path} -> ${status} (onRequest)`);
|
|
346
|
+
}
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
321
350
|
const paymentHeader = adapter.getHeader("payment-signature") ?? adapter.getHeader("x402-payment") ?? adapter.getHeader("x-payment");
|
|
322
351
|
if (debugEnabled) {
|
|
323
352
|
console.debug(`[server] ${method} ${path}`);
|
|
@@ -434,7 +463,15 @@ async function createX402zServer(config) {
|
|
|
434
463
|
}
|
|
435
464
|
}
|
|
436
465
|
const settleHeaders = settle.headers ?? {};
|
|
437
|
-
|
|
466
|
+
if (!routeConfig) {
|
|
467
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
468
|
+
res.end(JSON.stringify({ error: "route_config_missing" }));
|
|
469
|
+
if (debugEnabled) {
|
|
470
|
+
console.debug(`[server] ${method} ${path} -> 500 route_config_missing`);
|
|
471
|
+
}
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
const payload = await routeConfig.onPaid({
|
|
438
475
|
paymentRequirements: result.paymentRequirements,
|
|
439
476
|
settleHeaders
|
|
440
477
|
});
|