@agentcash/router 0.1.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.
@@ -0,0 +1,273 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { ZodType } from 'zod';
3
+
4
+ interface NonceStore {
5
+ check(nonce: string): Promise<boolean>;
6
+ }
7
+ declare class MemoryNonceStore implements NonceStore {
8
+ private seen;
9
+ check(nonce: string): Promise<boolean>;
10
+ private evict;
11
+ }
12
+
13
+ interface RequestMeta {
14
+ requestId: string;
15
+ method: string;
16
+ route: string;
17
+ origin: string;
18
+ referer: string | null;
19
+ walletAddress: string | null;
20
+ clientId: string | null;
21
+ sessionId: string | null;
22
+ contentType: string | null;
23
+ headers: Record<string, string>;
24
+ startTime: number;
25
+ }
26
+ interface PluginContext {
27
+ readonly requestId: string;
28
+ readonly route: string;
29
+ readonly walletAddress: string | null;
30
+ readonly clientId: string | null;
31
+ readonly sessionId: string | null;
32
+ verifiedWallet: string | null;
33
+ setVerifiedWallet(address: string): void;
34
+ }
35
+ interface PaymentEvent {
36
+ protocol: 'x402' | 'mpp';
37
+ payer: string;
38
+ amount: string;
39
+ network: string;
40
+ }
41
+ interface SettlementEvent {
42
+ protocol: 'x402' | 'mpp';
43
+ payer: string;
44
+ transaction: string;
45
+ network: string;
46
+ }
47
+ interface ResponseMeta {
48
+ statusCode: number;
49
+ statusText: string;
50
+ duration: number;
51
+ contentType: string | null;
52
+ headers: Record<string, string>;
53
+ }
54
+ interface ErrorEvent {
55
+ status: number;
56
+ message: string;
57
+ settled: boolean;
58
+ }
59
+ interface RouterPlugin {
60
+ init?(config: {
61
+ origin?: string;
62
+ }): void | Promise<void>;
63
+ onRequest?(meta: RequestMeta): PluginContext;
64
+ onPaymentVerified?(ctx: PluginContext, payment: PaymentEvent): void;
65
+ onPaymentSettled?(ctx: PluginContext, settlement: SettlementEvent): void;
66
+ onResponse?(ctx: PluginContext, response: ResponseMeta): void;
67
+ onError?(ctx: PluginContext, error: ErrorEvent): void;
68
+ onAlert?(ctx: PluginContext, alert: AlertEvent): void;
69
+ onProviderQuota?(ctx: PluginContext, event: ProviderQuotaEvent): void;
70
+ }
71
+ declare function consolePlugin(): RouterPlugin;
72
+
73
+ declare class HttpError extends Error {
74
+ readonly status: number;
75
+ constructor(message: string, status: number);
76
+ }
77
+ type AlertLevel = 'info' | 'warn' | 'error' | 'critical';
78
+ interface AlertEvent {
79
+ level: AlertLevel;
80
+ message: string;
81
+ route: string;
82
+ meta?: Record<string, unknown>;
83
+ }
84
+ type AlertFn = (level: AlertLevel, message: string, meta?: Record<string, unknown>) => void;
85
+ type ProtocolType = 'x402' | 'mpp';
86
+ type AuthMode = 'paid' | 'siwx' | 'apiKey' | 'unprotected';
87
+ interface TierConfig {
88
+ price: string;
89
+ label?: string;
90
+ }
91
+ type PricingConfig<TBody = unknown> = string | ((body: TBody) => string | Promise<string>) | {
92
+ field: string;
93
+ tiers: Record<string, TierConfig>;
94
+ default?: string;
95
+ };
96
+ interface PaidOptions {
97
+ protocols?: ProtocolType[];
98
+ maxPrice?: string;
99
+ }
100
+ interface HandlerContext<TBody = undefined, TQuery = undefined> {
101
+ body: TBody;
102
+ query: TQuery;
103
+ request: NextRequest;
104
+ requestId: string;
105
+ route: string;
106
+ wallet: string | null;
107
+ account: unknown;
108
+ alert: AlertFn;
109
+ setVerifiedWallet: (addr: string) => void;
110
+ }
111
+ type OveragePolicy = 'same-rate' | 'increased-rate' | 'hard-stop';
112
+ type QuotaLevel = 'healthy' | 'warn' | 'critical';
113
+ interface QuotaInfo {
114
+ remaining: number | null;
115
+ limit: number | null;
116
+ spend?: number;
117
+ }
118
+ interface ProviderConfig {
119
+ extractQuota?: (result: unknown, headers: Headers) => QuotaInfo | null;
120
+ monitor?: () => Promise<QuotaInfo | null>;
121
+ overage?: OveragePolicy;
122
+ warn?: number;
123
+ critical?: number;
124
+ }
125
+ interface ProviderQuotaEvent {
126
+ provider: string;
127
+ route: string;
128
+ remaining: number | null;
129
+ limit: number | null;
130
+ spend?: number;
131
+ level: QuotaLevel;
132
+ overage: OveragePolicy;
133
+ message: string;
134
+ }
135
+ interface RouteEntry {
136
+ key: string;
137
+ authMode: AuthMode;
138
+ pricing?: PricingConfig;
139
+ protocols: ProtocolType[];
140
+ bodySchema?: ZodType;
141
+ querySchema?: ZodType;
142
+ outputSchema?: ZodType;
143
+ description?: string;
144
+ path?: string;
145
+ method: 'GET' | 'POST';
146
+ maxPrice?: string;
147
+ apiKeyResolver?: (key: string) => unknown | Promise<unknown>;
148
+ providerName?: string;
149
+ providerConfig?: ProviderConfig;
150
+ }
151
+ interface RouterConfig {
152
+ payeeAddress: string;
153
+ network?: string;
154
+ facilitatorUrl?: string;
155
+ plugin?: RouterPlugin;
156
+ siwx?: {
157
+ nonceStore?: NonceStore;
158
+ };
159
+ prices?: Record<string, string>;
160
+ mpp?: {
161
+ secretKey: string;
162
+ currency: string;
163
+ recipient?: string;
164
+ };
165
+ }
166
+
167
+ declare class RouteRegistry {
168
+ private routes;
169
+ register(entry: RouteEntry): void;
170
+ get(key: string): RouteEntry | undefined;
171
+ entries(): IterableIterator<[string, RouteEntry]>;
172
+ has(key: string): boolean;
173
+ get size(): number;
174
+ validate(expectedKeys?: string[]): void;
175
+ }
176
+
177
+ interface WellKnownOptions {
178
+ instructions?: string | (() => string | Promise<string>);
179
+ ownershipProofs?: string[];
180
+ }
181
+
182
+ interface OpenAPIOptions {
183
+ title: string;
184
+ version: string;
185
+ description?: string;
186
+ baseUrl?: string;
187
+ contact?: {
188
+ name?: string;
189
+ url?: string;
190
+ };
191
+ }
192
+
193
+ interface OrchestrateDeps {
194
+ x402Server: Record<string, Function> | null;
195
+ initPromise: Promise<void>;
196
+ x402InitError?: string;
197
+ plugin?: RouterPlugin;
198
+ nonceStore: NonceStore;
199
+ payeeAddress: string;
200
+ network: string;
201
+ mppConfig?: {
202
+ secretKey: string;
203
+ currency: string;
204
+ recipient?: string;
205
+ };
206
+ }
207
+
208
+ type True = true;
209
+ type False = false;
210
+ declare class RouteBuilder<TBody = undefined, TQuery = undefined, HasAuth extends boolean = false, NeedsBody extends boolean = false, HasBody extends boolean = false> {
211
+ /** @internal */ readonly _key: string;
212
+ /** @internal */ readonly _registry: RouteRegistry;
213
+ /** @internal */ readonly _deps: OrchestrateDeps;
214
+ /** @internal */ _authMode: AuthMode | null;
215
+ /** @internal */ _pricing: PricingConfig | undefined;
216
+ /** @internal */ _protocols: ProtocolType[];
217
+ /** @internal */ _maxPrice: string | undefined;
218
+ /** @internal */ _bodySchema: ZodType | undefined;
219
+ /** @internal */ _querySchema: ZodType | undefined;
220
+ /** @internal */ _outputSchema: ZodType | undefined;
221
+ /** @internal */ _description: string | undefined;
222
+ /** @internal */ _path: string | undefined;
223
+ /** @internal */ _method: 'GET' | 'POST';
224
+ /** @internal */ _apiKeyResolver: ((key: string) => unknown | Promise<unknown>) | undefined;
225
+ /** @internal */ _providerName: string | undefined;
226
+ /** @internal */ _providerConfig: ProviderConfig | undefined;
227
+ constructor(key: string, registry: RouteRegistry, deps: OrchestrateDeps);
228
+ private fork;
229
+ paid(pricing: string, options?: PaidOptions): RouteBuilder<TBody, TQuery, True, False, HasBody>;
230
+ paid<TBodyIn>(pricing: (body: TBodyIn) => string | Promise<string>, options?: PaidOptions & {
231
+ maxPrice: string;
232
+ }): RouteBuilder<TBody, TQuery, True, True, HasBody>;
233
+ paid(pricing: {
234
+ field: string;
235
+ tiers: Record<string, {
236
+ price: string;
237
+ label?: string;
238
+ }>;
239
+ default?: string;
240
+ }, options?: PaidOptions): RouteBuilder<TBody, TQuery, True, True, HasBody>;
241
+ siwx(): HasAuth extends true ? never : RouteBuilder<TBody, TQuery, True, False, HasBody>;
242
+ apiKey(resolver: (key: string) => unknown | Promise<unknown>): RouteBuilder<TBody, TQuery, True, NeedsBody, HasBody>;
243
+ unprotected(): RouteBuilder<TBody, TQuery, True, False, HasBody>;
244
+ provider(name: string, config?: ProviderConfig): this;
245
+ body<T>(schema: ZodType<T>): RouteBuilder<T, TQuery, HasAuth, NeedsBody, True>;
246
+ query<T>(schema: ZodType<T>): RouteBuilder<TBody, T, HasAuth, NeedsBody, HasBody>;
247
+ output(schema: ZodType): this;
248
+ description(text: string): this;
249
+ path(p: string): this;
250
+ handler(this: RouteBuilder<TBody, TQuery, True, true, false>, fn: never): never;
251
+ handler(this: RouteBuilder<TBody, TQuery, false, boolean, boolean>, fn: never): never;
252
+ handler(this: RouteBuilder<TBody, TQuery, True, False, HasBody>, fn: (ctx: HandlerContext<TBody, TQuery>) => Promise<unknown>): (request: NextRequest) => Promise<Response>;
253
+ handler(this: RouteBuilder<TBody, TQuery, True, True, True>, fn: (ctx: HandlerContext<TBody, TQuery>) => Promise<unknown>): (request: NextRequest) => Promise<Response>;
254
+ }
255
+
256
+ interface MonitorEntry {
257
+ provider: string;
258
+ route: string;
259
+ monitor: () => Promise<QuotaInfo | null>;
260
+ overage: OveragePolicy;
261
+ warn?: number;
262
+ critical?: number;
263
+ }
264
+ interface ServiceRouter {
265
+ route(key: string): RouteBuilder;
266
+ wellKnown(options?: WellKnownOptions): (request: NextRequest) => Promise<NextResponse>;
267
+ openapi(options: OpenAPIOptions): (request: NextRequest) => Promise<NextResponse>;
268
+ monitors(): MonitorEntry[];
269
+ registry: RouteRegistry;
270
+ }
271
+ declare function createRouter(config: RouterConfig): ServiceRouter;
272
+
273
+ export { type AlertEvent, type AlertFn, type AlertLevel, type AuthMode, type ErrorEvent, type HandlerContext, HttpError, MemoryNonceStore, type MonitorEntry, type NonceStore, type OveragePolicy, type PaidOptions, type PaymentEvent, type PluginContext, type PricingConfig, type ProtocolType, type ProviderConfig, type ProviderQuotaEvent, type QuotaInfo, type QuotaLevel, type RequestMeta, type ResponseMeta, RouteBuilder, type RouteEntry, RouteRegistry, type RouterConfig, type RouterPlugin, type ServiceRouter, type SettlementEvent, type TierConfig, consolePlugin, createRouter };
@@ -0,0 +1,273 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { ZodType } from 'zod';
3
+
4
+ interface NonceStore {
5
+ check(nonce: string): Promise<boolean>;
6
+ }
7
+ declare class MemoryNonceStore implements NonceStore {
8
+ private seen;
9
+ check(nonce: string): Promise<boolean>;
10
+ private evict;
11
+ }
12
+
13
+ interface RequestMeta {
14
+ requestId: string;
15
+ method: string;
16
+ route: string;
17
+ origin: string;
18
+ referer: string | null;
19
+ walletAddress: string | null;
20
+ clientId: string | null;
21
+ sessionId: string | null;
22
+ contentType: string | null;
23
+ headers: Record<string, string>;
24
+ startTime: number;
25
+ }
26
+ interface PluginContext {
27
+ readonly requestId: string;
28
+ readonly route: string;
29
+ readonly walletAddress: string | null;
30
+ readonly clientId: string | null;
31
+ readonly sessionId: string | null;
32
+ verifiedWallet: string | null;
33
+ setVerifiedWallet(address: string): void;
34
+ }
35
+ interface PaymentEvent {
36
+ protocol: 'x402' | 'mpp';
37
+ payer: string;
38
+ amount: string;
39
+ network: string;
40
+ }
41
+ interface SettlementEvent {
42
+ protocol: 'x402' | 'mpp';
43
+ payer: string;
44
+ transaction: string;
45
+ network: string;
46
+ }
47
+ interface ResponseMeta {
48
+ statusCode: number;
49
+ statusText: string;
50
+ duration: number;
51
+ contentType: string | null;
52
+ headers: Record<string, string>;
53
+ }
54
+ interface ErrorEvent {
55
+ status: number;
56
+ message: string;
57
+ settled: boolean;
58
+ }
59
+ interface RouterPlugin {
60
+ init?(config: {
61
+ origin?: string;
62
+ }): void | Promise<void>;
63
+ onRequest?(meta: RequestMeta): PluginContext;
64
+ onPaymentVerified?(ctx: PluginContext, payment: PaymentEvent): void;
65
+ onPaymentSettled?(ctx: PluginContext, settlement: SettlementEvent): void;
66
+ onResponse?(ctx: PluginContext, response: ResponseMeta): void;
67
+ onError?(ctx: PluginContext, error: ErrorEvent): void;
68
+ onAlert?(ctx: PluginContext, alert: AlertEvent): void;
69
+ onProviderQuota?(ctx: PluginContext, event: ProviderQuotaEvent): void;
70
+ }
71
+ declare function consolePlugin(): RouterPlugin;
72
+
73
+ declare class HttpError extends Error {
74
+ readonly status: number;
75
+ constructor(message: string, status: number);
76
+ }
77
+ type AlertLevel = 'info' | 'warn' | 'error' | 'critical';
78
+ interface AlertEvent {
79
+ level: AlertLevel;
80
+ message: string;
81
+ route: string;
82
+ meta?: Record<string, unknown>;
83
+ }
84
+ type AlertFn = (level: AlertLevel, message: string, meta?: Record<string, unknown>) => void;
85
+ type ProtocolType = 'x402' | 'mpp';
86
+ type AuthMode = 'paid' | 'siwx' | 'apiKey' | 'unprotected';
87
+ interface TierConfig {
88
+ price: string;
89
+ label?: string;
90
+ }
91
+ type PricingConfig<TBody = unknown> = string | ((body: TBody) => string | Promise<string>) | {
92
+ field: string;
93
+ tiers: Record<string, TierConfig>;
94
+ default?: string;
95
+ };
96
+ interface PaidOptions {
97
+ protocols?: ProtocolType[];
98
+ maxPrice?: string;
99
+ }
100
+ interface HandlerContext<TBody = undefined, TQuery = undefined> {
101
+ body: TBody;
102
+ query: TQuery;
103
+ request: NextRequest;
104
+ requestId: string;
105
+ route: string;
106
+ wallet: string | null;
107
+ account: unknown;
108
+ alert: AlertFn;
109
+ setVerifiedWallet: (addr: string) => void;
110
+ }
111
+ type OveragePolicy = 'same-rate' | 'increased-rate' | 'hard-stop';
112
+ type QuotaLevel = 'healthy' | 'warn' | 'critical';
113
+ interface QuotaInfo {
114
+ remaining: number | null;
115
+ limit: number | null;
116
+ spend?: number;
117
+ }
118
+ interface ProviderConfig {
119
+ extractQuota?: (result: unknown, headers: Headers) => QuotaInfo | null;
120
+ monitor?: () => Promise<QuotaInfo | null>;
121
+ overage?: OveragePolicy;
122
+ warn?: number;
123
+ critical?: number;
124
+ }
125
+ interface ProviderQuotaEvent {
126
+ provider: string;
127
+ route: string;
128
+ remaining: number | null;
129
+ limit: number | null;
130
+ spend?: number;
131
+ level: QuotaLevel;
132
+ overage: OveragePolicy;
133
+ message: string;
134
+ }
135
+ interface RouteEntry {
136
+ key: string;
137
+ authMode: AuthMode;
138
+ pricing?: PricingConfig;
139
+ protocols: ProtocolType[];
140
+ bodySchema?: ZodType;
141
+ querySchema?: ZodType;
142
+ outputSchema?: ZodType;
143
+ description?: string;
144
+ path?: string;
145
+ method: 'GET' | 'POST';
146
+ maxPrice?: string;
147
+ apiKeyResolver?: (key: string) => unknown | Promise<unknown>;
148
+ providerName?: string;
149
+ providerConfig?: ProviderConfig;
150
+ }
151
+ interface RouterConfig {
152
+ payeeAddress: string;
153
+ network?: string;
154
+ facilitatorUrl?: string;
155
+ plugin?: RouterPlugin;
156
+ siwx?: {
157
+ nonceStore?: NonceStore;
158
+ };
159
+ prices?: Record<string, string>;
160
+ mpp?: {
161
+ secretKey: string;
162
+ currency: string;
163
+ recipient?: string;
164
+ };
165
+ }
166
+
167
+ declare class RouteRegistry {
168
+ private routes;
169
+ register(entry: RouteEntry): void;
170
+ get(key: string): RouteEntry | undefined;
171
+ entries(): IterableIterator<[string, RouteEntry]>;
172
+ has(key: string): boolean;
173
+ get size(): number;
174
+ validate(expectedKeys?: string[]): void;
175
+ }
176
+
177
+ interface WellKnownOptions {
178
+ instructions?: string | (() => string | Promise<string>);
179
+ ownershipProofs?: string[];
180
+ }
181
+
182
+ interface OpenAPIOptions {
183
+ title: string;
184
+ version: string;
185
+ description?: string;
186
+ baseUrl?: string;
187
+ contact?: {
188
+ name?: string;
189
+ url?: string;
190
+ };
191
+ }
192
+
193
+ interface OrchestrateDeps {
194
+ x402Server: Record<string, Function> | null;
195
+ initPromise: Promise<void>;
196
+ x402InitError?: string;
197
+ plugin?: RouterPlugin;
198
+ nonceStore: NonceStore;
199
+ payeeAddress: string;
200
+ network: string;
201
+ mppConfig?: {
202
+ secretKey: string;
203
+ currency: string;
204
+ recipient?: string;
205
+ };
206
+ }
207
+
208
+ type True = true;
209
+ type False = false;
210
+ declare class RouteBuilder<TBody = undefined, TQuery = undefined, HasAuth extends boolean = false, NeedsBody extends boolean = false, HasBody extends boolean = false> {
211
+ /** @internal */ readonly _key: string;
212
+ /** @internal */ readonly _registry: RouteRegistry;
213
+ /** @internal */ readonly _deps: OrchestrateDeps;
214
+ /** @internal */ _authMode: AuthMode | null;
215
+ /** @internal */ _pricing: PricingConfig | undefined;
216
+ /** @internal */ _protocols: ProtocolType[];
217
+ /** @internal */ _maxPrice: string | undefined;
218
+ /** @internal */ _bodySchema: ZodType | undefined;
219
+ /** @internal */ _querySchema: ZodType | undefined;
220
+ /** @internal */ _outputSchema: ZodType | undefined;
221
+ /** @internal */ _description: string | undefined;
222
+ /** @internal */ _path: string | undefined;
223
+ /** @internal */ _method: 'GET' | 'POST';
224
+ /** @internal */ _apiKeyResolver: ((key: string) => unknown | Promise<unknown>) | undefined;
225
+ /** @internal */ _providerName: string | undefined;
226
+ /** @internal */ _providerConfig: ProviderConfig | undefined;
227
+ constructor(key: string, registry: RouteRegistry, deps: OrchestrateDeps);
228
+ private fork;
229
+ paid(pricing: string, options?: PaidOptions): RouteBuilder<TBody, TQuery, True, False, HasBody>;
230
+ paid<TBodyIn>(pricing: (body: TBodyIn) => string | Promise<string>, options?: PaidOptions & {
231
+ maxPrice: string;
232
+ }): RouteBuilder<TBody, TQuery, True, True, HasBody>;
233
+ paid(pricing: {
234
+ field: string;
235
+ tiers: Record<string, {
236
+ price: string;
237
+ label?: string;
238
+ }>;
239
+ default?: string;
240
+ }, options?: PaidOptions): RouteBuilder<TBody, TQuery, True, True, HasBody>;
241
+ siwx(): HasAuth extends true ? never : RouteBuilder<TBody, TQuery, True, False, HasBody>;
242
+ apiKey(resolver: (key: string) => unknown | Promise<unknown>): RouteBuilder<TBody, TQuery, True, NeedsBody, HasBody>;
243
+ unprotected(): RouteBuilder<TBody, TQuery, True, False, HasBody>;
244
+ provider(name: string, config?: ProviderConfig): this;
245
+ body<T>(schema: ZodType<T>): RouteBuilder<T, TQuery, HasAuth, NeedsBody, True>;
246
+ query<T>(schema: ZodType<T>): RouteBuilder<TBody, T, HasAuth, NeedsBody, HasBody>;
247
+ output(schema: ZodType): this;
248
+ description(text: string): this;
249
+ path(p: string): this;
250
+ handler(this: RouteBuilder<TBody, TQuery, True, true, false>, fn: never): never;
251
+ handler(this: RouteBuilder<TBody, TQuery, false, boolean, boolean>, fn: never): never;
252
+ handler(this: RouteBuilder<TBody, TQuery, True, False, HasBody>, fn: (ctx: HandlerContext<TBody, TQuery>) => Promise<unknown>): (request: NextRequest) => Promise<Response>;
253
+ handler(this: RouteBuilder<TBody, TQuery, True, True, True>, fn: (ctx: HandlerContext<TBody, TQuery>) => Promise<unknown>): (request: NextRequest) => Promise<Response>;
254
+ }
255
+
256
+ interface MonitorEntry {
257
+ provider: string;
258
+ route: string;
259
+ monitor: () => Promise<QuotaInfo | null>;
260
+ overage: OveragePolicy;
261
+ warn?: number;
262
+ critical?: number;
263
+ }
264
+ interface ServiceRouter {
265
+ route(key: string): RouteBuilder;
266
+ wellKnown(options?: WellKnownOptions): (request: NextRequest) => Promise<NextResponse>;
267
+ openapi(options: OpenAPIOptions): (request: NextRequest) => Promise<NextResponse>;
268
+ monitors(): MonitorEntry[];
269
+ registry: RouteRegistry;
270
+ }
271
+ declare function createRouter(config: RouterConfig): ServiceRouter;
272
+
273
+ export { type AlertEvent, type AlertFn, type AlertLevel, type AuthMode, type ErrorEvent, type HandlerContext, HttpError, MemoryNonceStore, type MonitorEntry, type NonceStore, type OveragePolicy, type PaidOptions, type PaymentEvent, type PluginContext, type PricingConfig, type ProtocolType, type ProviderConfig, type ProviderQuotaEvent, type QuotaInfo, type QuotaLevel, type RequestMeta, type ResponseMeta, RouteBuilder, type RouteEntry, RouteRegistry, type RouterConfig, type RouterPlugin, type ServiceRouter, type SettlementEvent, type TierConfig, consolePlugin, createRouter };