CDP Frontend SDK
    Preparing search index...

    Module @coinbase/cdp-core - v0.0.47

    This package contains core business logic for the CDP Frontend SDK. It is intended for non-React applications that use pure Typescript.

    This guide will help you get started with @coinbase/cdp-core. You'll learn how to install the package, initialize the SDK, and make your first API call.

    First, add the package to your project using your preferred package manager.

    # With pnpm
    pnpm add @coinbase/cdp-core

    # With yarn
    yarn add @coinbase/cdp-core

    # With npm
    npm install @coinbase/cdp-core
    1. Sign in or create an account on the CDP Portal
    2. On your dashboard, select a project from the dropdown at the at the top, and copy the Project ID
    1. Navigate to the Embedded Wallet Configuration in CDP Portal, and click Add origin to include your local app
    2. Enter the origin of your locally running app - e.g., http://localhost:3000
    3. Click Add origin again to save your changes

    Before calling any methods in the SDK, you must first initialize it:

    import { Config, initialize } from "@coinbase/cdp-core";

    const config: Config = {
    // Copy and paste your project ID here.
    projectId: "your-project-id",
    }

    await initialize(config);

    You can configure the SDK to create different types of accounts for new users:

    Smart Account Configuration:

    const config: Config = {
    projectId: "your-project-id",
    ethereum: {
    createOnLogin: "smart", // Creates Smart Accounts instead of EOAs
    },
    }

    await initialize(config);

    When ethereum.createOnLogin is set to "smart", the SDK will:

    1. Create an EOA (Externally Owned Account) first
    2. Use that EOA as the owner to create a Smart Account
    3. Both accounts will be available on the user object

    Solana Account Configuration:

    const config: Config = {
    projectId: "your-project-id",
    solana: {
    createOnLogin: true, // Creates Solana accounts
    },
    }

    await initialize(config);

    When solana.createOnLogin is set to true, the SDK will:

    1. Create a Solana account for new users
    2. The Solana account will be available on the solanaAccounts property

    You're now ready to start calling the APIs provided by the package! The following code signs in an end user:

    import { signInWithEmail, verifyEmailOTP } from "@coinbase/cdp-core";

    // Send an email to user@example.com with a One Time Password (OTP).
    const authResult = await signInWithEmail({
    email: "user@example.com"
    });

    // Input the OTP sent to user@example.com.
    const verifyResult = await verifyEmailOTP({
    flowId: authResult.flowId,
    otp: "123456", // Hardcoded for convenience here.
    });

    // Get the authenticated end user.
    const user = verifyResult.user;

    Once the end user has signed in, you can display their information in your application:

    import { getCurrentUser, isSignedIn } from "@coinbase/cdp-core";

    // Check if user is signed in
    const signedIn = await isSignedIn();

    if (signedIn) {
    // Get the user's information
    const user = await getCurrentUser();
    console.log("User ID:", user.userId);

    // Display different account types based on configuration
    if (user.evmAccounts?.length > 0) {
    console.log("EVM Accounts (EOAs):", user.evmAccounts);
    }
    if (user.evmSmartAccounts?.length > 0) {
    console.log("EVM Smart Accounts:", user.evmSmartAccounts);
    }
    if (user.solanaAccounts?.length > 0) {
    console.log("Solana Accounts:", user.solanaAccounts);
    }

    // Find the user's email address (if they logged in with email/otp)
    const email = user.authenticationMethods.email?.email;
    console.log("Email Address:", email);
    }

    We support signing and sending an EVM transaction in a single call on the following networks:

    • Base
    • Base Sepolia
    • Ethereum
    • Ethereum Sepolia
    • Avalanche
    • Arbitrum
    • Optimism
    • Polygon
    import { sendEvmTransaction, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const evmAccount = user.evmAccounts[0];

    const result = await sendEvmTransaction({
    evmAccount,
    transaction: {
    to: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    value: 100000000000000n, // 0.0001 ETH in wei
    nonce: 0,
    gas: 21000n,
    maxFeePerGas: 30000000000n,
    maxPriorityFeePerGas: 1000000000n,
    chainId: 84532, // Base Sepolia
    type: "eip1559",
    }
    });

    console.log("Transaction Hash:", result.transactionHash);

    For EVM networks other than those supported by the CDP APIs, your end user must sign the transaction, and then you must broadcast the transaction yourself. This example uses the public client from viem to broadcast the transaction.

    import { signEvmTransaction, getCurrentUser } from "@coinbase/cdp-core";
    import { http, createPublicClient } from "viem";
    import { tron } from "viem/chains";

    const user = await getCurrentUser();
    const evmAccount = user.evmAccounts[0];

    // Sign the transaction
    const { signedTransaction } = await signEvmTransaction({
    evmAccount,
    transaction: {
    to: "0x...",
    value: 100000000000000n,
    nonce: 0,
    gas: 21000n,
    maxFeePerGas: 30000000000n,
    maxPriorityFeePerGas: 1000000000n,
    chainId: 728126428, // Tron
    type: "eip1559",
    }
    });

    // Broadcast signed transaction to non-Base chain
    const client = createPublicClient({
    chain: tron,
    transport: http()
    });

    const hash = await client.sendRawTransaction({
    serializedTransaction: signedTransaction
    });

    Smart Accounts provide advanced account abstraction features, including user operations and paymaster support.

    Spend permissions allow Smart Accounts to delegate spending authority to other accounts within specified limits and time periods. This enables use cases like subscription payments, automated DeFi strategies, and automatic topping up of AI agent funds.

    import { createSpendPermission, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const smartAccount = user.evmSmartAccounts[0];

    const result = await createSpendPermission({
    evmSmartAccount: smartAccount,
    network: "base-sepolia",
    spender: "0x742D35Cc6634C0532925a3b8D6Ec6F1C2b9c1E46", // Address that can spend tokens
    token: "eth", // Token symbol ("eth", "usdc") or contract address
    allowance: "1000000000000000000", // 1 ETH in wei
    period: 86400, // 24 hours in seconds
    start: new Date(), // Start time (optional, defaults to now)
    end: new Date(Date.now() + 86400 * 30 * 1000), // End time (optional, defaults to no expiration)
    useCdpPaymaster: true, // Use CDP paymaster for gas sponsorship
    });

    console.log("User Operation Hash:", result.userOperationHash);

    You can also use periodInDays for a more human-friendly API:

    const result = await createSpendPermission({
    evmSmartAccount: smartAccount,
    network: "base-sepolia",
    spender: "0x742D35Cc6634C0532925a3b8D6Ec6F1C2b9c1E46",
    token: "usdc", // USDC token
    allowance: "10000000", // 10 USDC (6 decimals)
    periodInDays: 7, // Weekly recurring allowance
    useCdpPaymaster: true
    });

    Retrieve all spend permissions for a Smart Account:

    import { listSpendPermissions, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const smartAccount = user.evmSmartAccounts[0];

    const result = await listSpendPermissions({
    evmSmartAccount: smartAccount,
    network: "base-sepolia",
    pageSize: 10
    });

    console.log("Found", result.spendPermissions.length, "spend permissions");
    for (const permission of result.spendPermissions) {
    console.log("Permission:", permission.permissionHash, "Revoked:", permission.revoked);
    console.log("Spender:", permission.permission.spender);
    console.log("Token:", permission.permission.token);
    console.log("Allowance:", permission.permission.allowance);
    }

    // Paginate through results if needed
    if (result.hasNextPage) {
    const nextPage = await listSpendPermissions({
    evmSmartAccount: smartAccount,
    network: "base-sepolia",
    pageToken: result.nextPageToken
    });
    }

    Revoke a spend permission for a Smart Account:

    import { revokeSpendPermission, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const smartAccount = user.evmSmartAccounts[0];

    const result = await revokeSpendPermission({
    evmSmartAccount: smartAccount,
    network: "base-sepolia",
    permissionHash: "0x5678...",
    useCdpPaymaster: true
    });

    console.log("User Operation Hash:", result.userOperationHash);

    When your application is configured with solana: { createOnLogin: true }, you can sign Solana transactions:

    import { signSolanaTransaction, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const solanaAccount = user.solanaAccounts[0];

    const result = await signSolanaTransaction({
    solanaAccount,
    transaction: "base64-encoded-solana-transaction" // Your Solana transaction here
    });

    console.log("Signed Transaction:", result.signedTransaction);
    // The signedTransaction can now be broadcast to the Solana network

    You can also sign arbitrary messages with Solana accounts:

    import { signSolanaMessage, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const solanaAccount = user.solanaAccounts[0];

    const message = Buffer.from("Hello, Solana!", "utf8").toString("base64");
    const result = await signSolanaMessage({
    solanaAccount,
    message // Base64 encoded message to sign
    });

    console.log("Message Signature:", result.signature);
    // The signature can be used for authentication or verification purposes

    You can sign and send a Solana transaction in a single call on the following Solana networks:

    • Solana Mainnet
    • Solana Devnet
    import { sendSolanaTransaction, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const solanaAccount = user.solanaAccounts[0];

    const result = await sendSolanaTransaction({
    solanaAccount,
    network: "solana-devnet", // or "solana" for mainnet
    transaction: "base64-encoded-solana-transaction" // Your Solana transaction here
    });

    console.log("Transaction Signature:", result.transactionSignature);
    // The transaction has been broadcast to the Solana network

    Send user operations from a Smart Account:

    import { sendUserOperation, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const smartAccount = user.evmSmartAccounts[0];

    const result = await sendUserOperation({
    evmSmartAccount: smartAccount,
    network: "base-sepolia",
    calls: [
    {
    to: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    value: 1000000000000000000n, // 1 ETH in wei
    data: "0x", // Optional contract interaction data
    }
    ],
    // Optional paymaster for gas sponsorship. Get your free Base paymaster URL [from the CDP Portal](https://portal.cdp.coinbase.com/products/node).
    paymasterUrl: "https://paymaster.example.com",
    });

    console.log("User Operation Hash:", result.userOperationHash);

    After sending a user operation, you can get its status and retrieve the result:

    import { getUserOperation } from "@coinbase/cdp-core";

    // Get the status of a user operation
    const userOperationResult = await getUserOperation({
    userOperationHash: result.userOperationHash,
    evmSmartAccount: smartAccount,
    network: "base-sepolia"
    });

    console.log("Status:", userOperationResult.status); // "pending", "complete", or "failed"

    if (userOperationResult.status === "complete") {
    console.log("Transaction Hash:", userOperationResult.transactionHash);
    console.log("Block Number:", userOperationResult.receipts?.[0]?.blockNumber);
    } else if (userOperationResult.status === "failed") {
    console.log("Failure reason:", userOperationResult.receipts?.[0]?.revert?.message);
    }

    End users can sign EVM messages, hashes, and typed data to generate signatures for various onchain applications.

    import { signEvmMessage, signEvmTypedData, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const evmAccount = user.evmAccounts[0];

    // Sign a message
    const messageResult = await signEvmMessage({
    evmAccount,
    message: "Hello World"
    });

    // Sign typed data (EIP-712)
    const typedDataResult = await signEvmTypedData({
    evmAccount,
    typedData: {
    domain: {
    name: "Example DApp",
    version: "1",
    chainId: 84532,
    },
    types: {
    Person: [
    { name: "name", type: "string" },
    { name: "wallet", type: "address" }
    ]
    },
    primaryType: "Person",
    message: {
    name: "Bob",
    wallet: evmAccount
    }
    }
    });

    End users can export their private keys from their embedded wallet, allowing them to import them into compatible wallets of their choice.

    import { exportEvmAccount, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const evmAccount = user.evmAccounts[0];

    const { privateKey } = await exportEvmAccount({
    evmAccount
    });

    // WARNING: Handle private keys with extreme care!
    console.log("EVM Private Key:", privateKey);

    When your application is configured with solana: { createOnLogin: true }, you can export Solana private keys:

    import { exportSolanaAccount, getCurrentUser } from "@coinbase/cdp-core";

    const user = await getCurrentUser();
    const solanaAccount = user.solanaAccounts[0];

    const { privateKey } = await exportSolanaAccount({
    solanaAccount
    });

    // WARNING: Handle private keys with extreme care!
    console.log("Solana Private Key:", privateKey);

    The core package includes an EIP-1193 compatible provider. This provider can be used to sign and send transactions.

    The provider is created by calling createCDPEmbeddedWallet, which exposes a .provider attribute. createCDPEmbeddedWallet must be called with the desired chains to support as well as the transports for these chains.

    The provider will initially connect to the first chain in the chains array. The transports are typically HTTP RPC endpoints, which are used internally for broadcasting non-Base transactions. For more information on transports, see Wagmi's createConfig setup.

    import { base, mainnet } from "viem/chains";
    import { http } from "viem"

    // Basic usage with default configuration
    const wallet = createCDPEmbeddedWallet({
    chains:[base, mainnet],
    transports: {
    [base.id]: http(),
    [mainnet.id]: http()
    }
    });
    const provider = wallet.provider;

    // Request account access
    const accounts = await provider.request({
    method: "eth_requestAccounts"
    });

    // Sign a message
    const signature = await provider.request({
    method: "personal_sign",
    params: ["Hello, World!", accounts[0]]
    });

    // Send a transaction
    const txHash = await provider.request({
    method: "eth_sendTransaction",
    params: [{
    from: accounts[0],
    to: "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
    value: "0x1000000000000000000"
    }]
    });

    // Listen for connection events
    provider.on("connect", (connectInfo) => {
    console.log("Connected to chain:", connectInfo.chainId);
    });

    provider.on("disconnect", () => {
    console.log("Disconnected from wallet");
    });

    The core package includes a toViemAccount utility function that enables wrapping an embedded wallet into a Viem account compatible interface. This allows the account to act as a drop-in replacement for any library or framework that accepts Viem accounts.

    import { toViemAccount, getCurrentUser } from "@coinbase/cdp-core";
    import { createWalletClient } from "viem";
    import { mainnet } from "viem/chains";
    import { http } from "viem";

    const user = await getCurrentUser();
    const evmAccount = user.evmAccounts[0];

    const viemAccount = toViemAccount(evmAccount);

    const client = createWalletClient({
    account: viemAccount,
    transport: http("https://example.com"),
    chain: mainnet,
    });

    Functions

    initialize
    signInWithEmail
    signInWithSms
    signInWithOAuth
    verifyEmailOTP
    verifySmsOTP
    verifyOAuth
    getCurrentUser
    isSignedIn
    signOut
    getAccessToken
    onAuthStateChange
    onOAuthStateChange
    signEvmHash
    signEvmTransaction
    signSolanaTransaction
    sendEvmTransaction
    sendSolanaTransaction
    signEvmMessage
    signSolanaMessage
    signEvmTypedData
    sendUserOperation
    getUserOperation
    exportEvmAccount
    exportSolanaAccount
    toViemAccount
    createSpendPermission
    listSpendPermissions
    revokeSpendPermission
    createCDPEmbeddedWallet

    Classes

    ModuleResolutionError
    InputValidationError
    APIError
    EIP1193ProviderError

    Interfaces

    EIP712Domain
    EIP712Types
    EIP712TypedData
    OAuthFlowState

    Type Aliases

    BaseConfig
    EthereumConfig
    NetworkConfig
    Config
    Hex
    EvmAddress
    SolanaAddress
    AuthenticationMethods
    User
    EmailAuthentication
    SmsAuthentication
    SignInWithEmailOptions
    SignInWithEmailResult
    SignInWithSmsOptions
    SignInWithSmsResult
    VerifyEmailOTPOptions
    VerifyEmailOTPResult
    VerifySmsOTPOptions
    VerifySmsOTPResult
    VerifyOAuthOptions
    VerifyOAuthResult
    OnAuthStateChangeFn
    SignEvmHashOptions
    SignEvmHashResult
    AllowedEvmTransactionType
    SignEvmTransactionOptions
    SignEvmTransactionResult
    SignSolanaTransactionOptions
    SignSolanaTransactionResult
    SignSolanaMessageOptions
    SignSolanaMessageResult
    SendEvmTransactionOptions
    SendEvmTransactionResult
    SendSolanaTransactionOptions
    SendSolanaTransactionResult
    SignEvmMessageOptions
    SignEvmMessageResult
    EIP712Message
    SignEvmTypedDataOptions
    EvmCall
    SendUserOperationOptions
    SendUserOperationResult
    GetUserOperationOptions
    GetUserOperationResult
    SignEvmTypedDataResult
    ExportEvmAccountOptions
    ExportEvmAccountResult
    ExportSolanaAccountOptions
    ExportSolanaAccountResult
    OAuthFlowStatus
    OAuthInfo
    OnOAuthStateChangeFn
    CDPEmbeddedWalletConfig
    EIP1193Provider
    CDPEmbeddedWallet
    EIP1193RequestFunctionType
    AccountsRequest
    RequestAccountsRequest
    PersonalSignRequest
    SendTransactionRequestParams
    SendTransactionRequest
    SignTypedDataRequest
    EthSignRequest
    ChainIdRequest
    WalletDisconnectRequest
    SwitchEthereumChainRequest
    SendCallsRequest
    GetCallsStatusRequest
    GetCapabilitiesRequest
    UnknownRequest
    ProviderRequest
    ExactPartial
    ProviderState
    ProviderStoreInstance
    WalletCapabilities
    SpendPermission
    SpendPermissionInput
    CreateSpendPermissionOptions
    CreateSpendPermissionResult
    ListSpendPermissionsOptions
    ListSpendPermissionsResult
    SpendPermissionNetwork
    SpendPermissionNetwork
    RevokeSpendPermissionOptions
    RevokeSpendPermissionResult
    APIErrorType
    ErrorType
    HttpErrorType
    SendEvmTransactionWithEndUserAccountBodyNetwork
    SendSolanaTransactionWithEndUserAccountBodyNetwork
    OAuth2ProviderType
    EIP1193ErrorCode
    RPCErrorCode

    Variables

    ErrorType
    HttpErrorType
    SendEvmTransactionWithEndUserAccountBodyNetwork
    SendSolanaTransactionWithEndUserAccountBodyNetwork
    OAuth2ProviderType
    STANDARD_ERROR_CODES