| name | fedimint-bitcoin-wallet |
| description | Use when a user wants to hold and send Bitcoin with `fedimint-cli` — a wallet that keeps a Bitcoin balance in a Fedimint federation and can send or receive it three ways: over **Lightning** (instant payments via a gateway), **on-chain** (deposit/withdraw regular Bitcoin), and as **ecash** (private bearer notes handed directly to another person). Covers joining a federation from an invite code, checking your balance, and backing up. Triggers on: "fedimint-cli", "fedimint wallet", "bitcoin wallet", "hold bitcoin", "send bitcoin", "join federation", "invite code", "ecash", "e-cash", "reissue", "spend notes", "ln-invoice", "ln-pay", "lightning invoice", "deposit address", "peg-in", "peg-out", "withdraw on-chain", "fedimint balance", "fedimint backup". |
A Bitcoin wallet with fedimint-cli
fedimint-cli lets a single user hold and send Bitcoin through a Fedimint federation. Your
balance is real Bitcoin, held on your behalf by the federation's guardians, and you can move it three
ways:
- Lightning — send and receive instant Bitcoin payments, brokered by a gateway.
- On-chain — deposit or withdraw ordinary Bitcoin (peg-in / peg-out with the federation's wallet).
- Ecash — hand private bearer notes directly to another person, no third party in the loop.
Under the hood: the balance you hold is Chaumian ecash — private, bearer Bitcoin tokens issued
by the federation. Lightning and on-chain are simply ways to convert value into or out of that ecash
balance. You mostly don't need to think about this; it's why payments are private and instant.
Setup
1. Install fedimint-cli
Pick the method that matches the platform. On Debian/Ubuntu use the .deb — it is by far the
cleanest path. None of these paths require the Nix package manager — the .deb/.rpm/darwin
binaries simply bundle their libraries under /nix/store and run without any nix command, daemon,
or /nix setup. (Verified on Ubuntu 24.04, Debian 12, and Arch with no Nix installed.)
Debian / Ubuntu (.deb):
apt-get update && apt-get install -y curl
curl -L -O https://github.com/fedimint/fedimint/releases/download/v0.11.1/fedimint-cli_0.11.1_amd64.deb
apt-get install -y ./fedimint-cli_0.11.1_amd64.deb
fedimint-cli version-hash
The .deb is ~170 MB — let the download finish before installing. Installing a truncated file
fails with a misleading E: Invalid archive member header. curl -L -O (no progress bar in scripts)
gives no hint; check the file size or use curl -fL so a failed download errors instead of half-writing.
(Fedora/RHEL: the same page has fedimint-cli-0.11.1-1.x86_64.rpm — dnf install ./…rpm.)
macOS (Apple Silicon): use the prebuilt darwin tarball — no Homebrew/Nix/admin needed, and a
curl download isn't Gatekeeper-quarantined so it runs as-is:
curl -fL -O https://github.com/fedimint/fedimint/releases/download/v0.11.1/fedimint-pkgs-v0.11.1-aarch64-apple-darwin.tar.gz
tar xzf fedimint-pkgs-v0.11.1-aarch64-apple-darwin.tar.gz
./bin/fedimint-cli version-hash
Note the macOS/BSD userland lacks GNU niceties: grep -P and the timeout command aren't available
(install coreutils via Homebrew for gtimeout, or use jq for JSON extraction below).
NixOS / any system with Nix:
nix profile install --accept-flake-config github:fedimint/fedimint/v0.11.1#fedimint-cli
Requires Nix with flakes enabled (experimental-features = nix-command flakes). On NixOS do not
use the raw release binary below — an unpatched dynamically-linked binary won't run; use Nix.
Arch / other Linux (no apt/dnf): two nix-free options —
Docker: the CLI ships in the fedimintd image:
docker run --rm -v fm-cli-data:/data fedimint/fedimintd:v0.11.1 fedimint-cli --data-dir /data info
2. Pick a data directory
The client stores its keys and database in a data directory. Set it once so every command uses the
same wallet — a different data dir is a different, empty wallet.
export FM_CLIENT_DIR="$HOME/.fedimint-cli"
mkdir -p "$FM_CLIENT_DIR"
Every command below can also take --data-dir <dir> explicitly. In scripts or any non-interactive
setting where each command runs in a fresh shell (so the export above won't persist), pass
--data-dir on every invocation instead — otherwise you silently get a fresh, empty wallet.
3. Join a federation
You need an invite code (fed11…) from the federation you want to use.
fedimint-cli join <INVITE_CODE>
fedimint-cli info
info prints the federation id, network, meta fields, and your holdings:
{
"denominations_msat": { "1": 2, "2": 3, "512": 3, "1024": 3 },
"federation_id": "c166a596345c126c2cde3fc57e399fec48b1ad741b49dcd48d313cb6cd4458b8",
"meta": { "federation_name": "Devimint Federation" },
"network": "regtest",
"total_amount_msat": 495166,
"total_num_notes": 41
}
Units — read this, it is the #1 footgun: amounts default to millisatoshis (msat). This
includes spend, ln-invoice --amount, and withdraw --amount. A bare number is msat:
withdraw --amount 20000 means 20 000 msat = 20 sats, which fails as "under the dust limit".
To withdraw 20 000 sats, write --amount 20000000 (msat) or use an explicit unit suffix:
--amount '20000 sat' or --amount 0.0002btc. total_amount_msat: 495166 = 495 166 msat ≈ 495 sats.
(deposit-address takes no amount — you send BTC to the address from elsewhere.)
Fees: the credited amount is often slightly less than the nominal amount. Reissuing/receiving
ecash can incur a small federation mint fee (e.g. reissue of 500 000 msat may credit ~495 000),
and receiving Lightning pays the gateway's fee. This is expected, not an error — check info for
the actual balance.
Ecash (out-of-band notes)
Ecash is transferred by handing someone a base64 note string. The sender spends (removing the value
from their wallet), the receiver reissues (claiming it). Reissue also prevents double-spends.
fedimint-cli spend 100000
fedimint-cli reissue BgAAAA…
fedimint-cli validate BgAAAA…
fedimint-cli dev decode notes BgAAAA…
spend fails if it can't represent the exact amount with available note denominations (notes come
in powers of two, so round decimal amounts like 500 000 often can't be made exactly). Add
--allow-overpay to send slightly more instead of failing.
- Spent-but-unclaimed notes are auto-reclaimed by the sender after
--timeout seconds (default 1 week),
so a receiver who never redeems doesn't cost the sender the money permanently.
- Add
--include-invite to spend so the receiver can join the federation from the notes alone.
The forward-looking form is fedimint-cli module mint {spend,reissue,split,combine}; the top-level
spend/reissue still work and print a deprecation note — either is fine.
Lightning (via a gateway)
Lightning payments are brokered by a gateway. List the gateways the federation knows and,
optionally, pick one:
fedimint-cli list-gateways
fedimint-cli switch-gateway <GATEWAY_ID>
Receive over Lightning
fedimint-cli ln-invoice --amount 100000
fedimint-cli await-invoice 5b37…
fedimint-cli info
Send over Lightning
fedimint-cli ln-pay "lnbcrt1u1p…"
Notes:
- Sending needs enough ecash balance; receiving needs the gateway to have inbound Lightning liquidity.
- If a payment fails, try
switch-gateway to a different gateway, or check list-gateways for one
that is active.
- The newer LNv2 protocol is under
fedimint-cli module lnv2 {receive,send,await-receive,await-send}.
On-chain Bitcoin (peg-in / peg-out)
Deposit (peg-in): on-chain BTC -> ecash
fedimint-cli deposit-address
fedimint-cli await-deposit <OPERATION_ID>
fedimint-cli info
Deposits need the federation's finality_delay in confirmations (often ~10 blocks) before the ecash
is credited. await-deposit blocks until then, and on success prints a bare null — that is not
an error; confirm the credit with info.
Withdraw (peg-out): ecash -> on-chain BTC
fedimint-cli withdraw --amount 50000000 --address bcrt1q…
fedimint-cli withdraw --amount '50000 sat' --address bcrt1q…
fedimint-cli withdraw --amount all --address bcrt1q…
The response contains a txid and fees_sat. On regtest the peg-out is broadcast once the federation
signs it; mine a block to confirm.
Backup & restore
The client is deterministic from a BIP-39 mnemonic; ecash notes can be recovered by restoring from
the federation's encrypted backup.
fedimint-cli print-secret
fedimint-cli backup
fedimint-cli restore --mnemonic "word1 word2 …" --invite-code fed11…
Restore is a scan and can take a while; run fedimint-cli info afterwards to confirm balances.
Quick reference
| Goal | Command |
|---|
| Join federation | fedimint-cli join <invite> |
| Balance / info / meta | fedimint-cli info |
| Read federation meta fields | fedimint-cli dev meta-fields |
| Send ecash | fedimint-cli spend <msat> → give notes |
| Receive ecash | fedimint-cli reissue <notes> |
| Receive Lightning | fedimint-cli ln-invoice --amount <msat> → await-invoice <op_id> |
| Send Lightning | fedimint-cli ln-pay <bolt11> |
| List/switch gateway | fedimint-cli list-gateways / switch-gateway <id> |
| Deposit on-chain | fedimint-cli deposit-address → await-deposit <op_id> |
| Withdraw on-chain | fedimint-cli withdraw --amount <msat, or '<n> sat'> --address <addr> |
| Backup / restore | fedimint-cli backup / restore --mnemonic … --invite-code … |
Common mistakes & troubleshooting
- Empty balance after
join: joining does not fund you. You need someone to spend you ecash,
a Lightning payment, or an on-chain deposit.
- Wrong wallet: if
info shows an unexpected balance, you are almost certainly pointing at a
different --data-dir/FM_CLIENT_DIR. Keep it consistent.
- msat vs sats: every
--amount (ecash, LN, and on-chain withdraw) defaults to msat. A
small bare number on withdraw fails as "under the dust limit" — use <n>000 msat or '<n> sat'.
spend fails with an amount error: denominations can't represent it exactly — use
--allow-overpay.
- Lightning payment fails / no gateway:
list-gateways; if the active one is down, switch-gateway
to another.
- Deprecation warnings on
spend/reissue/ln-invoice/etc. are expected — the commands still work.
- Deposit not credited: on-chain deposits wait for the federation's
finality_delay confirmations;
keep await-deposit running (on regtest you must mine blocks).
- A killed or contested
reissue can wedge the wallet: interrupting reissue, or reissuing notes
that were already spent/double-spent, can hang and leave a stuck pending state that makes later
commands panic (e.g. Cannot claim input, additional funding needed). Recover by starting over in a
fresh --data-dir and re-joining (your on-federation backup can be restored there). Only reissue
notes you control and haven't already claimed.
- Discover any subcommand's flags with
fedimint-cli help or fedimint-cli <cmd> --help.