@coinbase/cdp-sdk
Version:
SDK for interacting with the Coinbase Developer Platform Wallet API
461 lines • 18.6 kB
TypeScript
/**
* 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