# CDP SDK The Coinbase Developer Platform (CDP) SDK enables developers to programmatically create, manage, and use crypto wallets while relying on CDP to secure private keys. The SDK provides full-featured client libraries for TypeScript, Python, Go, and Rust, supporting both EVM-compatible blockchains (Ethereum, Base, Polygon, etc.) and Solana. Core functionality includes server-managed accounts, smart accounts with Account Abstraction (ERC-4337), transaction signing and sending, token transfers, swaps, faucet requests, and policy-based access controls. The SDK architecture centers around the `CdpClient` class, which is namespaced by blockchain type (`evm` for Ethereum Virtual Machine chains and `solana` for Solana). It supports multiple account types including server-managed EOA accounts, smart accounts with gas sponsorship capabilities, and delegated accounts for end-user wallet management. The SDK integrates seamlessly with popular libraries like Viem for Ethereum interactions and @solana/kit for Solana operations. ## Client Initialization The main entry point for the SDK is the `CdpClient` class, which requires CDP API credentials and optionally a wallet secret for write operations. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; // Using environment variables (CDP_API_KEY_ID, CDP_API_KEY_SECRET, CDP_WALLET_SECRET) const cdp = new CdpClient(); // Or with explicit configuration const cdp = new CdpClient({ apiKeyId: "your-api-key-id", apiKeySecret: "your-api-key-secret", walletSecret: "your-wallet-secret", }); ``` ## EVM Account Creation Creates a new CDP-managed EVM account with secure private key storage on Coinbase's infrastructure. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); // Create a basic account const account = await cdp.evm.createAccount(); console.log("Account address:", account.address); // Create with a name for easy retrieval const namedAccount = await cdp.evm.createAccount({ name: "MyWallet" }); // Create with idempotency key to prevent duplicates const idempotentAccount = await cdp.evm.createAccount({ name: "PaymentWallet", idempotencyKey: "unique-request-id-123", }); ``` ## EVM Account Retrieval Retrieves existing EVM accounts by address or name, with support for get-or-create patterns. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); // Get by address const accountByAddress = await cdp.evm.getAccount({ address: "0x1234567890123456789012345678901234567890", }); // Get by name const accountByName = await cdp.evm.getAccount({ name: "MyWallet" }); // Get or create (idempotent) const account = await cdp.evm.getOrCreateAccount({ name: "PaymentWallet" }); // List all accounts with pagination let page = await cdp.evm.listAccounts({ pageSize: 10 }); while (page.nextPageToken) { page = await cdp.evm.listAccounts({ pageToken: page.nextPageToken }); } ``` ## EVM Smart Account Creation Creates ERC-4337 smart accounts that support batched transactions, gas sponsorship, and advanced features like spend permissions. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; const cdp = new CdpClient(); // Create with CDP server account as owner const serverAccount = await cdp.evm.createAccount(); const smartAccount = await cdp.evm.createSmartAccount({ owner: serverAccount, }); // Create with local Viem account as owner const privateKey = generatePrivateKey(); const localOwner = privateKeyToAccount(privateKey); const smartAccountWithLocalOwner = await cdp.evm.createSmartAccount({ owner: localOwner, }); // Enable spend permissions for third-party spending const smartAccountWithSpendPermissions = await cdp.evm.createSmartAccount({ owner: serverAccount, enableSpendPermissions: true, }); console.log("Smart Account Address:", smartAccount.address); ``` ## Send EVM Transaction Signs and sends transactions on EVM networks with automatic nonce management and gas estimation. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; import { parseEther, serializeTransaction } from "viem"; import { baseSepolia } from "viem/chains"; const cdp = new CdpClient(); const account = await cdp.evm.createAccount(); // Send with transaction request object const { transactionHash } = await cdp.evm.sendTransaction({ address: account.address, network: "base-sepolia", transaction: { to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8", value: parseEther("0.001"), }, }); // Send with RLP-encoded transaction const serialized = serializeTransaction({ to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8", value: parseEther("0.001"), chainId: baseSepolia.id, }); const result = await cdp.evm.sendTransaction({ address: account.address, network: "base-sepolia", transaction: serialized, }); console.log("Transaction Hash:", result.transactionHash); ``` ## Send User Operation (Smart Account) Sends ERC-4337 user operations from smart accounts with optional gas sponsorship via paymasters. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; import { parseEther } from "viem"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; const cdp = new CdpClient(); const owner = privateKeyToAccount(generatePrivateKey()); const smartAccount = await cdp.evm.createSmartAccount({ owner }); // Send user operation with multiple calls (batched) const { userOpHash, status } = await cdp.evm.sendUserOperation({ smartAccount, network: "base-sepolia", calls: [ { to: "0x0000000000000000000000000000000000000000", value: parseEther("0.000001"), data: "0x", }, { to: "0x0000000000000000000000000000000000000001", value: parseEther("0.000001"), data: "0x", }, ], // Optional: use custom paymaster for gas sponsorship // paymasterUrl: "https://your-paymaster.com", }); // Wait for confirmation const receipt = await cdp.evm.waitForUserOperation({ smartAccountAddress: smartAccount.address, userOpHash, }); console.log("User Op Hash:", userOpHash); console.log("Transaction Hash:", receipt.transactionHash); ``` ## EVM Token Transfer Transfers native tokens or ERC-20 tokens between accounts using the account's transfer method. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; import { createPublicClient, http } from "viem"; import { baseSepolia } from "viem/chains"; const cdp = new CdpClient(); const sender = await cdp.evm.getOrCreateAccount({ name: "Sender" }); const receiver = await cdp.evm.getOrCreateAccount({ name: "Receiver" }); // Request test tokens from faucet await cdp.evm.requestFaucet({ address: sender.address, network: "base-sepolia", token: "usdc", }); await cdp.evm.requestFaucet({ address: sender.address, network: "base-sepolia", token: "eth", }); // Transfer USDC (0.01 USDC = 10000 with 6 decimals) const { transactionHash } = await sender.transfer({ to: receiver, amount: 10000n, token: "usdc", network: "base-sepolia", }); const publicClient = createPublicClient({ chain: baseSepolia, transport: http(), }); const receipt = await publicClient.waitForTransactionReceipt({ hash: transactionHash, }); console.log("Transfer status:", receipt.status); console.log("Explorer:", `https://sepolia.basescan.org/tx/${transactionHash}`); ``` ## EVM Token Swap Gets swap quotes and executes token swaps on EVM networks with slippage protection. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; import { parseUnits, formatUnits, type Address } from "viem"; const cdp = new CdpClient(); const account = await cdp.evm.getOrCreateAccount({ name: "SwapAccount" }); const WETH = "0x4200000000000000000000000000000000000006"; const USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; // Get swap price (indicative quote) const price = await cdp.evm.getSwapPrice({ network: "base", fromToken: WETH, toToken: USDC, fromAmount: parseUnits("0.1", 18), taker: account.address, }); if (price.liquidityAvailable) { console.log("Expected output:", formatUnits(BigInt(price.toAmount), 6), "USDC"); } // Create executable swap quote const swapQuote = await cdp.evm.createSwapQuote({ network: "base", fromToken: WETH, toToken: USDC, fromAmount: parseUnits("0.1", 18), taker: account.address, slippageBps: 100, // 1% slippage tolerance }); if (swapQuote.liquidityAvailable) { // Execute the swap using account method const result = await account.swap({ swapQuote }); console.log("Swap transaction:", result.transactionHash); } ``` ## EVM Message Signing Signs messages and typed data (EIP-191 and EIP-712) for authentication and off-chain verification. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); const account = await cdp.evm.createAccount(); // Sign EIP-191 message const messageSignature = await cdp.evm.signMessage({ address: account.address, message: "Hello, Coinbase!", }); console.log("Message Signature:", messageSignature.signature); // Sign raw hash const hashSignature = await cdp.evm.signHash({ address: account.address, hash: "0x1234567890123456789012345678901234567890123456789012345678901234", }); // Sign EIP-712 typed data const typedDataSignature = await cdp.evm.signTypedData({ address: account.address, domain: { name: "MyApp", version: "1", chainId: 8453, verifyingContract: "0x1234567890123456789012345678901234567890", }, types: { Person: [ { name: "name", type: "string" }, { name: "wallet", type: "address" }, ], }, primaryType: "Person", message: { name: "Alice", wallet: "0x1234567890123456789012345678901234567890", }, }); console.log("Typed Data Signature:", typedDataSignature.signature); ``` ## EVM Faucet Request Requests testnet tokens from CDP's faucet service for development and testing. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); const account = await cdp.evm.createAccount(); // Request testnet ETH const ethFaucet = await cdp.evm.requestFaucet({ address: account.address, network: "base-sepolia", token: "eth", }); console.log("ETH Faucet TX:", ethFaucet.transactionHash); // Request testnet USDC const usdcFaucet = await cdp.evm.requestFaucet({ address: account.address, network: "base-sepolia", token: "usdc", }); console.log("USDC Faucet TX:", usdcFaucet.transactionHash); ``` ## EVM Token Balances Lists token balances for any EVM address across supported networks. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); const balances = await cdp.evm.listTokenBalances({ address: "0x1234567890123456789012345678901234567890", network: "base-sepolia", }); for (const balance of balances.balances) { console.log(`${balance.token.symbol}: ${balance.amount.amount}`); } // With pagination let page = await cdp.evm.listTokenBalances({ address: "0x1234567890123456789012345678901234567890", network: "base-sepolia", pageSize: 10, }); while (page.nextPageToken) { page = await cdp.evm.listTokenBalances({ address: "0x1234567890123456789012345678901234567890", network: "base-sepolia", pageToken: page.nextPageToken, }); } ``` ## Account Import and Export Imports existing private keys into CDP or exports CDP-managed keys for backup or migration. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); // Import an existing EVM private key const importedAccount = await cdp.evm.importAccount({ privateKey: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", name: "ImportedWallet", }); console.log("Imported Address:", importedAccount.address); // Export a CDP account's private key (store securely!) const exportedPrivateKey = await cdp.evm.exportAccount({ address: importedAccount.address, }); console.log("Exported Key (hex, no 0x prefix):", exportedPrivateKey); // Export by name const exportedByName = await cdp.evm.exportAccount({ name: "ImportedWallet", }); ``` ## Solana Account Management Creates and manages Solana accounts with CDP's secure key infrastructure. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); // Create Solana account const account = await cdp.solana.createAccount(); console.log("Solana Address:", account.address); // Create with name const namedAccount = await cdp.solana.createAccount({ name: "MySolanaWallet" }); // Get or create (idempotent) const wallet = await cdp.solana.getOrCreateAccount({ name: "PaymentWallet" }); // List all Solana accounts const { accounts, nextPageToken } = await cdp.solana.listAccounts(); for (const acc of accounts) { console.log(acc.address); } // Import existing Solana key (base58 encoded) const imported = await cdp.solana.importAccount({ privateKey: "3Kzj...", // base58 private key name: "ImportedSolana", }); // Export Solana key const exportedKey = await cdp.solana.exportAccount({ address: imported.address, }); ``` ## Solana Token Transfer Transfers SOL or SPL tokens on Solana networks with automatic transaction building. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; import { createSolanaRpc, address as solanaAddress } from "@solana/kit"; const cdp = new CdpClient(); const LAMPORTS_PER_SOL = 1_000_000_000; const rpc = createSolanaRpc("https://api.devnet.solana.com"); const sender = await cdp.solana.getOrCreateAccount({ name: "Sender" }); // Request testnet SOL await sender.requestFaucet({ token: "sol" }); // Transfer SOL const { signature } = await sender.transfer({ to: "3KzDtddx4i53FBkvCzuDmRbaMozTZoJBb1TToWhz3JfE", amount: BigInt(0.001 * LAMPORTS_PER_SOL), token: "sol", network: "devnet", }); console.log("Transaction Signature:", signature); console.log(`Explorer: https://explorer.solana.com/tx/${signature}?cluster=devnet`); ``` ## Solana Transaction Signing Signs and sends Solana transactions with support for versioned transactions. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; import { address as solanaAddress, appendTransactionMessageInstructions, compileTransaction, createNoopSigner, createSolanaRpc, createTransactionMessage, getBase64EncodedWireTransaction, pipe, setTransactionMessageFeePayer, setTransactionMessageLifetimeUsingBlockhash, } from "@solana/kit"; import { getTransferSolInstruction } from "@solana-program/system"; const cdp = new CdpClient(); const account = await cdp.solana.createAccount(); const rpc = createSolanaRpc("https://api.devnet.solana.com"); const { value: { blockhash, lastValidBlockHeight } } = await rpc.getLatestBlockhash().send(); // Build transaction const txMsg = pipe( createTransactionMessage({ version: 0 }), (tx) => setTransactionMessageFeePayer(solanaAddress(account.address), tx), (tx) => setTransactionMessageLifetimeUsingBlockhash({ blockhash, lastValidBlockHeight }, tx), (tx) => appendTransactionMessageInstructions([ getTransferSolInstruction({ source: createNoopSigner(solanaAddress(account.address)), destination: solanaAddress("3KzDtddx4i53FBkvCzuDmRbaMozTZoJBb1TToWhz3JfE"), amount: 10000n, }), ], tx), ); const transaction = getBase64EncodedWireTransaction(compileTransaction(txMsg)); // Sign the transaction const { signedTransaction } = await cdp.solana.signTransaction({ address: account.address, transaction, }); // Or send directly with CDP sponsorship const result = await cdp.solana.sendTransaction({ network: "solana-devnet", transaction, useCdpSponsor: true, // CDP pays transaction fees }); console.log("Signature:", result.signature); ``` ## Policy Management Creates and manages policies to control account operations with rules for transaction limits, address allowlists, and more. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); // Create an account-level policy const policy = await cdp.policies.createPolicy({ policy: { scope: "account", description: "Transaction limits and allowlist", rules: [ { action: "accept", operation: "signEvmTransaction", criteria: [ { type: "ethValue", ethValue: "1000000000000000000", // 1 ETH max operator: "<=", }, { type: "evmAddress", addresses: ["0x000000000000000000000000000000000000dEaD"], operator: "in", }, ], }, { action: "accept", operation: "sendEvmTransaction", criteria: [ { type: "ethValue", ethValue: "1000000000000000000", operator: "<=", }, { type: "evmNetwork", networks: ["base", "base-sepolia"], operator: "in", }, ], }, { action: "accept", operation: "signEvmMessage", criteria: [{ type: "evmMessage", match: ".*" }], }, ], }, }); console.log("Policy ID:", policy.id); // Apply policy to account const account = await cdp.evm.createAccount({ accountPolicy: policy.id, }); // List policies const { policies } = await cdp.policies.listPolicies({ scope: "account" }); // Update policy await cdp.policies.updatePolicy({ id: policy.id, policy: { description: "Updated limits", rules: policy.rules, }, }); // Delete policy await cdp.policies.deletePolicy({ id: policy.id }); ``` ## End User Management Creates and manages end user accounts with delegated signing capabilities for consumer-facing applications. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); // Create an end user with authentication const endUser = await cdp.endUser.createEndUser({ authenticationMethods: [ { type: "email", email: "user@example.com" } ], evmAccount: { createSmartAccount: false }, }); console.log("User ID:", endUser.userId); // Add EVM account to existing user const evmResult = await cdp.endUser.addEndUserEvmAccount({ userId: endUser.userId, }); console.log("EVM Address:", evmResult.evmAccount.address); // Add smart account const smartResult = await cdp.endUser.addEndUserEvmSmartAccount({ userId: endUser.userId, enableSpendPermissions: true, }); // Add Solana account const solanaResult = await cdp.endUser.addEndUserSolanaAccount({ userId: endUser.userId, }); // Sign transaction on behalf of end user const signResult = await cdp.endUser.signEvmTransaction({ userId: endUser.userId, address: evmResult.evmAccount.address, transaction: "0x02...", }); // Send transaction on behalf of end user const sendResult = await cdp.endUser.sendEvmTransaction({ userId: endUser.userId, address: evmResult.evmAccount.address, transaction: "0x02...", network: "base-sepolia", }); // List all end users const { endUsers } = await cdp.endUser.listEndUsers({ pageSize: 20 }); ``` ## Webhook Subscriptions Creates webhook subscriptions to receive real-time notifications for wallet events. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); const subscription = await cdp.webhooks.createSubscription({ description: "Monitor wallet transactions", eventTypes: [ "wallet.transaction.pending", "wallet.transaction.confirmed", "wallet.transaction.failed", "wallet.transaction.created", "wallet.transaction.broadcast", "wallet.transaction.replaced", "wallet.transaction.signed", "wallet.typed_data.signed", "wallet.message.signed", "wallet.hash.signed", "wallet.delegation.created", "wallet.delegation.revoked", ], targetUrl: "https://your-app.com/webhook", targetHeaders: { "X-Custom-Header": "your-value", }, isEnabled: true, }); console.log("Subscription ID:", subscription.subscriptionId); console.log("Secret:", subscription.secret); // Use to verify webhook signatures ``` ## EIP-7702 Delegation Upgrades EOA accounts with smart account capabilities using EIP-7702 delegation. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; const cdp = new CdpClient(); const account = await cdp.evm.createAccount(); // Create EIP-7702 delegation const delegation = await cdp.evm.createEvmEip7702Delegation({ address: account.address, network: "base-sepolia", enableSpendPermissions: false, }); console.log("Delegation Operation ID:", delegation.delegationOperationId); // Wait for delegation to complete const operation = await cdp.evm.waitForEvmEip7702DelegationOperationStatus({ delegationOperationId: delegation.delegationOperationId, }); console.log("Delegation Status:", operation.status); // "COMPLETED" ``` ## Spend Permissions Creates and manages spend permissions allowing third parties to spend from smart accounts. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; const cdp = new CdpClient(); const owner = privateKeyToAccount(generatePrivateKey()); const smartAccount = await cdp.evm.createSmartAccount({ owner, enableSpendPermissions: true, }); // Create spend permission const userOp = await cdp.evm.createSpendPermission({ network: "base-sepolia", spendPermission: { account: smartAccount.address, spender: "0x1234567890123456789012345678901234567890", token: "0x036CbD53842c5426634e7929541eC2318f3dCF7e", // USDC allowance: 1000000n, // 1 USDC period: 86400, // 1 day start: Math.floor(Date.now() / 1000), end: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60, // 30 days salt: 0n, extraData: "0x", }, }); // List spend permissions const permissions = await cdp.evm.listSpendPermissions({ address: smartAccount.address, }); // Revoke spend permission await cdp.evm.revokeSpendPermission({ address: smartAccount.address, permissionHash: "0x...", network: "base-sepolia", }); ``` ## Network-Scoped Accounts Uses accounts scoped to specific networks for simplified interactions with Viem integration. ```typescript import { CdpClient } from "@coinbase/cdp-sdk"; import { parseEther } from "viem"; const cdp = new CdpClient(); const account = await cdp.evm.createAccount(); // Scope account to a specific network const baseSepoliaAccount = await account.useNetwork("base-sepolia"); // Request faucet using scoped account const { transactionHash: faucetTx } = await baseSepoliaAccount.requestFaucet({ token: "eth", }); // Wait for transaction using scoped account's client await baseSepoliaAccount.waitForTransactionReceipt({ hash: faucetTx }); // Send transaction (network is implicit) const { transactionHash } = await baseSepoliaAccount.sendTransaction({ transaction: { to: "0x0000000000000000000000000000000000000000", value: parseEther("0.000001"), }, }); await baseSepoliaAccount.waitForTransactionReceipt({ hash: transactionHash }); console.log(`TX: https://sepolia.basescan.org/tx/${transactionHash}`); ``` ## Summary The CDP SDK is designed for building crypto applications that require secure wallet management without the complexity of key custody. Primary use cases include payment processing systems, trading bots, DeFi integrations, NFT marketplaces, and any application requiring programmatic blockchain interactions. The SDK's server-managed accounts are ideal for backend services, while smart accounts with ERC-4337 support enable gasless transactions and batched operations for better user experiences. Integration patterns typically involve initializing the `CdpClient` with API credentials, creating or retrieving accounts based on your application's needs, and using the typed methods for blockchain operations. The SDK handles complexity like nonce management, gas estimation, and transaction signing automatically. For consumer applications, the end user API enables delegated wallet management while maintaining user custody semantics. Webhooks provide real-time event notifications for transaction monitoring and application state synchronization.