Back up and restore a wallet
Recovery from a phrase reconstructs your funds, not your records.
On Bitcoin, rescanning from a seed rebuilds your full transaction history, because the history is public and permanently associated with your keys. On Epic there is no public history to rebuild from. The chain holds blinded commitments with no sender, recipient or readable amount, so a rescan can identify which outputs are yours and nothing else about how they got there.
What to back up
| Item | Contains | Priority |
|---|---|---|
| Recovery phrase | The master secret, as words | Critical. Losing it with no seed file loses the funds |
wallet_data/wallet.seed | The same secret, encrypted with your password | Critical, and useless to a thief without the password |
wallet_data/db/sqlite/epic.db | Transaction history, account labels, slate messages, payment proof records | Important. Not recoverable from anywhere else |
wallet_data/saved_txs/ | Stored transaction objects | Important if you ever need repost |
epic-wallet.toml | Your settings | Convenience. A fresh init regenerates defaults |
Safe to lose: epic-wallet.log, wallet_tor/, .owner_api_secret, and the
SQLite -wal and -shm files when the wallet is not running.
.api_secret must match the node'sThe wallet's .owner_api_secret regenerates on next run. Its .api_secret is the credential the wallet
presents to the node, so deleting it breaks node calls until the node's value is copied back in. See
the credential the wallet presents to the node.
Backing up
The phrase is the only thing you strictly need, and it is printed once by init. To display it again:
epic-wallet recover
This prompts for your password, decrypts the seed and prints the phrase. It writes nothing and does not perform a recovery.
For a full backup, stop the wallet and copy the directory. Both commands below name the archive after the current date, and the restore section reuses the same name:
- Linux and macOS
- Windows
# Stop any listener or owner_api process first so SQLite is not mid-write.
stamp=$(date +%F)
tar czf "$HOME/epic-wallet-backup-$stamp.tar.gz" \
-C ~/.epic/main \
wallet_data epic-wallet.toml
# Verify the archive lists what you expect before trusting it.
tar tzf "$HOME/epic-wallet-backup-$stamp.tar.gz" | head
# Stop any listener or owner_api process first so SQLite is not mid-write.
$stamp = Get-Date -Format 'yyyy-MM-dd'
Compress-Archive -Path "$HOME\.epic\main\wallet_data", "$HOME\.epic\main\epic-wallet.toml" `
-DestinationPath "$HOME\epic-wallet-backup-$stamp.zip"
# Verify
Expand-Archive -Path "$HOME\epic-wallet-backup-$stamp.zip" -DestinationPath "$env:TEMP\verify" -Force
Get-ChildItem -Recurse "$env:TEMP\verify" | Select-Object -First 10
Keep the phrase and the archive in different places. The archive without the password is useless; the phrase alone is enough to move funds. Restore an archive into a scratch directory once before you need it, using the procedure in restoring a full directory backup.
SQLite runs in WAL mode. Copying epic.db while a wallet process is writing can produce an archive that
restores to a corrupt database. Stop listen and owner_api first.
Restoring from a phrase
- Linux and macOS
- Windows
mkdir -p ~/restored
cd ~/restored
epic-wallet init -w -r
New-Item -ItemType Directory -Force -Path "$HOME\restored"
Set-Location "$HOME\restored"
epic-wallet init -w -r
You will be prompted for the phrase, then for a new password. The phrase is validated on entry, so a mistyped word is rejected before the wallet is created.
-w puts the wallet in the current directory. It is a flag on init and takes no value, so
epic-wallet -w . init is not valid. To point a later command at a wallet outside ~/.epic/<network>,
either run it from that directory or pass --current_dir <path>.
Then rescan the chain to find your outputs:
epic-wallet scan
epic-wallet info
init -r marks the wallet as needing a scan, so this step is required rather than optional. Until it
completes, the wallet does not know it owns anything.
The scan walks the chain testing outputs against your keys. It needs a node that is fully synced, and on
mainnet it is not quick. -s starts it at a height instead of at 0:
epic-wallet scan -s <height>
Choose a height at or below the block that produced the wallet's first output. Any of these give one:
- The
confirmation_heightof the earliest entry inepic-wallet txson a device that still has the history. - The tip height at the time the wallet was created, from the block explorer.
- A round number safely below either. Starting too low costs scan time; starting above the first output silently misses it and the balance comes back short.
With no -s the scan starts at 0, which is always correct and always the slowest.
What recovery does not bring back
Recovered by init -r plus scan | Not recovered |
|---|---|
| All outputs belonging to your seed | Transaction history, who you paid and when |
| Correct spendable balance | Account labels, which are replaced by generated ones |
| The ability to spend everything you own | Slate messages attached to past transfers |
| Your epicbox, proof and Tor addresses | Payment proof records for past transfers |
Stored transaction objects, so repost will not work for old transfers | |
| Any transfer that was in flight when you lost the wallet |
Using the same recovery phrase on more than one device does not synchronize the wallets. Each instance
derives the same keys and, after scanning against a synced node, identifies the same current outputs and
calculates a valid balance. The transaction log is local database state, so each device records only the
transfers it took part in, and one device can show the correct balance while missing transfers and status
details recorded on the other. scan repairs output and balance state; it does not merge those records.
A recovery scan restores derivation paths, so outputs return to the account branch they were derived
under. Labels do not survive: default keeps its name, and each other path found is labelled
account_1, account_2 and so on in the order the scan discovers it
(libwallet/src/internal/scan.rs:512). Rename by creating the
labels you want, then moving the funds with the self transport:
epic-wallet account # list what the scan found, with each path
epic-wallet account -c savings
epic-wallet -a account_1 send -m self -d savings <amount>
See accounts.
In-flight transfers cannot be recovered
If a transfer was partly built when the wallet was lost, it is gone. The counterparty may still hold a slate referencing outputs you now own, but your side has no record of the exchange and the reserved-output state was in the lost database.
After a recovery scan those outputs appear spendable again. If the counterparty later submits a finalised transaction built from them, whichever transaction confirms first wins and the other becomes invalid. Agree with the counterparty which attempt is live before resending. See interactive transactions.
Restoring a full directory backup
If you kept the whole wallet_data directory, restore that instead of recovering from the phrase. It
brings back history, labels and proof records as well as funds. Substitute the archive you actually made
in backing up; the date in the filename is the day it was created.
- Linux and macOS
- Windows
stamp=2026-08-22 # the date on the archive you are restoring
mkdir -p ~/.epic/main
tar xzf "$HOME/epic-wallet-backup-$stamp.tar.gz" -C ~/.epic/main
epic-wallet info
$stamp = '2026-08-22' # the date on the archive you are restoring
New-Item -ItemType Directory -Force -Path "$HOME\.epic\main"
Expand-Archive -Path "$HOME\epic-wallet-backup-$stamp.zip" `
-DestinationPath "$HOME\.epic\main" -Force
epic-wallet info
If the figures disagree with the chain afterwards, run epic-wallet scan to rebuild output state. That
leaves your history intact.
Recovering into a directory that already has a wallet
The CLI will not do it. init -r still goes through wallet creation, which refuses when a seed file is
present (impls/src/lifecycle/default.rs:188), and there is no override
flag.
Move the existing wallet aside first:
- Linux and macOS
- Windows
mv ~/.epic/main/wallet_data/wallet.seed ~/.epic/main/wallet_data/wallet.seed.old
epic-wallet init -r
Move-Item "$HOME\.epic\main\wallet_data\wallet.seed" "$HOME\.epic\main\wallet_data\wallet.seed.old"
epic-wallet init -r
init without -r to "reset" a walletinit on its own generates a brand-new seed. If you delete wallet_data/ but keep epic-wallet.toml,
init proceeds and you end up with an empty wallet holding none of your funds. They are then reachable
only from the phrase.
Changing your password
epic-wallet change_password
The seed is re-encrypted with the new password. The phrase does not change, so an old backup of the phrase remains valid.
change_password writes wallet.seed.bak before re-encrypting, then deletes it once the new password is
confirmed. Passing --remove-backup keeps the file instead
(src/cmd/wallet_args.rs:452). Delete a kept backup once you have
confirmed the new password works.
scan --delete_unconfirmed is destructive
Plain scan rebuilds. Adding -d deletes unconfirmed outputs, unlocks locked outputs, and deletes the
transaction log entries associated with them.
The case for it is a wallet holding reserved outputs whose transfers are dead and which cancel cannot
clear. It removes history. Try cancelling individual transfers first.