fix(aegis): DigiByte import failed on every OTA install
Reported as "the Aegis DigiByte import error". The vendored @dgb-wallet/core
modules under lib/dgb/ imported "bitcoinjs-lib", "bip32", "ecpair",
"bip39" and "@bitcoinerlab/secp256k1" as bare specifiers. Node's ESM resolver
walks up from the importing file, so that resolves in a dev checkout — where
Theseus's node_modules sits above the add-on — and resolves nowhere once
Aegis is running from <userData>/extensions/aegis/, which is every OTA
install. The import threw, index.js caught it and set dgbCore = null, and any
DigiByte import then died in digibyteNetwork() with "DGB adapter not
available".
So DigiByte worked on a fresh install and disappeared after the first update.
Confirmed on this machine: the only node_modules reachable from the installed
extension carries bip39 and none of the other four.
lib/dgb/deps.js now holds the dependencies, injected by index.js from
api.require (which resolves against the app tree) before anything under
lib/dgb/ is imported — the same pattern every other lib/*.js in Aegis already
uses, and the reason that pattern exists. Consumers read them through
accessors rather than capturing them at module scope, so import order is no
longer load-bearing: hd.js builds its bip32 on first use and the two
initEccLib callers go through a once-only ensureEcc(). Using a DGB module
without injection now throws a named error instead of a resolver failure
swallowed into a null.
Verified by loading the modules from a directory with no reachable
node_modules and deriving real addresses: BIP44 D…, BIP49 S… with its legacy
3… pair, BIP84 dgb1q…, BIP86 dgb1p… taproot, plus a WIF round-trip and the
non-DGB WIF rejection.
2026-10-03 13:59:01 +02:00
|
|
|
// Dependency injection for the vendored DGB modules.
|
|
|
|
|
//
|
|
|
|
|
// These files were vendored from @dgb-wallet/core and imported
|
|
|
|
|
// "bitcoinjs-lib", "bip32", "ecpair" and "@bitcoinerlab/secp256k1" as bare
|
|
|
|
|
// specifiers. That resolves fine in a dev checkout, where Theseus's
|
|
|
|
|
// node_modules sits above the add-on — and fails for every OTA install, where
|
|
|
|
|
// Aegis lives in <userData>/extensions/aegis/ and Node's ESM resolver has
|
|
|
|
|
// nowhere to find them. index.js caught the failure and set dgbCore = null,
|
|
|
|
|
// so DigiByte quietly stopped existing and an import died with "DGB adapter
|
|
|
|
|
// not available". It worked on a fresh install and broke after the first
|
|
|
|
|
// update, which is the worst possible shape for a bug.
|
|
|
|
|
//
|
|
|
|
|
// index.js already holds all of these via api.require (which resolves against
|
|
|
|
|
// the app tree), so it injects them here before importing anything under
|
|
|
|
|
// lib/dgb/. Every consumer reads them through the accessors below rather than
|
|
|
|
|
// capturing them at module scope, so nothing depends on import order and a
|
|
|
|
|
// missing injection fails loudly at the call instead of silently at load.
|
|
|
|
|
|
|
|
|
|
let deps = null;
|
|
|
|
|
|
|
|
|
|
export function setDgbDeps(d) {
|
feat(aegis): recover DigiByte seeds from the 2018-19 mobile wallets
Ported from Digibyte.X/dgb-wallet @ 989a2696.
BIP32 builds the master key as HMAC-SHA512("Bitcoin seed", seed). DigiByte's
official 2018-19 Android/iOS wallets were BreadWallet forks and used
"DigiByte seed" as the HMAC key instead, so the same twelve words produce a
completely different key tree — every address differs, and a standard scan
finds nothing at all. Anyone importing one of those seeds into Aegis got a
valid, empty address and a zero balance with no way to tell why. Same shape
as the Bitcoin.com coin-type-0 problem.
- rootFromSeed() in the vendored lib/dgb/core/hd.js takes an optional HMAC
key, matching upstream, and exports HMAC_BITCOIN_SEED /
HMAC_DIGIBYTE_SEED.
- lib/import-derive.js grows the same option, since that is what actually
derives the address on an import, and importWallet records the variant on
the spec so the entry says which tree its stored address came from.
- The path scanner added in 0.24.0 now covers DigiByte: all four purposes
under the standard key, plus m/0' and BIP44 under the legacy one. So the
answer to "which tree holds my coins" is a scan rather than a guess, and
the Use button carries the key along with the path.
Verified against an independent HMAC-SHA512 computation, and end to end: the
same mnemonic gives DG1Khh…N1i under the standard key and DMWQ1g…PHse under
the DigiByte key, both valid, with m/0' deriving DGAf4M…Wyn.
Also fixes a coupling this exposed: lib/import-derive.js derives taproot
addresses but never called initEccLib, relying on chain-btc.js (and formerly
lib/dgb/core/address.js, before it went lazy here) doing it at load time. It
now installs the schnorr backend itself, once, so its taproot output no
longer depends on an unrelated module's import order.
The gap-limit change in 0a5d7ade (scan gap 200/100 for DigiScope parity) is
upstream-only for now — Aegis's imported DGB adapter watches a single stored
address rather than scanning a gap.
2026-10-03 14:13:25 +02:00
|
|
|
const need = ["bitcoinjs", "ecc", "bip32Factory", "ecpairFactory", "bip39", "hmac", "sha512"];
|
fix(aegis): DigiByte import failed on every OTA install
Reported as "the Aegis DigiByte import error". The vendored @dgb-wallet/core
modules under lib/dgb/ imported "bitcoinjs-lib", "bip32", "ecpair",
"bip39" and "@bitcoinerlab/secp256k1" as bare specifiers. Node's ESM resolver
walks up from the importing file, so that resolves in a dev checkout — where
Theseus's node_modules sits above the add-on — and resolves nowhere once
Aegis is running from <userData>/extensions/aegis/, which is every OTA
install. The import threw, index.js caught it and set dgbCore = null, and any
DigiByte import then died in digibyteNetwork() with "DGB adapter not
available".
So DigiByte worked on a fresh install and disappeared after the first update.
Confirmed on this machine: the only node_modules reachable from the installed
extension carries bip39 and none of the other four.
lib/dgb/deps.js now holds the dependencies, injected by index.js from
api.require (which resolves against the app tree) before anything under
lib/dgb/ is imported — the same pattern every other lib/*.js in Aegis already
uses, and the reason that pattern exists. Consumers read them through
accessors rather than capturing them at module scope, so import order is no
longer load-bearing: hd.js builds its bip32 on first use and the two
initEccLib callers go through a once-only ensureEcc(). Using a DGB module
without injection now throws a named error instead of a resolver failure
swallowed into a null.
Verified by loading the modules from a directory with no reachable
node_modules and deriving real addresses: BIP44 D…, BIP49 S… with its legacy
3… pair, BIP84 dgb1q…, BIP86 dgb1p… taproot, plus a WIF round-trip and the
non-DGB WIF rejection.
2026-10-03 13:59:01 +02:00
|
|
|
for (const k of need) {
|
|
|
|
|
if (!d || !d[k]) throw new Error(`setDgbDeps: missing ${k}`);
|
|
|
|
|
}
|
|
|
|
|
deps = d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function need() {
|
|
|
|
|
if (!deps) throw new Error("DGB modules used before setDgbDeps() — see lib/dgb/deps.js");
|
|
|
|
|
return deps;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const bitcoinjs = () => need().bitcoinjs;
|
|
|
|
|
export const payments = () => need().bitcoinjs.payments;
|
|
|
|
|
export const Psbt = () => need().bitcoinjs.Psbt;
|
|
|
|
|
export const ecc = () => need().ecc;
|
|
|
|
|
export const bip39 = () => need().bip39;
|
feat(aegis): recover DigiByte seeds from the 2018-19 mobile wallets
Ported from Digibyte.X/dgb-wallet @ 989a2696.
BIP32 builds the master key as HMAC-SHA512("Bitcoin seed", seed). DigiByte's
official 2018-19 Android/iOS wallets were BreadWallet forks and used
"DigiByte seed" as the HMAC key instead, so the same twelve words produce a
completely different key tree — every address differs, and a standard scan
finds nothing at all. Anyone importing one of those seeds into Aegis got a
valid, empty address and a zero balance with no way to tell why. Same shape
as the Bitcoin.com coin-type-0 problem.
- rootFromSeed() in the vendored lib/dgb/core/hd.js takes an optional HMAC
key, matching upstream, and exports HMAC_BITCOIN_SEED /
HMAC_DIGIBYTE_SEED.
- lib/import-derive.js grows the same option, since that is what actually
derives the address on an import, and importWallet records the variant on
the spec so the entry says which tree its stored address came from.
- The path scanner added in 0.24.0 now covers DigiByte: all four purposes
under the standard key, plus m/0' and BIP44 under the legacy one. So the
answer to "which tree holds my coins" is a scan rather than a guess, and
the Use button carries the key along with the path.
Verified against an independent HMAC-SHA512 computation, and end to end: the
same mnemonic gives DG1Khh…N1i under the standard key and DMWQ1g…PHse under
the DigiByte key, both valid, with m/0' deriving DGAf4M…Wyn.
Also fixes a coupling this exposed: lib/import-derive.js derives taproot
addresses but never called initEccLib, relying on chain-btc.js (and formerly
lib/dgb/core/address.js, before it went lazy here) doing it at load time. It
now installs the schnorr backend itself, once, so its taproot output no
longer depends on an unrelated module's import order.
The gap-limit change in 0a5d7ade (scan gap 200/100 for DigiScope parity) is
upstream-only for now — Aegis's imported DGB adapter watches a single stored
address rather than scanning a gap.
2026-10-03 14:13:25 +02:00
|
|
|
export const hmac = () => need().hmac;
|
|
|
|
|
export const sha512 = () => need().sha512;
|
fix(aegis): DigiByte import failed on every OTA install
Reported as "the Aegis DigiByte import error". The vendored @dgb-wallet/core
modules under lib/dgb/ imported "bitcoinjs-lib", "bip32", "ecpair",
"bip39" and "@bitcoinerlab/secp256k1" as bare specifiers. Node's ESM resolver
walks up from the importing file, so that resolves in a dev checkout — where
Theseus's node_modules sits above the add-on — and resolves nowhere once
Aegis is running from <userData>/extensions/aegis/, which is every OTA
install. The import threw, index.js caught it and set dgbCore = null, and any
DigiByte import then died in digibyteNetwork() with "DGB adapter not
available".
So DigiByte worked on a fresh install and disappeared after the first update.
Confirmed on this machine: the only node_modules reachable from the installed
extension carries bip39 and none of the other four.
lib/dgb/deps.js now holds the dependencies, injected by index.js from
api.require (which resolves against the app tree) before anything under
lib/dgb/ is imported — the same pattern every other lib/*.js in Aegis already
uses, and the reason that pattern exists. Consumers read them through
accessors rather than capturing them at module scope, so import order is no
longer load-bearing: hd.js builds its bip32 on first use and the two
initEccLib callers go through a once-only ensureEcc(). Using a DGB module
without injection now throws a named error instead of a resolver failure
swallowed into a null.
Verified by loading the modules from a directory with no reachable
node_modules and deriving real addresses: BIP44 D…, BIP49 S… with its legacy
3… pair, BIP84 dgb1q…, BIP86 dgb1p… taproot, plus a WIF round-trip and the
non-DGB WIF rejection.
2026-10-03 13:59:01 +02:00
|
|
|
|
|
|
|
|
// initEccLib must run before any Taproot derivation, and exactly once.
|
|
|
|
|
let eccInstalled = false;
|
|
|
|
|
export function ensureEcc() {
|
|
|
|
|
if (eccInstalled) return;
|
|
|
|
|
need().bitcoinjs.initEccLib(need().ecc);
|
|
|
|
|
eccInstalled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Built on first use rather than at module scope, so hd.js no longer forces
|
|
|
|
|
// the deps to exist merely by being imported.
|
|
|
|
|
let bip32Cached = null;
|
|
|
|
|
export function bip32() {
|
|
|
|
|
if (!bip32Cached) bip32Cached = need().bip32Factory(need().ecc);
|
|
|
|
|
return bip32Cached;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let ecpairCached = null;
|
|
|
|
|
export function ECPair() {
|
|
|
|
|
if (!ecpairCached) ecpairCached = need().ecpairFactory(need().ecc);
|
|
|
|
|
return ecpairCached;
|
|
|
|
|
}
|