Casper CLI Wallet
This CLI provides wallet management for Casper: create/recover wallets, derive accounts, and manage account names.

Install
cargo install casper-cli- Or download a tarball from the GitHub releases page and extract it into your
PATH.
Build and run
Development
Create a release tarball for the host platform:
The output is written to dist/casper-cli-{version}-{target}.tar.gz.
Global options
--no-interactive- Disable prompts when initializingconfig.toml(requires--keyringor--file-storageif the file is missing).--keyring- Force OS keyring storage for this run (overridesconfig.toml).--file-storage <ROOT_PATH>- Force file-based storage for this run using the provided root path (overridesconfig.toml).--config-path <PATH>- Use a customconfig.tomlpath instead of the default projectdirs location.
Storage layout
By default, wallets are stored under your OS config directory (for example, ~/Library/Application Support/casper-cli on macOS). You can configure the secret storage backend in config.toml:
The layout under the base directory (file storage backend):
wallets/<name>.json- wallet metadata (accounts, type, encryption flag)secrets/<name>.enc- encrypted wallet root secret
When using storage.type = "keyring", secrets are stored in the OS keyring instead of the secrets/ directory, the CLI does not prompt for a master password, and --unencrypted is not supported.
Wallet commands
wallet create
Creates a new wallet. BIP-39 is the default.
Seeded (deterministic) wallets:
Unencrypted (unsafe, for local dev only, file storage only):
[!NOTE]
- If you want to migrate from Casper Wallet, use your saved mnemonic words and an empty, optional passphrase, then this tool can derive accounts from that.
- If you want to derive accounts from a casper-devnet, pass
--seed <seed name>(casper-devnet defaults to thedefaultseed) and--domain casper-unsafe-devnet-v1. The devnet tool derives validator accounts from indexes 0..N and genesis accounts starting from index 100, so you may wantderive --start 100 --count <number of users>.
wallet recover
Recovers a wallet from a BIP-39 mnemonic. This will prompt for the mnemonic and optional passphrase.
wallet list
Lists all wallets in the storage directory.
wallet info
Shows wallet type, encryption state, and known accounts.
wallet derive
Derives accounts from the wallet root and stores them in metadata. The command fails if the requested range overlaps existing accounts. Use --name with a tinytemplate template to control account names; the DeriveNameContext fields are index (0-based), index1 (1-based), wallet (wallet name), network (active network key), and chain_name (active network chain name). The default is account-{index}.
Custom name templates:
To show private keys (dangerous):
wallet rename-account
Renames an existing account in a wallet.
External form:
wallet delete
Deletes the wallet metadata and secret.
Network commands
Networks are stored in config.toml under the same config directory as wallets. If the file is missing, casper-cli will prompt for the storage backend and then create it with a default devnet entry:
= "devnet"
[]
= "keyring"
# For file-based storage:
# type = "file"
# root_path = "/Users/you/Library/Application Support/casper-cli"
[]
= "casper-dev"
= "http://127.0.0.1:14102"
= "http://127.0.0.1:18102/events"
= "http://127.0.0.1:11102/rpc"
= "127.0.0.1:28101"
network use
Selects the active network by key or chain name:
network list
Lists configured networks and highlights which one is active:
Balance command
Fetches the balance for a wallet account, account hash hex, or a raw public key hex. The active network is read from config.toml.
View account command
Fetches account details from the active network and prints named keys.
Config commands
config edit
Opens config.toml in your $EDITOR:
Transaction commands
Simulation uses the network binary port; set binary (ip:port) in config.toml before using --simulate.
The simulator runs a local execution engine and will download trie objects from the node via the
binary port as needed. Unlike speculative execution, it can report return values, which can be
useful for calls like balance_of on a CEP-18 token without reconstructing dictionary item keys
from base64.
Return values are rendered on a best-effort basis into a human-readable CLValue representation,
even for nested/complex types. If formatting fails, the raw 0x bytes are shown instead.
Examples (from unit tests):
| CLType | Return bytes (hex) | Rendered output |
|---|---|---|
Option<Bool> |
0x0101 |
Some(true) |
(Bool, U32, String) |
0x0107000000020000006869 |
(true, 7, hi) |
Map<String, U32> |
0x0200000005000000616c70686101000000040000006265746102000000 |
{alpha: 1, beta: 2} |
Example output:
Simulation result on devnet at block height 10964:
Gas used: 0.013064020
Execution succeeded.
Return String: "Hello, world!"
New tries downloaded: 1
Cache hits during execution: 25
Cleaning up unreferenced tries...
Cleaned up 2 unreferenced tries
transaction put
Builds a session transaction from Wasm and submits it to the active network. The payment amount is specified in CSPR (default: 2.5 CSPR), with --gas-price-tolerance defaulting to 1. Use --simulate to run a local execution engine via the binary port without submitting the transaction. You can also use tx as an alias.
transaction call
Calls a stored contract by hash (formatted contract-/addressable-entity- or raw hex) using the call entry point. To call by name, pass the named key alias directly. Use --package to interpret the target as a package hash (latest version by default) and --version with --package to select a specific package version. The payment amount is specified in CSPR (default: 2.5 CSPR), with --gas-price-tolerance defaulting to 1. Use --simulate to run a local execution engine via the binary port without submitting the transaction.
transaction get
Fetches execution details for a transaction by hash. Use --finalized-approvals to request finalized approvals and --raw to print only the execution info JSON (or null if missing).
transaction transfer
Transfers CSPR from a wallet account to a target account. The recipient can be a wallet/account reference, public key bytes hex, or account hash bytes hex. You can set --gas-price-tolerance (default: 1). Use --simulate to run a local execution engine via the binary port without submitting the transaction, or --raw to print only the transaction hash.
Argument format
You can pass multiple --arg values. Each arg has one of two forms:
name:cltype=valueto parse the value using full CLType syntax (arbitrarily nested).name=valueto pass raw hex bytes with implicitAnytype (optional0xprefix).
If the arg name contains : or =, escape them with backslashes (e.g. meta\\:x\\=y).
The cltype portion supports arbitrarily nested Rust-like syntax (e.g. Result<Option<U64>, String>).
Aliases are also accepted: account_hash/account-hash => ByteArray[32], byte_array/byte-array
=> ByteArray[...], public_key/public-key => PublicKey, () => Unit.
For Option<T> where T is a basic type (Bool, numeric primitives, String, Key, URef, PublicKey, Unit),
you can supply the human-readable value for Some(T) and the literal None for the none tag. To force
hex bytes for Option<T>, prefix the value with 0x.
Examples:
| --arg example | CLType | value bytes (hex) |
|---|---|---|
--arg flag:Bool=true |
CLType::Bool |
01 |
--arg opt:Option<Bool>=None |
CLType::Option(CLType::Bool) |
00 |
--arg opt:Option<String>=hello |
CLType::Option(CLType::String) |
010500000068656c6c6f |
--arg opt:Option<Bool>=0x0101 |
CLType::Option(CLType::Bool) |
0101 |
--arg msg:String=abc |
CLType::String |
03000000616263 |
--arg amount:U64=1234 |
CLType::U64 |
d204000000000000 |
--arg bytes:List<U8>=0x03000000010203 |
CLType::List(CLType::U8) |
03000000010203 |
--arg res:Result<Option<U64>, U64>=0x01010700000000000000 |
CLType::Result { ok, err } |
01010700000000000000 |
--arg map:Map<String, U32>=0x0200000005000000616c70686101000000040000006265746102000000 |
CLType::Map { key, value } |
0200000005000000616c70686101000000040000006265746102000000 |
--arg pair:(Bool, U32)=0x0102000000 |
CLType::Tuple2([Bool, U32]) |
0102000000 |
--arg data:ByteArray[4]=0x01020304 |
CLType::ByteArray(4) |
01020304 |
--arg acct:account_hash=0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 |
CLType::ByteArray(32) |
0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20 |
--arg payload=0xdeadbeef |
CLType::Any |
deadbeef |
Arguments:
--arg name:cltype=valueto pass a typed argument (CLType syntax supports nesting likeOption<Bool>orResult<U64, U64>).--arg name=valueto pass raw bytes as hex with implicitAnytype (optional0xprefix).
Security notes
Wallet secrets are encrypted at rest by default:
- Key derivation uses Argon2id (memory-hard) with ~64 MiB RAM, 3 iterations, and 1 lane for interactive CLI usage.
- Encryption uses XChaCha20-Poly1305 (AEAD) with a random 24-byte nonce per file.
- The wallet name is bound as AAD during encryption to prevent file-renaming attacks.
- Secret files are written atomically and locked down to restrictive permissions (0600 files, 0700 directories on Unix).
You can opt out of encryption with --unencrypted for local dev workflows when using file storage, but this stores secrets in plaintext.
License
Apache-2.0