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.
Overview
This guide shows how to create and manage non-custodial wallets programmatically using API key authentication. Your server owns and controls the accounts while CDP secures all private keys inside a Trusted Execution Environment.
In this quickstart, you will:
Create EVM and Solana accounts
Fund your accounts with testnet tokens using CDP Faucets
Send a transaction
CDP CLI alternative. Create and fund an account without project setup:npm install -g @coinbase/cdp-cli
cdp env live --key-file ./cdp_api_key.json
cdp env live --wallet-secret-file ./cdp_wallet_secret.txt
cdp evm accounts create name=test
The CLI uses the same API key and Wallet Secret as the SDK. Use it for setup, validation, and ad-hoc operations; use the SDK below for application code.
Prerequisites
Create keys
Sign in to the CDP Portal , create a CDP API key and generate a Wallet Secret . Keep these values handy for the steps below.
Project setup
Initialize a new project and instantiate the CDP client.
Initialize a new TypeScript project: mkdir cdp-sdk-example && cd cdp-sdk-example && npm init -y && npm pkg set type="module" && touch main.ts && touch .env
Add your keys to .env: CDP_API_KEY_ID = your-api-key-id
CDP_API_KEY_SECRET = your-api-key-secret
CDP_WALLET_SECRET = your-wallet-secret
Install the CDP SDK: npm install @coinbase/cdp-sdk dotenv
Instantiate the client in main.ts: import { CdpClient } from "@coinbase/cdp-sdk" ;
import dotenv from "dotenv" ;
dotenv . config ();
const cdp = new CdpClient ();
Run your code with: Initialize a new Python project: mkdir cdp-sdk-example && cd cdp-sdk-example && python -m venv .venv && source .venv/bin/activate && touch main.py && touch .env
Add your keys to .env: CDP_API_KEY_ID = your-api-key-id
CDP_API_KEY_SECRET = your-api-key-secret
CDP_WALLET_SECRET = your-wallet-secret
Install the CDP SDK: pip install cdp-sdk python-dotenv
Instantiate the client in main.py: from cdp import CdpClient
import asyncio
from dotenv import load_dotenv
load_dotenv()
async def main ():
cdp = CdpClient()
await cdp.close()
asyncio.run(main())
Run your code with:
1. Create an account
EVM
import { CdpClient } from "@coinbase/cdp-sdk" ;
import dotenv from "dotenv" ;
dotenv . config ();
const cdp = new CdpClient ();
const account = await cdp . evm . createAccount ();
console . log ( `Created EVM account: ${ account . address } ` );
Created EVM account: 0x3c0D84055994c3062819Ce8730869D0aDeA4c3Bf
You can also create named accounts and retrieve them later with getOrCreateAccount. See Create & Manage Wallets for details.
Solana
const account = await cdp . solana . createAccount ();
console . log ( `Created Solana account: ${ account . address } ` );
Created Solana account: 2XBS6naS1v7pXEg25z43FGHnmEgEad53fmiZ9S6LPgKn
2. Fund with testnet tokens
EVM
const faucetResponse = await cdp . evm . requestFaucet ({
address: account . address ,
network: "base-sepolia" ,
token: "eth"
});
console . log ( `Faucet tx: https://sepolia.basescan.org/tx/ ${ faucetResponse . transactionHash } ` );
Solana
const { signature } = await cdp . solana . requestFaucet ({
address: account . address ,
token: "sol"
});
console . log ( `Faucet tx: https://explorer.solana.com/tx/ ${ signature } ?cluster=devnet` );
3. Send a transaction
EVM
Install viem to wait for transaction confirmation: import { CdpClient } from "@coinbase/cdp-sdk" ;
import { http , createPublicClient , parseEther } from "viem" ;
import { baseSepolia } from "viem/chains" ;
import dotenv from "dotenv" ;
dotenv . config ();
const cdp = new CdpClient ();
const publicClient = createPublicClient ({ chain: baseSepolia , transport: http () });
const account = await cdp . evm . createAccount ();
const { transactionHash : faucetHash } = await cdp . evm . requestFaucet ({
address: account . address ,
network: "base-sepolia" ,
token: "eth" ,
});
await publicClient . waitForTransactionReceipt ({ hash: faucetHash });
const { transactionHash } = await cdp . evm . sendTransaction ({
address: account . address ,
transaction: {
to: "0x0000000000000000000000000000000000000000" ,
value: parseEther ( "0.000001" ),
},
network: "base-sepolia" ,
});
await publicClient . waitForTransactionReceipt ({ hash: transactionHash });
console . log ( `Transaction sent: https://sepolia.basescan.org/tx/ ${ transactionHash } ` );
See all 30 lines
Install web3 to wait for transaction confirmation: import asyncio
from cdp import CdpClient
from cdp.evm_transaction_types import TransactionRequestEIP1559
from dotenv import load_dotenv
from web3 import Web3
load_dotenv()
w3 = Web3(Web3.HTTPProvider( "https://sepolia.base.org" ))
async def main ():
async with CdpClient() as cdp:
account = await cdp.evm.create_account()
faucet_hash = await cdp.evm.request_faucet(
address = account.address, network = "base-sepolia" , token = "eth"
)
w3.eth.wait_for_transaction_receipt(faucet_hash)
tx_hash = await cdp.evm.send_transaction(
address = account.address,
transaction = TransactionRequestEIP1559(
to = "0x0000000000000000000000000000000000000000" ,
value = w3.to_wei( 0.000001 , "ether" ),
),
network = "base-sepolia" ,
)
print ( f "Transaction sent: https://sepolia.basescan.org/tx/ { tx_hash } " )
asyncio.run(main())
See all 30 lines
Solana
Install the Solana web3.js library: npm install @solana/web3.js@1
import { Connection , PublicKey , SystemProgram , Transaction } from "@solana/web3.js" ;
import { CdpClient } from "@coinbase/cdp-sdk" ;
import dotenv from "dotenv" ;
dotenv . config ();
const cdp = new CdpClient ();
const connection = new Connection ( "https://api.devnet.solana.com" );
const account = await cdp . solana . createAccount ();
await cdp . solana . requestFaucet ({ address: account . address , token: "sol" });
// Wait for funds
let balance = 0 ;
while ( balance === 0 ) {
balance = await connection . getBalance ( new PublicKey ( account . address ));
if ( balance === 0 ) await new Promise ( r => setTimeout ( r , 1000 ));
}
const { blockhash } = await connection . getLatestBlockhash ();
const tx = new Transaction ();
tx . add ( SystemProgram . transfer ({
fromPubkey: new PublicKey ( account . address ),
toPubkey: new PublicKey ( "EeVPcnRE1mhcY85wAh3uPJG1uFiTNya9dCJjNUPABXzo" ),
lamports: 1000 ,
}));
tx . recentBlockhash = blockhash ;
tx . feePayer = new PublicKey ( account . address );
const serialized = Buffer . from ( tx . serialize ({ requireAllSignatures: false })). toString ( "base64" );
const { signature : signed } = await cdp . solana . signTransaction ({ address: account . address , transaction: serialized });
const sig = await connection . sendRawTransaction ( Buffer . from ( signed , "base64" ));
await connection . confirmTransaction ( sig );
console . log ( `Transaction sent: https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet` );
See all 35 lines
Install the Solana library: pip install solana solders
import time, base64, asyncio
from cdp import CdpClient
from dotenv import load_dotenv
from solana.rpc.api import Client as SolanaClient
from solana.rpc.types import TxOpts
from solders.pubkey import Pubkey as PublicKey
from solders.system_program import TransferParams, transfer
from solders.message import Message
load_dotenv()
connection = SolanaClient( "https://api.devnet.solana.com" )
async def main ():
async with CdpClient() as cdp:
account = await cdp.solana.create_account()
await cdp.solana.request_faucet(account.address, token = "sol" )
# Wait for funds
balance = 0
while balance == 0 :
balance = connection.get_balance(PublicKey.from_string(account.address)).value
if balance == 0 : time.sleep( 1 )
from_pk = PublicKey.from_string(account.address)
to_pk = PublicKey.from_string( "EeVPcnRE1mhcY85wAh3uPJG1uFiTNya9dCJjNUPABXzo" )
blockhash = connection.get_latest_blockhash().value.blockhash
msg = Message.new_with_blockhash([transfer(TransferParams( from_pubkey = from_pk, to_pubkey = to_pk, lamports = 1000 ))], from_pk, blockhash)
tx_bytes = bytes ([ 1 ]) + bytes ( 64 ) + bytes (msg)
serialized = base64.b64encode(tx_bytes).decode()
signed = await cdp.solana.sign_transaction(account.address, transaction = serialized)
decoded = base64.b64decode(signed.signed_transaction)
sig = connection.send_raw_transaction(decoded, opts = TxOpts( skip_preflight = False )).value
connection.confirm_transaction(sig)
print ( f "Transaction sent: https://explorer.solana.com/tx/ { sig } ?cluster=devnet" )
asyncio.run(main())
See all 40 lines
What to read next
Create & Manage Wallets Named accounts, listing, updating, and pre-generation
Smart Accounts Gas sponsorship, batched transactions, and spend permissions
Security TEE architecture, Wallet Secrets, and OFAC screening
Policy Engine Set rules that govern what transactions accounts can sign