@agentcash/router 1.1.9 → 1.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
@@ -625,8 +625,8 @@ function resolveMaxPrice(pricing) {
625
625
  }
626
626
 
627
627
  // src/orchestrate.ts
628
- var import_mppx = require("mppx");
629
- var import_viem = require("viem");
628
+ var import_mppx2 = require("mppx");
629
+ var import_viem2 = require("viem");
630
630
 
631
631
  // src/protocols/x402.ts
632
632
  init_x402_facilitators();
@@ -662,7 +662,14 @@ async function verifyX402Payment(opts) {
662
662
  if (!matching) {
663
663
  return invalidPaymentVerification();
664
664
  }
665
- const verify = await server.verifyPayment(payload, matching);
665
+ let verify;
666
+ try {
667
+ verify = await server.verifyPayment(payload, matching);
668
+ } catch (err) {
669
+ const sc = err.statusCode;
670
+ if (sc && sc >= 400 && sc < 500) return invalidPaymentVerification();
671
+ throw err;
672
+ }
666
673
  if (!verify.isValid) return invalidPaymentVerification();
667
674
  return {
668
675
  valid: true,
@@ -891,6 +898,22 @@ async function buildSIWXExtension() {
891
898
  return declareSIWxExtension();
892
899
  }
893
900
 
901
+ // src/auth/mpp-siwx.ts
902
+ var import_mppx = require("mppx");
903
+ var import_viem = require("viem");
904
+ async function verifyMppSiwx(request, mppx) {
905
+ const result = await mppx.charge({ amount: "0" })(request);
906
+ if (result.status === 402) {
907
+ return { valid: false, challenge: result.challenge };
908
+ }
909
+ const credential = import_mppx.Credential.fromRequest(request);
910
+ const rawSource = credential?.source ?? "";
911
+ const didParts = rawSource.split(":");
912
+ const lastPart = didParts[didParts.length - 1];
913
+ const wallet = normalizeWalletAddress((0, import_viem.isAddress)(lastPart) ? (0, import_viem.getAddress)(lastPart) : rawSource);
914
+ return { valid: true, wallet, withReceipt: result.withReceipt };
915
+ }
916
+
894
917
  // src/auth/api-key.ts
895
918
  async function verifyApiKey(request, resolver) {
896
919
  const apiKey = request.headers.get("X-API-Key") ?? extractBearerToken(request.headers.get("Authorization"));
@@ -1056,6 +1079,33 @@ function createRequestHandler(routeEntry, handler, deps) {
1056
1079
  }
1057
1080
  }
1058
1081
  const siwxHeader = request.headers.get("SIGN-IN-WITH-X");
1082
+ if (!siwxHeader && protocol === "mpp" && routeEntry.authMode === "siwx" && deps.mppx) {
1083
+ let mppSiwxResult;
1084
+ try {
1085
+ mppSiwxResult = await verifyMppSiwx(request, deps.mppx);
1086
+ } catch (err) {
1087
+ const message = err instanceof Error ? err.message : String(err);
1088
+ firePluginHook(deps.plugin, "onAlert", pluginCtx, {
1089
+ level: "critical",
1090
+ message: `MPP SIWX verification failed: ${message}`,
1091
+ route: routeEntry.key
1092
+ });
1093
+ return fail(500, `MPP SIWX verification failed: ${message}`, meta, pluginCtx);
1094
+ }
1095
+ if (mppSiwxResult.valid) {
1096
+ pluginCtx.setVerifiedWallet(mppSiwxResult.wallet);
1097
+ firePluginHook(deps.plugin, "onAuthVerified", pluginCtx, {
1098
+ authMode: "siwx",
1099
+ wallet: mppSiwxResult.wallet,
1100
+ route: routeEntry.key
1101
+ });
1102
+ const authResponse = await handleAuth(mppSiwxResult.wallet, void 0);
1103
+ if (authResponse.status < 400) {
1104
+ return mppSiwxResult.withReceipt(authResponse);
1105
+ }
1106
+ return authResponse;
1107
+ }
1108
+ }
1059
1109
  if (!siwxHeader && routeEntry.authMode === "siwx") {
1060
1110
  const url = new URL(request.url);
1061
1111
  const nonce = crypto.randomUUID().replace(/-/g, "");
@@ -1111,6 +1161,16 @@ function createRequestHandler(routeEntry, handler, deps) {
1111
1161
  headers: { "Content-Type": "application/json", "Cache-Control": "no-store" }
1112
1162
  });
1113
1163
  if (encoded) response.headers.set("PAYMENT-REQUIRED", encoded);
1164
+ if (deps.mppx) {
1165
+ try {
1166
+ const mppChallenge = await deps.mppx.charge({ amount: "0" })(request);
1167
+ if (mppChallenge.status === 402) {
1168
+ const wwwAuth = mppChallenge.challenge.headers.get("WWW-Authenticate");
1169
+ if (wwwAuth) response.headers.set("WWW-Authenticate", wwwAuth);
1170
+ }
1171
+ } catch {
1172
+ }
1173
+ }
1114
1174
  firePluginResponse(deps, pluginCtx, meta, response);
1115
1175
  return response;
1116
1176
  }
@@ -1336,11 +1396,11 @@ function createRequestHandler(routeEntry, handler, deps) {
1336
1396
  });
