feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
// Imported BCH wallet — single-address, key material lives in Theseus's
// wallet-imports.enc (design §3.2). This adapter mirrors chain-bch.js's
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
// public shape (snapshot, refresh, plan, signAndBroadcast, signMessage,
// dispose) but does NOT go through vault.derive + HKDF: derivation is
// direct from the seed+path or WIF that the user imported.
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
//
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
// 0.6.36+: spend path enabled. plan() builds a P2PKH tx off the wallet's
// single scripthash UTXO set; signAndBroadcast() pulls the signer material
// from api.vault.imports.signer(importId), decodes the WIF or derives the
// mnemonic/path into a 32-byte priv key, and signs every input in RAM.
// The private key never lands in adapter state — signAndBroadcast fetches
// it fresh per broadcast and drops it before returning.
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
module . exports = function makeImportedBchAdapter ( {
sha256 , ripemd160 , cashaddr , electrum , WebSocket , tx ,
HDKey , secp256k1 , base58check , vaultImports ,
} ) {
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
const toHex = ( b ) => Array . from ( b , ( x ) => x . toString ( 16 ) . padStart ( 2 , "0" ) ) . join ( "" ) ;
const p2pkhScript = ( h160 ) => Uint8Array . from ( [ 0x76 , 0xa9 , 0x14 , ... h160 , 0x88 , 0xac ] ) ;
const scripthashOf = ( script ) => toHex ( sha256 ( script ) . slice ( ) . reverse ( ) ) ;
const hash160 = ( b ) => ripemd160 ( sha256 ( b ) ) ;
const IMPORTED _BCH _NETWORKS = {
mainnet : {
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
id : "mainnet" , label : "Mainnet" , prefix : "bitcoincash" , wifVersion : 0x80 ,
2026-09-22 20:44:44 +02:00
explorerTx : "https://bchexplorer.cash/tx/" ,
explorerAddr : "https://bchexplorer.cash/address/" ,
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
defaultServers : [
"wss://bch.imaginary.cash:50004" ,
"wss://cashnode.bch.ninja:50004" ,
"wss://electroncash.dk:50004" ,
"wss://fulcrum.jettscythe.xyz:50004" ,
] ,
} ,
chipnet : {
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
id : "chipnet" , label : "Chipnet testnet" , prefix : "bchtest" , wifVersion : 0xef ,
2026-10-02 20:45:53 +02:00
// chipnet.imaginary.cash's WEB explorer has been returning 502 for
// weeks, so every history row and Explorer button on an imported
// chipnet wallet led to a dead page. chain-bch.js was moved to our own
// explorer and this adapter was missed — which is most of them, since
// a keystore bulk import produces imported wallets.
// Its Electrum endpoint on :50004 is unrelated and still in use below.
explorerTx : "https://aegis.x/explorer/chipnet/?tx=" ,
explorerAddr : "https://aegis.x/explorer/chipnet/?addr=" ,
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
defaultServers : [
"wss://chipnet.imaginary.cash:50004" ,
"wss://chipnet.bch.ninja:50004" ,
] ,
faucet : "https://tbch.googol.cash/" ,
} ,
} ;
function h160OfCashaddr ( addr ) {
const clean = String ( addr || "" ) . replace ( /^bitcoincash:|^bchtest:/ , "" ) ;
const { type , hash } = cashaddr . decode ( addr . includes ( ":" ) ? addr : "bitcoincash:" + clean ) ;
if ( type !== 0 ) throw new Error ( ` imported wallet must be P2PKH (got type ${ type } ) ` ) ;
return hash ;
}
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
// Decode a WIF-encoded private key. Accepts both mainnet (0x80) and
// testnet (0xef) version bytes and both compressed and uncompressed
// forms; returns { priv (32 bytes), compressed (bool) }.
function decodeWif ( wif , versionByte ) {
const bytes = base58check . decodeCheck ( String ( wif ) . trim ( ) ) ;
if ( ! ( bytes [ 0 ] === versionByte || bytes [ 0 ] === 0x80 || bytes [ 0 ] === 0xef ) ) {
throw new Error ( ` unexpected WIF version 0x ${ bytes [ 0 ] . toString ( 16 ) } ` ) ;
}
const compressed = bytes . length === 34 && bytes [ 33 ] === 0x01 ;
const priv = bytes . slice ( 1 , 33 ) ;
if ( priv . length !== 32 ) throw new Error ( "WIF payload is not 32 bytes" ) ;
return { priv , compressed } ;
}
// Derive a P2PKH signer (32-byte priv + 33-byte compressed pubkey) from
// whatever vault.imports.signer returned. Two shapes today:
// { kind: "seed", seed: hex, path: "m/…" } — BIP32 derivation
// { kind: "wif", wif: base58check } — direct decode
// Anything else (or a missing signer) throws with a clear message so
// the panel can surface it rather than the broadcast returning garbage.
function signerToKey ( signerBlob , net ) {
if ( ! signerBlob ) throw new Error ( "no signer material for this wallet" ) ;
if ( signerBlob . kind === "seed" ) {
const seed = signerBlob . seed ;
if ( ! /^[0-9a-f]+$/i . test ( seed ) ) throw new Error ( "seed material must be hex" ) ;
const seedBytes = Uint8Array . from ( seed . match ( /../g ) . map ( ( x ) => parseInt ( x , 16 ) ) ) ;
const node = HDKey . fromMasterSeed ( seedBytes ) . derive ( signerBlob . path || "m" ) ;
return { priv : node . privateKey , pub : node . publicKey } ;
}
if ( signerBlob . kind === "wif" ) {
const { priv } = decodeWif ( signerBlob . wif , net . wifVersion ) ;
const pub = secp256k1 . getPublicKey ( priv , true ) ;
return { priv , pub } ;
}
throw new Error ( ` unknown signer kind: ${ signerBlob . kind } ` ) ;
}
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
class ImportedBchWallet {
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
constructor ( {
walletId , storage , log = ( ) => { } , onChange = ( ) => { } ,
network = "mainnet" , cashaddr : address , servers , importId ,
} = { } ) {
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
const net = IMPORTED _BCH _NETWORKS [ network ] ;
if ( ! net ) throw new Error ( ` chain-bch-imported: unknown network ${ network } ` ) ;
if ( ! address ) throw new Error ( "chain-bch-imported: cashaddr required" ) ;
this . walletId = walletId ;
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
// importId is the vault-side id used to fetch the signer at
// sign-time. Optional here so a mount without spend capability
// still works (read-only surface unaffected).
this . _importId = importId || null ;
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
this . chain = "bch" ;
this . network = net . id ;
this . _net = net ;
this . log = log ;
this . onChange = onChange ;
this . _address = address ;
this . _h160 = h160OfCashaddr ( address ) ;
this . _script = p2pkhScript ( this . _h160 ) ;
this . _scripthash = scripthashOf ( this . _script ) ;
this . _scriptHex = toHex ( this . _script ) ;
this . _servers = Array . isArray ( servers ) && servers . length ? servers : net . defaultServers . slice ( ) ;
this . _client = new electrum . Client ( this . _servers ) ;
this . _client . onServer = ( ) => this . _emit ( ) ;
this . _state = {
balance : { confirmed : 0 , unconfirmed : 0 } ,
history : [ ] ,
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
utxos : [ ] ,
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
height : 0 ,
fix(aegis): 0.15.0 — ask Electrum for protocol 1.5, which is where the tokens were
Aegis negotiated a flat protocol "1.4". Measured against Fulcrum 2.1.0 on
chipnet, for a wallet holding CashTokens:
asked "1.4" -> negotiated 1.4 -> 39 utxos, 0 with token_data
asked ["1.4","1.5.3"] -> negotiated 1.5.3 -> 130 utxos, 91 with token_data
So 1.4 did not merely omit the `token_data` field — Fulcrum left the
token-bearing outputs out of listunspent altogether. Ninety-one UTXOs were
invisible to the wallet, along with the BCH sitting in them. That is a
balance-correctness bug, not only a missing Assets card, and it applied to
the HD path too, since lib/wallet.js reads the same listunspent.
Now a [min, max] range: a modern server picks 1.5.3, an older one still
settles on 1.4, so nothing that worked before stops working. The negotiated
version is recorded on the client for diagnosis.
Second half: the imported BCH adapter had no CashToken code at all — it never
set tokenBalances and snapshot() never exposed it, so the panel's Assets card
was hidden for every WIF import however many tokens the address held. A
chipnet test wallet with 46 categories showed nothing. It now aggregates from
the server's own token_data, which costs one call for the whole set rather
than the per-UTXO transaction fetch the HD path uses, and emits the same
serialised shape the panel already reads. Verified against that wallet: 130
UTXOs, 46 categories, 17 fungible, 32 with NFTs, JSON-clean.
Found because the user said their asset "uses a different asset category" and
suggested checking with the explorer. It is ordinary CashTokens; the wallet
simply could not see them. My earlier conclusion that the empty Assets card
was correct came from probing a single address that genuinely holds no tokens
and generalising from it.
2026-09-28 22:52:15 +02:00
tokenBalances : null , // { <categoryHex>: {fungible, nfts, utxoCount} }
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
scanning : false ,
error : null ,
} ;
}
setServers ( list ) {
this . _servers = Array . isArray ( list ) && list . length ? list : this . _net . defaultServers . slice ( ) ;
this . _client . setServers ( this . _servers ) ;
}
2026-09-14 02:30:51 +02:00
schedulePoll ( ms ) {
clearTimeout ( this . _pollTimer ) ;
this . _pollTimer = setTimeout ( ( ) => { this . refresh ( false ) . catch ( ( ) => { } ) ; this . schedulePoll ( ms ) ; } , ms ) ;
}
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
_emit ( ) { try { this . onChange ( ) ; } catch { } }
snapshot ( ) {
return {
chain : "bch" ,
network : this . _net . id ,
ticker : "BCH" ,
decimals : 8 ,
address : this . _address ,
addressIndex : 0 ,
addressPath : null ,
balance : this . _state . balance ,
height : this . _state . height ,
history : this . _state . history ,
fix(aegis): 0.15.0 — ask Electrum for protocol 1.5, which is where the tokens were
Aegis negotiated a flat protocol "1.4". Measured against Fulcrum 2.1.0 on
chipnet, for a wallet holding CashTokens:
asked "1.4" -> negotiated 1.4 -> 39 utxos, 0 with token_data
asked ["1.4","1.5.3"] -> negotiated 1.5.3 -> 130 utxos, 91 with token_data
So 1.4 did not merely omit the `token_data` field — Fulcrum left the
token-bearing outputs out of listunspent altogether. Ninety-one UTXOs were
invisible to the wallet, along with the BCH sitting in them. That is a
balance-correctness bug, not only a missing Assets card, and it applied to
the HD path too, since lib/wallet.js reads the same listunspent.
Now a [min, max] range: a modern server picks 1.5.3, an older one still
settles on 1.4, so nothing that worked before stops working. The negotiated
version is recorded on the client for diagnosis.
Second half: the imported BCH adapter had no CashToken code at all — it never
set tokenBalances and snapshot() never exposed it, so the panel's Assets card
was hidden for every WIF import however many tokens the address held. A
chipnet test wallet with 46 categories showed nothing. It now aggregates from
the server's own token_data, which costs one call for the whole set rather
than the per-UTXO transaction fetch the HD path uses, and emits the same
serialised shape the panel already reads. Verified against that wallet: 130
UTXOs, 46 categories, 17 fungible, 32 with NFTs, JSON-clean.
Found because the user said their asset "uses a different asset category" and
suggested checking with the explorer. It is ordinary CashTokens; the wallet
simply could not see them. My earlier conclusion that the empty Assets card
was correct came from probing a single address that genuinely holds no tokens
and generalising from it.
2026-09-28 22:52:15 +02:00
// Without this the panel's Assets card has nothing to read and stays
// hidden however many tokens refresh() found.
tokenBalances : this . _state . tokenBalances || null ,
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
scanning : this . _state . scanning ,
error : this . _state . error ,
server : this . _client . url || null ,
servers : this . _servers ,
imported : true ,
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
// 0.6.36+: imported wallets can spend when the vault signer is
// reachable (i.e. Theseus is unlocked). canSpend reflects that so
// the panel can enable the Send tab without probing.
canSpend : ! ! this . _importId ,
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
explorerTx : this . _net . explorerTx ,
explorerAddr : this . _net . explorerAddr ,
faucet : this . _net . faucet ,
} ;
}
async refresh ( full ) {
this . _state . scanning = true ; this . _emit ( ) ;
try {
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
const bal = await this . _client . call ( "blockchain.scripthash.get_balance" , [ this . _scripthash ] ) ;
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
this . _state . balance = { confirmed : Number ( bal ? . confirmed || 0 ) , unconfirmed : Number ( bal ? . unconfirmed || 0 ) } ;
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
// Always pull UTXOs so spend / send-max work off fresh state.
const utxos = await this . _client . call ( "blockchain.scripthash.listunspent" , [ this . _scripthash ] ) ;
fix(aegis): 0.15.0 — ask Electrum for protocol 1.5, which is where the tokens were
Aegis negotiated a flat protocol "1.4". Measured against Fulcrum 2.1.0 on
chipnet, for a wallet holding CashTokens:
asked "1.4" -> negotiated 1.4 -> 39 utxos, 0 with token_data
asked ["1.4","1.5.3"] -> negotiated 1.5.3 -> 130 utxos, 91 with token_data
So 1.4 did not merely omit the `token_data` field — Fulcrum left the
token-bearing outputs out of listunspent altogether. Ninety-one UTXOs were
invisible to the wallet, along with the BCH sitting in them. That is a
balance-correctness bug, not only a missing Assets card, and it applied to
the HD path too, since lib/wallet.js reads the same listunspent.
Now a [min, max] range: a modern server picks 1.5.3, an older one still
settles on 1.4, so nothing that worked before stops working. The negotiated
version is recorded on the client for diagnosis.
Second half: the imported BCH adapter had no CashToken code at all — it never
set tokenBalances and snapshot() never exposed it, so the panel's Assets card
was hidden for every WIF import however many tokens the address held. A
chipnet test wallet with 46 categories showed nothing. It now aggregates from
the server's own token_data, which costs one call for the whole set rather
than the per-UTXO transaction fetch the HD path uses, and emits the same
serialised shape the panel already reads. Verified against that wallet: 130
UTXOs, 46 categories, 17 fungible, 32 with NFTs, JSON-clean.
Found because the user said their asset "uses a different asset category" and
suggested checking with the explorer. It is ordinary CashTokens; the wallet
simply could not see them. My earlier conclusion that the empty Assets card
was correct came from probing a single address that genuinely holds no tokens
and generalising from it.
2026-09-28 22:52:15 +02:00
const list = Array . isArray ( utxos ) ? utxos : [ ] ;
this . _state . utxos = list . map ( ( u ) => ( {
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
txid : u . tx _hash , vout : u . tx _pos , value : Number ( u . value ) , height : Number ( u . height || 0 ) ,
fix(aegis): 0.15.0 — ask Electrum for protocol 1.5, which is where the tokens were
Aegis negotiated a flat protocol "1.4". Measured against Fulcrum 2.1.0 on
chipnet, for a wallet holding CashTokens:
asked "1.4" -> negotiated 1.4 -> 39 utxos, 0 with token_data
asked ["1.4","1.5.3"] -> negotiated 1.5.3 -> 130 utxos, 91 with token_data
So 1.4 did not merely omit the `token_data` field — Fulcrum left the
token-bearing outputs out of listunspent altogether. Ninety-one UTXOs were
invisible to the wallet, along with the BCH sitting in them. That is a
balance-correctness bug, not only a missing Assets card, and it applied to
the HD path too, since lib/wallet.js reads the same listunspent.
Now a [min, max] range: a modern server picks 1.5.3, an older one still
settles on 1.4, so nothing that worked before stops working. The negotiated
version is recorded on the client for diagnosis.
Second half: the imported BCH adapter had no CashToken code at all — it never
set tokenBalances and snapshot() never exposed it, so the panel's Assets card
was hidden for every WIF import however many tokens the address held. A
chipnet test wallet with 46 categories showed nothing. It now aggregates from
the server's own token_data, which costs one call for the whole set rather
than the per-UTXO transaction fetch the HD path uses, and emits the same
serialised shape the panel already reads. Verified against that wallet: 130
UTXOs, 46 categories, 17 fungible, 32 with NFTs, JSON-clean.
Found because the user said their asset "uses a different asset category" and
suggested checking with the explorer. It is ordinary CashTokens; the wallet
simply could not see them. My earlier conclusion that the empty Assets card
was correct came from probing a single address that genuinely holds no tokens
and generalising from it.
2026-09-28 22:52:15 +02:00
token : u . token _data || null ,
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
} ) ) ;
Aegis 0.31.0: chain adapters stop trusting what they should check
Start of the next batch; 0.30.0 is published.
- Tron panel sends signed whatever /wallet/createtransaction returned while
the approval showed the local request. The returned bytes are now decoded
and must be one transfer from this wallet, to that address, for that
amount, with a matching txID - checked at plan time and again at signing.
- Importing a Solana wallet from a seed phrase threw on every attempt (a
mis-parenthesised `new require("crypto").createHmac` plus a bare require
of an ESM-only subpath). SLIP-0010 now uses Node's HMAC, as chain-sol does.
- Imported BCH wallets put token-bearing UTXOs into coin selection. They are
excluded, as in the HD wallet, and the balance counts what can be spent.
- WizardConnect dropped the token from each spent output before signing, so
under SIGHASH_UTXOS every signature of a token transaction was invalid.
- A wallet disposed while a refresh was in flight re-armed its poll timer.
- BCMR registry content is bounded before it reaches the panel: control and
bidi characters stripped, lengths capped, decimals 0-18, icons https/ipfs
only, registries https only.
2026-10-04 01:38:50 +02:00
// get_balance counts the sats parked under token UTXOs, which this
// wallet never spends (see plan()). Report what is actually
// spendable so Max and the balance agree with what a send can move.
if ( this . _state . utxos . some ( ( u ) => u . token ) ) {
let confirmed = 0 , unconfirmed = 0 ;
for ( const u of this . _state . utxos ) {
if ( u . token ) continue ;
if ( u . height > 0 ) confirmed += u . value ; else unconfirmed += u . value ;
}
this . _state . balance = { confirmed , unconfirmed } ;
}
fix(aegis): 0.15.0 — ask Electrum for protocol 1.5, which is where the tokens were
Aegis negotiated a flat protocol "1.4". Measured against Fulcrum 2.1.0 on
chipnet, for a wallet holding CashTokens:
asked "1.4" -> negotiated 1.4 -> 39 utxos, 0 with token_data
asked ["1.4","1.5.3"] -> negotiated 1.5.3 -> 130 utxos, 91 with token_data
So 1.4 did not merely omit the `token_data` field — Fulcrum left the
token-bearing outputs out of listunspent altogether. Ninety-one UTXOs were
invisible to the wallet, along with the BCH sitting in them. That is a
balance-correctness bug, not only a missing Assets card, and it applied to
the HD path too, since lib/wallet.js reads the same listunspent.
Now a [min, max] range: a modern server picks 1.5.3, an older one still
settles on 1.4, so nothing that worked before stops working. The negotiated
version is recorded on the client for diagnosis.
Second half: the imported BCH adapter had no CashToken code at all — it never
set tokenBalances and snapshot() never exposed it, so the panel's Assets card
was hidden for every WIF import however many tokens the address held. A
chipnet test wallet with 46 categories showed nothing. It now aggregates from
the server's own token_data, which costs one call for the whole set rather
than the per-UTXO transaction fetch the HD path uses, and emits the same
serialised shape the panel already reads. Verified against that wallet: 130
UTXOs, 46 categories, 17 fungible, 32 with NFTs, JSON-clean.
Found because the user said their asset "uses a different asset category" and
suggested checking with the explorer. It is ordinary CashTokens; the wallet
simply could not see them. My earlier conclusion that the empty Assets card
was correct came from probing a single address that genuinely holds no tokens
and generalising from it.
2026-09-28 22:52:15 +02:00
// CashTokens. This adapter never looked for them, so a WIF-imported
// wallet holding tokens reported none and the panel hid its Assets
// card — a chipnet test wallet with 46 categories showed nothing.
//
// The HD path (lib/wallet.js) decodes the token prefix off each
// UTXO's scriptPubKey, which costs one transaction fetch per UTXO.
// Here we take the server's own `token_data` instead: one call for
// the whole set. That arrives only when protocol >= 1.5 was
// negotiated (see electrum.js), and when it does not, tokens are
// simply absent — the same as before this change, never wrong.
const tokenBalances = { } ;
for ( const u of list ) {
const t = u . token _data ;
if ( ! t || ! t . category ) continue ;
const cat = String ( t . category ) ;
if ( ! tokenBalances [ cat ] ) tokenBalances [ cat ] = { fungible : 0 n , nfts : [ ] , utxoCount : 0 } ;
const b = tokenBalances [ cat ] ;
b . utxoCount ++ ;
if ( t . amount ) { try { b . fungible += BigInt ( t . amount ) ; } catch ( _e ) { } }
if ( t . nft ) {
b . nfts . push ( {
utxoId : ` ${ u . tx _hash } : ${ u . tx _pos } ` ,
commitmentHex : t . nft . commitment || "" ,
capability : t . nft . capability || "none" ,
capabilityLabel : t . nft . capability || "none" ,
} ) ;
}
}
// Same serialised shape the HD wallet emits — fungible as a decimal
// string, since JSON.stringify cannot carry a BigInt.
const serialised = { } ;
for ( const [ cat , b ] of Object . entries ( tokenBalances ) ) {
serialised [ cat ] = { fungible : b . fungible . toString ( ) , nfts : b . nfts , utxoCount : b . utxoCount } ;
}
this . _state . tokenBalances = serialised ;
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
if ( full ) {
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
const hist = await this . _client . call ( "blockchain.scripthash.get_history" , [ this . _scripthash ] ) ;
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
this . _state . history = ( hist || [ ] ) . slice ( - 50 ) . map ( ( h ) => ( {
txid : h . tx _hash , time : 0 , delta : 0 , confirmations : h . height > 0 ? 1 : 0 ,
} ) ) ;
}
this . _state . error = null ;
} catch ( e ) {
this . _state . error = e ? . message || String ( e ) ;
} finally {
this . _state . scanning = false ;
this . _emit ( ) ;
}
}
nextAddress ( ) { return { address : this . _address , index : 0 } ; }
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
current ( ) {
return {
address : this . _address , index : 0 , branch : 0 , path : null ,
h160 : this . _h160 , script : this . _script , scripthash : this . _scripthash , scriptHex : this . _scriptHex ,
} ;
}
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
// 0.6.36 spend path. Builds an unsigned P2PKH plan against the wallet's
// own UTXO set. Signing happens in signAndBroadcast, which fetches the
// key material from Theseus's vault at broadcast time — nothing key-
// bearing lives in the plan itself, so a plan can round-trip through
// the approval overlay without leaking secrets.
plan ( spec ) {
if ( ! this . _state . utxos . length ) throw new Error ( "wallet has no unspent outputs to spend from" ) ;
const targets = Array . isArray ( spec ? . outputs ) && spec . outputs . length
? spec . outputs . map ( ( o ) => ( { to : o . to , value : o . amount ? ? o . value } ) )
: [ { to : spec ? . to , value : spec ? . amount ? ? spec ? . value } ] ;
const outs = targets . map ( ( t ) => {
const a = cashaddr . parseAny ( t . to , sha256 , this . _net . prefix ) ;
const script = a . type === 0
? Uint8Array . from ( [ 0x76 , 0xa9 , 0x14 , ... a . hash , 0x88 , 0xac ] )
: Uint8Array . from ( [ 0xa9 , 0x14 , ... a . hash , 0x87 ] ) ;
return { value : Math . round ( Number ( t . value ) || 0 ) , script , to : a . cashaddr } ;
} ) ;
if ( spec ? . memo ) outs . push ( { value : 0 , script : tx . memoScript ( String ( spec . memo ) ) , data : true , memo : String ( spec . memo ) } ) ;
const rate = Math . min ( 10 , Math . max ( 1 , Number ( spec ? . feeRate ) || 1 ) ) ;
// Imported wallets have exactly one address, so change goes back to
// itself — no need to derive a fresh change entry from an HD tree.
const changeScript = this . _script ;
Aegis 0.31.0: chain adapters stop trusting what they should check
Start of the next batch; 0.30.0 is published.
- Tron panel sends signed whatever /wallet/createtransaction returned while
the approval showed the local request. The returned bytes are now decoded
and must be one transfer from this wallet, to that address, for that
amount, with a matching txID - checked at plan time and again at signing.
- Importing a Solana wallet from a seed phrase threw on every attempt (a
mis-parenthesised `new require("crypto").createHmac` plus a bare require
of an ESM-only subpath). SLIP-0010 now uses Node's HMAC, as chain-sol does.
- Imported BCH wallets put token-bearing UTXOs into coin selection. They are
excluded, as in the HD wallet, and the balance counts what can be spent.
- WizardConnect dropped the token from each spent output before signing, so
under SIGHASH_UTXOS every signature of a token transaction was invalid.
- A wallet disposed while a refresh was in flight re-armed its poll timer.
- BCMR registry content is bounded before it reaches the panel: control and
bidi characters stripped, lengths capped, decimals 0-18, icons https/ipfs
only, registries https only.
2026-10-04 01:38:50 +02:00
// Token-bearing UTXOs never enter coin selection — same rule as the HD
// wallet. tx.js builds plain P2PKH inputs with no token prefix, so a
// selected token UTXO fails at broadcast today, and would BURN the
// token the day the sighash learns about prefixes.
const spendable = this . _state . utxos . filter ( ( u ) => ! u . token ) . sort ( ( a , b ) => ( b . height > 0 ) - ( a . height > 0 ) ) ;
if ( ! spendable . length ) throw new Error ( "every unspent output in this wallet carries a token; there is no plain BCH to spend" ) ;
chore(aegis): 0.8.2 — sectioned Settings tab
Settings grew tall enough that the user had to scroll past a dozen
cards to reach Prices, Sites or About. Split it into six named
sections (Security, Session, Wallet, Prices, Sites, About) with a
chip nav row at the top; only one section is visible at a time and
the choice persists across restarts.
Adds an About card that names the wallet, the aegis.x front-door
site and the silentmode.st umbrella, so support triage has a
one-click way to reach either from within the panel.
Includes the accumulated 0.7.x-0.8.1 wallet work that was already
shipping on OTA (CashTokens/BCMR, imported-wallet spend, siascan
integration, consolidate, currency picker, footer update chip).
2026-09-22 20:37:28 +02:00
const sel = tx . select ( spendable , outs , rate , changeScript , { sendMax : ! ! spec ? . sendMax } ) ;
const nonData = sel . outputs . filter ( ( o ) => ! o . data ) ;
const total = sel . outputs . reduce ( ( a , o ) => a + o . value , 0 ) ;
return {
... sel ,
feeRate : rate ,
recipients : nonData
. filter ( ( _ , i ) => outs [ i ] && ! outs [ i ] . data )
. map ( ( o , i ) => ( { to : outs [ i ] . to , value : o . value } ) ) ,
memo : spec ? . memo || null ,
total ,
} ;
}
async signAndBroadcast ( plan ) {
if ( ! this . _importId ) throw new Error ( "this wallet has no signer registered" ) ;
if ( ! vaultImports || typeof vaultImports . signer !== "function" ) throw new Error ( "vault.imports.signer unavailable" ) ;
const signerBlob = await vaultImports . signer ( this . _importId ) ;
let key ;
try {
key = signerToKey ( signerBlob , this . _net ) ;
// Belt-and-braces: the signer must match the wallet's own address.
// Catches vault-side corruption and any accidental cross-mount.
const derivedH160 = hash160 ( key . pub ) ;
const same = derivedH160 . length === this . _h160 . length && derivedH160 . every ( ( b , i ) => b === this . _h160 [ i ] ) ;
if ( ! same ) throw new Error ( "signer material does not match this wallet's address" ) ;
const inputs = plan . inputs . map ( ( u ) => ( { ... u , script : this . _script } ) ) ;
const t = { inputs , outputs : plan . outputs } ;
const signed = tx . sign ( t , ( inp , _i , digest ) => ( {
sig : secp256k1 . sign ( digest , key . priv , { prehash : false , lowS : true , format : "der" } ) ,
publicKey : key . pub ,
} ) ) ;
const txid = await this . _client . call ( "blockchain.transaction.broadcast" , [ signed . hex ] ) ;
if ( typeof txid !== "string" || txid . length !== 64 ) throw new Error ( "broadcast rejected: " + JSON . stringify ( txid ) ) ;
this . log ( "broadcast" , txid ) ;
setTimeout ( ( ) => this . refresh ( false ) . catch ( ( ) => { } ) , 1500 ) ;
return { txid , hex : signed . hex , fee : plan . fee } ;
} finally {
// Wipe the private material before returning. Not perfect (JS can
// still relocate the underlying buffer during GC) but it minimises
// the window in which the raw key sits in this frame.
if ( key && key . priv && key . priv . fill ) { try { key . priv . fill ( 0 ) ; } catch { } }
}
}
// BIP-137 message signing from the imported key. Same MAGIC / double-
// sha256 payload as chain-bch.js so the resulting sig verifies through
// Electron Cash and every other BCH tool.
async signMessage ( message ) {
if ( ! this . _importId ) throw new Error ( "this wallet has no signer registered" ) ;
if ( ! vaultImports || typeof vaultImports . signer !== "function" ) throw new Error ( "vault.imports.signer unavailable" ) ;
const signerBlob = await vaultImports . signer ( this . _importId ) ;
let key ;
try {
key = signerToKey ( signerBlob , this . _net ) ;
const enc = new TextEncoder ( ) ;
const varstr = ( s ) => { const b = enc . encode ( s ) ; if ( b . length >= 0xfd ) throw new Error ( "too long" ) ; return Uint8Array . from ( [ b . length , ... b ] ) ; } ;
const MAGIC = "Bitcoin Signed Message:\n" ;
const payload = Uint8Array . from ( [ ... varstr ( MAGIC ) , ... varstr ( String ( message ) ) ] ) ;
const digest = sha256 ( sha256 ( payload ) ) ;
const sig = secp256k1 . sign ( digest , key . priv , { prehash : false , lowS : true , format : "recovered" } ) ;
const out = new Uint8Array ( 65 ) ;
out [ 0 ] = 27 + sig [ 0 ] + 4 ;
out . set ( sig . subarray ( 1 ) , 1 ) ;
return { address : this . _address , signature : Buffer . from ( out ) . toString ( "base64" ) } ;
} finally {
if ( key && key . priv && key . priv . fill ) { try { key . priv . fill ( 0 ) ; } catch { } }
}
}
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
recovery ( ) { return { accountPath : null , xpub : null , xprv : null , note : "Recovery lives in the source of the import (Deviant keystore or wherever you got the seed/WIF from)." } ; }
2026-09-14 02:30:51 +02:00
dispose ( ) { clearTimeout ( this . _pollTimer ) ; try { this . _client . disconnect ( ) ; } catch { } }
feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:
- Vault lifecycle from the wallet gate. The locked / not-yet-created states
now show a master-password form (with optional BIP39 mnemonic on setup)
instead of redirecting users to Settings › Passwords. New
api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
the existing "vault-derive" capability. api.openSettings(section) also
added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
path or a WIF; the cashaddr is derived in the add-on, the signer material
goes to a separate wallet-imports.enc via api.vault.imports {list, add,
remove, signer}. Argus password-vault gains createImports / unlockImports /
saveImports with its own KDF salt so the imports key is disjoint from the
passwords key. lib/chain-bch-imported.js is a single-address Electrum
adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
in add-on storage. Fiat lines under balances, in the wallet picker, and a
portfolio total when 2+ wallets are open. Settings tab is now reachable
while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
@wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
on the right side of LGPL §4d. Sign requests go through approvalModal and
are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
taking the whole add-on down.
2026-09-09 10:33:21 +02:00
}
return { ImportedBchWallet , IMPORTED _BCH _NETWORKS } ;
} ;