@agentcash/router 1.6.0 → 1.7.1
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/AGENTS.md +85 -0
- package/README.md +133 -550
- package/dist/index.cjs +993 -824
- package/dist/index.d.cts +96 -101
- package/dist/index.d.ts +96 -101
- package/dist/index.js +985 -805
- package/package.json +6 -14
- package/.claude/CLAUDE.md +0 -343
- package/.claude/skills/router-guide/SKILL.md +0 -585
package/dist/index.d.cts
CHANGED
|
@@ -4,7 +4,6 @@ import { ZodType } from 'zod';
|
|
|
4
4
|
import { PaymentRequirements, PaymentRequired, VerifyResponse, SettleResponse, Network } from '@x402/core/types';
|
|
5
5
|
import * as viem from 'viem';
|
|
6
6
|
import { Transport } from 'mppx/server';
|
|
7
|
-
import { Store } from 'mppx';
|
|
8
7
|
|
|
9
8
|
interface KvStore {
|
|
10
9
|
get(key: string): Promise<unknown>;
|
|
@@ -26,42 +25,15 @@ type KvChange<R> = {
|
|
|
26
25
|
op: 'delete';
|
|
27
26
|
result: R;
|
|
28
27
|
};
|
|
29
|
-
declare function withPrefix(kv: KvStore, prefix: string): KvStore;
|
|
30
28
|
|
|
31
|
-
declare const SIWX_CHALLENGE_EXPIRY_MS: number;
|
|
32
29
|
interface NonceStore {
|
|
33
30
|
check(nonce: string): Promise<boolean>;
|
|
34
31
|
}
|
|
35
|
-
declare class MemoryNonceStore implements NonceStore {
|
|
36
|
-
private seen;
|
|
37
|
-
check(nonce: string): Promise<boolean>;
|
|
38
|
-
private evict;
|
|
39
|
-
}
|
|
40
|
-
interface KvNonceStoreOptions {
|
|
41
|
-
prefix?: string;
|
|
42
|
-
ttlMs?: number;
|
|
43
|
-
}
|
|
44
|
-
declare function createKvNonceStore(kv: KvStore, options?: KvNonceStoreOptions): NonceStore;
|
|
45
32
|
|
|
46
33
|
interface EntitlementStore {
|
|
47
34
|
has(route: string, wallet: string): Promise<boolean>;
|
|
48
35
|
grant(route: string, wallet: string): Promise<void>;
|
|
49
36
|
}
|
|
50
|
-
declare class MemoryEntitlementStore implements EntitlementStore {
|
|
51
|
-
private readonly routeToWallets;
|
|
52
|
-
has(route: string, wallet: string): Promise<boolean>;
|
|
53
|
-
grant(route: string, wallet: string): Promise<void>;
|
|
54
|
-
}
|
|
55
|
-
interface KvEntitlementStoreOptions {
|
|
56
|
-
prefix?: string;
|
|
57
|
-
}
|
|
58
|
-
declare function createKvEntitlementStore(kv: KvStore, options?: KvEntitlementStoreOptions): EntitlementStore;
|
|
59
|
-
|
|
60
|
-
type MppStore = Store.Store;
|
|
61
|
-
interface KvMppStoreOptions {
|
|
62
|
-
prefix?: string;
|
|
63
|
-
}
|
|
64
|
-
declare function createKvMppStore(kv: KvStore, options?: KvMppStoreOptions): Promise<MppStore>;
|
|
65
37
|
|
|
66
38
|
interface RequestMeta {
|
|
67
39
|
requestId: string;
|
|
@@ -137,7 +109,6 @@ interface RouterPlugin {
|
|
|
137
109
|
onAlert?(ctx: PluginContext, alert: AlertEvent): void;
|
|
138
110
|
onProviderQuota?(ctx: PluginContext, event: ProviderQuotaEvent): void;
|
|
139
111
|
}
|
|
140
|
-
declare function consolePlugin(): RouterPlugin;
|
|
141
112
|
|
|
142
113
|
declare class HttpError extends Error {
|
|
143
114
|
readonly status: number;
|
|
@@ -222,10 +193,6 @@ interface X402AcceptConfig extends X402AcceptBase {
|
|
|
222
193
|
/** Per-accept payee override. Function form receives the request and parsed body for dynamic recipient routing. Falls back to `RouterConfig.payeeAddress`. */
|
|
223
194
|
payTo?: PayToConfig;
|
|
224
195
|
}
|
|
225
|
-
interface X402ResolvedAccept extends X402AcceptBase {
|
|
226
|
-
scheme: string;
|
|
227
|
-
payTo: string;
|
|
228
|
-
}
|
|
229
196
|
interface X402RouterFacilitatorConfig extends FacilitatorConfig {
|
|
230
197
|
/** Async header builder invoked per facilitator call. Use for short-lived auth tokens (e.g. CDP signed headers). */
|
|
231
198
|
createAcceptsHeaders?: () => Promise<Record<string, string>>;
|
|
@@ -233,9 +200,7 @@ interface X402RouterFacilitatorConfig extends FacilitatorConfig {
|
|
|
233
200
|
/** A facilitator URL or a full `FacilitatorConfig` (URL + auth header builders). */
|
|
234
201
|
type X402FacilitatorTarget = string | X402RouterFacilitatorConfig;
|
|
235
202
|
interface X402FacilitatorsConfig {
|
|
236
|
-
/** Facilitator for
|
|
237
|
-
evm?: X402FacilitatorTarget;
|
|
238
|
-
/** Facilitator for Solana. Required to accept Solana payments — there's no default. */
|
|
203
|
+
/** Facilitator for Solana. Defaults to {@link DEFAULT_SOLANA_FACILITATOR_URL}. The EVM facilitator is hardcoded to Coinbase (CDP) — set `CDP_API_KEY_ID` / `CDP_API_KEY_SECRET`. */
|
|
239
204
|
solana?: X402FacilitatorTarget;
|
|
240
205
|
}
|
|
241
206
|
interface MppProtocolInfo {
|
|
@@ -409,7 +374,7 @@ interface RouterConfig {
|
|
|
409
374
|
/** Per-chain facilitator overrides (`evm`/`solana`). Defaults to the Coinbase facilitator on EVM; set `solana` to accept Solana payments. */
|
|
410
375
|
facilitators?: X402FacilitatorsConfig;
|
|
411
376
|
};
|
|
412
|
-
/** Observability hook receiving request/auth/payment/settlement events.
|
|
377
|
+
/** Observability hook receiving request/auth/payment/settlement events. Implement `RouterPlugin` for structured logs/analytics. */
|
|
413
378
|
plugin?: RouterPlugin;
|
|
414
379
|
/** Single KV cache for SIWX nonce, SIWX entitlement, and MPP tx-hash replay (prefixed `siwx:nonce:`, `siwx:ent:`, `mpp:`). Pass `{ url, token }` for an Upstash-compatible REST endpoint (Upstash, Vercel KV), or a custom `KvStore` implementation. Omitted: auto-bootstraps from `KV_REST_API_URL` + `KV_REST_API_TOKEN`; falls back to in-memory when missing (unsafe in serverless). */
|
|
415
380
|
kvStore?: KvStore | {
|
|
@@ -422,7 +387,7 @@ interface RouterConfig {
|
|
|
422
387
|
mpp?: {
|
|
423
388
|
/** HMAC key for signing/verifying MPP challenge nonces. Persist across deploys — rotating invalidates outstanding 402 challenges. Falls back to `MPP_SECRET_KEY`. */
|
|
424
389
|
secretKey: string;
|
|
425
|
-
/** Tempo currency contract address (0x-prefixed). Use `
|
|
390
|
+
/** Tempo currency contract address (0x-prefixed). Use `TEMPO_USDC_ADDRESS` for USDC on Tempo. */
|
|
426
391
|
currency: string;
|
|
427
392
|
/** MPP payee address (EVM). Overrides `payeeAddress` for MPP only. Required when `payeeAddress` is unset. MUST equal `operatorKey`'s derived address when `session` is enabled. */
|
|
428
393
|
recipient?: string;
|
|
@@ -473,6 +438,7 @@ type MppxMiddlewareResponse<T extends Transport.AnyTransport> = {
|
|
|
473
438
|
withReceipt: Transport.WithReceipt<T>;
|
|
474
439
|
};
|
|
475
440
|
type MppxMiddleware<TOptions, T extends Transport.AnyTransport> = (options: TOptions) => (input: Request) => Promise<MppxMiddlewareResponse<T>>;
|
|
441
|
+
|
|
476
442
|
interface RouterDeps {
|
|
477
443
|
x402Server: X402Server | null;
|
|
478
444
|
initPromise: Promise<void>;
|
|
@@ -527,37 +493,12 @@ type StreamArg<TBody, TQuery, HasAuth extends boolean, NeedsBody extends boolean
|
|
|
527
493
|
} : {
|
|
528
494
|
__missing: 'Select an auth mode: .paid({ dynamic: true, ... }) — streaming requires handler-driven dynamic pricing';
|
|
529
495
|
};
|
|
496
|
+
interface RouteBuilderDefaults {
|
|
497
|
+
protocols?: ProtocolType[];
|
|
498
|
+
}
|
|
530
499
|
declare class RouteBuilder<TBody = undefined, TQuery = undefined, TOutput = undefined, HasAuth extends boolean = false, NeedsBody extends boolean = false, HasBody extends boolean = false, IsDynamic extends boolean = false> {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
/** @internal */ readonly _deps: OrchestrateDeps;
|
|
534
|
-
/** @internal */ _authMode: AuthMode | null;
|
|
535
|
-
/** @internal */ _pricing: PricingConfig | undefined;
|
|
536
|
-
/** @internal */ _siwxEnabled: boolean;
|
|
537
|
-
/** @internal */ _protocols: ProtocolType[];
|
|
538
|
-
/** @internal */ _maxPrice: string | undefined;
|
|
539
|
-
/** @internal */ _minPrice: string | undefined;
|
|
540
|
-
/** @internal */ _dynamicPrice: boolean;
|
|
541
|
-
/** @internal */ _tickCost: string | undefined;
|
|
542
|
-
/** @internal */ _unitType: string | undefined;
|
|
543
|
-
/** @internal */ _payTo: PayToConfig | undefined;
|
|
544
|
-
/** @internal */ _bodySchema: ZodType | undefined;
|
|
545
|
-
/** @internal */ _querySchema: ZodType | undefined;
|
|
546
|
-
/** @internal */ _outputSchema: ZodType | undefined;
|
|
547
|
-
/** @internal */ _inputExample: JsonObject | undefined;
|
|
548
|
-
/** @internal */ _hasInputExample: boolean;
|
|
549
|
-
/** @internal */ _outputExample: JsonValue | undefined;
|
|
550
|
-
/** @internal */ _hasOutputExample: boolean;
|
|
551
|
-
/** @internal */ _description: string | undefined;
|
|
552
|
-
/** @internal */ _path: string | undefined;
|
|
553
|
-
/** @internal */ _method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
|
|
554
|
-
/** @internal */ _apiKeyResolver: ((key: string) => unknown | Promise<unknown>) | undefined;
|
|
555
|
-
/** @internal */ _providerName: string | undefined;
|
|
556
|
-
/** @internal */ _providerConfig: ProviderConfig | undefined;
|
|
557
|
-
/** @internal */ _validateFn: ((body: TBody) => void | Promise<void>) | undefined;
|
|
558
|
-
/** @internal */ _settlement: SettlementLifecycle<TBody> | undefined;
|
|
559
|
-
/** @internal */ _mppInfo: MppProtocolInfo | undefined;
|
|
560
|
-
constructor(key: string, registry: RouteRegistry, deps: OrchestrateDeps);
|
|
500
|
+
#private;
|
|
501
|
+
constructor(key: string, registry: RouteRegistry, deps: OrchestrateDeps, defaults?: RouteBuilderDefaults);
|
|
561
502
|
private fork;
|
|
562
503
|
/**
|
|
563
504
|
* Charge a fixed price per request, denominated in USDC as a decimal string.
|
|
@@ -827,50 +768,83 @@ declare class RouteBuilder<TBody = undefined, TQuery = undefined, TOutput = unde
|
|
|
827
768
|
private register;
|
|
828
769
|
}
|
|
829
770
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
declare const TEMPO_USDC_CURRENCY = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
833
|
-
declare const ZERO_EVM_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
834
|
-
|
|
835
|
-
type RouterEnv = Record<string, string | undefined>;
|
|
836
|
-
type RouterConfigIssueCode = 'missing_base_url' | 'empty_protocols' | 'missing_x402_accepts' | 'missing_x402_network' | 'unsupported_x402_network' | 'missing_x402_asset' | 'invalid_x402_decimals' | 'missing_x402_payee' | 'missing_cdp_keys' | 'placeholder_payee' | 'missing_mpp_config' | 'missing_mpp_secret_key' | 'missing_mpp_currency' | 'invalid_mpp_currency' | 'missing_mpp_recipient' | 'invalid_mpp_recipient' | 'missing_mpp_rpc_url' | 'invalid_mpp_fee_payer_key' | 'invalid_mpp_operator_key' | 'mpp_operator_equals_fee_payer';
|
|
771
|
+
type RouterConfigIssueCode = 'missing_base_url' | 'invalid_base_url' | 'empty_protocols' | 'missing_x402_accepts' | 'missing_x402_network' | 'unsupported_x402_network' | 'missing_x402_asset' | 'invalid_x402_decimals' | 'missing_x402_payee' | 'invalid_x402_payee' | 'invalid_solana_payee' | 'invalid_solana_facilitator_url' | 'missing_cdp_keys' | 'placeholder_payee' | 'missing_mpp_config' | 'missing_mpp_secret_key' | 'missing_mpp_currency' | 'invalid_mpp_currency' | 'missing_mpp_recipient' | 'invalid_mpp_recipient' | 'missing_mpp_rpc_url' | 'invalid_mpp_rpc_url' | 'invalid_mpp_fee_payer_key' | 'invalid_mpp_operator_key' | 'mpp_operator_equals_fee_payer' | 'missing_discovery_title' | 'missing_discovery_description' | 'missing_discovery_guidance' | 'invalid_server_url' | 'kv_url_without_token' | 'kv_token_without_url' | 'invalid_kv_url' | 'missing_kv_in_production';
|
|
772
|
+
type RouterConfigIssueSeverity = 'error' | 'warning';
|
|
837
773
|
interface RouterConfigIssue {
|
|
838
774
|
code: RouterConfigIssueCode;
|
|
839
775
|
message: string;
|
|
840
776
|
protocol?: ProtocolType;
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
777
|
+
/** @default 'error' — warnings are surfaced via `console.warn` and do not throw. */
|
|
778
|
+
severity?: RouterConfigIssueSeverity;
|
|
779
|
+
}
|
|
780
|
+
/** Options for {@link createRouterFromEnv} / {@link routerConfigFromEnv}. */
|
|
781
|
+
interface CreateRouterFromEnvOptions<TPrices extends Record<string, string> = Record<never, string>> {
|
|
782
|
+
/** Defaults to `process.env`. Pass an explicit object in tests. */
|
|
783
|
+
env?: Record<string, string | undefined>;
|
|
784
|
+
/** Discovery title. Shown in `.well-known/agentcash`, OpenAPI, and `/llms.txt`. */
|
|
785
|
+
title: string;
|
|
786
|
+
/** Discovery description. */
|
|
787
|
+
description: string;
|
|
788
|
+
/** Long-form usage guidance for agent consumers. Served at `/llms.txt`. Pass an empty string to opt out. */
|
|
789
|
+
guidance: string;
|
|
790
|
+
/** Discovery version. @default '1.0.0' */
|
|
791
|
+
version?: string;
|
|
792
|
+
/** Optional contact metadata published in discovery. */
|
|
793
|
+
contact?: DiscoveryConfig['contact'];
|
|
794
|
+
/** Optional ownership proofs published in `.well-known/agentcash`. */
|
|
795
|
+
ownershipProofs?: string[];
|
|
796
|
+
/** Per-route HTTP method hint visibility. */
|
|
797
|
+
methodHints?: DiscoveryConfig['methodHints'];
|
|
798
|
+
/** Override the OpenAPI `servers[].url`. Defaults to `BASE_URL`. */
|
|
799
|
+
serverUrl?: string;
|
|
800
|
+
/** Centralized price map keyed by route id. `route(key)` auto-applies `.paid(prices[key])` for matching keys. */
|
|
801
|
+
prices?: TPrices;
|
|
802
|
+
/** Observability plugin. */
|
|
803
|
+
plugin?: RouterPlugin;
|
|
804
|
+
/** Custom KV store. When omitted, the router auto-bootstraps from `KV_REST_API_URL` + `KV_REST_API_TOKEN`. */
|
|
805
|
+
kvStore?: KvStore;
|
|
806
|
+
/** Override x402 facilitators. The Solana facilitator defaults to `SOLANA_FACILITATOR_URL` env or `DEFAULT_SOLANA_FACILITATOR_URL`. */
|
|
807
|
+
x402Facilitators?: X402FacilitatorsConfig;
|
|
808
|
+
/** Explicit protocol list. Default: `['x402']`, with `'mpp'` added when `MPP_SECRET_KEY` is set. */
|
|
809
|
+
protocols?: readonly ProtocolType[];
|
|
810
|
+
/** Require `route({ path })` form for every route. @default false */
|
|
811
|
+
strictRoutes?: boolean;
|
|
845
812
|
}
|
|
846
813
|
|
|
847
814
|
declare class RouterConfigError extends Error {
|
|
848
815
|
readonly issues: RouterConfigIssue[];
|
|
849
816
|
constructor(issues: RouterConfigIssue[]);
|
|
850
817
|
}
|
|
851
|
-
declare function formatRouterConfigIssues(issues: readonly RouterConfigIssue[]): string;
|
|
852
818
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
solanaPayeeAddress?: string;
|
|
866
|
-
solanaPayeeEnv?: string;
|
|
867
|
-
}): X402AcceptConfig[];
|
|
868
|
-
declare function paidOptionsForProtocols(protocols: readonly ProtocolType[]): PaidOptions;
|
|
819
|
+
/**
|
|
820
|
+
* Build a {@link RouterConfig} from environment variables.
|
|
821
|
+
*
|
|
822
|
+
* `envShape` in this file is the single source of truth for env vars; README
|
|
823
|
+
* and `.env.example` are drift-tested against `ENV_KEYS`. Validates every
|
|
824
|
+
* required value up front and throws a single {@link RouterConfigError}
|
|
825
|
+
* containing all issues at once. Soft warnings (e.g. half-configured KV) are
|
|
826
|
+
* emitted via `console.warn`.
|
|
827
|
+
*/
|
|
828
|
+
declare function routerConfigFromEnv<const TPrices extends Record<string, string> = Record<never, string>>(options: CreateRouterFromEnvOptions<TPrices>): RouterConfig & {
|
|
829
|
+
prices?: TPrices;
|
|
830
|
+
};
|
|
869
831
|
|
|
870
|
-
/**
|
|
871
|
-
|
|
872
|
-
/**
|
|
873
|
-
declare const
|
|
832
|
+
/** Base mainnet CAIP-2 network ID (`eip155:8453`). */
|
|
833
|
+
declare const BASE_MAINNET_NETWORK = "eip155:8453";
|
|
834
|
+
/** Solana mainnet CAIP-2 network ID. */
|
|
835
|
+
declare const SOLANA_MAINNET_NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
|
|
836
|
+
/** USDC contract address on Tempo (the `mpp.currency` value for Tempo USDC). */
|
|
837
|
+
declare const TEMPO_USDC_ADDRESS = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
838
|
+
/** USDC has 6 decimals on Tempo. */
|
|
839
|
+
declare const TEMPO_USDC_DECIMALS = 6;
|
|
840
|
+
/** USDC contract on Base mainnet. */
|
|
841
|
+
declare const BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
842
|
+
/** USDC has 6 decimals on Base. */
|
|
843
|
+
declare const BASE_USDC_DECIMALS = 6;
|
|
844
|
+
/** All-zeros EVM address. Used as a placeholder/sentinel; not a valid payee. */
|
|
845
|
+
declare const ZERO_EVM_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
846
|
+
/** Public Solana x402 facilitator. Override per-deployment via `SOLANA_FACILITATOR_URL`. */
|
|
847
|
+
declare const DEFAULT_SOLANA_FACILITATOR_URL = "https://facilitator.corbits.dev";
|
|
874
848
|
|
|
875
849
|
interface MonitorEntry {
|
|
876
850
|
provider: string;
|
|
@@ -891,5 +865,26 @@ interface ServiceRouter<TPriceKeys extends string = never> {
|
|
|
891
865
|
declare function createRouter<const P extends Record<string, string> = Record<never, string>>(config: RouterConfig & {
|
|
892
866
|
prices?: P;
|
|
893
867
|
}): ServiceRouter<Extract<keyof P, string>>;
|
|
868
|
+
/**
|
|
869
|
+
* Build a {@link ServiceRouter} from environment variables.
|
|
870
|
+
*
|
|
871
|
+
* Validates every required env var up front and throws a single
|
|
872
|
+
* {@link RouterConfigError} containing all problems at once. Most consumers
|
|
873
|
+
* should use this entry point. Use {@link createRouter} when you need to
|
|
874
|
+
* construct a {@link RouterConfig} programmatically.
|
|
875
|
+
*
|
|
876
|
+
* The env vars this function reads are the canonical schema in
|
|
877
|
+
* `src/config/schema.ts` (`ENV_SPEC`).
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
* ```ts
|
|
881
|
+
* export const router = createRouterFromEnv({
|
|
882
|
+
* title: 'My API',
|
|
883
|
+
* description: 'Pay-per-call search.',
|
|
884
|
+
* guidance: 'POST /search with { q: string }. Returns top 10 results.',
|
|
885
|
+
* });
|
|
886
|
+
* ```
|
|
887
|
+
*/
|
|
888
|
+
declare function createRouterFromEnv<const P extends Record<string, string> = Record<never, string>>(options: CreateRouterFromEnvOptions<P>): ServiceRouter<Extract<keyof P, string>>;
|
|
894
889
|
|
|
895
|
-
export {
|
|
890
|
+
export { BASE_MAINNET_NETWORK, BASE_USDC_ADDRESS, BASE_USDC_DECIMALS, type CreateRouterFromEnvOptions, DEFAULT_SOLANA_FACILITATOR_URL, type DiscoveryConfig, type HandlerContext, HttpError, type KvStore, type PaidOptions, type ProtocolType, type RouterConfig, RouterConfigError, type RouterConfigIssue, type RouterConfigIssueCode, type RouterConfigIssueSeverity, type RouterPlugin, SOLANA_MAINNET_NETWORK, type ServiceRouter, type SettlementErrorContext, type SettlementLifecycleContext, type SettlementSettledContext, TEMPO_USDC_ADDRESS, TEMPO_USDC_DECIMALS, type X402FacilitatorsConfig, ZERO_EVM_ADDRESS, createRouter, createRouterFromEnv, routerConfigFromEnv };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { ZodType } from 'zod';
|
|
|
4
4
|
import { PaymentRequirements, PaymentRequired, VerifyResponse, SettleResponse, Network } from '@x402/core/types';
|
|
5
5
|
import * as viem from 'viem';
|
|
6
6
|
import { Transport } from 'mppx/server';
|
|
7
|
-
import { Store } from 'mppx';
|
|
8
7
|
|
|
9
8
|
interface KvStore {
|
|
10
9
|
get(key: string): Promise<unknown>;
|
|
@@ -26,42 +25,15 @@ type KvChange<R> = {
|
|
|
26
25
|
op: 'delete';
|
|
27
26
|
result: R;
|
|
28
27
|
};
|
|
29
|
-
declare function withPrefix(kv: KvStore, prefix: string): KvStore;
|
|
30
28
|
|
|
31
|
-
declare const SIWX_CHALLENGE_EXPIRY_MS: number;
|
|
32
29
|
interface NonceStore {
|
|
33
30
|
check(nonce: string): Promise<boolean>;
|
|
34
31
|
}
|
|
35
|
-
declare class MemoryNonceStore implements NonceStore {
|
|
36
|
-
private seen;
|
|
37
|
-
check(nonce: string): Promise<boolean>;
|
|
38
|
-
private evict;
|
|
39
|
-
}
|
|
40
|
-
interface KvNonceStoreOptions {
|
|
41
|
-
prefix?: string;
|
|
42
|
-
ttlMs?: number;
|
|
43
|
-
}
|
|
44
|
-
declare function createKvNonceStore(kv: KvStore, options?: KvNonceStoreOptions): NonceStore;
|
|
45
32
|
|
|
46
33
|
interface EntitlementStore {
|
|
47
34
|
has(route: string, wallet: string): Promise<boolean>;
|
|
48
35
|
grant(route: string, wallet: string): Promise<void>;
|
|
49
36
|
}
|
|
50
|
-
declare class MemoryEntitlementStore implements EntitlementStore {
|
|
51
|
-
private readonly routeToWallets;
|
|
52
|
-
has(route: string, wallet: string): Promise<boolean>;
|
|
53
|
-
grant(route: string, wallet: string): Promise<void>;
|
|
54
|
-
}
|
|
55
|
-
interface KvEntitlementStoreOptions {
|
|
56
|
-
prefix?: string;
|
|
57
|
-
}
|
|
58
|
-
declare function createKvEntitlementStore(kv: KvStore, options?: KvEntitlementStoreOptions): EntitlementStore;
|
|
59
|
-
|
|
60
|
-
type MppStore = Store.Store;
|
|
61
|
-
interface KvMppStoreOptions {
|
|
62
|
-
prefix?: string;
|
|
63
|
-
}
|
|
64
|
-
declare function createKvMppStore(kv: KvStore, options?: KvMppStoreOptions): Promise<MppStore>;
|
|
65
37
|
|
|
66
38
|
interface RequestMeta {
|
|
67
39
|
requestId: string;
|
|
@@ -137,7 +109,6 @@ interface RouterPlugin {
|
|
|
137
109
|
onAlert?(ctx: PluginContext, alert: AlertEvent): void;
|
|
138
110
|
onProviderQuota?(ctx: PluginContext, event: ProviderQuotaEvent): void;
|
|
139
111
|
}
|
|
140
|
-
declare function consolePlugin(): RouterPlugin;
|
|
141
112
|
|
|
142
113
|
declare class HttpError extends Error {
|
|
143
114
|
readonly status: number;
|
|
@@ -222,10 +193,6 @@ interface X402AcceptConfig extends X402AcceptBase {
|
|
|
222
193
|
/** Per-accept payee override. Function form receives the request and parsed body for dynamic recipient routing. Falls back to `RouterConfig.payeeAddress`. */
|
|
223
194
|
payTo?: PayToConfig;
|
|
224
195
|
}
|
|
225
|
-
interface X402ResolvedAccept extends X402AcceptBase {
|
|
226
|
-
scheme: string;
|
|
227
|
-
payTo: string;
|
|
228
|
-
}
|
|
229
196
|
interface X402RouterFacilitatorConfig extends FacilitatorConfig {
|
|
230
197
|
/** Async header builder invoked per facilitator call. Use for short-lived auth tokens (e.g. CDP signed headers). */
|
|
231
198
|
createAcceptsHeaders?: () => Promise<Record<string, string>>;
|
|
@@ -233,9 +200,7 @@ interface X402RouterFacilitatorConfig extends FacilitatorConfig {
|
|
|
233
200
|
/** A facilitator URL or a full `FacilitatorConfig` (URL + auth header builders). */
|
|
234
201
|
type X402FacilitatorTarget = string | X402RouterFacilitatorConfig;
|
|
235
202
|
interface X402FacilitatorsConfig {
|
|
236
|
-
/** Facilitator for
|
|
237
|
-
evm?: X402FacilitatorTarget;
|
|
238
|
-
/** Facilitator for Solana. Required to accept Solana payments — there's no default. */
|
|
203
|
+
/** Facilitator for Solana. Defaults to {@link DEFAULT_SOLANA_FACILITATOR_URL}. The EVM facilitator is hardcoded to Coinbase (CDP) — set `CDP_API_KEY_ID` / `CDP_API_KEY_SECRET`. */
|
|
239
204
|
solana?: X402FacilitatorTarget;
|
|
240
205
|
}
|
|
241
206
|
interface MppProtocolInfo {
|
|
@@ -409,7 +374,7 @@ interface RouterConfig {
|
|
|
409
374
|
/** Per-chain facilitator overrides (`evm`/`solana`). Defaults to the Coinbase facilitator on EVM; set `solana` to accept Solana payments. */
|
|
410
375
|
facilitators?: X402FacilitatorsConfig;
|
|
411
376
|
};
|
|
412
|
-
/** Observability hook receiving request/auth/payment/settlement events.
|
|
377
|
+
/** Observability hook receiving request/auth/payment/settlement events. Implement `RouterPlugin` for structured logs/analytics. */
|
|
413
378
|
plugin?: RouterPlugin;
|
|
414
379
|
/** Single KV cache for SIWX nonce, SIWX entitlement, and MPP tx-hash replay (prefixed `siwx:nonce:`, `siwx:ent:`, `mpp:`). Pass `{ url, token }` for an Upstash-compatible REST endpoint (Upstash, Vercel KV), or a custom `KvStore` implementation. Omitted: auto-bootstraps from `KV_REST_API_URL` + `KV_REST_API_TOKEN`; falls back to in-memory when missing (unsafe in serverless). */
|
|
415
380
|
kvStore?: KvStore | {
|
|
@@ -422,7 +387,7 @@ interface RouterConfig {
|
|
|
422
387
|
mpp?: {
|
|
423
388
|
/** HMAC key for signing/verifying MPP challenge nonces. Persist across deploys — rotating invalidates outstanding 402 challenges. Falls back to `MPP_SECRET_KEY`. */
|
|
424
389
|
secretKey: string;
|
|
425
|
-
/** Tempo currency contract address (0x-prefixed). Use `
|
|
390
|
+
/** Tempo currency contract address (0x-prefixed). Use `TEMPO_USDC_ADDRESS` for USDC on Tempo. */
|
|
426
391
|
currency: string;
|
|
427
392
|
/** MPP payee address (EVM). Overrides `payeeAddress` for MPP only. Required when `payeeAddress` is unset. MUST equal `operatorKey`'s derived address when `session` is enabled. */
|
|
428
393
|
recipient?: string;
|
|
@@ -473,6 +438,7 @@ type MppxMiddlewareResponse<T extends Transport.AnyTransport> = {
|
|
|
473
438
|
withReceipt: Transport.WithReceipt<T>;
|
|
474
439
|
};
|
|
475
440
|
type MppxMiddleware<TOptions, T extends Transport.AnyTransport> = (options: TOptions) => (input: Request) => Promise<MppxMiddlewareResponse<T>>;
|
|
441
|
+
|
|
476
442
|
interface RouterDeps {
|
|
477
443
|
x402Server: X402Server | null;
|
|
478
444
|
initPromise: Promise<void>;
|
|
@@ -527,37 +493,12 @@ type StreamArg<TBody, TQuery, HasAuth extends boolean, NeedsBody extends boolean
|
|
|
527
493
|
} : {
|
|
528
494
|
__missing: 'Select an auth mode: .paid({ dynamic: true, ... }) — streaming requires handler-driven dynamic pricing';
|
|
529
495
|
};
|
|
496
|
+
interface RouteBuilderDefaults {
|
|
497
|
+
protocols?: ProtocolType[];
|
|
498
|
+
}
|
|
530
499
|
declare class RouteBuilder<TBody = undefined, TQuery = undefined, TOutput = undefined, HasAuth extends boolean = false, NeedsBody extends boolean = false, HasBody extends boolean = false, IsDynamic extends boolean = false> {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
/** @internal */ readonly _deps: OrchestrateDeps;
|
|
534
|
-
/** @internal */ _authMode: AuthMode | null;
|
|
535
|
-
/** @internal */ _pricing: PricingConfig | undefined;
|
|
536
|
-
/** @internal */ _siwxEnabled: boolean;
|
|
537
|
-
/** @internal */ _protocols: ProtocolType[];
|
|
538
|
-
/** @internal */ _maxPrice: string | undefined;
|
|
539
|
-
/** @internal */ _minPrice: string | undefined;
|
|
540
|
-
/** @internal */ _dynamicPrice: boolean;
|
|
541
|
-
/** @internal */ _tickCost: string | undefined;
|
|
542
|
-
/** @internal */ _unitType: string | undefined;
|
|
543
|
-
/** @internal */ _payTo: PayToConfig | undefined;
|
|
544
|
-
/** @internal */ _bodySchema: ZodType | undefined;
|
|
545
|
-
/** @internal */ _querySchema: ZodType | undefined;
|
|
546
|
-
/** @internal */ _outputSchema: ZodType | undefined;
|
|
547
|
-
/** @internal */ _inputExample: JsonObject | undefined;
|
|
548
|
-
/** @internal */ _hasInputExample: boolean;
|
|
549
|
-
/** @internal */ _outputExample: JsonValue | undefined;
|
|
550
|
-
/** @internal */ _hasOutputExample: boolean;
|
|
551
|
-
/** @internal */ _description: string | undefined;
|
|
552
|
-
/** @internal */ _path: string | undefined;
|
|
553
|
-
/** @internal */ _method: 'GET' | 'POST' | 'DELETE' | 'PUT' | 'PATCH';
|
|
554
|
-
/** @internal */ _apiKeyResolver: ((key: string) => unknown | Promise<unknown>) | undefined;
|
|
555
|
-
/** @internal */ _providerName: string | undefined;
|
|
556
|
-
/** @internal */ _providerConfig: ProviderConfig | undefined;
|
|
557
|
-
/** @internal */ _validateFn: ((body: TBody) => void | Promise<void>) | undefined;
|
|
558
|
-
/** @internal */ _settlement: SettlementLifecycle<TBody> | undefined;
|
|
559
|
-
/** @internal */ _mppInfo: MppProtocolInfo | undefined;
|
|
560
|
-
constructor(key: string, registry: RouteRegistry, deps: OrchestrateDeps);
|
|
500
|
+
#private;
|
|
501
|
+
constructor(key: string, registry: RouteRegistry, deps: OrchestrateDeps, defaults?: RouteBuilderDefaults);
|
|
561
502
|
private fork;
|
|
562
503
|
/**
|
|
563
504
|
* Charge a fixed price per request, denominated in USDC as a decimal string.
|
|
@@ -827,50 +768,83 @@ declare class RouteBuilder<TBody = undefined, TQuery = undefined, TOutput = unde
|
|
|
827
768
|
private register;
|
|
828
769
|
}
|
|
829
770
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
declare const TEMPO_USDC_CURRENCY = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
833
|
-
declare const ZERO_EVM_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
834
|
-
|
|
835
|
-
type RouterEnv = Record<string, string | undefined>;
|
|
836
|
-
type RouterConfigIssueCode = 'missing_base_url' | 'empty_protocols' | 'missing_x402_accepts' | 'missing_x402_network' | 'unsupported_x402_network' | 'missing_x402_asset' | 'invalid_x402_decimals' | 'missing_x402_payee' | 'missing_cdp_keys' | 'placeholder_payee' | 'missing_mpp_config' | 'missing_mpp_secret_key' | 'missing_mpp_currency' | 'invalid_mpp_currency' | 'missing_mpp_recipient' | 'invalid_mpp_recipient' | 'missing_mpp_rpc_url' | 'invalid_mpp_fee_payer_key' | 'invalid_mpp_operator_key' | 'mpp_operator_equals_fee_payer';
|
|
771
|
+
type RouterConfigIssueCode = 'missing_base_url' | 'invalid_base_url' | 'empty_protocols' | 'missing_x402_accepts' | 'missing_x402_network' | 'unsupported_x402_network' | 'missing_x402_asset' | 'invalid_x402_decimals' | 'missing_x402_payee' | 'invalid_x402_payee' | 'invalid_solana_payee' | 'invalid_solana_facilitator_url' | 'missing_cdp_keys' | 'placeholder_payee' | 'missing_mpp_config' | 'missing_mpp_secret_key' | 'missing_mpp_currency' | 'invalid_mpp_currency' | 'missing_mpp_recipient' | 'invalid_mpp_recipient' | 'missing_mpp_rpc_url' | 'invalid_mpp_rpc_url' | 'invalid_mpp_fee_payer_key' | 'invalid_mpp_operator_key' | 'mpp_operator_equals_fee_payer' | 'missing_discovery_title' | 'missing_discovery_description' | 'missing_discovery_guidance' | 'invalid_server_url' | 'kv_url_without_token' | 'kv_token_without_url' | 'invalid_kv_url' | 'missing_kv_in_production';
|
|
772
|
+
type RouterConfigIssueSeverity = 'error' | 'warning';
|
|
837
773
|
interface RouterConfigIssue {
|
|
838
774
|
code: RouterConfigIssueCode;
|
|
839
775
|
message: string;
|
|
840
776
|
protocol?: ProtocolType;
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
777
|
+
/** @default 'error' — warnings are surfaced via `console.warn` and do not throw. */
|
|
778
|
+
severity?: RouterConfigIssueSeverity;
|
|
779
|
+
}
|
|
780
|
+
/** Options for {@link createRouterFromEnv} / {@link routerConfigFromEnv}. */
|
|
781
|
+
interface CreateRouterFromEnvOptions<TPrices extends Record<string, string> = Record<never, string>> {
|
|
782
|
+
/** Defaults to `process.env`. Pass an explicit object in tests. */
|
|
783
|
+
env?: Record<string, string | undefined>;
|
|
784
|
+
/** Discovery title. Shown in `.well-known/agentcash`, OpenAPI, and `/llms.txt`. */
|
|
785
|
+
title: string;
|
|
786
|
+
/** Discovery description. */
|
|
787
|
+
description: string;
|
|
788
|
+
/** Long-form usage guidance for agent consumers. Served at `/llms.txt`. Pass an empty string to opt out. */
|
|
789
|
+
guidance: string;
|
|
790
|
+
/** Discovery version. @default '1.0.0' */
|
|
791
|
+
version?: string;
|
|
792
|
+
/** Optional contact metadata published in discovery. */
|
|
793
|
+
contact?: DiscoveryConfig['contact'];
|
|
794
|
+
/** Optional ownership proofs published in `.well-known/agentcash`. */
|
|
795
|
+
ownershipProofs?: string[];
|
|
796
|
+
/** Per-route HTTP method hint visibility. */
|
|
797
|
+
methodHints?: DiscoveryConfig['methodHints'];
|
|
798
|
+
/** Override the OpenAPI `servers[].url`. Defaults to `BASE_URL`. */
|
|
799
|
+
serverUrl?: string;
|
|
800
|
+
/** Centralized price map keyed by route id. `route(key)` auto-applies `.paid(prices[key])` for matching keys. */
|
|
801
|
+
prices?: TPrices;
|
|
802
|
+
/** Observability plugin. */
|
|
803
|
+
plugin?: RouterPlugin;
|
|
804
|
+
/** Custom KV store. When omitted, the router auto-bootstraps from `KV_REST_API_URL` + `KV_REST_API_TOKEN`. */
|
|
805
|
+
kvStore?: KvStore;
|
|
806
|
+
/** Override x402 facilitators. The Solana facilitator defaults to `SOLANA_FACILITATOR_URL` env or `DEFAULT_SOLANA_FACILITATOR_URL`. */
|
|
807
|
+
x402Facilitators?: X402FacilitatorsConfig;
|
|
808
|
+
/** Explicit protocol list. Default: `['x402']`, with `'mpp'` added when `MPP_SECRET_KEY` is set. */
|
|
809
|
+
protocols?: readonly ProtocolType[];
|
|
810
|
+
/** Require `route({ path })` form for every route. @default false */
|
|
811
|
+
strictRoutes?: boolean;
|
|
845
812
|
}
|
|
846
813
|
|
|
847
814
|
declare class RouterConfigError extends Error {
|
|
848
815
|
readonly issues: RouterConfigIssue[];
|
|
849
816
|
constructor(issues: RouterConfigIssue[]);
|
|
850
817
|
}
|
|
851
|
-
declare function formatRouterConfigIssues(issues: readonly RouterConfigIssue[]): string;
|
|
852
818
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
solanaPayeeAddress?: string;
|
|
866
|
-
solanaPayeeEnv?: string;
|
|
867
|
-
}): X402AcceptConfig[];
|
|
868
|
-
declare function paidOptionsForProtocols(protocols: readonly ProtocolType[]): PaidOptions;
|
|
819
|
+
/**
|
|
820
|
+
* Build a {@link RouterConfig} from environment variables.
|
|
821
|
+
*
|
|
822
|
+
* `envShape` in this file is the single source of truth for env vars; README
|
|
823
|
+
* and `.env.example` are drift-tested against `ENV_KEYS`. Validates every
|
|
824
|
+
* required value up front and throws a single {@link RouterConfigError}
|
|
825
|
+
* containing all issues at once. Soft warnings (e.g. half-configured KV) are
|
|
826
|
+
* emitted via `console.warn`.
|
|
827
|
+
*/
|
|
828
|
+
declare function routerConfigFromEnv<const TPrices extends Record<string, string> = Record<never, string>>(options: CreateRouterFromEnvOptions<TPrices>): RouterConfig & {
|
|
829
|
+
prices?: TPrices;
|
|
830
|
+
};
|
|
869
831
|
|
|
870
|
-
/**
|
|
871
|
-
|
|
872
|
-
/**
|
|
873
|
-
declare const
|
|
832
|
+
/** Base mainnet CAIP-2 network ID (`eip155:8453`). */
|
|
833
|
+
declare const BASE_MAINNET_NETWORK = "eip155:8453";
|
|
834
|
+
/** Solana mainnet CAIP-2 network ID. */
|
|
835
|
+
declare const SOLANA_MAINNET_NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
|
|
836
|
+
/** USDC contract address on Tempo (the `mpp.currency` value for Tempo USDC). */
|
|
837
|
+
declare const TEMPO_USDC_ADDRESS = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
838
|
+
/** USDC has 6 decimals on Tempo. */
|
|
839
|
+
declare const TEMPO_USDC_DECIMALS = 6;
|
|
840
|
+
/** USDC contract on Base mainnet. */
|
|
841
|
+
declare const BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
842
|
+
/** USDC has 6 decimals on Base. */
|
|
843
|
+
declare const BASE_USDC_DECIMALS = 6;
|
|
844
|
+
/** All-zeros EVM address. Used as a placeholder/sentinel; not a valid payee. */
|
|
845
|
+
declare const ZERO_EVM_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
846
|
+
/** Public Solana x402 facilitator. Override per-deployment via `SOLANA_FACILITATOR_URL`. */
|
|
847
|
+
declare const DEFAULT_SOLANA_FACILITATOR_URL = "https://facilitator.corbits.dev";
|
|
874
848
|
|
|
875
849
|
interface MonitorEntry {
|
|
876
850
|
provider: string;
|
|
@@ -891,5 +865,26 @@ interface ServiceRouter<TPriceKeys extends string = never> {
|
|
|
891
865
|
declare function createRouter<const P extends Record<string, string> = Record<never, string>>(config: RouterConfig & {
|
|
892
866
|
prices?: P;
|
|
893
867
|
}): ServiceRouter<Extract<keyof P, string>>;
|
|
868
|
+
/**
|
|
869
|
+
* Build a {@link ServiceRouter} from environment variables.
|
|
870
|
+
*
|
|
871
|
+
* Validates every required env var up front and throws a single
|
|
872
|
+
* {@link RouterConfigError} containing all problems at once. Most consumers
|
|
873
|
+
* should use this entry point. Use {@link createRouter} when you need to
|
|
874
|
+
* construct a {@link RouterConfig} programmatically.
|
|
875
|
+
*
|
|
876
|
+
* The env vars this function reads are the canonical schema in
|
|
877
|
+
* `src/config/schema.ts` (`ENV_SPEC`).
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
* ```ts
|
|
881
|
+
* export const router = createRouterFromEnv({
|
|
882
|
+
* title: 'My API',
|
|
883
|
+
* description: 'Pay-per-call search.',
|
|
884
|
+
* guidance: 'POST /search with { q: string }. Returns top 10 results.',
|
|
885
|
+
* });
|
|
886
|
+
* ```
|
|
887
|
+
*/
|
|
888
|
+
declare function createRouterFromEnv<const P extends Record<string, string> = Record<never, string>>(options: CreateRouterFromEnvOptions<P>): ServiceRouter<Extract<keyof P, string>>;
|
|
894
889
|
|
|
895
|
-
export {
|
|
890
|
+
export { BASE_MAINNET_NETWORK, BASE_USDC_ADDRESS, BASE_USDC_DECIMALS, type CreateRouterFromEnvOptions, DEFAULT_SOLANA_FACILITATOR_URL, type DiscoveryConfig, type HandlerContext, HttpError, type KvStore, type PaidOptions, type ProtocolType, type RouterConfig, RouterConfigError, type RouterConfigIssue, type RouterConfigIssueCode, type RouterConfigIssueSeverity, type RouterPlugin, SOLANA_MAINNET_NETWORK, type ServiceRouter, type SettlementErrorContext, type SettlementLifecycleContext, type SettlementSettledContext, TEMPO_USDC_ADDRESS, TEMPO_USDC_DECIMALS, type X402FacilitatorsConfig, ZERO_EVM_ADDRESS, createRouter, createRouterFromEnv, routerConfigFromEnv };
|