Documentation Index
Fetch the complete documentation index at: https://docs.cloud.coinbase.com/llms.txt
Use this file to discover all available pages before exploring further.
Account types
CDP Wallets support three account types:
- EOA - Standard EVM account controlled by a private key. Supports all EVM networks. Best for simple transfers, signing, and broad network coverage.
- Smart Account - Programmable EVM account (ERC-4337) that enables gas sponsorship, batched transactions, and spend permissions. Supported on Base, Ethereum, Arbitrum, Optimism, Polygon, BNB, Avalanche, and Zora. Requires an EOA as its owner.
- Solana - Native Solana account. Supported on Mainnet and Devnet.
Create a user wallet
User wallets are owned by your end users. Users sign in with email, SMS, or social login and retain full custody of their assets. Your backend can also pre-generate wallets before a user signs in for a seamless first-time experience.
React
Node (TypeScript)
Python
Configure createOnLogin to create an account automatically when the user signs in. Use "eoa" for a standard account or "smart" for a Smart Account with gas sponsorship and batching:<CDPReactProvider config={{
projectId: "your-project-id",
ethereum: { createOnLogin: "eoa" }, // or "smart"
solana: { createOnLogin: true },
}}>
To create additional accounts after the user signs in:import { useCreateEvmEoaAccount, useCreateSolanaAccount } from "@coinbase/cdp-hooks";
const { createEvmEoaAccount } = useCreateEvmEoaAccount();
const { createSolanaAccount } = useCreateSolanaAccount();
const evmAccount = await createEvmEoaAccount();
const solAccount = await createSolanaAccount();
Pre-generate wallets on your backend before users sign in, so you can fund them with assets upfront:const endUser = await cdp.endUser.createEndUser({
authenticationMethods: [
{ type: "email", email: "user@example.com" }
],
evmAccount: { createSmartAccount: false },
solanaAccount: { createSmartAccount: false },
});
console.log("EVM:", endUser.evmAccounts?.[0]);
console.log("Solana:", endUser.solanaAccounts?.[0]);
Supported authentication methods: email, sms (with phoneNumber), and jwt (with sub and kid). See Authentication for details. Pre-generate wallets on your backend before users sign in, so you can fund them with assets upfront:from cdp.openapi_client.models.authentication_method import AuthenticationMethod
from cdp.openapi_client.models.email_authentication import EmailAuthentication
from cdp.openapi_client.models.create_end_user_request_evm_account import CreateEndUserRequestEvmAccount
from cdp.openapi_client.models.create_end_user_request_solana_account import CreateEndUserRequestSolanaAccount
end_user = await cdp.end_user.create_end_user(
authentication_methods=[
AuthenticationMethod(EmailAuthentication(type="email", email="user@example.com"))
],
evm_account=CreateEndUserRequestEvmAccount(create_smart_account=False),
solana_account=CreateEndUserRequestSolanaAccount(create_smart_account=False),
)
Supported authentication methods: email, sms (with phoneNumber), and jwt (with sub and kid). See Authentication for details.
Multiple accounts per user
Each end user can have up to 10 EVM EOAs, 10 Smart Accounts, and 10 Solana accounts. One account of each configured type is created automatically via createOnLogin. To add more:
import {
useCreateEvmEoaAccount,
useCreateEvmSmartAccount,
useCreateSolanaAccount,
useCurrentUser,
} from "@coinbase/cdp-hooks";
const { createEvmEoaAccount } = useCreateEvmEoaAccount();
const { createEvmSmartAccount } = useCreateEvmSmartAccount();
const { createSolanaAccount } = useCreateSolanaAccount();
const { currentUser } = useCurrentUser();
// Add another EVM EOA
const eoa = await createEvmEoaAccount();
// Add a Smart Account (needs an EOA owner)
const ownerAddress = currentUser?.evmAccountObjects?.[0]?.address;
const smart = await createEvmSmartAccount({ ownerAddress });
// Add a Solana account
const sol = await createSolanaAccount();
Each Smart Account requires a unique EOA owner. You cannot create multiple Smart Accounts with the same EOA.
Create an API key wallet
API key wallets are owned and controlled by your server. Your backend creates and manages accounts using your CDP API key and Wallet Secret.
EVM EOA
const account = await cdp.evm.createAccount();
console.log("Address:", account.address);
account = await cdp.evm.create_account()
print(f"Address: {account.address}")
EVM Smart Account
A Smart Account is an ERC-4337 account owned by an EOA. Each EOA can own one Smart Account. Use getOrCreateSmartAccount to also assign a name for easier retrieval later.
const owner = await cdp.evm.getOrCreateAccount({ name: "my-owner" });
// Create a Smart Account
const smartAccount = await cdp.evm.createSmartAccount({ owner });
console.log("Smart Account:", smartAccount.address);
// Create or retrieve a named Smart Account
const named = await cdp.evm.getOrCreateSmartAccount({
name: "my-smart-account",
owner,
});
console.log("Named Smart Account:", named.address);
owner = await cdp.evm.get_or_create_account(name="my-owner")
# Create a Smart Account
smart_account = await cdp.evm.create_smart_account(owner=owner)
print(f"Smart Account: {smart_account.address}")
# Create or retrieve a named Smart Account
named = await cdp.evm.get_or_create_smart_account(
name="my-smart-account",
owner=owner,
)
print(f"Named Smart Account: {named.address}")
Solana
const account = await cdp.solana.createAccount();
console.log("Address:", account.address);
account = await cdp.solana.create_account()
print(f"Address: {account.address}")
Named accounts
Assign a human-readable name for easier retrieval of wallets created with API keys. Names must be 2-36 alphanumeric characters or hyphens, and unique per account type within a project. getOrCreateAccount creates the account if it doesn’t exist, or returns the existing one:
const account = await cdp.evm.getOrCreateAccount({ name: "treasury" });
const solAccount = await cdp.solana.getOrCreateAccount({ name: "sol-treasury" });
account = await cdp.evm.get_or_create_account(name="treasury")
sol_account = await cdp.solana.get_or_create_account(name="sol-treasury")
Manage accounts
Get an account
For user authentication, accounts are available on the current user object. For API key authentication, retrieve accounts by address or name.
React
Node (TypeScript)
Python
import { useCurrentUser } from "@coinbase/cdp-hooks";
const { currentUser } = useCurrentUser();
// All EVM EOAs
const evmAccounts = currentUser?.evmAccountObjects;
// All Smart Accounts
const smartAccounts = currentUser?.evmSmartAccountObjects;
// All Solana accounts
const solanaAccounts = currentUser?.solanaAccountObjects;
// By address
const account = await cdp.evm.getAccount({
address: "0x1234...5678"
});
// By name
const named = await cdp.evm.getAccount({ name: "treasury" });
# By address
account = await cdp.evm.get_account(address="0x1234...5678")
# By name
named = await cdp.evm.get_account(name="treasury")
List accounts
let response = await cdp.evm.listAccounts();
while (true) {
for (const account of response.accounts) {
console.log(account.address);
}
if (!response.nextPageToken) break;
response = await cdp.evm.listAccounts({ pageToken: response.nextPageToken });
}
response = await cdp.evm.list_accounts()
while True:
for account in response.accounts:
print(account.address)
if not response.next_page_token:
break
response = await cdp.evm.list_accounts(page_token=response.next_page_token)
Update an account
// Rename
const updated = await cdp.evm.updateAccount({
address: account.address,
update: { name: "new-name" },
});
// Attach a policy
const withPolicy = await cdp.evm.updateAccount({
address: account.address,
update: { accountPolicy: "policy-id" },
});
# Rename
updated = await cdp.evm.update_account(
address=account.address,
update={"name": "new-name"},
)
# Attach a policy
with_policy = await cdp.evm.update_account(
address=account.address,
update={"account_policy": "policy-id"},
)
Token balances
Retrieve balances for native tokens (ETH, SOL) and ERC-20 / SPL tokens on any supported network. Balance queries are read-only and work for any public address, not just accounts you own.
EVM
Supported networks: ethereum, base, base-sepolia.
let page = await cdp.evm.listTokenBalances({
address: account.address,
network: "base-sepolia",
pageSize: 10,
});
while (true) {
for (const balance of page.balances) {
console.log(balance.token.contractAddress, balance.amount.amount);
}
if (!page.nextPageToken) break;
page = await cdp.evm.listTokenBalances({
address: account.address,
network: "base-sepolia",
pageSize: 10,
pageToken: page.nextPageToken,
});
}
page = await cdp.evm.list_token_balances(
address=account.address,
network="base-sepolia",
page_size=10,
)
while True:
for balance in page.balances:
print(balance.token.contract_address, balance.amount.amount)
if not page.next_page_token:
break
page = await cdp.evm.list_token_balances(
address=account.address,
network="base-sepolia",
page_size=10,
page_token=page.next_page_token,
)
Solana
Supported networks: solana, solana-devnet.
let page = await cdp.solana.listTokenBalances({
address: account.address,
network: "solana-devnet",
pageSize: 10,
});
while (true) {
for (const balance of page.balances) {
console.log(balance.token.mintAddress, balance.amount.amount);
}
if (!page.nextPageToken) break;
page = await cdp.solana.listTokenBalances({
address: account.address,
network: "solana-devnet",
pageSize: 10,
pageToken: page.nextPageToken,
});
}
page = await cdp.solana.list_token_balances(
address=account.address,
network="solana-devnet",
page_size=10,
)
while True:
for balance in page.balances:
print(balance.token.mint_address, balance.amount.amount)
if not page.next_page_token:
break
page = await cdp.solana.list_token_balances(
address=account.address,
network="solana-devnet",
page_size=10,
page_token=page.next_page_token,
)