Last updated: 2026-02-25
This document is the source of truth for the bitcoinjs-lib v7 + @bitcoinerlab/* migration.
It tracks:
- the full staged plan,
- what has already been done,
- what still blocks completion,
- and exact next jobs so we do not miss anything.
Upgrade app and tests to:
bitcoinjs-lib@7.x@bitcoinerlab/descriptors@3.x@bitcoinerlab/discovery@2.x@bitcoinerlab/coinselect@2.x@bitcoinerlab/explorer@1.x@bitcoinerlab/miniscript@2.x
while preserving functionality and keeping the app buildable throughout.
satsin domain code must bebigint(notnumber).- App code should use typed arrays (
Uint8Array) at bitcoin boundaries. - Remove app-level
Bufferusage. - Keep changes staged and verifiable at each phase.
- Persist bigint values as decimal strings at storage boundaries.
- Keep tests TS-first (compiled to JS by current test build pipeline).
[x]complete[~]in progress / partially complete[ ]not started
[x]Stage 0 - Baseline snapshot and guardrails[x]Stage 1 - Dependency major upgrades + temporary compatibility[~]Stage 2 - Sats/bytes boundaries and migration scaffolding[~]Stage 3 - Core vault/send logic migration (partial, still adapter-backed)[x]Stage 4 - Buffer removal from app code[~]Stage 6 - Tests and integration hardening (functional E2E restored)[ ]Stage 5 - UI/state/storage full bigint normalization[ ]Stage 7 - Cleanup and enforcement gates
Note: Stage numbers reflect original plan order; Stage 6 has partial work because tests had to be updated and stabilized while migrating core APIs.
Installed and verified:
bitcoinjs-lib@7.0.1@bitcoinerlab/descriptors@3.0.6@bitcoinerlab/discovery@2.0.0@bitcoinerlab/coinselect@2.0.0@bitcoinerlab/explorer@1.0.0@bitcoinerlab/miniscript@2.0.0(devDependency)@bitcoinerlab/miniscript-policies@1.1.0(devDependency; policy compiler compatibility)@bitcoinerlab/btcmessage@4.0.1(replaces priorbitcoinjs-messagefork)
Command evidence:
npm ls bitcoinjs-lib @bitcoinerlab/descriptors @bitcoinerlab/discovery @bitcoinerlab/coinselect @bitcoinerlab/explorer @bitcoinerlab/miniscript @bitcoinerlab/miniscript-policies @bitcoinerlab/btcmessage
Current status:
npm run build:srcpasses.npm run build:testpasses.
Added temporary conversion module:
src/app/lib/sats.tsnumberToSats(...)satsToNumber(...)satsToNumberOrUndefined(...)
Purpose:
- keep app compiling while incrementally moving from number-based sats to bigint-based sats.
Important:
- these adapters are temporary and must be removed or isolated to strict I/O boundaries by later stages.
Updated core modules to handle v7 + coinselect/discovery major changes while preserving behavior:
src/app/lib/vaults.tssrc/app/lib/vaultRange.tssrc/app/lib/sendTransaction.tssrc/app/lib/walletDerivedData.ts
Key changes included:
- coinselect call sites adapted for bigint value types;
- typed-array hex conversions via
uint8array-toolswhere needed; - temporary number/bigint bridges to keep existing interfaces working.
@bitcoinerlab/miniscript-policies now requires waiting for ready before compile functions.
Actions taken:
- App runtime path no longer depends on policy compilation boot timing:
src/app/lib/vaultDescriptors.tsnow builds the known equivalent miniscript descriptor directly increateTriggerDescriptor(...).
- Tests that still call
compilePolicy(...)now wait for readiness:test/basic-vault.test.ts->await ready.test/batch-vault.js->await ready.
Removed fragile internal type import path:
- replaced
@bitcoinerlab/discovery/dist/typesusage insrc/app/lib/walletDerivedData.ts.
Some Buffer-style hex operations were replaced with uint8array-tools helpers in:
src/app/lib/vaults.tssrc/app/lib/backup.tssrc/app/screens/NewWalletScreen.tsx- tests updated similarly.
Updated test files for upgraded APIs/types:
test/basic-vault.test.tstest/edge2edge.test.tstest/vaultDescriptors.unit.test.tstest/batch-vault.js
Current test outcome:
- Unit suites pass.
- E2E suites pass after discovery-v2 sequencing updates in
test/edge2edge.test.ts.
Implemented explicit fetch prerequisites before deriving indices/utxos:
- Fetch change descriptor before
getNextIndex({ descriptor: changeDescriptor }). - Fetch receive descriptor before
getNextIndex({ descriptor: receiveDescriptor }). - Re-fetch descriptor set before
getUtxos({ descriptors }). - Added network test timeouts to reduce false failures in slower environments.
Result:
test/edge2edge.test.jsnow passes.- Full
npm testcurrently passes (with existing lint warnings only).
Removed all remaining app-level Buffer usage:
src/common/lib/cipher.tsnow hashes password bytes viaTextEncoder.src/app/lib/backup.tsnow usestoBase64(...)and no longer converts throughBuffer.src/app/lib/backup.tsno longer wraps private keys withBuffer.from(...)before signing.- Message signing now uses
@bitcoinerlab/btcmessageinsrc/app/lib/backup.ts. init.tsno longer installs a globalBufferpolyfill.
Validation:
grep '\bBuffer\b' src-> no matches.grep '\bBuffer\b' init.ts-> no matches.npm test-> pass (after Buffer removal +@bitcoinerlab/btcmessageswitch).
npm run lint-> passes with existing warnings only (no errors).npm run build:src-> pass.npm run build:test-> pass.npm test-> pass (all suites green).
- Discovery v2 fetch/index sequencing:
Cannot derive data from ... since it has not been previously fetchedPass descriptor or descriptors
Resolution:
- Added explicit
discovery.fetch(...)calls before index/utxo derivation in E2E flow.
Keep monitoring for infra flakiness (ECONNRESET/Bad Request) in CI/regtest environments.
- Capture pre-upgrade behavior and failure baseline.
- Establish migration constraints and verification loop.
- Baseline commands run and documented.
- Known pre-existing warnings/failures recorded.
- Baseline understood and reproducible.
- Upgrade dependency majors together.
- Keep app/build/test compile paths functional.
- All target dependency majors upgraded.
- Lockfile updated.
- Builds fixed (
build:src,build:test). - Temporary adapters introduced to bridge bigint/number mismatch.
- compilePolicy readiness issue addressed (runtime + tests).
- none (dependency upgrade and compile compatibility goals met).
- achieved for build-level acceptance;
- functional E2E parity restored during Stage 6 hardening.
- Define where number<->bigint conversions are allowed.
- Ensure UI/storage/network boundaries are explicit.
- Added shared sats conversion helpers (
src/app/lib/sats.ts). - Began using helpers in vault/send/ui components.
- Introduce explicit
type Sats = bigintin shared domain types. - Restrict number<->bigint conversion to boundary modules only.
- Add boundary helper coverage for parse/format/serialize paths.
- Audit domain models so sat fields are bigint-native.
- Domain layer uses bigint for sats end-to-end.
- Number sats remain only at strictly defined UX/display boundaries.
- Move core business logic from compatibility mode to true bigint/typed-array mode.
- Core files adapted enough to compile against new libs:
src/app/lib/vaults.tssrc/app/lib/vaultRange.tssrc/app/lib/sendTransaction.ts
- Remove temporary number bridging from core computations.
- Ensure
txMap, output values, fees, and dust comparisons are bigint-safe. - Align discovery usage to v2 expectations (fetch before deriving indexes/utxos).
- Re-verify vault creation/unfreeze/panic flow under regtest.
- Core vault/send pipeline runs with bigint-native values and passes integration tests.
- Eliminate app-level
Bufferdependence in favor of typed arrays and explicit encoding utils.
- none in app source (
src/**) orinit.ts.
- Replace remaining
Buffer.from(...)usage inbackup.ts. - Replace
Bufferusage incipher.tswith typed-array hashing input. - Re-evaluate and remove
global.Bufferpolyfill frominit.ts.
- App source no longer uses
Bufferdirectly (except explicitly justified third-party glue).
- Ensure state and UI deal with sats in a consistent boundary-safe manner.
- Audit
WalletContext/derived data for number sats assumptions. - Ensure storage serialization/deserialization of bigint via decimal strings.
- Normalize amount/fee inputs to parse string -> bigint, render via formatter.
- Remove accidental mixed arithmetic (
number+bigint) in UI paths.
- UI and persisted state obey boundary conventions without lossy conversions.
- Restore confidence with deterministic test coverage on new stack.
- Test compile works with updated dependencies.
- Multiple tests updated for v7 typed-array/bigint shifts.
- compilePolicy readiness integrated for tests that use it.
- Discovery v2 sequencing fixed in E2E setup/use paths.
- Full pipeline green:
npm testpasses.
- Fix regtest E2E flow with discovery v2 ordering requirements.
- [~] Investigate and stabilize explorer requests (
Bad Request,ECONNRESET) in CI if flakiness appears. - Add targeted regression tests for bigint fee math and conversion boundaries.
- Ensure E2E setup/teardown avoids leaking handles/timers.
npm testgreen (currently achieved) and resilient in CI/regtest environments.
- Remove temporary migration debt and lock in guarantees.
- Remove or reduce temporary compatibility adapters in
sats.ts. - Add CI guardrails for
Bufferand sat number usage in domain code. - Document final migration notes in repo docs.
- Final smoke test across main wallet/vault user journeys.
- Migration complete, enforced, and documented.
- Introduce explicit domain
Sats = biginttyping and reduce adapter usage to I/O only. - Normalize UI/state/storage boundaries to bigint + decimal-string persistence.
- Expand regression coverage for fee math and dust threshold behavior under bigint.
- Add lightweight CI guardrails for
Bufferand sat-number usage in domain modules.
Current modified/new files in this migration branch include:
MIGRATION_BJS7_CHECKLIST.mdinit.tspackage.jsonpackage-lock.jsonsrc/app/lib/sats.ts(new)src/app/lib/vaults.tssrc/app/lib/vaultRange.tssrc/app/lib/sendTransaction.tssrc/app/lib/vaultDescriptors.tssrc/app/lib/backup.tssrc/app/lib/walletDerivedData.tssrc/common/lib/cipher.tssrc/app/screens/NewWalletScreen.tsxsrc/app/components/InitUnfreeze.tsxsrc/app/components/Rescue.tsxsrc/app/components/Transactions.tsxtest/basic-vault.test.tstest/edge2edge.test.tstest/vaultDescriptors.unit.test.tstest/batch-vault.js
Use git status --short for the live list.