theseus/bundled-addons/bchwallet/index.js

1356 lines
59 KiB
JavaScript
Raw Normal View History

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.
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/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/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/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) {
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");
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");
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): Ethereum + Solana adapters, DGB address-family picker, Aegis-branded shield Multi-currency coverage matches what aegis.x has been advertising: BCH, TRX, SC, DGB, ETH, SOL — six coins, two-step coin/network picker for each. Panel logos, favicon and fallback all read as Aegis. - Ethereum (lib/chain-eth.js): mainnet + Sepolia. BIP44 m/44'/60'/0'/0/0 → secp256k1 → EIP-55 checksummed hex address (verified against MetaMask's canonical abandon×11 vector 0x9858EfFD23…4EcaEda94). JSON-RPC backend (Cloudflare mainnet, PublicNode Sepolia by default; per-wallet override). EIP-1559 send with an inline RLP encoder + secp256k1 recoverable sign; broadcast via eth_sendRawTransaction. personal_sign message signing follows the \x19Ethereum Signed Message:\n prefix. - Solana (lib/chain-sol.js): mainnet-beta + devnet. SLIP-0010 ed25519 derivation at m/44'/501'/0'/0' (all-hardened), base58 address (@noble ed25519). SLIP-0010 layer verified against spec Test Vector 1 in scratchpad/verify-slip10.mjs. Native SOL transfer via the system program with compact-u16 message serialization + ed25519 sign + sendTransaction. Devnet gets a faucet.solana.com link in Receive; the panel appends ?cluster=devnet when opening the explorer. - DGB address family selector (lib/chain-dgb.js already carried the paths): the Settings block now shows a Native SegWit / Taproot / Wrapped SegWit / Legacy P2PKH picker. Selecting a family auto-fills the derivation-path input with that family's default; Apply rebuilds the wallet against the new path. Address families exposed via chainMeta.addressFamilies so the panel can render them from data. - Panel branding: inline SVG shield (hexagonal aspis, same silhouette as the aegis.x hero) replaces the "?" fallback in logoSvg() and is what the header shows before a wallet is selected. Data-URI favicon wired into panel.html so the Theseus sidebar tab icon reads as Aegis rather than a chain-specific coin mark. - QR payloads now follow each chain's own URI scheme (BIP21 for BCH/DGB, EIP-681 for ETH, Solana Pay for SOL) so external scanners route the scan to the right wallet. Not shipped: EIP-1193 provider (window.ethereum) and wallet-adapter protocol (window.solana). The signing paths exist; only the page-inject bridge glue is missing. History for ETH/SOL is also empty in this rev — both need indexer plumbing (Etherscan V2 for ETH, getSignaturesForAddress + getTransaction pagination for SOL).
2026-09-07 20:31:27 +02:00
const ethAdapter = require("./lib/chain-eth.js")({ HDKey, secp256k1, keccak_256 });
// Solana uses the raw base58 alphabet (no checksum), which lives inside
// base58check as encodeBase58 / decodeBase58 — expose them under a
// `{encode, decode}` shape the SOL adapter reads from.
const solBase58 = { encode: base58check.encodeBase58, decode: base58check.decodeBase58 };
const solAdapter = require("./lib/chain-sol.js")({ ed25519, base58: solBase58 });
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): Bitcoin adapter (mainnet + testnet3, BIP84 native SegWit) Seven coins across twelve networks now — BTC joins the shipping roster. - lib/chain-btc.js: BIP84 native SegWit — m/84'/0'/0'/0/x → bc1q… (mainnet), m/84'/1'/0'/0/x → tb1q… (testnet3). Reuses the exact same stack the DGB adapter already pulls in: bitcoinjs-lib for network params + payments.p2wpkh + PSBT, bip32 for HD derivation, ecpair for the Signer interface, ecc (@bitcoinerlab/secp256k1) for message-sign recoverable sigs. No new npm deps. - Backend: same lib/electrum.js Aegis uses for BCH and DGB — plugged into a public Bitcoin ElectrumX pool (blockstream.info, lu.ke, grey.pw) for mainnet and aranguren.org / blockstream.info:993 for testnet3. Send flow: PSBT build + per-input signInput + finalizeAllInputs + broadcast. BIP-137 recoverable message signing. - Registered as btc:mainnet + btc:testnet in COINS with the orange Bitcoin disc SVG logo. Mount case mirrors DGB (accountPath honored, so switching to m/44'/0'/0' or m/49'/0'/0' via the setAccountPath message gives legacy 1… or wrapped-segwit 3… — same one-line UI plumb as the DGB address-family selector, deferred to a follow-up). - Panel: sat as the small-unit label, bitcoin: BIP21 QR payload, chain-aware send placeholder ("bc1q…" mainnet / "tb1q…" testnet). - Verified: BIP84 spec test vector — abandon×11 mnemonic derives bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu at m/84'/0'/0'/0/0 (byte-identical to the vector in the BIP text). Testnet variant produces tb1q6rz28mcfaxtmd6v789l9rrlrusdprr9pqcpvkl at m/84'/1'/0'/0/0 (cross-checkable on iancoleman.io/bip39 with coin BTC Testnet).
2026-09-07 21:15:45 +02:00
const btcAdapter = require("./lib/chain-btc.js")({
bitcoinjs, bip32Factory: BIP32Factory, ecpairFactory: ECPairFactory, ecc,
sha256, electrum,
});
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): Bitcoin adapter (mainnet + testnet3, BIP84 native SegWit) Seven coins across twelve networks now — BTC joins the shipping roster. - lib/chain-btc.js: BIP84 native SegWit — m/84'/0'/0'/0/x → bc1q… (mainnet), m/84'/1'/0'/0/x → tb1q… (testnet3). Reuses the exact same stack the DGB adapter already pulls in: bitcoinjs-lib for network params + payments.p2wpkh + PSBT, bip32 for HD derivation, ecpair for the Signer interface, ecc (@bitcoinerlab/secp256k1) for message-sign recoverable sigs. No new npm deps. - Backend: same lib/electrum.js Aegis uses for BCH and DGB — plugged into a public Bitcoin ElectrumX pool (blockstream.info, lu.ke, grey.pw) for mainnet and aranguren.org / blockstream.info:993 for testnet3. Send flow: PSBT build + per-input signInput + finalizeAllInputs + broadcast. BIP-137 recoverable message signing. - Registered as btc:mainnet + btc:testnet in COINS with the orange Bitcoin disc SVG logo. Mount case mirrors DGB (accountPath honored, so switching to m/44'/0'/0' or m/49'/0'/0' via the setAccountPath message gives legacy 1… or wrapped-segwit 3… — same one-line UI plumb as the DGB address-family selector, deferred to a follow-up). - Panel: sat as the small-unit label, bitcoin: BIP21 QR payload, chain-aware send placeholder ("bc1q…" mainnet / "tb1q…" testnet). - Verified: BIP84 spec test vector — abandon×11 mnemonic derives bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu at m/84'/0'/0'/0/0 (byte-identical to the vector in the BIP text). Testnet variant produces tb1q6rz28mcfaxtmd6v789l9rrlrusdprr9pqcpvkl at m/84'/1'/0'/0/0 (cross-checkable on iancoleman.io/bip39 with coin BTC Testnet).
2026-09-07 21:15:45 +02:00
bchAdapter, tronAdapter, siaAdapter, dgbAdapter, ethAdapter, solAdapter, btcAdapter,
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, ecc };
}
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,
feat(theseus/aegis): Ethereum + Solana adapters, DGB address-family picker, Aegis-branded shield Multi-currency coverage matches what aegis.x has been advertising: BCH, TRX, SC, DGB, ETH, SOL — six coins, two-step coin/network picker for each. Panel logos, favicon and fallback all read as Aegis. - Ethereum (lib/chain-eth.js): mainnet + Sepolia. BIP44 m/44'/60'/0'/0/0 → secp256k1 → EIP-55 checksummed hex address (verified against MetaMask's canonical abandon×11 vector 0x9858EfFD23…4EcaEda94). JSON-RPC backend (Cloudflare mainnet, PublicNode Sepolia by default; per-wallet override). EIP-1559 send with an inline RLP encoder + secp256k1 recoverable sign; broadcast via eth_sendRawTransaction. personal_sign message signing follows the \x19Ethereum Signed Message:\n prefix. - Solana (lib/chain-sol.js): mainnet-beta + devnet. SLIP-0010 ed25519 derivation at m/44'/501'/0'/0' (all-hardened), base58 address (@noble ed25519). SLIP-0010 layer verified against spec Test Vector 1 in scratchpad/verify-slip10.mjs. Native SOL transfer via the system program with compact-u16 message serialization + ed25519 sign + sendTransaction. Devnet gets a faucet.solana.com link in Receive; the panel appends ?cluster=devnet when opening the explorer. - DGB address family selector (lib/chain-dgb.js already carried the paths): the Settings block now shows a Native SegWit / Taproot / Wrapped SegWit / Legacy P2PKH picker. Selecting a family auto-fills the derivation-path input with that family's default; Apply rebuilds the wallet against the new path. Address families exposed via chainMeta.addressFamilies so the panel can render them from data. - Panel branding: inline SVG shield (hexagonal aspis, same silhouette as the aegis.x hero) replaces the "?" fallback in logoSvg() and is what the header shows before a wallet is selected. Data-URI favicon wired into panel.html so the Theseus sidebar tab icon reads as Aegis rather than a chain-specific coin mark. - QR payloads now follow each chain's own URI scheme (BIP21 for BCH/DGB, EIP-681 for ETH, Solana Pay for SOL) so external scanners route the scan to the right wallet. Not shipped: EIP-1193 provider (window.ethereum) and wallet-adapter protocol (window.solana). The signing paths exist; only the page-inject bridge glue is missing. History for ETH/SOL is also empty in this rev — both need indexer plumbing (Etherscan V2 for ETH, getSignaturesForAddress + getTransaction pagination for SOL).
2026-09-07 20:31:27 +02:00
// BIP44/49/84/86 address families — the picker lives in the DGB
// settings block. Default is BIP84 (dgb1q…), which matches modern
feat(theseus/aegis): BTC address-family picker (BIP44/49/84/86 + Taproot) BTC now matches DGB's family selector: pick BIP44 (1…), BIP49 (3…), BIP84 (bc1q…, default) or BIP86 Taproot (bc1p…) from Settings, on mainnet or testnet3 (paths shift coin type 0 → 1 automatically). - lib/chain-btc.js: paymentFor(purpose, node, network) returns the right bitcoinjs-lib payment (p2pkh / p2sh(p2wpkh) / p2wpkh / p2tr) keyed off the derivation path's purpose. WalletKeys.entry captures the family, redeem script (BIP49) and internal x-only pubkey (BIP86) alongside the standard script/address fields. bitcoinjs.initEccLib(ecc) is called once at load so p2tr resolves. - Registry: BTC + DGB address families are purpose-only now; a helper (addressFamiliesFor / defaultAccountPathFor) computes the concrete m/PURPOSE'/COIN'/0' per (chain, network) — coin type {mainnet:0, testnet:1} for BTC, always 20 for DGB. chainMeta expands the list so the panel doesn't need per-chain knowledge. - Panel: #btcSettings block mirrors #dgbSettings (family select → path input auto-fill → Apply). The family-select listener + the fillFamilyPicker() helper are shared between DGB and BTC — the DOM prefix is the only per-chain input. - Send is wired for BIP84 (default) and BIP49 (adds redeemScript to the PSBT input). BIP44 (needs nonWitnessUtxo prev-tx fetch) and BIP86 (needs tap-tweaked signer) throw a clear "not yet in this rev — sweep to BIP84" error so users hit it at plan time, not at broadcast time. Receive works on all four families today. - Verified all four families derive the canonical BIP44/49/84/86 spec test vectors for the standard abandon×11 mnemonic — see scratchpad/verify-btc-families.mjs. Byte-identical to the BIPs.
2026-09-07 21:23:15 +02:00
// DGB Core, DigiByte-Go, and the SilentCode web-wallet. `coinType`
// per chain feeds the path builder below.
feat(theseus/aegis): Ethereum + Solana adapters, DGB address-family picker, Aegis-branded shield Multi-currency coverage matches what aegis.x has been advertising: BCH, TRX, SC, DGB, ETH, SOL — six coins, two-step coin/network picker for each. Panel logos, favicon and fallback all read as Aegis. - Ethereum (lib/chain-eth.js): mainnet + Sepolia. BIP44 m/44'/60'/0'/0/0 → secp256k1 → EIP-55 checksummed hex address (verified against MetaMask's canonical abandon×11 vector 0x9858EfFD23…4EcaEda94). JSON-RPC backend (Cloudflare mainnet, PublicNode Sepolia by default; per-wallet override). EIP-1559 send with an inline RLP encoder + secp256k1 recoverable sign; broadcast via eth_sendRawTransaction. personal_sign message signing follows the \x19Ethereum Signed Message:\n prefix. - Solana (lib/chain-sol.js): mainnet-beta + devnet. SLIP-0010 ed25519 derivation at m/44'/501'/0'/0' (all-hardened), base58 address (@noble ed25519). SLIP-0010 layer verified against spec Test Vector 1 in scratchpad/verify-slip10.mjs. Native SOL transfer via the system program with compact-u16 message serialization + ed25519 sign + sendTransaction. Devnet gets a faucet.solana.com link in Receive; the panel appends ?cluster=devnet when opening the explorer. - DGB address family selector (lib/chain-dgb.js already carried the paths): the Settings block now shows a Native SegWit / Taproot / Wrapped SegWit / Legacy P2PKH picker. Selecting a family auto-fills the derivation-path input with that family's default; Apply rebuilds the wallet against the new path. Address families exposed via chainMeta.addressFamilies so the panel can render them from data. - Panel branding: inline SVG shield (hexagonal aspis, same silhouette as the aegis.x hero) replaces the "?" fallback in logoSvg() and is what the header shows before a wallet is selected. Data-URI favicon wired into panel.html so the Theseus sidebar tab icon reads as Aegis rather than a chain-specific coin mark. - QR payloads now follow each chain's own URI scheme (BIP21 for BCH/DGB, EIP-681 for ETH, Solana Pay for SOL) so external scanners route the scan to the right wallet. Not shipped: EIP-1193 provider (window.ethereum) and wallet-adapter protocol (window.solana). The signing paths exist; only the page-inject bridge glue is missing. History for ETH/SOL is also empty in this rev — both need indexer plumbing (Etherscan V2 for ETH, getSignaturesForAddress + getTransaction pagination for SOL).
2026-09-07 20:31:27 +02:00
addressFamilies: [
feat(theseus/aegis): BTC address-family picker (BIP44/49/84/86 + Taproot) BTC now matches DGB's family selector: pick BIP44 (1…), BIP49 (3…), BIP84 (bc1q…, default) or BIP86 Taproot (bc1p…) from Settings, on mainnet or testnet3 (paths shift coin type 0 → 1 automatically). - lib/chain-btc.js: paymentFor(purpose, node, network) returns the right bitcoinjs-lib payment (p2pkh / p2sh(p2wpkh) / p2wpkh / p2tr) keyed off the derivation path's purpose. WalletKeys.entry captures the family, redeem script (BIP49) and internal x-only pubkey (BIP86) alongside the standard script/address fields. bitcoinjs.initEccLib(ecc) is called once at load so p2tr resolves. - Registry: BTC + DGB address families are purpose-only now; a helper (addressFamiliesFor / defaultAccountPathFor) computes the concrete m/PURPOSE'/COIN'/0' per (chain, network) — coin type {mainnet:0, testnet:1} for BTC, always 20 for DGB. chainMeta expands the list so the panel doesn't need per-chain knowledge. - Panel: #btcSettings block mirrors #dgbSettings (family select → path input auto-fill → Apply). The family-select listener + the fillFamilyPicker() helper are shared between DGB and BTC — the DOM prefix is the only per-chain input. - Send is wired for BIP84 (default) and BIP49 (adds redeemScript to the PSBT input). BIP44 (needs nonWitnessUtxo prev-tx fetch) and BIP86 (needs tap-tweaked signer) throw a clear "not yet in this rev — sweep to BIP84" error so users hit it at plan time, not at broadcast time. Receive works on all four families today. - Verified all four families derive the canonical BIP44/49/84/86 spec test vectors for the standard abandon×11 mnemonic — see scratchpad/verify-btc-families.mjs. Byte-identical to the BIPs.
2026-09-07 21:23:15 +02:00
{ id: "bip84", purpose: 84, label: "Native SegWit (dgb1q…)" },
{ id: "bip86", purpose: 86, label: "Taproot (dgb1p…)" },
{ id: "bip49", purpose: 49, label: "Wrapped SegWit (S…)" },
{ id: "bip44", purpose: 44, label: "Legacy P2PKH (D…)" },
feat(theseus/aegis): Ethereum + Solana adapters, DGB address-family picker, Aegis-branded shield Multi-currency coverage matches what aegis.x has been advertising: BCH, TRX, SC, DGB, ETH, SOL — six coins, two-step coin/network picker for each. Panel logos, favicon and fallback all read as Aegis. - Ethereum (lib/chain-eth.js): mainnet + Sepolia. BIP44 m/44'/60'/0'/0/0 → secp256k1 → EIP-55 checksummed hex address (verified against MetaMask's canonical abandon×11 vector 0x9858EfFD23…4EcaEda94). JSON-RPC backend (Cloudflare mainnet, PublicNode Sepolia by default; per-wallet override). EIP-1559 send with an inline RLP encoder + secp256k1 recoverable sign; broadcast via eth_sendRawTransaction. personal_sign message signing follows the \x19Ethereum Signed Message:\n prefix. - Solana (lib/chain-sol.js): mainnet-beta + devnet. SLIP-0010 ed25519 derivation at m/44'/501'/0'/0' (all-hardened), base58 address (@noble ed25519). SLIP-0010 layer verified against spec Test Vector 1 in scratchpad/verify-slip10.mjs. Native SOL transfer via the system program with compact-u16 message serialization + ed25519 sign + sendTransaction. Devnet gets a faucet.solana.com link in Receive; the panel appends ?cluster=devnet when opening the explorer. - DGB address family selector (lib/chain-dgb.js already carried the paths): the Settings block now shows a Native SegWit / Taproot / Wrapped SegWit / Legacy P2PKH picker. Selecting a family auto-fills the derivation-path input with that family's default; Apply rebuilds the wallet against the new path. Address families exposed via chainMeta.addressFamilies so the panel can render them from data. - Panel branding: inline SVG shield (hexagonal aspis, same silhouette as the aegis.x hero) replaces the "?" fallback in logoSvg() and is what the header shows before a wallet is selected. Data-URI favicon wired into panel.html so the Theseus sidebar tab icon reads as Aegis rather than a chain-specific coin mark. - QR payloads now follow each chain's own URI scheme (BIP21 for BCH/DGB, EIP-681 for ETH, Solana Pay for SOL) so external scanners route the scan to the right wallet. Not shipped: EIP-1193 provider (window.ethereum) and wallet-adapter protocol (window.solana). The signing paths exist; only the page-inject bridge glue is missing. History for ETH/SOL is also empty in this rev — both need indexer plumbing (Etherscan V2 for ETH, getSignaturesForAddress + getTransaction pagination for SOL).
2026-09-07 20:31:27 +02:00
],
feat(theseus/aegis): BTC address-family picker (BIP44/49/84/86 + Taproot) BTC now matches DGB's family selector: pick BIP44 (1…), BIP49 (3…), BIP84 (bc1q…, default) or BIP86 Taproot (bc1p…) from Settings, on mainnet or testnet3 (paths shift coin type 0 → 1 automatically). - lib/chain-btc.js: paymentFor(purpose, node, network) returns the right bitcoinjs-lib payment (p2pkh / p2sh(p2wpkh) / p2wpkh / p2tr) keyed off the derivation path's purpose. WalletKeys.entry captures the family, redeem script (BIP49) and internal x-only pubkey (BIP86) alongside the standard script/address fields. bitcoinjs.initEccLib(ecc) is called once at load so p2tr resolves. - Registry: BTC + DGB address families are purpose-only now; a helper (addressFamiliesFor / defaultAccountPathFor) computes the concrete m/PURPOSE'/COIN'/0' per (chain, network) — coin type {mainnet:0, testnet:1} for BTC, always 20 for DGB. chainMeta expands the list so the panel doesn't need per-chain knowledge. - Panel: #btcSettings block mirrors #dgbSettings (family select → path input auto-fill → Apply). The family-select listener + the fillFamilyPicker() helper are shared between DGB and BTC — the DOM prefix is the only per-chain input. - Send is wired for BIP84 (default) and BIP49 (adds redeemScript to the PSBT input). BIP44 (needs nonWitnessUtxo prev-tx fetch) and BIP86 (needs tap-tweaked signer) throw a clear "not yet in this rev — sweep to BIP84" error so users hit it at plan time, not at broadcast time. Receive works on all four families today. - Verified all four families derive the canonical BIP44/49/84/86 spec test vectors for the standard abandon×11 mnemonic — see scratchpad/verify-btc-families.mjs. Byte-identical to the BIPs.
2026-09-07 21:23:15 +02:00
coinType: 20,
defaultPurpose: 84,
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
networks: {
mainnet: {
id: "mainnet", label: "Mainnet", testnet: false,
purposePrefix: "bchwallet/dgb/mainnet/", startIndex: 0,
},
},
},
feat(theseus/aegis): Ethereum + Solana adapters, DGB address-family picker, Aegis-branded shield Multi-currency coverage matches what aegis.x has been advertising: BCH, TRX, SC, DGB, ETH, SOL — six coins, two-step coin/network picker for each. Panel logos, favicon and fallback all read as Aegis. - Ethereum (lib/chain-eth.js): mainnet + Sepolia. BIP44 m/44'/60'/0'/0/0 → secp256k1 → EIP-55 checksummed hex address (verified against MetaMask's canonical abandon×11 vector 0x9858EfFD23…4EcaEda94). JSON-RPC backend (Cloudflare mainnet, PublicNode Sepolia by default; per-wallet override). EIP-1559 send with an inline RLP encoder + secp256k1 recoverable sign; broadcast via eth_sendRawTransaction. personal_sign message signing follows the \x19Ethereum Signed Message:\n prefix. - Solana (lib/chain-sol.js): mainnet-beta + devnet. SLIP-0010 ed25519 derivation at m/44'/501'/0'/0' (all-hardened), base58 address (@noble ed25519). SLIP-0010 layer verified against spec Test Vector 1 in scratchpad/verify-slip10.mjs. Native SOL transfer via the system program with compact-u16 message serialization + ed25519 sign + sendTransaction. Devnet gets a faucet.solana.com link in Receive; the panel appends ?cluster=devnet when opening the explorer. - DGB address family selector (lib/chain-dgb.js already carried the paths): the Settings block now shows a Native SegWit / Taproot / Wrapped SegWit / Legacy P2PKH picker. Selecting a family auto-fills the derivation-path input with that family's default; Apply rebuilds the wallet against the new path. Address families exposed via chainMeta.addressFamilies so the panel can render them from data. - Panel branding: inline SVG shield (hexagonal aspis, same silhouette as the aegis.x hero) replaces the "?" fallback in logoSvg() and is what the header shows before a wallet is selected. Data-URI favicon wired into panel.html so the Theseus sidebar tab icon reads as Aegis rather than a chain-specific coin mark. - QR payloads now follow each chain's own URI scheme (BIP21 for BCH/DGB, EIP-681 for ETH, Solana Pay for SOL) so external scanners route the scan to the right wallet. Not shipped: EIP-1193 provider (window.ethereum) and wallet-adapter protocol (window.solana). The signing paths exist; only the page-inject bridge glue is missing. History for ETH/SOL is also empty in this rev — both need indexer plumbing (Etherscan V2 for ETH, getSignaturesForAddress + getTransaction pagination for SOL).
2026-09-07 20:31:27 +02:00
eth: {
chain: "eth",
label: "Ethereum",
short: "ETH",
ticker: "ETH",
decimals: 18,
color: "#627eea",
logo: "eth",
supportsMessageSign: true,
supportsPageInject: false, // EIP-1193 provider is a follow-up
networks: {
mainnet: {
id: "mainnet", label: "Mainnet", testnet: false,
purposePrefix: "bchwallet/eth/mainnet/", startIndex: 0,
},
sepolia: {
id: "sepolia", label: "Sepolia testnet", testnet: true,
purposePrefix: "bchwallet/eth/sepolia/", startIndex: 0,
},
},
},
sol: {
chain: "sol",
label: "Solana",
short: "SOL",
ticker: "SOL",
decimals: 9,
color: "#9945ff",
logo: "sol",
supportsMessageSign: true,
supportsPageInject: false,
networks: {
mainnet: {
id: "mainnet", label: "Mainnet-beta", testnet: false,
purposePrefix: "bchwallet/sol/mainnet/", startIndex: 0,
},
devnet: {
id: "devnet", label: "Devnet", testnet: true,
purposePrefix: "bchwallet/sol/devnet/", startIndex: 0,
},
},
},
feat(theseus/aegis): Bitcoin adapter (mainnet + testnet3, BIP84 native SegWit) Seven coins across twelve networks now — BTC joins the shipping roster. - lib/chain-btc.js: BIP84 native SegWit — m/84'/0'/0'/0/x → bc1q… (mainnet), m/84'/1'/0'/0/x → tb1q… (testnet3). Reuses the exact same stack the DGB adapter already pulls in: bitcoinjs-lib for network params + payments.p2wpkh + PSBT, bip32 for HD derivation, ecpair for the Signer interface, ecc (@bitcoinerlab/secp256k1) for message-sign recoverable sigs. No new npm deps. - Backend: same lib/electrum.js Aegis uses for BCH and DGB — plugged into a public Bitcoin ElectrumX pool (blockstream.info, lu.ke, grey.pw) for mainnet and aranguren.org / blockstream.info:993 for testnet3. Send flow: PSBT build + per-input signInput + finalizeAllInputs + broadcast. BIP-137 recoverable message signing. - Registered as btc:mainnet + btc:testnet in COINS with the orange Bitcoin disc SVG logo. Mount case mirrors DGB (accountPath honored, so switching to m/44'/0'/0' or m/49'/0'/0' via the setAccountPath message gives legacy 1… or wrapped-segwit 3… — same one-line UI plumb as the DGB address-family selector, deferred to a follow-up). - Panel: sat as the small-unit label, bitcoin: BIP21 QR payload, chain-aware send placeholder ("bc1q…" mainnet / "tb1q…" testnet). - Verified: BIP84 spec test vector — abandon×11 mnemonic derives bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu at m/84'/0'/0'/0/0 (byte-identical to the vector in the BIP text). Testnet variant produces tb1q6rz28mcfaxtmd6v789l9rrlrusdprr9pqcpvkl at m/84'/1'/0'/0/0 (cross-checkable on iancoleman.io/bip39 with coin BTC Testnet).
2026-09-07 21:15:45 +02:00
btc: {
chain: "btc",
label: "Bitcoin",
short: "BTC",
ticker: "BTC",
decimals: 8,
color: "#f7931a",
logo: "btc",
supportsMessageSign: true,
supportsPageInject: false,
feat(theseus/aegis): BTC address-family picker (BIP44/49/84/86 + Taproot) BTC now matches DGB's family selector: pick BIP44 (1…), BIP49 (3…), BIP84 (bc1q…, default) or BIP86 Taproot (bc1p…) from Settings, on mainnet or testnet3 (paths shift coin type 0 → 1 automatically). - lib/chain-btc.js: paymentFor(purpose, node, network) returns the right bitcoinjs-lib payment (p2pkh / p2sh(p2wpkh) / p2wpkh / p2tr) keyed off the derivation path's purpose. WalletKeys.entry captures the family, redeem script (BIP49) and internal x-only pubkey (BIP86) alongside the standard script/address fields. bitcoinjs.initEccLib(ecc) is called once at load so p2tr resolves. - Registry: BTC + DGB address families are purpose-only now; a helper (addressFamiliesFor / defaultAccountPathFor) computes the concrete m/PURPOSE'/COIN'/0' per (chain, network) — coin type {mainnet:0, testnet:1} for BTC, always 20 for DGB. chainMeta expands the list so the panel doesn't need per-chain knowledge. - Panel: #btcSettings block mirrors #dgbSettings (family select → path input auto-fill → Apply). The family-select listener + the fillFamilyPicker() helper are shared between DGB and BTC — the DOM prefix is the only per-chain input. - Send is wired for BIP84 (default) and BIP49 (adds redeemScript to the PSBT input). BIP44 (needs nonWitnessUtxo prev-tx fetch) and BIP86 (needs tap-tweaked signer) throw a clear "not yet in this rev — sweep to BIP84" error so users hit it at plan time, not at broadcast time. Receive works on all four families today. - Verified all four families derive the canonical BIP44/49/84/86 spec test vectors for the standard abandon×11 mnemonic — see scratchpad/verify-btc-families.mjs. Byte-identical to the BIPs.
2026-09-07 21:23:15 +02:00
// BIP44/49/84/86 across bc1q… / bc1p… / 3… / 1… on mainnet and
feat(theseus/aegis): EIP-1193 + Solana wallet-adapter bridges; BTC signet Aegis now integrates with the two dapp-wallet APIs the wider ecosystem actually uses — MetaMask-style window.ethereum for Ethereum, Phantom-style window.solana for Solana — plus BTC signet as a third Bitcoin network alongside mainnet + testnet3. - wallet-inject.js: adds a main-world bridge, installed via a one-shot <script textContent=…> appended to <head> and immediately removed. Electron's contextBridge shallow-copies args and strips methods, which means BCH- and Tron-shaped params (plain data) work in the isolated world but Solana's wallet-adapter dapps — which pass @solana/web3.js Transaction objects and expect .serializeMessage()/.addSignature() to fire on them — need code that lives in the same world as the dapp. Bridge talks back to the isolated world via window.postMessage on a namespaced envelope (aegisTag = "aegis-" + addonId), which forwards to theseus.invoke. Same pattern MetaMask + Phantom use. - window.ethereum (EIP-1193): request({method, params}), on(), removeListener(), chainId, networkVersion, selectedAddress. Handles eth_requestAccounts, eth_accounts, eth_chainId, net_version, personal_sign, eth_sign, eth_sendTransaction, wallet_switchEthereumChain (rejects with "use the Aegis picker"), wallet_addEthereumChain (rejects, chains come from Settings), wallet_get/requestPermissions. Every other eth_*/net_*/web3_* method passes through to the wallet's configured RPC via a new eth.rpc handler. EIP-6963 announceProvider event fires so wagmi / RainbowKit / any 6963-aware dapp discovers Aegis alongside MetaMask instead of racing for window.ethereum. - window.solana (wallet-adapter shape): connect(), disconnect(), publicKey (with toString/toBase58/toBytes/equals — the PublicKey interface dapps check), signMessage(u8) → {publicKey, signature: u8}, signTransaction(tx) → mutates + returns the same tx with the signature added, signAndSendTransaction(tx) → returns {signature: txid}, signAllTransactions([tx]), request({method, params}). isPhantom flag set true so dapps that gate on it pick us. on/off events for connect / disconnect / accountChanged. - Handlers in index.js registerPageMessages: eth.requestAccounts, eth.personalSign, eth.sendTransaction, eth.switchChain, eth.rpc, sol.connect, sol.signMessage, sol.signAndSend. Every write path is per-origin gated + goes through api.approvalModal with the wallet label + network in the row list so the user always knows which Aegis wallet is about to sign. - Signet added to chain-btc.js — signet shares testnet3's address format and SLIP-44 coin type (BIP-325 only changed consensus/signing), so bitcoinjs-lib.networks.testnet handles derivation unchanged. Only the electrum pool (aranguren + wakiyamap) + explorer (mempool.space /signet) + faucet (signetfaucet.com) differ. Registered as btc:signet in COINS with per-network coinType lookup. Known limits (follow-ups in the same shape as existing chains): - SOL signAndSendTransaction is single-signer only; dapps that combine the wallet's sig with co-signer sigs need the wire assembled on the dapp side. - ETH eth_signTypedData_v4 (EIP-712) is not wired — the handler set covers personal_sign only.
2026-09-07 22:08:56 +02:00
// tb1q… / tb1p… / 2… / m/n… on testnet3 + signet. Coin type shifts
// per network (0 for mainnet, 1 for both testnet3 and signet — SLIP-44
// treats every Bitcoin testnet as coin type 1).
feat(theseus/aegis): BTC address-family picker (BIP44/49/84/86 + Taproot) BTC now matches DGB's family selector: pick BIP44 (1…), BIP49 (3…), BIP84 (bc1q…, default) or BIP86 Taproot (bc1p…) from Settings, on mainnet or testnet3 (paths shift coin type 0 → 1 automatically). - lib/chain-btc.js: paymentFor(purpose, node, network) returns the right bitcoinjs-lib payment (p2pkh / p2sh(p2wpkh) / p2wpkh / p2tr) keyed off the derivation path's purpose. WalletKeys.entry captures the family, redeem script (BIP49) and internal x-only pubkey (BIP86) alongside the standard script/address fields. bitcoinjs.initEccLib(ecc) is called once at load so p2tr resolves. - Registry: BTC + DGB address families are purpose-only now; a helper (addressFamiliesFor / defaultAccountPathFor) computes the concrete m/PURPOSE'/COIN'/0' per (chain, network) — coin type {mainnet:0, testnet:1} for BTC, always 20 for DGB. chainMeta expands the list so the panel doesn't need per-chain knowledge. - Panel: #btcSettings block mirrors #dgbSettings (family select → path input auto-fill → Apply). The family-select listener + the fillFamilyPicker() helper are shared between DGB and BTC — the DOM prefix is the only per-chain input. - Send is wired for BIP84 (default) and BIP49 (adds redeemScript to the PSBT input). BIP44 (needs nonWitnessUtxo prev-tx fetch) and BIP86 (needs tap-tweaked signer) throw a clear "not yet in this rev — sweep to BIP84" error so users hit it at plan time, not at broadcast time. Receive works on all four families today. - Verified all four families derive the canonical BIP44/49/84/86 spec test vectors for the standard abandon×11 mnemonic — see scratchpad/verify-btc-families.mjs. Byte-identical to the BIPs.
2026-09-07 21:23:15 +02:00
addressFamilies: [
{ id: "bip84", purpose: 84, label: "Native SegWit (bc1q… / tb1q…)" },
{ id: "bip86", purpose: 86, label: "Taproot (bc1p… / tb1p…)" },
{ id: "bip49", purpose: 49, label: "Wrapped SegWit (3… / 2…)" },
{ id: "bip44", purpose: 44, label: "Legacy P2PKH (1… / m…, n…)" },
],
feat(theseus/aegis): EIP-1193 + Solana wallet-adapter bridges; BTC signet Aegis now integrates with the two dapp-wallet APIs the wider ecosystem actually uses — MetaMask-style window.ethereum for Ethereum, Phantom-style window.solana for Solana — plus BTC signet as a third Bitcoin network alongside mainnet + testnet3. - wallet-inject.js: adds a main-world bridge, installed via a one-shot <script textContent=…> appended to <head> and immediately removed. Electron's contextBridge shallow-copies args and strips methods, which means BCH- and Tron-shaped params (plain data) work in the isolated world but Solana's wallet-adapter dapps — which pass @solana/web3.js Transaction objects and expect .serializeMessage()/.addSignature() to fire on them — need code that lives in the same world as the dapp. Bridge talks back to the isolated world via window.postMessage on a namespaced envelope (aegisTag = "aegis-" + addonId), which forwards to theseus.invoke. Same pattern MetaMask + Phantom use. - window.ethereum (EIP-1193): request({method, params}), on(), removeListener(), chainId, networkVersion, selectedAddress. Handles eth_requestAccounts, eth_accounts, eth_chainId, net_version, personal_sign, eth_sign, eth_sendTransaction, wallet_switchEthereumChain (rejects with "use the Aegis picker"), wallet_addEthereumChain (rejects, chains come from Settings), wallet_get/requestPermissions. Every other eth_*/net_*/web3_* method passes through to the wallet's configured RPC via a new eth.rpc handler. EIP-6963 announceProvider event fires so wagmi / RainbowKit / any 6963-aware dapp discovers Aegis alongside MetaMask instead of racing for window.ethereum. - window.solana (wallet-adapter shape): connect(), disconnect(), publicKey (with toString/toBase58/toBytes/equals — the PublicKey interface dapps check), signMessage(u8) → {publicKey, signature: u8}, signTransaction(tx) → mutates + returns the same tx with the signature added, signAndSendTransaction(tx) → returns {signature: txid}, signAllTransactions([tx]), request({method, params}). isPhantom flag set true so dapps that gate on it pick us. on/off events for connect / disconnect / accountChanged. - Handlers in index.js registerPageMessages: eth.requestAccounts, eth.personalSign, eth.sendTransaction, eth.switchChain, eth.rpc, sol.connect, sol.signMessage, sol.signAndSend. Every write path is per-origin gated + goes through api.approvalModal with the wallet label + network in the row list so the user always knows which Aegis wallet is about to sign. - Signet added to chain-btc.js — signet shares testnet3's address format and SLIP-44 coin type (BIP-325 only changed consensus/signing), so bitcoinjs-lib.networks.testnet handles derivation unchanged. Only the electrum pool (aranguren + wakiyamap) + explorer (mempool.space /signet) + faucet (signetfaucet.com) differ. Registered as btc:signet in COINS with per-network coinType lookup. Known limits (follow-ups in the same shape as existing chains): - SOL signAndSendTransaction is single-signer only; dapps that combine the wallet's sig with co-signer sigs need the wire assembled on the dapp side. - ETH eth_signTypedData_v4 (EIP-712) is not wired — the handler set covers personal_sign only.
2026-09-07 22:08:56 +02:00
coinType: { mainnet: 0, testnet: 1, signet: 1 },
feat(theseus/aegis): BTC address-family picker (BIP44/49/84/86 + Taproot) BTC now matches DGB's family selector: pick BIP44 (1…), BIP49 (3…), BIP84 (bc1q…, default) or BIP86 Taproot (bc1p…) from Settings, on mainnet or testnet3 (paths shift coin type 0 → 1 automatically). - lib/chain-btc.js: paymentFor(purpose, node, network) returns the right bitcoinjs-lib payment (p2pkh / p2sh(p2wpkh) / p2wpkh / p2tr) keyed off the derivation path's purpose. WalletKeys.entry captures the family, redeem script (BIP49) and internal x-only pubkey (BIP86) alongside the standard script/address fields. bitcoinjs.initEccLib(ecc) is called once at load so p2tr resolves. - Registry: BTC + DGB address families are purpose-only now; a helper (addressFamiliesFor / defaultAccountPathFor) computes the concrete m/PURPOSE'/COIN'/0' per (chain, network) — coin type {mainnet:0, testnet:1} for BTC, always 20 for DGB. chainMeta expands the list so the panel doesn't need per-chain knowledge. - Panel: #btcSettings block mirrors #dgbSettings (family select → path input auto-fill → Apply). The family-select listener + the fillFamilyPicker() helper are shared between DGB and BTC — the DOM prefix is the only per-chain input. - Send is wired for BIP84 (default) and BIP49 (adds redeemScript to the PSBT input). BIP44 (needs nonWitnessUtxo prev-tx fetch) and BIP86 (needs tap-tweaked signer) throw a clear "not yet in this rev — sweep to BIP84" error so users hit it at plan time, not at broadcast time. Receive works on all four families today. - Verified all four families derive the canonical BIP44/49/84/86 spec test vectors for the standard abandon×11 mnemonic — see scratchpad/verify-btc-families.mjs. Byte-identical to the BIPs.
2026-09-07 21:23:15 +02:00
defaultPurpose: 84,
feat(theseus/aegis): Bitcoin adapter (mainnet + testnet3, BIP84 native SegWit) Seven coins across twelve networks now — BTC joins the shipping roster. - lib/chain-btc.js: BIP84 native SegWit — m/84'/0'/0'/0/x → bc1q… (mainnet), m/84'/1'/0'/0/x → tb1q… (testnet3). Reuses the exact same stack the DGB adapter already pulls in: bitcoinjs-lib for network params + payments.p2wpkh + PSBT, bip32 for HD derivation, ecpair for the Signer interface, ecc (@bitcoinerlab/secp256k1) for message-sign recoverable sigs. No new npm deps. - Backend: same lib/electrum.js Aegis uses for BCH and DGB — plugged into a public Bitcoin ElectrumX pool (blockstream.info, lu.ke, grey.pw) for mainnet and aranguren.org / blockstream.info:993 for testnet3. Send flow: PSBT build + per-input signInput + finalizeAllInputs + broadcast. BIP-137 recoverable message signing. - Registered as btc:mainnet + btc:testnet in COINS with the orange Bitcoin disc SVG logo. Mount case mirrors DGB (accountPath honored, so switching to m/44'/0'/0' or m/49'/0'/0' via the setAccountPath message gives legacy 1… or wrapped-segwit 3… — same one-line UI plumb as the DGB address-family selector, deferred to a follow-up). - Panel: sat as the small-unit label, bitcoin: BIP21 QR payload, chain-aware send placeholder ("bc1q…" mainnet / "tb1q…" testnet). - Verified: BIP84 spec test vector — abandon×11 mnemonic derives bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu at m/84'/0'/0'/0/0 (byte-identical to the vector in the BIP text). Testnet variant produces tb1q6rz28mcfaxtmd6v789l9rrlrusdprr9pqcpvkl at m/84'/1'/0'/0/0 (cross-checkable on iancoleman.io/bip39 with coin BTC Testnet).
2026-09-07 21:15:45 +02:00
networks: {
mainnet: {
id: "mainnet", label: "Mainnet", testnet: false,
purposePrefix: "bchwallet/btc/mainnet/", startIndex: 0,
},
testnet: {
id: "testnet", label: "Testnet3", testnet: true,
purposePrefix: "bchwallet/btc/testnet/", startIndex: 0,
},
feat(theseus/aegis): EIP-1193 + Solana wallet-adapter bridges; BTC signet Aegis now integrates with the two dapp-wallet APIs the wider ecosystem actually uses — MetaMask-style window.ethereum for Ethereum, Phantom-style window.solana for Solana — plus BTC signet as a third Bitcoin network alongside mainnet + testnet3. - wallet-inject.js: adds a main-world bridge, installed via a one-shot <script textContent=…> appended to <head> and immediately removed. Electron's contextBridge shallow-copies args and strips methods, which means BCH- and Tron-shaped params (plain data) work in the isolated world but Solana's wallet-adapter dapps — which pass @solana/web3.js Transaction objects and expect .serializeMessage()/.addSignature() to fire on them — need code that lives in the same world as the dapp. Bridge talks back to the isolated world via window.postMessage on a namespaced envelope (aegisTag = "aegis-" + addonId), which forwards to theseus.invoke. Same pattern MetaMask + Phantom use. - window.ethereum (EIP-1193): request({method, params}), on(), removeListener(), chainId, networkVersion, selectedAddress. Handles eth_requestAccounts, eth_accounts, eth_chainId, net_version, personal_sign, eth_sign, eth_sendTransaction, wallet_switchEthereumChain (rejects with "use the Aegis picker"), wallet_addEthereumChain (rejects, chains come from Settings), wallet_get/requestPermissions. Every other eth_*/net_*/web3_* method passes through to the wallet's configured RPC via a new eth.rpc handler. EIP-6963 announceProvider event fires so wagmi / RainbowKit / any 6963-aware dapp discovers Aegis alongside MetaMask instead of racing for window.ethereum. - window.solana (wallet-adapter shape): connect(), disconnect(), publicKey (with toString/toBase58/toBytes/equals — the PublicKey interface dapps check), signMessage(u8) → {publicKey, signature: u8}, signTransaction(tx) → mutates + returns the same tx with the signature added, signAndSendTransaction(tx) → returns {signature: txid}, signAllTransactions([tx]), request({method, params}). isPhantom flag set true so dapps that gate on it pick us. on/off events for connect / disconnect / accountChanged. - Handlers in index.js registerPageMessages: eth.requestAccounts, eth.personalSign, eth.sendTransaction, eth.switchChain, eth.rpc, sol.connect, sol.signMessage, sol.signAndSend. Every write path is per-origin gated + goes through api.approvalModal with the wallet label + network in the row list so the user always knows which Aegis wallet is about to sign. - Signet added to chain-btc.js — signet shares testnet3's address format and SLIP-44 coin type (BIP-325 only changed consensus/signing), so bitcoinjs-lib.networks.testnet handles derivation unchanged. Only the electrum pool (aranguren + wakiyamap) + explorer (mempool.space /signet) + faucet (signetfaucet.com) differ. Registered as btc:signet in COINS with per-network coinType lookup. Known limits (follow-ups in the same shape as existing chains): - SOL signAndSendTransaction is single-signer only; dapps that combine the wallet's sig with co-signer sigs need the wire assembled on the dapp side. - ETH eth_signTypedData_v4 (EIP-712) is not wired — the handler set covers personal_sign only.
2026-09-07 22:08:56 +02:00
signet: {
id: "signet", label: "Signet", testnet: true,
purposePrefix: "bchwallet/btc/signet/", startIndex: 0,
},
feat(theseus/aegis): Bitcoin adapter (mainnet + testnet3, BIP84 native SegWit) Seven coins across twelve networks now — BTC joins the shipping roster. - lib/chain-btc.js: BIP84 native SegWit — m/84'/0'/0'/0/x → bc1q… (mainnet), m/84'/1'/0'/0/x → tb1q… (testnet3). Reuses the exact same stack the DGB adapter already pulls in: bitcoinjs-lib for network params + payments.p2wpkh + PSBT, bip32 for HD derivation, ecpair for the Signer interface, ecc (@bitcoinerlab/secp256k1) for message-sign recoverable sigs. No new npm deps. - Backend: same lib/electrum.js Aegis uses for BCH and DGB — plugged into a public Bitcoin ElectrumX pool (blockstream.info, lu.ke, grey.pw) for mainnet and aranguren.org / blockstream.info:993 for testnet3. Send flow: PSBT build + per-input signInput + finalizeAllInputs + broadcast. BIP-137 recoverable message signing. - Registered as btc:mainnet + btc:testnet in COINS with the orange Bitcoin disc SVG logo. Mount case mirrors DGB (accountPath honored, so switching to m/44'/0'/0' or m/49'/0'/0' via the setAccountPath message gives legacy 1… or wrapped-segwit 3… — same one-line UI plumb as the DGB address-family selector, deferred to a follow-up). - Panel: sat as the small-unit label, bitcoin: BIP21 QR payload, chain-aware send placeholder ("bc1q…" mainnet / "tb1q…" testnet). - Verified: BIP84 spec test vector — abandon×11 mnemonic derives bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu at m/84'/0'/0'/0/0 (byte-identical to the vector in the BIP text). Testnet variant produces tb1q6rz28mcfaxtmd6v789l9rrlrusdprr9pqcpvkl at m/84'/1'/0'/0/0 (cross-checkable on iancoleman.io/bip39 with coin BTC Testnet).
2026-09-07 21:15:45 +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 chainKey(chain, network) { return `${chain}:${network}`; }
feat(theseus/aegis): BTC address-family picker (BIP44/49/84/86 + Taproot) BTC now matches DGB's family selector: pick BIP44 (1…), BIP49 (3…), BIP84 (bc1q…, default) or BIP86 Taproot (bc1p…) from Settings, on mainnet or testnet3 (paths shift coin type 0 → 1 automatically). - lib/chain-btc.js: paymentFor(purpose, node, network) returns the right bitcoinjs-lib payment (p2pkh / p2sh(p2wpkh) / p2wpkh / p2tr) keyed off the derivation path's purpose. WalletKeys.entry captures the family, redeem script (BIP49) and internal x-only pubkey (BIP86) alongside the standard script/address fields. bitcoinjs.initEccLib(ecc) is called once at load so p2tr resolves. - Registry: BTC + DGB address families are purpose-only now; a helper (addressFamiliesFor / defaultAccountPathFor) computes the concrete m/PURPOSE'/COIN'/0' per (chain, network) — coin type {mainnet:0, testnet:1} for BTC, always 20 for DGB. chainMeta expands the list so the panel doesn't need per-chain knowledge. - Panel: #btcSettings block mirrors #dgbSettings (family select → path input auto-fill → Apply). The family-select listener + the fillFamilyPicker() helper are shared between DGB and BTC — the DOM prefix is the only per-chain input. - Send is wired for BIP84 (default) and BIP49 (adds redeemScript to the PSBT input). BIP44 (needs nonWitnessUtxo prev-tx fetch) and BIP86 (needs tap-tweaked signer) throw a clear "not yet in this rev — sweep to BIP84" error so users hit it at plan time, not at broadcast time. Receive works on all four families today. - Verified all four families derive the canonical BIP44/49/84/86 spec test vectors for the standard abandon×11 mnemonic — see scratchpad/verify-btc-families.mjs. Byte-identical to the BIPs.
2026-09-07 21:23:15 +02:00
// Coin type per (chain, network). A number literal on the COINS entry
// (DGB uses a single 20) or a per-network object ({mainnet: 0, testnet: 1}
// for BTC). Returns null when the chain doesn't declare a family picker.
function coinTypeFor(c, network) {
if (!c || c.coinType == null) return null;
return typeof c.coinType === "number" ? c.coinType : (c.coinType[network] ?? null);
}
// Full derivation paths per family for a given (chain, network) — expands
// the family list on the fly so each picker knows exactly which path a
// pick would produce.
function addressFamiliesFor(c, network) {
if (!c || !c.addressFamilies) return null;
const ct = coinTypeFor(c, network);
if (ct == null) return c.addressFamilies;
return c.addressFamilies.map((f) => ({
...f,
defaultAccountPath: `m/${f.purpose}'/${ct}'/0'`,
}));
}
function defaultAccountPathFor(c, network) {
const ct = coinTypeFor(c, network);
if (ct == null || c.defaultPurpose == null) return null;
return `m/${c.defaultPurpose}'/${ct}'/0'`;
}
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,
feat(theseus/aegis): BTC address-family picker (BIP44/49/84/86 + Taproot) BTC now matches DGB's family selector: pick BIP44 (1…), BIP49 (3…), BIP84 (bc1q…, default) or BIP86 Taproot (bc1p…) from Settings, on mainnet or testnet3 (paths shift coin type 0 → 1 automatically). - lib/chain-btc.js: paymentFor(purpose, node, network) returns the right bitcoinjs-lib payment (p2pkh / p2sh(p2wpkh) / p2wpkh / p2tr) keyed off the derivation path's purpose. WalletKeys.entry captures the family, redeem script (BIP49) and internal x-only pubkey (BIP86) alongside the standard script/address fields. bitcoinjs.initEccLib(ecc) is called once at load so p2tr resolves. - Registry: BTC + DGB address families are purpose-only now; a helper (addressFamiliesFor / defaultAccountPathFor) computes the concrete m/PURPOSE'/COIN'/0' per (chain, network) — coin type {mainnet:0, testnet:1} for BTC, always 20 for DGB. chainMeta expands the list so the panel doesn't need per-chain knowledge. - Panel: #btcSettings block mirrors #dgbSettings (family select → path input auto-fill → Apply). The family-select listener + the fillFamilyPicker() helper are shared between DGB and BTC — the DOM prefix is the only per-chain input. - Send is wired for BIP84 (default) and BIP49 (adds redeemScript to the PSBT input). BIP44 (needs nonWitnessUtxo prev-tx fetch) and BIP86 (needs tap-tweaked signer) throw a clear "not yet in this rev — sweep to BIP84" error so users hit it at plan time, not at broadcast time. Receive works on all four families today. - Verified all four families derive the canonical BIP44/49/84/86 spec test vectors for the standard abandon×11 mnemonic — see scratchpad/verify-btc-families.mjs. Byte-identical to the BIPs.
2026-09-07 21:23:15 +02:00
addressFamilies: addressFamiliesFor(c, network),
defaultAccountPath: defaultAccountPathFor(c, 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 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/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() {
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/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) {
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;
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);
} 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();
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): Ethereum + Solana adapters, DGB address-family picker, Aegis-branded shield Multi-currency coverage matches what aegis.x has been advertising: BCH, TRX, SC, DGB, ETH, SOL — six coins, two-step coin/network picker for each. Panel logos, favicon and fallback all read as Aegis. - Ethereum (lib/chain-eth.js): mainnet + Sepolia. BIP44 m/44'/60'/0'/0/0 → secp256k1 → EIP-55 checksummed hex address (verified against MetaMask's canonical abandon×11 vector 0x9858EfFD23…4EcaEda94). JSON-RPC backend (Cloudflare mainnet, PublicNode Sepolia by default; per-wallet override). EIP-1559 send with an inline RLP encoder + secp256k1 recoverable sign; broadcast via eth_sendRawTransaction. personal_sign message signing follows the \x19Ethereum Signed Message:\n prefix. - Solana (lib/chain-sol.js): mainnet-beta + devnet. SLIP-0010 ed25519 derivation at m/44'/501'/0'/0' (all-hardened), base58 address (@noble ed25519). SLIP-0010 layer verified against spec Test Vector 1 in scratchpad/verify-slip10.mjs. Native SOL transfer via the system program with compact-u16 message serialization + ed25519 sign + sendTransaction. Devnet gets a faucet.solana.com link in Receive; the panel appends ?cluster=devnet when opening the explorer. - DGB address family selector (lib/chain-dgb.js already carried the paths): the Settings block now shows a Native SegWit / Taproot / Wrapped SegWit / Legacy P2PKH picker. Selecting a family auto-fills the derivation-path input with that family's default; Apply rebuilds the wallet against the new path. Address families exposed via chainMeta.addressFamilies so the panel can render them from data. - Panel branding: inline SVG shield (hexagonal aspis, same silhouette as the aegis.x hero) replaces the "?" fallback in logoSvg() and is what the header shows before a wallet is selected. Data-URI favicon wired into panel.html so the Theseus sidebar tab icon reads as Aegis rather than a chain-specific coin mark. - QR payloads now follow each chain's own URI scheme (BIP21 for BCH/DGB, EIP-681 for ETH, Solana Pay for SOL) so external scanners route the scan to the right wallet. Not shipped: EIP-1193 provider (window.ethereum) and wallet-adapter protocol (window.solana). The signing paths exist; only the page-inject bridge glue is missing. History for ETH/SOL is also empty in this rev — both need indexer plumbing (Etherscan V2 for ETH, getSignaturesForAddress + getTransaction pagination for SOL).
2026-09-07 20:31:27 +02:00
} else if (entry.chain === "eth") {
const rpcUrl = String(c.api.storage.get(`wallets/${entry.id}/rpcUrl`, "") || "");
adapter = new c.d.ethAdapter.EthWallet(root, entry.network, {
walletId: entry.id,
storage: c.api.storage,
log: (...a) => c.api.log(`[${entry.id}]`, ...a),
onChange: () => emitStateForWallet(entry.id),
rpcUrl,
});
adapter.schedulePoll(20_000);
} else if (entry.chain === "sol") {
const rpcUrl = String(c.api.storage.get(`wallets/${entry.id}/rpcUrl`, "") || "");
adapter = new c.d.solAdapter.SolWallet(root, entry.network, {
walletId: entry.id,
storage: c.api.storage,
log: (...a) => c.api.log(`[${entry.id}]`, ...a),
onChange: () => emitStateForWallet(entry.id),
rpcUrl,
});
adapter.schedulePoll(20_000);
feat(theseus/aegis): Bitcoin adapter (mainnet + testnet3, BIP84 native SegWit) Seven coins across twelve networks now — BTC joins the shipping roster. - lib/chain-btc.js: BIP84 native SegWit — m/84'/0'/0'/0/x → bc1q… (mainnet), m/84'/1'/0'/0/x → tb1q… (testnet3). Reuses the exact same stack the DGB adapter already pulls in: bitcoinjs-lib for network params + payments.p2wpkh + PSBT, bip32 for HD derivation, ecpair for the Signer interface, ecc (@bitcoinerlab/secp256k1) for message-sign recoverable sigs. No new npm deps. - Backend: same lib/electrum.js Aegis uses for BCH and DGB — plugged into a public Bitcoin ElectrumX pool (blockstream.info, lu.ke, grey.pw) for mainnet and aranguren.org / blockstream.info:993 for testnet3. Send flow: PSBT build + per-input signInput + finalizeAllInputs + broadcast. BIP-137 recoverable message signing. - Registered as btc:mainnet + btc:testnet in COINS with the orange Bitcoin disc SVG logo. Mount case mirrors DGB (accountPath honored, so switching to m/44'/0'/0' or m/49'/0'/0' via the setAccountPath message gives legacy 1… or wrapped-segwit 3… — same one-line UI plumb as the DGB address-family selector, deferred to a follow-up). - Panel: sat as the small-unit label, bitcoin: BIP21 QR payload, chain-aware send placeholder ("bc1q…" mainnet / "tb1q…" testnet). - Verified: BIP84 spec test vector — abandon×11 mnemonic derives bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu at m/84'/0'/0'/0/0 (byte-identical to the vector in the BIP text). Testnet variant produces tb1q6rz28mcfaxtmd6v789l9rrlrusdprr9pqcpvkl at m/84'/1'/0'/0/0 (cross-checkable on iancoleman.io/bip39 with coin BTC Testnet).
2026-09-07 21:15:45 +02:00
} else if (entry.chain === "btc") {
adapter = new c.d.btcAdapter.BtcWallet(root, entry.network, {
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/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/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/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,
feat(theseus/aegis): Ethereum + Solana adapters, DGB address-family picker, Aegis-branded shield Multi-currency coverage matches what aegis.x has been advertising: BCH, TRX, SC, DGB, ETH, SOL — six coins, two-step coin/network picker for each. Panel logos, favicon and fallback all read as Aegis. - Ethereum (lib/chain-eth.js): mainnet + Sepolia. BIP44 m/44'/60'/0'/0/0 → secp256k1 → EIP-55 checksummed hex address (verified against MetaMask's canonical abandon×11 vector 0x9858EfFD23…4EcaEda94). JSON-RPC backend (Cloudflare mainnet, PublicNode Sepolia by default; per-wallet override). EIP-1559 send with an inline RLP encoder + secp256k1 recoverable sign; broadcast via eth_sendRawTransaction. personal_sign message signing follows the \x19Ethereum Signed Message:\n prefix. - Solana (lib/chain-sol.js): mainnet-beta + devnet. SLIP-0010 ed25519 derivation at m/44'/501'/0'/0' (all-hardened), base58 address (@noble ed25519). SLIP-0010 layer verified against spec Test Vector 1 in scratchpad/verify-slip10.mjs. Native SOL transfer via the system program with compact-u16 message serialization + ed25519 sign + sendTransaction. Devnet gets a faucet.solana.com link in Receive; the panel appends ?cluster=devnet when opening the explorer. - DGB address family selector (lib/chain-dgb.js already carried the paths): the Settings block now shows a Native SegWit / Taproot / Wrapped SegWit / Legacy P2PKH picker. Selecting a family auto-fills the derivation-path input with that family's default; Apply rebuilds the wallet against the new path. Address families exposed via chainMeta.addressFamilies so the panel can render them from data. - Panel branding: inline SVG shield (hexagonal aspis, same silhouette as the aegis.x hero) replaces the "?" fallback in logoSvg() and is what the header shows before a wallet is selected. Data-URI favicon wired into panel.html so the Theseus sidebar tab icon reads as Aegis rather than a chain-specific coin mark. - QR payloads now follow each chain's own URI scheme (BIP21 for BCH/DGB, EIP-681 for ETH, Solana Pay for SOL) so external scanners route the scan to the right wallet. Not shipped: EIP-1193 provider (window.ethereum) and wallet-adapter protocol (window.solana). The signing paths exist; only the page-inject bridge glue is missing. History for ETH/SOL is also empty in this rev — both need indexer plumbing (Etherscan V2 for ETH, getSignaturesForAddress + getTransaction pagination for SOL).
2026-09-07 20:31:27 +02:00
addressFamilies: meta.addressFamilies, defaultAccountPath: meta.defaultAccountPath,
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
} : 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");
}
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();
});
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) => {
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/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): Bitcoin adapter (mainnet + testnet3, BIP84 native SegWit) Seven coins across twelve networks now — BTC joins the shipping roster. - lib/chain-btc.js: BIP84 native SegWit — m/84'/0'/0'/0/x → bc1q… (mainnet), m/84'/1'/0'/0/x → tb1q… (testnet3). Reuses the exact same stack the DGB adapter already pulls in: bitcoinjs-lib for network params + payments.p2wpkh + PSBT, bip32 for HD derivation, ecpair for the Signer interface, ecc (@bitcoinerlab/secp256k1) for message-sign recoverable sigs. No new npm deps. - Backend: same lib/electrum.js Aegis uses for BCH and DGB — plugged into a public Bitcoin ElectrumX pool (blockstream.info, lu.ke, grey.pw) for mainnet and aranguren.org / blockstream.info:993 for testnet3. Send flow: PSBT build + per-input signInput + finalizeAllInputs + broadcast. BIP-137 recoverable message signing. - Registered as btc:mainnet + btc:testnet in COINS with the orange Bitcoin disc SVG logo. Mount case mirrors DGB (accountPath honored, so switching to m/44'/0'/0' or m/49'/0'/0' via the setAccountPath message gives legacy 1… or wrapped-segwit 3… — same one-line UI plumb as the DGB address-family selector, deferred to a follow-up). - Panel: sat as the small-unit label, bitcoin: BIP21 QR payload, chain-aware send placeholder ("bc1q…" mainnet / "tb1q…" testnet). - Verified: BIP84 spec test vector — abandon×11 mnemonic derives bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu at m/84'/0'/0'/0/0 (byte-identical to the vector in the BIP text). Testnet variant produces tb1q6rz28mcfaxtmd6v789l9rrlrusdprr9pqcpvkl at m/84'/1'/0'/0/0 (cross-checkable on iancoleman.io/bip39 with coin BTC Testnet).
2026-09-07 21:15:45 +02:00
if (!["bch", "dgb", "btc"].includes(entry.chain)) throw new Error("account path is a BCH/BTC/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): Bitcoin adapter (mainnet + testnet3, BIP84 native SegWit) Seven coins across twelve networks now — BTC joins the shipping roster. - lib/chain-btc.js: BIP84 native SegWit — m/84'/0'/0'/0/x → bc1q… (mainnet), m/84'/1'/0'/0/x → tb1q… (testnet3). Reuses the exact same stack the DGB adapter already pulls in: bitcoinjs-lib for network params + payments.p2wpkh + PSBT, bip32 for HD derivation, ecpair for the Signer interface, ecc (@bitcoinerlab/secp256k1) for message-sign recoverable sigs. No new npm deps. - Backend: same lib/electrum.js Aegis uses for BCH and DGB — plugged into a public Bitcoin ElectrumX pool (blockstream.info, lu.ke, grey.pw) for mainnet and aranguren.org / blockstream.info:993 for testnet3. Send flow: PSBT build + per-input signInput + finalizeAllInputs + broadcast. BIP-137 recoverable message signing. - Registered as btc:mainnet + btc:testnet in COINS with the orange Bitcoin disc SVG logo. Mount case mirrors DGB (accountPath honored, so switching to m/44'/0'/0' or m/49'/0'/0' via the setAccountPath message gives legacy 1… or wrapped-segwit 3… — same one-line UI plumb as the DGB address-family selector, deferred to a follow-up). - Panel: sat as the small-unit label, bitcoin: BIP21 QR payload, chain-aware send placeholder ("bc1q…" mainnet / "tb1q…" testnet). - Verified: BIP84 spec test vector — abandon×11 mnemonic derives bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu at m/84'/0'/0'/0/0 (byte-identical to the vector in the BIP text). Testnet variant produces tb1q6rz28mcfaxtmd6v789l9rrlrusdprr9pqcpvkl at m/84'/1'/0'/0/0 (cross-checkable on iancoleman.io/bip39 with coin BTC Testnet).
2026-09-07 21:15:45 +02:00
if (v && !/^m(\/\d+'?)+$/.test(v)) throw new Error("derivation path must look like m/84'/0'/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): BTC address-family picker (BIP44/49/84/86 + Taproot) BTC now matches DGB's family selector: pick BIP44 (1…), BIP49 (3…), BIP84 (bc1q…, default) or BIP86 Taproot (bc1p…) from Settings, on mainnet or testnet3 (paths shift coin type 0 → 1 automatically). - lib/chain-btc.js: paymentFor(purpose, node, network) returns the right bitcoinjs-lib payment (p2pkh / p2sh(p2wpkh) / p2wpkh / p2tr) keyed off the derivation path's purpose. WalletKeys.entry captures the family, redeem script (BIP49) and internal x-only pubkey (BIP86) alongside the standard script/address fields. bitcoinjs.initEccLib(ecc) is called once at load so p2tr resolves. - Registry: BTC + DGB address families are purpose-only now; a helper (addressFamiliesFor / defaultAccountPathFor) computes the concrete m/PURPOSE'/COIN'/0' per (chain, network) — coin type {mainnet:0, testnet:1} for BTC, always 20 for DGB. chainMeta expands the list so the panel doesn't need per-chain knowledge. - Panel: #btcSettings block mirrors #dgbSettings (family select → path input auto-fill → Apply). The family-select listener + the fillFamilyPicker() helper are shared between DGB and BTC — the DOM prefix is the only per-chain input. - Send is wired for BIP84 (default) and BIP49 (adds redeemScript to the PSBT input). BIP44 (needs nonWitnessUtxo prev-tx fetch) and BIP86 (needs tap-tweaked signer) throw a clear "not yet in this rev — sweep to BIP84" error so users hit it at plan time, not at broadcast time. Receive works on all four families today. - Verified all four families derive the canonical BIP44/49/84/86 spec test vectors for the standard abandon×11 mnemonic — see scratchpad/verify-btc-families.mjs. Byte-identical to the BIPs.
2026-09-07 21:23:15 +02:00
// Per-network default: BTC/DGB come from the registry helper, BCH keeps
// its historical m/44'/145'/0'.
const dflt = entry.chain === "bch"
? "m/44'/145'/0'"
: (defaultAccountPathFor(COINS[entry.chain], entry.network) || "m/84'/0'/0'");
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
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): Ethereum + Solana adapters, DGB address-family picker, Aegis-branded shield Multi-currency coverage matches what aegis.x has been advertising: BCH, TRX, SC, DGB, ETH, SOL — six coins, two-step coin/network picker for each. Panel logos, favicon and fallback all read as Aegis. - Ethereum (lib/chain-eth.js): mainnet + Sepolia. BIP44 m/44'/60'/0'/0/0 → secp256k1 → EIP-55 checksummed hex address (verified against MetaMask's canonical abandon×11 vector 0x9858EfFD23…4EcaEda94). JSON-RPC backend (Cloudflare mainnet, PublicNode Sepolia by default; per-wallet override). EIP-1559 send with an inline RLP encoder + secp256k1 recoverable sign; broadcast via eth_sendRawTransaction. personal_sign message signing follows the \x19Ethereum Signed Message:\n prefix. - Solana (lib/chain-sol.js): mainnet-beta + devnet. SLIP-0010 ed25519 derivation at m/44'/501'/0'/0' (all-hardened), base58 address (@noble ed25519). SLIP-0010 layer verified against spec Test Vector 1 in scratchpad/verify-slip10.mjs. Native SOL transfer via the system program with compact-u16 message serialization + ed25519 sign + sendTransaction. Devnet gets a faucet.solana.com link in Receive; the panel appends ?cluster=devnet when opening the explorer. - DGB address family selector (lib/chain-dgb.js already carried the paths): the Settings block now shows a Native SegWit / Taproot / Wrapped SegWit / Legacy P2PKH picker. Selecting a family auto-fills the derivation-path input with that family's default; Apply rebuilds the wallet against the new path. Address families exposed via chainMeta.addressFamilies so the panel can render them from data. - Panel branding: inline SVG shield (hexagonal aspis, same silhouette as the aegis.x hero) replaces the "?" fallback in logoSvg() and is what the header shows before a wallet is selected. Data-URI favicon wired into panel.html so the Theseus sidebar tab icon reads as Aegis rather than a chain-specific coin mark. - QR payloads now follow each chain's own URI scheme (BIP21 for BCH/DGB, EIP-681 for ETH, Solana Pay for SOL) so external scanners route the scan to the right wallet. Not shipped: EIP-1193 provider (window.ethereum) and wallet-adapter protocol (window.solana). The signing paths exist; only the page-inject bridge glue is missing. History for ETH/SOL is also empty in this rev — both need indexer plumbing (Etherscan V2 for ETH, getSignaturesForAddress + getTransaction pagination for SOL).
2026-09-07 20:31:27 +02:00
// ETH/SOL: per-wallet RPC URL, live-swap without key rebuild.
api.onMessage("setRpcUrl", (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 !== "eth" && entry.chain !== "sol") throw new Error("RPC URL is an ETH/SOL setting");
const v = String(patch.rpcUrl || "").trim();
if (v && !/^https?:\/\/[^\s]+$/i.test(v)) throw new Error("RPC URL must start with http:// or https://");
api.storage.set(`wallets/${id}/rpcUrl`, v);
const rt = ctx.runtimes.get(id);
if (rt && rt.adapter && typeof rt.adapter.setRpcUrl === "function") {
rt.adapter.setRpcUrl(v);
rt.adapter.refresh().catch((e) => api.log(`[${id}] refresh:`, e?.message || e));
}
emitState();
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/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.
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
];
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,
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/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("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 };
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.
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.",
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;
}
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/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
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");
}
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) ----
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();
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;
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 }],
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;
});
});
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();
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 || {}); }
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");
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);
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 };
}
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)` });
rows.push({ label: "Total", value: fmtBch(d.total) + " BCH" });
const pick = await api.approvalModal({
title: "Send Bitcoin Cash?",
origin,
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.",
rows,
actions: [{ id: "send", label: "Send", primary: true }],
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` }))],
},
});
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)) {
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);
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();
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 },
],
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);
});
});
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();
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);
});
});
feat(theseus/aegis): EIP-1193 + Solana wallet-adapter bridges; BTC signet Aegis now integrates with the two dapp-wallet APIs the wider ecosystem actually uses — MetaMask-style window.ethereum for Ethereum, Phantom-style window.solana for Solana — plus BTC signet as a third Bitcoin network alongside mainnet + testnet3. - wallet-inject.js: adds a main-world bridge, installed via a one-shot <script textContent=…> appended to <head> and immediately removed. Electron's contextBridge shallow-copies args and strips methods, which means BCH- and Tron-shaped params (plain data) work in the isolated world but Solana's wallet-adapter dapps — which pass @solana/web3.js Transaction objects and expect .serializeMessage()/.addSignature() to fire on them — need code that lives in the same world as the dapp. Bridge talks back to the isolated world via window.postMessage on a namespaced envelope (aegisTag = "aegis-" + addonId), which forwards to theseus.invoke. Same pattern MetaMask + Phantom use. - window.ethereum (EIP-1193): request({method, params}), on(), removeListener(), chainId, networkVersion, selectedAddress. Handles eth_requestAccounts, eth_accounts, eth_chainId, net_version, personal_sign, eth_sign, eth_sendTransaction, wallet_switchEthereumChain (rejects with "use the Aegis picker"), wallet_addEthereumChain (rejects, chains come from Settings), wallet_get/requestPermissions. Every other eth_*/net_*/web3_* method passes through to the wallet's configured RPC via a new eth.rpc handler. EIP-6963 announceProvider event fires so wagmi / RainbowKit / any 6963-aware dapp discovers Aegis alongside MetaMask instead of racing for window.ethereum. - window.solana (wallet-adapter shape): connect(), disconnect(), publicKey (with toString/toBase58/toBytes/equals — the PublicKey interface dapps check), signMessage(u8) → {publicKey, signature: u8}, signTransaction(tx) → mutates + returns the same tx with the signature added, signAndSendTransaction(tx) → returns {signature: txid}, signAllTransactions([tx]), request({method, params}). isPhantom flag set true so dapps that gate on it pick us. on/off events for connect / disconnect / accountChanged. - Handlers in index.js registerPageMessages: eth.requestAccounts, eth.personalSign, eth.sendTransaction, eth.switchChain, eth.rpc, sol.connect, sol.signMessage, sol.signAndSend. Every write path is per-origin gated + goes through api.approvalModal with the wallet label + network in the row list so the user always knows which Aegis wallet is about to sign. - Signet added to chain-btc.js — signet shares testnet3's address format and SLIP-44 coin type (BIP-325 only changed consensus/signing), so bitcoinjs-lib.networks.testnet handles derivation unchanged. Only the electrum pool (aranguren + wakiyamap) + explorer (mempool.space /signet) + faucet (signetfaucet.com) differ. Registered as btc:signet in COINS with per-network coinType lookup. Known limits (follow-ups in the same shape as existing chains): - SOL signAndSendTransaction is single-signer only; dapps that combine the wallet's sig with co-signer sigs need the wire assembled on the dapp side. - ETH eth_signTypedData_v4 (EIP-712) is not wired — the handler set covers personal_sign only.
2026-09-07 22:08:56 +02:00
// ---- Ethereum (EIP-1193) ---------------------------------------------
// Routes the same way as Tron: pick the currently-selected ETH wallet if
// any; else the first ready ETH wallet. Chain switches happen at the
// wallet-picker level, not here — dapps that call wallet_switchEthereumChain
// get a friendly "switch wallet in the Aegis sidebar" error.
function activeEthRuntime() {
const selId = selectedWalletId();
const selRt = selId && ctx.runtimes.get(selId);
if (selRt && selRt.entry.chain === "eth" && selRt.phase === "ready") return selRt;
for (const rt of ctx.runtimes.values()) if (rt.entry.chain === "eth" && rt.phase === "ready") return rt;
throw new Error("no Ethereum wallet available — add one in the Aegis sidebar");
}
function ethConnectedFor(origin) {
const p = permissions(api)[origin];
return !!(p && p.eth && p.eth.readAddress);
}
api.onMessage("eth.requestAccounts", async (_p, m) => {
const origin = fromPage(m);
const rt = activeEthRuntime();
const snap = rt.adapter.snapshot();
const chainIdHex = "0x" + Number(snap.chainId).toString(16);
const networkVersion = String(snap.chainId);
const perms = permissions(api);
if (perms[origin] && perms[origin].eth && perms[origin].eth.readAddress) {
return { address: snap.address, chainIdHex, networkVersion };
}
return withOriginLock(origin, async () => {
const pick = await api.approvalModal({
title: "Connect this site to your Ethereum 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 === "mainnet" ? "Ethereum mainnet" : "Sepolia testnet" },
{ label: "Wallet", value: `${rt.entry.label} — Ethereum · ${snap.network}` },
],
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] || {}), eth: { readAddress: true, chainId: snap.chainId } };
api.storage.set("permissions", perms);
emitState();
}
return { address: snap.address, chainIdHex, networkVersion };
});
});
api.onMessage("eth.personalSign", async (p, m) => {
const origin = fromPage(m);
if (!ethConnectedFor(origin)) throw new Error("not connected — call eth_requestAccounts first");
const rt = activeEthRuntime();
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 an Ethereum message?",
origin,
body: "Signing proves you control this address. It moves no ETH.",
rows: [
{ label: "Message", value: message.length > 400 ? message.slice(0, 400) + "…" : message, mono: true },
{ label: "Address", value: rt.adapter.snapshot().address, mono: true },
],
actions: [{ id: "sign", label: "Sign", primary: true }],
});
if (pick !== "sign") throw new Error("user rejected");
return rt.adapter.signMessage(message);
});
});
api.onMessage("eth.sendTransaction", async (p, m) => {
const origin = fromPage(m);
if (!ethConnectedFor(origin)) throw new Error("not connected — call eth_requestAccounts first");
const rt = activeEthRuntime();
const tx = (p && p.tx) || {};
if (!tx.to) throw new Error("tx.to required");
// MetaMask semantics: `value` and `gas`/`gasLimit` are hex-encoded wei;
// convert to numbers/bigints Aegis's own plan() understands.
const valueWei = tx.value ? BigInt(tx.value).toString() : "0";
return withOriginLock(origin, async () => {
const snap = rt.adapter.snapshot();
const plan = await rt.adapter.plan({ to: tx.to, amount: valueWei, sendMax: false });
const meta = chainMeta("eth", rt.entry.network);
const pick = await api.approvalModal({
title: "Send Ethereum transaction?",
origin,
body: tx.data && tx.data !== "0x" ? "This transaction carries call data (a contract call). Check the destination + value carefully." : "This site is asking your wallet to send ETH.",
rows: [
{ label: "To", value: plan.recipients[0].to, mono: true },
{ label: "Amount", value: `${fmtValue(plan.recipients[0].value, meta.decimals)} ETH`, strong: true },
{ label: "Fee (est.)", value: `${fmtValue(plan.fee, meta.decimals)} ETH` },
{ label: "Wallet", value: `${rt.entry.label} — Ethereum · ${snap.network}` },
],
actions: [{ id: "send", label: "Send", primary: true }],
});
if (pick !== "send") throw new Error("user rejected");
const r = await rt.adapter.signAndBroadcast(plan);
return { txid: r.txid };
});
});
api.onMessage("eth.switchChain", async (p, m) => {
fromPage(m);
const want = String(p && p.chainId || "").toLowerCase();
const rt = activeEthRuntime();
const cur = "0x" + Number(rt.adapter.snapshot().chainId).toString(16);
if (want === cur) return null;
throw new Error(`Aegis: switch chains via the Aegis sidebar picker. This wallet is on ${cur}; site asked for ${want}.`);
});
// Read passthrough: forward eth_getBalance / eth_call / etc. to the
// wallet's own configured RPC. Nothing here reveals the private key.
api.onMessage("eth.rpc", async (p, m) => {
fromPage(m);
const rt = activeEthRuntime();
const method = String(p && p.method || "");
const params = (p && p.params) || [];
if (!/^eth_|^net_|^web3_/.test(method)) throw new Error("Aegis: only eth_/net_/web3_ read methods are passed through");
return rt.adapter._client.call(method, params);
});
// ---- Solana (wallet-adapter) ------------------------------------------
function activeSolRuntime() {
const selId = selectedWalletId();
const selRt = selId && ctx.runtimes.get(selId);
if (selRt && selRt.entry.chain === "sol" && selRt.phase === "ready") return selRt;
for (const rt of ctx.runtimes.values()) if (rt.entry.chain === "sol" && rt.phase === "ready") return rt;
throw new Error("no Solana wallet available — add one in the Aegis sidebar");
}
function solConnectedFor(origin) {
const p = permissions(api)[origin];
return !!(p && p.sol && p.sol.readAddress);
}
api.onMessage("sol.connect", async (_p, m) => {
const origin = fromPage(m);
const rt = activeSolRuntime();
const snap = rt.adapter.snapshot();
if (solConnectedFor(origin)) return { address: snap.address, network: snap.network };
return withOriginLock(origin, async () => {
const pick = await api.approvalModal({
title: "Connect this site to your Solana 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 === "mainnet" ? "Mainnet-beta" : "Devnet" },
{ label: "Wallet", value: `${rt.entry.label} — Solana · ${snap.network}` },
],
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") {
const perms = permissions(api);
perms[origin] = { ...(perms[origin] || {}), sol: { readAddress: true, network: snap.network } };
api.storage.set("permissions", perms);
emitState();
}
return { address: snap.address, network: snap.network };
});
});
api.onMessage("sol.signMessage", async (p, m) => {
const origin = fromPage(m);
if (!solConnectedFor(origin)) throw new Error("not connected — call solana.connect first");
const rt = activeSolRuntime();
const b64 = String(p && p.messageB64 || "");
const bytes = Buffer.from(b64, "base64");
if (bytes.length > 4096) throw new Error("message too long");
return withOriginLock(origin, async () => {
const preview = bytes.every((c) => c >= 0x20 && c < 0x7f) ? bytes.toString("utf8") : `<${bytes.length} bytes: 0x${bytes.toString("hex").slice(0, 60)}…>`;
const pick = await api.approvalModal({
title: "Sign a Solana message?",
origin,
body: "Signing proves you control this address. It moves no SOL.",
rows: [
{ label: "Message", value: preview.length > 400 ? preview.slice(0, 400) + "…" : preview, mono: true },
{ label: "Address", value: rt.adapter.snapshot().address, mono: true },
],
actions: [{ id: "sign", label: "Sign", primary: true }],
});
if (pick !== "sign") throw new Error("user rejected");
return rt.adapter.signMessage(bytes);
});
});
// Dapp-built transaction: page hands us the wallet-adapter Transaction's
// .serializeMessage() output (base64). We sign it + broadcast via the
// adapter's own RPC. The txid returned by broadcast is the wire's txid.
api.onMessage("sol.signAndSend", async (p, m) => {
const origin = fromPage(m);
if (!solConnectedFor(origin)) throw new Error("not connected — call solana.connect first");
const rt = activeSolRuntime();
const b64 = String(p && p.messageB64 || "");
const messageBytes = new Uint8Array(Buffer.from(b64, "base64"));
return withOriginLock(origin, async () => {
const snap = rt.adapter.snapshot();
const pick = await api.approvalModal({
title: "Sign + send a Solana transaction?",
origin,
body: "The site built this transaction. Aegis can't decode arbitrary Solana instructions in this rev — verify the site before signing.",
rows: [
{ label: "Message size", value: `${messageBytes.length} bytes` },
{ label: "Address", value: snap.address, mono: true },
{ label: "Wallet", value: `${rt.entry.label} — Solana · ${snap.network}` },
],
actions: [{ id: "send", label: "Sign & send", primary: true }],
});
if (pick !== "send") throw new Error("user rejected");
// Sign the message with the wallet's ed25519 key (Solana signs the
// raw message bytes, no prefix).
const sigInfo = rt.adapter.signMessage(messageBytes); // {signature: base58}
const sigBytes = ctx.d.base58check.decodeBase58(sigInfo.signature);
if (sigBytes.length !== 64) throw new Error("bad ed25519 signature length");
// Wire = compact-u16(1) || 64-byte sig || message. Single-signer only
// in this rev: multi-signer flows would need the dapp's other sigs.
const wire = new Uint8Array(1 + 64 + messageBytes.length);
wire[0] = 0x01;
wire.set(sigBytes, 1);
wire.set(messageBytes, 65);
const wireB58 = ctx.d.base58check.encodeBase58(wire);
const txid = await rt.adapter._client.call("sendTransaction", [wireB58]);
if (typeof txid !== "string" || !txid.length) throw new Error("bad txid from RPC: " + JSON.stringify(txid));
setTimeout(() => rt.adapter.refresh().catch(() => {}), 4000);
return { txid };
});
});
}
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 ---------------------------------------------------------------
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);
registerPanelMessages(api);
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) => {
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();
}).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();
});
},
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();
},
};