grenadeandClaude Fable 5.1 5776cfd218
ci / gate (push) Successful in 4m56s
feat(keystore): read and write quantus-cli wallet files, byte for byte
`wallet_data::keystore` is the CLI's format: AES-256-GCM over the JSON of
the wallet data, keyed by Argon2id under the frozen profile (m=19456, t=2,
p=1) and a 16-byte salt, with the PHC string carrying the profile and salt
and never the digest. A file whose PHC string does embed a digest is refused,
as the CLI refuses it. On open the address is re-derived from the decrypted
key and the file refused if it differs, so a file that lies about its
address cannot be opened, let alone signed with. Legacy files with no
`scheme` are ML-DSA-87; files with no `wallet_type` are hot.

The directory rules are the CLI's too: a wallet name is a plain filename,
writes go through an unpredictable temporary file and a no-clobber rename
at mode 0600, and a symlink where a wallet should be is refused.

Proof in both directions. Eight real files open here: six written by
quantus-cli 2.2.2 for the dev phrase, one per scheme and path, and the two
fixtures the extension fork tests against. A file written here lists in
`quantus wallet list` with the expected address (ignored test, run with
QUANTUS_CLI set). A test greps the written file for phrase words and secret
key bytes and finds neither.

`Keystore` is a port in wallet-core: list, open, create, import a file,
export a file. Opening yields a `Signer` and, when the file carries one, the
phrase in a wiping holder; neither leaves Rust.

Closes #15

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ftBXYuba8ARhQeF74oUgW
2026-09-15 18:19:27 +03:00

blackbeard wallet

A desktop wallet for post-quantum chains, Quantus first. Linux, Windows and macOS; installable on Fedora with dnf.

Shape

The wallet is a Rust cargo workspace with a Tauri shell and a React webview. That split is the security model, not a convenience: every key, signature, decoded transaction and amount lives on the Rust side, and the webview only renders what a Tauri command hands it. Nothing that could serialise a secret is reachable from JavaScript.

crates/
  wallet-entities/   domain types and the IPC wire protocol; exported to TypeScript
  wallet-core/       wallet logic and the ports it is written against
  wallet-data/       adapters behind those ports: keystore, cache, RPC, provider APIs
  wallet-app/        the Tauri binary; commands are one-line shims into core
ui/                  Vite + React + TypeScript webview

The ports in wallet-core are what make "any post-quantum chain" a profile rather than a rewrite:

  • KeyScheme turns a seed and a path into a signer. ML-DSA-65 and ML-DSA-87 now; whatever the next chain uses later.
  • ChainAdapter knows one chain: balances, building and submitting a transaction, watching it. The Substrate adapter is driven by runtime metadata plus a small per-chain profile (ss58 prefix, decimals, signature enum, transaction extensions, signing-context rule, coin type).
  • SwapProvider is a swap venue. NEAR Intents first.
  • FiatRamp builds a provider session through a relay on our infrastructure, which holds the provider secrets, and opens it in the system browser.

The wallet is post-quantum only. Classical chains appear only as transit legs of a swap or ramp; the wallet never derives a secp256k1 or ed25519 key.

Why these choices

Quantus signs extrinsics with ML-DSA, hashes public keys with Poseidon2 for the account id, and shields mining rewards behind a Plonky2 wormhole whose prover is minutes of native CPU. All of that exists as Rust crates and nothing else, so the core is Rust. Tauri is the house desktop convention (~/git/architecture/generic.md §4) and the only shell that packages rpm, deb, msi and dmg with a Rust-owned IPC boundary out of the box.

NEAR's post-quantum work (their MPC fork with threshold ML-DSA-87) is not yet able to sign a Quantus extrinsic, so the swap module is built and tested against chains NEAR Intents already lists, with Quantus as a registry entry that lights up when the bridge does.

Building

pnpm --dir ui install
cargo tauri dev --config crates/wallet-app/tauri.conf.json   # from crates/wallet-app: cargo tauri dev
cargo test --workspace                                        # also regenerates ui/src/api/generated

The CI gate is cargo fmt --check, cargo clippy -D warnings, cargo test, and the webview's typecheck, lint and build. Run them before claiming done.

Work

Work is filed before it is done. Epics carry the epic label and an external definition of done; their steps carry child, in dependency order, at https://git.lair.cafe/blackbeard/wallet/issues. A commit that finishes a child closes it (Closes #N); when an investigation contradicts an issue, the correction is a comment on the issue, dated, not a surprise in a diff.

S
Description
Desktop wallet for post-quantum chains, Quantus first: ML-DSA signing in Rust, Tauri shell, NEAR Intents swaps and fiat ramps via transit chains. Linux (rpm/deb), Windows and macOS.
Readme
3.7 MiB
v0.4.1
Latest
2026-10-12 08:37:06 +00:00
Languages
Rust 73.4%
TypeScript 23.3%
CSS 1.6%
Python 1.2%
Shell 0.3%
Other 0.1%