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
http://localhost:3000
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'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);
console.log("EVM Accounts:", user.evmAccounts);
// 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 a Blockchain transaction in a single call on the following networks:
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 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
});
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 it into an EVM-compatible wallet 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("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,
});