UNPKG

@coinbase/cdp-sdk

Version:

SDK for interacting with the Coinbase Developer Platform Wallet API

461 lines • 18.6 kB
/** * CDP-powered x402 resource server. * * `createX402Server()` is the primary entry point. It accepts a route * configuration (and optional receiver wallet config), provisions EVM and * Solana receiver wallets automatically, and returns a fully initialized * `X402Server`. * * `X402Server` **extends** `x402HTTPResourceServer` — it is a drop-in * replacement and can be passed anywhere an `x402HTTPResourceServer` is * expected (e.g. `paymentMiddlewareFromHTTPServer`, Hono / Next.js adapters). * * Routes may be supplied in either format: * * **Simplified CDP format** (`CdpRouteConfig`) — just `price` and optional * `description` / `networks` / `paymentFlow`. The server fills in `scheme`, * `payTo`, and all x402 internals automatically. `paymentFlow` is exact-scheme * only (`"authorization"` default, or `"upfront"`) and is applied to every * network the route expands to (Base and Solana when `networks` is omitted). * * **Full x402 format** (`RouteConfig`) — the same `accepts` / `description` * shape accepted by `x402HTTPResourceServer`. Vacant `payTo` fields (`""`) * are filled with the provisioned receiver address for that network family. * * Both formats can be mixed within the same `routes` map. * * The `payToConfig` field controls how the receiver wallet address is resolved: * - `{ type: "eoa" }` (default) — provisions a CDP EVM EOA + Solana account * - `{ type: "smart", ownerAccountName }` — provisions a CDP Smart Contract Wallet * - `{ type: "address", evm, solana }` — uses provided addresses directly, no provisioning * * @example Minimal CDP Dev setup: * ```typescript * import { createX402Server } from "@coinbase/cdp-sdk/x402"; * import { paymentMiddlewareFromHTTPServer } from "@x402/express"; * * // Set: CDP_API_KEY_ID, CDP_API_KEY_SECRET, CDP_WALLET_SECRET * const server = await createX402Server({ * routes: { * "GET /report": { price: "$0.01", description: "AI-generated report" }, * }, * }); * app.use(paymentMiddlewareFromHTTPServer(server)); * console.log("EVM receiver:", server.payToEvmAddress); * console.log("Solana receiver:", server.payToSvmAddress); * ``` * * @example Bring your own addresses (skip wallet provisioning): * ```typescript * const server = await createX402Server({ * routes: { "GET /report": { price: "$0.01" } }, * payToConfig: { type: "address", evm: "0x...", solana: "..." }, * }); * ``` * * @example Full x402 format (interop with x402HTTPResourceServer): * ```typescript * const server = await createX402Server({ * routes: { * "GET /report": { * accepts: [ * { scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: "" }, * { scheme: "exact", price: "$0.01", network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", payTo: "" }, * ], * }, * }, * }); * ``` */ import { x402ResourceServer, x402HTTPResourceServer } from "@x402/core/server"; import type { RouteConfig } from "@x402/core/server"; import type { Address } from "viem"; /** * Default EVM networks (production) — Base mainnet (`eip155:8453`). */ export declare const CDP_SERVER_DEFAULT_EVM_NETWORKS: readonly ["eip155:8453"]; /** * Default Solana networks (production) — Solana mainnet. */ export declare const CDP_SERVER_DEFAULT_SVM_NETWORKS: readonly ["solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"]; /** * Default networks for production: Base mainnet + Solana mainnet. */ export declare const CDP_SERVER_DEFAULT_NETWORKS: readonly string[]; /** * Default EVM networks for development — Base Sepolia (`eip155:84532`). */ export declare const CDP_SERVER_DEVELOPMENT_EVM_NETWORKS: readonly ["eip155:84532"]; /** * Default Solana networks for development — Solana Devnet. */ export declare const CDP_SERVER_DEVELOPMENT_SVM_NETWORKS: readonly ["solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"]; /** * Default networks for development: Base Sepolia + Solana Devnet. */ export declare const CDP_SERVER_DEVELOPMENT_NETWORKS: readonly string[]; /** * Payment scheme identifiers supported by the simplified CDP route format. * * - `"exact"` — (default) Transfer a fixed amount, locked at signing time. * - `"upto"` — Usage-based billing: the client authorizes a maximum amount * and the server settles the actual amount charged (≤ max), via Permit2 on * EVM and a payment channel on Solana. * * Both support EVM and Solana networks. Solana `upto` delegates voucher signing * to the facilitator. */ export type CdpPaymentScheme = "exact" | "upto"; /** * Payment flows supported on the simplified CDP route format. * * The shorthand is exact-scheme only: * - `"authorization"` — (default) verify, run the handler, then settle. * - `"upfront"` — settle on-chain before the handler runs. */ export type CdpPaymentFlow = "authorization" | "upfront"; /** * Simplified CDP-owned route configuration. * * Specifying just `price` (and optionally `description` / `networks` / * `paymentFlow`) is enough for most routes. `createX402Server` automatically * expands this into the full x402 `RouteConfig` format with `scheme`, `payTo`, * and `maxTimeoutSeconds` filled in. * * For routes that need fine-grained control (custom scheme, `extra`, explicit * `payTo`, etc.) pass a full x402 `RouteConfig` instead — both formats are * accepted in the same `routes` map. */ export interface CdpRouteConfig { /** * Payment amount required to access this route, e.g. `"$0.01"`. * Accepts any amount string supported by the x402 protocol. */ price: string; /** Human-readable description of what this route provides. */ description?: string; /** * Payment scheme to use for this route. * * Defaults to `"exact"`. Both `"exact"` and `"upto"` support Base and * Solana out of the box — see {@link CdpPaymentScheme}. */ scheme?: CdpPaymentScheme; /** * Payment flow for this route. Exact-scheme only. * * Defaults to `"authorization"` (the x402 protocol default) when omitted. * `"upfront"` settles on-chain before the route handler runs, and is * stamped onto every payment option this route expands to — including the * default Base and Solana networks when `networks` is omitted. * * Throws if set on a non-`"exact"` scheme. For other schemes, pass a * full x402 route with `accepts[].extra.paymentFlow`. */ paymentFlow?: CdpPaymentFlow; /** * CAIP-2 network identifiers for which the route accepts payments. * Defaults to `CDP_SERVER_DEFAULT_NETWORKS` (Base mainnet + Solana mainnet), * or `CDP_SERVER_DEVELOPMENT_NETWORKS` (Base Sepolia + Solana Devnet) when * `environment` is `"development"`. */ networks?: string[]; /** * Maximum seconds a payment token is valid before expiry. * Defaults to `300` (5 minutes). */ maxTimeoutSeconds?: number; /** * Extension overrides for this route. * * Gas-sponsoring, `bazaar`, and `builder-code` are injected automatically on * EVM routes (`builder-code` always carries the SDK's own service code, plus * the server config's `builderCode` app code when set). Use this field to * override the auto-generated Bazaar or builder-code declaration. */ extensions?: Record<string, unknown>; } /** * Receiver wallet configuration for `createX402Server`. * * Controls how receiver wallet addresses are resolved: * - `"eoa"` — provision a CDP EVM EOA + Solana account (default) * - `"smart"` — provision a CDP Smart Contract Wallet + Solana account * - `"address"` — use provided addresses directly, no provisioning needed */ export type PayToConfig = { /** CDP Server Wallet (EOA). Default when `type` is omitted. */ type: "eoa"; /** * Named CDP account to use as the receiver wallet. * Defaults to `"x402-receiver-wallet-1"`. */ accountName?: string; } | { /** CDP Smart Contract Wallet. */ type: "smart"; /** * Named CDP smart account. Defaults to `"x402-receiver-wallet-1"`. */ accountName?: string; /** * Owner EOA account name. Required for `"smart"` type. */ ownerAccountName: string; } | { /** * Use provided addresses directly. * No wallet provisioning is performed — `CDP_WALLET_SECRET` is not required. * API key credentials (`CDP_API_KEY_ID` / `CDP_API_KEY_SECRET`) are still * needed for the CDP facilitator. * At least one of `evm` or `solana` should be provided, or all routes * must supply explicit `payTo` values in the full x402 `RouteConfig` format. */ type: "address"; /** EVM address to receive payments. */ evm?: Address; /** Solana address to receive payments. */ solana?: string; }; /** * Configuration for `createX402Server()`. * * All credential fields fall back to environment variables, so an empty * object `{}` with a `routes` map is sufficient in most environments. * * Pass `configPath` to load routes (and optionally credentials) from a JSON * file instead of specifying them inline. */ export interface CdpX402ServerConfig { /** * CDP API key ID. * Falls back to `CDP_API_KEY_ID` env var. */ apiKeyId?: string; /** * CDP API key secret. * Falls back to `CDP_API_KEY_SECRET` env var. */ apiKeySecret?: string; /** * CDP wallet secret used to provision the receiver wallet. * Falls back to `CDP_WALLET_SECRET` env var. * Not required when `payToConfig.type` is `"address"`. */ walletSecret?: string; /** * Deployment environment. Controls which networks are used by default. * * - `"production"` (default) — Base mainnet + Solana mainnet. * - `"development"` — Base Sepolia + Solana Devnet. * * Falls back to `CDP_X402_SERVER_ENVIRONMENT` env var. */ environment?: "production" | "development"; /** * Receiver wallet / payTo configuration. * * Defaults to `{ type: "eoa" }` which provisions a CDP Server Wallet (EOA) * named `"x402-receiver-wallet-1"`. * * Use `{ type: "address", evm: "0x...", solana: "..." }` to provide your * own addresses without provisioning a CDP wallet. */ payToConfig?: PayToConfig; /** * Optional [builder code](https://github.com/x402-foundation/x402/blob/main/specs/extensions/builder_code.md) * for on-chain attribution (`a` / app code). * * Every route with an EVM (`eip155:*`) payment option always advertises the * `builder-code` extension with this SDK's own service code (`s`); Solana-only * routes are skipped because the attribution suffix is ERC-8021 EVM calldata. * Setting `builderCode` additionally declares your own app code (`a`) on * those routes. Must match `^[a-z0-9_]{1,32}$`. Override per-route via * `extensions["builder-code"]`. */ builderCode?: string; /** * Payment-protected routes served by this server. * * Map of HTTP method + path pattern → route config. * Keys use the `"METHOD /path"` convention, e.g. `"GET /report"`. * * Each value is either: * - A `CdpRouteConfig` — simplified format, just `price` + optional fields. * - A `RouteConfig` — full x402 format with an `accepts` array/object. * * Both formats can be mixed within the same map. * May be omitted when `configPath` supplies the routes. */ routes?: Record<string, CdpRouteConfig | RouteConfig>; /** * Path to a JSON file whose fields are merged with this inline config. * Inline config takes precedence over file config when both specify the * same field. The file mirrors {@link CdpX402ServerConfig} (minus `configPath`). * * @example * ```json * { * "routes": { * "GET /report": { "price": "$0.01", "description": "AI-generated report" } * } * } * ``` * * A full JSON Schema for the file lives at * `examples/typescript/x402/servers/express/x402.config.schema.json`. * * Security: this file may carry credentials (`apiKeySecret` / `walletSecret`). * Prefer environment variables for credentials and use the file for `routes`; * if secrets are stored here, keep the file out of version control. */ configPath?: string; } /** * A CDP-powered x402 resource server that **extends** `x402HTTPResourceServer`. * * It is a drop-in replacement anywhere an `x402HTTPResourceServer` is * expected — pass it directly to `paymentMiddlewareFromHTTPServer`, Hono / * Next.js adapters, or any other framework integration. * * Use `createX402Server()` (or `X402Server.create()`) to obtain an initialized * instance. The constructor is intentionally private; call the factory instead. * * In addition to the full `x402HTTPResourceServer` surface (`initialize()`, * `processHTTPRequest()`, `processSettlement()`, `requiresPayment()`, etc.) * this class exposes `payToEvmAddress` and `payToSvmAddress` for the * provisioned receiver wallets. */ export declare class X402Server extends x402HTTPResourceServer { /** * EVM address of the receiver wallet. `undefined` when no EVM wallet was * provisioned (no `eip155:*` route, and `payToConfig` did not supply an * `evm` address). */ readonly payToEvmAddress: Address | undefined; /** * Solana address of the provisioned receiver wallet. `undefined` when no * Solana wallet was provisioned (no `solana:*` route, and `payToConfig` did * not supply a `solana` address). */ readonly payToSvmAddress: string | undefined; /** * Owner account name for `"smart"` receiver wallets, otherwise `undefined`. * Only set when `payToConfig.type` is `"smart"`. */ readonly ownerWallet: string | undefined; private _initPromise; /** * Private constructor — use `createX402Server()` or `X402Server.create()` instead. * * @param resourceServer - Initialized `x402ResourceServer` with schemes registered. * @param routes - Resolved `RoutesConfig` with `payTo` and extensions filled in. * @param payToEvmAddress - EVM address of the provisioned receiver wallet, * or `undefined` if none was provisioned. * @param payToSvmAddress - Solana address of the provisioned receiver wallet, * or `undefined` if none was provisioned. * @param ownerWallet - Owner account name for smart wallets, otherwise `undefined`. * @internal */ private constructor(); /** * The underlying `x402ResourceServer` with EVM and Solana schemes registered. * * @returns The `x402ResourceServer` instance used by this server. */ get resourceServer(): x402ResourceServer; /** * Provisions CDP receiver wallets (unless `payToConfig.type` is `"address"`), * resolves routes, constructs the HTTP resource server, and syncs supported * schemes with the CDP facilitator. * * This is the async entry point for `X402Server`. Prefer the module-level * `createX402Server()` wrapper for convenience. * * @param config - Credential, wallet, and route configuration. * @returns A fully initialized `X402Server` instance ready to be passed to * any framework middleware. */ static create(config: CdpX402ServerConfig): Promise<X402Server>; /** * Initializes the underlying resource server (facilitator support sync + * route validation) exactly once. * * `createX402Server()` already calls this before returning, and framework * adapters such as `paymentMiddlewareFromHTTPServer` call `initialize()` * again on startup. The base implementation re-fetches facilitator support * on every call, so this override memoizes the first run to avoid a redundant * facilitator round-trip. The promise is cleared on failure so a later call * can retry. * * @returns A promise that resolves once initialization has completed. */ initialize(): Promise<void>; } /** * Creates and initializes a CDP-powered x402 resource server. * * Returns an `X402Server` which **extends** `x402HTTPResourceServer` and can * be passed directly to `paymentMiddlewareFromHTTPServer` or any other * framework adapter. * * All credential fields fall back to environment variables; an empty `{}` * with a `routes` map is sufficient in most environments. * * Pass `payToConfig: { type: "address", evm: "0x...", solana: "..." }` to * provide your own receiver addresses without provisioning a CDP wallet. * * @param config - Credential, wallet, and route configuration. All credential fields * fall back to environment variables; `routes` is the only required field (or * `configPath` pointing to a JSON file that supplies routes). * @returns A fully initialized `X402Server` ready to be passed to any framework middleware. * @example Minimal setup (auto-provisions receiver wallet): * ```typescript * // Set: CDP_API_KEY_ID, CDP_API_KEY_SECRET, CDP_WALLET_SECRET * const server = await createX402Server({ * routes: { * "GET /report": { price: "$0.01", description: "AI-generated report" }, * }, * }); * app.use(paymentMiddlewareFromHTTPServer(server)); * console.log("EVM receiver:", server.payToEvmAddress); * console.log("Solana receiver:", server.payToSvmAddress); * ``` * * @example Bring your own addresses: * ```typescript * const server = await createX402Server({ * routes: { "GET /report": { price: "$0.01" } }, * payToConfig: { type: "address", evm: "0x1234...", solana: "ABC..." }, * }); * ``` * * @example Exact + upfront payment flow (shorthand; applies to Base and Solana): * ```typescript * const server = await createX402Server({ * routes: { * "GET /report": { price: "$0.01", paymentFlow: "upfront" }, * }, * }); * ``` * * @example Full x402 RouteConfig format with vacant payTo: * ```typescript * const server = await createX402Server({ * routes: { * "GET /report": { * accepts: { scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: "" }, * }, * }, * }); * ``` * * @example Config-file variant: * ```typescript * // x402.config.json: { "routes": { "GET /report": { "price": "$0.01" } } } * const server = await createX402Server({ configPath: "./x402.config.json" }); * ``` */ export declare function createX402Server(config: CdpX402ServerConfig): Promise<X402Server>; export type { RoutesConfig, RouteConfig } from "@x402/core/server"; //# sourceMappingURL=server.d.ts.map