Configuration
RPC Endpoints
All commands require RPC endpoints for the networks involved. The CLI accepts both http[s] and ws[s] URLs.
Where to Get RPCs
- EVM
- Solana
- Aptos
| Provider | Description |
|---|---|
| QuickNode | Multi-chain support with free tier |
| Alchemy | Enterprise-grade with free tier |
| Chainlist.org | Free public RPCs for EVM networks |
| Infura | Reliable EVM endpoints with free tier |
| Nodereal | Aptos and EVM support with free tier |
| Provider | Description |
|---|---|
| QuickNode | Multi-chain support with free tier |
| Alchemy | Enterprise-grade with free tier |
| Helius | Popular Solana RPC with generous free tier |
| Solana Official | Free but rate-limited official endpoints |
| Provider | Description |
|---|---|
| QuickNode | Multi-chain support with free tier |
| Aptos Labs | Official Aptos endpoints |
| Nodereal | Aptos and EVM support with free tier |
Providing RPCs
Command line: Use --rpc or --rpcs to specify endpoints directly:
ccip-cli show 0x123... \
--rpc https://eth-sepolia.example.com \
--rpc https://arb-sepolia.example.com
You can also pass comma-separated values:
ccip-cli show 0x123... \
--rpcs "https://eth-sepolia.example.com,https://arb-sepolia.example.com"
Environment variables: Export variables prefixed with RPC_. See Environment Variables for details.
Configuration file: Use --rpcs-file to load from a file (default: ./.env):
ccip-cli show 0x123... --rpcs-file ./my-rpcs.txt
File Format
The parser extracts URLs from any format. Lines can contain prefixes, suffixes, or comments:
https://eth-sepolia.g.alchemy.com/v2/demo
ARB_SEPOLIA_RPC: https://arbitrum-sepolia.drpc.org
RPC_AVALANCHE_TESTNET=https://avalanche-fuji-c-chain-rpc.publicnode.com
https://api.devnet.solana.com # solana devnet
https://api.testnet.aptoslabs.com/v1
The CLI connects to all endpoints in parallel and uses the fastest responding RPC for each network.
Environment Variables
The CLI supports environment variables for configuration. Command-line flags override environment variables.
RPC Configuration
| Variable | Description | Example |
|---|---|---|
RPC_* | RPC endpoints (any suffix) | RPC_SEPOLIA=https://... |
Wallet Configuration
The CLI checks these environment variables in order: PRIVATE_KEY, USER_KEY, OWNER_KEY.
| Variable | Description |
|---|---|
PRIVATE_KEY | Private key (EVM: hex, Solana: base58) |
USER_KEY | Alias for PRIVATE_KEY |
OWNER_KEY | Alias for PRIVATE_KEY |
USER_KEY_PASSWORD | Password for encrypted JSON keystore file or keystore fallback |
FOUNDRY_KEYSTORE_PASSWORD | Password for Foundry keystore (takes priority over USER_KEY_PASSWORD) |
HARDHAT_KEYSTORE_PASSWORD | Password for Hardhat keystore (takes priority over USER_KEY_PASSWORD) |
FOUNDRY_DIR | Override Foundry home directory (default: ~/.foundry) |
Output Preferences
| Variable | Description | Default |
|---|---|---|
CCIP_FORMAT | Output format (pretty, log, json) | pretty |
CCIP_VERBOSE | Enable debug logging (true/false) | false |
CCIP_PAGE | Pagination size for getLogs queries | - |
CCIP_API | CCIP API endpoint URL, or false/no to disable API calls (decentralized mode). true/yes to enable with default URL. | Enabled (https://api.ccip.chain.link) |
Example .env file:
# RPC Endpoints
RPC_SEPOLIA=https://eth-sepolia.example.com
RPC_ARB_SEPOLIA=https://arb-sepolia.example.com
RPC_AVALANCHE_FUJI=https://avalanche-fuji.example.com
RPC_SOLANA_DEVNET=https://api.devnet.solana.com
RPC_APTOS_TESTNET=https://api.testnet.aptoslabs.com/v1
# Wallet (for send/manual-exec commands)
USER_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
# Or use a named keystore (pass --wallet foundry:<name> or --wallet hardhat:<name>)
# FOUNDRY_KEYSTORE_PASSWORD=yourFoundryKeystorePassword
# HARDHAT_KEYSTORE_PASSWORD=yourHardhatKeystorePassword # hardhat type requires running from inside a Hardhat project
# Output preferences
CCIP_FORMAT=json
CCIP_VERBOSE=false
Use --rpcs-file to load a different file: ccip-cli show 0x... --rpcs-file ./prod.env
Wallet Configuration
Commands that send transactions require a wallet. The CLI checks these sources in order:
Auto-Detection
If --wallet is omitted, the CLI checks environment variables first (PRIVATE_KEY, USER_KEY, OWNER_KEY in that order), then falls back to scanning your --rpcs-file (default: ./.env):
# .env file
RPC_SEPOLIA=https://eth-sepolia.example.com
USER_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
# CLI will use USER_KEY automatically
ccip-cli send ethereum-testnet-sepolia 0x... dest --receiver 0x...
--wallet Option
Pass directly or specify a file path:
| Chain | Accepted Formats |
|---|---|
| EVM | Hex private key, path to encrypted JSON keystore, ledger[:index], foundry:<name>, or hardhat:<name> |
| Solana | Base58 private key, or path to id.json file (default: ~/.config/solana/id.json) |
| Aptos | Hex private key, or path to text file containing it |
| Sui | Hex or base64 private key |
| TON | 64-byte hex private key (0x-prefixed), mnemonic phrase (space-separated), path to key file, or ledger[:index] |
| Canton | Not required — party ID comes from --canton-config; transactions submit via JWT |
Foundry Cast Keystore
If you manage keys with Foundry Cast, use foundry:<name>:
# Import a key into the Foundry keystore (one-time setup)
cast wallet import sender --interactive
# Use it with the CLI
ccip-cli send ... --wallet foundry:sender
Password resolution order:
$FOUNDRY_KEYSTORE_PASSWORDenv var$USER_KEY_PASSWORDenv var- Interactive prompt
The keystore directory defaults to ~/.foundry/keystores/ and can be overridden with $FOUNDRY_DIR.
Hardhat Keystore
If you manage keys with Hardhat's built-in keystore, use hardhat:<name>. The CLI runs node_modules/.bin/hardhat keystore get directly, so Hardhat must be installed as a dev dependency in your project:
# Import a key into the Hardhat keystore (one-time setup)
npx hardhat keystore set sender
# Use it with the CLI (run from inside your Hardhat project)
ccip-cli send ... --wallet hardhat:sender
Password resolution order:
$HARDHAT_KEYSTORE_PASSWORDenv var (piped silently to Hardhat)$USER_KEY_PASSWORDenv var (piped silently to Hardhat)- Interactive prompt (ccip-cli prompts, answer is piped to Hardhat)
Ledger Hardware Wallet
Connect a Ledger device:
ccip-cli send ... --wallet ledger
Use a specific derivation index:
ccip-cli send ... --wallet ledger:1 # Uses m/44'/60'/1'/0/0 for EVM
Global Options
These options are available on all commands:
| Option | Alias | Type | Default | Description |
|---|---|---|---|---|
--rpcs | --rpc | string[] | - | RPC endpoint URLs |
--rpcs-file | - | string | ./.env | File containing RPC endpoints |
--format | -f | string | pretty | Output format: pretty, log, or json |
--verbose | -v | boolean | - | Enable debug logging |
--page | - | number | - | Pagination size for getLogs queries |
--api | - | string | https://api.ccip.chain.link | CCIP API endpoint URL. Enabled by default. Pass a URL for a custom endpoint. Use --no-api to disable (decentralized RPC-only mode) |
--canton-config | - | string | - | Path to Canton config JSON file (required for Canton operations) |
--indexer | - | string[] | - | CCIP v2 indexer URLs for CCV verifications (used when lane involves Canton) |
--help | -h | boolean | - | Show help |
--version | -V | boolean | - | Show version |
Output formats:
| Format | Use Case |
|---|---|
pretty | Human-readable tables (default) |
log | Console output with additional details |
json | Machine-readable, suitable for scripting — see Reading JSON Output |
Network Identifiers
Networks can be specified by name, chain ID, or CCIP chain selector. The CLI uses chain-selectors for resolution.
| Chain Family | Identifier Format | Example |
|---|---|---|
| All | CCIP chain selector | 16015286601757825753 (Sepolia) |
| All | Network name | ethereum-mainnet, ethereum-testnet-sepolia |
| EVM | Numeric chain ID | 1 (Ethereum), 11155111 (Sepolia) |
| Solana | Genesis hash | 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d |
| Aptos | Prefixed chain ID | aptos:1 (mainnet), aptos:2 (testnet) |
| Sui | Prefixed chain ID | sui:1 |
| Canton | Prefixed chain ID | canton:TestNet, canton:DevNet, canton:MainNet |
Canton Configuration
Canton operations require a JSON config file passed via --canton-config <path>. The Canton Ledger API URL is provided through the normal --rpc / --rpcs mechanism (detected by /api/json, /api/ledger, or port 7575).
Config file format:
{
"party": "u_7c1f39da042a::1220c250c23c...",
"ccipParty": "ccipOwner::1220e382f4e5...",
"auth": {
"type": "clientCredentials",
"authUrl": "https://auth.example.com/oauth2/default"
},
"edsUrl": "https://eds.example.com",
"transferInstructionUrl": "https://transfer-instruction.example.com",
"indexerUrl": "https://indexer.example.com",
"chainId": "canton:TestNet",
"packages": {
"perPartyRouter": "ccip-runtime-v2",
"ccipReceiver": "ccip-receiver-v2",
"ccipSender": "ccip-sender-v2"
},
"senderInstanceId": "prod-ccipsender",
"ccvs": ["0x5b92820da106..."]
}
Set CANTON_CLIENT_ID and CANTON_CLIENT_SECRET env vars for the clientCredentials flow, or use "jwt": "eyJ..." in place of the auth block for a pre-obtained token. See Canton Authentication for all flows.
| Field | Required | Description |
|---|---|---|
party | Yes | User ledger party for actAs and transaction visibility |
ccipParty | Yes | CCIP operator party (CCIPSender signatory / fee recipient) |
jwt | No* | JSON Web Token for Canton Ledger API authentication |
auth | No* | OIDC auth config (alternative to jwt — see below) |
edsUrl | Yes | Base URL for the Explicit Disclosure Service (EDS) |
transferInstructionUrl | Yes | Base URL for the Transfer Instruction API |
externalEdsUrlsByOwner | No | Map of owner party → external EDS URL |
indexerUrl | No | CCIP v2 indexer URL for CCV verifications (required for Canton manual execution) |
chainId | No | CCIP Canton chain ID (e.g. canton:TestNet); skips auto-detection |
senderInstanceId | No | CCIPSender instance id used as router on Canton source (CLI -r overrides) |
defaultSendGasLimit | No | Default gas limit for Canton → destination sends |
feeTransferFactoryAmount | No | Transfer-factory preview amount for fee payments (default: "1.0") |
ccvs | No | CCV instance addresses for execute disclosures and send defaults |
packages | No | DAR package names for ACS template filters |
* Either jwt or auth is required. If both are present, jwt takes precedence.
Canton Authentication
Instead of a static jwt, you can provide an auth object to obtain a JWT automatically via OpenID Connect (OIDC). Three flows are supported (mirroring the Go commonconfig.AuthConfig):
auth.type | Use case | Required auth fields |
|---|---|---|
static | Pre-obtained JWT (TLS) | jwt |
insecureStatic | Pre-obtained JWT (no TLS, devnet) | jwt |
clientCredentials | Machine-to-machine (CI/CD) | authUrl, clientId†, clientSecret† |
authorizationCode | Interactive browser login (PKCE) | authUrl, clientId† |
† clientId and clientSecret may be omitted from the config file and resolved from CANTON_CLIENT_ID / CANTON_CLIENT_SECRET env vars instead. Keep secrets in env vars, not in config files.
Client credentials example (CI/CD, machine-to-machine):
{
"auth": {
"type": "clientCredentials",
"authUrl": "https://auth.example.com"
}
}
export CANTON_CLIENT_ID="my-client-id"
export CANTON_CLIENT_SECRET="my-client-secret"
Authorization code example (interactive browser login for human users):
{
"auth": {
"type": "authorizationCode",
"authUrl": "https://auth.example.com",
"callbackUrl": "http://localhost:8400/callback"
}
}
The authorizationCode flow opens a browser for login and starts a local callback server to receive the authorization code. The callbackUrl defaults to http://localhost:8400/callback — override it if port 8400 is in use or your OIDC provider requires a different redirect URI. PKCE with S256 is required.
When auth is set, the CLI resolves a JWT on demand via the SDK's authentication package (backed by oauth4webapi). Optional auth fields: audience (Auth0-specific), scopes (defaults to daml_ledger_api for client credentials, openid daml_ledger_api for authorization code), callbackUrl (authorization code only), openBrowser (default true), timeoutMs (default 120000).
Canton Wallet
On Canton, the party ID comes from config and transactions are submitted directly using the JWT from config (either the static jwt field or a token resolved from auth). The --wallet flag is not required for Canton operations.
ccip-cli send \
-s canton-testnet \
-d ethereum-testnet-sepolia \
-r prod-ccipsender \
--canton-config ./canton-config.json \
--rpc https://ledger.example.com/api/json \
--rpc https://ethereum-sepolia-rpc.example.com \
--to 0xReceiverContract \
-t link-token=1.0 \
--no-estimate-gas-limit
Shell Completion
Enable tab-completion for commands and options by adding the completion script to your shell profile:
# bash
ccip-cli completion >> ~/.bashrc
# zsh
ccip-cli completion >> ~/.zshrc
Restart your shell or run source ~/.bashrc (or ~/.zshrc) to activate. Once enabled, press Tab to autocomplete commands, subcommands, and flags.