Wallet strip: - Clicking a coin opens that coin's page (addresses, price, totals, back and close) instead of only flipping the selection and leaving the list sitting there. The page already existed but was reachable only via the small count chip. - The per-coin second action was a gear that selected the wallet and opened the global Settings tab — the same destination for every coin, so it read as a per-coin control that wasn't one. It is now Remove, behind a confirm, with the default/legacy wallet showing a lock instead since it gates legacy funds. - Each address in the drilldown can expand to show what THAT address holds: TRC20/SPL via the adapter's tokens, BCH CashTokens via tokenBalances. walletSummary now carries both per wallet, so the view no longer has to borrow the selected wallet's assets. WizardConnect — the Connect pane was effectively unusable: - The locked-vault branch told the user to unlock and gave them nothing to click. It is reachable without the lock screen ever appearing, because a mounted imported wallet makes overallPhase read "ready". It now carries the same unlock form the lock screen uses. - Imported BCH wallets were never registered with the WC manager — startForWallet ran only in the vault-derived mount branch. They mount as ready, so they appeared in the "Sign with" picker and then failed on pair. They now register from their stored seed. WC derives a child key tree, so single-key (WIF) imports genuinely cannot pair; those are disabled in the picker with the reason, rather than failing on click. - Adds window.wizardconnect so a dapp can hand over the wiz:// URI it already generated instead of making the user copy it between tabs. The protocol is Nostr-relay pairing designed for phone-scans-QR, and the SDK has no in-page discovery at all, so this is our own surface: connect() + isReady(), plus a wizardconnect:announceProvider event shaped like EIP-6963 so several WC wallets can coexist. Pairing always goes through the approval modal; the URI is validated before any UI shows, and the wallet never reads the page to find one.
1081 lines
71 KiB
HTML
1081 lines
71 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Aegis Wallet</title>
|
||
<!-- Aegis brand mark from aegis.x/brand/favicon.svg — kept byte-close so
|
||
the sidebar-tab icon reads as the identity a user just downloaded from. -->
|
||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml;utf8,%3Csvg%20xmlns%3D'http%3A//www.w3.org/2000/svg'%20viewBox%3D'0%200%2032%2032'%20fill%3D'none'%3E%3Cpolygon%20points%3D'16%2C2%2028%2C9%2028%2C23%2016%2C30%204%2C23%204%2C9'%20fill%3D'%230a0a0d'%20stroke%3D'%23D6FF3D'%20stroke-width%3D'1.6'%20stroke-linejoin%3D'round'/%3E%3Ccircle%20cx%3D'16'%20cy%3D'16'%20r%3D'4.5'%20fill%3D'none'%20stroke%3D'%23D6FF3D'%20stroke-width%3D'1.4'/%3E%3Ccircle%20cx%3D'16'%20cy%3D'16'%20r%3D'1.6'%20fill%3D'%23D6FF3D'/%3E%3C/svg%3E">
|
||
<style>
|
||
:root { color-scheme: light dark;
|
||
--bg:#0e131c; --panel:#141a24; --card:#0f1621; --line:rgba(255,255,255,.09);
|
||
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d; --danger:#f6768a; --ok:#5ad38a;
|
||
--bch:#0ac18e; --trx:#ff060a; --trxNile:#4d9dff; }
|
||
@media (prefers-color-scheme: light) {
|
||
:root { --bg:#f8faff; --panel:#ffffff; --card:#f1f4fa; --line:rgba(0,0,0,.10);
|
||
--ink:#1a1f2b; --mut:#5c6577; --dim:#8a93a5;
|
||
/* Darker acid on light backgrounds — ~7:1 contrast on white. */
|
||
--acid: #0AC18E; }
|
||
}
|
||
* { box-sizing: border-box; }
|
||
html, body { margin: 0; height: 100%; }
|
||
body { background: var(--bg); color: var(--ink);
|
||
font: 13.5px/1.5 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
||
display: flex; flex-direction: column; position: relative; }
|
||
header { padding: 10px 14px 10px; border-bottom: 1px solid var(--line); background: var(--panel); position: relative; }
|
||
.picker { display: flex; align-items: center; justify-content: space-between; gap: 8px; cursor: pointer; user-select: none; }
|
||
.picker .t { display: flex; align-items: center; gap: 7px; font-weight: 600; min-width: 0; }
|
||
.picker .t .badge { font-size: 15px; line-height: 1; }
|
||
.picker .t .lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.picker .caret { color: var(--mut); font-size: 10px; }
|
||
.picker:hover { color: var(--acid); }
|
||
.net { display: flex; align-items: center; gap: 6px; color: var(--dim); font-size: 11.5px; white-space: nowrap; }
|
||
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--dim); }
|
||
.dot.on { background: var(--ok); } .dot.busy { background: #e0b341; }
|
||
.bal { margin-top: 8px; font-variant-numeric: tabular-nums; }
|
||
.bal .big { font-size: 22px; font-weight: 650; letter-spacing: .2px; }
|
||
.bal .big small { font-size: 13px; color: var(--mut); font-weight: 500; margin-left: 4px; }
|
||
.bal .sub { color: var(--dim); font-size: 11.5px; display: flex; justify-content: space-between; gap: 8px; }
|
||
.bal .sub .netlbl { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
/* Full-panel sheet — fills most of the sidebar but stops above the
|
||
footer so the aegis.x brand + version chip stay visible. Users
|
||
opening + should still know which build they're on and be able
|
||
to hit the update button. */
|
||
#drop { position: fixed; left: 0; right: 0; top: 60px; bottom: 30px;
|
||
background: var(--panel); border-top: 1px solid var(--line);
|
||
box-shadow: 0 -6px 26px rgba(0,0,0,.35); z-index: 20;
|
||
display: flex; flex-direction: column; }
|
||
#drop[hidden] { display: none; }
|
||
#drop .droptabs { display: flex; border-bottom: 1px solid var(--line); flex: none; }
|
||
#drop .droptabs button { flex: 1; background: transparent; border: 0; color: var(--dim);
|
||
padding: 10px 8px; font: inherit; font-size: 13px; cursor: pointer; border-bottom: 2px solid transparent; }
|
||
#drop .droptabs button.on { color: var(--ink); border-bottom-color: var(--acid, #d6ff3d); font-weight: 600; }
|
||
#drop .droptabs .closex { flex: none; width: 40px; font-size: 16px; color: var(--dim); border-left: 1px solid var(--line); }
|
||
#drop .droppane { flex: 1; overflow-y: auto; padding: 6px; }
|
||
#drop .droppane[hidden] { display: none; }
|
||
#drop .row, #drop .coinrow { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 7px; cursor: pointer; }
|
||
#drop .row:hover, #drop .coinrow:hover { background: rgba(255,255,255,.05); }
|
||
#drop .row .m, #drop .coinrow .m { flex: 1; min-width: 0; }
|
||
#drop .row .m .l, #drop .coinrow .m .l { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
#drop .row .m .s, #drop .coinrow .m .s { color: var(--dim); font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
#drop .row .v { color: var(--mut); font-size: 12px; font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
|
||
#drop .row .v .fs { color: var(--dim); font-size: 11px; margin-top: 2px; }
|
||
#drop .row.on { background: rgb(from var(--acid) r g b / .10); }
|
||
#drop .coinrow .caret { color: var(--dim); font-size: 11px; }
|
||
#drop hr { border: 0; border-top: 1px solid var(--line); margin: 6px 0; }
|
||
#drop .addhdr { padding: 5px 8px 3px; color: var(--dim); font-size: 11px; text-transform: uppercase; letter-spacing: .04em; }
|
||
#drop .netgroup { padding: 2px 4px 6px 40px; }
|
||
#drop .netgroup[hidden] { display: none; }
|
||
#drop .netchoice { padding: 6px 8px; border-radius: 6px; cursor: pointer; font-size: 12.5px; color: var(--mut); }
|
||
#drop .netchoice:hover { background: rgba(255,255,255,.06); color: var(--ink); }
|
||
/* Currency-browse network chip row (0.8.0). Sits above the wallet list
|
||
under a coin; clicking a chip switches which subnetwork's wallets
|
||
are visible AND persists the choice per chain. */
|
||
#drop .brnetrow { display: flex; gap: 6px; padding: 8px 8px 4px; flex-wrap: wrap; border-bottom: 1px solid var(--line); }
|
||
#drop .brnet { background: transparent; border: 1px solid var(--line); color: var(--mut);
|
||
border-radius: 999px; padding: 3px 10px; font: inherit; font-size: 12px; cursor: pointer;
|
||
display: inline-flex; align-items: center; gap: 4px; }
|
||
#drop .brnet:hover { border-color: var(--acid, #d6ff3d); color: var(--acid, #d6ff3d); }
|
||
#drop .brnet.on { background: rgb(from var(--acid, #d6ff3d) r g b / .14); border-color: rgb(from var(--acid, #d6ff3d) r g b / .55);
|
||
color: var(--acid, #d6ff3d); font-weight: 600; }
|
||
#drop .brnet .hint { color: currentColor; opacity: .65; font-size: 11px; }
|
||
.ttag { display: inline-block; font-size: 9.5px; letter-spacing: .06em; padding: 1px 5px; border-radius: 3px;
|
||
background: rgba(224,179,65,.18); color: #e0b341; font-weight: 700; vertical-align: middle; margin-left: 2px; }
|
||
/* 0.8.4: hNet became a proper chip on its own row (.netrow) so the
|
||
network the wallet is on is easy to spot AND easy to switch. */
|
||
.netrow { display: flex; margin-top: 6px; padding: 0 2px; }
|
||
.netchip { background: rgba(255,255,255,.05); border: 1px solid var(--line);
|
||
color: var(--mut); border-radius: 999px; padding: 3px 10px 3px 8px;
|
||
font: inherit; font-size: 11.5px; cursor: pointer; display: inline-flex;
|
||
align-items: center; gap: 6px; line-height: 1.2; }
|
||
.netchip:hover { border-color: var(--acid, #d6ff3d); color: var(--acid, #d6ff3d); }
|
||
.netchip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .7; }
|
||
/* Currency-picker search + all-coins catalogue (0.8.4). */
|
||
#drop .pickersearch { padding: 8px; border-bottom: 1px solid var(--line); }
|
||
#drop .pickersearch input { width: 100%; box-sizing: border-box; background: rgba(255,255,255,.04);
|
||
border: 1px solid var(--line); color: var(--ink); border-radius: 7px;
|
||
padding: 7px 10px; font: inherit; font-size: 12.5px; outline: none; }
|
||
#drop .pickersearch input:focus { border-color: rgb(from var(--acid, #d6ff3d) r g b / .55); }
|
||
#drop .catgroup { padding: 4px 6px 2px 10px; color: var(--dim); font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; }
|
||
#drop .row.unowned { opacity: .8; }
|
||
#drop .row.unowned .v { color: var(--acid, #d6ff3d); font-weight: 600; font-size: 11px; }
|
||
.fiat { color: var(--dim); font-size: 12.5px; margin-left: 10px; font-weight: 500; letter-spacing: .2px; }
|
||
.portfolio { margin-top: 6px; color: var(--mut); font-size: 11.5px; }
|
||
.portfolio b { color: var(--ink); font-weight: 600; }
|
||
.portfolio[hidden] { display: none; }
|
||
.picker-actions { display: flex; align-items: center; gap: 6px; }
|
||
.chip { background: transparent; border: 1px solid var(--line); color: var(--mut); border-radius: 6px;
|
||
padding: 0 8px; height: 22px; cursor: pointer; font: inherit; font-size: 13.5px; line-height: 1;
|
||
display: inline-flex; align-items: center; justify-content: center; }
|
||
.chip:hover { border-color: var(--acid); color: var(--acid); }
|
||
/* Edit-this-wallet button living inside the label group. Compact and
|
||
borderless so it reads as an inline affordance, not a separate
|
||
action chip. Fades in on hover of the label row so the header
|
||
itself stays visually quiet when the user isn't targeting it. */
|
||
.editchip { background: transparent; border: 0; color: var(--dim); cursor: pointer;
|
||
padding: 2px 4px; border-radius: 4px; font: inherit; font-size: 12px; line-height: 1;
|
||
opacity: .5; transition: opacity .12s, color .12s; margin-left: 2px; }
|
||
.picker:hover .editchip { opacity: 1; }
|
||
.editchip:hover { color: var(--acid, #d6ff3d); background: rgba(255,255,255,.06); }
|
||
/* Send/Receive mode toggle (0.8.0). Segmented control at the top of a
|
||
tab; picks whether the body shows the normal flow or the consolidate
|
||
inline picker. */
|
||
.modetoggle { display: flex; gap: 0; border: 1px solid var(--line); border-radius: 8px; padding: 3px;
|
||
margin-bottom: 12px; background: rgba(255,255,255,.03); }
|
||
.modetoggle[hidden] { display: none; }
|
||
.modetoggle button { flex: 1; background: transparent; border: 0; color: var(--dim);
|
||
padding: 6px 8px; font: inherit; font-size: 12.5px; border-radius: 6px;
|
||
cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 5px; }
|
||
.modetoggle button.on { background: rgb(from var(--acid, #d6ff3d) r g b / .16); color: var(--acid, #d6ff3d); font-weight: 600; }
|
||
.modetoggle button:hover:not(.on) { color: var(--ink); }
|
||
.modetoggle .hint { color: currentColor; opacity: .65; font-size: 11px; }
|
||
/* Settings section chip nav (0.8.2). Segmented row that pages between
|
||
Security / Session / Wallet / Prices / Sites / About cards without
|
||
scrolling through the whole tab. */
|
||
.setsecnav { display: flex; flex-wrap: wrap; gap: 4px; border: 1px solid var(--line);
|
||
border-radius: 8px; padding: 3px; margin-bottom: 14px;
|
||
background: rgba(255,255,255,.03); }
|
||
.setsecnav button { flex: 1 0 auto; min-width: 62px; background: transparent; border: 0;
|
||
color: var(--dim); padding: 6px 10px; font: inherit; font-size: 12px;
|
||
border-radius: 6px; cursor: pointer; }
|
||
.setsecnav button.on { background: rgb(from var(--acid, #d6ff3d) r g b / .16);
|
||
color: var(--acid, #d6ff3d); font-weight: 600; }
|
||
.setsecnav button:hover:not(.on) { color: var(--ink); }
|
||
nav { display: flex; border-bottom: 1px solid var(--line); background: var(--panel); }
|
||
nav button { flex: 1; padding: 9px 0 8px; border: 0; background: transparent; color: var(--mut); cursor: pointer;
|
||
font: inherit; font-size: 12.5px; border-bottom: 2px solid transparent; }
|
||
nav button.on { color: var(--acid); border-bottom-color: var(--acid); }
|
||
nav button:hover { color: var(--ink); }
|
||
main { flex: 1; overflow: auto; padding: 14px; }
|
||
/* Persistent aegis.x brand strip. Sticks to the panel's bottom edge so the
|
||
wallet always advertises its own front-door site — helps users bookmark
|
||
it, and doubles as a version marker for support triage. */
|
||
.brandfoot { flex: none; display: flex; align-items: center; justify-content: space-between;
|
||
padding: 6px 12px; border-top: 1px solid var(--line); background: var(--panel);
|
||
font-size: 11px; color: var(--dim); }
|
||
.brandlink { display: inline-flex; align-items: center; gap: 5px; color: var(--dim); text-decoration: none;
|
||
padding: 2px 4px; border-radius: 4px; }
|
||
.brandlink:hover { color: var(--acid, #d6ff3d); }
|
||
.brandlink svg { color: currentColor; }
|
||
.brandver { font-variant-numeric: tabular-nums; letter-spacing: .3px; }
|
||
.brandfoot-right { display: inline-flex; align-items: center; gap: 8px; }
|
||
.brandcheck { background: transparent; border: 0; color: var(--dim); cursor: pointer; padding: 0 2px;
|
||
font: inherit; font-size: 12px; line-height: 1; opacity: .7; transition: opacity .12s, color .12s; }
|
||
.brandcheck:hover { color: var(--acid, #d6ff3d); opacity: 1; }
|
||
.brandcheck.spin { animation: brandspin 1s linear infinite; }
|
||
@keyframes brandspin { to { transform: rotate(360deg); } }
|
||
.brandupd { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; padding: 2px 8px;
|
||
border-radius: 999px; background: rgb(from var(--acid, #d6ff3d) r g b / .14); color: var(--acid, #d6ff3d);
|
||
cursor: pointer; text-decoration: none; font-weight: 600;
|
||
transition: opacity .2s; }
|
||
.brandupd[hidden] { display: none; }
|
||
.brandupd:hover { background: rgb(from var(--acid, #d6ff3d) r g b / .22); }
|
||
/* Transient states painted by paintFooterUpdate: "✓ Up to date" after a
|
||
manual check when no newer version is available, and "⚠ Check failed"
|
||
when the OTA fetch errors. Both auto-hide after ~2s; the styling reads
|
||
as ephemeral confirmation rather than a persistent chip. */
|
||
.brandupd.brandok { background: rgba(255,255,255,.06); color: var(--dim); font-weight: 500;
|
||
cursor: default; }
|
||
.brandupd.brandok:hover { background: rgba(255,255,255,.06); }
|
||
.brandupd.branderr { background: rgba(224,90,90,.18); color: #e05a5a; font-weight: 500;
|
||
cursor: default; }
|
||
.brandupd.branderr:hover { background: rgba(224,90,90,.18); }
|
||
/* In-progress state: painted while the panel is fetching / staging /
|
||
restarting. Not clickable, dimmer than the acid CTA chip so users
|
||
don't try to smash it. */
|
||
.brandupd.brandwait { background: rgba(255,255,255,.06); color: var(--mut);
|
||
font-weight: 500; cursor: default; }
|
||
.brandupd.brandwait:hover { background: rgba(255,255,255,.06); }
|
||
section[hidden] { display: none; }
|
||
.card { background: var(--card); border: 1px solid var(--line); border-radius: 10px; padding: 12px; }
|
||
.mono { font: 12.5px/1.45 ui-monospace, "Cascadia Code", Consolas, monospace; word-break: break-all; }
|
||
.lbl { color: var(--dim); font-size: 11.5px; margin-bottom: 4px; }
|
||
.btn { padding: 7px 12px; border-radius: 7px; border: 1px solid var(--line); background: var(--panel); color: var(--ink);
|
||
cursor: pointer; font: inherit; font-size: 12.5px; }
|
||
.btn:hover { border-color: rgb(from var(--acid) r g b / .4); }
|
||
.btn.primary { background: var(--acid); color: #0b0e14; border-color: transparent; font-weight: 650; }
|
||
.btn.primary:disabled { opacity: .45; cursor: default; }
|
||
.btn.danger { color: var(--danger); }
|
||
.btn.sm { padding: 4px 9px; font-size: 12px; }
|
||
.actions { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
|
||
.qrwrap { display: grid; place-items: center; padding: 12px; background: #fff; border-radius: 10px; margin-bottom: 12px; }
|
||
canvas { image-rendering: pixelated; }
|
||
input[type=text], input[type=number], input[type=password], textarea { width: 100%; padding: 7px 9px; border-radius: 7px; background: var(--panel);
|
||
border: 1px solid var(--line); color: var(--ink); font: inherit; font-size: 13px; outline: none; }
|
||
input:focus, textarea:focus { border-color: rgb(from var(--acid) r g b / .5); }
|
||
textarea { resize: vertical; min-height: 96px; font: 12px/1.45 ui-monospace, Consolas, monospace; }
|
||
.field { margin-bottom: 12px; }
|
||
.hint { color: var(--dim); font-size: 11.5px; margin-top: 4px; }
|
||
.switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; font-size: 12.5px; color: var(--ink); }
|
||
.switch input { accent-color: var(--brand, #d6ff3d); width: 15px; height: 15px; margin: 0; }
|
||
.amt { display: flex; gap: 6px; }
|
||
.amt input { flex: 1; }
|
||
.unit { display: flex; border: 1px solid var(--line); border-radius: 7px; overflow: hidden; }
|
||
.unit button { border: 0; background: var(--panel); color: var(--mut); padding: 0 10px; cursor: pointer; font: inherit; font-size: 12px; }
|
||
.unit button.on { background: rgb(from var(--acid) r g b / .14); color: var(--acid); }
|
||
.fee { display: flex; align-items: center; gap: 10px; }
|
||
.fee input[type=range] { flex: 1; accent-color: var(--acid); }
|
||
.fee .v { color: var(--mut); font-size: 12px; min-width: 70px; text-align: right; font-variant-numeric: tabular-nums; }
|
||
.summary { display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; font-size: 12.5px; margin-top: 10px; }
|
||
.summary .k { color: var(--dim); } .summary .v { text-align: right; font-variant-numeric: tabular-nums; }
|
||
.msg { margin-top: 10px; font-size: 12.5px; padding: 8px 10px; border-radius: 7px; }
|
||
.msg.err { background: rgba(246,118,138,.12); color: var(--danger); }
|
||
.msg.ok { background: rgba(90,211,138,.12); color: var(--ok); }
|
||
.msg a { color: inherit; }
|
||
.tx { display: grid; grid-template-columns: 22px 1fr auto; gap: 2px 10px; padding: 9px 4px; border-bottom: 1px solid var(--line); cursor: pointer; }
|
||
.tx:hover { background: rgba(255,255,255,.03); }
|
||
.tx .ic { font-size: 15px; line-height: 1.3; }
|
||
.tx .ic.in { color: var(--ok); } .tx .ic.out { color: var(--danger); }
|
||
.tx .what { font-size: 12.5px; }
|
||
.tx .when { color: var(--dim); font-size: 11.5px; grid-column: 2; }
|
||
.tx .amt2 { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; font-size: 12.5px; }
|
||
.tx .amt2.in { color: var(--ok); }
|
||
.tx .conf { grid-column: 3; text-align: right; color: var(--dim); font-size: 11px; }
|
||
.tx .conf.pending { color: #e0b341; }
|
||
.empty { color: var(--dim); text-align: center; padding: 30px 10px; font-size: 12.5px; }
|
||
.gate { padding: 40px 18px; text-align: center; color: var(--mut); }
|
||
.gate .big { font-size: 28px; margin-bottom: 8px; }
|
||
.gate b { color: var(--ink); }
|
||
.kv { margin-top: 10px; }
|
||
.kv .lbl { margin-top: 8px; }
|
||
a.link { color: var(--acid); text-decoration: none; cursor: pointer; }
|
||
/* Preset-server checkbox list — one row per known Electrum endpoint, plus
|
||
any URL the user added via the "Add a custom server" reveal. Rows show
|
||
the host + a small hover-to-remove for user-added entries. */
|
||
.serverlist { display: flex; flex-direction: column; gap: 3px; margin-top: 4px; }
|
||
.serverlist label { display: flex; align-items: center; gap: 8px; padding: 5px 6px;
|
||
border-radius: 6px; cursor: pointer; font-size: 12.5px; color: var(--mut); }
|
||
.serverlist label:hover { background: rgba(255,255,255,.04); color: var(--ink); }
|
||
.serverlist input[type=checkbox] { accent-color: var(--acid, #d6ff3d); width: 14px; height: 14px; margin: 0; }
|
||
.serverlist .surl { flex: 1; font: 11.5px/1.4 ui-monospace, Consolas, monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.serverlist .sremove { flex: none; background: transparent; border: 0; color: var(--dim); cursor: pointer; padding: 0 4px; opacity: 0; }
|
||
.serverlist label:hover .sremove { opacity: 1; }
|
||
.serverlist .sremove:hover { color: var(--danger, #f6768a); }
|
||
/* Always-visible wallet list — vertical column of rows so users can scan
|
||
names + balances without dragging chips sideways. Capped at ~40vh so a
|
||
giant list still leaves the main content readable; scrolls inside. */
|
||
.wstrip { flex: none; display: flex; flex-direction: column; gap: 1px; padding: 4px 6px 5px 6px;
|
||
max-height: 44vh; overflow-y: auto; scrollbar-width: thin;
|
||
background: var(--panel); border-bottom: 1px solid var(--line); }
|
||
.wstrip::-webkit-scrollbar { width: 4px; }
|
||
.wstrip::-webkit-scrollbar-thumb { background: var(--line); border-radius: 2px; }
|
||
.wstrip .wchip { display: flex; align-items: center; gap: 4px; padding: 4px 6px 4px 4px;
|
||
background: transparent; border: 1px solid transparent; border-radius: 7px;
|
||
font: inherit; font-size: 12.5px; color: var(--mut); min-width: 0; }
|
||
.wstrip .wchip:hover { background: rgba(255,255,255,.04); color: var(--ink); }
|
||
.wstrip .wchip.on { background: rgb(from var(--acid, #d6ff3d) r g b / .10);
|
||
border-color: rgb(from var(--acid, #d6ff3d) r g b / .35);
|
||
color: var(--ink); }
|
||
.wstrip .wchip .wclick { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0;
|
||
cursor: pointer; padding: 2px 4px; border-radius: 5px; }
|
||
.wstrip .wchip .wtext { flex: 1; min-width: 0; overflow: hidden; display: inline-flex;
|
||
align-items: center; gap: 6px; flex-wrap: nowrap; }
|
||
.wstrip .wchip .wname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.wstrip .wchip .wsub { color: var(--dim); font-size: 10.5px; font-weight: 400; margin-left: 6px;
|
||
font-variant-numeric: tabular-nums; white-space: nowrap; }
|
||
/* Price chip sitting right next to the wallet label. Acid tint with a
|
||
subtle glow lifts it off the grey row so users spot movement without
|
||
hunting; the small background gives it structural presence too. */
|
||
.wstrip .wchip .wprice { color: var(--acid, #d6ff3d); font-size: 11px; font-weight: 600;
|
||
font-variant-numeric: tabular-nums; white-space: nowrap;
|
||
padding: 1px 6px; border-radius: 999px;
|
||
background: rgb(from var(--acid, #d6ff3d) r g b / .10);
|
||
text-shadow: 0 0 6px rgb(from var(--acid, #d6ff3d) r g b / .35); }
|
||
.wstrip .wchip .wact { flex: none; background: transparent; border: 0; color: var(--dim);
|
||
cursor: pointer; padding: 3px 6px; border-radius: 5px; font-size: 12px; line-height: 1; }
|
||
.wstrip .wchip .wact:hover { color: var(--acid, #d6ff3d); background: rgba(255,255,255,.06); }
|
||
/* Four-column layout: [logo][ticker+price stack][amount+fiat stack][actions].
|
||
The old separate Price and Chain columns collapsed into the ticker cell —
|
||
per-unit price sits directly under the ticker so the eye can read
|
||
"BCH · $430" as one unit before jumping to the balance on the right.
|
||
A non-mainnet row also carries a small network pill inline with the
|
||
ticker (Chipnet / Sepolia / …); mainnet rows omit it entirely. */
|
||
.wstrip { padding: 4px 6px 6px 6px; }
|
||
.wstrip .wrow { display: grid; grid-template-columns: 18px minmax(72px,auto) minmax(0,1fr) auto auto;
|
||
gap: 8px; align-items: center; padding: 5px 4px;
|
||
border-radius: 6px; border: 1px solid transparent; cursor: pointer;
|
||
min-height: 30px; }
|
||
.wstrip .wrow:hover { background: rgba(255,255,255,.04); }
|
||
.wstrip .wrow.on { background: rgb(from var(--acid, #d6ff3d) r g b / .10);
|
||
border-color: rgb(from var(--acid, #d6ff3d) r g b / .35); }
|
||
.wstrip .wrow.dragging { opacity: .45; cursor: grabbing; }
|
||
.wstrip .wrow.drop-before { box-shadow: 0 -2px 0 0 var(--acid, #d6ff3d); }
|
||
.wstrip .wrow.drop-after { box-shadow: 0 2px 0 0 var(--acid, #d6ff3d); }
|
||
.wstrip .wgrip { display: inline-block; color: var(--dim); font-size: 10px; padding: 0 2px;
|
||
cursor: grab; user-select: none; opacity: 0; transition: opacity .12s; }
|
||
.wstrip .wrow:hover .wgrip { opacity: 1; }
|
||
.wstrip .wrow[draggable="true"] { cursor: grab; }
|
||
.wstrip .wcell { min-width: 0; display: inline-flex; align-items: center; gap: 3px; }
|
||
.wstrip .wclogo { justify-self: start; align-self: start; padding-top: 2px; }
|
||
/* Ticker cell: two-line stack. Line 1 has the ticker, an optional ▾
|
||
chevron (only when the chain has more than one network to switch
|
||
between), an optional Chipnet/Testnet pill, and the wallet count.
|
||
Line 2 is the per-unit price in acid-green. The cell as a whole is
|
||
the click target for the network dropdown. */
|
||
.wstrip .wcname { flex-direction: column; align-items: flex-start; line-height: 1.15; gap: 1px; }
|
||
.wstrip .wcname .wtline { display: inline-flex; align-items: center; gap: 5px; }
|
||
.wstrip .wcname .wtck { font-weight: 700; font-size: 13px; color: var(--ink); }
|
||
.wstrip .wcname .wchev { color: var(--dim); font-size: 9px; line-height: 1; padding: 0 1px;
|
||
transition: color .12s, transform .12s; }
|
||
.wstrip .wcname.wswitchable { cursor: pointer; }
|
||
.wstrip .wcname.wswitchable:hover .wchev { color: var(--acid, #d6ff3d); }
|
||
.wstrip .wcname .wnetpill { font-size: 10px; padding: 1px 6px; border-radius: 999px;
|
||
background: rgba(255,255,255,.06); color: var(--mut);
|
||
white-space: nowrap; line-height: 1.35; }
|
||
.wstrip .wcname .wnetpill.wchipnet { background: rgb(from var(--acid, #d6ff3d) r g b / .18);
|
||
color: var(--acid, #d6ff3d); font-weight: 600; }
|
||
.wstrip .wcname .wnetpill.wtestnet { background: rgba(224,179,65,.18); color: #e0b341; font-weight: 600; }
|
||
/* Multi-wallet count pill inside the ticker cell. When the group has
|
||
more than one wallet it doubles as the "swap active wallet" trigger
|
||
(▾ chevron), independent of the row's own click target which now
|
||
selects the current active wallet directly. */
|
||
.wstrip .wcname .wgcount.wgpick { cursor: pointer; }
|
||
.wstrip .wcname .wgcount.wgpick:hover { background: rgba(255,255,255,.12); color: var(--acid, #d6ff3d); }
|
||
.wstrip .wcname .wgcount .wgchev { color: var(--dim); font-size: 9px; margin-left: 1px; }
|
||
.wstrip .wcname .wgcount.wgpick:hover .wgchev { color: var(--acid, #d6ff3d); }
|
||
.wstrip .wcname .wgcount { color: var(--dim); font-size: 10.5px; padding: 0 6px; border-radius: 999px;
|
||
background: rgba(255,255,255,.06); font-variant-numeric: tabular-nums; line-height: 1.4; }
|
||
.wstrip .wcname .wcprice { color: var(--acid, #d6ff3d); font-size: 11px; font-weight: 600;
|
||
font-variant-numeric: tabular-nums; white-space: nowrap;
|
||
text-shadow: 0 0 5px rgb(from var(--acid, #d6ff3d) r g b / .30); }
|
||
.wstrip .wcamt { flex-direction: column; align-items: flex-end; text-align: right;
|
||
font-variant-numeric: tabular-nums; line-height: 1.2; }
|
||
.wstrip .wcamt .wnative { font-size: 12.5px; color: var(--ink); font-weight: 500; }
|
||
.wstrip .wcamt .wfiat { font-size: 11px; color: var(--dim); }
|
||
.wstrip .wcact { display: inline-flex; gap: 2px; }
|
||
.wstrip .wcact .wact { background: transparent; border: 0; color: var(--dim); cursor: pointer;
|
||
padding: 2px 5px; border-radius: 4px; font-size: 12.5px; line-height: 1; }
|
||
.wstrip .wcact .wact:hover { color: var(--acid, #d6ff3d); background: rgba(255,255,255,.06); }
|
||
/* Network dropdown menu — anchored below the ticker cell on click. Shows
|
||
every network under the chain (mainnet + testnets) with its own totals,
|
||
so switching networks feels like flipping a segment on the same coin
|
||
row rather than jumping to a separate wallet. */
|
||
.netmenu { position: absolute; z-index: 60; min-width: 180px; background: var(--panel, #1a1a1a);
|
||
border: 1px solid var(--line); border-radius: 8px; padding: 4px;
|
||
box-shadow: 0 6px 20px rgba(0,0,0,.35); }
|
||
.netmenu .nmitem { display: flex; align-items: center; justify-content: space-between;
|
||
gap: 10px; padding: 6px 8px; border-radius: 5px; cursor: pointer;
|
||
color: var(--ink); font-size: 12.5px; }
|
||
.netmenu .nmitem:hover { background: rgba(255,255,255,.06); }
|
||
.netmenu .nmitem.on { background: rgb(from var(--acid, #d6ff3d) r g b / .12);
|
||
color: var(--acid, #d6ff3d); }
|
||
.netmenu .nmitem .nmname { display: inline-flex; align-items: center; gap: 6px; }
|
||
.netmenu .nmitem .nmnet { font-weight: 600; }
|
||
.netmenu .nmitem .nmcount { color: var(--dim); font-size: 10.5px; padding: 0 5px; border-radius: 999px;
|
||
background: rgba(255,255,255,.06); }
|
||
.netmenu .nmitem .nmamt { font-variant-numeric: tabular-nums; font-size: 11.5px; color: var(--dim); }
|
||
.netmenu .nmitem.on .nmamt { color: var(--acid, #d6ff3d); }
|
||
/* Acid-green testnet tag for the Chipnet group. Overrides the warm-amber
|
||
default so chipnet reads as "the friendly BCH testnet" instead of
|
||
borrowing the caution palette. */
|
||
.ttag.acid { background: rgb(from var(--acid, #d6ff3d) r g b / .18); color: var(--acid, #d6ff3d); }
|
||
.wstrip .waddwrap { display: flex; gap: 5px; padding: 0 0 4px 0; margin-bottom: 4px; border-bottom: 1px solid var(--line); }
|
||
.wstrip .waddwrap button { flex: 1; background: transparent; border: 1px dashed var(--line); border-radius: 6px;
|
||
padding: 5px 8px; color: var(--dim); cursor: pointer; font: inherit; font-size: 12px; line-height: 1; }
|
||
.wstrip .waddwrap button:hover { color: var(--acid, #d6ff3d); border-color: var(--acid, #d6ff3d); }
|
||
/* Inline coin-address view — takes the place of the six-column grid when
|
||
a user opens a multi-wallet group. Back-arrow row + one row per wallet
|
||
under the coin. Same container so the visual context stays put. */
|
||
.wstrip .wcoinhead { display: flex; align-items: center; gap: 6px; padding: 3px 4px 4px 4px;
|
||
border-bottom: 1px solid var(--line); }
|
||
.wstrip .wcoinhead .wback { background: transparent; border: 0; color: var(--dim); cursor: pointer;
|
||
padding: 2px 4px; border-radius: 4px; font: inherit; font-size: 12px; line-height: 1; }
|
||
.wstrip .wcoinhead .wback:hover { color: var(--acid, #d6ff3d); background: rgba(255,255,255,.06); }
|
||
.wstrip .wcoinhead .wctitle { flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: 6px;
|
||
font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.wstrip .wcoinhead .wcount { color: var(--dim); font-size: 11.5px; font-weight: 500; }
|
||
/* Inline address-list row (per-coin drilldown). 0.6.35 layout: strictly
|
||
columnar so every row's fields line up in the same x positions no
|
||
matter how long each label happens to be. The address column is the
|
||
only flex one (minmax 0/1fr) — it fills whatever's left after the
|
||
fixed cells and truncates with an ellipsis, so a wider sidebar shows
|
||
more of the address without the label/balance jumping around. Every
|
||
other column has an explicit width — label pill is fixed to 68px so
|
||
"a" and "anthem…" occupy the same slot, amount is fixed to 90px so
|
||
"0" and "0.000123" right-align identically, actions are fixed to
|
||
46px. Net result: columns look like a table, not a flex mess. */
|
||
.wstrip .warow { display: grid;
|
||
grid-template-columns: 16px minmax(0,1fr) 22px 68px 90px 46px;
|
||
gap: 6px; align-items: center; padding: 4px 4px;
|
||
border-radius: 6px; border: 1px solid transparent; cursor: pointer; min-height: 28px; }
|
||
.wstrip .warow:hover { background: rgba(255,255,255,.04); }
|
||
.wstrip .warow.on { background: rgb(from var(--acid, #d6ff3d) r g b / .10);
|
||
border-color: rgb(from var(--acid, #d6ff3d) r g b / .35); }
|
||
.wstrip .warow .waaddr { font: 12px/1.15 ui-monospace, Consolas, monospace; color: var(--ink);
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
||
/* Copy chip anchored right after the address. Fixed 22px column so the
|
||
copy button sits at the same x on every row. */
|
||
.wstrip .warow .wacopy { background: transparent; border: 0; color: var(--dim); cursor: pointer;
|
||
padding: 2px 4px; border-radius: 4px; font-size: 11px; line-height: 1;
|
||
transition: color .12s; justify-self: start; }
|
||
.wstrip .warow .wacopy:hover { color: var(--acid, #d6ff3d); background: rgba(255,255,255,.06); }
|
||
.wstrip .warow .wacopy.copied { color: var(--acid, #d6ff3d); }
|
||
/* Label pill: fixed 68px column. Even an empty label renders an
|
||
invisible placeholder so the amount column stays put. Long labels
|
||
truncate with ellipsis inside the pill (max-width: 100% of column). */
|
||
.wstrip .warow .walabel { font-size: 11px; color: var(--mut);
|
||
padding: 1px 6px; border-radius: 999px;
|
||
background: rgba(255,255,255,.06);
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
max-width: 100%; box-sizing: border-box;
|
||
justify-self: center; }
|
||
.wstrip .warow .walabel:empty { visibility: hidden; }
|
||
/* Balance shares a single line with everything else — no vertical
|
||
amount/fiat stack. Ticker follows the number in a dim tone so the
|
||
row reads "0 BCH" at a glance. Right-aligned within the fixed
|
||
amount column so short and long numbers line up. */
|
||
.wstrip .warow .waamt { text-align: right; font-variant-numeric: tabular-nums;
|
||
font-size: 12.5px; color: var(--ink); white-space: nowrap;
|
||
display: inline-flex; align-items: baseline; gap: 4px;
|
||
justify-self: end; overflow: hidden; }
|
||
.wstrip .warow .waamt .watkr { color: var(--dim); font-size: 11px; font-weight: 500; }
|
||
.wstrip .warow .wact { background: transparent; border: 0; color: var(--dim); cursor: pointer;
|
||
padding: 2px 5px; border-radius: 4px; font-size: 12.5px; line-height: 1; }
|
||
.wstrip .warow .wact:hover { color: var(--acid, #d6ff3d); background: rgba(255,255,255,.06); }
|
||
/* Destructive strip action (remove wallet). Stays quiet until hovered so
|
||
a row of icons doesn't read as a row of warnings. */
|
||
.wstrip .wact.wactdel:hover { color: var(--danger, #f6768a); background: rgb(from var(--danger, #f6768a) r g b / .12); }
|
||
/* Per-address asset list (0.8.8). The count chip expands the row into a
|
||
nested list of what that ONE address holds beyond the native coin. */
|
||
.wstrip .waassets { background: rgba(255,255,255,.06); border: 0; color: var(--dim); cursor: pointer;
|
||
font: inherit; font-size: 10px; padding: 1px 6px; border-radius: 999px; line-height: 1.5; }
|
||
.wstrip .waassets:hover, .wstrip .waassets.on { color: var(--acid, #d6ff3d); background: rgb(from var(--acid, #d6ff3d) r g b / .14); }
|
||
.wstrip .waassetlist { padding: 2px 6px 6px 26px; display: flex; flex-direction: column; gap: 2px; }
|
||
.wstrip .waasset { display: grid; grid-template-columns: minmax(0,1fr) auto auto; gap: 8px; align-items: baseline;
|
||
font-size: 11px; color: var(--mut); padding: 2px 4px; border-radius: 4px; }
|
||
.wstrip .waasset:hover { background: rgba(255,255,255,.04); }
|
||
.wstrip .waasset .waaname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.wstrip .waasset .waaid { color: var(--dim); font-size: 10px; }
|
||
.wstrip .waasset .waaamt { font-variant-numeric: tabular-nums; color: var(--ink); }
|
||
/* Coin drilldown header: shows the coin's per-unit price + running
|
||
total of the addresses below, so the aggregate context isn't lost
|
||
when the user is deep in the per-address view. */
|
||
.wstrip .wcoinsub { display: flex; align-items: baseline; gap: 8px; padding: 2px 4px 5px 4px;
|
||
font-size: 11.5px; color: var(--mut); border-bottom: 1px solid var(--line);
|
||
margin-bottom: 3px; }
|
||
.wstrip .wcoinsub .wprice { color: var(--acid, #d6ff3d); font-weight: 600; font-variant-numeric: tabular-nums;
|
||
text-shadow: 0 0 5px rgb(from var(--acid, #d6ff3d) r g b / .30); }
|
||
.wstrip .wcoinsub .wsep { color: var(--dim); }
|
||
.wstrip .wcoinsub .wtot { color: var(--ink); font-variant-numeric: tabular-nums; font-weight: 500; }
|
||
.wstrip .wcoinsub .wtotfiat { color: var(--dim); font-variant-numeric: tabular-nums; }
|
||
/* Adapter-error line above the address rows. Shown only when at least
|
||
one wallet has a non-null .error — makes silent RPC failures visible
|
||
instead of the display quietly rendering 0. */
|
||
.wstrip .wcoinerr { color: #e05a5a; font-size: 11px; padding: 4px 6px;
|
||
background: rgba(224,90,90,.08); border-radius: 4px;
|
||
margin-bottom: 4px; overflow-wrap: anywhere; }
|
||
|
||
/* Full-panel lock screen — takes over the entire panel below the aegis
|
||
footer when the vault is locked or awaiting first-time setup. Rest of
|
||
the app (header picker, tabs, wallet strip) is hidden until unlocked
|
||
so nothing sensitive shows and there is no accidental interaction
|
||
surface. */
|
||
#lockScreen[hidden] { display: none; }
|
||
#lockScreen { position: absolute; inset: 0 0 30px 0; z-index: 50; background: var(--bg);
|
||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||
padding: 24px 18px; color: var(--ink); text-align: center; }
|
||
#lockScreen .aegisMark { width: 64px; height: 64px; margin-bottom: 14px; }
|
||
#lockScreen .aegisMark svg { width: 100%; height: 100%; color: var(--acid, #d6ff3d);
|
||
filter: drop-shadow(0 0 12px rgb(from var(--acid, #d6ff3d) r g b / .35)); }
|
||
#lockScreen h1 { font: 600 16px/1.3 inherit; margin: 0 0 4px 0; letter-spacing: .2px; }
|
||
#lockScreen .subhint { color: var(--mut); font-size: 12px; max-width: 320px; margin: 0 0 20px 0; }
|
||
#lockScreen .lockform { width: min(320px, 100%); display: flex; flex-direction: column; gap: 10px; text-align: left; }
|
||
#lockScreen .lockform input[type=password],
|
||
#lockScreen .lockform input[type=text],
|
||
#lockScreen .lockform textarea { text-align: center; }
|
||
#lockScreen .altline { color: var(--dim); font-size: 11.5px; margin-top: 12px; text-align: center; }
|
||
#lockScreen .altline a { color: var(--acid, #d6ff3d); cursor: pointer; text-decoration: none; }
|
||
#lockScreen .altline a:hover { text-decoration: underline; }
|
||
/* PIN pad — six dots + a 3x4 keypad. Used both in lock screen and in the
|
||
PIN approval modal. */
|
||
.pinpad { display: flex; flex-direction: column; align-items: center; gap: 14px; }
|
||
.pinpad .pindots { display: flex; gap: 12px; }
|
||
.pinpad .pindot { width: 12px; height: 12px; border-radius: 50%; border: 1.5px solid var(--dim);
|
||
background: transparent; transition: background .12s, border-color .12s; }
|
||
.pinpad .pindot.on { background: var(--acid, #d6ff3d); border-color: var(--acid, #d6ff3d);
|
||
box-shadow: 0 0 6px rgb(from var(--acid, #d6ff3d) r g b / .5); }
|
||
.pinpad .pinkeys { display: grid; grid-template-columns: repeat(3, 62px); gap: 8px; }
|
||
.pinpad .pinkeys button { height: 46px; border-radius: 10px; border: 1px solid var(--line);
|
||
background: var(--card); color: var(--ink); font: 500 18px inherit;
|
||
cursor: pointer; }
|
||
.pinpad .pinkeys button:hover { border-color: var(--acid, #d6ff3d); color: var(--acid, #d6ff3d); }
|
||
.pinpad .pinkeys button.util { background: transparent; font-size: 13px; color: var(--dim); }
|
||
.pinpad .pinerr { color: var(--danger); font-size: 12px; text-align: center; min-height: 16px; }
|
||
|
||
/* PIN modal overlay — used for set-PIN / change-PIN / verify-PIN flows. */
|
||
.pinmodal { position: fixed; inset: 0; background: rgba(0,0,0,.55); display: flex;
|
||
align-items: center; justify-content: center; z-index: 9999; padding: 20px; }
|
||
.pinmodal .pincard { width: min(94vw, 340px); background: var(--panel); border: 1px solid var(--line);
|
||
border-radius: 12px; padding: 18px 16px 14px; box-shadow: 0 10px 40px rgba(0,0,0,.4); }
|
||
.pinmodal h2 { margin: 0 0 6px 0; font: 600 15px inherit; }
|
||
.pinmodal .pinsub { color: var(--mut); font-size: 12px; margin-bottom: 12px; text-align: center; }
|
||
.pinmodal .pinactions { display: flex; gap: 6px; justify-content: center; margin-top: 12px; }
|
||
|
||
/* General settings cards — pinned at top of Settings tab so cross-cutting
|
||
security/policy controls stay in one place, ahead of the per-wallet
|
||
stuff below. */
|
||
.gsec { margin-bottom: 14px; }
|
||
.gsec .gtitle { font: 600 13px inherit; color: var(--ink); margin-bottom: 6px; }
|
||
.gsec .gline { display: flex; align-items: center; justify-content: space-between; gap: 10px;
|
||
padding: 6px 0; border-top: 1px solid var(--line); }
|
||
.gsec .gline:first-of-type { border-top: 0; }
|
||
.gsec .gline .glabel { min-width: 0; font-size: 12.5px; color: var(--ink); }
|
||
.gsec .gline .ghint { display: block; color: var(--dim); font-size: 11px; margin-top: 2px; }
|
||
.gsec .gline .gactions { flex: none; display: inline-flex; gap: 6px; }
|
||
.gsec .gsoon { font-size: 10px; padding: 1px 6px; border-radius: 999px; letter-spacing: .04em;
|
||
background: rgba(224,179,65,.14); color: #e0b341; text-transform: uppercase; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<div class="picker" id="pickerBtn">
|
||
<div class="t">
|
||
<span class="badge" id="hBadge"></span>
|
||
<span class="lbl" id="hLabel">Aegis Wallet</span>
|
||
<!-- Edit chip sits inline with the wallet name so it reads as
|
||
"edit THIS wallet". Was in picker-actions on the far right
|
||
until 0.7.2, which mixed poorly with the global + button. -->
|
||
<button type="button" id="hManage" class="editchip" title="Edit this wallet — rename, derivation path, remove">✎</button>
|
||
</div>
|
||
<div class="picker-actions">
|
||
<!-- Single right-corner chip. Opens a compact popover menu with
|
||
Create new / Import / Connect / About — replacing the old
|
||
three-chip cluster (+ ⋯ ✎). Method chosen there routes into
|
||
the coin picker inside #drop or an appropriate modal. -->
|
||
<button type="button" id="hAdd" class="chip" title="Add or import a wallet">+</button>
|
||
</div>
|
||
</div>
|
||
<!-- 0.8.4: network picker is its own row below the coin label so it
|
||
reads as "the network I'm on right now" instead of a tiny suffix
|
||
next to the wallet name. Click cycles / opens the network menu. -->
|
||
<div class="netrow" id="hNetRow" hidden>
|
||
<button type="button" class="netchip" id="hNet" title="Switch network"></button>
|
||
</div>
|
||
<div id="drop" hidden></div>
|
||
<div class="bal">
|
||
<div class="big">
|
||
<span id="balMain">—</span><small id="balTicker">—</small>
|
||
<span id="balFiat" class="fiat" hidden></span>
|
||
</div>
|
||
<div class="sub">
|
||
<span class="netlbl" id="netlbl">connecting…</span>
|
||
<span class="net"><span class="dot" id="dot"></span></span>
|
||
</div>
|
||
<div id="portfolio" class="portfolio" hidden></div>
|
||
</div>
|
||
</header>
|
||
<nav>
|
||
<button data-tab="receive" class="on">Receive</button>
|
||
<button data-tab="send">Send</button>
|
||
<button data-tab="history">History</button>
|
||
<button data-tab="settings">Settings</button>
|
||
</nav>
|
||
<!-- Always-visible wallet list. Sits under the Receive/Send/History/Settings
|
||
tab bar so the top of the panel stays about the SELECTED wallet, and
|
||
the list of siblings/switch-targets reads as a secondary layer below.
|
||
[+ Add] opens the Add-only picker; [⋯ More] opens Import/Connect/Manage. -->
|
||
<div id="walletStrip" class="wstrip" aria-label="Your wallets"></div>
|
||
<main>
|
||
<div id="gate" class="gate" hidden></div>
|
||
<div id="tabs">
|
||
<section id="tab-receive">
|
||
<!-- Segmented mode toggle (0.8.0). Switches the tab body between
|
||
the normal Receive view (QR + address) and the Consolidate
|
||
view (inline picker for sweeping other-wallet balances into
|
||
this one). Hidden when there is nothing to consolidate. -->
|
||
<div id="rcvModeToggle" class="modetoggle" hidden>
|
||
<button data-rcv-mode="receive" class="on" type="button">Receive</button>
|
||
<button data-rcv-mode="consolidate" type="button">Consolidate <span id="rcvConsolidateCount" class="hint"></span></button>
|
||
</div>
|
||
<div id="rcvNormal">
|
||
<div class="qrwrap"><canvas id="qr" width="200" height="200"></canvas></div>
|
||
<div class="card">
|
||
<div class="lbl">Receiving address <span id="addrMeta"></span></div>
|
||
<div class="mono" id="addr">—</div>
|
||
<div class="actions">
|
||
<button class="btn sm" id="copyAddr">Copy</button>
|
||
<button class="btn sm" id="nextAddr" hidden>Next unused address</button>
|
||
<button class="btn sm" id="viewAddr">Explorer</button>
|
||
<button class="btn sm" id="openFaucet" hidden>Faucet</button>
|
||
</div>
|
||
</div>
|
||
<div class="card" id="tokensCard" hidden style="margin-top:12px">
|
||
<div class="lbl">Tokens</div>
|
||
<div id="tokensList" class="kv"></div>
|
||
<div class="hint" id="tokensHint">Tokens held by this wallet.</div>
|
||
</div>
|
||
</div><!-- /rcvNormal -->
|
||
<!-- Consolidate view (inline, replaces Receive body when active). -->
|
||
<div id="rcvConsolidate" hidden>
|
||
<div id="rcvConsolidateInline"></div>
|
||
</div>
|
||
</section>
|
||
<section id="tab-send" hidden>
|
||
<!-- Send/Consolidate mode toggle (0.8.0). Same pattern as Receive. -->
|
||
<div id="sendModeToggle" class="modetoggle" hidden>
|
||
<button data-send-mode="send" class="on" type="button">Send</button>
|
||
<button data-send-mode="consolidate" type="button">Consolidate <span id="sendConsolidateCount" class="hint"></span></button>
|
||
</div>
|
||
<div id="sendNormal">
|
||
<!-- Legacy chip retained but hidden — 0.7.7's chip is replaced by
|
||
the mode toggle above. Kept in the DOM so existing panel.js
|
||
code that reads it doesn't NPE mid-migration. -->
|
||
<div id="consolidateChipWrap" hidden style="margin-bottom:12px">
|
||
<button id="consolidateChip" class="btn sm" type="button" style="width:100%;text-align:left;display:flex;align-items:center;gap:8px;justify-content:space-between">
|
||
<span>⇢ Consolidate balances into <b id="consolidateChipDest">this wallet</b></span>
|
||
<span class="hint" id="consolidateChipCount"></span>
|
||
</button>
|
||
</div>
|
||
<div class="field" id="sendAssetField" hidden>
|
||
<div class="lbl">Asset</div>
|
||
<select id="sendAsset"></select>
|
||
<div class="hint">Pick the native coin or an SPL token in this wallet.</div>
|
||
</div>
|
||
<div class="field">
|
||
<div class="lbl">Recipient</div>
|
||
<input type="text" id="sendTo" spellcheck="false" autocomplete="off" placeholder="…">
|
||
<div class="hint" id="sendToHint"></div>
|
||
</div>
|
||
<div class="field">
|
||
<div class="lbl">Amount <span id="sendAmtFiat" class="fiat" style="margin-left:8px" hidden></span></div>
|
||
<div class="amt">
|
||
<input type="text" id="sendAmt" inputmode="decimal" autocomplete="off" placeholder="0.00">
|
||
<div class="unit" id="unitPicker"></div>
|
||
<button class="btn sm" id="sendMax" type="button">Max</button>
|
||
</div>
|
||
</div>
|
||
<div class="field" id="feeField">
|
||
<div class="lbl">Fee</div>
|
||
<div class="fee"><input type="range" id="feeRate" min="1" max="5" step="1" value="1"><span class="v" id="feeLbl">1 sat/B</span></div>
|
||
</div>
|
||
<!-- Optional OP_RETURN memo. BCH-only for now (UTXO chains only);
|
||
the field hides when a non-BCH wallet is selected. 220 byte cap
|
||
keeps the tx under standardness relay policy. Memo is public on
|
||
the ledger — the placeholder text warns before someone types. -->
|
||
<div class="field" id="memoField" hidden>
|
||
<div class="lbl">Memo <span class="hint" style="margin-left:8px;font-weight:normal">optional · public on-chain · ≤220 bytes</span></div>
|
||
<input type="text" id="sendMemo" maxlength="220" spellcheck="false" autocomplete="off"
|
||
placeholder="e.g. Invoice #1234 — visible to anyone">
|
||
</div>
|
||
<div class="card">
|
||
<div class="summary">
|
||
<div class="k">Amount</div><div class="v" id="sumAmt">—</div>
|
||
<div class="k">Network fee</div><div class="v" id="sumFee">—</div>
|
||
<div class="k">Total</div><div class="v" id="sumTotal">—</div>
|
||
</div>
|
||
</div>
|
||
<div class="actions"><button class="btn primary" id="sendBtn" disabled>Send</button></div>
|
||
<div class="msg" id="sendMsg" hidden></div>
|
||
</div><!-- /sendNormal -->
|
||
<div id="sendConsolidate" hidden>
|
||
<div id="sendConsolidateInline"></div>
|
||
</div>
|
||
</section>
|
||
<section id="tab-history" hidden>
|
||
<div id="txlist"></div>
|
||
</section>
|
||
<section id="tab-settings" hidden>
|
||
<!-- 0.8.2: Settings sectioned. Chip row at top picks which section
|
||
is visible; each section wraps a group of related cards. The
|
||
chain-specific cards (bchSettings / trxSettings / …) sit
|
||
inside the "Wallet" section and their own hidden-vs-shown
|
||
toggle (per selected chain) still applies within it. -->
|
||
<div class="setsecnav" id="setsecnav">
|
||
<button data-setsec="security" class="on" type="button">Security</button>
|
||
<button data-setsec="session" type="button">Session</button>
|
||
<button data-setsec="wallet" type="button">Wallet</button>
|
||
<button data-setsec="prices" type="button">Prices</button>
|
||
<button data-setsec="sites" type="button">Sites</button>
|
||
<button data-setsec="about" type="button">About</button>
|
||
</div>
|
||
<div data-setsec-body="security">
|
||
<!-- Cross-cutting security / policy controls, ahead of anything
|
||
per-wallet or chain-specific. Present even when the vault is
|
||
still locked so users can set up a PIN or read the multi-sig
|
||
roadmap without unlocking first (they only do the ACTUAL PIN
|
||
enrollment after a fresh unlock, though). -->
|
||
<div class="card gsec" id="genSecurity" style="margin-bottom:14px">
|
||
<div class="gtitle">Security</div>
|
||
<div class="gline">
|
||
<div class="glabel">
|
||
Quick-access PIN
|
||
<span class="ghint" id="pinStatusHint">Off — Aegis asks for the master password every time.</span>
|
||
</div>
|
||
<div class="gactions">
|
||
<button class="btn sm" id="gsPinSet" hidden>Set PIN…</button>
|
||
<button class="btn sm" id="gsPinChange" hidden>Change…</button>
|
||
<button class="btn sm danger" id="gsPinRemove" hidden>Remove</button>
|
||
</div>
|
||
</div>
|
||
<div class="gline" id="gsRequirePinLine" hidden>
|
||
<div class="glabel">
|
||
Require PIN for sending
|
||
<span class="ghint">Prompts for your PIN on every panel-initiated Send. Dapp-driven approvals still use the standard approval overlay.</span>
|
||
</div>
|
||
<div class="gactions">
|
||
<label class="switch"><input type="checkbox" id="gsRequirePin"><span></span></label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /security section (multi-sig card lives inside it below) -->
|
||
<div data-setsec-body="session" hidden>
|
||
<!-- Session: stay-signed-in + idle auto-lock + manual sign-out.
|
||
Uses electron.safeStorage under the hood so the master password
|
||
is only decryptable under this OS user account. When "Lock on
|
||
Navigator close" is on (the default), Aegis stores nothing on
|
||
disk and forces a fresh unlock on every launch. -->
|
||
<div class="card gsec" id="genSession" style="margin-bottom:14px">
|
||
<div class="gtitle">Session</div>
|
||
<div class="gline">
|
||
<div class="glabel">
|
||
Lock on Navigator close
|
||
<span class="ghint" id="gsSessionHint">On — Aegis asks for the master password (or PIN) every time Theseus starts. Turn off to stay signed in across restarts via the OS keystore.</span>
|
||
</div>
|
||
<div class="gactions">
|
||
<label class="switch"><input type="checkbox" id="gsLockOnClose" checked><span></span></label>
|
||
</div>
|
||
</div>
|
||
<div class="gline">
|
||
<div class="glabel">
|
||
Auto-lock when idle
|
||
<span class="ghint">Locks the vault after this long with no panel activity. Applies inside the wallet panel; a locked panel elsewhere in the browser doesn't count as idle.</span>
|
||
</div>
|
||
<div class="gactions">
|
||
<select id="gsIdleMinutes" style="padding:5px 8px;border-radius:6px;background:var(--panel);border:1px solid var(--line);color:var(--ink);font-size:12px">
|
||
<option value="0">Never</option>
|
||
<option value="5">5 min</option>
|
||
<option value="15" selected>15 min</option>
|
||
<option value="30">30 min</option>
|
||
<option value="60">1 hour</option>
|
||
<option value="180">3 hours</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="gline">
|
||
<div class="glabel">
|
||
Sign out now
|
||
<span class="ghint">Locks the vault immediately. Any dapp connections stay paired, but Aegis will refuse to sign until you unlock again.</span>
|
||
</div>
|
||
<div class="gactions">
|
||
<button class="btn sm danger" id="gsSignOut">Sign out</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card gsec" id="genMasterPw" style="margin-bottom:14px">
|
||
<div class="gtitle">Master password</div>
|
||
<div class="gline">
|
||
<div class="glabel">
|
||
Change master password
|
||
<span class="ghint">Opens Theseus <span class="mono">Settings › Passwords</span>. The vault re-encrypts under the new password; every derived wallet keeps working.</span>
|
||
</div>
|
||
<div class="gactions">
|
||
<button class="btn sm" id="gsOpenPasswords">Open Passwords…</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><!-- /session section -->
|
||
|
||
<div data-setsec-body="security" hidden>
|
||
<div class="card gsec" id="genMultiSig" style="margin-bottom:14px">
|
||
<div class="gtitle">Second-device approval <span class="gsoon">soon</span></div>
|
||
<div class="gline">
|
||
<div class="glabel">
|
||
Co-sign sends from a second device
|
||
<span class="ghint">Aegis will pair with Ariadne on your phone so large transfers need a nod from both places before they broadcast. Not shipped yet.</span>
|
||
</div>
|
||
<div class="gactions">
|
||
<button class="btn sm" disabled title="Not shipped yet">Set up…</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><!-- /security-multisig -->
|
||
|
||
<div data-setsec-body="wallet" hidden>
|
||
<div class="card" id="walletManage" style="margin-bottom:14px">
|
||
<div class="lbl">This wallet</div>
|
||
<div class="field" style="margin-top:6px;margin-bottom:8px">
|
||
<input type="text" id="renameLabel" placeholder="Wallet name">
|
||
</div>
|
||
<div class="actions">
|
||
<button class="btn sm" id="renameBtn">Rename</button>
|
||
<button class="btn sm danger" id="removeBtn">Remove wallet</button>
|
||
</div>
|
||
<div class="hint" id="removeHint"></div>
|
||
</div>
|
||
|
||
<div id="bchSettings" hidden>
|
||
<div class="field">
|
||
<div class="lbl">Derivation path (account)</div>
|
||
<input type="text" id="setPath" spellcheck="false" placeholder="m/44'/145'/0'">
|
||
<div class="hint">Changing this switches to a different set of addresses under the same wallet seed.</div>
|
||
</div>
|
||
<div class="field" id="bchServersRow">
|
||
<div class="lbl">Electrum servers <span class="hint" style="font-weight:normal">(BCH mainnet — shared across BCH wallets)</span></div>
|
||
<div id="setServersList" class="serverlist"></div>
|
||
<details style="margin-top:6px">
|
||
<summary style="cursor:pointer;color:var(--dim);font-size:11.5px">Add a custom server…</summary>
|
||
<div style="display:flex;gap:6px;margin-top:6px">
|
||
<input type="text" id="setServersCustom" spellcheck="false" placeholder="wss://host:port" style="flex:1">
|
||
<button class="btn sm" id="addCustomServer" type="button">Add</button>
|
||
</div>
|
||
</details>
|
||
<div class="hint" id="serverHint"></div>
|
||
</div>
|
||
<div class="actions">
|
||
<button class="btn primary" id="applySettings">Apply</button>
|
||
<button class="btn" id="resetServers">Reset servers</button>
|
||
</div>
|
||
<div class="card" style="margin-top:16px">
|
||
<div class="lbl">Recovery info</div>
|
||
<div class="hint">Keys come from your Theseus password vault under <span class="mono" id="purpose"></span>. The same vault seed on another machine recreates this wallet.</div>
|
||
<div class="kv" id="recovery"></div>
|
||
<div class="actions">
|
||
<button class="btn" id="showXpub">Show account xpub</button>
|
||
<button class="btn danger" id="showXprv">Show account private key</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card" style="margin-top:16px" id="wcCard">
|
||
<div class="lbl">WizardConnect</div>
|
||
<div class="hint" style="margin-bottom:8px">
|
||
Pair this BCH wallet with a dapp that speaks the WizardConnect protocol
|
||
(Cauldron, Moria, or any site built on the SDK). Paste the <span class="mono">wiz://</span>
|
||
URI the dapp shows in its Connect dialog. Aegis signs every transaction only after you approve it.
|
||
</div>
|
||
<!-- Warning that appears when the selected wallet is imported —
|
||
WC signing needs the derive-based signer path, which imported
|
||
wallets don't have yet. Shown in place of the input so users
|
||
don't try to paste a URI and hit "wallet not ready". -->
|
||
<div class="msg err" id="wcImportedNotice" hidden style="margin-bottom:8px">
|
||
WizardConnect isn't available for imported wallets yet — pairing
|
||
uses Aegis' vault-derived signer path, and imported wallets are
|
||
read-only for now. Coming in a later release.
|
||
</div>
|
||
<div id="wcInputs">
|
||
<div class="field" style="margin-top:8px">
|
||
<input type="text" id="wcUri" spellcheck="false" placeholder="wiz://?p=…&s=…">
|
||
</div>
|
||
<div class="actions">
|
||
<button class="btn primary" id="wcConnectBtn">Connect</button>
|
||
</div>
|
||
</div>
|
||
<div class="msg" id="wcMsg" hidden></div>
|
||
<div class="kv" id="wcSites" style="margin-top:8px"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="trxSettings" hidden>
|
||
<div class="card">
|
||
<div class="lbl">Recovery info</div>
|
||
<div class="hint">Keys come from your Theseus password vault under <span class="mono" id="trxPurpose"></span>. Import into TronLink with the derivation path <span class="mono">m/44'/195'/0'/0/0</span> from the same vault seed.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="scSettings" hidden>
|
||
<div class="field">
|
||
<div class="lbl">walletd URL</div>
|
||
<input type="text" id="setWalletdUrl" spellcheck="false" placeholder="https://your-walletd.example/api">
|
||
<div class="hint">Any public or self-hosted <span class="mono">go.sia.tech/walletd</span> in "full" index mode. The URL is per-wallet, so different Sia sub-accounts can point at different nodes. It is not shared with anyone else.</div>
|
||
</div>
|
||
<div class="actions">
|
||
<button class="btn primary" id="applyWalletdUrl">Apply</button>
|
||
</div>
|
||
<div class="card" style="margin-top:16px">
|
||
<div class="lbl">Recovery info</div>
|
||
<div class="hint">Keys come from your Theseus password vault under <span class="mono" id="scPurpose"></span>. Address scheme: walletd <span class="mono">KeyFromSeed(seed, index)</span>.</div>
|
||
<div class="kv" id="scRecovery"></div>
|
||
<div class="actions">
|
||
<button class="btn danger" id="showScSeed">Reveal wallet seed</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="dgbSettings" hidden>
|
||
<div class="field">
|
||
<div class="lbl">Address family</div>
|
||
<select id="setDgbFamily"></select>
|
||
<div class="hint">Picks the BIP purpose that shapes your DGB addresses. Switching rebuilds the wallet against a different set of addresses under the same seed — old funds don't move; they still live under the family they were received on.</div>
|
||
</div>
|
||
<div class="field">
|
||
<div class="lbl">Derivation path (account)</div>
|
||
<input type="text" id="setDgbPath" spellcheck="false" placeholder="m/84'/20'/0'">
|
||
<div class="hint">Auto-filled from the family above. Edit only if you need a non-default account.</div>
|
||
</div>
|
||
<div class="actions">
|
||
<button class="btn primary" id="applyDgbPath">Apply</button>
|
||
</div>
|
||
<div class="card" style="margin-top:16px">
|
||
<div class="lbl">Recovery info</div>
|
||
<div class="hint">Keys come from your Theseus password vault under <span class="mono" id="dgbPurpose"></span>. Any BIP39 tool set to <span class="mono">DGB</span> (coin type 20) at the same purpose can reproduce this wallet.</div>
|
||
<div class="kv" id="dgbRecovery"></div>
|
||
<div class="actions">
|
||
<button class="btn" id="showDgbXpub">Show account xpub</button>
|
||
<button class="btn danger" id="showDgbXprv">Show account private key</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="btcSettings" hidden>
|
||
<div class="field">
|
||
<div class="lbl">Address family</div>
|
||
<select id="setBtcFamily"></select>
|
||
<div class="hint">Picks the BIP purpose that shapes your Bitcoin addresses. Switching rebuilds the wallet against a different set of addresses under the same seed — old funds don't move; they still live under the family they were received on.</div>
|
||
</div>
|
||
<div class="field">
|
||
<div class="lbl">Derivation path (account)</div>
|
||
<input type="text" id="setBtcPath" spellcheck="false" placeholder="m/84'/0'/0'">
|
||
<div class="hint">Auto-filled from the family above. Edit only if you need a non-default account.</div>
|
||
</div>
|
||
<div class="actions">
|
||
<button class="btn primary" id="applyBtcPath">Apply</button>
|
||
</div>
|
||
<div class="card" style="margin-top:16px">
|
||
<div class="lbl">Recovery info</div>
|
||
<div class="hint">Keys come from your Theseus password vault under <span class="mono" id="btcPurpose"></span>. Any BIP39 tool at coin type 0 (mainnet) / 1 (testnet) and the same purpose can reproduce this wallet.</div>
|
||
<div class="kv" id="btcRecovery"></div>
|
||
<div class="actions">
|
||
<button class="btn" id="showBtcXpub">Show account xpub</button>
|
||
<button class="btn danger" id="showBtcXprv">Show account private key</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="ethSettings" hidden>
|
||
<div class="field">
|
||
<div class="lbl">RPC URL</div>
|
||
<input type="text" id="setEthRpcUrl" spellcheck="false" placeholder="https://cloudflare-eth.com">
|
||
<div class="hint">JSON-RPC endpoint Aegis reads balances and broadcasts from. Any provider works — public gateways (Cloudflare, PublicNode), Alchemy, Infura, or your own node. Stored per-wallet; not shared.</div>
|
||
</div>
|
||
<div class="actions">
|
||
<button class="btn primary" id="applyEthRpc">Apply</button>
|
||
</div>
|
||
<div class="card" style="margin-top:16px">
|
||
<div class="lbl">Recovery info</div>
|
||
<div class="hint">Keys come from your Theseus password vault under <span class="mono" id="ethPurpose"></span>. Import into MetaMask / any Ethereum wallet using the derivation path <span class="mono">m/44'/60'/0'/0/0</span> from the same vault seed.</div>
|
||
<div class="kv" id="ethRecovery"></div>
|
||
<div class="actions">
|
||
<button class="btn danger" id="showEthKey">Reveal private key</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="solSettings" hidden>
|
||
<div class="field">
|
||
<div class="lbl">RPC URL</div>
|
||
<input type="text" id="setSolRpcUrl" spellcheck="false" placeholder="https://api.mainnet-beta.solana.com">
|
||
<div class="hint">JSON-RPC endpoint. The public Solana RPCs are heavily rate-limited — for real use point Aegis at Helius / QuickNode / your own node.</div>
|
||
</div>
|
||
<div class="actions">
|
||
<button class="btn primary" id="applySolRpc">Apply</button>
|
||
</div>
|
||
<div class="card" style="margin-top:16px">
|
||
<div class="lbl">Recovery info</div>
|
||
<div class="hint">Keys come from your Theseus password vault under <span class="mono" id="solPurpose"></span>. Import into Phantom / Solflare with the derivation path <span class="mono">m/44'/501'/0'/0'</span> from the same vault seed.</div>
|
||
<div class="kv" id="solRecovery"></div>
|
||
<div class="actions">
|
||
<button class="btn danger" id="showSolKey">Reveal wallet seed</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /wallet section -->
|
||
|
||
<div data-setsec-body="prices" hidden>
|
||
<div class="card" style="margin-top:0">
|
||
<div class="lbl">Fiat prices</div>
|
||
<div class="hint" style="margin-bottom:10px">
|
||
Off by default. When enabled, Aegis polls every supported oracle in
|
||
parallel and reconciles the results — two or more sources agreeing
|
||
within ±3% form the trusted price, so no single oracle can quietly
|
||
make Aegis show a wrong number. Every enabled oracle sees your IP
|
||
+ a User-Agent every poll, which is a signal that a wallet is open
|
||
on this machine.
|
||
</div>
|
||
<div class="actions" style="align-items:center;gap:12px">
|
||
<label class="switch">
|
||
<input type="checkbox" id="pricesToggle">
|
||
<span>Enable USD prices</span>
|
||
</label>
|
||
<button class="btn sm" id="refreshPrices" hidden>Refresh now</button>
|
||
<span class="hint" id="pricesStatus" style="margin-left:auto"></span>
|
||
</div>
|
||
<!-- Per-source status: which oracles are up, which are down, and
|
||
the last per-chain reconciliation method (majority / median /
|
||
single). Populated from the priceFeed snapshot. -->
|
||
<div id="pricesSources" class="hint" style="margin-top:10px"></div>
|
||
</div>
|
||
<!-- Hidden legacy select so panel.js code that reads .value doesn't
|
||
NPE while we transition; select stays hidden and empty. -->
|
||
<select id="pricesSource" hidden></select>
|
||
<span id="pricesSourceHint" hidden></span>
|
||
</div><!-- /prices section -->
|
||
|
||
<div data-setsec-body="sites" hidden>
|
||
<div class="card" style="margin-top:0">
|
||
<div class="lbl">Connected sites</div>
|
||
<div class="hint">Sites allowed to see your address, allowances for silent BCH payments, and Tron dapps you've connected. Message signing always asks.</div>
|
||
<div id="sites" class="kv"></div>
|
||
</div>
|
||
</div><!-- /sites section -->
|
||
|
||
<div data-setsec-body="about" hidden>
|
||
<div class="card" style="margin-top:0">
|
||
<div class="lbl">About Aegis</div>
|
||
<div class="hint" style="margin-bottom:10px">
|
||
Aegis is Silent Mode's built-in multi-chain wallet. Keys are derived
|
||
from your Theseus vault — same vault, every wallet across every
|
||
chain. Aegis lives at <a class="link" id="aboutOpenAegisSite">aegis.x</a> and
|
||
this build's version + update chip sit at the bottom-right of the
|
||
panel.
|
||
</div>
|
||
<div class="hint">
|
||
Silent Mode — <a class="link" id="aboutOpenSilentmodeSite">silentmode.st</a> ·
|
||
docs on the plugin system live at <span class="mono">theseus.x/plug-ins</span>.
|
||
</div>
|
||
</div>
|
||
</div><!-- /about section -->
|
||
<div class="msg err" id="settingsMsg" hidden></div>
|
||
</section>
|
||
</div>
|
||
</main>
|
||
<!-- Full-panel lock screen. Absolutely positioned so it takes over the
|
||
entire content area (everything above the aegis footer) whenever the
|
||
vault is locked or awaiting first-time setup — the header picker, nav
|
||
tabs, and wallet strip stay in the DOM but sit visually under it. The
|
||
Settings tab still hides itself; nothing here interacts with it. -->
|
||
<div id="lockScreen" hidden>
|
||
<div class="aegisMark" aria-hidden="true">
|
||
<svg viewBox="0 0 32 32" fill="none">
|
||
<polygon points="16,2 28,9 28,23 16,30 4,23 4,9" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/>
|
||
<circle cx="16" cy="16" r="4.5" fill="none" stroke="currentColor" stroke-width="1.4"/>
|
||
<circle cx="16" cy="16" r="1.6" fill="currentColor"/>
|
||
</svg>
|
||
</div>
|
||
<h1 id="lockTitle">Unlock Aegis</h1>
|
||
<div class="subhint" id="lockSub">Aegis derives its keys from your Theseus vault. There's nothing separate to unlock — the vault is your wallet.</div>
|
||
<div id="lockBody"></div>
|
||
</div>
|
||
<footer class="brandfoot" id="brandFoot">
|
||
<a href="#" id="brandLink" class="brandlink" title="Open aegis.x">
|
||
<svg viewBox="0 0 32 32" width="14" height="14" aria-hidden="true"><polygon points="16,2 28,9 28,23 16,30 4,23 4,9" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/><circle cx="16" cy="16" r="4.3" fill="none" stroke="currentColor" stroke-width="1.4"/><circle cx="16" cy="16" r="1.3" fill="currentColor"/></svg>
|
||
<span>aegis.x</span>
|
||
</a>
|
||
<!-- Update controls (0.8.1): the update chip lives INSIDE the right-side
|
||
group, sharing the slot with the version marker. paintFooterUpdate()
|
||
hides brandVer when a newer build is available and shows brandUpdate
|
||
in its place — clicking the acid-green "↑ v0.8.1" text stages the
|
||
download and relaunches Theseus. Idle: brandVer visible, brandUpdate
|
||
hidden. Same one-click Update/Install path the user asked for, at
|
||
the exact spot they identified. -->
|
||
<span class="brandfoot-right">
|
||
<button id="brandCheck" class="brandcheck" type="button" title="Check for updates">↻</button>
|
||
<span id="brandUpdate" class="brandupd" hidden></span>
|
||
<span class="brandver" id="brandVer"></span>
|
||
</span>
|
||
</footer>
|
||
<script src="qr.js"></script>
|
||
<script src="panel.js"></script>
|
||
</body>
|
||
</html>
|