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.
Get up and running with your custom stablecoin. This guide walks through reading a balance and sending your first transfer. The onchain source code is available at coinbase/custom-stablecoin .
Ethereum Virtual Machine
Solana Virtual Machine
Prerequisites
Node.js 18+ installed
A wallet with a private key for Base Sepolia
Base Sepolia ETH for gas fees (get from CDP Faucet )
Base Sepolia CBTUSD tokens (get from CDP Faucet )
Basic familiarity with TypeScript
This quickstart uses CBTUSD , a test custom stablecoin already deployed on Base Sepolia. Your production stablecoin address is provided during onboarding.
1. Create tsconfig.json {
"compilerOptions" : {
"target" : "ES2020" ,
"module" : "CommonJS" ,
"esModuleInterop" : true ,
"resolveJsonModule" : true ,
"skipLibCheck" : true ,
"strict" : true
}
}
2. Install dependencies npm install ethers
npm install --save-dev ts-node typescript @types/node
3. Set environment variables export PRIVATE_KEY = "your-wallet-private-key"
export RPC_URL = "https://sepolia.base.org"
Never commit your private key to source control. Use environment variables or a secrets manager. For production, use CDP Server Wallet v2 for secure key management. 4. Create your script import { ethers } from "ethers" ;
const TOKEN_ADDRESS = "0x57AB1EFE59b1C7b36b1Dc9315B4782bCcBb83721" ; // CBTUSD on Base Sepolia
const ERC20_ABI = [
"function balanceOf(address account) view returns (uint256)" ,
"function decimals() view returns (uint8)" ,
"function transfer(address to, uint256 amount) returns (bool)" ,
];
async function main () {
const provider = new ethers . JsonRpcProvider ( process . env . RPC_URL );
const signer = new ethers . Wallet ( process . env . PRIVATE_KEY ! , provider );
const token = new ethers . Contract ( TOKEN_ADDRESS , ERC20_ABI , signer );
const decimals = await token . decimals ();
const balance = await token . balanceOf ( signer . address );
console . log ( "Balance:" , ethers . formatUnits ( balance , decimals ));
// Transfer 1 token to yourself as a smoke test
const amount = ethers . parseUnits ( "1" , decimals );
const tx = await token . transfer ( signer . address , amount );
const receipt = await tx . wait ();
console . log ( "Transfer confirmed:" , receipt . hash );
}
main ()
. then (() => process . exit ( 0 ))
. catch (( err ) => { console . error ( err . message ); process . exit ( 1 ); });
5. Run your script Prerequisites
Node.js 18+ installed
A Solana wallet keypair file
Devnet SOL for transaction fees (get from CDP Faucet )
Devnet CBTUSD tokens (get from CDP Faucet )
Basic familiarity with TypeScript
This quickstart uses CBTUSD , a test custom stablecoin already deployed on Solana devnet. Your production stablecoin mint address is provided during onboarding.
Don't have a Solana wallet?
# Install Solana CLI
sh -c "$( curl -sSfL https://release.solana.com/stable/install)"
# Create a wallet keypair
solana-keygen new --outfile ~/.config/solana/id.json
For production, use CDP Server Wallet v2 for secure key management. 1. Create tsconfig.json {
"compilerOptions" : {
"target" : "ES2020" ,
"module" : "CommonJS" ,
"esModuleInterop" : true ,
"resolveJsonModule" : true ,
"skipLibCheck" : true ,
"strict" : false
}
}
2. Install dependencies npm install @solana/web3.js @solana/spl-token
npm install --save-dev ts-node typescript @types/node
3. Set environment variables export RPC_URL = "https://api.devnet.solana.com"
export WALLET_PATH = " $HOME /.config/solana/id.json"
4. Create your script import {
Connection ,
Keypair ,
PublicKey ,
} from "@solana/web3.js" ;
import {
getMint ,
getOrCreateAssociatedTokenAccount ,
transfer ,
} from "@solana/spl-token" ;
import * as fs from "fs" ;
const MINT_ADDRESS = new PublicKey ( "5P6MkoaCd9byPxH4X99kgKtS6SiuCQ67ZPCJzpXGkpCe" ); // CBTUSD on devnet
async function main () {
const connection = new Connection ( process . env . RPC_URL ! );
const keyData = JSON . parse ( fs . readFileSync ( process . env . WALLET_PATH ! , "utf-8" ));
const payer = Keypair . fromSecretKey ( Uint8Array . from ( keyData ));
// Get or create the token account for your wallet
const tokenAccount = await getOrCreateAssociatedTokenAccount (
connection ,
payer ,
MINT_ADDRESS ,
payer . publicKey
);
const mintInfo = await getMint ( connection , MINT_ADDRESS );
const balance = Number ( tokenAccount . amount ) / Math . pow ( 10 , mintInfo . decimals );
console . log ( "Balance:" , balance );
// Transfer 1 token to yourself as a smoke test
const amount = BigInt ( 1 ) * BigInt ( 10 ** mintInfo . decimals );
const sig = await transfer (
connection ,
payer ,
tokenAccount . address , // source
tokenAccount . address , // destination (self-transfer for test)
payer ,
amount
);
console . log ( "Transfer confirmed:" , sig );
}
main ()
. then (() => process . exit ( 0 ))
. catch (( err ) => { console . error ( err . message ); process . exit ( 1 ); });
5. Run your script
What’s next?
Examples Memos, permit, gasless transfers, and more
Reference Full function and program reference
Key Addresses Contract and mint addresses
Overview Learn about Custom Stablecoins