Fix static-analyzer backend loading and refactor Ledger entrypoints for future HWW support#68
Merged
Fix static-analyzer backend loading and refactor Ledger entrypoints for future HWW support#68
Conversation
…set compatibility
…behavior and prepare future HWW support
…y shims in @bitcoinerlab/descriptors
…compat and preset flows
This was referenced Mar 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Some static analyzers used by bundlers followed the code too aggressively and assumed some backend-specific paths could be needed, even when those
require()branches would never be hit at runtime. That could still make users hit missing peer dependency problems even when they only wanted one backend (bitcoinjsorscure).This started from #66 and from the discussion in #67.
While looking at that issue, I decided to also fix the Ledger side even if the original report did not complain about it directly. The reason is that the same kind of static-analysis problem could also appear later when users imported signer helpers.
In addition, I also fixed the complementary problem in the other direction: not only scure users could accidentally pull bitcoinjs-related paths, but bitcoinjs users could also still reach scure/noble-related paths in some flows. This PR tries to clean both directions.
The solution proposed in #67 moved in the right direction, but it also made the public API break in places where I would rather keep compatibility, especially for
@bitcoinerlab/descriptors, which is the package most users actually depend on.Main idea
The code now tries to separate three things much more clearly:
@bitcoinerlab/descriptors/@bitcoinerlab/descriptors-scure3.xusersThis removes a lot of hidden backend coupling, reduces the need for runtime
require()tricks and makes the code easier to evolve later.What this PR covers
1. Fix the original static-analysis / bundler issue without breaking
@bitcoinerlab/descriptorsDescriptorsFactoryin core does not call any adapter's code implicitlyBitcoinLibbackend instead of trying to load helper modules on the flyrequire()chains were removed and replaced with clearer explicit entrypoints or internal wiringThis work was applied not only to the exact path reported in #66, but also to the Ledger-related paths and to the reverse case where bitcoinjs users could still end up pulling scure/noble-related code.
At the same time,
@bitcoinerlab/descriptorsstill keeps the old compatibility behavior for existing users.So the main public contract stays working, while the internals become much cleaner.
2. Refactor Ledger around explicit entrypoints
This is a big part of the PR.
Ledger is no longer treated as a loose bag of helpers mixed with internal policy logic. It is now separated into:
This matters not only for static analyzers and bundlers, but also for the future architecture.
I put a lot of emphasis here because I think this is the right preparation work for future hardware wallet support. Ledger should be one explicit path, with a clean public surface and separate internal logic. That way, when we later add support for other HWWs, we do not need to untangle public and internal concerns again.
In other words: this PR is not just a bundler fix. It also prepares the project structure for the next stage of hardware wallet support.
3. Prefer architecture over lazy loading
The goal here was not just "make static analyzers / bundlers stop failing".
The goal was to reduce the reasons why the code needed lazy loading in the first place.
So instead of keeping more
require()and hidden conditional loading in core, this PR moves the code toward:There is still one local
require()kept on purpose in the deprecated root compat path of@bitcoinerlab/descriptors, but that is now only there for backwards compatibility and to avoid forcing the Ledger peer dependency on non-Ledger users of the root package.4. Put real effort into backwards compatibility
This PR does not treat compatibility as an afterthought.
I intentionally kept
@bitcoinerlab/descriptorsworking for old users even while moving core and the newer package shapes to a cleaner API.That means:
DescriptorsFactory(...)usage is still supported on@bitcoinerlab/descriptors@bitcoinerlab/descriptorsledgerManager.eccflows are still normalized in the compat layerBut all of that compatibility code is now clearly marked as temporary and deprecated, so the next major version can remove it much more easily.
Deprecations introduced in this PR
These deprecations are mainly about the preset package
@bitcoinerlab/descriptors.Deprecated there:
DescriptorsFactory()/DescriptorsFactory(ecc)/DescriptorsFactory(...)ledgerkeyExpressionLedgersigners.signLedgersigners.signInputLedgerscriptExpressions.*LedgerLedgerStateandLedgerManagertypesNew code should instead use:
Output,signers,scriptExpressions, etc.)@bitcoinerlab/descriptors/ledgerfor Ledger@bitcoinerlab/descriptors-scure/ledgerfor scure + LedgerAlso, the advanced custom
eccinitialization path on@bitcoinerlab/descriptorsis now documented as temporary. It is kept only for3.xcompatibility and is planned to stop being a public preset-package API in the next major release.DescriptorsFactoryitself is not deprecated in core, because core still needs it internally. But it is no longer presented as a normal end-user API.Notes about package compatibility
This PR puts most of the compatibility effort into
@bitcoinerlab/descriptors, because that is the main user-facing contract we want to preserve.At the same time,
@bitcoinerlab/descriptors-coreand@bitcoinerlab/descriptors-scureare moved to the cleaner, newer API shape sooner. That keeps the long-term architecture cleaner instead of carrying legacy behavior everywhere.Detailed changes
DescriptorsFactorynow accepts only an explicitBitcoinLibapplyPR2137was moved out ofsrc/adapters/intosrc/bitcoinjsHdPatch.ts, which matches its real role bettersrc/ledger/client.tssrc/ledger/policies.tssrc/ledger/index.tsas the public Ledger barrelCloses #66.