feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
// Aegis — multi-chain wallet bundled with Theseus. activate() runs in the
|
|
|
|
|
// main process; every wallet's key material lives here, in memory, and is
|
|
|
|
|
// re-derived from the password vault on every launch. Nothing secret is ever
|
|
|
|
|
// written to disk or logged.
|
|
|
|
|
//
|
|
|
|
|
// A single addon can hold many wallets — one per {chain, network}, or several
|
|
|
|
|
// sub-accounts of the same chain — and each wallet is backed by its own
|
|
|
|
|
// vault-derived 32-byte HKDF root. Chains today: BCH, Tron mainnet, Tron
|
|
|
|
|
// Nile testnet. Adding a fourth chain is a new adapter file under lib/ and
|
|
|
|
|
// an entry in the CHAIN_REGISTRY below.
|
|
|
|
|
//
|
|
|
|
|
// Back-compat: the addon id stays "bchwallet" (the manifest label became
|
|
|
|
|
// Aegis, but the id gates the vault-derive namespace and older vaults have
|
|
|
|
|
// funds against it). The legacy BCH default wallet uses purpose
|
|
|
|
|
// "bchwallet/mainnet/0" — byte-identical to the pre-multi-wallet build —
|
|
|
|
|
// so on-disk funds are untouched. See memory bchwallet-vault-root-derivation.
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
const path = require("node:path");
|
|
|
|
|
const fs = require("node:fs");
|
|
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const LEGACY_BCH_PURPOSE = "bchwallet/mainnet/0";
|
|
|
|
|
const LEGACY_BCH_WALLET_ID = "bch-default";
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
let ctx = null;
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
// ---- deps -------------------------------------------------------------------
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
async function loadDeps(api) {
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
const { secp256k1 } = await api.import("@noble/curves/secp256k1.js");
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
const { ed25519 } = await api.import("@noble/curves/ed25519.js");
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
const { sha256 } = await api.import("@noble/hashes/sha2.js");
|
|
|
|
|
const { ripemd160 } = await api.import("@noble/hashes/legacy.js");
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const { keccak_256 } = await api.import("@noble/hashes/sha3.js");
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
const { blake2b } = await api.import("@noble/hashes/blake2.js");
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
const { HDKey } = await api.import("@scure/bip32");
|
|
|
|
|
const WebSocket = api.require("ws");
|
|
|
|
|
const cashaddr = require("./lib/cashaddr.js");
|
|
|
|
|
const keysLib = require("./lib/keys.js")({ HDKey, secp256k1, sha256, ripemd160, cashaddr });
|
|
|
|
|
const tx = require("./lib/tx.js")({ sha256 });
|
|
|
|
|
const electrum = require("./lib/electrum.js")({ WebSocket, log: (...a) => api.log("electrum", ...a) });
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const base58check = require("./lib/base58check.js")({ sha256 });
|
|
|
|
|
const bchAdapter = require("./lib/chain-bch.js")({
|
|
|
|
|
HDKey, secp256k1, sha256, ripemd160, cashaddr, keysLib, tx, electrum, WebSocket,
|
|
|
|
|
});
|
|
|
|
|
const tronAdapter = require("./lib/chain-tron.js")({
|
|
|
|
|
HDKey, secp256k1, sha256, keccak_256, base58check,
|
|
|
|
|
});
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
const siaAdapter = require("./lib/chain-sia.js")({ ed25519, blake2b });
|
feat(theseus/aegis): DGB adapter on @dgb-wallet/{core,psbt} vendored packages
Aegis now shares its DGB code with the standalone DigiByte web-wallet at
D:\Dev\SilentCode\Digibyte. Address derivation and PSBT construction come
from that project's @dgb-wallet/core and @dgb-wallet/psbt packages instead
of Aegis-local reimplementations. Any bugfix upstream flows in via a
re-vendor of dist/*.
- lib/dgb/{core,psbt}/ — vendored dist/ output of the two packages plus
a tiny package.json shim marking them as ESM. @dgb-wallet/core's own
import specifier "@dgb-wallet/core" inside psbt/*.js is rewritten to
"../core/index.js" so the sibling module resolves without a workspace.
- New Theseus deps: bitcoinjs-lib, bip32, bip39, @bitcoinerlab/secp256k1,
ecpair — the peer deps the vendored packages need. Loaded via
api.require in index.js's loadDeps().
- chain-dgb.js is a thin adapter now: BIP32 tree via bip32 + DGB
Network object, addresses via core.p2wpkhAddress, tx via
psbt.buildPsbt + PSBT.signInput (per-input, since each UTXO's key
differs) + psbt.finalizeAndExtract. Runtime backend stays the same —
Theseus's lib/electrum.js against the DGB ElectrumX pool.
- Verified end-to-end in scratchpad: abandon×11 mnemonic derives
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8 (matches iancoleman.io/bip39
and the previous inline implementation, so no on-chain address change
for anyone who was already using Aegis's DGB slot). PSBT build+sign+
finalize on a mock UTXO produces a valid 223-byte witness tx.
BIP44 (D…) and BIP49 (S…) address families are implemented in the
vendored core but not yet exposed in Aegis's picker — the panel needs
an "address family" selector inside the DGB settings block first. Left
for a follow-up; today's DGB pick uses BIP84 native SegWit only.
2026-09-07 02:19:44 +02:00
|
|
|
// DGB delegates address derivation + PSBT to the vendored @dgb-wallet/*
|
|
|
|
|
// packages under lib/dgb/. Those are ESM; the peer deps (bitcoinjs-lib,
|
|
|
|
|
// bip32, ecpair, @bitcoinerlab/secp256k1) are CommonJS and reachable via
|
|
|
|
|
// api.require from the Theseus dependency tree.
|
|
|
|
|
const { pathToFileURL } = require("node:url");
|
|
|
|
|
const dgbCore = await import(pathToFileURL(path.join(api.folder, "lib/dgb/core/index.js")).href);
|
|
|
|
|
const dgbPsbt = await import(pathToFileURL(path.join(api.folder, "lib/dgb/psbt/index.js")).href);
|
|
|
|
|
const bitcoinjs = api.require("bitcoinjs-lib");
|
|
|
|
|
const { BIP32Factory } = api.require("bip32");
|
|
|
|
|
const { ECPairFactory } = api.require("ecpair");
|
|
|
|
|
const ecc = api.require("@bitcoinerlab/secp256k1");
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
const dgbAdapter = require("./lib/chain-dgb.js")({
|
feat(theseus/aegis): DGB adapter on @dgb-wallet/{core,psbt} vendored packages
Aegis now shares its DGB code with the standalone DigiByte web-wallet at
D:\Dev\SilentCode\Digibyte. Address derivation and PSBT construction come
from that project's @dgb-wallet/core and @dgb-wallet/psbt packages instead
of Aegis-local reimplementations. Any bugfix upstream flows in via a
re-vendor of dist/*.
- lib/dgb/{core,psbt}/ — vendored dist/ output of the two packages plus
a tiny package.json shim marking them as ESM. @dgb-wallet/core's own
import specifier "@dgb-wallet/core" inside psbt/*.js is rewritten to
"../core/index.js" so the sibling module resolves without a workspace.
- New Theseus deps: bitcoinjs-lib, bip32, bip39, @bitcoinerlab/secp256k1,
ecpair — the peer deps the vendored packages need. Loaded via
api.require in index.js's loadDeps().
- chain-dgb.js is a thin adapter now: BIP32 tree via bip32 + DGB
Network object, addresses via core.p2wpkhAddress, tx via
psbt.buildPsbt + PSBT.signInput (per-input, since each UTXO's key
differs) + psbt.finalizeAndExtract. Runtime backend stays the same —
Theseus's lib/electrum.js against the DGB ElectrumX pool.
- Verified end-to-end in scratchpad: abandon×11 mnemonic derives
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8 (matches iancoleman.io/bip39
and the previous inline implementation, so no on-chain address change
for anyone who was already using Aegis's DGB slot). PSBT build+sign+
finalize on a mock UTXO produces a valid 223-byte witness tx.
BIP44 (D…) and BIP49 (S…) address families are implemented in the
vendored core but not yet exposed in Aegis's picker — the panel needs
an "address family" selector inside the DGB settings block first. Left
for a follow-up; today's DGB pick uses BIP84 native SegWit only.
2026-09-07 02:19:44 +02:00
|
|
|
dgbCore, dgbPsbt, bitcoinjs,
|
|
|
|
|
bip32Factory: BIP32Factory, ecpairFactory: ECPairFactory, ecc,
|
|
|
|
|
sha256, electrum,
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
});
|
feat(theseus/aegis): DGB adapter on @dgb-wallet/{core,psbt} vendored packages
Aegis now shares its DGB code with the standalone DigiByte web-wallet at
D:\Dev\SilentCode\Digibyte. Address derivation and PSBT construction come
from that project's @dgb-wallet/core and @dgb-wallet/psbt packages instead
of Aegis-local reimplementations. Any bugfix upstream flows in via a
re-vendor of dist/*.
- lib/dgb/{core,psbt}/ — vendored dist/ output of the two packages plus
a tiny package.json shim marking them as ESM. @dgb-wallet/core's own
import specifier "@dgb-wallet/core" inside psbt/*.js is rewritten to
"../core/index.js" so the sibling module resolves without a workspace.
- New Theseus deps: bitcoinjs-lib, bip32, bip39, @bitcoinerlab/secp256k1,
ecpair — the peer deps the vendored packages need. Loaded via
api.require in index.js's loadDeps().
- chain-dgb.js is a thin adapter now: BIP32 tree via bip32 + DGB
Network object, addresses via core.p2wpkhAddress, tx via
psbt.buildPsbt + PSBT.signInput (per-input, since each UTXO's key
differs) + psbt.finalizeAndExtract. Runtime backend stays the same —
Theseus's lib/electrum.js against the DGB ElectrumX pool.
- Verified end-to-end in scratchpad: abandon×11 mnemonic derives
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8 (matches iancoleman.io/bip39
and the previous inline implementation, so no on-chain address change
for anyone who was already using Aegis's DGB slot). PSBT build+sign+
finalize on a mock UTXO produces a valid 223-byte witness tx.
BIP44 (D…) and BIP49 (S…) address families are implemented in the
vendored core but not yet exposed in Aegis's picker — the panel needs
an "address family" selector inside the DGB settings block first. Left
for a follow-up; today's DGB pick uses BIP84 native SegWit only.
2026-09-07 02:19:44 +02:00
|
|
|
return { HDKey, secp256k1, ed25519, sha256, ripemd160, keccak_256, blake2b,
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
cashaddr, keysLib, tx, electrum, base58check,
|
feat(theseus/aegis): DGB adapter on @dgb-wallet/{core,psbt} vendored packages
Aegis now shares its DGB code with the standalone DigiByte web-wallet at
D:\Dev\SilentCode\Digibyte. Address derivation and PSBT construction come
from that project's @dgb-wallet/core and @dgb-wallet/psbt packages instead
of Aegis-local reimplementations. Any bugfix upstream flows in via a
re-vendor of dist/*.
- lib/dgb/{core,psbt}/ — vendored dist/ output of the two packages plus
a tiny package.json shim marking them as ESM. @dgb-wallet/core's own
import specifier "@dgb-wallet/core" inside psbt/*.js is rewritten to
"../core/index.js" so the sibling module resolves without a workspace.
- New Theseus deps: bitcoinjs-lib, bip32, bip39, @bitcoinerlab/secp256k1,
ecpair — the peer deps the vendored packages need. Loaded via
api.require in index.js's loadDeps().
- chain-dgb.js is a thin adapter now: BIP32 tree via bip32 + DGB
Network object, addresses via core.p2wpkhAddress, tx via
psbt.buildPsbt + PSBT.signInput (per-input, since each UTXO's key
differs) + psbt.finalizeAndExtract. Runtime backend stays the same —
Theseus's lib/electrum.js against the DGB ElectrumX pool.
- Verified end-to-end in scratchpad: abandon×11 mnemonic derives
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8 (matches iancoleman.io/bip39
and the previous inline implementation, so no on-chain address change
for anyone who was already using Aegis's DGB slot). PSBT build+sign+
finalize on a mock UTXO produces a valid 223-byte witness tx.
BIP44 (D…) and BIP49 (S…) address families are implemented in the
vendored core but not yet exposed in Aegis's picker — the panel needs
an "address family" selector inside the DGB settings block first. Left
for a follow-up; today's DGB pick uses BIP84 native SegWit only.
2026-09-07 02:19:44 +02:00
|
|
|
bchAdapter, tronAdapter, siaAdapter, dgbAdapter,
|
|
|
|
|
dgbCore, dgbPsbt, bitcoinjs, ecc };
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
}
|
|
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
// ---- servers ---------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function bchDefaultServers(api) {
|
|
|
|
|
try { return JSON.parse(fs.readFileSync(path.join(api.folder, "electrum-servers.json"), "utf8")); }
|
|
|
|
|
catch { return []; }
|
|
|
|
|
}
|
|
|
|
|
function bchServerList(api) {
|
|
|
|
|
const custom = api.storage.get("servers", null);
|
|
|
|
|
return Array.isArray(custom) && custom.length ? custom : bchDefaultServers(api);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---- chain registry --------------------------------------------------------
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
// Two-level structure so the panel can present coin-then-network as separate
|
|
|
|
|
// picks. `coin` fields are chain-wide; `networks[<id>]` fields override or
|
|
|
|
|
// add to them per-network. `logo` is the SVG key panel.js draws from.
|
|
|
|
|
const COINS = {
|
|
|
|
|
bch: {
|
|
|
|
|
chain: "bch",
|
|
|
|
|
label: "Bitcoin Cash",
|
|
|
|
|
short: "BCH",
|
|
|
|
|
ticker: "BCH",
|
|
|
|
|
decimals: 8,
|
|
|
|
|
color: "#0ac18e",
|
|
|
|
|
logo: "bch",
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
supportsMessageSign: true,
|
|
|
|
|
supportsPageInject: true, // window.bitcoincash on *.x pages
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
networks: {
|
|
|
|
|
mainnet: {
|
|
|
|
|
id: "mainnet", label: "Mainnet", testnet: false,
|
|
|
|
|
// Legacy default wallet uses the flat "bchwallet/mainnet/0" purpose;
|
|
|
|
|
// new BCH mainnet sub-accounts start at index 1 under the /bch/ prefix.
|
|
|
|
|
purposePrefix: "bchwallet/bch/",
|
|
|
|
|
startIndex: 1,
|
|
|
|
|
},
|
|
|
|
|
chipnet: {
|
|
|
|
|
id: "chipnet", label: "Chipnet testnet", testnet: true,
|
|
|
|
|
purposePrefix: "bchwallet/bch/chipnet/",
|
|
|
|
|
startIndex: 0,
|
|
|
|
|
},
|
|
|
|
|
},
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
},
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
trx: {
|
|
|
|
|
chain: "trx",
|
|
|
|
|
label: "Tron",
|
|
|
|
|
short: "TRX",
|
|
|
|
|
ticker: "TRX",
|
|
|
|
|
decimals: 6,
|
|
|
|
|
color: "#ff060a",
|
|
|
|
|
logo: "trx",
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
supportsMessageSign: true,
|
|
|
|
|
supportsPageInject: true, // window.tronWeb everywhere
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
networks: {
|
|
|
|
|
mainnet: {
|
|
|
|
|
id: "mainnet", label: "Mainnet", testnet: false,
|
|
|
|
|
purposePrefix: "bchwallet/trx/mainnet/", startIndex: 0,
|
|
|
|
|
},
|
|
|
|
|
nile: {
|
|
|
|
|
id: "nile", label: "Nile testnet", testnet: true,
|
|
|
|
|
purposePrefix: "bchwallet/trx/nile/", startIndex: 0,
|
|
|
|
|
},
|
|
|
|
|
},
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
},
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
sc: {
|
|
|
|
|
chain: "sc",
|
|
|
|
|
label: "Siacoin",
|
|
|
|
|
short: "SC",
|
|
|
|
|
ticker: "SC",
|
|
|
|
|
decimals: 24,
|
|
|
|
|
color: "#20be82",
|
|
|
|
|
logo: "sc",
|
|
|
|
|
supportsMessageSign: true,
|
|
|
|
|
supportsPageInject: false,
|
|
|
|
|
// First SC wallet in Aegis reuses the legacy standalone-siawallet purpose
|
|
|
|
|
// so pre-Aegis funds carry over automatically (addon.json declares
|
|
|
|
|
// `absorbs: ["siawallet"]` to allow the derivation). Second+ use the new
|
|
|
|
|
// Aegis-namespaced prefix.
|
|
|
|
|
networks: {
|
|
|
|
|
mainnet: {
|
|
|
|
|
id: "mainnet", label: "Mainnet", testnet: false,
|
|
|
|
|
purposePrefix: "bchwallet/sc/mainnet/", startIndex: 1,
|
|
|
|
|
legacyFirstPurpose: "siawallet/mainnet/0",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
dgb: {
|
|
|
|
|
chain: "dgb",
|
|
|
|
|
label: "DigiByte",
|
|
|
|
|
short: "DGB",
|
|
|
|
|
ticker: "DGB",
|
|
|
|
|
decimals: 8,
|
|
|
|
|
color: "#0066cc",
|
|
|
|
|
logo: "dgb",
|
|
|
|
|
supportsMessageSign: true,
|
|
|
|
|
supportsPageInject: false,
|
|
|
|
|
networks: {
|
|
|
|
|
mainnet: {
|
|
|
|
|
id: "mainnet", label: "Mainnet", testnet: false,
|
|
|
|
|
purposePrefix: "bchwallet/dgb/mainnet/", startIndex: 0,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
};
|
|
|
|
|
function chainKey(chain, network) { return `${chain}:${network}`; }
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
function chainMeta(chain, network) {
|
|
|
|
|
const c = COINS[chain]; const n = c && c.networks[network];
|
|
|
|
|
if (!c || !n) return null;
|
|
|
|
|
return {
|
|
|
|
|
chain: c.chain, network: n.id,
|
|
|
|
|
label: c.label + " · " + n.label, short: c.short, ticker: c.ticker, decimals: c.decimals,
|
|
|
|
|
color: c.color, logo: c.logo, coinLabel: c.label, networkLabel: n.label, testnet: !!n.testnet,
|
|
|
|
|
purposePrefix: n.purposePrefix, startIndex: n.startIndex,
|
|
|
|
|
supportsMessageSign: !!c.supportsMessageSign, supportsPageInject: !!c.supportsPageInject,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
function coinsForPanel() {
|
|
|
|
|
return Object.values(COINS).map((c) => ({
|
|
|
|
|
chain: c.chain, label: c.label, short: c.short, ticker: c.ticker, color: c.color, logo: c.logo, decimals: c.decimals,
|
|
|
|
|
networks: Object.values(c.networks).map((n) => ({ id: n.id, label: n.label, testnet: !!n.testnet })),
|
|
|
|
|
}));
|
|
|
|
|
}
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
|
|
|
|
|
// ---- wallet list ------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function readWallets(api) {
|
|
|
|
|
const raw = api.storage.get("wallets", null);
|
|
|
|
|
return Array.isArray(raw) ? raw : null;
|
|
|
|
|
}
|
|
|
|
|
function writeWallets(api, list) { api.storage.set("wallets", list); }
|
|
|
|
|
|
|
|
|
|
// Bring pre-multi-wallet storage forward: create the legacy BCH default entry
|
|
|
|
|
// and rehome its receiveCursor / txCache under the new per-wallet subkey.
|
|
|
|
|
function migrateLegacyStorage(api) {
|
|
|
|
|
if (readWallets(api)) return; // already multi-wallet
|
|
|
|
|
const legacyAccountPath = String(api.storage.get("accountPath", "") || "").trim() || "m/44'/145'/0'";
|
|
|
|
|
const wallets = [{
|
|
|
|
|
id: LEGACY_BCH_WALLET_ID,
|
|
|
|
|
label: "BCH — main",
|
|
|
|
|
chain: "bch",
|
|
|
|
|
network: "mainnet",
|
|
|
|
|
purpose: LEGACY_BCH_PURPOSE,
|
|
|
|
|
accountPath: legacyAccountPath,
|
|
|
|
|
isDefault: true,
|
|
|
|
|
isLegacy: true,
|
|
|
|
|
createdAt: 0,
|
|
|
|
|
}];
|
|
|
|
|
writeWallets(api, wallets);
|
|
|
|
|
api.storage.set("selectedWalletId", LEGACY_BCH_WALLET_ID);
|
|
|
|
|
// Move per-wallet state under the scoped prefix used by chain-bch.js.
|
|
|
|
|
const prefix = `wallets/${LEGACY_BCH_WALLET_ID}/`;
|
|
|
|
|
for (const legacyKey of ["receiveCursor", "txCache"]) {
|
|
|
|
|
const v = api.storage.get(legacyKey, null);
|
|
|
|
|
if (v !== null && api.storage.get(prefix + legacyKey, null) === null) {
|
|
|
|
|
api.storage.set(prefix + legacyKey, v);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
api.log("migrated legacy BCH wallet into multi-wallet layout");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function nextIndex(wallets, meta) {
|
|
|
|
|
let max = meta.startIndex - 1;
|
|
|
|
|
for (const w of wallets) {
|
|
|
|
|
if (chainKey(w.chain, w.network) !== chainKey(meta.chain, meta.network)) continue;
|
|
|
|
|
if (w.isLegacy) continue;
|
|
|
|
|
const m = /\/(\d+)$/.exec(w.purpose || "");
|
|
|
|
|
const n = m ? Number(m[1]) : NaN;
|
|
|
|
|
if (Number.isFinite(n) && n > max) max = n;
|
|
|
|
|
}
|
|
|
|
|
return max + 1;
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
}
|
|
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
function makeWalletId(meta, index) {
|
|
|
|
|
const n = String(meta.network).replace(/[^a-z0-9]/gi, "");
|
|
|
|
|
return `${meta.chain}-${n}-${index}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function autoLabel(meta, wallets) {
|
|
|
|
|
const same = wallets.filter((w) => chainKey(w.chain, w.network) === chainKey(meta.chain, meta.network));
|
|
|
|
|
if (!same.length) return meta.short;
|
|
|
|
|
return `${meta.short} #${same.length + 1}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---- runtime wallet map -----------------------------------------------------
|
|
|
|
|
// A "runtime" is a mounted wallet: its adapter instance plus phase + error.
|
|
|
|
|
// activate() derives all of them in parallel once the vault unlocks.
|
|
|
|
|
|
|
|
|
|
async function mountAllWallets() {
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
const c = ctx;
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const walletList = readWallets(c.api) || [];
|
|
|
|
|
for (const w of walletList) {
|
|
|
|
|
if (!c.runtimes.has(w.id)) c.runtimes.set(w.id, { entry: w, phase: "locked", error: null, adapter: null });
|
|
|
|
|
}
|
|
|
|
|
emitState();
|
|
|
|
|
await Promise.all(walletList.map((w) => mountWallet(w)));
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
}
|
|
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
async function mountWallet(entry) {
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
const c = ctx;
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const rt = c.runtimes.get(entry.id) || { entry, phase: "locked", error: null, adapter: null };
|
|
|
|
|
rt.entry = entry;
|
|
|
|
|
rt.phase = "locked"; rt.error = null;
|
|
|
|
|
c.runtimes.set(entry.id, rt);
|
|
|
|
|
emitState();
|
|
|
|
|
let root;
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
try {
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
root = await c.api.vault.derive(entry.purpose);
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
} catch (e) {
|
|
|
|
|
const msg = e?.message || String(e);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
rt.phase = /not set up/i.test(msg) ? "nosetup" : "error";
|
|
|
|
|
rt.error = msg;
|
|
|
|
|
emitState();
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
return;
|
|
|
|
|
}
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
if (ctx !== c) return;
|
|
|
|
|
try {
|
|
|
|
|
let adapter;
|
|
|
|
|
if (entry.chain === "bch") {
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
// Mainnet still honors the user-set custom electrum list; chipnet uses
|
|
|
|
|
// adapter-embedded defaults (no per-network custom list in this rev).
|
|
|
|
|
const servers = entry.network === "mainnet" ? bchServerList(c.api) : undefined;
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
adapter = new c.d.bchAdapter.BchWallet(root, {
|
|
|
|
|
walletId: entry.id,
|
|
|
|
|
storage: c.api.storage,
|
|
|
|
|
log: (...a) => c.api.log(`[${entry.id}]`, ...a),
|
|
|
|
|
onChange: () => emitStateForWallet(entry.id),
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
network: entry.network,
|
|
|
|
|
servers,
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
accountPath: entry.accountPath,
|
|
|
|
|
});
|
|
|
|
|
} else if (entry.chain === "trx") {
|
|
|
|
|
adapter = new c.d.tronAdapter.TronWallet(root, entry.network, {
|
|
|
|
|
storage: c.api.storage,
|
|
|
|
|
log: (...a) => c.api.log(`[${entry.id}]`, ...a),
|
|
|
|
|
onChange: () => emitStateForWallet(entry.id),
|
|
|
|
|
});
|
|
|
|
|
adapter.schedulePoll(20_000);
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
} else if (entry.chain === "sc") {
|
|
|
|
|
// walletdUrl is per-Sia-wallet (each sub-account may point at a
|
|
|
|
|
// different node) and stored under the scoped wallets/<id>/walletdUrl
|
|
|
|
|
// key. Empty = the panel shows a "point me at walletd" gate.
|
|
|
|
|
const walletdUrl = String(c.api.storage.get(`wallets/${entry.id}/walletdUrl`, "") || "");
|
|
|
|
|
adapter = new c.d.siaAdapter.SiaWallet(root, {
|
|
|
|
|
walletId: entry.id,
|
|
|
|
|
storage: c.api.storage,
|
|
|
|
|
log: (...a) => c.api.log(`[${entry.id}]`, ...a),
|
|
|
|
|
onChange: () => emitStateForWallet(entry.id),
|
|
|
|
|
walletdUrl,
|
|
|
|
|
});
|
|
|
|
|
if (walletdUrl) adapter.startPolling();
|
|
|
|
|
} else if (entry.chain === "dgb") {
|
|
|
|
|
adapter = new c.d.dgbAdapter.DgbWallet(root, {
|
|
|
|
|
walletId: entry.id,
|
|
|
|
|
storage: c.api.storage,
|
|
|
|
|
log: (...a) => c.api.log(`[${entry.id}]`, ...a),
|
|
|
|
|
onChange: () => emitStateForWallet(entry.id),
|
|
|
|
|
accountPath: entry.accountPath,
|
|
|
|
|
});
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
} else {
|
|
|
|
|
throw new Error(`unknown chain ${entry.chain}`);
|
|
|
|
|
}
|
|
|
|
|
rt.adapter = adapter;
|
|
|
|
|
rt.phase = "ready";
|
|
|
|
|
// Kick a first fetch. Errors here don't fail the mount — the panel shows
|
|
|
|
|
// them per-wallet via snapshot.error.
|
|
|
|
|
adapter.refresh(true).catch((e) => c.api.log(`[${entry.id}] initial refresh:`, e?.message || e));
|
|
|
|
|
emitStateForWallet(entry.id);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
rt.phase = "error";
|
|
|
|
|
rt.error = e?.message || String(e);
|
|
|
|
|
emitState();
|
|
|
|
|
} finally {
|
|
|
|
|
// Wipe the root buffer — the adapter has already turned it into keys.
|
|
|
|
|
if (root) try { root.fill(0); } catch {}
|
|
|
|
|
}
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
}
|
|
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
function unmountWallet(walletId) {
|
|
|
|
|
const rt = ctx.runtimes.get(walletId);
|
|
|
|
|
if (rt && rt.adapter) { try { rt.adapter.dispose(); } catch {} }
|
|
|
|
|
ctx.runtimes.delete(walletId);
|
feat(theseus/bchwallet): send — plan, approval overlay, sign, broadcast
Send tab: recipient (cashaddr or legacy, testnet rejected), amount with
BCH/sat toggle and Max, 1-5 sat/B fee slider, live fee/total preview via
planSend. Sending goes plan -> approval-modal (To/Amount/Fee/Total) ->
ECDSA DER + SIGHASH_ALL|FORKID -> blockchain.transaction.broadcast, then
shows the txid with an explorer link. Confirmed coins are spent before
unconfirmed; dust change folds into the fee. Verified end to end against a
fake Fulcrum: broadcast tx re-parsed, sighash recomputed, signature checks.
2026-09-06 02:49:09 +02:00
|
|
|
}
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
|
|
|
|
|
// ---- state / snapshot -------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function selectedWalletId() {
|
|
|
|
|
const list = readWallets(ctx.api) || [];
|
|
|
|
|
if (!list.length) return null;
|
|
|
|
|
const saved = String(ctx.api.storage.get("selectedWalletId", "") || "");
|
|
|
|
|
if (saved && list.some((w) => w.id === saved)) return saved;
|
|
|
|
|
const dflt = list.find((w) => w.isDefault) || list[0];
|
|
|
|
|
return dflt.id;
|
feat(theseus/bchwallet): send — plan, approval overlay, sign, broadcast
Send tab: recipient (cashaddr or legacy, testnet rejected), amount with
BCH/sat toggle and Max, 1-5 sat/B fee slider, live fee/total preview via
planSend. Sending goes plan -> approval-modal (To/Amount/Fee/Total) ->
ECDSA DER + SIGHASH_ALL|FORKID -> blockchain.transaction.broadcast, then
shows the txid with an explorer link. Confirmed coins are spent before
unconfirmed; dust change folds into the fee. Verified end to end against a
fake Fulcrum: broadcast tx re-parsed, sighash recomputed, signature checks.
2026-09-06 02:49:09 +02:00
|
|
|
}
|
|
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
function walletEntries() { return readWallets(ctx.api) || []; }
|
|
|
|
|
|
|
|
|
|
function overallPhase() {
|
|
|
|
|
// If ANY wallet is nosetup, treat the whole addon as nosetup — the user
|
|
|
|
|
// hasn't unlocked / set up the vault, so no wallet can work.
|
|
|
|
|
const runtimes = [...ctx.runtimes.values()];
|
|
|
|
|
if (!runtimes.length) return "locked";
|
|
|
|
|
if (runtimes.some((r) => r.phase === "nosetup")) return "nosetup";
|
|
|
|
|
if (runtimes.some((r) => r.phase === "locked")) return "locked";
|
|
|
|
|
return "ready";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function walletSummary(w) {
|
|
|
|
|
const meta = chainMeta(w.chain, w.network);
|
|
|
|
|
const rt = ctx.runtimes.get(w.id);
|
|
|
|
|
const snap = rt && rt.adapter ? rt.adapter.snapshot() : null;
|
|
|
|
|
return {
|
|
|
|
|
id: w.id, label: w.label, chain: w.chain, network: w.network, isDefault: !!w.isDefault, isLegacy: !!w.isLegacy,
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
logo: meta?.logo || null, color: meta?.color || "#888",
|
|
|
|
|
coinLabel: meta?.coinLabel || w.chain, networkLabel: meta?.networkLabel || w.network, testnet: !!meta?.testnet,
|
|
|
|
|
ticker: meta?.ticker || "?", short: meta?.short || w.chain, decimals: meta?.decimals || 8,
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
address: snap?.address || null,
|
|
|
|
|
balance: snap?.balance || { confirmed: 0, unconfirmed: 0 },
|
|
|
|
|
phase: rt?.phase || "locked",
|
|
|
|
|
error: rt?.error || null,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function snapshotForSelected() {
|
|
|
|
|
const id = selectedWalletId();
|
|
|
|
|
if (!id) return { phase: "empty" };
|
|
|
|
|
const rt = ctx.runtimes.get(id);
|
|
|
|
|
const entry = walletEntries().find((w) => w.id === id);
|
|
|
|
|
const meta = entry ? chainMeta(entry.chain, entry.network) : null;
|
|
|
|
|
const base = {
|
|
|
|
|
walletId: id,
|
|
|
|
|
label: entry?.label,
|
|
|
|
|
chain: entry?.chain,
|
|
|
|
|
network: entry?.network,
|
|
|
|
|
isLegacy: !!entry?.isLegacy,
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
meta: meta ? {
|
|
|
|
|
logo: meta.logo, color: meta.color, short: meta.short, ticker: meta.ticker, decimals: meta.decimals,
|
|
|
|
|
coinLabel: meta.coinLabel, networkLabel: meta.networkLabel, testnet: meta.testnet,
|
|
|
|
|
} : null,
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
supportsMessageSign: !!meta?.supportsMessageSign,
|
|
|
|
|
phase: rt?.phase || "locked",
|
|
|
|
|
error: rt?.error || null,
|
|
|
|
|
};
|
|
|
|
|
if (rt && rt.adapter) Object.assign(base, rt.adapter.snapshot());
|
|
|
|
|
return base;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function fullState() {
|
|
|
|
|
return {
|
|
|
|
|
overallPhase: overallPhase(),
|
|
|
|
|
selectedWalletId: selectedWalletId(),
|
|
|
|
|
wallets: walletEntries().map(walletSummary),
|
|
|
|
|
selected: snapshotForSelected(),
|
|
|
|
|
bchServers: {
|
|
|
|
|
list: bchServerList(ctx.api),
|
|
|
|
|
custom: Array.isArray(ctx.api.storage.get("servers", null)),
|
|
|
|
|
},
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
coins: coinsForPanel(),
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function emitState() { try { ctx.api.emit("state", fullState()); } catch {} }
|
|
|
|
|
function emitStateForWallet(id) {
|
|
|
|
|
// Any wallet change fans out to the panel with the full state so the
|
|
|
|
|
// wallet list balances update in the header too.
|
|
|
|
|
if (!ctx || !ctx.runtimes.has(id)) return;
|
|
|
|
|
emitState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---- panel messages ---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function requireWallet(id) {
|
|
|
|
|
const rt = ctx.runtimes.get(id);
|
|
|
|
|
if (!rt || rt.phase !== "ready" || !rt.adapter) throw new Error("wallet is not ready (vault locked?)");
|
|
|
|
|
return rt;
|
|
|
|
|
}
|
|
|
|
|
function requireSelected() { return requireWallet(selectedWalletId()); }
|
|
|
|
|
function fromPanel(m) { if (!m || m.from !== "panel") throw new Error("panel-only message"); }
|
|
|
|
|
function fromPage(m) {
|
|
|
|
|
if (!m || m.from !== "page" || !m.origin) throw new Error("page-only message");
|
|
|
|
|
return m.origin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const fmtBch = (sats) => (Number(sats) / 1e8).toFixed(8).replace(/(\.\d*?[1-9])0+$|\.0+$/, "$1");
|
|
|
|
|
const fmtTrx = (sun) => (Number(sun) / 1e6).toFixed(6).replace(/(\.\d*?[1-9])0+$|\.0+$/, "$1");
|
|
|
|
|
function fmtValue(units, decimals) {
|
|
|
|
|
const n = Number(units) / Math.pow(10, decimals);
|
|
|
|
|
return n.toFixed(decimals).replace(/(\.\d*?[1-9])0+$|\.0+$/, "$1");
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function registerPanelMessages(api) {
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
api.onMessage("state", (_p, m) => { fromPanel(m); return fullState(); });
|
|
|
|
|
api.onMessage("selectWallet", (p, m) => {
|
|
|
|
|
fromPanel(m);
|
|
|
|
|
const id = String(p && p.id || "");
|
|
|
|
|
if (!walletEntries().some((w) => w.id === id)) throw new Error("unknown wallet");
|
|
|
|
|
api.storage.set("selectedWalletId", id);
|
|
|
|
|
emitState();
|
|
|
|
|
return fullState();
|
|
|
|
|
});
|
|
|
|
|
api.onMessage("addWallet", async (p, m) => {
|
|
|
|
|
fromPanel(m);
|
|
|
|
|
const chain = String(p && p.chain || "");
|
|
|
|
|
const network = String(p && p.network || "");
|
|
|
|
|
const meta = chainMeta(chain, network);
|
|
|
|
|
if (!meta) throw new Error("unknown chain/network");
|
|
|
|
|
const list = walletEntries().slice();
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
// If this coin+network declares a `legacyFirstPurpose` (SC does, to
|
|
|
|
|
// recover funds from the standalone siawallet addon) and no wallet of
|
|
|
|
|
// this coin+network exists yet, use that purpose verbatim. The bump
|
|
|
|
|
// to the /aegis-namespaced/ prefix only starts on the second sub-account.
|
|
|
|
|
const netMeta = COINS[chain]?.networks?.[network] || {};
|
|
|
|
|
const existingForCoin = list.filter((w) => w.chain === chain && w.network === network && !w.isLegacy);
|
|
|
|
|
let purpose, isLegacy = false;
|
|
|
|
|
if (netMeta.legacyFirstPurpose && existingForCoin.length === 0
|
|
|
|
|
&& !list.some((w) => w.purpose === netMeta.legacyFirstPurpose)) {
|
|
|
|
|
purpose = netMeta.legacyFirstPurpose;
|
|
|
|
|
isLegacy = true;
|
|
|
|
|
} else {
|
|
|
|
|
const index = nextIndex(list, meta);
|
|
|
|
|
purpose = meta.purposePrefix + index;
|
|
|
|
|
}
|
|
|
|
|
const idIndex = nextIndex(list, meta);
|
|
|
|
|
const id = makeWalletId(meta, idIndex);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
if (list.some((w) => w.id === id || w.purpose === purpose)) throw new Error("duplicate wallet");
|
|
|
|
|
const label = String(p && p.label || "").trim() || autoLabel(meta, list);
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
const entry = { id, label, chain, network, purpose, isLegacy, createdAt: Date.now() };
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
list.push(entry);
|
|
|
|
|
writeWallets(api, list);
|
|
|
|
|
api.storage.set("selectedWalletId", id);
|
|
|
|
|
ctx.runtimes.set(id, { entry, phase: "locked", error: null, adapter: null });
|
|
|
|
|
emitState();
|
|
|
|
|
await mountWallet(entry);
|
|
|
|
|
return fullState();
|
|
|
|
|
});
|
|
|
|
|
api.onMessage("removeWallet", (p, m) => {
|
|
|
|
|
fromPanel(m);
|
|
|
|
|
const id = String(p && p.id || "");
|
|
|
|
|
const list = walletEntries();
|
|
|
|
|
const entry = list.find((w) => w.id === id);
|
|
|
|
|
if (!entry) throw new Error("unknown wallet");
|
|
|
|
|
if (entry.isDefault) throw new Error("the default wallet cannot be removed");
|
|
|
|
|
const next = list.filter((w) => w.id !== id);
|
|
|
|
|
writeWallets(api, next);
|
|
|
|
|
if (selectedWalletId() === id) api.storage.set("selectedWalletId", next[0]?.id || "");
|
|
|
|
|
unmountWallet(id);
|
|
|
|
|
// Drop per-wallet storage subtree.
|
|
|
|
|
const all = api.storage.all ? api.storage.all() : {};
|
|
|
|
|
const prefix = `wallets/${id}/`;
|
|
|
|
|
for (const k of Object.keys(all)) if (k.startsWith(prefix)) api.storage.set(k, null);
|
|
|
|
|
emitState();
|
|
|
|
|
return fullState();
|
|
|
|
|
});
|
|
|
|
|
api.onMessage("renameWallet", (p, m) => {
|
|
|
|
|
fromPanel(m);
|
|
|
|
|
const id = String(p && p.id || "");
|
|
|
|
|
const label = String(p && p.label || "").trim().slice(0, 60);
|
|
|
|
|
if (!label) throw new Error("label required");
|
|
|
|
|
const list = walletEntries();
|
|
|
|
|
const entry = list.find((w) => w.id === id);
|
|
|
|
|
if (!entry) throw new Error("unknown wallet");
|
|
|
|
|
entry.label = label;
|
|
|
|
|
writeWallets(api, list);
|
|
|
|
|
emitState();
|
|
|
|
|
return fullState();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
api.onMessage("refresh", async (_p, m) => { fromPanel(m); const rt = requireSelected(); await rt.adapter.refresh(true); return snapshotForSelected(); });
|
|
|
|
|
api.onMessage("nextAddress", (_p, m) => {
|
|
|
|
|
fromPanel(m);
|
|
|
|
|
const rt = requireSelected();
|
|
|
|
|
if (rt.entry.chain !== "bch") throw new Error("only BCH wallets have multiple receive addresses");
|
|
|
|
|
rt.adapter.nextAddress();
|
|
|
|
|
return snapshotForSelected();
|
|
|
|
|
});
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
api.onMessage("openUrl", (p, m) => { fromPanel(m); api.openTab(String(p && p.url || "")); return true; });
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
|
|
|
|
|
api.onMessage("setBchServers", (p, m) => {
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
fromPanel(m);
|
|
|
|
|
const patch = p || {};
|
|
|
|
|
if ("servers" in patch) {
|
|
|
|
|
const list = Array.isArray(patch.servers) ? patch.servers.map((s) => String(s).trim()).filter(Boolean) : [];
|
|
|
|
|
for (const s of list) if (!/^wss?:\/\/[^/\s]+$/i.test(s)) throw new Error(`server must be ws(s)://host:port — got ${s}`);
|
|
|
|
|
api.storage.set("servers", list.length ? list : null);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
// Push the new server list into every mounted BCH wallet.
|
|
|
|
|
for (const rt of ctx.runtimes.values()) {
|
|
|
|
|
if (rt.entry.chain === "bch" && rt.adapter) rt.adapter.setServers(bchServerList(api));
|
|
|
|
|
}
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
}
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
return fullState();
|
|
|
|
|
});
|
|
|
|
|
api.onMessage("setAccountPath", (p, m) => {
|
|
|
|
|
fromPanel(m);
|
|
|
|
|
const patch = p || {};
|
|
|
|
|
const id = String(patch.id || selectedWalletId());
|
|
|
|
|
const entry = walletEntries().find((w) => w.id === id);
|
|
|
|
|
if (!entry) throw new Error("unknown wallet");
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
if (entry.chain !== "bch" && entry.chain !== "dgb") throw new Error("account path is a BCH/DGB-only setting");
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const v = String(patch.accountPath || "").trim();
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
if (v && !/^m(\/\d+'?)+$/.test(v)) throw new Error("derivation path must look like m/84'/20'/0'");
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const list = walletEntries();
|
|
|
|
|
const idx = list.findIndex((w) => w.id === id);
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
const dflt = entry.chain === "bch" ? "m/44'/145'/0'" : "m/84'/20'/0'";
|
|
|
|
|
list[idx] = { ...list[idx], accountPath: v || dflt };
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
writeWallets(api, list);
|
|
|
|
|
const rt = ctx.runtimes.get(id);
|
|
|
|
|
if (rt && rt.adapter) { try { rt.adapter.dispose(); } catch {} rt.adapter = null; rt.phase = "locked"; }
|
|
|
|
|
mountWallet(list[idx]);
|
|
|
|
|
return fullState();
|
|
|
|
|
});
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
// Sia-only: per-wallet walletd URL. Live: pushes the URL into the adapter
|
|
|
|
|
// without rebuilding the keys (the seed stays derived from the same
|
|
|
|
|
// vault path — only the node the wallet talks to changes).
|
|
|
|
|
api.onMessage("setWalletdUrl", (p, m) => {
|
|
|
|
|
fromPanel(m);
|
|
|
|
|
const patch = p || {};
|
|
|
|
|
const id = String(patch.id || selectedWalletId());
|
|
|
|
|
const entry = walletEntries().find((w) => w.id === id);
|
|
|
|
|
if (!entry) throw new Error("unknown wallet");
|
|
|
|
|
if (entry.chain !== "sc") throw new Error("walletd URL is a Sia-only setting");
|
|
|
|
|
const v = String(patch.walletdUrl || "").trim();
|
|
|
|
|
if (v && !/^https?:\/\/[^\s]+$/i.test(v)) throw new Error("walletd URL must start with http:// or https://");
|
|
|
|
|
api.storage.set(`wallets/${id}/walletdUrl`, v);
|
|
|
|
|
const rt = ctx.runtimes.get(id);
|
|
|
|
|
if (rt && rt.adapter) {
|
|
|
|
|
rt.adapter.setWalletdUrl(v);
|
|
|
|
|
if (v) rt.adapter.startPolling();
|
|
|
|
|
rt.adapter.refresh(true).catch((e) => api.log(`[${id}] refresh:`, e?.message || e));
|
|
|
|
|
}
|
|
|
|
|
emitState();
|
|
|
|
|
return fullState();
|
|
|
|
|
});
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
|
|
|
|
|
// Live plan preview for the selected wallet.
|
|
|
|
|
api.onMessage("planSend", async (p, m) => {
|
|
|
|
|
fromPanel(m);
|
|
|
|
|
const rt = requireSelected();
|
|
|
|
|
const plan = await Promise.resolve(rt.adapter.plan(p || {}));
|
|
|
|
|
return describePlan(plan, rt.entry.chain, rt.entry.network);
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
});
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
// Execute a send with approval overlay.
|
feat(theseus/bchwallet): send — plan, approval overlay, sign, broadcast
Send tab: recipient (cashaddr or legacy, testnet rejected), amount with
BCH/sat toggle and Max, 1-5 sat/B fee slider, live fee/total preview via
planSend. Sending goes plan -> approval-modal (To/Amount/Fee/Total) ->
ECDSA DER + SIGHASH_ALL|FORKID -> blockchain.transaction.broadcast, then
shows the txid with an explorer link. Confirmed coins are spent before
unconfirmed; dust change folds into the fee. Verified end to end against a
fake Fulcrum: broadcast tx re-parsed, sighash recomputed, signature checks.
2026-09-06 02:49:09 +02:00
|
|
|
api.onMessage("send", async (p, m) => {
|
|
|
|
|
fromPanel(m);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const rt = requireSelected();
|
|
|
|
|
const plan = await Promise.resolve(rt.adapter.plan(p || {}));
|
|
|
|
|
const d = describePlan(plan, rt.entry.chain, rt.entry.network);
|
|
|
|
|
const meta = chainMeta(rt.entry.chain, rt.entry.network);
|
|
|
|
|
const rows = [
|
|
|
|
|
{ label: "To", value: d.recipients[0].to, mono: true },
|
|
|
|
|
{ label: "Amount", value: `${fmtValue(d.recipients[0].value, meta.decimals)} ${meta.ticker}`, strong: true },
|
|
|
|
|
{ label: "Fee", value: rt.entry.chain === "bch" ? `${plan.fee} sat (${plan.feeRate} sat/B)` : `${fmtValue(plan.fee, meta.decimals)} ${meta.ticker}` },
|
|
|
|
|
{ label: "Total", value: `${fmtValue(d.total, meta.decimals)} ${meta.ticker}` },
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
{ label: "Wallet", value: `${rt.entry.label} — ${meta.coinLabel} · ${meta.networkLabel}` },
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
];
|
feat(theseus/bchwallet): send — plan, approval overlay, sign, broadcast
Send tab: recipient (cashaddr or legacy, testnet rejected), amount with
BCH/sat toggle and Max, 1-5 sat/B fee slider, live fee/total preview via
planSend. Sending goes plan -> approval-modal (To/Amount/Fee/Total) ->
ECDSA DER + SIGHASH_ALL|FORKID -> blockchain.transaction.broadcast, then
shows the txid with an explorer link. Confirmed coins are spent before
unconfirmed; dust change folds into the fee. Verified end to end against a
fake Fulcrum: broadcast tx re-parsed, sighash recomputed, signature checks.
2026-09-06 02:49:09 +02:00
|
|
|
const pick = await api.approvalModal({
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
title: `Send ${meta.ticker}?`,
|
|
|
|
|
origin: "Aegis wallet panel",
|
|
|
|
|
rows,
|
feat(theseus/bchwallet): send — plan, approval overlay, sign, broadcast
Send tab: recipient (cashaddr or legacy, testnet rejected), amount with
BCH/sat toggle and Max, 1-5 sat/B fee slider, live fee/total preview via
planSend. Sending goes plan -> approval-modal (To/Amount/Fee/Total) ->
ECDSA DER + SIGHASH_ALL|FORKID -> blockchain.transaction.broadcast, then
shows the txid with an explorer link. Confirmed coins are spent before
unconfirmed; dust change folds into the fee. Verified end to end against a
fake Fulcrum: broadcast tx re-parsed, sighash recomputed, signature checks.
2026-09-06 02:49:09 +02:00
|
|
|
actions: [{ id: "send", label: "Send", primary: true }],
|
|
|
|
|
});
|
|
|
|
|
if (pick !== "send") throw new Error("cancelled");
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
return rt.adapter.signAndBroadcast(plan);
|
feat(theseus/bchwallet): send — plan, approval overlay, sign, broadcast
Send tab: recipient (cashaddr or legacy, testnet rejected), amount with
BCH/sat toggle and Max, 1-5 sat/B fee slider, live fee/total preview via
planSend. Sending goes plan -> approval-modal (To/Amount/Fee/Total) ->
ECDSA DER + SIGHASH_ALL|FORKID -> blockchain.transaction.broadcast, then
shows the txid with an explorer link. Confirmed coins are spent before
unconfirmed; dust change folds into the fee. Verified end to end against a
fake Fulcrum: broadcast tx re-parsed, sighash recomputed, signature checks.
2026-09-06 02:49:09 +02:00
|
|
|
});
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
api.onMessage("recovery", async (p, m) => {
|
|
|
|
|
fromPanel(m);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const id = String(p && p.id || selectedWalletId());
|
|
|
|
|
const rt = requireWallet(id);
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
if (typeof rt.adapter.recovery !== "function") throw new Error("this chain does not expose recovery details");
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const r = rt.adapter.recovery();
|
|
|
|
|
const out = { accountPath: r.accountPath, xpub: r.xpub, purpose: rt.entry.purpose };
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
if (p && p.reveal) {
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
// Sia's "xprv" is really the 32-byte wallet seed (walletd KeyFromSeed);
|
|
|
|
|
// BCH/DGB's is the account xprv. Warning copy fits both.
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
const pick = await api.approvalModal({
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
title: rt.entry.chain === "sc" ? "Reveal the wallet seed?" : "Reveal the account private key?",
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
origin: "Aegis wallet panel",
|
feat(theseus/aegis): fold Sia into the addon; add DGB (BIP84 native SegWit)
Aegis now covers four coins across two-step coin+network picks: BCH
(mainnet + chipnet), TRX (mainnet + Nile), SC (mainnet), DGB (mainnet).
- Sia (SC): pulled the standalone siawallet's lib into
bundled-addons/bchwallet/lib/sia/ and wrote lib/chain-sia.js exposing
the common adapter shape. The very first SC wallet the user adds in
Aegis reuses purpose "siawallet/mainnet/0" so pre-Aegis funds carry
over automatically; subsequent SC sub-accounts start at
"bchwallet/sc/mainnet/1". Per-wallet walletd URL setting; empty URL
shows a "Point Aegis at a walletd node" gate in the panel.
- Vault-derive gate now honors a manifest-declared `absorbs` list, so
Aegis's addon.json can list `absorbs: ["siawallet"]` and the derive()
guard accepts paths under either the current id or the absorbed one —
the mechanism a superseding add-on uses to inherit an older add-on's
keyspace without orphaning funds.
- DigiByte (DGB): lib/chain-dgb.js ports the relevant bits of the
SilentCode Digibyte design — SLIP-44 coin type 20, BIP84 native SegWit
(m/84'/20'/0'/0/x → dgb1q…) via ripemd160(sha256(pubkey)) + bech32.
ElectrumX-DGB backend reuses lib/electrum.js (public wss:50022 pool).
BIP143 P2WPKH sighash + witness-tx serialize implemented inline (no
FORKID — DGB uses standard Bitcoin sighash). Derivation cross-checked
against a known BIP39 vector in scratchpad/verify-dgb.mjs — the address
for "abandon×11 about, m/84'/20'/0'/0/0" is
dgb1q9gmf0pv8jdymcly6lz6fl7lf6mhslsd72e2jq8, matching iancoleman.io/bip39.
- Panel: SVG coin logos for SC (green disc with S) and DGB (blue
octagon with D) alongside the BCH/TRX marks. Chain-specific settings
block per coin (walletd URL for SC; derivation path for DGB). Balance
render uses BigInt-safe arithmetic so 24-decimal SC amounts don't
lose precision on the way through the panel; amount input on SC
returns a hastings string.
- Every chain adapter's snapshot fits the panel's shared shape
(address/balance/history/etc.), so future chains only need a new
chain-<x>.js file, a COINS registry entry, a matching case in
mountWallet, and an SVG logo.
Standalone siawallet addon stays as-is on disk; users can delete it once
they've confirmed Aegis shows the same balance. Nothing here disables it.
2026-09-07 01:56:25 +02:00
|
|
|
body: "Anyone holding this can spend every coin in this wallet. It stays on screen until you close the Settings tab.",
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
actions: [{ id: "reveal", label: "Reveal", danger: true }],
|
|
|
|
|
});
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
if (pick === "reveal") out.xprv = r.xprv;
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
}
|
|
|
|
|
return out;
|
|
|
|
|
});
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
|
|
|
|
|
api.onMessage("permissions", (_p, m) => { fromPanel(m); return permissions(api); });
|
|
|
|
|
api.onMessage("revoke", (p, m) => {
|
|
|
|
|
fromPanel(m);
|
|
|
|
|
const perms = permissions(api);
|
|
|
|
|
delete perms[String(p && p.origin || "")];
|
|
|
|
|
api.storage.set("permissions", perms);
|
|
|
|
|
return perms;
|
|
|
|
|
});
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
}
|
|
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
// One "describePlan" is enough for both chains because plan() returns a
|
|
|
|
|
// common shape: {recipients:[{to,value}], fee, feeRate, total, inputs:[]…}.
|
|
|
|
|
function describePlan(plan) {
|
|
|
|
|
const sent = plan.recipients.reduce((a, r) => a + r.value, 0);
|
|
|
|
|
return {
|
|
|
|
|
recipients: plan.recipients, fee: plan.fee, feeRate: plan.feeRate,
|
|
|
|
|
inputs: (plan.inputs || []).length, change: plan.change || null,
|
|
|
|
|
total: plan.total != null ? plan.total : (sent + plan.fee),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---- dapp bridges (page → activate()) --------------------------------------
|
|
|
|
|
// Permission model stays the same as the single-wallet build for BCH:
|
|
|
|
|
// { [origin]: { readAddress:true, sendTx:{capSats,usedSats,grantedAt},
|
|
|
|
|
// trx: { readAddress:true, network } } }
|
|
|
|
|
// The BCH bridge always talks to the LEGACY default BCH wallet (the .x pages
|
|
|
|
|
// pre-date multi-wallet and cannot pick between them). The Tron bridge talks
|
|
|
|
|
// to the currently-SELECTED Tron wallet; if none is selected, requests fail.
|
|
|
|
|
const BCH_ALLOWANCES = [100000, 1000000, 10000000]; // 0.001, 0.01, 0.1 BCH
|
2026-09-06 02:56:34 +02:00
|
|
|
const pendingByOrigin = new Set();
|
|
|
|
|
function permissions(api) { const p = api.storage.get("permissions", {}); return p && typeof p === "object" ? p : {}; }
|
|
|
|
|
async function withOriginLock(origin, fn) {
|
|
|
|
|
if (pendingByOrigin.has(origin)) throw new Error("a wallet request from this site is already waiting for approval");
|
|
|
|
|
pendingByOrigin.add(origin);
|
|
|
|
|
try { return await fn(); } finally { pendingByOrigin.delete(origin); }
|
|
|
|
|
}
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
|
|
|
|
|
// Only .x sites (BCNR-native TLD) get the BCH bridge, matching the pre-
|
|
|
|
|
// multi-wallet gate. Widening the manifest to https://*/* makes the Tron
|
|
|
|
|
// bridge available everywhere; the BCH side enforces its narrower rule
|
|
|
|
|
// inside the handlers.
|
|
|
|
|
function isBchOrigin(origin) {
|
|
|
|
|
try { const h = new URL(origin).hostname; return /\.x$/.test(h); }
|
|
|
|
|
catch { return false; }
|
|
|
|
|
}
|
|
|
|
|
function legacyBchRuntime() {
|
|
|
|
|
const rt = ctx.runtimes.get(LEGACY_BCH_WALLET_ID);
|
|
|
|
|
if (!rt || rt.phase !== "ready" || !rt.adapter) throw new Error("wallet is not ready (vault locked?)");
|
|
|
|
|
return rt;
|
|
|
|
|
}
|
|
|
|
|
// The Tron bridge routes to the currently-selected wallet if it is Tron;
|
|
|
|
|
// otherwise it looks for the first ready Tron wallet on the selected network
|
|
|
|
|
// hint; else rejects with "no tron wallet".
|
|
|
|
|
function activeTronRuntime() {
|
|
|
|
|
const selId = selectedWalletId();
|
|
|
|
|
const selRt = selId && ctx.runtimes.get(selId);
|
|
|
|
|
if (selRt && selRt.entry.chain === "trx" && selRt.phase === "ready") return selRt;
|
|
|
|
|
for (const rt of ctx.runtimes.values()) if (rt.entry.chain === "trx" && rt.phase === "ready") return rt;
|
|
|
|
|
throw new Error("no Tron wallet available — add one in the Aegis sidebar");
|
2026-09-06 02:56:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function registerPageMessages(api) {
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
// ---- BCH bridge (unchanged behavior; wallet source is legacy default) ----
|
2026-09-06 02:56:34 +02:00
|
|
|
api.onMessage("getAddress", async (_p, m) => {
|
|
|
|
|
const origin = fromPage(m);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
if (!isBchOrigin(origin)) throw new Error("this site is not on a Bitcoin Cash origin");
|
|
|
|
|
const rt = legacyBchRuntime();
|
2026-09-06 02:56:34 +02:00
|
|
|
const perms = permissions(api);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
if (perms[origin] && perms[origin].readAddress) return rt.adapter.current().address;
|
2026-09-06 02:56:34 +02:00
|
|
|
return withOriginLock(origin, async () => {
|
|
|
|
|
const pick = await api.approvalModal({
|
|
|
|
|
title: "Share your Bitcoin Cash address?",
|
|
|
|
|
origin,
|
|
|
|
|
body: "The site will see your current receiving address and can look up its balance and history on the public chain.",
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
rows: [{ label: "Address", value: rt.adapter.current().address, mono: true }],
|
2026-09-06 02:56:34 +02:00
|
|
|
actions: [{ id: "allow", label: "Share", primary: true }],
|
|
|
|
|
checkbox: { id: "always", label: "Always allow this site to see my address" },
|
|
|
|
|
});
|
|
|
|
|
if (!pick.startsWith("allow")) throw new Error("user rejected");
|
|
|
|
|
if (pick === "allow+always") { perms[origin] = { ...(perms[origin] || {}), readAddress: true }; api.storage.set("permissions", perms); emitState(); }
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
return rt.adapter.current().address;
|
2026-09-06 02:56:34 +02:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
api.onMessage("signAndSend", async (p, m) => {
|
|
|
|
|
const origin = fromPage(m);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
if (!isBchOrigin(origin)) throw new Error("this site is not on a Bitcoin Cash origin");
|
|
|
|
|
const rt = legacyBchRuntime();
|
2026-09-06 02:56:34 +02:00
|
|
|
return withOriginLock(origin, async () => {
|
|
|
|
|
let plan;
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
try { plan = rt.adapter.plan(p || {}); }
|
2026-09-06 02:56:34 +02:00
|
|
|
catch (e) { throw new Error(/insufficient funds|too small/i.test(e?.message) ? "insufficient funds" : e?.message || String(e)); }
|
|
|
|
|
const d = describePlan(plan);
|
|
|
|
|
if (d.recipients.length > 8) throw new Error("too many outputs");
|
2026-09-06 12:43:17 +02:00
|
|
|
const perms = permissions(api);
|
|
|
|
|
const budget = perms[origin] && perms[origin].sendTx;
|
|
|
|
|
const remaining = budget ? Math.max(0, (budget.capSats | 0) - (budget.usedSats | 0)) : 0;
|
|
|
|
|
if (budget && d.total <= remaining) {
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const r = await rt.adapter.signAndBroadcast(plan);
|
2026-09-06 12:43:17 +02:00
|
|
|
budget.usedSats = (budget.usedSats | 0) + d.total;
|
|
|
|
|
api.storage.set("permissions", perms);
|
|
|
|
|
emitState();
|
|
|
|
|
api.log(`silent send ${d.total} sat for ${origin}, ${remaining - d.total} sat of allowance left`);
|
|
|
|
|
return { txid: r.txid };
|
|
|
|
|
}
|
2026-09-06 02:56:34 +02:00
|
|
|
const rows = d.recipients.map((r, i) => ({ label: d.recipients.length > 1 ? `To #${i + 1}` : "To", value: r.to, mono: true }));
|
|
|
|
|
rows.push({ label: "Amount", value: fmtBch(d.recipients.reduce((a, r) => a + r.value, 0)) + " BCH", strong: true });
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
rows.push({ label: "Fee", value: `${plan.fee} sat (${plan.feeRate} sat/B)` });
|
2026-09-06 02:56:34 +02:00
|
|
|
rows.push({ label: "Total", value: fmtBch(d.total) + " BCH" });
|
|
|
|
|
const pick = await api.approvalModal({
|
|
|
|
|
title: "Send Bitcoin Cash?",
|
|
|
|
|
origin,
|
2026-09-06 12:43:17 +02:00
|
|
|
body: budget
|
|
|
|
|
? `This payment is over what is left of the site's allowance (${fmtBch(remaining)} BCH). Check the address and amount.`
|
|
|
|
|
: "This site is asking your wallet to pay. Check the address and amount.",
|
2026-09-06 02:56:34 +02:00
|
|
|
rows,
|
|
|
|
|
actions: [{ id: "send", label: "Send", primary: true }],
|
2026-09-06 12:43:17 +02:00
|
|
|
select: {
|
|
|
|
|
id: "cap", label: "Afterwards",
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
options: [{ value: "", label: "ask every time" }, ...BCH_ALLOWANCES.map((s) => ({ value: String(s), label: `allow up to ${fmtBch(s)} BCH more without asking` }))],
|
2026-09-06 12:43:17 +02:00
|
|
|
},
|
2026-09-06 02:56:34 +02:00
|
|
|
});
|
2026-09-06 12:43:17 +02:00
|
|
|
const [action, ...flags] = pick.split("+");
|
|
|
|
|
if (action !== "send") throw new Error("user rejected");
|
|
|
|
|
const cap = flags.find((f) => f.startsWith("cap="));
|
|
|
|
|
const capSats = cap ? Number(cap.slice(4)) : 0;
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
if (BCH_ALLOWANCES.includes(capSats)) {
|
2026-09-06 12:43:17 +02:00
|
|
|
perms[origin] = { ...(perms[origin] || {}), sendTx: { capSats, usedSats: 0, grantedAt: Date.now() } };
|
|
|
|
|
api.storage.set("permissions", perms);
|
|
|
|
|
} else if (budget) {
|
|
|
|
|
delete perms[origin].sendTx;
|
|
|
|
|
api.storage.set("permissions", perms);
|
|
|
|
|
}
|
|
|
|
|
emitState();
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const r = await rt.adapter.signAndBroadcast(plan);
|
2026-09-06 02:56:34 +02:00
|
|
|
return { txid: r.txid };
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
api.onMessage("signMessage", async (p, m) => {
|
|
|
|
|
const origin = fromPage(m);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
if (!isBchOrigin(origin)) throw new Error("this site is not on a Bitcoin Cash origin");
|
|
|
|
|
const rt = legacyBchRuntime();
|
2026-09-06 02:56:34 +02:00
|
|
|
const message = String(p && p.message != null ? p.message : "");
|
|
|
|
|
if (message.length > 4096) throw new Error("message too long");
|
|
|
|
|
return withOriginLock(origin, async () => {
|
|
|
|
|
const pick = await api.approvalModal({
|
|
|
|
|
title: "Sign a message?",
|
|
|
|
|
origin,
|
|
|
|
|
body: "Signing proves you control the address below. It moves no coins.",
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
rows: [
|
|
|
|
|
{ label: "Message", value: message.length > 400 ? message.slice(0, 400) + "…" : message, mono: true },
|
|
|
|
|
{ label: "Address", value: rt.adapter.current().address, mono: true },
|
|
|
|
|
],
|
2026-09-06 02:56:34 +02:00
|
|
|
actions: [{ id: "sign", label: "Sign", primary: true }],
|
|
|
|
|
});
|
|
|
|
|
if (pick !== "sign") throw new Error("user rejected");
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
return rt.adapter.signMessage(message);
|
2026-09-06 02:56:34 +02:00
|
|
|
});
|
|
|
|
|
});
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
|
|
|
|
|
// ---- Tron bridge (tronWeb / tronLink) -----------------------------------
|
|
|
|
|
api.onMessage("trx.requestAccounts", async (_p, m) => {
|
|
|
|
|
const origin = fromPage(m);
|
|
|
|
|
const rt = activeTronRuntime();
|
2026-09-06 02:56:34 +02:00
|
|
|
const perms = permissions(api);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const alreadyOK = perms[origin] && perms[origin].trx && perms[origin].trx.readAddress;
|
|
|
|
|
const snap = rt.adapter.snapshot();
|
|
|
|
|
if (alreadyOK) return { code: 200, address: snap.address, network: snap.network };
|
|
|
|
|
return withOriginLock(origin, async () => {
|
|
|
|
|
const pick = await api.approvalModal({
|
|
|
|
|
title: "Connect this site to your Tron wallet?",
|
|
|
|
|
origin,
|
|
|
|
|
body: "The site will see this address and can build transactions for you to sign.",
|
|
|
|
|
rows: [
|
|
|
|
|
{ label: "Address", value: snap.address, mono: true },
|
|
|
|
|
{ label: "Network", value: snap.network === "nile" ? "Nile testnet" : "Tron mainnet" },
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
{ label: "Wallet", value: `${rt.entry.label} — Tron · ${snap.network === "nile" ? "Nile testnet" : "Mainnet"}` },
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
],
|
|
|
|
|
actions: [{ id: "allow", label: "Connect", primary: true }],
|
|
|
|
|
checkbox: { id: "always", label: "Always allow this site to see this address" },
|
|
|
|
|
});
|
|
|
|
|
if (!pick.startsWith("allow")) throw new Error("user rejected");
|
|
|
|
|
if (pick === "allow+always") {
|
|
|
|
|
perms[origin] = { ...(perms[origin] || {}), trx: { readAddress: true, network: snap.network } };
|
|
|
|
|
api.storage.set("permissions", perms);
|
|
|
|
|
emitState();
|
|
|
|
|
}
|
|
|
|
|
return { code: 200, address: snap.address, network: snap.network };
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
api.onMessage("trx.getAccount", (_p, m) => {
|
|
|
|
|
const origin = fromPage(m);
|
|
|
|
|
const perms = permissions(api);
|
|
|
|
|
if (!(perms[origin] && perms[origin].trx && perms[origin].trx.readAddress)) throw new Error("not connected — call tron_requestAccounts first");
|
|
|
|
|
const rt = activeTronRuntime();
|
|
|
|
|
const snap = rt.adapter.snapshot();
|
|
|
|
|
return { address: snap.address, network: snap.network };
|
|
|
|
|
});
|
|
|
|
|
// Sign an arbitrary raw_data_hex the dapp built (with its own tronWeb).
|
|
|
|
|
// The wallet never guesses the intent — the approval overlay shows the
|
|
|
|
|
// decoded contract type and destination when it can, and always the txID.
|
|
|
|
|
api.onMessage("trx.signTransaction", async (p, m) => {
|
|
|
|
|
const origin = fromPage(m);
|
|
|
|
|
const rt = activeTronRuntime();
|
|
|
|
|
const perms = permissions(api);
|
|
|
|
|
if (!(perms[origin] && perms[origin].trx && perms[origin].trx.readAddress)) throw new Error("not connected — call tron_requestAccounts first");
|
|
|
|
|
const tx = p && p.transaction;
|
|
|
|
|
if (!tx || typeof tx !== "object" || !tx.raw_data_hex || !tx.raw_data) throw new Error("bad transaction");
|
|
|
|
|
return withOriginLock(origin, async () => {
|
|
|
|
|
const contract = (tx.raw_data.contract || [])[0];
|
|
|
|
|
const type = contract?.type || "Contract";
|
|
|
|
|
const rows = [{ label: "Type", value: type }, { label: "Tx ID", value: tx.txID || "(unset)", mono: true }];
|
|
|
|
|
if (type === "TransferContract") {
|
|
|
|
|
const v = contract.parameter?.value || {};
|
|
|
|
|
try {
|
|
|
|
|
const to = v.to_address ? ctx.d.tronAdapter.hexToAddress(v.to_address) : (v.to_address || "");
|
|
|
|
|
const amount = Number(v.amount || 0);
|
|
|
|
|
rows.splice(1, 0, { label: "To", value: to, mono: true }, { label: "Amount", value: `${fmtTrx(amount)} TRX`, strong: true });
|
|
|
|
|
} catch {}
|
|
|
|
|
}
|
feat(theseus/aegis): SVG coin logos, two-step coin/network picker, BCH Chipnet
- Inline SVG logos for BCH (green disc + ₿) and TRX (red disc + geometric T)
replace the 🟨/🔴/🔵 emoji in the sidebar header and wallet picker rows.
The approval overlay stays text-only ("Wallet: <name> — BCH · Mainnet")
because that surface renders plain rows, not HTML.
- Wallet picker's "Add wallet" is now two-step: click a coin to expand its
networks, then click a network to create the wallet. The flat list is gone.
- BCH Chipnet is a real chain option now: bchtest cashaddr prefix,
m/44'/1'/0' derivation (BIP44 testnet coin type), bundled Chipnet electrum
defaults, chipnet.imaginary.cash explorer, tbch.googol.cash faucet link
in Receive. The shared electrum-servers setting stays mainnet-only in
this rev; Chipnet uses adapter-embedded defaults.
- lib/chain-bch.js gained a BCH_NETWORKS table so mainnet vs chipnet
differences (prefix, path, servers, explorer, faucet) live in one place.
- Registry is grouped by coin ({networks:{…}}) instead of a flat
chain:network map — snapshot exposes coins[] for the panel and adds
coinLabel/networkLabel/testnet fields per wallet.
- Testnet wallets get a small "TEST" tag next to the network name so the
user can never mistake a chipnet or Nile balance for real money.
Legacy BCH mainnet index 0 derivation unchanged (bchwallet/mainnet/0 →
m/44'/145'/0' → bitcoincash prefix); the network parameter defaults to
"mainnet" and BCH_NETWORKS.mainnet reproduces the pre-change constants.
2026-09-07 01:07:31 +02:00
|
|
|
rows.push({ label: "Wallet", value: `${rt.entry.label} — Tron · ${rt.adapter.snapshot().network === "nile" ? "Nile testnet" : "Mainnet"}` });
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
const pick = await api.approvalModal({
|
|
|
|
|
title: "Sign a Tron transaction?",
|
|
|
|
|
origin,
|
|
|
|
|
body: "The site built this transaction. Check the type, amount, and destination before signing.",
|
|
|
|
|
rows,
|
|
|
|
|
actions: [{ id: "sign", label: "Sign", primary: true }],
|
|
|
|
|
});
|
|
|
|
|
if (pick !== "sign") throw new Error("user rejected");
|
|
|
|
|
const sig = rt.adapter.signRawData(tx.raw_data_hex);
|
|
|
|
|
const signed = { ...tx, signature: [sig] };
|
|
|
|
|
return signed;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
api.onMessage("trx.sendRawTransaction", async (p, m) => {
|
|
|
|
|
const origin = fromPage(m);
|
|
|
|
|
const rt = activeTronRuntime();
|
|
|
|
|
const perms = permissions(api);
|
|
|
|
|
if (!(perms[origin] && perms[origin].trx && perms[origin].trx.readAddress)) throw new Error("not connected — call tron_requestAccounts first");
|
|
|
|
|
const signedTx = p && p.transaction;
|
|
|
|
|
if (!signedTx || !signedTx.raw_data_hex || !Array.isArray(signedTx.signature)) throw new Error("bad signed tx");
|
|
|
|
|
// No approval here — broadcasting a *signed* tx does not add any risk
|
|
|
|
|
// the sign step didn't already carry. Sites that don't want an extra
|
|
|
|
|
// network round-trip pass {broadcast:true} to sign; we support both.
|
|
|
|
|
return rt.adapter.broadcastSignedTx(signedTx);
|
|
|
|
|
});
|
|
|
|
|
api.onMessage("trx.signMessageV2", async (p, m) => {
|
|
|
|
|
const origin = fromPage(m);
|
|
|
|
|
const rt = activeTronRuntime();
|
|
|
|
|
const perms = permissions(api);
|
|
|
|
|
if (!(perms[origin] && perms[origin].trx && perms[origin].trx.readAddress)) throw new Error("not connected — call tron_requestAccounts first");
|
|
|
|
|
const message = String(p && p.message != null ? p.message : "");
|
|
|
|
|
if (message.length > 4096) throw new Error("message too long");
|
|
|
|
|
return withOriginLock(origin, async () => {
|
|
|
|
|
const snap = rt.adapter.snapshot();
|
|
|
|
|
const pick = await api.approvalModal({
|
|
|
|
|
title: "Sign a Tron message?",
|
|
|
|
|
origin,
|
|
|
|
|
body: "Signing proves you control this address. It moves no coins.",
|
|
|
|
|
rows: [
|
|
|
|
|
{ label: "Message", value: message.length > 400 ? message.slice(0, 400) + "…" : message, mono: true },
|
|
|
|
|
{ label: "Address", value: snap.address, mono: true },
|
|
|
|
|
],
|
|
|
|
|
actions: [{ id: "sign", label: "Sign", primary: true }],
|
|
|
|
|
});
|
|
|
|
|
if (pick !== "sign") throw new Error("user rejected");
|
|
|
|
|
return rt.adapter.signMessageV2(message);
|
|
|
|
|
});
|
2026-09-06 02:56:34 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
// ---- activate ---------------------------------------------------------------
|
|
|
|
|
|
2026-09-06 02:33:27 +02:00
|
|
|
module.exports = {
|
|
|
|
|
activate(api) {
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
api.registerSidebarPanel({ id: "main", title: "Wallet", icon: "🛡", page: "panel.html" });
|
|
|
|
|
const c = ctx = {
|
|
|
|
|
api,
|
|
|
|
|
d: null,
|
|
|
|
|
runtimes: new Map(), // walletId -> { entry, phase, error, adapter }
|
|
|
|
|
};
|
|
|
|
|
migrateLegacyStorage(api);
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
registerPanelMessages(api);
|
2026-09-06 02:56:34 +02:00
|
|
|
registerPageMessages(api);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
loadDeps(api).then((d) => {
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
if (ctx !== c) return;
|
|
|
|
|
c.d = d;
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
return mountAllWallets();
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
}).catch((e) => {
|
|
|
|
|
if (ctx !== c) return;
|
|
|
|
|
api.log("startup failed:", e?.message);
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
emitState();
|
feat(theseus/bchwallet): receive + history — vault-derived keys, cashaddr, QR, electrum
Wallet core on mainnet:
- keys from api.vault.derive("bchwallet/mainnet/0") -> BIP32 m/44'/145'/0'
(@scure/bip32), never persisted; wiped on deactivate.
- lib/cashaddr.js (encode/decode + legacy Base58Check, spec vectors pass),
lib/keys.js (hash160, p2pkh, electrum scripthash, ECDSA DER + BIP-137
recoverable signing), lib/tx.js (serialization, SIGHASH_ALL|FORKID
digest, coin selection, fee estimate), lib/electrum.js (Fulcrum WSS
client with failover + subscriptions), lib/wallet.js (gap-limit scan,
balance, UTXOs, 25-tx history with per-tx deltas, cached public txs).
- qr.js: dependency-free QR encoder (byte mode, v1-10, EC M/L; verified
against jsQR).
- panel: balance header, Receive (QR, copy, next unused address, explorer),
History (deltas, confirmations, explorer links), Settings (derivation
path, electrum server list, xpub / approval-gated xprv reveal). Locked
and not-set-up vault states explained in-panel.
- host: api.import for ESM-only deps, api.openTab for explorer links; an
add-on whose activate() throws is no longer listed twice.
2026-09-06 02:46:41 +02:00
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
deactivate() {
|
|
|
|
|
const c = ctx; ctx = null;
|
|
|
|
|
if (!c) return;
|
feat(theseus/aegis): multi-wallet + Tron mainnet + Tron Nile in the bundled addon
Turns the single-account BCH addon into Aegis: a chain-agnostic wallet manager
with a wallet picker in the sidebar header, per-wallet sub-accounts, and Tron
mainnet + Nile alongside BCH. Add-on id stays "bchwallet" so vault-derive paths
stay in the same namespace and the legacy BCH default wallet uses PURPOSE
"bchwallet/mainnet/0" byte-identical to before — funds are untouched.
- lib/chain-bch.js wraps the existing keys/tx/wallet/electrum stack with the
common adapter shape and scopes each wallet's storage under wallets/<id>/…
- lib/chain-tron.js: m/44'/195'/0'/0/0 → secp256k1 → keccak256 → 0x41 || h20
→ base58check. Balance + history via TronGrid v1, send via createtransaction
+ sha256(raw_data_hex) sign + broadcasttransaction. Mainnet and Nile share
the address format; different vault paths mean different keys so a mainnet
wallet can never accidentally sign against Nile.
- lib/base58check.js: bitcoin-alphabet base58 with sha256d checksum. k=1
derivation verified against Ethereum's canonical k=1 H160 in a scratchpad
harness (correct-by-construction for Tron address).
- Combined wallet-inject.js: window.bitcoincash on .x pages (unchanged gate),
window.tronWeb + window.tronLink on any https page. tron_requestAccounts
triggers the approval overlay; sign / sendRawTransaction / signMessageV2
route to the currently-selected Tron wallet. Emits accountsChanged /
setNode messages TronLink dapps listen for; chain ids 0x2b6653dc /
0xcd8690dc match what TronLink itself uses.
- New panel: chain-aware wallet picker in the header (badges 🟨 BCH,
🔴 Tron, 🔵 Nile), Add-wallet dropdown per chain, per-chain unit picker
(BCH/sat, TRX/sun), per-wallet rename + remove (isLegacy default is
protected). Sends show the chosen wallet in the approval overlay so the
user can never mistake sub-account.
- Migration on first launch: pre-multi-wallet storage (top-level
receiveCursor / txCache) is rehomed under wallets/bch-default/… and the
legacy account path is preserved.
Not shipped: user is bundling into the next release. Live Nile broadcast +
real dapp connect need a set-up vault; the code paths are unit-verified end
to end but a testnet send + tronscan.io/nile connect are user-side steps.
2026-09-06 22:00:27 +02:00
|
|
|
for (const rt of c.runtimes.values()) {
|
|
|
|
|
try { rt.adapter && rt.adapter.dispose(); } catch {}
|
|
|
|
|
}
|
|
|
|
|
c.runtimes.clear();
|
2026-09-06 02:33:27 +02:00
|
|
|
},
|
|
|
|
|
};
|