BAL — Bitcoin After Life (Electrum plugin)
Free and decentralized Bitcoin inheritance support for the Electrum wallet. Build time-locked "will" transactions that transfer your funds to your heirs if you stop refreshing them (dead-man's switch), optionally relayed by will-executor servers.
This repository contains a refactored and extended version of the original plugin. The logic was reorganized to cleanly separate business logic from the PyQt GUI, and new features have been added including a headless CLI, auto-rebuild on new transactions, OP_RETURN heirs, and configurable calendar reminders.
Repository layout
bal/ the installable Electrum plugin package
├── manifest.json plugin metadata (Electrum reads this)
├── qt.py Qt entry-point shim (re-exports Plugin)
├── cmdline.py CLI entry-point shim (re-exports Plugin)
├── core/ GUI-free logic (importable without Qt)
│ ├── util.py
│ ├── plugin_base.py
│ ├── heirs.py
│ ├── will.py
│ ├── willexecutors.py
│ ├── checkalive.py
│ ├── reminders.py
│ └── input_rules.py
├── cli/ headless command-line layer (no Qt)
│ ├── commands.py bal_* daemon commands (@plugin_command)
│ ├── controller.py headless BalController (replicates BalWindow)
│ └── plugin.py CLI Plugin entry point
├── gui/qt/ PyQt6 presentation layer
│ ├── theme.py status → color mapping
│ ├── common.py shared imports / helpers
│ ├── widgets.py leaf widgets
│ ├── calendar.py calendar widget
│ ├── dialogs.py dialog windows
│ ├── lists.py tree/list views
│ ├── window.py per-wallet GUI controller
│ ├── window_utils.py GUI utility helpers
│ └── plugin.py Plugin (Electrum @hooks → GUI)
├── icons/ wallet_util/ LICENSE README.md
build_zip.py builds a clean, zipimport-friendly distribution zip
tests/ smoke + external-zip regression tests
Requirements
- Electrum 4.7.2 or 4.8.0 — the plugin detects which wallet-DB
registration API is available (
json_db.register_dicton 4.7.2,stored_dict.register_nameon 4.8.0) and adapts automatically. - PyQt6 (bundled with the Electrum desktop GUI).
Wallet compatibility
BAL currently supports standard (single-signature) wallets and
hardware wallets supported by Electrum. Multisig wallets and
Electrum TrustedCoin (2FA) wallets are not yet supported — see
COMPATIBILITY.md for the full compatibility matrix and
current status.
Installation
Build the distribution archive
python3 build_zip.py
# -> bal-electrum-plugin.zip (prints size + SHA-256 for integrity checks)
The builder writes a zipimport-friendly archive (files only, standard
DEFLATE, deterministic order) to avoid loader errors seen on some Electrum
portable builds.
Install as an external plugin (zip)
- Electrum → Tools → Plugins → install from file → pick the built zip.
- Enable Bitcoin After Life and restart Electrum.
- (Recommended) verify the downloaded zip's SHA-256 matches the value printed
by
build_zip.py.
Install as an internal plugin
Copy the bal/ directory into your Electrum installation's
electrum/plugins/ directory, so that electrum/plugins/bal/manifest.json
exists, then enable it from Tools → Plugins.
Command-line / headless usage
BAL can be used without the Qt GUI via Electrum's daemon mode. The CLI layer
exposes bal_* commands that replicate the full inheritance cycle.
Prerequisites
- An Electrum daemon running (
electrum daemon -d) - A wallet loaded (
electrum load_wallet)
Available commands
| Category | Commands |
|---|---|
| Settings | bal_settings_list, bal_settings_get, bal_settings_set, bal_settings_reset |
| Heirs | bal_heirs_list, bal_heirs_show, bal_heirs_add, bal_heirs_update, bal_heirs_delete, bal_heirs_import, bal_heirs_export |
| Will-Executors | bal_willexecutors_list, bal_willexecutors_show, bal_willexecutors_add, bal_willexecutors_update, bal_willexecutors_select, bal_willexecutors_delete, bal_willexecutors_ping, bal_willexecutors_download, bal_willexecutors_import, bal_willexecutors_export |
| Will | bal_will_status, bal_will_check, bal_will_prepare, bal_will_autorebuild, bal_will_sign, bal_will_broadcast, bal_will_export, bal_will_import_merge, bal_will_invalidate, bal_will_check_executor |
Example workflow
electrum daemon -d
electrum load_wallet
electrum bal_heirs_list
electrum bal_will_prepare
electrum bal_will_sign --password '...'
electrum bal_will_broadcast
electrum stop
All commands require a running daemon (Electrum's plugin_command enforces
this). Wallet-bound commands (bal_heirs_*, bal_will_*, etc.) require the
wallet to be loaded first. Signing commands require --password for encrypted
wallets.
Inheritance safety: anticipate / postpone
A will transaction is signed with a fixed, immutable locktime and then optionally sent to will-executor servers, which are economically incentivised to broadcast it (they collect fees). Because the locktime is baked into the signed transaction, simply changing the delivery time later is not enough: the old, already-signed transaction keeps living on the will-executors.
The plugin handles the cases as follows (triggered when you press Prepare on the WILL tab):
- Anticipate (new delivery time earlier than the signed locktime, still in the future): a plain rebuild — the transactions are re-created with the new, earlier locktime. No on-chain invalidation and no Bitcoin fee, even if the will was already signed/sent: moving the date earlier only makes the inheritance available sooner, so there is no early-execution risk.
- Expire (new delivery time now in the past): the will is genuinely expired and you are asked to invalidate the old transaction on-chain, then rebuild.
- Postpone (new delivery time later than the signed locktime) on a will
that was already signed and/or pushed: the previously committed coins
must be invalidated on-chain first, otherwise a will-executor could
broadcast the old (earlier-locktime) transaction and execute the inheritance
too early. The plugin detects this by comparing the requested locktime with
the locktime frozen inside the signed transaction (
tx.locktime), and asks you to sign and broadcast an invalidation transaction. After it is broadcast, press Prepare again to rebuild, re-sign and re-send the new (postponed) inheritance. Postponing a will that was never signed/sent just rebuilds it (no on-chain fee).
Transaction list: the "Server" column
The will transaction list shows a dedicated Server column so you always know whether each inheritance transaction is actually stored on the will-executor servers, independently of the row colour:
| Label | Meaning |
|---|---|
Confirmed on server |
the will-executor confirmed it stored the transaction |
Sent (not checked) |
pushed to the will-executor, not yet re-checked |
Send failed / Not on server |
push failed or the server no longer has it |
Signed (not sent) |
signed locally, not sent to any will-executor |
Not sent |
not signed/sent yet |
Hovering the cell shows a tooltip with the will-executor URL and the current state.
Testing
Run the tests with the runtime environment active (see HANDOFF.md §3 for
the two venvs and how to activate them):
# imports + behavior
QT_QPA_PLATFORM=offscreen python3 tests/smoke_test.py electrum.plugins.bal
# external-zip loading regression (run after build_zip.py)
QT_QPA_PLATFORM=offscreen python3 tests/external_zip_test.py bal-electrum-plugin.zip
⚠️ Safety
This plugin builds real Bitcoin inheritance transactions with time-locks. Test on testnet or a fund-less wallet first, and review the generated transactions before broadcasting.
License
MIT — see bal/LICENSE.