@agentcash/router 1.1.0 → 1.1.2
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 +46 -15
- package/dist/index.js +46 -15
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -366,6 +366,11 @@ var RouteRegistry = class {
|
|
|
366
366
|
// src/orchestrate.ts
|
|
367
367
|
var import_server2 = require("next/server");
|
|
368
368
|
|
|
369
|
+
// src/auth/normalize-wallet.ts
|
|
370
|
+
function normalizeWalletAddress(address) {
|
|
371
|
+
return address.startsWith("0x") ? address.toLowerCase() : address;
|
|
372
|
+
}
|
|
373
|
+
|
|
369
374
|
// src/plugin.ts
|
|
370
375
|
function createDefaultContext(meta) {
|
|
371
376
|
const ctx = {
|
|
@@ -877,6 +882,23 @@ function getRequirementNetwork(requirements, fallback) {
|
|
|
877
882
|
const network = requirements?.network;
|
|
878
883
|
return typeof network === "string" ? network : fallback;
|
|
879
884
|
}
|
|
885
|
+
function siwxSignatureType(network) {
|
|
886
|
+
return network.startsWith("solana:") ? "ed25519" : "eip191";
|
|
887
|
+
}
|
|
888
|
+
function getSupportedChains(x402Accepts, fallbackNetwork) {
|
|
889
|
+
const seen = /* @__PURE__ */ new Set();
|
|
890
|
+
const chains = [];
|
|
891
|
+
for (const accept of x402Accepts) {
|
|
892
|
+
if (accept.network && !seen.has(accept.network)) {
|
|
893
|
+
seen.add(accept.network);
|
|
894
|
+
chains.push({ chainId: accept.network, type: siwxSignatureType(accept.network) });
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
if (chains.length === 0) {
|
|
898
|
+
chains.push({ chainId: fallbackNetwork, type: siwxSignatureType(fallbackNetwork) });
|
|
899
|
+
}
|
|
900
|
+
return chains;
|
|
901
|
+
}
|
|
880
902
|
function createRequestHandler(routeEntry, handler, deps) {
|
|
881
903
|
async function invoke(request, meta, pluginCtx, wallet, account, parsedBody) {
|
|
882
904
|
const ctx = {
|
|
@@ -1004,12 +1026,14 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1004
1026
|
if (!siwxHeader && routeEntry.authMode === "siwx") {
|
|
1005
1027
|
const url = new URL(request.url);
|
|
1006
1028
|
const nonce = crypto.randomUUID().replace(/-/g, "");
|
|
1029
|
+
const supportedChains = getSupportedChains(deps.x402Accepts, deps.network);
|
|
1030
|
+
const primaryChain = supportedChains[0];
|
|
1007
1031
|
const siwxInfo = {
|
|
1008
1032
|
domain: url.hostname,
|
|
1009
1033
|
uri: request.url,
|
|
1010
1034
|
version: "1",
|
|
1011
|
-
chainId:
|
|
1012
|
-
type:
|
|
1035
|
+
chainId: primaryChain.chainId,
|
|
1036
|
+
type: primaryChain.type,
|
|
1013
1037
|
nonce,
|
|
1014
1038
|
issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1015
1039
|
expirationTime: new Date(Date.now() + SIWX_CHALLENGE_EXPIRY_MS).toISOString(),
|
|
@@ -1033,7 +1057,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1033
1057
|
"sign-in-with-x": {
|
|
1034
1058
|
info: siwxInfo,
|
|
1035
1059
|
// supportedChains at top level required by MCP tools for chain detection
|
|
1036
|
-
supportedChains
|
|
1060
|
+
supportedChains,
|
|
1037
1061
|
...siwxSchema ? { schema: siwxSchema } : {}
|
|
1038
1062
|
}
|
|
1039
1063
|
}
|
|
@@ -1069,7 +1093,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1069
1093
|
return response;
|
|
1070
1094
|
}
|
|
1071
1095
|
} else {
|
|
1072
|
-
const wallet = siwx.wallet
|
|
1096
|
+
const wallet = normalizeWalletAddress(siwx.wallet);
|
|
1073
1097
|
pluginCtx.setVerifiedWallet(wallet);
|
|
1074
1098
|
if (routeEntry.authMode === "siwx") {
|
|
1075
1099
|
firePluginHook(deps.plugin, "onAuthVerified", pluginCtx, {
|
|
@@ -1171,7 +1195,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1171
1195
|
if (!verify?.valid) return await build402(request, routeEntry, deps, meta, pluginCtx);
|
|
1172
1196
|
const { payload: verifyPayload, requirements: verifyRequirements } = verify;
|
|
1173
1197
|
const matchedNetwork = getRequirementNetwork(verifyRequirements, deps.network);
|
|
1174
|
-
const wallet = verify.payer
|
|
1198
|
+
const wallet = normalizeWalletAddress(verify.payer);
|
|
1175
1199
|
pluginCtx.setVerifiedWallet(wallet);
|
|
1176
1200
|
firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
|
|
1177
1201
|
protocol: "x402",
|
|
@@ -1194,6 +1218,12 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1194
1218
|
verifyPayload,
|
|
1195
1219
|
verifyRequirements
|
|
1196
1220
|
);
|
|
1221
|
+
if (!settle.result?.success) {
|
|
1222
|
+
const reason = settle.result?.errorReason || "x402 settlement returned success=false";
|
|
1223
|
+
const error = new Error(reason);
|
|
1224
|
+
error.errorReason = reason;
|
|
1225
|
+
throw error;
|
|
1226
|
+
}
|
|
1197
1227
|
if (routeEntry.siwxEnabled) {
|
|
1198
1228
|
try {
|
|
1199
1229
|
await deps.entitlementStore.grant(routeEntry.key, wallet);
|
|
@@ -1218,6 +1248,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1218
1248
|
message: err instanceof Error ? err.message : String(err),
|
|
1219
1249
|
route: routeEntry.key,
|
|
1220
1250
|
network: matchedNetwork,
|
|
1251
|
+
errorReason: errObj.errorReason,
|
|
1221
1252
|
facilitatorStatus: errObj.response?.status,
|
|
1222
1253
|
facilitatorBody: errObj.response?.data ?? errObj.response?.body
|
|
1223
1254
|
});
|
|
@@ -1266,7 +1297,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1266
1297
|
const rawSource = credential?.source ?? "";
|
|
1267
1298
|
const didParts = rawSource.split(":");
|
|
1268
1299
|
const lastPart = didParts[didParts.length - 1];
|
|
1269
|
-
const wallet = ((0, import_viem.isAddress)(lastPart) ? (0, import_viem.getAddress)(lastPart) : rawSource)
|
|
1300
|
+
const wallet = normalizeWalletAddress((0, import_viem.isAddress)(lastPart) ? (0, import_viem.getAddress)(lastPart) : rawSource);
|
|
1270
1301
|
pluginCtx.setVerifiedWallet(wallet);
|
|
1271
1302
|
firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
|
|
1272
1303
|
protocol: "mpp",
|
|
@@ -1762,16 +1793,16 @@ var MemoryEntitlementStore = class {
|
|
|
1762
1793
|
async has(route, wallet) {
|
|
1763
1794
|
const wallets = this.routeToWallets.get(route);
|
|
1764
1795
|
if (!wallets) return false;
|
|
1765
|
-
return wallets.has(wallet
|
|
1796
|
+
return wallets.has(normalizeWalletAddress(wallet));
|
|
1766
1797
|
}
|
|
1767
1798
|
async grant(route, wallet) {
|
|
1768
|
-
const
|
|
1799
|
+
const normalized = normalizeWalletAddress(wallet);
|
|
1769
1800
|
let wallets = this.routeToWallets.get(route);
|
|
1770
1801
|
if (!wallets) {
|
|
1771
1802
|
wallets = /* @__PURE__ */ new Set();
|
|
1772
1803
|
this.routeToWallets.set(route, wallets);
|
|
1773
1804
|
}
|
|
1774
|
-
wallets.add(
|
|
1805
|
+
wallets.add(normalized);
|
|
1775
1806
|
}
|
|
1776
1807
|
};
|
|
1777
1808
|
function detectRedisClientType2(client) {
|
|
@@ -1794,26 +1825,26 @@ function createRedisEntitlementStore(client, options) {
|
|
|
1794
1825
|
return {
|
|
1795
1826
|
async has(route, wallet) {
|
|
1796
1827
|
const key = `${prefix}${route}`;
|
|
1797
|
-
const
|
|
1828
|
+
const normalized = normalizeWalletAddress(wallet);
|
|
1798
1829
|
if (clientType === "upstash") {
|
|
1799
1830
|
const redis2 = client;
|
|
1800
|
-
const result2 = await redis2.sismember(key,
|
|
1831
|
+
const result2 = await redis2.sismember(key, normalized);
|
|
1801
1832
|
return result2 === 1 || result2 === true;
|
|
1802
1833
|
}
|
|
1803
1834
|
const redis = client;
|
|
1804
|
-
const result = await redis.sismember(key,
|
|
1835
|
+
const result = await redis.sismember(key, normalized);
|
|
1805
1836
|
return result === 1;
|
|
1806
1837
|
},
|
|
1807
1838
|
async grant(route, wallet) {
|
|
1808
1839
|
const key = `${prefix}${route}`;
|
|
1809
|
-
const
|
|
1840
|
+
const normalized = normalizeWalletAddress(wallet);
|
|
1810
1841
|
if (clientType === "upstash") {
|
|
1811
1842
|
const redis2 = client;
|
|
1812
|
-
await redis2.sadd(key,
|
|
1843
|
+
await redis2.sadd(key, normalized);
|
|
1813
1844
|
return;
|
|
1814
1845
|
}
|
|
1815
1846
|
const redis = client;
|
|
1816
|
-
await redis.sadd(key,
|
|
1847
|
+
await redis.sadd(key, normalized);
|
|
1817
1848
|
}
|
|
1818
1849
|
};
|
|
1819
1850
|
}
|
package/dist/index.js
CHANGED
|
@@ -327,6 +327,11 @@ var RouteRegistry = class {
|
|
|
327
327
|
// src/orchestrate.ts
|
|
328
328
|
import { NextResponse as NextResponse2 } from "next/server";
|
|
329
329
|
|
|
330
|
+
// src/auth/normalize-wallet.ts
|
|
331
|
+
function normalizeWalletAddress(address) {
|
|
332
|
+
return address.startsWith("0x") ? address.toLowerCase() : address;
|
|
333
|
+
}
|
|
334
|
+
|
|
330
335
|
// src/plugin.ts
|
|
331
336
|
function createDefaultContext(meta) {
|
|
332
337
|
const ctx = {
|
|
@@ -838,6 +843,23 @@ function getRequirementNetwork(requirements, fallback) {
|
|
|
838
843
|
const network = requirements?.network;
|
|
839
844
|
return typeof network === "string" ? network : fallback;
|
|
840
845
|
}
|
|
846
|
+
function siwxSignatureType(network) {
|
|
847
|
+
return network.startsWith("solana:") ? "ed25519" : "eip191";
|
|
848
|
+
}
|
|
849
|
+
function getSupportedChains(x402Accepts, fallbackNetwork) {
|
|
850
|
+
const seen = /* @__PURE__ */ new Set();
|
|
851
|
+
const chains = [];
|
|
852
|
+
for (const accept of x402Accepts) {
|
|
853
|
+
if (accept.network && !seen.has(accept.network)) {
|
|
854
|
+
seen.add(accept.network);
|
|
855
|
+
chains.push({ chainId: accept.network, type: siwxSignatureType(accept.network) });
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
if (chains.length === 0) {
|
|
859
|
+
chains.push({ chainId: fallbackNetwork, type: siwxSignatureType(fallbackNetwork) });
|
|
860
|
+
}
|
|
861
|
+
return chains;
|
|
862
|
+
}
|
|
841
863
|
function createRequestHandler(routeEntry, handler, deps) {
|
|
842
864
|
async function invoke(request, meta, pluginCtx, wallet, account, parsedBody) {
|
|
843
865
|
const ctx = {
|
|
@@ -965,12 +987,14 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
965
987
|
if (!siwxHeader && routeEntry.authMode === "siwx") {
|
|
966
988
|
const url = new URL(request.url);
|
|
967
989
|
const nonce = crypto.randomUUID().replace(/-/g, "");
|
|
990
|
+
const supportedChains = getSupportedChains(deps.x402Accepts, deps.network);
|
|
991
|
+
const primaryChain = supportedChains[0];
|
|
968
992
|
const siwxInfo = {
|
|
969
993
|
domain: url.hostname,
|
|
970
994
|
uri: request.url,
|
|
971
995
|
version: "1",
|
|
972
|
-
chainId:
|
|
973
|
-
type:
|
|
996
|
+
chainId: primaryChain.chainId,
|
|
997
|
+
type: primaryChain.type,
|
|
974
998
|
nonce,
|
|
975
999
|
issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
976
1000
|
expirationTime: new Date(Date.now() + SIWX_CHALLENGE_EXPIRY_MS).toISOString(),
|
|
@@ -994,7 +1018,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
994
1018
|
"sign-in-with-x": {
|
|
995
1019
|
info: siwxInfo,
|
|
996
1020
|
// supportedChains at top level required by MCP tools for chain detection
|
|
997
|
-
supportedChains
|
|
1021
|
+
supportedChains,
|
|
998
1022
|
...siwxSchema ? { schema: siwxSchema } : {}
|
|
999
1023
|
}
|
|
1000
1024
|
}
|
|
@@ -1030,7 +1054,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1030
1054
|
return response;
|
|
1031
1055
|
}
|
|
1032
1056
|
} else {
|
|
1033
|
-
const wallet = siwx.wallet
|
|
1057
|
+
const wallet = normalizeWalletAddress(siwx.wallet);
|
|
1034
1058
|
pluginCtx.setVerifiedWallet(wallet);
|
|
1035
1059
|
if (routeEntry.authMode === "siwx") {
|
|
1036
1060
|
firePluginHook(deps.plugin, "onAuthVerified", pluginCtx, {
|
|
@@ -1132,7 +1156,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1132
1156
|
if (!verify?.valid) return await build402(request, routeEntry, deps, meta, pluginCtx);
|
|
1133
1157
|
const { payload: verifyPayload, requirements: verifyRequirements } = verify;
|
|
1134
1158
|
const matchedNetwork = getRequirementNetwork(verifyRequirements, deps.network);
|
|
1135
|
-
const wallet = verify.payer
|
|
1159
|
+
const wallet = normalizeWalletAddress(verify.payer);
|
|
1136
1160
|
pluginCtx.setVerifiedWallet(wallet);
|
|
1137
1161
|
firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
|
|
1138
1162
|
protocol: "x402",
|
|
@@ -1155,6 +1179,12 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1155
1179
|
verifyPayload,
|
|
1156
1180
|
verifyRequirements
|
|
1157
1181
|
);
|
|
1182
|
+
if (!settle.result?.success) {
|
|
1183
|
+
const reason = settle.result?.errorReason || "x402 settlement returned success=false";
|
|
1184
|
+
const error = new Error(reason);
|
|
1185
|
+
error.errorReason = reason;
|
|
1186
|
+
throw error;
|
|
1187
|
+
}
|
|
1158
1188
|
if (routeEntry.siwxEnabled) {
|
|
1159
1189
|
try {
|
|
1160
1190
|
await deps.entitlementStore.grant(routeEntry.key, wallet);
|
|
@@ -1179,6 +1209,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1179
1209
|
message: err instanceof Error ? err.message : String(err),
|
|
1180
1210
|
route: routeEntry.key,
|
|
1181
1211
|
network: matchedNetwork,
|
|
1212
|
+
errorReason: errObj.errorReason,
|
|
1182
1213
|
facilitatorStatus: errObj.response?.status,
|
|
1183
1214
|
facilitatorBody: errObj.response?.data ?? errObj.response?.body
|
|
1184
1215
|
});
|
|
@@ -1227,7 +1258,7 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
1227
1258
|
const rawSource = credential?.source ?? "";
|
|
1228
1259
|
const didParts = rawSource.split(":");
|
|
1229
1260
|
const lastPart = didParts[didParts.length - 1];
|
|
1230
|
-
const wallet = (isAddress(lastPart) ? getAddress(lastPart) : rawSource)
|
|
1261
|
+
const wallet = normalizeWalletAddress(isAddress(lastPart) ? getAddress(lastPart) : rawSource);
|
|
1231
1262
|
pluginCtx.setVerifiedWallet(wallet);
|
|
1232
1263
|
firePluginHook(deps.plugin, "onPaymentVerified", pluginCtx, {
|
|
1233
1264
|
protocol: "mpp",
|
|
@@ -1723,16 +1754,16 @@ var MemoryEntitlementStore = class {
|
|
|
1723
1754
|
async has(route, wallet) {
|
|
1724
1755
|
const wallets = this.routeToWallets.get(route);
|
|
1725
1756
|
if (!wallets) return false;
|
|
1726
|
-
return wallets.has(wallet
|
|
1757
|
+
return wallets.has(normalizeWalletAddress(wallet));
|
|
1727
1758
|
}
|
|
1728
1759
|
async grant(route, wallet) {
|
|
1729
|
-
const
|
|
1760
|
+
const normalized = normalizeWalletAddress(wallet);
|
|
1730
1761
|
let wallets = this.routeToWallets.get(route);
|
|
1731
1762
|
if (!wallets) {
|
|
1732
1763
|
wallets = /* @__PURE__ */ new Set();
|
|
1733
1764
|
this.routeToWallets.set(route, wallets);
|
|
1734
1765
|
}
|
|
1735
|
-
wallets.add(
|
|
1766
|
+
wallets.add(normalized);
|
|
1736
1767
|
}
|
|
1737
1768
|
};
|
|
1738
1769
|
function detectRedisClientType2(client) {
|
|
@@ -1755,26 +1786,26 @@ function createRedisEntitlementStore(client, options) {
|
|
|
1755
1786
|
return {
|
|
1756
1787
|
async has(route, wallet) {
|
|
1757
1788
|
const key = `${prefix}${route}`;
|
|
1758
|
-
const
|
|
1789
|
+
const normalized = normalizeWalletAddress(wallet);
|
|
1759
1790
|
if (clientType === "upstash") {
|
|
1760
1791
|
const redis2 = client;
|
|
1761
|
-
const result2 = await redis2.sismember(key,
|
|
1792
|
+
const result2 = await redis2.sismember(key, normalized);
|
|
1762
1793
|
return result2 === 1 || result2 === true;
|
|
1763
1794
|
}
|
|
1764
1795
|
const redis = client;
|
|
1765
|
-
const result = await redis.sismember(key,
|
|
1796
|
+
const result = await redis.sismember(key, normalized);
|
|
1766
1797
|
return result === 1;
|
|
1767
1798
|
},
|
|
1768
1799
|
async grant(route, wallet) {
|
|
1769
1800
|
const key = `${prefix}${route}`;
|
|
1770
|
-
const
|
|
1801
|
+
const normalized = normalizeWalletAddress(wallet);
|
|
1771
1802
|
if (clientType === "upstash") {
|
|
1772
1803
|
const redis2 = client;
|
|
1773
|
-
await redis2.sadd(key,
|
|
1804
|
+
await redis2.sadd(key, normalized);
|
|
1774
1805
|
return;
|
|
1775
1806
|
}
|
|
1776
1807
|
const redis = client;
|
|
1777
|
-
await redis.sadd(key,
|
|
1808
|
+
await redis.sadd(key, normalized);
|
|
1778
1809
|
}
|
|
1779
1810
|
};
|
|
1780
1811
|
}
|