@agentcash/router 0.1.0 → 0.2.0

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/index.cjs CHANGED
@@ -35,12 +35,12 @@ var server_exports = {};
35
35
  __export(server_exports, {
36
36
  createX402Server: () => createX402Server
37
37
  });
38
- function createX402Server(config) {
39
- const { x402ResourceServer, HTTPFacilitatorClient } = require("@x402/core/server");
40
- const { registerExactEvmScheme } = require("@x402/evm/exact/server");
41
- const { bazaarResourceServerExtension } = require("@x402/extensions/bazaar");
42
- const { siwxResourceServerExtension } = require("@x402/extensions/sign-in-with-x");
43
- const { facilitator: defaultFacilitator } = require("@coinbase/x402");
38
+ async function createX402Server(config) {
39
+ const { x402ResourceServer, HTTPFacilitatorClient } = await import("@x402/core/server");
40
+ const { registerExactEvmScheme } = await import("@x402/evm/exact/server");
41
+ const { bazaarResourceServerExtension } = await import("@x402/extensions/bazaar");
42
+ const { siwxResourceServerExtension } = await import("@x402/extensions/sign-in-with-x");
43
+ const { facilitator: defaultFacilitator } = await import("@coinbase/x402");
44
44
  const facilitatorUrl = config.facilitatorUrl ?? defaultFacilitator;
45
45
  const client = new HTTPFacilitatorClient(facilitatorUrl);
46
46
  const server = new x402ResourceServer(client);
@@ -214,7 +214,7 @@ async function safeCallHandler(handler, ctx) {
214
214
  if (result instanceof Response) return result;
215
215
  return import_server.NextResponse.json(result);
216
216
  } catch (error) {
217
- const status = error instanceof HttpError ? error.status : 500;
217
+ const status = error instanceof HttpError ? error.status : typeof error.status === "number" ? error.status : 500;
218
218
  const message = error instanceof Error ? error.message : "Internal error";
219
219
  return import_server.NextResponse.json({ success: false, error: message }, { status });
220
220
  }
@@ -288,8 +288,8 @@ function resolveMaxPrice(pricing) {
288
288
  }
289
289
 
290
290
  // src/protocols/x402.ts
291
- function buildX402Challenge(server, routeEntry, request, price, payeeAddress, network, extensions) {
292
- const { encodePaymentRequiredHeader } = require("@x402/core/http");
291
+ async function buildX402Challenge(server, routeEntry, request, price, payeeAddress, network, extensions) {
292
+ const { encodePaymentRequiredHeader } = await import("@x402/core/http");
293
293
  const options = {
294
294
  scheme: "exact",
295
295
  network,
@@ -314,7 +314,7 @@ function buildX402Challenge(server, routeEntry, request, price, payeeAddress, ne
314
314
  return { encoded, requirements };
315
315
  }
316
316
  async function verifyX402Payment(server, request, routeEntry, price, payeeAddress, network) {
317
- const { decodePaymentSignatureHeader } = require("@x402/core/http");
317
+ const { decodePaymentSignatureHeader } = await import("@x402/core/http");
318
318
  const paymentHeader = request.headers.get("PAYMENT-SIGNATURE") ?? request.headers.get("X-PAYMENT");
319
319
  if (!paymentHeader) return null;
320
320
  const payload = decodePaymentSignatureHeader(paymentHeader);
@@ -340,7 +340,7 @@ async function verifyX402Payment(server, request, routeEntry, price, payeeAddres
340
340
  };
341
341
  }
342
342
  async function settleX402Payment(server, payload, requirements) {
343
- const { encodePaymentResponseHeader } = require("@x402/core/http");
343
+ const { encodePaymentResponseHeader } = await import("@x402/core/http");
344
344
  const result = await server.settlePayment(payload, requirements);
345
345
  const encoded = encodePaymentResponseHeader(result);
346
346
  return { encoded, result };
@@ -352,22 +352,22 @@ var Challenge;
352
352
  var Credential;
353
353
  var Receipt;
354
354
  var tempo;
355
- function ensureMpay() {
355
+ async function ensureMpay() {
356
356
  if (mpayLoaded) return;
357
357
  try {
358
- const mpay = require("mpay");
358
+ const mpay = await import("mpay");
359
359
  Challenge = mpay.Challenge;
360
360
  Credential = mpay.Credential;
361
361
  Receipt = mpay.Receipt;
362
- const mpayServer = require("mpay/server");
362
+ const mpayServer = await import("mpay/server");
363
363
  tempo = mpayServer.tempo;
364
364
  mpayLoaded = true;
365
365
  } catch {
366
366
  throw new Error("mpay package is required for MPP protocol support. Install it: pnpm add mpay");
367
367
  }
368
368
  }
369
- function buildMPPChallenge(routeEntry, request, mppConfig, price) {
370
- ensureMpay();
369
+ async function buildMPPChallenge(routeEntry, request, mppConfig, price) {
370
+ await ensureMpay();
371
371
  const intent = {
372
372
  amount: price,
373
373
  currency: mppConfig.currency,
@@ -381,7 +381,7 @@ function buildMPPChallenge(routeEntry, request, mppConfig, price) {
381
381
  return Challenge.serialize(challenge);
382
382
  }
383
383
  async function verifyMPPCredential(request, _routeEntry, mppConfig, price) {
384
- ensureMpay();
384
+ await ensureMpay();
385
385
  const credential = Credential.fromRequest(request);
386
386
  if (!credential) return null;
387
387
  const isValid = Challenge.verify(credential, { secretKey: mppConfig.secretKey });
@@ -402,8 +402,8 @@ async function verifyMPPCredential(request, _routeEntry, mppConfig, price) {
402
402
  payer: verifyResult.payer
403
403
  };
404
404
  }
405
- function buildMPPReceipt(reference) {
406
- ensureMpay();
405
+ async function buildMPPReceipt(reference) {
406
+ await ensureMpay();
407
407
  const receipt = Receipt.from({
408
408
  method: "tempo",
409
409
  status: "success",
@@ -415,11 +415,7 @@ function buildMPPReceipt(reference) {
415
415
 
416
416
  // src/auth/siwx.ts
417
417
  async function verifySIWX(request, _routeEntry, nonceStore) {
418
- const {
419
- parseSIWxHeader,
420
- validateSIWxMessage,
421
- verifySIWxSignature
422
- } = require("@x402/extensions/sign-in-with-x");
418
+ const { parseSIWxHeader, validateSIWxMessage, verifySIWxSignature } = await import("@x402/extensions/sign-in-with-x");
423
419
  const header = request.headers.get("SIGN-IN-WITH-X");
424
420
  if (!header) return { valid: false, wallet: null };
425
421
  const payload = parseSIWxHeader(header);
@@ -427,17 +423,17 @@ async function verifySIWX(request, _routeEntry, nonceStore) {
427
423
  const validation = await validateSIWxMessage(payload, uri, {
428
424
  checkNonce: (nonce) => nonceStore.check(nonce)
429
425
  });
430
- if (!validation.isValid) {
426
+ if (!validation.valid) {
431
427
  return { valid: false, wallet: null };
432
428
  }
433
429
  const verified = await verifySIWxSignature(payload);
434
- if (!verified?.isValid) {
430
+ if (!verified?.valid) {
435
431
  return { valid: false, wallet: null };
436
432
  }
437
433
  return { valid: true, wallet: verified.address };
438
434
  }
439
- function buildSIWXExtension() {
440
- const { declareSIWxExtension } = require("@x402/extensions/sign-in-with-x");
435
+ async function buildSIWXExtension() {
436
+ const { declareSIWxExtension } = await import("@x402/extensions/sign-in-with-x");
441
437
  return declareSIWxExtension();
442
438
  }
443
439
 
@@ -537,11 +533,51 @@ function createRequestHandler(routeEntry, handler, deps) {
537
533
  const protocol = detectProtocol(request);
538
534
  if (routeEntry.authMode === "siwx") {
539
535
  if (!request.headers.get("SIGN-IN-WITH-X")) {
540
- const response = new import_server2.NextResponse(null, { status: 402 });
536
+ const url = new URL(request.url);
537
+ const nonce = crypto.randomUUID();
538
+ const siwxInfo = {
539
+ domain: url.hostname,
540
+ uri: request.url,
541
+ version: "1",
542
+ chainId: deps.network,
543
+ type: "eip191",
544
+ nonce,
545
+ issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
546
+ expirationTime: new Date(Date.now() + 3e5).toISOString(),
547
+ statement: "Sign in to verify your wallet identity"
548
+ };
549
+ let siwxSchema;
541
550
  try {
542
- if (buildSIWXExtension()) response.headers.set("X-SIWX-REQUIRED", "true");
551
+ siwxSchema = await buildSIWXExtension();
543
552
  } catch {
544
553
  }
554
+ const paymentRequired = {
555
+ x402Version: 2,
556
+ error: "SIWX authentication required",
557
+ resource: {
558
+ url: request.url,
559
+ description: routeEntry.description ?? "SIWX-protected endpoint",
560
+ mimeType: "application/json"
561
+ },
562
+ accepts: [],
563
+ extensions: {
564
+ "sign-in-with-x": {
565
+ info: siwxInfo,
566
+ ...siwxSchema ? { schema: siwxSchema } : {}
567
+ }
568
+ }
569
+ };
570
+ let encoded;
571
+ try {
572
+ const { encodePaymentRequiredHeader } = await import("@x402/core/http");
573
+ encoded = encodePaymentRequiredHeader(paymentRequired);
574
+ } catch {
575
+ }
576
+ const response = new import_server2.NextResponse(JSON.stringify(paymentRequired), {
577
+ status: 402,
578
+ headers: { "Content-Type": "application/json" }
579
+ });
580
+ if (encoded) response.headers.set("PAYMENT-REQUIRED", encoded);
545
581
  firePluginResponse(deps, pluginCtx, meta, response);
546
582
  return response;
547
583
  }
@@ -558,7 +594,7 @@ function createRequestHandler(routeEntry, handler, deps) {
558
594
  return handleAuth(siwx.wallet, void 0);
559
595
  }
560
596
  if (!protocol || protocol === "siwx") {
561
- return build402(request, routeEntry, deps, meta, pluginCtx);
597
+ return await build402(request, routeEntry, deps, meta, pluginCtx);
562
598
  }
563
599
  const body = await parseBody(request, routeEntry);
564
600
  if (!body.ok) {
@@ -589,7 +625,7 @@ function createRequestHandler(routeEntry, handler, deps) {
589
625
  deps.payeeAddress,
590
626
  deps.network
591
627
  );
592
- if (!verify?.valid) return build402(request, routeEntry, deps, meta, pluginCtx);
628
+ if (!verify?.valid) return await build402(request, routeEntry, deps, meta, pluginCtx);
593
629
  pluginCtx.setVerifiedWallet(verify.payer);
594
630
  firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
595
631
  protocol: "x402",
@@ -631,9 +667,9 @@ function createRequestHandler(routeEntry, handler, deps) {
631
667
  return response;
632
668
  }
633
669
  if (protocol === "mpp") {
634
- if (!deps.mppConfig) return build402(request, routeEntry, deps, meta, pluginCtx);
670
+ if (!deps.mppConfig) return await build402(request, routeEntry, deps, meta, pluginCtx);
635
671
  const verify = await verifyMPPCredential(request, routeEntry, deps.mppConfig, price);
636
- if (!verify?.valid) return build402(request, routeEntry, deps, meta, pluginCtx);
672
+ if (!verify?.valid) return await build402(request, routeEntry, deps, meta, pluginCtx);
637
673
  const wallet = verify.payer;
638
674
  pluginCtx.setVerifiedWallet(wallet);
639
675
  firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
@@ -652,14 +688,14 @@ function createRequestHandler(routeEntry, handler, deps) {
652
688
  );
653
689
  if (response.status < 400) {
654
690
  try {
655
- response.headers.set("Payment-Receipt", buildMPPReceipt(crypto.randomUUID()));
691
+ response.headers.set("Payment-Receipt", await buildMPPReceipt(crypto.randomUUID()));
656
692
  } catch {
657
693
  }
658
694
  }
659
695
  finalize(response, rawResult, meta, pluginCtx);
660
696
  return response;
661
697
  }
662
- return build402(request, routeEntry, deps, meta, pluginCtx);
698
+ return await build402(request, routeEntry, deps, meta, pluginCtx);
663
699
  };
664
700
  }
665
701
  async function parseBody(request, routeEntry) {
@@ -696,7 +732,7 @@ function parseQuery(request, routeEntry) {
696
732
  const result = routeEntry.querySchema.safeParse(params);
697
733
  return result.success ? result.data : params;
698
734
  }
699
- function build402(request, routeEntry, deps, meta, pluginCtx) {
735
+ async function build402(request, routeEntry, deps, meta, pluginCtx) {
700
736
  const response = new import_server2.NextResponse(null, { status: 402 });
701
737
  let challengePrice;
702
738
  if (routeEntry.maxPrice) {
@@ -712,8 +748,8 @@ function build402(request, routeEntry, deps, meta, pluginCtx) {
712
748
  }
713
749
  let extensions;
714
750
  try {
715
- const { z } = require("zod");
716
- const { declareDiscoveryExtension } = require("@x402/extensions/bazaar");
751
+ const { z } = await import("zod");
752
+ const { declareDiscoveryExtension } = await import("@x402/extensions/bazaar");
717
753
  const inputSchema = routeEntry.bodySchema ? z.toJSONSchema(routeEntry.bodySchema, { target: "draft-2020-12" }) : routeEntry.querySchema ? z.toJSONSchema(routeEntry.querySchema, { target: "draft-2020-12" }) : void 0;
718
754
  const outputSchema = routeEntry.outputSchema ? z.toJSONSchema(routeEntry.outputSchema, { target: "draft-2020-12" }) : void 0;
719
755
  if (inputSchema) {
@@ -728,7 +764,7 @@ function build402(request, routeEntry, deps, meta, pluginCtx) {
728
764
  }
729
765
  if (routeEntry.protocols.includes("x402") && deps.x402Server) {
730
766
  try {
731
- const { encoded } = buildX402Challenge(
767
+ const { encoded } = await buildX402Challenge(
732
768
  deps.x402Server,
733
769
  routeEntry,
734
770
  request,
@@ -745,7 +781,7 @@ function build402(request, routeEntry, deps, meta, pluginCtx) {
745
781
  try {
746
782
  response.headers.set(
747
783
  "WWW-Authenticate",
748
- buildMPPChallenge(routeEntry, request, deps.mppConfig, challengePrice)
784
+ await buildMPPChallenge(routeEntry, request, deps.mppConfig, challengePrice)
749
785
  );
750
786
  } catch {
751
787
  }
@@ -932,6 +968,11 @@ var RouteBuilder = class {
932
968
  next._path = p;
933
969
  return next;
934
970
  }
971
+ method(m) {
972
+ const next = this.fork();
973
+ next._method = m;
974
+ return next;
975
+ }
935
976
  handler(fn) {
936
977
  const entry = {
937
978
  key: this._key,
@@ -980,12 +1021,12 @@ function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
980
1021
  registry.validate(pricesKeys);
981
1022
  validated = true;
982
1023
  }
983
- const x402Resources = [];
984
- const mppResources = [];
1024
+ const x402Set = /* @__PURE__ */ new Set();
1025
+ const mppSet = /* @__PURE__ */ new Set();
985
1026
  for (const [key, entry] of registry.entries()) {
986
1027
  const url = `${baseUrl}/api/${entry.path ?? key}`;
987
- if (entry.protocols.includes("x402")) x402Resources.push(url);
988
- if (entry.protocols.includes("mpp")) mppResources.push(url);
1028
+ if (entry.authMode !== "unprotected") x402Set.add(url);
1029
+ if (entry.protocols.includes("mpp")) mppSet.add(url);
989
1030
  }
990
1031
  let instructions;
991
1032
  if (typeof options.instructions === "function") {
@@ -995,18 +1036,28 @@ function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
995
1036
  }
996
1037
  const body = {
997
1038
  version: 1,
998
- resources: x402Resources
1039
+ resources: Array.from(x402Set)
999
1040
  };
1041
+ const mppResources = Array.from(mppSet);
1000
1042
  if (mppResources.length > 0) {
1001
1043
  body.mppResources = mppResources;
1002
1044
  }
1045
+ if (options.description) {
1046
+ body.description = options.description;
1047
+ }
1003
1048
  if (options.ownershipProofs) {
1004
1049
  body.ownershipProofs = options.ownershipProofs;
1005
1050
  }
1006
1051
  if (instructions) {
1007
1052
  body.instructions = instructions;
1008
1053
  }
1009
- return import_server3.NextResponse.json(body);
1054
+ return import_server3.NextResponse.json(body, {
1055
+ headers: {
1056
+ "Access-Control-Allow-Origin": "*",
1057
+ "Access-Control-Allow-Methods": "GET",
1058
+ "Access-Control-Allow-Headers": "Content-Type"
1059
+ }
1060
+ });
1010
1061
  };
1011
1062
  }
1012
1063
 
@@ -1029,9 +1080,7 @@ function createOpenAPIHandler(registry, baseUrl, pricesKeys, options) {
1029
1080
  const method = entry.method.toLowerCase();
1030
1081
  const tag = deriveTag(key);
1031
1082
  tagSet.add(tag);
1032
- paths[apiPath] = {
1033
- [method]: buildOperation(key, entry, tag)
1034
- };
1083
+ paths[apiPath] = { ...paths[apiPath], [method]: buildOperation(key, entry, tag) };
1035
1084
  }
1036
1085
  cached = createDocument({
1037
1086
  openapi: "3.1.0",
@@ -1122,16 +1171,17 @@ function createRouter(config) {
1122
1171
  network,
1123
1172
  mppConfig: config.mpp
1124
1173
  };
1125
- try {
1126
- const { createX402Server: createX402Server2 } = (init_server(), __toCommonJS(server_exports));
1127
- const result = createX402Server2(config);
1128
- deps.x402Server = result.server;
1129
- deps.initPromise = result.initPromise.catch((err) => {
1174
+ deps.initPromise = (async () => {
1175
+ try {
1176
+ const { createX402Server: createX402Server2 } = await Promise.resolve().then(() => (init_server(), server_exports));
1177
+ const result = await createX402Server2(config);
1178
+ deps.x402Server = result.server;
1179
+ await result.initPromise;
1180
+ } catch (err) {
1130
1181
  deps.x402Server = null;
1131
1182
  deps.x402InitError = err instanceof Error ? err.message : String(err);
1132
- });
1133
- } catch {
1134
- }
1183
+ }
1184
+ })();
1135
1185
  const pricesKeys = config.prices ? Object.keys(config.prices) : void 0;
1136
1186
  return {
1137
1187
  route(key) {
package/dist/index.d.cts CHANGED
@@ -142,7 +142,7 @@ interface RouteEntry {
142
142
  outputSchema?: ZodType;
143
143
  description?: string;
144
144
  path?: string;
145
- method: 'GET' | 'POST';
145
+ method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
146
146
  maxPrice?: string;
147
147
  apiKeyResolver?: (key: string) => unknown | Promise<unknown>;
148
148
  providerName?: string;
@@ -175,6 +175,7 @@ declare class RouteRegistry {
175
175
  }
176
176
 
177
177
  interface WellKnownOptions {
178
+ description?: string;
178
179
  instructions?: string | (() => string | Promise<string>);
179
180
  ownershipProofs?: string[];
180
181
  }
@@ -220,7 +221,7 @@ declare class RouteBuilder<TBody = undefined, TQuery = undefined, HasAuth extend
220
221
  /** @internal */ _outputSchema: ZodType | undefined;
221
222
  /** @internal */ _description: string | undefined;
222
223
  /** @internal */ _path: string | undefined;
223
- /** @internal */ _method: 'GET' | 'POST';
224
+ /** @internal */ _method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
224
225
  /** @internal */ _apiKeyResolver: ((key: string) => unknown | Promise<unknown>) | undefined;
225
226
  /** @internal */ _providerName: string | undefined;
226
227
  /** @internal */ _providerConfig: ProviderConfig | undefined;
@@ -247,6 +248,7 @@ declare class RouteBuilder<TBody = undefined, TQuery = undefined, HasAuth extend
247
248
  output(schema: ZodType): this;
248
249
  description(text: string): this;
249
250
  path(p: string): this;
251
+ method(m: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH'): this;
250
252
  handler(this: RouteBuilder<TBody, TQuery, True, true, false>, fn: never): never;
251
253
  handler(this: RouteBuilder<TBody, TQuery, false, boolean, boolean>, fn: never): never;
252
254
  handler(this: RouteBuilder<TBody, TQuery, True, False, HasBody>, fn: (ctx: HandlerContext<TBody, TQuery>) => Promise<unknown>): (request: NextRequest) => Promise<Response>;
package/dist/index.d.ts CHANGED
@@ -142,7 +142,7 @@ interface RouteEntry {
142
142
  outputSchema?: ZodType;
143
143
  description?: string;
144
144
  path?: string;
145
- method: 'GET' | 'POST';
145
+ method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
146
146
  maxPrice?: string;
147
147
  apiKeyResolver?: (key: string) => unknown | Promise<unknown>;
148
148
  providerName?: string;
@@ -175,6 +175,7 @@ declare class RouteRegistry {
175
175
  }
176
176
 
177
177
  interface WellKnownOptions {
178
+ description?: string;
178
179
  instructions?: string | (() => string | Promise<string>);
179
180
  ownershipProofs?: string[];
180
181
  }
@@ -220,7 +221,7 @@ declare class RouteBuilder<TBody = undefined, TQuery = undefined, HasAuth extend
220
221
  /** @internal */ _outputSchema: ZodType | undefined;
221
222
  /** @internal */ _description: string | undefined;
222
223
  /** @internal */ _path: string | undefined;
223
- /** @internal */ _method: 'GET' | 'POST';
224
+ /** @internal */ _method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
224
225
  /** @internal */ _apiKeyResolver: ((key: string) => unknown | Promise<unknown>) | undefined;
225
226
  /** @internal */ _providerName: string | undefined;
226
227
  /** @internal */ _providerConfig: ProviderConfig | undefined;
@@ -247,6 +248,7 @@ declare class RouteBuilder<TBody = undefined, TQuery = undefined, HasAuth extend
247
248
  output(schema: ZodType): this;
248
249
  description(text: string): this;
249
250
  path(p: string): this;
251
+ method(m: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH'): this;
250
252
  handler(this: RouteBuilder<TBody, TQuery, True, true, false>, fn: never): never;
251
253
  handler(this: RouteBuilder<TBody, TQuery, false, boolean, boolean>, fn: never): never;
252
254
  handler(this: RouteBuilder<TBody, TQuery, True, False, HasBody>, fn: (ctx: HandlerContext<TBody, TQuery>) => Promise<unknown>): (request: NextRequest) => Promise<Response>;
package/dist/index.js CHANGED
@@ -1,13 +1,5 @@
1
1
  var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
6
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
7
- }) : x)(function(x) {
8
- if (typeof require !== "undefined") return require.apply(this, arguments);
9
- throw Error('Dynamic require of "' + x + '" is not supported');
10
- });
11
3
  var __esm = (fn, res) => function __init() {
12
4
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
13
5
  };
@@ -15,27 +7,18 @@ var __export = (target, all) => {
15
7
  for (var name in all)
16
8
  __defProp(target, name, { get: all[name], enumerable: true });
17
9
  };
18
- var __copyProps = (to, from, except, desc) => {
19
- if (from && typeof from === "object" || typeof from === "function") {
20
- for (let key of __getOwnPropNames(from))
21
- if (!__hasOwnProp.call(to, key) && key !== except)
22
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
- }
24
- return to;
25
- };
26
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
10
 
28
11
  // src/server.ts
29
12
  var server_exports = {};
30
13
  __export(server_exports, {
31
14
  createX402Server: () => createX402Server
32
15
  });
33
- function createX402Server(config) {
34
- const { x402ResourceServer, HTTPFacilitatorClient } = __require("@x402/core/server");
35
- const { registerExactEvmScheme } = __require("@x402/evm/exact/server");
36
- const { bazaarResourceServerExtension } = __require("@x402/extensions/bazaar");
37
- const { siwxResourceServerExtension } = __require("@x402/extensions/sign-in-with-x");
38
- const { facilitator: defaultFacilitator } = __require("@coinbase/x402");
16
+ async function createX402Server(config) {
17
+ const { x402ResourceServer, HTTPFacilitatorClient } = await import("@x402/core/server");
18
+ const { registerExactEvmScheme } = await import("@x402/evm/exact/server");
19
+ const { bazaarResourceServerExtension } = await import("@x402/extensions/bazaar");
20
+ const { siwxResourceServerExtension } = await import("@x402/extensions/sign-in-with-x");
21
+ const { facilitator: defaultFacilitator } = await import("@coinbase/x402");
39
22
  const facilitatorUrl = config.facilitatorUrl ?? defaultFacilitator;
40
23
  const client = new HTTPFacilitatorClient(facilitatorUrl);
41
24
  const server = new x402ResourceServer(client);
@@ -197,7 +180,7 @@ async function safeCallHandler(handler, ctx) {
197
180
  if (result instanceof Response) return result;
198
181
  return NextResponse.json(result);
199
182
  } catch (error) {
200
- const status = error instanceof HttpError ? error.status : 500;
183
+ const status = error instanceof HttpError ? error.status : typeof error.status === "number" ? error.status : 500;
201
184
  const message = error instanceof Error ? error.message : "Internal error";
202
185
  return NextResponse.json({ success: false, error: message }, { status });
203
186
  }
@@ -271,8 +254,8 @@ function resolveMaxPrice(pricing) {
271
254
  }
272
255
 
273
256
  // src/protocols/x402.ts
274
- function buildX402Challenge(server, routeEntry, request, price, payeeAddress, network, extensions) {
275
- const { encodePaymentRequiredHeader } = __require("@x402/core/http");
257
+ async function buildX402Challenge(server, routeEntry, request, price, payeeAddress, network, extensions) {
258
+ const { encodePaymentRequiredHeader } = await import("@x402/core/http");
276
259
  const options = {
277
260
  scheme: "exact",
278
261
  network,
@@ -297,7 +280,7 @@ function buildX402Challenge(server, routeEntry, request, price, payeeAddress, ne
297
280
  return { encoded, requirements };
298
281
  }
299
282
  async function verifyX402Payment(server, request, routeEntry, price, payeeAddress, network) {
300
- const { decodePaymentSignatureHeader } = __require("@x402/core/http");
283
+ const { decodePaymentSignatureHeader } = await import("@x402/core/http");
301
284
  const paymentHeader = request.headers.get("PAYMENT-SIGNATURE") ?? request.headers.get("X-PAYMENT");
302
285
  if (!paymentHeader) return null;
303
286
  const payload = decodePaymentSignatureHeader(paymentHeader);
@@ -323,7 +306,7 @@ async function verifyX402Payment(server, request, routeEntry, price, payeeAddres
323
306
  };
324
307
  }
325
308
  async function settleX402Payment(server, payload, requirements) {
326
- const { encodePaymentResponseHeader } = __require("@x402/core/http");
309
+ const { encodePaymentResponseHeader } = await import("@x402/core/http");
327
310
  const result = await server.settlePayment(payload, requirements);
328
311
  const encoded = encodePaymentResponseHeader(result);
329
312
  return { encoded, result };
@@ -335,22 +318,22 @@ var Challenge;
335
318
  var Credential;
336
319
  var Receipt;
337
320
  var tempo;
338
- function ensureMpay() {
321
+ async function ensureMpay() {
339
322
  if (mpayLoaded) return;
340
323
  try {
341
- const mpay = __require("mpay");
324
+ const mpay = await import("mpay");
342
325
  Challenge = mpay.Challenge;
343
326
  Credential = mpay.Credential;
344
327
  Receipt = mpay.Receipt;
345
- const mpayServer = __require("mpay/server");
328
+ const mpayServer = await import("mpay/server");
346
329
  tempo = mpayServer.tempo;
347
330
  mpayLoaded = true;
348
331
  } catch {
349
332
  throw new Error("mpay package is required for MPP protocol support. Install it: pnpm add mpay");
350
333
  }
351
334
  }
352
- function buildMPPChallenge(routeEntry, request, mppConfig, price) {
353
- ensureMpay();
335
+ async function buildMPPChallenge(routeEntry, request, mppConfig, price) {
336
+ await ensureMpay();
354
337
  const intent = {
355
338
  amount: price,
356
339
  currency: mppConfig.currency,
@@ -364,7 +347,7 @@ function buildMPPChallenge(routeEntry, request, mppConfig, price) {
364
347
  return Challenge.serialize(challenge);
365
348
  }
366
349
  async function verifyMPPCredential(request, _routeEntry, mppConfig, price) {
367
- ensureMpay();
350
+ await ensureMpay();
368
351
  const credential = Credential.fromRequest(request);
369
352
  if (!credential) return null;
370
353
  const isValid = Challenge.verify(credential, { secretKey: mppConfig.secretKey });
@@ -385,8 +368,8 @@ async function verifyMPPCredential(request, _routeEntry, mppConfig, price) {
385
368
  payer: verifyResult.payer
386
369
  };
387
370
  }
388
- function buildMPPReceipt(reference) {
389
- ensureMpay();
371
+ async function buildMPPReceipt(reference) {
372
+ await ensureMpay();
390
373
  const receipt = Receipt.from({
391
374
  method: "tempo",
392
375
  status: "success",
@@ -398,11 +381,7 @@ function buildMPPReceipt(reference) {
398
381
 
399
382
  // src/auth/siwx.ts
400
383
  async function verifySIWX(request, _routeEntry, nonceStore) {
401
- const {
402
- parseSIWxHeader,
403
- validateSIWxMessage,
404
- verifySIWxSignature
405
- } = __require("@x402/extensions/sign-in-with-x");
384
+ const { parseSIWxHeader, validateSIWxMessage, verifySIWxSignature } = await import("@x402/extensions/sign-in-with-x");
406
385
  const header = request.headers.get("SIGN-IN-WITH-X");
407
386
  if (!header) return { valid: false, wallet: null };
408
387
  const payload = parseSIWxHeader(header);
@@ -410,17 +389,17 @@ async function verifySIWX(request, _routeEntry, nonceStore) {
410
389
  const validation = await validateSIWxMessage(payload, uri, {
411
390
  checkNonce: (nonce) => nonceStore.check(nonce)
412
391
  });
413
- if (!validation.isValid) {
392
+ if (!validation.valid) {
414
393
  return { valid: false, wallet: null };
415
394
  }
416
395
  const verified = await verifySIWxSignature(payload);
417
- if (!verified?.isValid) {
396
+ if (!verified?.valid) {
418
397
  return { valid: false, wallet: null };
419
398
  }
420
399
  return { valid: true, wallet: verified.address };
421
400
  }
422
- function buildSIWXExtension() {
423
- const { declareSIWxExtension } = __require("@x402/extensions/sign-in-with-x");
401
+ async function buildSIWXExtension() {
402
+ const { declareSIWxExtension } = await import("@x402/extensions/sign-in-with-x");
424
403
  return declareSIWxExtension();
425
404
  }
426
405
 
@@ -520,11 +499,51 @@ function createRequestHandler(routeEntry, handler, deps) {
520
499
  const protocol = detectProtocol(request);
521
500
  if (routeEntry.authMode === "siwx") {
522
501
  if (!request.headers.get("SIGN-IN-WITH-X")) {
523
- const response = new NextResponse2(null, { status: 402 });
502
+ const url = new URL(request.url);
503
+ const nonce = crypto.randomUUID();
504
+ const siwxInfo = {
505
+ domain: url.hostname,
506
+ uri: request.url,
507
+ version: "1",
508
+ chainId: deps.network,
509
+ type: "eip191",
510
+ nonce,
511
+ issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
512
+ expirationTime: new Date(Date.now() + 3e5).toISOString(),
513
+ statement: "Sign in to verify your wallet identity"
514
+ };
515
+ let siwxSchema;
524
516
  try {
525
- if (buildSIWXExtension()) response.headers.set("X-SIWX-REQUIRED", "true");
517
+ siwxSchema = await buildSIWXExtension();
526
518
  } catch {
527
519
  }
520
+ const paymentRequired = {
521
+ x402Version: 2,
522
+ error: "SIWX authentication required",
523
+ resource: {
524
+ url: request.url,
525
+ description: routeEntry.description ?? "SIWX-protected endpoint",
526
+ mimeType: "application/json"
527
+ },
528
+ accepts: [],
529
+ extensions: {
530
+ "sign-in-with-x": {
531
+ info: siwxInfo,
532
+ ...siwxSchema ? { schema: siwxSchema } : {}
533
+ }
534
+ }
535
+ };
536
+ let encoded;
537
+ try {
538
+ const { encodePaymentRequiredHeader } = await import("@x402/core/http");
539
+ encoded = encodePaymentRequiredHeader(paymentRequired);
540
+ } catch {
541
+ }
542
+ const response = new NextResponse2(JSON.stringify(paymentRequired), {
543
+ status: 402,
544
+ headers: { "Content-Type": "application/json" }
545
+ });
546
+ if (encoded) response.headers.set("PAYMENT-REQUIRED", encoded);
528
547
  firePluginResponse(deps, pluginCtx, meta, response);
529
548
  return response;
530
549
  }
@@ -541,7 +560,7 @@ function createRequestHandler(routeEntry, handler, deps) {
541
560
  return handleAuth(siwx.wallet, void 0);
542
561
  }
543
562
  if (!protocol || protocol === "siwx") {
544
- return build402(request, routeEntry, deps, meta, pluginCtx);
563
+ return await build402(request, routeEntry, deps, meta, pluginCtx);
545
564
  }
546
565
  const body = await parseBody(request, routeEntry);
547
566
  if (!body.ok) {
@@ -572,7 +591,7 @@ function createRequestHandler(routeEntry, handler, deps) {
572
591
  deps.payeeAddress,
573
592
  deps.network
574
593
  );
575
- if (!verify?.valid) return build402(request, routeEntry, deps, meta, pluginCtx);
594
+ if (!verify?.valid) return await build402(request, routeEntry, deps, meta, pluginCtx);
576
595
  pluginCtx.setVerifiedWallet(verify.payer);
577
596
  firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
578
597
  protocol: "x402",
@@ -614,9 +633,9 @@ function createRequestHandler(routeEntry, handler, deps) {
614
633
  return response;
615
634
  }
616
635
  if (protocol === "mpp") {
617
- if (!deps.mppConfig) return build402(request, routeEntry, deps, meta, pluginCtx);
636
+ if (!deps.mppConfig) return await build402(request, routeEntry, deps, meta, pluginCtx);
618
637
  const verify = await verifyMPPCredential(request, routeEntry, deps.mppConfig, price);
619
- if (!verify?.valid) return build402(request, routeEntry, deps, meta, pluginCtx);
638
+ if (!verify?.valid) return await build402(request, routeEntry, deps, meta, pluginCtx);
620
639
  const wallet = verify.payer;
621
640
  pluginCtx.setVerifiedWallet(wallet);
622
641
  firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
@@ -635,14 +654,14 @@ function createRequestHandler(routeEntry, handler, deps) {
635
654
  );
636
655
  if (response.status < 400) {
637
656
  try {
638
- response.headers.set("Payment-Receipt", buildMPPReceipt(crypto.randomUUID()));
657
+ response.headers.set("Payment-Receipt", await buildMPPReceipt(crypto.randomUUID()));
639
658
  } catch {
640
659
  }
641
660
  }
642
661
  finalize(response, rawResult, meta, pluginCtx);
643
662
  return response;
644
663
  }
645
- return build402(request, routeEntry, deps, meta, pluginCtx);
664
+ return await build402(request, routeEntry, deps, meta, pluginCtx);
646
665
  };
647
666
  }
648
667
  async function parseBody(request, routeEntry) {
@@ -679,7 +698,7 @@ function parseQuery(request, routeEntry) {
679
698
  const result = routeEntry.querySchema.safeParse(params);
680
699
  return result.success ? result.data : params;
681
700
  }
682
- function build402(request, routeEntry, deps, meta, pluginCtx) {
701
+ async function build402(request, routeEntry, deps, meta, pluginCtx) {
683
702
  const response = new NextResponse2(null, { status: 402 });
684
703
  let challengePrice;
685
704
  if (routeEntry.maxPrice) {
@@ -695,8 +714,8 @@ function build402(request, routeEntry, deps, meta, pluginCtx) {
695
714
  }
696
715
  let extensions;
697
716
  try {
698
- const { z } = __require("zod");
699
- const { declareDiscoveryExtension } = __require("@x402/extensions/bazaar");
717
+ const { z } = await import("zod");
718
+ const { declareDiscoveryExtension } = await import("@x402/extensions/bazaar");
700
719
  const inputSchema = routeEntry.bodySchema ? z.toJSONSchema(routeEntry.bodySchema, { target: "draft-2020-12" }) : routeEntry.querySchema ? z.toJSONSchema(routeEntry.querySchema, { target: "draft-2020-12" }) : void 0;
701
720
  const outputSchema = routeEntry.outputSchema ? z.toJSONSchema(routeEntry.outputSchema, { target: "draft-2020-12" }) : void 0;
702
721
  if (inputSchema) {
@@ -711,7 +730,7 @@ function build402(request, routeEntry, deps, meta, pluginCtx) {
711
730
  }
712
731
  if (routeEntry.protocols.includes("x402") && deps.x402Server) {
713
732
  try {
714
- const { encoded } = buildX402Challenge(
733
+ const { encoded } = await buildX402Challenge(
715
734
  deps.x402Server,
716
735
  routeEntry,
717
736
  request,
@@ -728,7 +747,7 @@ function build402(request, routeEntry, deps, meta, pluginCtx) {
728
747
  try {
729
748
  response.headers.set(
730
749
  "WWW-Authenticate",
731
- buildMPPChallenge(routeEntry, request, deps.mppConfig, challengePrice)
750
+ await buildMPPChallenge(routeEntry, request, deps.mppConfig, challengePrice)
732
751
  );
733
752
  } catch {
734
753
  }
@@ -915,6 +934,11 @@ var RouteBuilder = class {
915
934
  next._path = p;
916
935
  return next;
917
936
  }
937
+ method(m) {
938
+ const next = this.fork();
939
+ next._method = m;
940
+ return next;
941
+ }
918
942
  handler(fn) {
919
943
  const entry = {
920
944
  key: this._key,
@@ -963,12 +987,12 @@ function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
963
987
  registry.validate(pricesKeys);
964
988
  validated = true;
965
989
  }
966
- const x402Resources = [];
967
- const mppResources = [];
990
+ const x402Set = /* @__PURE__ */ new Set();
991
+ const mppSet = /* @__PURE__ */ new Set();
968
992
  for (const [key, entry] of registry.entries()) {
969
993
  const url = `${baseUrl}/api/${entry.path ?? key}`;
970
- if (entry.protocols.includes("x402")) x402Resources.push(url);
971
- if (entry.protocols.includes("mpp")) mppResources.push(url);
994
+ if (entry.authMode !== "unprotected") x402Set.add(url);
995
+ if (entry.protocols.includes("mpp")) mppSet.add(url);
972
996
  }
973
997
  let instructions;
974
998
  if (typeof options.instructions === "function") {
@@ -978,18 +1002,28 @@ function createWellKnownHandler(registry, baseUrl, pricesKeys, options = {}) {
978
1002
  }
979
1003
  const body = {
980
1004
  version: 1,
981
- resources: x402Resources
1005
+ resources: Array.from(x402Set)
982
1006
  };
1007
+ const mppResources = Array.from(mppSet);
983
1008
  if (mppResources.length > 0) {
984
1009
  body.mppResources = mppResources;
985
1010
  }
1011
+ if (options.description) {
1012
+ body.description = options.description;
1013
+ }
986
1014
  if (options.ownershipProofs) {
987
1015
  body.ownershipProofs = options.ownershipProofs;
988
1016
  }
989
1017
  if (instructions) {
990
1018
  body.instructions = instructions;
991
1019
  }
992
- return NextResponse3.json(body);
1020
+ return NextResponse3.json(body, {
1021
+ headers: {
1022
+ "Access-Control-Allow-Origin": "*",
1023
+ "Access-Control-Allow-Methods": "GET",
1024
+ "Access-Control-Allow-Headers": "Content-Type"
1025
+ }
1026
+ });
993
1027
  };
994
1028
  }
995
1029
 
@@ -1012,9 +1046,7 @@ function createOpenAPIHandler(registry, baseUrl, pricesKeys, options) {
1012
1046
  const method = entry.method.toLowerCase();
1013
1047
  const tag = deriveTag(key);
1014
1048
  tagSet.add(tag);
1015
- paths[apiPath] = {
1016
- [method]: buildOperation(key, entry, tag)
1017
- };
1049
+ paths[apiPath] = { ...paths[apiPath], [method]: buildOperation(key, entry, tag) };
1018
1050
  }
1019
1051
  cached = createDocument({
1020
1052
  openapi: "3.1.0",
@@ -1105,16 +1137,17 @@ function createRouter(config) {
1105
1137
  network,
1106
1138
  mppConfig: config.mpp
1107
1139
  };
1108
- try {
1109
- const { createX402Server: createX402Server2 } = (init_server(), __toCommonJS(server_exports));
1110
- const result = createX402Server2(config);
1111
- deps.x402Server = result.server;
1112
- deps.initPromise = result.initPromise.catch((err) => {
1140
+ deps.initPromise = (async () => {
1141
+ try {
1142
+ const { createX402Server: createX402Server2 } = await Promise.resolve().then(() => (init_server(), server_exports));
1143
+ const result = await createX402Server2(config);
1144
+ deps.x402Server = result.server;
1145
+ await result.initPromise;
1146
+ } catch (err) {
1113
1147
  deps.x402Server = null;
1114
1148
  deps.x402InitError = err instanceof Error ? err.message : String(err);
1115
- });
1116
- } catch {
1117
- }
1149
+ }
1150
+ })();
1118
1151
  const pricesKeys = config.prices ? Object.keys(config.prices) : void 0;
1119
1152
  return {
1120
1153
  route(key) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcash/router",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Unified route builder for Next.js App Router APIs with x402, MPP, SIWX, and API key auth",
5
5
  "type": "module",
6
6
  "exports": {
@@ -21,6 +21,17 @@
21
21
  "files": [
22
22
  "dist"
23
23
  ],
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "typecheck": "tsc --noEmit",
27
+ "lint": "eslint src/",
28
+ "lint:fix": "eslint src/ --fix",
29
+ "format": "prettier --write 'src/**/*.ts' 'tests/**/*.ts' '*.json' '*.mjs'",
30
+ "format:check": "prettier --check 'src/**/*.ts' 'tests/**/*.ts' '*.json' '*.mjs'",
31
+ "test": "vitest run",
32
+ "test:watch": "vitest",
33
+ "check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm build && pnpm test"
34
+ },
24
35
  "peerDependencies": {
25
36
  "@coinbase/x402": "^2.1.0",
26
37
  "@x402/core": "^2.3.0",
@@ -55,20 +66,10 @@
55
66
  "zod": "^4.0.0",
56
67
  "zod-openapi": "^5.0.0"
57
68
  },
69
+ "packageManager": "pnpm@10.28.0",
58
70
  "license": "MIT",
59
71
  "repository": {
60
72
  "type": "git",
61
73
  "url": "https://github.com/merit-systems/agentcash-router"
62
- },
63
- "scripts": {
64
- "build": "tsup",
65
- "typecheck": "tsc --noEmit",
66
- "lint": "eslint src/",
67
- "lint:fix": "eslint src/ --fix",
68
- "format": "prettier --write 'src/**/*.ts' 'tests/**/*.ts' '*.json' '*.mjs'",
69
- "format:check": "prettier --check 'src/**/*.ts' 'tests/**/*.ts' '*.json' '*.mjs'",
70
- "test": "vitest run",
71
- "test:watch": "vitest",
72
- "check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm build && pnpm test"
73
74
  }
74
- }
75
+ }