@agentcash/router 0.5.1 → 0.6.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 +32 -16
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +32 -16
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -43,25 +43,26 @@ async function createX402Server(config) {
|
|
|
43
43
|
const { facilitator: defaultFacilitator } = await import("@coinbase/x402");
|
|
44
44
|
const raw = config.facilitatorUrl ?? defaultFacilitator;
|
|
45
45
|
const facilitatorConfig = typeof raw === "string" ? { url: raw } : raw;
|
|
46
|
-
const
|
|
46
|
+
const httpClient = new HTTPFacilitatorClient(facilitatorConfig);
|
|
47
|
+
const network = config.network ?? "eip155:8453";
|
|
48
|
+
const client = cachedClient(httpClient, network);
|
|
47
49
|
const server = new x402ResourceServer(client);
|
|
48
50
|
registerExactEvmScheme(server);
|
|
49
51
|
server.registerExtension(bazaarResourceServerExtension);
|
|
50
52
|
server.registerExtension(siwxResourceServerExtension);
|
|
51
|
-
const initPromise =
|
|
53
|
+
const initPromise = server.initialize();
|
|
52
54
|
return { server, initPromise };
|
|
53
55
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
56
|
+
function cachedClient(inner, network) {
|
|
57
|
+
return {
|
|
58
|
+
verify: inner.verify.bind(inner),
|
|
59
|
+
settle: inner.settle.bind(inner),
|
|
60
|
+
getSupported: async () => ({
|
|
61
|
+
kinds: [{ x402Version: 2, scheme: "exact", network }],
|
|
62
|
+
extensions: [],
|
|
63
|
+
signers: {}
|
|
64
|
+
})
|
|
65
|
+
};
|
|
65
66
|
}
|
|
66
67
|
var init_server = __esm({
|
|
67
68
|
"src/server.ts"() {
|
|
@@ -503,6 +504,11 @@ function extractBearerToken(header) {
|
|
|
503
504
|
}
|
|
504
505
|
|
|
505
506
|
// src/orchestrate.ts
|
|
507
|
+
async function resolvePayTo(routeEntry, request, fallback) {
|
|
508
|
+
if (!routeEntry.payTo) return fallback;
|
|
509
|
+
if (typeof routeEntry.payTo === "string") return routeEntry.payTo;
|
|
510
|
+
return routeEntry.payTo(request);
|
|
511
|
+
}
|
|
506
512
|
function createRequestHandler(routeEntry, handler, deps) {
|
|
507
513
|
async function invoke(request, meta, pluginCtx, wallet, account, parsedBody) {
|
|
508
514
|
const ctx = {
|
|
@@ -765,12 +771,13 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
765
771
|
console.error(`[router] ${routeEntry.key}: ${reason}`);
|
|
766
772
|
return fail(500, reason, meta, pluginCtx);
|
|
767
773
|
}
|
|
774
|
+
const payTo = await resolvePayTo(routeEntry, request, deps.payeeAddress);
|
|
768
775
|
const verify = await verifyX402Payment(
|
|
769
776
|
deps.x402Server,
|
|
770
777
|
request,
|
|
771
778
|
routeEntry,
|
|
772
779
|
price,
|
|
773
|
-
|
|
780
|
+
payTo,
|
|
774
781
|
deps.network
|
|
775
782
|
);
|
|
776
783
|
if (!verify?.valid) return await build402(request, routeEntry, deps, meta, pluginCtx);
|
|
@@ -1008,22 +1015,27 @@ async function build402(request, routeEntry, deps, meta, pluginCtx, bodyData) {
|
|
|
1008
1015
|
}
|
|
1009
1016
|
if (routeEntry.protocols.includes("x402") && deps.x402Server) {
|
|
1010
1017
|
try {
|
|
1018
|
+
const payTo = await resolvePayTo(routeEntry, request, deps.payeeAddress);
|
|
1011
1019
|
const { encoded } = await buildX402Challenge(
|
|
1012
1020
|
deps.x402Server,
|
|
1013
1021
|
routeEntry,
|
|
1014
1022
|
request,
|
|
1015
1023
|
challengePrice,
|
|
1016
|
-
|
|
1024
|
+
payTo,
|
|
1017
1025
|
deps.network,
|
|
1018
1026
|
extensions
|
|
1019
1027
|
);
|
|
1020
1028
|
response.headers.set("PAYMENT-REQUIRED", encoded);
|
|
1021
1029
|
} catch (err) {
|
|
1030
|
+
const message = `x402 challenge build failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
1022
1031
|
firePluginHook(deps.plugin, "onAlert", pluginCtx, {
|
|
1023
1032
|
level: "critical",
|
|
1024
|
-
message
|
|
1033
|
+
message,
|
|
1025
1034
|
route: routeEntry.key
|
|
1026
1035
|
});
|
|
1036
|
+
const errorResponse = import_server2.NextResponse.json({ success: false, error: message }, { status: 500 });
|
|
1037
|
+
firePluginResponse(deps, pluginCtx, meta, errorResponse);
|
|
1038
|
+
return errorResponse;
|
|
1027
1039
|
}
|
|
1028
1040
|
}
|
|
1029
1041
|
if (routeEntry.protocols.includes("mpp") && deps.mppx) {
|
|
@@ -1109,6 +1121,8 @@ var RouteBuilder = class {
|
|
|
1109
1121
|
/** @internal */
|
|
1110
1122
|
_minPrice;
|
|
1111
1123
|
/** @internal */
|
|
1124
|
+
_payTo;
|
|
1125
|
+
/** @internal */
|
|
1112
1126
|
_bodySchema;
|
|
1113
1127
|
/** @internal */
|
|
1114
1128
|
_querySchema;
|
|
@@ -1151,6 +1165,7 @@ var RouteBuilder = class {
|
|
|
1151
1165
|
if (options?.protocols) next._protocols = options.protocols;
|
|
1152
1166
|
if (options?.maxPrice) next._maxPrice = options.maxPrice;
|
|
1153
1167
|
if (options?.minPrice) next._minPrice = options.minPrice;
|
|
1168
|
+
if (options?.payTo) next._payTo = options.payTo;
|
|
1154
1169
|
if (typeof pricing === "object" && "tiers" in pricing) {
|
|
1155
1170
|
for (const [tierKey, tierConfig] of Object.entries(pricing.tiers)) {
|
|
1156
1171
|
if (!tierKey) {
|
|
@@ -1288,6 +1303,7 @@ var RouteBuilder = class {
|
|
|
1288
1303
|
method: this._method,
|
|
1289
1304
|
maxPrice: this._maxPrice,
|
|
1290
1305
|
minPrice: this._minPrice,
|
|
1306
|
+
payTo: this._payTo,
|
|
1291
1307
|
apiKeyResolver: this._apiKeyResolver,
|
|
1292
1308
|
providerName: this._providerName,
|
|
1293
1309
|
providerConfig: this._providerConfig,
|
package/dist/index.d.cts
CHANGED
|
@@ -171,6 +171,8 @@ interface PaidOptions {
|
|
|
171
171
|
protocols?: ProtocolType[];
|
|
172
172
|
maxPrice?: string;
|
|
173
173
|
minPrice?: string;
|
|
174
|
+
/** Override the payment recipient. String for static, function for dynamic (receives the Request). */
|
|
175
|
+
payTo?: string | ((request: Request) => string | Promise<string>);
|
|
174
176
|
}
|
|
175
177
|
interface HandlerContext<TBody = undefined, TQuery = undefined> {
|
|
176
178
|
body: TBody;
|
|
@@ -220,6 +222,7 @@ interface RouteEntry {
|
|
|
220
222
|
method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
|
|
221
223
|
maxPrice?: string;
|
|
222
224
|
minPrice?: string;
|
|
225
|
+
payTo?: string | ((request: Request) => string | Promise<string>);
|
|
223
226
|
apiKeyResolver?: (key: string) => unknown | Promise<unknown>;
|
|
224
227
|
providerName?: string;
|
|
225
228
|
providerConfig?: ProviderConfig;
|
|
@@ -325,6 +328,7 @@ declare class RouteBuilder<TBody = undefined, TQuery = undefined, HasAuth extend
|
|
|
325
328
|
/** @internal */ _protocols: ProtocolType[];
|
|
326
329
|
/** @internal */ _maxPrice: string | undefined;
|
|
327
330
|
/** @internal */ _minPrice: string | undefined;
|
|
331
|
+
/** @internal */ _payTo: string | ((request: Request) => string | Promise<string>) | undefined;
|
|
328
332
|
/** @internal */ _bodySchema: ZodType | undefined;
|
|
329
333
|
/** @internal */ _querySchema: ZodType | undefined;
|
|
330
334
|
/** @internal */ _outputSchema: ZodType | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -171,6 +171,8 @@ interface PaidOptions {
|
|
|
171
171
|
protocols?: ProtocolType[];
|
|
172
172
|
maxPrice?: string;
|
|
173
173
|
minPrice?: string;
|
|
174
|
+
/** Override the payment recipient. String for static, function for dynamic (receives the Request). */
|
|
175
|
+
payTo?: string | ((request: Request) => string | Promise<string>);
|
|
174
176
|
}
|
|
175
177
|
interface HandlerContext<TBody = undefined, TQuery = undefined> {
|
|
176
178
|
body: TBody;
|
|
@@ -220,6 +222,7 @@ interface RouteEntry {
|
|
|
220
222
|
method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
|
|
221
223
|
maxPrice?: string;
|
|
222
224
|
minPrice?: string;
|
|
225
|
+
payTo?: string | ((request: Request) => string | Promise<string>);
|
|
223
226
|
apiKeyResolver?: (key: string) => unknown | Promise<unknown>;
|
|
224
227
|
providerName?: string;
|
|
225
228
|
providerConfig?: ProviderConfig;
|
|
@@ -325,6 +328,7 @@ declare class RouteBuilder<TBody = undefined, TQuery = undefined, HasAuth extend
|
|
|
325
328
|
/** @internal */ _protocols: ProtocolType[];
|
|
326
329
|
/** @internal */ _maxPrice: string | undefined;
|
|
327
330
|
/** @internal */ _minPrice: string | undefined;
|
|
331
|
+
/** @internal */ _payTo: string | ((request: Request) => string | Promise<string>) | undefined;
|
|
328
332
|
/** @internal */ _bodySchema: ZodType | undefined;
|
|
329
333
|
/** @internal */ _querySchema: ZodType | undefined;
|
|
330
334
|
/** @internal */ _outputSchema: ZodType | undefined;
|
package/dist/index.js
CHANGED
|
@@ -21,25 +21,26 @@ async function createX402Server(config) {
|
|
|
21
21
|
const { facilitator: defaultFacilitator } = await import("@coinbase/x402");
|
|
22
22
|
const raw = config.facilitatorUrl ?? defaultFacilitator;
|
|
23
23
|
const facilitatorConfig = typeof raw === "string" ? { url: raw } : raw;
|
|
24
|
-
const
|
|
24
|
+
const httpClient = new HTTPFacilitatorClient(facilitatorConfig);
|
|
25
|
+
const network = config.network ?? "eip155:8453";
|
|
26
|
+
const client = cachedClient(httpClient, network);
|
|
25
27
|
const server = new x402ResourceServer(client);
|
|
26
28
|
registerExactEvmScheme(server);
|
|
27
29
|
server.registerExtension(bazaarResourceServerExtension);
|
|
28
30
|
server.registerExtension(siwxResourceServerExtension);
|
|
29
|
-
const initPromise =
|
|
31
|
+
const initPromise = server.initialize();
|
|
30
32
|
return { server, initPromise };
|
|
31
33
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
34
|
+
function cachedClient(inner, network) {
|
|
35
|
+
return {
|
|
36
|
+
verify: inner.verify.bind(inner),
|
|
37
|
+
settle: inner.settle.bind(inner),
|
|
38
|
+
getSupported: async () => ({
|
|
39
|
+
kinds: [{ x402Version: 2, scheme: "exact", network }],
|
|
40
|
+
extensions: [],
|
|
41
|
+
signers: {}
|
|
42
|
+
})
|
|
43
|
+
};
|
|
43
44
|
}
|
|
44
45
|
var init_server = __esm({
|
|
45
46
|
"src/server.ts"() {
|
|
@@ -466,6 +467,11 @@ function extractBearerToken(header) {
|
|
|
466
467
|
}
|
|
467
468
|
|
|
468
469
|
// src/orchestrate.ts
|
|
470
|
+
async function resolvePayTo(routeEntry, request, fallback) {
|
|
471
|
+
if (!routeEntry.payTo) return fallback;
|
|
472
|
+
if (typeof routeEntry.payTo === "string") return routeEntry.payTo;
|
|
473
|
+
return routeEntry.payTo(request);
|
|
474
|
+
}
|
|
469
475
|
function createRequestHandler(routeEntry, handler, deps) {
|
|
470
476
|
async function invoke(request, meta, pluginCtx, wallet, account, parsedBody) {
|
|
471
477
|
const ctx = {
|
|
@@ -728,12 +734,13 @@ function createRequestHandler(routeEntry, handler, deps) {
|
|
|
728
734
|
console.error(`[router] ${routeEntry.key}: ${reason}`);
|
|
729
735
|
return fail(500, reason, meta, pluginCtx);
|
|
730
736
|
}
|
|
737
|
+
const payTo = await resolvePayTo(routeEntry, request, deps.payeeAddress);
|
|
731
738
|
const verify = await verifyX402Payment(
|
|
732
739
|
deps.x402Server,
|
|
733
740
|
request,
|
|
734
741
|
routeEntry,
|
|
735
742
|
price,
|
|
736
|
-
|
|
743
|
+
payTo,
|
|
737
744
|
deps.network
|
|
738
745
|
);
|
|
739
746
|
if (!verify?.valid) return await build402(request, routeEntry, deps, meta, pluginCtx);
|
|
@@ -971,22 +978,27 @@ async function build402(request, routeEntry, deps, meta, pluginCtx, bodyData) {
|
|
|
971
978
|
}
|
|
972
979
|
if (routeEntry.protocols.includes("x402") && deps.x402Server) {
|
|
973
980
|
try {
|
|
981
|
+
const payTo = await resolvePayTo(routeEntry, request, deps.payeeAddress);
|
|
974
982
|
const { encoded } = await buildX402Challenge(
|
|
975
983
|
deps.x402Server,
|
|
976
984
|
routeEntry,
|
|
977
985
|
request,
|
|
978
986
|
challengePrice,
|
|
979
|
-
|
|
987
|
+
payTo,
|
|
980
988
|
deps.network,
|
|
981
989
|
extensions
|
|
982
990
|
);
|
|
983
991
|
response.headers.set("PAYMENT-REQUIRED", encoded);
|
|
984
992
|
} catch (err) {
|
|
993
|
+
const message = `x402 challenge build failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
985
994
|
firePluginHook(deps.plugin, "onAlert", pluginCtx, {
|
|
986
995
|
level: "critical",
|
|
987
|
-
message
|
|
996
|
+
message,
|
|
988
997
|
route: routeEntry.key
|
|
989
998
|
});
|
|
999
|
+
const errorResponse = NextResponse2.json({ success: false, error: message }, { status: 500 });
|
|
1000
|
+
firePluginResponse(deps, pluginCtx, meta, errorResponse);
|
|
1001
|
+
return errorResponse;
|
|
990
1002
|
}
|
|
991
1003
|
}
|
|
992
1004
|
if (routeEntry.protocols.includes("mpp") && deps.mppx) {
|
|
@@ -1072,6 +1084,8 @@ var RouteBuilder = class {
|
|
|
1072
1084
|
/** @internal */
|
|
1073
1085
|
_minPrice;
|
|
1074
1086
|
/** @internal */
|
|
1087
|
+
_payTo;
|
|
1088
|
+
/** @internal */
|
|
1075
1089
|
_bodySchema;
|
|
1076
1090
|
/** @internal */
|
|
1077
1091
|
_querySchema;
|
|
@@ -1114,6 +1128,7 @@ var RouteBuilder = class {
|
|
|
1114
1128
|
if (options?.protocols) next._protocols = options.protocols;
|
|
1115
1129
|
if (options?.maxPrice) next._maxPrice = options.maxPrice;
|
|
1116
1130
|
if (options?.minPrice) next._minPrice = options.minPrice;
|
|
1131
|
+
if (options?.payTo) next._payTo = options.payTo;
|
|
1117
1132
|
if (typeof pricing === "object" && "tiers" in pricing) {
|
|
1118
1133
|
for (const [tierKey, tierConfig] of Object.entries(pricing.tiers)) {
|
|
1119
1134
|
if (!tierKey) {
|
|
@@ -1251,6 +1266,7 @@ var RouteBuilder = class {
|
|
|
1251
1266
|
method: this._method,
|
|
1252
1267
|
maxPrice: this._maxPrice,
|
|
1253
1268
|
minPrice: this._minPrice,
|
|
1269
|
+
payTo: this._payTo,
|
|
1254
1270
|
apiKeyResolver: this._apiKeyResolver,
|
|
1255
1271
|
providerName: this._providerName,
|
|
1256
1272
|
providerConfig: this._providerConfig,
|