@tabai/sdk 0.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/LICENSE +23 -0
- package/README.md +401 -0
- package/bin/tab.mjs +23 -0
- package/dist/_shared/abi.d.ts +150 -0
- package/dist/_shared/abi.d.ts.map +1 -0
- package/dist/_shared/abi.js +197 -0
- package/dist/_shared/abi.js.map +1 -0
- package/dist/_shared/chains.d.ts +118 -0
- package/dist/_shared/chains.d.ts.map +1 -0
- package/dist/_shared/chains.js +89 -0
- package/dist/_shared/chains.js.map +1 -0
- package/dist/_shared/hex.d.ts +35 -0
- package/dist/_shared/hex.d.ts.map +1 -0
- package/dist/_shared/hex.js +40 -0
- package/dist/_shared/hex.js.map +1 -0
- package/dist/_shared/index.d.ts +14 -0
- package/dist/_shared/index.d.ts.map +1 -0
- package/dist/_shared/index.js +14 -0
- package/dist/_shared/index.js.map +1 -0
- package/dist/_shared/keccak256.d.ts +29 -0
- package/dist/_shared/keccak256.d.ts.map +1 -0
- package/dist/_shared/keccak256.js +145 -0
- package/dist/_shared/keccak256.js.map +1 -0
- package/dist/_shared/result.d.ts +78 -0
- package/dist/_shared/result.d.ts.map +1 -0
- package/dist/_shared/result.js +61 -0
- package/dist/_shared/result.js.map +1 -0
- package/dist/cli/client-config.d.ts +155 -0
- package/dist/cli/client-config.d.ts.map +1 -0
- package/dist/cli/client-config.js +382 -0
- package/dist/cli/client-config.js.map +1 -0
- package/dist/cli/connect.d.ts +76 -0
- package/dist/cli/connect.d.ts.map +1 -0
- package/dist/cli/connect.js +158 -0
- package/dist/cli/connect.js.map +1 -0
- package/dist/cli/doctor.d.ts +57 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +253 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +13 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/main.d.ts +45 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +371 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/errors.d.ts +29 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +37 -0
- package/dist/errors.js.map +1 -0
- package/dist/http/client-402.d.ts +243 -0
- package/dist/http/client-402.d.ts.map +1 -0
- package/dist/http/client-402.js +515 -0
- package/dist/http/client-402.js.map +1 -0
- package/dist/http/headers.d.ts +173 -0
- package/dist/http/headers.d.ts.map +1 -0
- package/dist/http/headers.js +284 -0
- package/dist/http/headers.js.map +1 -0
- package/dist/http/index.d.ts +15 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +15 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/metering-claim.d.ts +82 -0
- package/dist/http/metering-claim.d.ts.map +1 -0
- package/dist/http/metering-claim.js +99 -0
- package/dist/http/metering-claim.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +40 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +50 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp/assets.d.ts +31 -0
- package/dist/mcp/assets.d.ts.map +1 -0
- package/dist/mcp/assets.js +78 -0
- package/dist/mcp/assets.js.map +1 -0
- package/dist/mcp/index.d.ts +19 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +19 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/json-schema.d.ts +86 -0
- package/dist/mcp/json-schema.d.ts.map +1 -0
- package/dist/mcp/json-schema.js +215 -0
- package/dist/mcp/json-schema.js.map +1 -0
- package/dist/mcp/json.d.ts +43 -0
- package/dist/mcp/json.d.ts.map +1 -0
- package/dist/mcp/json.js +69 -0
- package/dist/mcp/json.js.map +1 -0
- package/dist/mcp/registry-client.d.ts +88 -0
- package/dist/mcp/registry-client.d.ts.map +1 -0
- package/dist/mcp/registry-client.js +158 -0
- package/dist/mcp/registry-client.js.map +1 -0
- package/dist/mcp/schemas.d.ts +82 -0
- package/dist/mcp/schemas.d.ts.map +1 -0
- package/dist/mcp/schemas.js +493 -0
- package/dist/mcp/schemas.js.map +1 -0
- package/dist/mcp/server.d.ts +97 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +285 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/settings.d.ts +90 -0
- package/dist/mcp/settings.d.ts.map +1 -0
- package/dist/mcp/settings.js +160 -0
- package/dist/mcp/settings.js.map +1 -0
- package/dist/mcp/toolset.d.ts +231 -0
- package/dist/mcp/toolset.d.ts.map +1 -0
- package/dist/mcp/toolset.js +760 -0
- package/dist/mcp/toolset.js.map +1 -0
- package/dist/payments/abi.d.ts +9 -0
- package/dist/payments/abi.d.ts.map +1 -0
- package/dist/payments/abi.js +17 -0
- package/dist/payments/abi.js.map +1 -0
- package/dist/payments/config.d.ts +199 -0
- package/dist/payments/config.d.ts.map +1 -0
- package/dist/payments/config.js +259 -0
- package/dist/payments/config.js.map +1 -0
- package/dist/payments/index.d.ts +13 -0
- package/dist/payments/index.d.ts.map +1 -0
- package/dist/payments/index.js +13 -0
- package/dist/payments/index.js.map +1 -0
- package/dist/payments/kuru.d.ts +191 -0
- package/dist/payments/kuru.d.ts.map +1 -0
- package/dist/payments/kuru.js +377 -0
- package/dist/payments/kuru.js.map +1 -0
- package/dist/payments/monad.d.ts +69 -0
- package/dist/payments/monad.d.ts.map +1 -0
- package/dist/payments/monad.js +306 -0
- package/dist/payments/monad.js.map +1 -0
- package/dist/payments/permit2.d.ts +118 -0
- package/dist/payments/permit2.d.ts.map +1 -0
- package/dist/payments/permit2.js +366 -0
- package/dist/payments/permit2.js.map +1 -0
- package/dist/payments/registry.d.ts +119 -0
- package/dist/payments/registry.d.ts.map +1 -0
- package/dist/payments/registry.js +199 -0
- package/dist/payments/registry.js.map +1 -0
- package/dist/payments/strategy.d.ts +80 -0
- package/dist/payments/strategy.d.ts.map +1 -0
- package/dist/payments/strategy.js +103 -0
- package/dist/payments/strategy.js.map +1 -0
- package/dist/proxy/hooks.d.ts +90 -0
- package/dist/proxy/hooks.d.ts.map +1 -0
- package/dist/proxy/hooks.js +35 -0
- package/dist/proxy/hooks.js.map +1 -0
- package/dist/proxy/index.d.ts +9 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +9 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/proxy/proxy.d.ts +156 -0
- package/dist/proxy/proxy.d.ts.map +1 -0
- package/dist/proxy/proxy.js +366 -0
- package/dist/proxy/proxy.js.map +1 -0
- package/dist/server/adapters/express.d.ts +89 -0
- package/dist/server/adapters/express.d.ts.map +1 -0
- package/dist/server/adapters/express.js +215 -0
- package/dist/server/adapters/express.js.map +1 -0
- package/dist/server/adapters/hono.d.ts +52 -0
- package/dist/server/adapters/hono.d.ts.map +1 -0
- package/dist/server/adapters/hono.js +61 -0
- package/dist/server/adapters/hono.js.map +1 -0
- package/dist/server/adapters/next.d.ts +52 -0
- package/dist/server/adapters/next.d.ts.map +1 -0
- package/dist/server/adapters/next.js +56 -0
- package/dist/server/adapters/next.js.map +1 -0
- package/dist/server/index.d.ts +30 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +30 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/metering.d.ts +209 -0
- package/dist/server/metering.d.ts.map +1 -0
- package/dist/server/metering.js +365 -0
- package/dist/server/metering.js.map +1 -0
- package/dist/server/post-paid.d.ts +355 -0
- package/dist/server/post-paid.d.ts.map +1 -0
- package/dist/server/post-paid.js +512 -0
- package/dist/server/post-paid.js.map +1 -0
- package/dist/x402/client.d.ts +203 -0
- package/dist/x402/client.d.ts.map +1 -0
- package/dist/x402/client.js +337 -0
- package/dist/x402/client.js.map +1 -0
- package/dist/x402/hub.d.ts +79 -0
- package/dist/x402/hub.d.ts.map +1 -0
- package/dist/x402/hub.js +164 -0
- package/dist/x402/hub.js.map +1 -0
- package/dist/x402/index.d.ts +27 -0
- package/dist/x402/index.d.ts.map +1 -0
- package/dist/x402/index.js +27 -0
- package/dist/x402/index.js.map +1 -0
- package/dist/x402/proxy.d.ts +162 -0
- package/dist/x402/proxy.d.ts.map +1 -0
- package/dist/x402/proxy.js +198 -0
- package/dist/x402/proxy.js.map +1 -0
- package/dist/x402/server.d.ts +162 -0
- package/dist/x402/server.d.ts.map +1 -0
- package/dist/x402/server.js +306 -0
- package/dist/x402/server.js.map +1 -0
- package/dist/x402/wire.d.ts +104 -0
- package/dist/x402/wire.d.ts.map +1 -0
- package/dist/x402/wire.js +265 -0
- package/dist/x402/wire.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monad's API Hub, read as a list of tools a fronting Service can sell on credit.
|
|
3
|
+
*
|
|
4
|
+
* The Hub fronts pay-per-request providers behind one x402 endpoint,
|
|
5
|
+
* `POST https://x402.monid.ai/v1/run`, and publishes what each provider offers
|
|
6
|
+
* at `https://api.monid.ai/public/v1/endpoints?provider=<provider>`. Every
|
|
7
|
+
* endpoint there carries a display name, a description, a USD price and the
|
|
8
|
+
* networks its payment is accepted on. This module fetches that manifest and
|
|
9
|
+
* reduces it to what `tab_discover` shows: the Hub endpoints as tools of the
|
|
10
|
+
* Service fronting them.
|
|
11
|
+
*
|
|
12
|
+
* ## Prices are the Hub's word, not Tab's
|
|
13
|
+
*
|
|
14
|
+
* A Hub price is a decimal USD figure. The Asset a fronting Service meters in is
|
|
15
|
+
* a six-decimal dollar stablecoin, so the figure is also rendered as base units
|
|
16
|
+
* of one, for a per-call price. A per-result or per-unit price depends on the
|
|
17
|
+
* response and is reported with the rate alone: the metered amount is whatever
|
|
18
|
+
* the upstream's `402` asks for on the day, plus the Service's margin, and the
|
|
19
|
+
* manifest is a catalogue, never a quote.
|
|
20
|
+
*/
|
|
21
|
+
import { type Result } from "../_shared/index.js";
|
|
22
|
+
/** Where the Hub publishes its manifest. */
|
|
23
|
+
export declare const API_HUB_MANIFEST_URL = "https://api.monid.ai/public/v1/endpoints";
|
|
24
|
+
/** The one x402 endpoint every Hub provider is called through. */
|
|
25
|
+
export declare const API_HUB_RUN_URL = "https://x402.monid.ai/v1/run";
|
|
26
|
+
/** How a Hub endpoint is priced. The Hub may add kinds; unknown ones are carried as they came. */
|
|
27
|
+
export type HubPriceType = "PER_CALL" | "PER_RESULT" | "PER_UNIT" | "PER_UNIT_MATRIX" | (string & {});
|
|
28
|
+
export interface HubEndpoint {
|
|
29
|
+
readonly provider: string;
|
|
30
|
+
readonly providerName: string | null;
|
|
31
|
+
/** The provider-relative path, for example `/get_current_weather`. */
|
|
32
|
+
readonly endpoint: string;
|
|
33
|
+
readonly name: string | null;
|
|
34
|
+
readonly description: string | null;
|
|
35
|
+
readonly priceType: HubPriceType;
|
|
36
|
+
/** The manifest's decimal USD figure, as text. Null when the manifest carries none. */
|
|
37
|
+
readonly priceUsd: string | null;
|
|
38
|
+
/** The same figure in six-decimal base units, for a per-call price. Null otherwise. */
|
|
39
|
+
readonly priceBaseUnits: string | null;
|
|
40
|
+
/** CAIP-2 networks the Hub accepts payment on, for example `eip155:143`. */
|
|
41
|
+
readonly networks: readonly string[];
|
|
42
|
+
readonly categories: readonly string[];
|
|
43
|
+
readonly tags: readonly string[];
|
|
44
|
+
}
|
|
45
|
+
export interface HubManifest {
|
|
46
|
+
readonly provider: string;
|
|
47
|
+
readonly endpoints: readonly HubEndpoint[];
|
|
48
|
+
/** What the manifest said it holds for the provider, which may exceed the pages fetched. */
|
|
49
|
+
readonly total: number;
|
|
50
|
+
}
|
|
51
|
+
/** The little of a fetch this module needs. */
|
|
52
|
+
export interface HubFetchResponse {
|
|
53
|
+
readonly status: number;
|
|
54
|
+
json(): Promise<unknown>;
|
|
55
|
+
}
|
|
56
|
+
export type HubFetch = (url: string, init: {
|
|
57
|
+
readonly method: "GET";
|
|
58
|
+
readonly headers: Readonly<Record<string, string>>;
|
|
59
|
+
}) => Promise<HubFetchResponse>;
|
|
60
|
+
export interface FetchHubManifestOptions {
|
|
61
|
+
readonly provider: string;
|
|
62
|
+
/** Defaults to {@link API_HUB_MANIFEST_URL}. */
|
|
63
|
+
readonly manifestUrl?: string;
|
|
64
|
+
readonly fetchImpl?: HubFetch;
|
|
65
|
+
/** Pages followed through the manifest's cursor. Defaults to 5, at 100 endpoints a page. */
|
|
66
|
+
readonly maxPages?: number;
|
|
67
|
+
}
|
|
68
|
+
/** Fetches one provider's manifest, following its cursor. */
|
|
69
|
+
export declare function fetchHubManifest(options: FetchHubManifestOptions): Promise<Result<HubManifest>>;
|
|
70
|
+
/**
|
|
71
|
+
* A decimal USD figure as six-decimal base units, as text.
|
|
72
|
+
*
|
|
73
|
+
* String arithmetic, because the figure came out of JSON as a double and this
|
|
74
|
+
* is the last place it can be turned into an exact integer before it is shown
|
|
75
|
+
* beside a Tab price that always was one. Anything finer than six decimals is
|
|
76
|
+
* rounded up: a catalogue must not understate a price.
|
|
77
|
+
*/
|
|
78
|
+
export declare function usdToBaseUnits(usd: string): string | null;
|
|
79
|
+
//# sourceMappingURL=hub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub.d.ts","sourceRoot":"","sources":["../../src/x402/hub.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAqB,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAK/D,4CAA4C;AAC5C,eAAO,MAAM,oBAAoB,6CAA6C,CAAC;AAE/E,kEAAkE;AAClE,eAAO,MAAM,eAAe,iCAAiC,CAAC;AAE9D,kGAAkG;AAClG,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,iBAAiB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAEtG,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,WAAW,EAAE,CAAC;IAC3C,4FAA4F;IAC5F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,+CAA+C;AAC/C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1B;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAExJ,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC;IAC9B,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,6DAA6D;AAC7D,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CA+DrG;AAmDD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASzD"}
|
package/dist/x402/hub.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monad's API Hub, read as a list of tools a fronting Service can sell on credit.
|
|
3
|
+
*
|
|
4
|
+
* The Hub fronts pay-per-request providers behind one x402 endpoint,
|
|
5
|
+
* `POST https://x402.monid.ai/v1/run`, and publishes what each provider offers
|
|
6
|
+
* at `https://api.monid.ai/public/v1/endpoints?provider=<provider>`. Every
|
|
7
|
+
* endpoint there carries a display name, a description, a USD price and the
|
|
8
|
+
* networks its payment is accepted on. This module fetches that manifest and
|
|
9
|
+
* reduces it to what `tab_discover` shows: the Hub endpoints as tools of the
|
|
10
|
+
* Service fronting them.
|
|
11
|
+
*
|
|
12
|
+
* ## Prices are the Hub's word, not Tab's
|
|
13
|
+
*
|
|
14
|
+
* A Hub price is a decimal USD figure. The Asset a fronting Service meters in is
|
|
15
|
+
* a six-decimal dollar stablecoin, so the figure is also rendered as base units
|
|
16
|
+
* of one, for a per-call price. A per-result or per-unit price depends on the
|
|
17
|
+
* response and is reported with the rate alone: the metered amount is whatever
|
|
18
|
+
* the upstream's `402` asks for on the day, plus the Service's margin, and the
|
|
19
|
+
* manifest is a catalogue, never a quote.
|
|
20
|
+
*/
|
|
21
|
+
import { causeOf, ok, wrap } from "../_shared/index.js";
|
|
22
|
+
import { upstreamError, validationError } from "../errors.js";
|
|
23
|
+
import { asArray, asNumber, asRecord, asString, asStringOrNull, field, isRecord } from "../mcp/json.js";
|
|
24
|
+
/** Where the Hub publishes its manifest. */
|
|
25
|
+
export const API_HUB_MANIFEST_URL = "https://api.monid.ai/public/v1/endpoints";
|
|
26
|
+
/** The one x402 endpoint every Hub provider is called through. */
|
|
27
|
+
export const API_HUB_RUN_URL = "https://x402.monid.ai/v1/run";
|
|
28
|
+
/** Fetches one provider's manifest, following its cursor. */
|
|
29
|
+
export async function fetchHubManifest(options) {
|
|
30
|
+
const provider = options.provider.trim();
|
|
31
|
+
if (provider.length === 0 || !/^[a-z0-9][a-z0-9._-]*$/i.test(provider)) {
|
|
32
|
+
return validationError("HUB_PROVIDER_INVALID", `\`${options.provider}\` is not a Hub provider slug`, {
|
|
33
|
+
details: { provider: options.provider },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const send = options.fetchImpl ?? hostFetch();
|
|
37
|
+
if (send === undefined) {
|
|
38
|
+
return upstreamError("FETCH_UNAVAILABLE", "this host has no global fetch; supply fetchImpl, or run on Node 20.10 or later");
|
|
39
|
+
}
|
|
40
|
+
const base = options.manifestUrl ?? API_HUB_MANIFEST_URL;
|
|
41
|
+
const maxPages = options.maxPages ?? 5;
|
|
42
|
+
const endpoints = [];
|
|
43
|
+
let total = 0;
|
|
44
|
+
let cursor;
|
|
45
|
+
for (let page = 0; page < maxPages; page += 1) {
|
|
46
|
+
const url = pageUrl(base, provider, cursor);
|
|
47
|
+
if (!url.ok)
|
|
48
|
+
return url;
|
|
49
|
+
const fetched = await wrap(async () => send(url.value, { method: "GET", headers: { accept: "application/json" } }), (error) => ({
|
|
50
|
+
category: "UPSTREAM",
|
|
51
|
+
code: "HUB_MANIFEST_UNREACHABLE",
|
|
52
|
+
message: `the API Hub manifest at ${base} did not answer`,
|
|
53
|
+
retryable: true,
|
|
54
|
+
details: { provider },
|
|
55
|
+
cause: causeOf(error),
|
|
56
|
+
}));
|
|
57
|
+
if (!fetched.ok)
|
|
58
|
+
return fetched;
|
|
59
|
+
if (fetched.value.status < 200 || fetched.value.status >= 300) {
|
|
60
|
+
return upstreamError("HUB_MANIFEST_REFUSED", `the API Hub manifest answered ${fetched.value.status} for provider ${provider}`, {
|
|
61
|
+
retryable: fetched.value.status >= 500,
|
|
62
|
+
details: { provider, status: fetched.value.status },
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
const body = await wrap(async () => fetched.value.json(), (error) => ({
|
|
66
|
+
category: "UPSTREAM",
|
|
67
|
+
code: "HUB_MANIFEST_INVALID",
|
|
68
|
+
message: "the API Hub manifest is not JSON",
|
|
69
|
+
retryable: false,
|
|
70
|
+
details: { provider },
|
|
71
|
+
cause: causeOf(error),
|
|
72
|
+
}));
|
|
73
|
+
if (!body.ok)
|
|
74
|
+
return body;
|
|
75
|
+
if (!isRecord(body.value) || !Array.isArray(body.value["items"])) {
|
|
76
|
+
return upstreamError("HUB_MANIFEST_INVALID", "the API Hub manifest carries no `items` array", { details: { provider } });
|
|
77
|
+
}
|
|
78
|
+
total = asNumber(body.value["total"], total);
|
|
79
|
+
for (const item of asArray(body.value["items"])) {
|
|
80
|
+
const endpoint = toHubEndpoint(item, provider);
|
|
81
|
+
if (endpoint !== undefined)
|
|
82
|
+
endpoints.push(endpoint);
|
|
83
|
+
}
|
|
84
|
+
const next = asStringOrNull(body.value["cursor"]);
|
|
85
|
+
if (next === null || next.length === 0)
|
|
86
|
+
break;
|
|
87
|
+
cursor = next;
|
|
88
|
+
}
|
|
89
|
+
return ok({ provider, endpoints, total: Math.max(total, endpoints.length) });
|
|
90
|
+
}
|
|
91
|
+
function pageUrl(base, provider, cursor) {
|
|
92
|
+
try {
|
|
93
|
+
const url = new URL(base);
|
|
94
|
+
url.searchParams.set("provider", provider);
|
|
95
|
+
url.searchParams.set("limit", "100");
|
|
96
|
+
if (cursor !== undefined)
|
|
97
|
+
url.searchParams.set("cursor", cursor);
|
|
98
|
+
return ok(url.toString());
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return validationError("HUB_MANIFEST_URL_INVALID", `\`${base}\` is not an absolute URL`, { details: { manifestUrl: base } });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** One manifest item, or nothing when it names no endpoint. */
|
|
105
|
+
function toHubEndpoint(item, provider) {
|
|
106
|
+
const endpoint = asString(field(item, "endpoint"), "");
|
|
107
|
+
if (endpoint.length === 0)
|
|
108
|
+
return undefined;
|
|
109
|
+
const price = asRecord(field(item, "price"));
|
|
110
|
+
const priceType = asString(price["type"], "PER_CALL");
|
|
111
|
+
const priceUsd = usdText(field(price["amount"], "value"));
|
|
112
|
+
return {
|
|
113
|
+
provider: asString(field(item, "provider"), provider),
|
|
114
|
+
providerName: asStringOrNull(field(item, "providerDisplayName")),
|
|
115
|
+
endpoint,
|
|
116
|
+
name: asStringOrNull(field(item, "displayName")),
|
|
117
|
+
description: asStringOrNull(field(item, "displayDescription")),
|
|
118
|
+
priceType,
|
|
119
|
+
priceUsd,
|
|
120
|
+
priceBaseUnits: priceType === "PER_CALL" && priceUsd !== null ? usdToBaseUnits(priceUsd) : null,
|
|
121
|
+
networks: asArray(field(item, "supportedX402Networks")).map((entry) => asString(entry, "")).filter((entry) => entry.length > 0),
|
|
122
|
+
categories: asArray(field(item, "categories")).map((entry) => asString(entry, "")).filter((entry) => entry.length > 0),
|
|
123
|
+
tags: asArray(field(item, "tags")).map((entry) => asString(entry, "")).filter((entry) => entry.length > 0),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The manifest's price as plain decimal text.
|
|
128
|
+
*
|
|
129
|
+
* A JSON number smaller than a millionth prints with an exponent, `1e-7`, and
|
|
130
|
+
* an exponent is not a price anyone can read or parse into base units. Twelve
|
|
131
|
+
* fixed decimals cover any USD figure the Hub lists, and the trailing zeros go.
|
|
132
|
+
*/
|
|
133
|
+
function usdText(value) {
|
|
134
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
135
|
+
return Number.isInteger(value) ? value.toString(10) : value.toFixed(12).replace(/0+$/, "").replace(/\.$/, "");
|
|
136
|
+
}
|
|
137
|
+
if (typeof value === "string" && /^[0-9]+(\.[0-9]+)?$/.test(value.trim()))
|
|
138
|
+
return value.trim();
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* A decimal USD figure as six-decimal base units, as text.
|
|
143
|
+
*
|
|
144
|
+
* String arithmetic, because the figure came out of JSON as a double and this
|
|
145
|
+
* is the last place it can be turned into an exact integer before it is shown
|
|
146
|
+
* beside a Tab price that always was one. Anything finer than six decimals is
|
|
147
|
+
* rounded up: a catalogue must not understate a price.
|
|
148
|
+
*/
|
|
149
|
+
export function usdToBaseUnits(usd) {
|
|
150
|
+
const match = /^([0-9]+)(?:\.([0-9]+))?$/.exec(usd.trim());
|
|
151
|
+
if (match === null || match[1] === undefined)
|
|
152
|
+
return null;
|
|
153
|
+
const whole = BigInt(match[1]);
|
|
154
|
+
const fraction = (match[2] ?? "").padEnd(6, "0");
|
|
155
|
+
const kept = BigInt(fraction.slice(0, 6));
|
|
156
|
+
const remainder = fraction.slice(6);
|
|
157
|
+
const roundUp = /[1-9]/.test(remainder) ? 1n : 0n;
|
|
158
|
+
return (whole * 1000000n + kept + roundUp).toString(10);
|
|
159
|
+
}
|
|
160
|
+
function hostFetch() {
|
|
161
|
+
const candidate = globalThis.fetch;
|
|
162
|
+
return typeof candidate === "function" ? candidate : undefined;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=hub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub.js","sourceRoot":"","sources":["../../src/x402/hub.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Monad's API Hub, read as a list of tools a fronting Service can sell on credit.\n *\n * The Hub fronts pay-per-request providers behind one x402 endpoint,\n * `POST https://x402.monid.ai/v1/run`, and publishes what each provider offers\n * at `https://api.monid.ai/public/v1/endpoints?provider=<provider>`. Every\n * endpoint there carries a display name, a description, a USD price and the\n * networks its payment is accepted on. This module fetches that manifest and\n * reduces it to what `tab_discover` shows: the Hub endpoints as tools of the\n * Service fronting them.\n *\n * ## Prices are the Hub's word, not Tab's\n *\n * A Hub price is a decimal USD figure. The Asset a fronting Service meters in is\n * a six-decimal dollar stablecoin, so the figure is also rendered as base units\n * of one, for a per-call price. A per-result or per-unit price depends on the\n * response and is reported with the rate alone: the metered amount is whatever\n * the upstream's `402` asks for on the day, plus the Service's margin, and the\n * manifest is a catalogue, never a quote.\n */\n\nimport { causeOf, ok, wrap, type Result } from \"../_shared/index.js\";\n\nimport { upstreamError, validationError } from \"../errors.js\";\nimport { asArray, asNumber, asRecord, asString, asStringOrNull, field, isRecord } from \"../mcp/json.js\";\n\n/** Where the Hub publishes its manifest. */\nexport const API_HUB_MANIFEST_URL = \"https://api.monid.ai/public/v1/endpoints\";\n\n/** The one x402 endpoint every Hub provider is called through. */\nexport const API_HUB_RUN_URL = \"https://x402.monid.ai/v1/run\";\n\n/** How a Hub endpoint is priced. The Hub may add kinds; unknown ones are carried as they came. */\nexport type HubPriceType = \"PER_CALL\" | \"PER_RESULT\" | \"PER_UNIT\" | \"PER_UNIT_MATRIX\" | (string & {});\n\nexport interface HubEndpoint {\n readonly provider: string;\n readonly providerName: string | null;\n /** The provider-relative path, for example `/get_current_weather`. */\n readonly endpoint: string;\n readonly name: string | null;\n readonly description: string | null;\n readonly priceType: HubPriceType;\n /** The manifest's decimal USD figure, as text. Null when the manifest carries none. */\n readonly priceUsd: string | null;\n /** The same figure in six-decimal base units, for a per-call price. Null otherwise. */\n readonly priceBaseUnits: string | null;\n /** CAIP-2 networks the Hub accepts payment on, for example `eip155:143`. */\n readonly networks: readonly string[];\n readonly categories: readonly string[];\n readonly tags: readonly string[];\n}\n\nexport interface HubManifest {\n readonly provider: string;\n readonly endpoints: readonly HubEndpoint[];\n /** What the manifest said it holds for the provider, which may exceed the pages fetched. */\n readonly total: number;\n}\n\n/** The little of a fetch this module needs. */\nexport interface HubFetchResponse {\n readonly status: number;\n json(): Promise<unknown>;\n}\n\nexport type HubFetch = (url: string, init: { readonly method: \"GET\"; readonly headers: Readonly<Record<string, string>> }) => Promise<HubFetchResponse>;\n\nexport interface FetchHubManifestOptions {\n readonly provider: string;\n /** Defaults to {@link API_HUB_MANIFEST_URL}. */\n readonly manifestUrl?: string;\n readonly fetchImpl?: HubFetch;\n /** Pages followed through the manifest's cursor. Defaults to 5, at 100 endpoints a page. */\n readonly maxPages?: number;\n}\n\n/** Fetches one provider's manifest, following its cursor. */\nexport async function fetchHubManifest(options: FetchHubManifestOptions): Promise<Result<HubManifest>> {\n const provider = options.provider.trim();\n if (provider.length === 0 || !/^[a-z0-9][a-z0-9._-]*$/i.test(provider)) {\n return validationError(\"HUB_PROVIDER_INVALID\", `\\`${options.provider}\\` is not a Hub provider slug`, {\n details: { provider: options.provider },\n });\n }\n const send = options.fetchImpl ?? hostFetch();\n if (send === undefined) {\n return upstreamError(\"FETCH_UNAVAILABLE\", \"this host has no global fetch; supply fetchImpl, or run on Node 20.10 or later\");\n }\n const base = options.manifestUrl ?? API_HUB_MANIFEST_URL;\n const maxPages = options.maxPages ?? 5;\n\n const endpoints: HubEndpoint[] = [];\n let total = 0;\n let cursor: string | undefined;\n for (let page = 0; page < maxPages; page += 1) {\n const url = pageUrl(base, provider, cursor);\n if (!url.ok) return url;\n const fetched = await wrap(\n async () => send(url.value, { method: \"GET\", headers: { accept: \"application/json\" } }),\n (error) => ({\n category: \"UPSTREAM\" as const,\n code: \"HUB_MANIFEST_UNREACHABLE\",\n message: `the API Hub manifest at ${base} did not answer`,\n retryable: true,\n details: { provider },\n cause: causeOf(error),\n }),\n );\n if (!fetched.ok) return fetched;\n if (fetched.value.status < 200 || fetched.value.status >= 300) {\n return upstreamError(\"HUB_MANIFEST_REFUSED\", `the API Hub manifest answered ${fetched.value.status} for provider ${provider}`, {\n retryable: fetched.value.status >= 500,\n details: { provider, status: fetched.value.status },\n });\n }\n const body = await wrap(\n async () => fetched.value.json(),\n (error) => ({\n category: \"UPSTREAM\" as const,\n code: \"HUB_MANIFEST_INVALID\",\n message: \"the API Hub manifest is not JSON\",\n retryable: false,\n details: { provider },\n cause: causeOf(error),\n }),\n );\n if (!body.ok) return body;\n if (!isRecord(body.value) || !Array.isArray(body.value[\"items\"])) {\n return upstreamError(\"HUB_MANIFEST_INVALID\", \"the API Hub manifest carries no `items` array\", { details: { provider } });\n }\n total = asNumber(body.value[\"total\"], total);\n for (const item of asArray(body.value[\"items\"])) {\n const endpoint = toHubEndpoint(item, provider);\n if (endpoint !== undefined) endpoints.push(endpoint);\n }\n const next = asStringOrNull(body.value[\"cursor\"]);\n if (next === null || next.length === 0) break;\n cursor = next;\n }\n return ok({ provider, endpoints, total: Math.max(total, endpoints.length) });\n}\n\nfunction pageUrl(base: string, provider: string, cursor: string | undefined): Result<string> {\n try {\n const url = new URL(base);\n url.searchParams.set(\"provider\", provider);\n url.searchParams.set(\"limit\", \"100\");\n if (cursor !== undefined) url.searchParams.set(\"cursor\", cursor);\n return ok(url.toString());\n } catch {\n return validationError(\"HUB_MANIFEST_URL_INVALID\", `\\`${base}\\` is not an absolute URL`, { details: { manifestUrl: base } });\n }\n}\n\n/** One manifest item, or nothing when it names no endpoint. */\nfunction toHubEndpoint(item: unknown, provider: string): HubEndpoint | undefined {\n const endpoint = asString(field(item, \"endpoint\"), \"\");\n if (endpoint.length === 0) return undefined;\n const price = asRecord(field(item, \"price\"));\n const priceType = asString(price[\"type\"], \"PER_CALL\");\n const priceUsd = usdText(field(price[\"amount\"], \"value\"));\n return {\n provider: asString(field(item, \"provider\"), provider),\n providerName: asStringOrNull(field(item, \"providerDisplayName\")),\n endpoint,\n name: asStringOrNull(field(item, \"displayName\")),\n description: asStringOrNull(field(item, \"displayDescription\")),\n priceType,\n priceUsd,\n priceBaseUnits: priceType === \"PER_CALL\" && priceUsd !== null ? usdToBaseUnits(priceUsd) : null,\n networks: asArray(field(item, \"supportedX402Networks\")).map((entry) => asString(entry, \"\")).filter((entry) => entry.length > 0),\n categories: asArray(field(item, \"categories\")).map((entry) => asString(entry, \"\")).filter((entry) => entry.length > 0),\n tags: asArray(field(item, \"tags\")).map((entry) => asString(entry, \"\")).filter((entry) => entry.length > 0),\n };\n}\n\n/**\n * The manifest's price as plain decimal text.\n *\n * A JSON number smaller than a millionth prints with an exponent, `1e-7`, and\n * an exponent is not a price anyone can read or parse into base units. Twelve\n * fixed decimals cover any USD figure the Hub lists, and the trailing zeros go.\n */\nfunction usdText(value: unknown): string | null {\n if (typeof value === \"number\" && Number.isFinite(value) && value >= 0) {\n return Number.isInteger(value) ? value.toString(10) : value.toFixed(12).replace(/0+$/, \"\").replace(/\\.$/, \"\");\n }\n if (typeof value === \"string\" && /^[0-9]+(\\.[0-9]+)?$/.test(value.trim())) return value.trim();\n return null;\n}\n\n/**\n * A decimal USD figure as six-decimal base units, as text.\n *\n * String arithmetic, because the figure came out of JSON as a double and this\n * is the last place it can be turned into an exact integer before it is shown\n * beside a Tab price that always was one. Anything finer than six decimals is\n * rounded up: a catalogue must not understate a price.\n */\nexport function usdToBaseUnits(usd: string): string | null {\n const match = /^([0-9]+)(?:\\.([0-9]+))?$/.exec(usd.trim());\n if (match === null || match[1] === undefined) return null;\n const whole = BigInt(match[1]);\n const fraction = (match[2] ?? \"\").padEnd(6, \"0\");\n const kept = BigInt(fraction.slice(0, 6));\n const remainder = fraction.slice(6);\n const roundUp = /[1-9]/.test(remainder) ? 1n : 0n;\n return (whole * 1_000_000n + kept + roundUp).toString(10);\n}\n\nfunction hostFetch(): HubFetch | undefined {\n const candidate = (globalThis as { fetch?: unknown }).fetch;\n return typeof candidate === \"function\" ? (candidate as HubFetch) : undefined;\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402, the prepaid protocol, as a fallback beside Tab's credit and as an
|
|
3
|
+
* upstream a Tab Service can front.
|
|
4
|
+
*
|
|
5
|
+
* - `wire.ts` is the V2 wire format: the three headers, the codecs from
|
|
6
|
+
* `@x402/core`, and the one selector that decides which `accepts` entry this
|
|
7
|
+
* package can sign.
|
|
8
|
+
* - `client.ts` signs an EIP-3009 authorization with an ethers signer and
|
|
9
|
+
* repeats a request with it. The Tab 402 client and `tab_call` use it when a
|
|
10
|
+
* credit refusal carries `PAYMENT-REQUIRED` and an x402 signer is configured.
|
|
11
|
+
* - `server.ts` builds the requirement a Tab `402` can offer and takes a signed
|
|
12
|
+
* payment through a facilitator: verify, deliver, settle.
|
|
13
|
+
* - `proxy.ts` fronts an x402 upstream: the Service pays it and meters the Agent.
|
|
14
|
+
* - `hub.ts` reads Monad's API Hub manifest so `tab_discover` can list a
|
|
15
|
+
* fronted provider's endpoints as tools.
|
|
16
|
+
*
|
|
17
|
+
* Nothing here throws. The official `@x402/core` is used for types, header
|
|
18
|
+
* codecs and the facilitator HTTP client; the EIP-3009 signing and the
|
|
19
|
+
* fronting logic are this package's own and are documented against the
|
|
20
|
+
* specification in each file.
|
|
21
|
+
*/
|
|
22
|
+
export * from "./wire.js";
|
|
23
|
+
export * from "./client.js";
|
|
24
|
+
export * from "./server.js";
|
|
25
|
+
export * from "./proxy.js";
|
|
26
|
+
export * from "./hub.js";
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/x402/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402, the prepaid protocol, as a fallback beside Tab's credit and as an
|
|
3
|
+
* upstream a Tab Service can front.
|
|
4
|
+
*
|
|
5
|
+
* - `wire.ts` is the V2 wire format: the three headers, the codecs from
|
|
6
|
+
* `@x402/core`, and the one selector that decides which `accepts` entry this
|
|
7
|
+
* package can sign.
|
|
8
|
+
* - `client.ts` signs an EIP-3009 authorization with an ethers signer and
|
|
9
|
+
* repeats a request with it. The Tab 402 client and `tab_call` use it when a
|
|
10
|
+
* credit refusal carries `PAYMENT-REQUIRED` and an x402 signer is configured.
|
|
11
|
+
* - `server.ts` builds the requirement a Tab `402` can offer and takes a signed
|
|
12
|
+
* payment through a facilitator: verify, deliver, settle.
|
|
13
|
+
* - `proxy.ts` fronts an x402 upstream: the Service pays it and meters the Agent.
|
|
14
|
+
* - `hub.ts` reads Monad's API Hub manifest so `tab_discover` can list a
|
|
15
|
+
* fronted provider's endpoints as tools.
|
|
16
|
+
*
|
|
17
|
+
* Nothing here throws. The official `@x402/core` is used for types, header
|
|
18
|
+
* codecs and the facilitator HTTP client; the EIP-3009 signing and the
|
|
19
|
+
* fronting logic are this package's own and are documented against the
|
|
20
|
+
* specification in each file.
|
|
21
|
+
*/
|
|
22
|
+
export * from "./wire.js";
|
|
23
|
+
export * from "./client.js";
|
|
24
|
+
export * from "./server.js";
|
|
25
|
+
export * from "./proxy.js";
|
|
26
|
+
export * from "./hub.js";
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/x402/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC","sourcesContent":["/**\n * x402, the prepaid protocol, as a fallback beside Tab's credit and as an\n * upstream a Tab Service can front.\n *\n * - `wire.ts` is the V2 wire format: the three headers, the codecs from\n * `@x402/core`, and the one selector that decides which `accepts` entry this\n * package can sign.\n * - `client.ts` signs an EIP-3009 authorization with an ethers signer and\n * repeats a request with it. The Tab 402 client and `tab_call` use it when a\n * credit refusal carries `PAYMENT-REQUIRED` and an x402 signer is configured.\n * - `server.ts` builds the requirement a Tab `402` can offer and takes a signed\n * payment through a facilitator: verify, deliver, settle.\n * - `proxy.ts` fronts an x402 upstream: the Service pays it and meters the Agent.\n * - `hub.ts` reads Monad's API Hub manifest so `tab_discover` can list a\n * fronted provider's endpoints as tools.\n *\n * Nothing here throws. The official `@x402/core` is used for types, header\n * codecs and the facilitator HTTP client; the EIP-3009 signing and the\n * fronting logic are this package's own and are documented against the\n * specification in each file.\n */\n\nexport * from \"./wire.js\";\nexport * from \"./client.js\";\nexport * from \"./server.js\";\nexport * from \"./proxy.js\";\nexport * from \"./hub.js\";\n"]}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Buy now, pay later for x402 APIs: a Tab Service fronts a pay-per-request
|
|
3
|
+
* upstream, pays it with the Service operator's own key, and meters the Agent's
|
|
4
|
+
* Open Tab for what it paid.
|
|
5
|
+
*
|
|
6
|
+
* ## The shape
|
|
7
|
+
*
|
|
8
|
+
* ```text
|
|
9
|
+
* Agent --(Tab-Agent)--> fronting proxy --(request)--> x402 upstream
|
|
10
|
+
* <--(402, PAYMENT-REQUIRED)--
|
|
11
|
+
* operator signs EIP-3009 for the quoted amount
|
|
12
|
+
* --(PAYMENT-SIGNATURE)-->
|
|
13
|
+
* <--(200, PAYMENT-RESPONSE)--
|
|
14
|
+
* post-paid plugin meters upstream price + margin onto the Open Tab
|
|
15
|
+
* Agent <--(200, Tab-Charge-*)--
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* The Agent never signs and never holds the upstream's currency. It buys on
|
|
19
|
+
* credit, from a Service it already has a tab with, and settles later exactly
|
|
20
|
+
* as it settles every other Tab charge. The Service is the one taking the
|
|
21
|
+
* upstream's price risk, which is what the margin is for.
|
|
22
|
+
*
|
|
23
|
+
* ## The price is known only after the upstream's 402
|
|
24
|
+
*
|
|
25
|
+
* `tabPostPaid` asks `priceOf(request)` once the response exists, which is
|
|
26
|
+
* after the forward. So the forward records what it paid, keyed by the request
|
|
27
|
+
* object, and {@link X402UpstreamPricing.priceOf} reads it back for the same
|
|
28
|
+
* object. `createTabProxy` hands its `fetchImpl` that request for this reason.
|
|
29
|
+
*
|
|
30
|
+
* ## Before the operator's funds move
|
|
31
|
+
*
|
|
32
|
+
* An upstream paid for a delivery the Agent then cannot be metered for is the
|
|
33
|
+
* operator's loss. `preflight` runs between the upstream's `402` and the
|
|
34
|
+
* signature, with the quoted amount in hand, so a Service can simulate the
|
|
35
|
+
* delivery against `TabBook` and refuse an Agent with no headroom before paying.
|
|
36
|
+
* A refusal is answered at its category's status, `402` for `LIMIT`, and the
|
|
37
|
+
* upstream is not paid.
|
|
38
|
+
*/
|
|
39
|
+
import { type Address, type Bytes32, type Result, type TabError } from "../_shared/index.js";
|
|
40
|
+
import type { AssetRef } from "../payments/strategy.js";
|
|
41
|
+
import { type TabProxy, type TabProxyOptions } from "../proxy/proxy.js";
|
|
42
|
+
import type { MeteredRequest, PriceQuote } from "../server/post-paid.js";
|
|
43
|
+
import { type X402Fetch, type X402PaymentReceipt, type X402Signer } from "./client.js";
|
|
44
|
+
import type { PaymentRequired, PaymentRequirements } from "./wire.js";
|
|
45
|
+
/** What the Service adds on top of the upstream's price. Both parts optional; both default to nothing. */
|
|
46
|
+
export interface X402UpstreamMargin {
|
|
47
|
+
/** Basis points of the upstream amount, rounded down. `500n` is five percent. */
|
|
48
|
+
readonly bps?: bigint;
|
|
49
|
+
/** A flat count of Asset base units per call. */
|
|
50
|
+
readonly flatBaseUnits?: bigint;
|
|
51
|
+
}
|
|
52
|
+
export interface X402UpstreamPricingOptions {
|
|
53
|
+
/** The tool key the fronted calls are metered under, as the applied price list holds it. */
|
|
54
|
+
readonly tool: Bytes32;
|
|
55
|
+
readonly margin?: X402UpstreamMargin;
|
|
56
|
+
/**
|
|
57
|
+
* What one unit of this tool costs on chain, as `ServiceRegistry` holds it.
|
|
58
|
+
*
|
|
59
|
+
* A fronted call's price is not known until the upstream answers, and
|
|
60
|
+
* `TabBook.recordDelivery` refuses any unit price that is not the one in the
|
|
61
|
+
* applied price list. So the varying amount rides in the **unit count**, not
|
|
62
|
+
* in the unit price: a Service publishes a small fixed unit and a call
|
|
63
|
+
* consumes as many of them as it cost. One base unit, the default, makes the
|
|
64
|
+
* charge exact; a coarser unit rounds up, never down, so the Service is
|
|
65
|
+
* never left short by its own rounding.
|
|
66
|
+
*
|
|
67
|
+
* The published price and this number must be the same, or every fronted
|
|
68
|
+
* delivery reverts `PriceListChangedMidCall` and the Service pays the
|
|
69
|
+
* upstream for work it bills nobody.
|
|
70
|
+
*/
|
|
71
|
+
readonly unitBaseUnits?: bigint;
|
|
72
|
+
}
|
|
73
|
+
/** One fronted call's economics: what the operator paid and what the Agent is metered. */
|
|
74
|
+
export interface X402UpstreamCharge {
|
|
75
|
+
readonly upstreamAmount: bigint;
|
|
76
|
+
readonly margin: bigint;
|
|
77
|
+
/** `upstreamAmount + margin`: what lands on the Open Tab. */
|
|
78
|
+
readonly amount: bigint;
|
|
79
|
+
readonly payment: X402PaymentReceipt;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The price book a fronting proxy writes and its post-paid plugin reads.
|
|
83
|
+
*
|
|
84
|
+
* Built once and shared: the plugin takes `priceOf` at construction, and the
|
|
85
|
+
* proxy takes the whole object so it can `record` into it. Keyed weakly by the
|
|
86
|
+
* request, so nothing is retained after the request is gone.
|
|
87
|
+
*/
|
|
88
|
+
export interface X402UpstreamPricing {
|
|
89
|
+
readonly tool: Bytes32;
|
|
90
|
+
/** For `tabPostPaid({ priceOf })`. Nothing when no upstream payment was made for this request. */
|
|
91
|
+
priceOf(request: MeteredRequest): PriceQuote | undefined;
|
|
92
|
+
chargeOf(request: MeteredRequest): X402UpstreamCharge | undefined;
|
|
93
|
+
record(request: MeteredRequest, payment: X402PaymentReceipt): X402UpstreamCharge;
|
|
94
|
+
/** The Agent's price for an upstream amount, margin applied. */
|
|
95
|
+
amountFor(upstreamAmount: bigint): bigint;
|
|
96
|
+
/** What one unit costs on chain: the unit price every quote carries. */
|
|
97
|
+
readonly unitBaseUnits: bigint;
|
|
98
|
+
}
|
|
99
|
+
export declare function createX402UpstreamPricing(options: X402UpstreamPricingOptions): X402UpstreamPricing;
|
|
100
|
+
/** What `preflight` is told before the operator signs. */
|
|
101
|
+
export interface X402PreflightQuote {
|
|
102
|
+
/** The Agent named by `Tab-Agent`, when the request named one. */
|
|
103
|
+
readonly agent: Address | undefined;
|
|
104
|
+
readonly tool: Bytes32;
|
|
105
|
+
/** What the Agent will be metered: upstream amount plus margin. */
|
|
106
|
+
readonly amount: bigint;
|
|
107
|
+
readonly upstreamAmount: bigint;
|
|
108
|
+
readonly requirement: PaymentRequirements;
|
|
109
|
+
readonly required: PaymentRequired;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Where an upstream is paid, when that is not the Service's own chain and Asset.
|
|
113
|
+
*
|
|
114
|
+
* The API Hub takes USDC on Monad Mainnet and nothing else, and a Service on
|
|
115
|
+
* Testnet meters in a Testnet Asset, so the two sides of a fronted call can sit
|
|
116
|
+
* on different chains. This names the paying side. The signer is the one that
|
|
117
|
+
* holds funds there, and defaults to the proxy's own; the amount the Agent is
|
|
118
|
+
* metered is the upstream's base units passed through `pricing`, which is right
|
|
119
|
+
* only when both Assets are six-decimal dollar stablecoins, and a Service that
|
|
120
|
+
* fronts anything else states its own conversion in `pricing`.
|
|
121
|
+
*/
|
|
122
|
+
export interface X402UpstreamPayment {
|
|
123
|
+
readonly chainId: bigint;
|
|
124
|
+
readonly asset: Address;
|
|
125
|
+
readonly signer?: X402Signer;
|
|
126
|
+
}
|
|
127
|
+
export interface X402FrontedProxyOptions extends Omit<TabProxyOptions, "fetchImpl"> {
|
|
128
|
+
/** The Service operator's key: what pays the upstream. */
|
|
129
|
+
readonly signer: X402Signer;
|
|
130
|
+
readonly pricing: X402UpstreamPricing;
|
|
131
|
+
/** The Asset the Service meters in. The upstream is paid in it, on its chain, unless `upstreamPayment` says otherwise. */
|
|
132
|
+
readonly asset: Pick<AssetRef, "chainId" | "address">;
|
|
133
|
+
/** The chain, Asset and key the upstream is paid with, where they differ from the Service's own. */
|
|
134
|
+
readonly upstreamPayment?: X402UpstreamPayment;
|
|
135
|
+
/** The `fetch` the paying client sends with. Defaults to the host's. */
|
|
136
|
+
readonly fetchImpl?: X402Fetch<Response>;
|
|
137
|
+
/** Refuse any upstream price above this many atomic units. Omitted sets no ceiling. */
|
|
138
|
+
readonly maxUpstreamAmount?: bigint;
|
|
139
|
+
/** Runs after the upstream's 402 and before the signature. An `err` stops the payment. */
|
|
140
|
+
readonly preflight?: (quote: X402PreflightQuote, request: Request) => Promise<Result<void>> | Result<void>;
|
|
141
|
+
/** Replaces the response a `preflight` refusal is answered with. */
|
|
142
|
+
readonly onRefused?: (error: TabError, quote: X402PreflightQuote, request: Request) => Response | undefined;
|
|
143
|
+
readonly onPayment?: (receipt: X402PaymentReceipt, request: Request) => void;
|
|
144
|
+
/** Seconds since the epoch, for `validBefore`. A test passes a fixed clock. */
|
|
145
|
+
readonly nowSeconds?: () => number;
|
|
146
|
+
}
|
|
147
|
+
export interface X402FrontedProxy extends TabProxy {
|
|
148
|
+
readonly pricing: X402UpstreamPricing;
|
|
149
|
+
/** Every upstream payment made, oldest first. */
|
|
150
|
+
payments(): readonly X402PaymentReceipt[];
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Builds the fronting proxy: `createTabProxy` with a forward that pays.
|
|
154
|
+
*
|
|
155
|
+
* Everything `createTabProxy` does, hooks, header hygiene, the metering plugin
|
|
156
|
+
* around the forward, streaming of the response, holds. The one thing it gives
|
|
157
|
+
* up is streaming of the *request* body: an upstream that answers `402` has to
|
|
158
|
+
* be sent the same body twice, so a streamed body is read into memory before
|
|
159
|
+
* the first attempt.
|
|
160
|
+
*/
|
|
161
|
+
export declare function createX402FrontedProxy(options: X402FrontedProxyOptions): X402FrontedProxy;
|
|
162
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/x402/proxy.ts"],"names":[],"mappings":"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"}
|