x402z-server 0.0.7 → 0.0.9
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 +8 -2
- package/dist/index.d.mts +21 -13
- package/dist/index.d.ts +21 -13
- package/dist/index.js +51 -26
- package/dist/index.mjs +46 -21
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,13 +8,19 @@ Server-side helpers for the erc7984-mind-v1 x402 scheme.
|
|
|
8
8
|
pnpm add x402z-server
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## Folder map
|
|
12
|
+
|
|
13
|
+
- `src/http/`: server HTTP helpers
|
|
14
|
+
- `src/scheme/`: scheme implementation + registration
|
|
15
|
+
- `src/index.ts`: public exports
|
|
16
|
+
|
|
11
17
|
## Usage
|
|
12
18
|
|
|
13
19
|
```ts
|
|
14
20
|
import { createX402zServer } from "x402z-server";
|
|
15
|
-
import {
|
|
21
|
+
import { createRelayer, SepoliaConfig } from "x402z-shared";
|
|
16
22
|
|
|
17
|
-
const relayer = await
|
|
23
|
+
const relayer = await createRelayer({
|
|
18
24
|
...SepoliaConfig,
|
|
19
25
|
network: "https://sepolia.infura.io/v3/...",
|
|
20
26
|
});
|
package/dist/index.d.mts
CHANGED
|
@@ -4,9 +4,9 @@ import { x402ResourceServer } from '@x402/core/server';
|
|
|
4
4
|
export { x402ResourceServer } from '@x402/core/server';
|
|
5
5
|
import * as http from 'http';
|
|
6
6
|
import { RelayerSigner, RelayerInstance } from 'x402z-shared';
|
|
7
|
-
export { CompiledRoute, DynamicPayTo, DynamicPrice, FacilitatorClient, FacilitatorConfig, HTTPAdapter, HTTPFacilitatorClient, HTTPProcessResult, HTTPRequestContext, HTTPResponseInstructions, PaymentOption, PaywallConfig, PaywallProvider, ProcessSettleFailureResponse, ProcessSettleResultResponse, ProcessSettleSuccessResponse,
|
|
7
|
+
export { CompiledRoute, DynamicPayTo, DynamicPrice, FacilitatorClient, FacilitatorConfig, HTTPAdapter, HTTPFacilitatorClient, HTTPProcessResult, HTTPRequestContext, HTTPResponseInstructions, PaymentOption, PaywallConfig, PaywallProvider, ProcessSettleFailureResponse, ProcessSettleResultResponse, ProcessSettleSuccessResponse, RouteConfigurationError, RouteValidationError, RoutesConfig, UnpaidResponseBody, UnpaidResponseResult, x402HTTPResourceServer } from '@x402/core/http';
|
|
8
8
|
|
|
9
|
-
type
|
|
9
|
+
type X402zServerNetworkOptions = {
|
|
10
10
|
asset: `0x${string}`;
|
|
11
11
|
eip712: {
|
|
12
12
|
name: string;
|
|
@@ -16,13 +16,13 @@ type ConfidentialServerNetworkConfig = {
|
|
|
16
16
|
resourceHash?: `0x${string}`;
|
|
17
17
|
batcherAddress: `0x${string}`;
|
|
18
18
|
};
|
|
19
|
-
type
|
|
20
|
-
getNetworkConfig: (network: Network) =>
|
|
19
|
+
type X402zServerSchemeOptions = X402zServerNetworkOptions | {
|
|
20
|
+
getNetworkConfig: (network: Network) => X402zServerNetworkOptions;
|
|
21
21
|
};
|
|
22
|
-
declare class
|
|
22
|
+
declare class X402zEvmServerScheme implements SchemeNetworkServer {
|
|
23
23
|
readonly scheme = "erc7984-mind-v1";
|
|
24
24
|
private readonly getConfig;
|
|
25
|
-
constructor(config:
|
|
25
|
+
constructor(config: X402zServerSchemeOptions);
|
|
26
26
|
parsePrice(price: Price, network: Network): Promise<AssetAmount>;
|
|
27
27
|
enhancePaymentRequirements(paymentRequirements: PaymentRequirements, supportedKind: {
|
|
28
28
|
x402Version: number;
|
|
@@ -34,12 +34,12 @@ declare class ConfidentialEvmScheme implements SchemeNetworkServer {
|
|
|
34
34
|
private convertToTokenAmount;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
type
|
|
37
|
+
type X402zServerRegistrationOptions = X402zServerSchemeOptions & {
|
|
38
38
|
networks?: Network[];
|
|
39
39
|
};
|
|
40
|
-
declare function
|
|
40
|
+
declare function registerX402zEvmServerScheme(server: x402ResourceServer, config: X402zServerRegistrationOptions): x402ResourceServer;
|
|
41
41
|
|
|
42
|
-
type
|
|
42
|
+
type X402zRouteOptions = {
|
|
43
43
|
accepts: {
|
|
44
44
|
payTo: string;
|
|
45
45
|
price: string;
|
|
@@ -57,14 +57,22 @@ type X402zRouteHandler = (args: {
|
|
|
57
57
|
headers?: Record<string, string>;
|
|
58
58
|
body: string;
|
|
59
59
|
}>;
|
|
60
|
-
type
|
|
60
|
+
type X402zServerOptions = X402zServerRegistrationOptions & {
|
|
61
61
|
facilitatorUrl: string;
|
|
62
|
-
routes: Record<string,
|
|
62
|
+
routes: Record<string, X402zRouteOptions>;
|
|
63
63
|
onPaid: X402zRouteHandler;
|
|
64
64
|
signer: RelayerSigner;
|
|
65
65
|
relayer: RelayerInstance;
|
|
66
66
|
debug?: boolean;
|
|
67
|
+
cors?: {
|
|
68
|
+
allowOrigin: string;
|
|
69
|
+
allowMethods?: string;
|
|
70
|
+
allowHeaders?: string;
|
|
71
|
+
exposeHeaders?: string;
|
|
72
|
+
allowCredentials?: boolean;
|
|
73
|
+
maxAgeSeconds?: number;
|
|
74
|
+
};
|
|
67
75
|
};
|
|
68
|
-
declare function createX402zServer(config:
|
|
76
|
+
declare function createX402zServer(config: X402zServerOptions): Promise<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>>;
|
|
69
77
|
|
|
70
|
-
export {
|
|
78
|
+
export { X402zEvmServerScheme, type X402zRouteHandler, type X402zRouteOptions, type X402zServerNetworkOptions, type X402zServerOptions, type X402zServerRegistrationOptions, type X402zServerSchemeOptions, createX402zServer, registerX402zEvmServerScheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,9 +4,9 @@ import { x402ResourceServer } from '@x402/core/server';
|
|
|
4
4
|
export { x402ResourceServer } from '@x402/core/server';
|
|
5
5
|
import * as http from 'http';
|
|
6
6
|
import { RelayerSigner, RelayerInstance } from 'x402z-shared';
|
|
7
|
-
export { CompiledRoute, DynamicPayTo, DynamicPrice, FacilitatorClient, FacilitatorConfig, HTTPAdapter, HTTPFacilitatorClient, HTTPProcessResult, HTTPRequestContext, HTTPResponseInstructions, PaymentOption, PaywallConfig, PaywallProvider, ProcessSettleFailureResponse, ProcessSettleResultResponse, ProcessSettleSuccessResponse,
|
|
7
|
+
export { CompiledRoute, DynamicPayTo, DynamicPrice, FacilitatorClient, FacilitatorConfig, HTTPAdapter, HTTPFacilitatorClient, HTTPProcessResult, HTTPRequestContext, HTTPResponseInstructions, PaymentOption, PaywallConfig, PaywallProvider, ProcessSettleFailureResponse, ProcessSettleResultResponse, ProcessSettleSuccessResponse, RouteConfigurationError, RouteValidationError, RoutesConfig, UnpaidResponseBody, UnpaidResponseResult, x402HTTPResourceServer } from '@x402/core/http';
|
|
8
8
|
|
|
9
|
-
type
|
|
9
|
+
type X402zServerNetworkOptions = {
|
|
10
10
|
asset: `0x${string}`;
|
|
11
11
|
eip712: {
|
|
12
12
|
name: string;
|
|
@@ -16,13 +16,13 @@ type ConfidentialServerNetworkConfig = {
|
|
|
16
16
|
resourceHash?: `0x${string}`;
|
|
17
17
|
batcherAddress: `0x${string}`;
|
|
18
18
|
};
|
|
19
|
-
type
|
|
20
|
-
getNetworkConfig: (network: Network) =>
|
|
19
|
+
type X402zServerSchemeOptions = X402zServerNetworkOptions | {
|
|
20
|
+
getNetworkConfig: (network: Network) => X402zServerNetworkOptions;
|
|
21
21
|
};
|
|
22
|
-
declare class
|
|
22
|
+
declare class X402zEvmServerScheme implements SchemeNetworkServer {
|
|
23
23
|
readonly scheme = "erc7984-mind-v1";
|
|
24
24
|
private readonly getConfig;
|
|
25
|
-
constructor(config:
|
|
25
|
+
constructor(config: X402zServerSchemeOptions);
|
|
26
26
|
parsePrice(price: Price, network: Network): Promise<AssetAmount>;
|
|
27
27
|
enhancePaymentRequirements(paymentRequirements: PaymentRequirements, supportedKind: {
|
|
28
28
|
x402Version: number;
|
|
@@ -34,12 +34,12 @@ declare class ConfidentialEvmScheme implements SchemeNetworkServer {
|
|
|
34
34
|
private convertToTokenAmount;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
type
|
|
37
|
+
type X402zServerRegistrationOptions = X402zServerSchemeOptions & {
|
|
38
38
|
networks?: Network[];
|
|
39
39
|
};
|
|
40
|
-
declare function
|
|
40
|
+
declare function registerX402zEvmServerScheme(server: x402ResourceServer, config: X402zServerRegistrationOptions): x402ResourceServer;
|
|
41
41
|
|
|
42
|
-
type
|
|
42
|
+
type X402zRouteOptions = {
|
|
43
43
|
accepts: {
|
|
44
44
|
payTo: string;
|
|
45
45
|
price: string;
|
|
@@ -57,14 +57,22 @@ type X402zRouteHandler = (args: {
|
|
|
57
57
|
headers?: Record<string, string>;
|
|
58
58
|
body: string;
|
|
59
59
|
}>;
|
|
60
|
-
type
|
|
60
|
+
type X402zServerOptions = X402zServerRegistrationOptions & {
|
|
61
61
|
facilitatorUrl: string;
|
|
62
|
-
routes: Record<string,
|
|
62
|
+
routes: Record<string, X402zRouteOptions>;
|
|
63
63
|
onPaid: X402zRouteHandler;
|
|
64
64
|
signer: RelayerSigner;
|
|
65
65
|
relayer: RelayerInstance;
|
|
66
66
|
debug?: boolean;
|
|
67
|
+
cors?: {
|
|
68
|
+
allowOrigin: string;
|
|
69
|
+
allowMethods?: string;
|
|
70
|
+
allowHeaders?: string;
|
|
71
|
+
exposeHeaders?: string;
|
|
72
|
+
allowCredentials?: boolean;
|
|
73
|
+
maxAgeSeconds?: number;
|
|
74
|
+
};
|
|
67
75
|
};
|
|
68
|
-
declare function createX402zServer(config:
|
|
76
|
+
declare function createX402zServer(config: X402zServerOptions): Promise<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>>;
|
|
69
77
|
|
|
70
|
-
export {
|
|
78
|
+
export { X402zEvmServerScheme, type X402zRouteHandler, type X402zRouteOptions, type X402zServerNetworkOptions, type X402zServerOptions, type X402zServerRegistrationOptions, type X402zServerSchemeOptions, createX402zServer, registerX402zEvmServerScheme };
|
package/dist/index.js
CHANGED
|
@@ -20,17 +20,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
HTTPFacilitatorClient: () => import_http3.HTTPFacilitatorClient,
|
|
24
|
+
X402zEvmServerScheme: () => X402zEvmServerScheme,
|
|
25
25
|
createX402zServer: () => createX402zServer,
|
|
26
|
-
|
|
27
|
-
x402HTTPResourceServer: () =>
|
|
28
|
-
x402ResourceServer: () =>
|
|
26
|
+
registerX402zEvmServerScheme: () => registerX402zEvmServerScheme,
|
|
27
|
+
x402HTTPResourceServer: () => import_http3.x402HTTPResourceServer,
|
|
28
|
+
x402ResourceServer: () => import_server3.x402ResourceServer
|
|
29
29
|
});
|
|
30
30
|
module.exports = __toCommonJS(index_exports);
|
|
31
31
|
|
|
32
|
-
// src/scheme.ts
|
|
33
|
-
var
|
|
32
|
+
// src/scheme/scheme.ts
|
|
33
|
+
var X402zEvmServerScheme = class {
|
|
34
34
|
constructor(config) {
|
|
35
35
|
this.scheme = "erc7984-mind-v1";
|
|
36
36
|
if ("getNetworkConfig" in config) {
|
|
@@ -107,19 +107,19 @@ var ConfidentialEvmScheme = class {
|
|
|
107
107
|
}
|
|
108
108
|
};
|
|
109
109
|
|
|
110
|
-
// src/register.ts
|
|
111
|
-
function
|
|
110
|
+
// src/scheme/register.ts
|
|
111
|
+
function registerX402zEvmServerScheme(server, config) {
|
|
112
112
|
if ("networks" in config && config.networks && config.networks.length > 0) {
|
|
113
113
|
for (const network of config.networks) {
|
|
114
|
-
server.register(network, new
|
|
114
|
+
server.register(network, new X402zEvmServerScheme(config));
|
|
115
115
|
}
|
|
116
116
|
return server;
|
|
117
117
|
}
|
|
118
|
-
server.register("eip155:*", new
|
|
118
|
+
server.register("eip155:*", new X402zEvmServerScheme(config));
|
|
119
119
|
return server;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
// src/http.ts
|
|
122
|
+
// src/http/server.ts
|
|
123
123
|
var import_node_http = require("http");
|
|
124
124
|
var import_node_url = require("url");
|
|
125
125
|
var import_server = require("@x402/core/server");
|
|
@@ -157,7 +157,7 @@ async function createX402zServer(config) {
|
|
|
157
157
|
const debugEnabled = config.debug ?? process.env.X402Z_DEBUG === "1";
|
|
158
158
|
const facilitatorClient = new import_http2.HTTPFacilitatorClient({ url: config.facilitatorUrl });
|
|
159
159
|
const resourceServer = new import_server.x402ResourceServer(facilitatorClient);
|
|
160
|
-
|
|
160
|
+
registerX402zEvmServerScheme(resourceServer, config);
|
|
161
161
|
const relayer = config.relayer;
|
|
162
162
|
const rpcUrl = getRelayerRpcUrl(relayer);
|
|
163
163
|
const routes = {};
|
|
@@ -176,10 +176,29 @@ async function createX402zServer(config) {
|
|
|
176
176
|
const adapter = buildAdapter(req);
|
|
177
177
|
const method = adapter.getMethod();
|
|
178
178
|
const path = adapter.getPath();
|
|
179
|
-
const paymentHeader = adapter.getHeader("x402-payment") ?? adapter.getHeader("x-payment");
|
|
179
|
+
const paymentHeader = adapter.getHeader("payment-signature") ?? adapter.getHeader("x402-payment") ?? adapter.getHeader("x-payment");
|
|
180
180
|
console.log(`[server] ${method} ${path}`);
|
|
181
|
+
const corsHeaders = config.cors ? {
|
|
182
|
+
"Access-Control-Allow-Origin": config.cors.allowOrigin,
|
|
183
|
+
"Access-Control-Allow-Methods": config.cors.allowMethods ?? "GET,POST,OPTIONS",
|
|
184
|
+
"Access-Control-Allow-Headers": config.cors.allowHeaders ?? "content-type,x402-payment,x-payment,payment-signature",
|
|
185
|
+
"Access-Control-Expose-Headers": config.cors.exposeHeaders ?? "payment-required,payment-signature,x402-payment,x-payment,x-settle,content-type",
|
|
186
|
+
"Access-Control-Max-Age": String(config.cors.maxAgeSeconds ?? 600),
|
|
187
|
+
...config.cors.allowCredentials ? { "Access-Control-Allow-Credentials": "true" } : {}
|
|
188
|
+
} : {};
|
|
189
|
+
if (method === "OPTIONS") {
|
|
190
|
+
res.writeHead(204, corsHeaders);
|
|
191
|
+
res.end();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
181
194
|
if (debugEnabled && paymentHeader) {
|
|
182
195
|
console.debug("[x402z-server] payment header", paymentHeader);
|
|
196
|
+
try {
|
|
197
|
+
const decoded = (0, import_http.decodePaymentSignatureHeader)(paymentHeader);
|
|
198
|
+
console.debug("[x402z-server] payment payload", decoded);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.debug("[x402z-server] payment payload decode failed", error);
|
|
201
|
+
}
|
|
183
202
|
}
|
|
184
203
|
const result = await httpServer.processHTTPRequest({
|
|
185
204
|
adapter,
|
|
@@ -187,7 +206,7 @@ async function createX402zServer(config) {
|
|
|
187
206
|
method: adapter.getMethod()
|
|
188
207
|
});
|
|
189
208
|
if (result.type === "payment-error") {
|
|
190
|
-
res.writeHead(result.response.status, result.response.headers);
|
|
209
|
+
res.writeHead(result.response.status, { ...corsHeaders, ...result.response.headers });
|
|
191
210
|
res.end(result.response.isHtml ? result.response.body : JSON.stringify(result.response.body ?? {}));
|
|
192
211
|
console.log(`[server] ${method} ${path} -> ${result.response.status}`);
|
|
193
212
|
return;
|
|
@@ -195,7 +214,7 @@ async function createX402zServer(config) {
|
|
|
195
214
|
if (result.type === "payment-verified") {
|
|
196
215
|
const settle = await httpServer.processSettlement(result.paymentPayload, result.paymentRequirements);
|
|
197
216
|
if (!settle.success) {
|
|
198
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
217
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
199
218
|
res.end(JSON.stringify({ error: settle.errorReason }));
|
|
200
219
|
console.log(`[server] ${method} ${path} -> 500 settlement_failed`);
|
|
201
220
|
return;
|
|
@@ -213,7 +232,7 @@ async function createX402zServer(config) {
|
|
|
213
232
|
});
|
|
214
233
|
const signerAddress = (0, import_viem.getAddress)(config.signer.address);
|
|
215
234
|
if (!observer || !(0, import_viem.isAddressEqual)(observer, signerAddress)) {
|
|
216
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
235
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
217
236
|
res.end(JSON.stringify({ error: "observer_required" }));
|
|
218
237
|
console.log(`[server] ${method} ${path} -> 500 observer_required`);
|
|
219
238
|
return;
|
|
@@ -221,12 +240,12 @@ async function createX402zServer(config) {
|
|
|
221
240
|
const batch = settle;
|
|
222
241
|
const transferredHandle = batch.batch?.transferredHandle;
|
|
223
242
|
if (!transferredHandle) {
|
|
224
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
243
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
225
244
|
res.end(JSON.stringify({ error: "missing_transferred_handle" }));
|
|
226
245
|
console.log(`[server] ${method} ${path} -> 500 missing_transferred_handle`);
|
|
227
246
|
return;
|
|
228
247
|
}
|
|
229
|
-
const decryptedAmount = await (0, import_x402z_shared.
|
|
248
|
+
const decryptedAmount = await (0, import_x402z_shared.decryptEuint64)(
|
|
230
249
|
relayer,
|
|
231
250
|
transferredHandle,
|
|
232
251
|
result.paymentRequirements.asset,
|
|
@@ -234,13 +253,13 @@ async function createX402zServer(config) {
|
|
|
234
253
|
);
|
|
235
254
|
const expected = BigInt(result.paymentRequirements.amount);
|
|
236
255
|
if (decryptedAmount !== expected) {
|
|
237
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
256
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
238
257
|
res.end(JSON.stringify({ error: "settlement_amount_mismatch" }));
|
|
239
258
|
console.log(`[server] ${method} ${path} -> 500 settlement_amount_mismatch`);
|
|
240
259
|
return;
|
|
241
260
|
}
|
|
242
261
|
} catch (error) {
|
|
243
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
262
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
244
263
|
res.end(JSON.stringify({ error: "settlement_verification_failed" }));
|
|
245
264
|
console.log(`[server] ${method} ${path} -> 500 settlement_verification_failed`);
|
|
246
265
|
if (debugEnabled) {
|
|
@@ -254,6 +273,7 @@ async function createX402zServer(config) {
|
|
|
254
273
|
});
|
|
255
274
|
const status = payload.status ?? 200;
|
|
256
275
|
const responseHeaders = {
|
|
276
|
+
...corsHeaders,
|
|
257
277
|
"Content-Type": "text/plain",
|
|
258
278
|
...settle.headers,
|
|
259
279
|
...payload.headers ?? {}
|
|
@@ -269,21 +289,26 @@ async function createX402zServer(config) {
|
|
|
269
289
|
console.log(`[server] ${method} ${path} -> ${status}`);
|
|
270
290
|
return;
|
|
271
291
|
}
|
|
272
|
-
sendText(
|
|
292
|
+
sendText(
|
|
293
|
+
res,
|
|
294
|
+
200,
|
|
295
|
+
{ ...corsHeaders, "Content-Type": "text/plain" },
|
|
296
|
+
"no payment required"
|
|
297
|
+
);
|
|
273
298
|
console.log(`[server] ${method} ${path} -> 200`);
|
|
274
299
|
});
|
|
275
300
|
return server;
|
|
276
301
|
}
|
|
277
302
|
|
|
278
303
|
// src/index.ts
|
|
279
|
-
var
|
|
280
|
-
var
|
|
304
|
+
var import_server3 = require("@x402/core/server");
|
|
305
|
+
var import_http3 = require("@x402/core/http");
|
|
281
306
|
// Annotate the CommonJS export names for ESM import in node:
|
|
282
307
|
0 && (module.exports = {
|
|
283
|
-
ConfidentialEvmScheme,
|
|
284
308
|
HTTPFacilitatorClient,
|
|
309
|
+
X402zEvmServerScheme,
|
|
285
310
|
createX402zServer,
|
|
286
|
-
|
|
311
|
+
registerX402zEvmServerScheme,
|
|
287
312
|
x402HTTPResourceServer,
|
|
288
313
|
x402ResourceServer
|
|
289
314
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// src/scheme.ts
|
|
2
|
-
var
|
|
1
|
+
// src/scheme/scheme.ts
|
|
2
|
+
var X402zEvmServerScheme = class {
|
|
3
3
|
constructor(config) {
|
|
4
4
|
this.scheme = "erc7984-mind-v1";
|
|
5
5
|
if ("getNetworkConfig" in config) {
|
|
@@ -76,25 +76,25 @@ var ConfidentialEvmScheme = class {
|
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
78
|
|
|
79
|
-
// src/register.ts
|
|
80
|
-
function
|
|
79
|
+
// src/scheme/register.ts
|
|
80
|
+
function registerX402zEvmServerScheme(server, config) {
|
|
81
81
|
if ("networks" in config && config.networks && config.networks.length > 0) {
|
|
82
82
|
for (const network of config.networks) {
|
|
83
|
-
server.register(network, new
|
|
83
|
+
server.register(network, new X402zEvmServerScheme(config));
|
|
84
84
|
}
|
|
85
85
|
return server;
|
|
86
86
|
}
|
|
87
|
-
server.register("eip155:*", new
|
|
87
|
+
server.register("eip155:*", new X402zEvmServerScheme(config));
|
|
88
88
|
return server;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
// src/http.ts
|
|
91
|
+
// src/http/server.ts
|
|
92
92
|
import { createServer } from "http";
|
|
93
93
|
import { URL } from "url";
|
|
94
94
|
import { x402ResourceServer } from "@x402/core/server";
|
|
95
|
-
import { x402HTTPResourceServer } from "@x402/core/http";
|
|
95
|
+
import { decodePaymentSignatureHeader, x402HTTPResourceServer } from "@x402/core/http";
|
|
96
96
|
import { HTTPFacilitatorClient } from "@x402/core/http";
|
|
97
|
-
import { confidentialTokenAbi,
|
|
97
|
+
import { confidentialTokenAbi, decryptEuint64 } from "x402z-shared";
|
|
98
98
|
import { createPublicClient, getAddress, http, isAddressEqual } from "viem";
|
|
99
99
|
function getRelayerRpcUrl(relayer) {
|
|
100
100
|
const network = relayer.network;
|
|
@@ -126,7 +126,7 @@ async function createX402zServer(config) {
|
|
|
126
126
|
const debugEnabled = config.debug ?? process.env.X402Z_DEBUG === "1";
|
|
127
127
|
const facilitatorClient = new HTTPFacilitatorClient({ url: config.facilitatorUrl });
|
|
128
128
|
const resourceServer = new x402ResourceServer(facilitatorClient);
|
|
129
|
-
|
|
129
|
+
registerX402zEvmServerScheme(resourceServer, config);
|
|
130
130
|
const relayer = config.relayer;
|
|
131
131
|
const rpcUrl = getRelayerRpcUrl(relayer);
|
|
132
132
|
const routes = {};
|
|
@@ -145,10 +145,29 @@ async function createX402zServer(config) {
|
|
|
145
145
|
const adapter = buildAdapter(req);
|
|
146
146
|
const method = adapter.getMethod();
|
|
147
147
|
const path = adapter.getPath();
|
|
148
|
-
const paymentHeader = adapter.getHeader("x402-payment") ?? adapter.getHeader("x-payment");
|
|
148
|
+
const paymentHeader = adapter.getHeader("payment-signature") ?? adapter.getHeader("x402-payment") ?? adapter.getHeader("x-payment");
|
|
149
149
|
console.log(`[server] ${method} ${path}`);
|
|
150
|
+
const corsHeaders = config.cors ? {
|
|
151
|
+
"Access-Control-Allow-Origin": config.cors.allowOrigin,
|
|
152
|
+
"Access-Control-Allow-Methods": config.cors.allowMethods ?? "GET,POST,OPTIONS",
|
|
153
|
+
"Access-Control-Allow-Headers": config.cors.allowHeaders ?? "content-type,x402-payment,x-payment,payment-signature",
|
|
154
|
+
"Access-Control-Expose-Headers": config.cors.exposeHeaders ?? "payment-required,payment-signature,x402-payment,x-payment,x-settle,content-type",
|
|
155
|
+
"Access-Control-Max-Age": String(config.cors.maxAgeSeconds ?? 600),
|
|
156
|
+
...config.cors.allowCredentials ? { "Access-Control-Allow-Credentials": "true" } : {}
|
|
157
|
+
} : {};
|
|
158
|
+
if (method === "OPTIONS") {
|
|
159
|
+
res.writeHead(204, corsHeaders);
|
|
160
|
+
res.end();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
150
163
|
if (debugEnabled && paymentHeader) {
|
|
151
164
|
console.debug("[x402z-server] payment header", paymentHeader);
|
|
165
|
+
try {
|
|
166
|
+
const decoded = decodePaymentSignatureHeader(paymentHeader);
|
|
167
|
+
console.debug("[x402z-server] payment payload", decoded);
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.debug("[x402z-server] payment payload decode failed", error);
|
|
170
|
+
}
|
|
152
171
|
}
|
|
153
172
|
const result = await httpServer.processHTTPRequest({
|
|
154
173
|
adapter,
|
|
@@ -156,7 +175,7 @@ async function createX402zServer(config) {
|
|
|
156
175
|
method: adapter.getMethod()
|
|
157
176
|
});
|
|
158
177
|
if (result.type === "payment-error") {
|
|
159
|
-
res.writeHead(result.response.status, result.response.headers);
|
|
178
|
+
res.writeHead(result.response.status, { ...corsHeaders, ...result.response.headers });
|
|
160
179
|
res.end(result.response.isHtml ? result.response.body : JSON.stringify(result.response.body ?? {}));
|
|
161
180
|
console.log(`[server] ${method} ${path} -> ${result.response.status}`);
|
|
162
181
|
return;
|
|
@@ -164,7 +183,7 @@ async function createX402zServer(config) {
|
|
|
164
183
|
if (result.type === "payment-verified") {
|
|
165
184
|
const settle = await httpServer.processSettlement(result.paymentPayload, result.paymentRequirements);
|
|
166
185
|
if (!settle.success) {
|
|
167
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
186
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
168
187
|
res.end(JSON.stringify({ error: settle.errorReason }));
|
|
169
188
|
console.log(`[server] ${method} ${path} -> 500 settlement_failed`);
|
|
170
189
|
return;
|
|
@@ -182,7 +201,7 @@ async function createX402zServer(config) {
|
|
|
182
201
|
});
|
|
183
202
|
const signerAddress = getAddress(config.signer.address);
|
|
184
203
|
if (!observer || !isAddressEqual(observer, signerAddress)) {
|
|
185
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
204
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
186
205
|
res.end(JSON.stringify({ error: "observer_required" }));
|
|
187
206
|
console.log(`[server] ${method} ${path} -> 500 observer_required`);
|
|
188
207
|
return;
|
|
@@ -190,12 +209,12 @@ async function createX402zServer(config) {
|
|
|
190
209
|
const batch = settle;
|
|
191
210
|
const transferredHandle = batch.batch?.transferredHandle;
|
|
192
211
|
if (!transferredHandle) {
|
|
193
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
212
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
194
213
|
res.end(JSON.stringify({ error: "missing_transferred_handle" }));
|
|
195
214
|
console.log(`[server] ${method} ${path} -> 500 missing_transferred_handle`);
|
|
196
215
|
return;
|
|
197
216
|
}
|
|
198
|
-
const decryptedAmount = await
|
|
217
|
+
const decryptedAmount = await decryptEuint64(
|
|
199
218
|
relayer,
|
|
200
219
|
transferredHandle,
|
|
201
220
|
result.paymentRequirements.asset,
|
|
@@ -203,13 +222,13 @@ async function createX402zServer(config) {
|
|
|
203
222
|
);
|
|
204
223
|
const expected = BigInt(result.paymentRequirements.amount);
|
|
205
224
|
if (decryptedAmount !== expected) {
|
|
206
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
225
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
207
226
|
res.end(JSON.stringify({ error: "settlement_amount_mismatch" }));
|
|
208
227
|
console.log(`[server] ${method} ${path} -> 500 settlement_amount_mismatch`);
|
|
209
228
|
return;
|
|
210
229
|
}
|
|
211
230
|
} catch (error) {
|
|
212
|
-
res.writeHead(500, { "Content-Type": "application/json" });
|
|
231
|
+
res.writeHead(500, { ...corsHeaders, "Content-Type": "application/json" });
|
|
213
232
|
res.end(JSON.stringify({ error: "settlement_verification_failed" }));
|
|
214
233
|
console.log(`[server] ${method} ${path} -> 500 settlement_verification_failed`);
|
|
215
234
|
if (debugEnabled) {
|
|
@@ -223,6 +242,7 @@ async function createX402zServer(config) {
|
|
|
223
242
|
});
|
|
224
243
|
const status = payload.status ?? 200;
|
|
225
244
|
const responseHeaders = {
|
|
245
|
+
...corsHeaders,
|
|
226
246
|
"Content-Type": "text/plain",
|
|
227
247
|
...settle.headers,
|
|
228
248
|
...payload.headers ?? {}
|
|
@@ -238,7 +258,12 @@ async function createX402zServer(config) {
|
|
|
238
258
|
console.log(`[server] ${method} ${path} -> ${status}`);
|
|
239
259
|
return;
|
|
240
260
|
}
|
|
241
|
-
sendText(
|
|
261
|
+
sendText(
|
|
262
|
+
res,
|
|
263
|
+
200,
|
|
264
|
+
{ ...corsHeaders, "Content-Type": "text/plain" },
|
|
265
|
+
"no payment required"
|
|
266
|
+
);
|
|
242
267
|
console.log(`[server] ${method} ${path} -> 200`);
|
|
243
268
|
});
|
|
244
269
|
return server;
|
|
@@ -251,10 +276,10 @@ import {
|
|
|
251
276
|
x402HTTPResourceServer as x402HTTPResourceServer2
|
|
252
277
|
} from "@x402/core/http";
|
|
253
278
|
export {
|
|
254
|
-
ConfidentialEvmScheme,
|
|
255
279
|
HTTPFacilitatorClient2 as HTTPFacilitatorClient,
|
|
280
|
+
X402zEvmServerScheme,
|
|
256
281
|
createX402zServer,
|
|
257
|
-
|
|
282
|
+
registerX402zEvmServerScheme,
|
|
258
283
|
x402HTTPResourceServer2 as x402HTTPResourceServer,
|
|
259
284
|
x402ResourceServer2 as x402ResourceServer
|
|
260
285
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "x402z-server",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@x402/core": "^2.0.0",
|
|
12
12
|
"viem": "^2.43.3",
|
|
13
|
-
"x402z-shared": "0.0.
|
|
13
|
+
"x402z-shared": "0.0.9"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"jest": "^29.7.0",
|