How to migrate from the old .env plaintext-key pattern to the new encrypted
named-keystore system.
- Private keys stored in plaintext in
.env(ETH_PRIVATE_KEY_0=0x...) - Single wallet at
~/.config/dincli/wallet.json - Password cached on disk in
~/.config/dincli/.session(15-min TTL, since removed)
- Encrypted named keystores at
~/.config/dincli/wallets/wallet_<name>.json - Each keystore is a standard eth-account keystore wrapped with metadata (address, source, name)
- No disk-based password caching — passphrase entered per command or via
DIN_WALLET_PASSWORD - Runtime selection via
--wallet <name>orDIN_WALLET_NAMEenv var - Legacy
wallet.jsonstill loads as thedefaultaccount for back-compat
dincli no longer caches passwords across command invocations. The old on-disk
CONFIG_DIR/.session file stored plaintext passwords — this has been replaced
with an in-memory cache that lasts only for the duration of a single process.
To avoid re-prompting across commands, set DIN_WALLET_PASSWORD in your .env:
DIN_WALLET_PASSWORD=your_secure_passphraseThis is the only supported no-prompt-across-commands option.
Use the eth-account Python library to export your existing private key as a
standard Ethereum keystore (this is a one-time operation):
python3 -c "
from eth_account import Account
from getpass import getpass
import json
key = getpass('Existing private key (0x...): ')
pw = getpass('Keystore passphrase: ')
ks = Account.encrypt(key, pw)
with open('keystore.json', 'w') as f:
json.dump(ks, f)
print('Keystore exported to ./keystore.json')
"dincli system register-wallet --keystore ./keystore.json --name validatordincli will:
- Prompt for the keystore passphrase
- Decrypt the key to derive and verify the address
- Write the wrapped keystore to
~/.config/dincli/wallets/wallet_validator.json - Set file permissions to
0o600
rm keystore.jsonDo not hand-create or hand-edit files in wallets/ — the internal wrapper
schema is managed by dincli.
If you run dincli via din-node, the keystore lives on the bind-mounted volume
at $DIN_STATE_DIR/config/dincli/wallets/. No changes are needed to
docker-compose.yml — the config/dincli/ directory is already mounted.
To select a named wallet at runtime, add DIN_WALLET_NAME to the .env used by
docker-compose, or pass --wallet with each command:
docker compose exec din-node dincli --wallet validator client submit-lm 0Set DIN_WALLET_NAME in your project .env:
DIN_WALLET_NAME=validatorOr use the top-level flag:
dincli --wallet validator client submit-lm 0| Artifact | Location | Survives restart? |
|---|---|---|
| Encrypted keystore | $DIN_STATE_DIR/config/dincli/wallets/ |
Yes (bind-mounted volume) |
| Passphrase | (never stored) | No — entered each command |
DIN_WALLET_PASSWORD |
.env file on bind-mounted volume |
Yes |
The passphrase is never stored on disk. Each
register-walletor command that needs to unlock the wallet will prompt you, unlessDIN_WALLET_PASSWORDis set.
When resolving the default wallet:
~/.config/dincli/wallets/wallet_default.json(new named default) — wins~/.config/dincli/wallet.json(legacy) — used only as fallback when no named default exists
If you run register-wallet --name default, the new wallets/wallet_default.json
is created and the legacy file is not overwritten.
| Mechanism | Scope | Example |
|---|---|---|
--wallet <name> |
Per-command override | dincli --wallet validator dintoken buy 0.001 |
DIN_WALLET_NAME env var |
Process-level default | export DIN_WALLET_NAME=validator |
Config wallet_name |
Persistent default | Set via dincli system connect-wallet <name> (set-wallet is a deprecated alias) |
| None of the above | Fallback to default |
Legacy wallet.json or wallets/wallet_default.json |
See also: Wallet Setup Guide for creating and funding a new burner wallet.
dincli system list-accountsShows all named keystores with their addresses (read from metadata — no decrypt needed) and marks the currently active wallet.
If a stale ~/config/dincli/.session file exists from a previous dincli
version, it is safe to delete:
rm ~/.config/dincli/.sessiondincli also deletes it automatically on first run after upgrade.