1337
1397
  return await build402(request, routeEntry, deps, meta, pluginCtx, body.data);
1338
1398
  }
1339
- const credential = import_mppx.Credential.fromRequest(request);
1399
+ const credential = import_mppx2.Credential.fromRequest(request);
1340
1400
  const rawSource = credential?.source ?? "";
1341
1401
  const didParts = rawSource.split(":");
1342
1402
  const lastPart = didParts[didParts.length - 1];
1343
- const wallet = normalizeWalletAddress((0, import_viem.isAddress)(lastPart) ? (0, import_viem.getAddress)(lastPart) : rawSource);
1403
+ const wallet = normalizeWalletAddress((0, import_viem2.isAddress)(lastPart) ? (0, import_viem2.getAddress)(lastPart) : rawSource);
1344
1404
  pluginCtx.setVerifiedWallet(wallet);
1345
1405
  firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
1346
1406
  protocol: "mpp",
@@ -1419,7 +1479,7 @@ async function resolveDynamicPrice(bodyData, routeEntry, deps, pluginCtx, meta)
1419
1479
  if (routeEntry.maxPrice) {
1420
1480
  const calculated = parseFloat(price);
1421
1481
  const max = parseFloat(routeEntry.maxPrice);
1422
- if (calculated > max) {
1482
+ if (!Number.isFinite(calculated) || calculated > max) {
1423
1483
  firePluginHook(deps.plugin, "onAlert", pluginCtx, {
1424
1484
  level: "warn",
1425
1485
  message: `Price ${price} exceeds maxPrice ${routeEntry.maxPrice}, capping`,
package/dist/index.js CHANGED
@@ -586,8 +586,8 @@ function resolveMaxPrice(pricing) {
586
586
  }
587
587
 
588
588
  // src/orchestrate.ts
589
- import { Credential } from "mppx";
590
- import { isAddress, getAddress } from "viem";
589
+ import { Credential as Credential2 } from "mppx";
590
+ import { isAddress as isAddress2, getAddress as getAddress2 } from "viem";
591
591
 
592
592
  // src/protocols/x402.ts
593
593
  init_x402_facilitators();
@@ -623,7 +623,14 @@ async function verifyX402Payment(opts) {
623
623
  if (!matching) {
624
624
  return invalidPaymentVerification();
625
625
  }
626
- const verify = await server.verifyPayment(payload, matching);
626
+ let verify;
627
+ try {
628
+ verify = await server.verifyPayment(payload, matching);
629
+ } catch (err) {
630
+ const sc = err.statusCode;
631
+ if (sc && sc >= 400 && sc < 500) return invalidPaymentVerification();
632
+ throw err;
633
+ }
627
634
  if (!verify.isValid) return invalidPaymentVerification();
628
635
  return {
629
636
  valid: true,
@@ -852,6 +859,22 @@ async function buildSIWXExtension() {
852
859
  return declareSIWxExtension();
853
860
  }
854
861
 
862
+ // src/auth/mpp-siwx.ts
863
+ import { Credential } from "mppx";
864
+ import { isAddress, getAddress } from "viem";
865
+ async function verifyMppSiwx(request, mppx) {
866
+ const result = await mppx.charge({ amount: "0" })(request);
867
+ if (result.status === 402) {
868
+ return { valid: false, challenge: result.challenge };
869
+ }
870
+ const credential = Credential.fromRequest(request);
871
+ const rawSource = credential?.source ?? "";
872
+ const didParts = rawSource.split(":");
873
+ const lastPart = didParts[didParts.length - 1];
874
+ const wallet = normalizeWalletAddress(isAddress(lastPart) ? getAddress(lastPart) : rawSource);
875
+ return { valid: true, wallet, withReceipt: result.withReceipt };
876
+ }
877
+
855
878
  // src/auth/api-key.ts
856
879
  async function verifyApiKey(request, resolver) {
857
880
  const apiKey = request.headers.get("X-API-Key") ?? extractBearerToken(request.headers.get("Authorization"));
@@ -1017,6 +1040,33 @@ function createRequestHandler(routeEntry, handler, deps) {
1017
1040
  }
1018
1041
  }
1019
1042
  const siwxHeader = request.headers.get("SIGN-IN-WITH-X");
1043
+ if (!siwxHeader && protocol === "mpp" && routeEntry.authMode === "siwx" && deps.mppx) {
1044
+ let mppSiwxResult;
1045
+ try {
1046
+ mppSiwxResult = await verifyMppSiwx(request, deps.mppx);
1047
+ } catch (err) {
1048
+ const message = err instanceof Error ? err.message : String(err);
1049
+ firePluginHook(deps.plugin, "onAlert", pluginCtx, {
1050
+ level: "critical",
1051
+ message: `MPP SIWX verification failed: ${message}`,
1052
+ route: routeEntry.key
1053
+ });
1054
+ return fail(500, `MPP SIWX verification failed: ${message}`, meta, pluginCtx);
1055
+ }
1056
+ if (mppSiwxResult.valid) {
1057
+ pluginCtx.setVerifiedWallet(mppSiwxResult.wallet);
1058
+ firePluginHook(deps.plugin, "onAuthVerified", pluginCtx, {
1059
+ authMode: "siwx",
1060
+ wallet: mppSiwxResult.wallet,
1061
+ route: routeEntry.key
1062
+ });
1063
+ const authResponse = await handleAuth(mppSiwxResult.wallet, void 0);
1064
+ if (authResponse.status < 400) {
1065
+ return mppSiwxResult.withReceipt(authResponse);
1066
+ }
1067
+ return authResponse;
1068
+ }
1069
+ }
1020
1070
  if (!siwxHeader && routeEntry.authMode === "siwx") {
1021
1071
  const url = new URL(request.url);
1022
1072
  const nonce = crypto.randomUUID().replace(/-/g, "");
@@ -1072,6 +1122,16 @@ function createRequestHandler(routeEntry, handler, deps) {
1072
1122
  headers: { "Content-Type": "application/json", "Cache-Control": "no-store" }
1073
1123
  });
1074
1124
  if (encoded) response.headers.set("PAYMENT-REQUIRED", encoded);
1125
+ if (deps.mppx) {
1126
+ try {
1127
+ const mppChallenge = await deps.mppx.charge({ amount: "0" })(request);
1128
+ if (mppChallenge.status === 402) {
1129
+ const wwwAuth = mppChallenge.challenge.headers.get("WWW-Authenticate");
1130
+ if (wwwAuth) response.headers.set("WWW-Authenticate", wwwAuth);
1131
+ }
1132
+ } catch {
1133
+ }
1134
+ }
1075
1135
  firePluginResponse(deps, pluginCtx, meta, response);
1076
1136
  return response;
1077
1137
  }
@@ -1297,11 +1357,11 @@ function createRequestHandler(routeEntry, handler, deps) {
1297
1357
  });
1298
1358
  return await build402(request, routeEntry, deps, meta, pluginCtx, body.data);
1299
1359
  }
1300
- const credential = Credential.fromRequest(request);
1360
+ const credential = Credential2.fromRequest(request);
1301
1361
  const rawSource = credential?.source ?? "";
1302
1362
  const didParts = rawSource.split(":");
1303
1363
  const lastPart = didParts[didParts.length - 1];
1304
- const wallet = normalizeWalletAddress(isAddress(lastPart) ? getAddress(lastPart) : rawSource);
1364
+ const wallet = normalizeWalletAddress(isAddress2(lastPart) ? getAddress2(lastPart) : rawSource);
1305
1365
  pluginCtx.setVerifiedWallet(wallet);
1306
1366
  firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
1307
1367
  protocol: "mpp",
@@ -1380,7 +1440,7 @@ async function resolveDynamicPrice(bodyData, routeEntry, deps, pluginCtx, meta)
1380
1440
  if (routeEntry.maxPrice) {
1381
1441
  const calculated = parseFloat(price);
1382
1442
  const max = parseFloat(routeEntry.maxPrice);
1383
- if (calculated > max) {
1443
+ if (!Number.isFinite(calculated) || calculated > max) {
1384
1444
  firePluginHook(deps.plugin, "onAlert", pluginCtx, {
1385
1445
  level: "warn",
1386
1446
  message: `Price ${price} exceeds maxPrice ${routeEntry.maxPrice}, capping`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcash/router",
3
- "version": "1.1.9",
3
+ "version": "1.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": {