|
| 1 | +# CLAUDE.md - Agent Instructions for bdk-wasm |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +WASM bindings for [BDK](https://github.com/bitcoindevkit/bdk_wallet) (Bitcoin Dev Kit). |
| 6 | +Wraps `bdk_wallet` for use in browsers and Node.js via `wasm-bindgen`. |
| 7 | + |
| 8 | +**Used in production by MetaMask Bitcoin Snap (~30M+ AUM). Treat all changes with extreme care.** |
| 9 | + |
| 10 | +## Architecture |
| 11 | + |
| 12 | +``` |
| 13 | +src/ |
| 14 | +├── lib.rs # Crate root, re-exports |
| 15 | +├── bitcoin/ # Core wallet functionality wrappers |
| 16 | +│ ├── wallet.rs # Wallet (create, load, sign, sync, addresses, UTXOs) |
| 17 | +│ ├── tx_builder.rs # Transaction builder |
| 18 | +│ ├── esplora_client.rs # Esplora blockchain client (behind `esplora` feature) |
| 19 | +│ ├── descriptor.rs # Descriptor utilities |
| 20 | +│ └── wallet_tx.rs # Wallet transaction wrapper |
| 21 | +├── types/ # WASM-compatible type wrappers (From/Into pattern) |
| 22 | +│ ├── address.rs, amount.rs, balance.rs, block.rs, chain.rs, |
| 23 | +│ │ changeset.rs, checkpoint.rs, error.rs, fee.rs, input.rs, |
| 24 | +│ │ keychain.rs, network.rs, output.rs, psbt.rs, script.rs, |
| 25 | +│ │ slip10.rs, transaction.rs |
| 26 | +│ └── mod.rs |
| 27 | +└── utils/ # Helpers (descriptor utils, panic hook, result type) |
| 28 | +``` |
| 29 | + |
| 30 | +### Pattern |
| 31 | + |
| 32 | +Every BDK type is wrapped with a WASM-compatible struct that: |
| 33 | +1. Holds the inner BDK type |
| 34 | +2. Implements `From<BdkType>` and `Into<BdkType>` conversions |
| 35 | +3. Exposes methods via `#[wasm_bindgen]` |
| 36 | + |
| 37 | +`Wallet` uses `Rc<RefCell<BdkWallet>>` because `wasm_bindgen` doesn't support Rust lifetimes. |
| 38 | +`TxBuilder` shares the wallet reference via `Rc<RefCell<>>` and builds its own parameter set, |
| 39 | +then calls the real BDK builder in `finish()`. |
| 40 | + |
| 41 | +## Building |
| 42 | + |
| 43 | +Requires: Rust stable, `wasm-pack`, `wasm32-unknown-unknown` target. |
| 44 | + |
| 45 | +```bash |
| 46 | +# Browser target (default) |
| 47 | +wasm-pack build --all-features |
| 48 | + |
| 49 | +# Node.js target |
| 50 | +wasm-pack build --target nodejs --all-features |
| 51 | + |
| 52 | +# Specific features |
| 53 | +wasm-pack build --features esplora |
| 54 | +wasm-pack build --features debug,esplora |
| 55 | +``` |
| 56 | + |
| 57 | +## Testing |
| 58 | + |
| 59 | +### Browser tests (Rust) |
| 60 | +```bash |
| 61 | +wasm-pack test --chrome --firefox --headless --features debug,default |
| 62 | +wasm-pack test --chrome --firefox --headless --features debug,esplora |
| 63 | +``` |
| 64 | + |
| 65 | +### Node.js tests (TypeScript/Jest) |
| 66 | +```bash |
| 67 | +cd tests/node |
| 68 | +yarn install --immutable |
| 69 | +yarn build # runs wasm-pack build --target nodejs --all-features |
| 70 | +yarn test # runs jest |
| 71 | +yarn lint # runs eslint |
| 72 | +``` |
| 73 | + |
| 74 | +Node tests are in `tests/node/integration/`: |
| 75 | +- `wallet.test.ts` — Wallet creation, addresses, descriptors |
| 76 | +- `esplora.test.ts` — Esplora sync, full scan, transaction sending (uses **Mutinynet signet**) |
| 77 | +- `utilities.test.ts` — Amount, Script, Address utilities |
| 78 | +- `errors.test.ts` — Error handling and error codes |
| 79 | + |
| 80 | +**Note:** `esplora.test.ts` depends on Mutinynet signet (`https://mutinynet.com/api`) with a |
| 81 | +pre-funded test wallet. This test can be flaky if the faucet/signet is down. |
| 82 | + |
| 83 | +### CI |
| 84 | + |
| 85 | +GitHub Actions runs on every PR: |
| 86 | +- **Lint:** `cargo fmt --check` + `cargo clippy --all-features --all-targets -- -D warnings` |
| 87 | +- **Browser build:** Three matrix configs (all features, debug+default, debug+esplora) |
| 88 | +- **Node build + test:** Full wasm-pack build + Jest test suite |
| 89 | + |
| 90 | +CI must be green before merging. Clippy treats warnings as errors (`-D warnings`). |
| 91 | + |
| 92 | +## Features |
| 93 | + |
| 94 | +- `default` — Core wallet functionality only |
| 95 | +- `esplora` — Adds `EsploraClient` for blockchain sync (enables `bdk_esplora` + `wasm-bindgen-futures`) |
| 96 | +- `debug` — Enables `console_error_panic_hook` for better WASM error messages |
| 97 | + |
| 98 | +## Dependencies |
| 99 | + |
| 100 | +Key dependencies (keep these in sync): |
| 101 | +- `bdk_wallet` — Core wallet library |
| 102 | +- `bdk_esplora` — Esplora client (must match `bdk_wallet` version series) |
| 103 | +- `bitcoin` — Bitcoin primitives |
| 104 | +- `wasm-bindgen` — Rust/JS interop |
| 105 | + |
| 106 | +Check https://crates.io/crates/bdk_wallet/versions for latest releases. |
| 107 | +BDK uses a monorepo-ish approach: `bdk_wallet` and `bdk_esplora` versions must be compatible. |
| 108 | + |
| 109 | +## Conventions |
| 110 | + |
| 111 | +- **Conventional commits** (required for all commits and PR titles): |
| 112 | + - `feat:` — New feature or API wrapper |
| 113 | + - `fix:` — Bug fix |
| 114 | + - `refactor:` — Code restructuring without behavior change |
| 115 | + - `docs:` — Documentation only |
| 116 | + - `test:` — Adding or updating tests |
| 117 | + - `chore:` — Maintenance (deps, config, tooling) |
| 118 | + - `ci:` — CI/CD pipeline changes |
| 119 | + - `build:` — Build system changes |
| 120 | + - Scope is optional but encouraged: `feat(wallet):`, `fix(tx_builder):`, `chore(deps):` |
| 121 | + - Breaking changes: add `!` after type, e.g. `feat!:` or `feat(wallet)!:` |
| 122 | + - These prefixes feed into CHANGELOG.md generation |
| 123 | +- **Formatting:** `cargo fmt` with default settings |
| 124 | +- **All public items must be documented** |
| 125 | +- **Safe Rust only** — no `unsafe` without exceptional justification |
| 126 | +- **New features require tests** |
| 127 | + |
| 128 | +## Known Issues |
| 129 | + |
| 130 | +- `SignOptions` is deprecated in BDK 2.2.0+ (signer module moved to `bitcoin::psbt`). |
| 131 | + We use `#[allow(deprecated)]` until BDK provides a migration path, since `Wallet::sign` |
| 132 | + still requires it internally. |
| 133 | +- Esplora integration tests use Mutinynet signet which can be flaky. |
| 134 | + |
| 135 | +## Maintenance Notes |
| 136 | + |
| 137 | +- This repo is maintained by an AI agent (Toshi) with human review by @darioAnongba |
| 138 | +- All changes go through PRs — never push to main directly |
| 139 | +- One PR at a time to keep review manageable |
| 140 | +- Check BDK releases periodically for new APIs to wrap |
0 commit comments