EVM server accounts are managed by Coinbase’s infrastructure, providing secure key management without requiring you to handle private keys directly. These accounts work with all EVM-compatible chains supported by CDP.
Creating an EVM Account
Initialize the CDP Client
First, set up your CDP client with your API credentials:import { CdpClient } from "@coinbase/cdp-sdk";
const cdp = new CdpClient();
from cdp import CdpClient
async with CdpClient() as cdp:
# Your code here
Create a new account
Create a new EVM account with an optional name:const account = await cdp.evm.createAccount({
name: "MyAccount"
});
console.log(`Created account: ${account.address}`);
account = await cdp.evm.create_account(name="MyAccount")
print(f"Created account: {account.address}")
Create with a policy
You can apply an account-level policy during creation:const account = await cdp.evm.createAccount({
name: "RestrictedAccount",
accountPolicy: "pol_abc123..."
});
account = await cdp.evm.create_account(
name="RestrictedAccount",
account_policy="pol_abc123..."
)
Retrieving Accounts
Get or Create Pattern
Use getOrCreateAccount for idempotent account creation:
// Returns existing account or creates new one
const account = await cdp.evm.getOrCreateAccount({
name: "MyAccount"
});
# Returns existing account or creates new one
account = await cdp.evm.get_or_create_account(name="MyAccount")
Get Account by Address or Name
// By address
const account = await cdp.evm.getAccount({
address: "0x1234..."
});
// By name
const account = await cdp.evm.getAccount({
name: "MyAccount"
});
# By address
account = await cdp.evm.get_account(address="0x1234...")
# By name
account = await cdp.evm.get_account(name="MyAccount")
List All Accounts
Retrieve all accounts with pagination support:
const response = await cdp.evm.listAccounts({
pageSize: 50,
pageToken: "optional-token-for-next-page"
});
console.log(`Found ${response.accounts.length} accounts`);
if (response.nextPageToken) {
console.log("More pages available");
}
response = await cdp.evm.list_accounts(
page_size=50,
page_token="optional-token-for-next-page"
)
print(f"Found {len(response.accounts)} accounts")
if response.next_page_token:
print("More pages available")
Updating Accounts
You can update an account’s name or apply/remove policies:
const updatedAccount = await cdp.evm.updateAccount({
address: account.address,
name: "NewAccountName",
accountPolicy: "pol_xyz789..." // Optional
});
from cdp.update_account_types import UpdateAccountOptions
updated_account = await cdp.evm.update_account(
address=account.address,
options=UpdateAccountOptions(
name="NewAccountName",
account_policy="pol_xyz789..." # Optional
)
)
Importing Accounts
Import an existing private key as a CDP-managed account:
const account = await cdp.evm.importAccount({
privateKey: "0xabcdef...",
name: "ImportedAccount"
});
account = await cdp.evm.import_account(
private_key="0xabcdef...",
name="ImportedAccount"
)
The private key is encrypted using RSA before transmission to CDP servers.
Exporting Accounts
Export the private key of a CDP-managed account:
// Export by address
const privateKey = await cdp.evm.exportAccount({
address: account.address
});
// Export by name
const privateKey = await cdp.evm.exportAccount({
name: "MyAccount"
});
console.log(`Private key (without 0x prefix): ${privateKey}`);
# Export by address
private_key = await cdp.evm.export_account(address=account.address)
# Export by name
private_key = await cdp.evm.export_account(name="MyAccount")
print(f"Private key (without 0x prefix): {private_key}")
Store exported private keys securely. Never commit them to version control or share them.
Account Properties
EVM server accounts expose the following properties:
The Ethereum address of the account (e.g., 0x1234...)
The optional name assigned to the account
List of policy IDs applied to this account
Common Operations
Once you have an EVM account, you can:
- Transfer tokens: See Token Transfers
- Send transactions: See Sending Transactions
- Swap tokens: See Token Swaps
- Sign messages: Use
account.signMessage() for EIP-191 signatures
- Sign typed data: Use
account.signTypedData() for EIP-712 signatures
- Check balances: Use
account.listTokenBalances(network)
Troubleshooting
Account Not Found
If getAccount() throws an error, the account doesn’t exist. Use getOrCreateAccount() for idempotent operations.
Name Conflicts
Account names must be unique within your project. Use updateAccount() to rename.
Rate Limits
If you hit rate limits, use idempotencyKey parameters to safely retry failed requests:
const account = await cdp.evm.createAccount({
name: "MyAccount",
idempotencyKey: "unique-key-123"
});
account = await cdp.evm.create_account(
name="MyAccount",
idempotency_key="unique-key-123"
)
Next Steps