Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RustWallet — starter scaffold

A minimal but real BDK-powered Bitcoin wallet: create/import a seed, derive a BIP84 SegWit wallet, show balance, generate a receive address + QR code. Runs on desktop, Android, and iOS from the same codebase via Dioxus.

Honesty check: this was written and reviewed against the documented APIs of bdk_wallet, bdk_file_store, bdk_esplora, bip39, and dioxus, but it has not been compiled — the environment that produced it has no internet access to fetch crates. Treat this as a strong, carefully-written first draft, not a verified build. The first time you run cargo build, expect to fix a handful of small things (an import path, a method that got renamed in a point release). That's normal Rust development against fast-moving crates, not a sign something's fundamentally wrong. Paste me the compiler error if you get stuck — that's the fastest way for me to fix it exactly.

What's already written for you

core/src/
  lib.rs        — module wiring
  mnemonic.rs   — generate/parse a 12-word seed, derive BIP84 descriptors
  wallet.rs     — open-or-create wallet, receive address, balance, persist
  chain.rs      — sync balance/history from an Esplora server (testnet)

ui/src/
  main.rs           — app state, screen routing
  screens/welcome.rs    — "Create New Wallet" / "Import Existing Wallet"
  screens/seed_backup.rs — "write these words down" screen
  screens/home.rs       — balance + Receive button (Send is stubbed)
  screens/receive.rs    — address + QR code

What's not included yet, on purpose (see "Next steps" below): sending transactions, Lightning, biometric lock, encrypted-at-rest storage, and anything mainnet-related. Build and test the above first — it's the foundation everything else sits on.

Setup — run these in order

1. Scaffold the two crates

mkdir rustwallet && cd rustwallet

# Core logic crate
cargo new --lib core

# UI crate — let Dioxus's own CLI generate this, don't hand-write it.
# When prompted, pick the blank/minimal template.
dx new ui
cd ui && dx new . --platform mobile 2>/dev/null; cd ..   # if dx new asked for a platform separately, this covers it — otherwise ignore

(If dx new ui already asked you to choose a platform interactively, just pick "mobile" or "desktop" — you can run on any platform afterward regardless of what's marked default.)

2. Make it a workspace

Replace whatever Cargo.toml exists at the rustwallet/ root with:

[workspace]
members = ["core", "ui"]
resolver = "2"

(This file is also provided at the root of this download — just copy it in.)

3. Add dependencies — via cargo add, not by hand

cd core
cargo add bdk_wallet@2.3.0
cargo add bdk_file_store
cargo add bdk_esplora --features blocking
cargo add bip39
cargo add anyhow

cd ../ui
cargo add core --path ../core
cargo add qrcode

cargo add resolves versions that are actually compatible with each other today — typing version numbers into Cargo.toml by hand is how you end up with a dependency graph that doesn't resolve.

4. Drop in the real source files

Copy every file from this download's core/src/ over what cargo new generated, and every file from ui/src/ (including the whole screens/ folder) over what dx new generated. Overwrite freely — the generated boilerplate isn't needed.

5. Run it

cd rustwallet
dx serve --platform desktop      # fastest loop — start here
dx serve --platform android       # once desktop works
dx serve --platform ios           # macOS only

Try it

  1. Launch the app → "Create New Wallet"
  2. Write down (mentally, this is testnet) the 12 words → confirm
  3. You land on Home with a 0 sats balance — this is a brand-new wallet, nothing's synced yet
  4. Tap Receive → you get a real testnet address + QR code
  5. Get testnet coins to that address from a faucet (search "bitcoin testnet faucet") and you'll want to wire up core::chain::full_scan from main.rs to actually see the balance update — that's wired as a library function but not yet called from a UI button. That's a good first thing to add yourself, or ask me to add a "Refresh" button that calls it.

Next steps, roughly in the order I'd tackle them

  1. Wire up the sync button — call core::chain::full_scan from a "Refresh" button on Home, using core::chain::endpoints::MEMPOOL_SPACE_TESTNET.
  2. Build the Send screenbdk_wallet's TxBuilder (via wallet.build_tx()) handles coin selection and PSBT construction; you'll sign with wallet.sign() and broadcast via the same Esplora client used for syncing.
  3. Encrypt the seed at rest — right now nothing encrypts wallet.db or the mnemonic. Before this touches real money, add aes-gcm + argon2 (derive a key from a user PIN) around however you persist the mnemonic, or better, push the mnemonic into the OS Keychain / Android Keystore via Dioxus's native FFI bridge instead of storing it yourself.
  4. Biometric unlock — small native Swift/Kotlin snippet, called through Dioxus.
  5. Lightning — add ldk-node as a new module in core, once on-chain send/receive is solid. Don't start here.
  6. Only after all of the above, and ideally a security review — consider a mainnet build.

A note on safety

This handles real cryptographic key material once you give it a real seed. Keep all development on testnet (already the default in main.rs) until send, receive, and restore-from-seed have all been exercised repeatedly and you understand exactly what every line of wallet.rs does. Don't point this at mainnet funds without a security review — losing a private key in a wallet app means losing money, permanently, with no recourse.

Bitcoinwallet

Bitcoinwallet

About

Written in rust

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages