From 1be352dad6a594e1cd7d63b37087aef1fe161ca1 Mon Sep 17 00:00:00 2001 From: Local Dev Date: Wed, 23 Sep 2026 01:17:33 +0200 Subject: [PATCH] =?UTF-8?q?chore(aegis):=200.9.2=20=E2=80=94=20Receive=20t?= =?UTF-8?q?ab=20reorder,=20one=20balance,=20token=20history?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Receive was ordered QR → address → tokens, so 200px of always-on QR sat above the thing people came for and pushed the asset list off screen. - Address first, with Copy and a QR button; the QR expands inline and the choice sticks, because someone who receives by QR wants it every time and someone who copies never does. - Explorer and Faucet moved up to the header status row. They act on the selected wallet, not on the act of receiving, and down there they competed with Copy for the one row that gets used. - Assets card renamed from Tokens and now leads with the native coin, so "what does this wallet hold" is one list rather than two places. - "+ Add another " moved below the address list. The balance appeared three times — header, drilldown subtitle, address row. Now once in the header; the subtitle keeps only the per-unit price, and the per-address amount returns when a coin actually has more than one address to compare. The address row drops its truncated address (the full one is at the top of Receive) and keeps the wallet name. The per-address asset list added in 0.8.8 duplicated the Assets card and is removed — assets live in one place. Token amounts were unreadable: an 18-decimal balance rendered as 60000000.000000005435817984. Capped to 8 decimals with thousands separators, exact value on hover. A symbol claimed by more than one contract now carries a LOOK-ALIKE tag. The test wallet holds four different contracts all calling themselves "Test USDT" — spam mints borrowing a trusted ticker so a careless send lands on the wrong one. We can't tell which is genuine, so we mark every member of the clash rather than guessing. History showed native transfers only, so a wallet that had only ever moved USDT looked empty. TRC20 transfers are merged in newest-first, each carrying its own decimals and ticker (rendering a token against the chain's scale would be off by orders of magnitude). Both feeds are on by default; the checkboxes narrow rather than opt in, and the last one checked can't be unchecked into an empty list. --- bundled-addons/aegis/addon.json | 2 +- .../aegis/lib/chain-generic-imported.js | 41 +++- bundled-addons/aegis/panel.html | 51 +++- bundled-addons/aegis/panel.js | 221 +++++++++++------- 4 files changed, 220 insertions(+), 95 deletions(-) diff --git a/bundled-addons/aegis/addon.json b/bundled-addons/aegis/addon.json index 63f66378..7ff71e12 100644 --- a/bundled-addons/aegis/addon.json +++ b/bundled-addons/aegis/addon.json @@ -1,7 +1,7 @@ { "id": "aegis", "name": "Aegis Wallet", - "version": "0.9.1", + "version": "0.9.2", "category": "plugin", "description": "Multi-chain wallet (BCH, BTC, TRX, ETH, SOL, SC, DGB) derived from your Theseus vault. Dapps get window.bitcoincash on .x sites; window.tronWeb / window.tronLink / window.ethereum / window.solana on any https page.", "author": "Silent Mode", diff --git a/bundled-addons/aegis/lib/chain-generic-imported.js b/bundled-addons/aegis/lib/chain-generic-imported.js index c170c433..9b4ff497 100644 --- a/bundled-addons/aegis/lib/chain-generic-imported.js +++ b/bundled-addons/aegis/lib/chain-generic-imported.js @@ -150,7 +150,45 @@ module.exports = function makeGenericImportedAdapter() { const j = await r.json(); return String(j?.balance || 0); }, - async fetchHistory({ rpc, address }) { + // Native TRX transfers AND TRC20 token transfers, merged newest-first + // and each tagged with `asset` so the History tab can filter. Token + // movement is invisible in the native feed — a wallet that only ever + // moved USDT looked like it had no history at all. + async fetchHistory(opts) { + const [native, tokens] = await Promise.all([ + CHAIN_CFGS.trx._fetchNativeHistory(opts), + CHAIN_CFGS.trx._fetchTokenHistory(opts).catch(() => []), + ]); + return [...native, ...tokens] + .sort((a, b) => (b.time || 0) - (a.time || 0)) + .slice(0, 40); + }, + async _fetchTokenHistory({ rpc, address }) { + const r = await fetch(`${rpc.replace(/\/+$/, "")}/v1/accounts/${encodeURIComponent(address)}/transactions/trc20?limit=25`); + if (!r.ok) throw new Error(`Tron trc20 history HTTP ${r.status}`); + const j = await r.json(); + const list = Array.isArray(j?.data) ? j.data : []; + const me = String(address); + return list.map((t) => { + const ti = t.token_info || {}; + const outgoing = String(t.from || "") === me; + const raw = String(t.value || "0"); + return { + txid: t.transaction_id, + time: Math.floor(Number(t.block_timestamp || 0) / 1000), + confirmations: 1, + status: "confirmed", + // Token amounts are in the TOKEN's own decimals, not the + // chain's, so they travel with their own scale rather than + // being rendered against the native one. + delta: (outgoing ? "-" : "") + raw, + assetDecimals: Number.isFinite(Number(ti.decimals)) ? Number(ti.decimals) : 0, + asset: cleanTokenText(ti.symbol) || "token", + kind: "TRC20", + }; + }).filter((t) => t.txid); + }, + async _fetchNativeHistory({ rpc, address }) { const r = await fetch(`${rpc.replace(/\/+$/, "")}/v1/accounts/${encodeURIComponent(address)}/transactions?limit=25`); if (!r.ok) throw new Error(`Tron history HTTP ${r.status}`); const j = await r.json(); @@ -171,6 +209,7 @@ module.exports = function makeGenericImportedAdapter() { status: ok ? "confirmed" : "failed", // Aegis renders `delta` in the wallet's base unit (sun here). delta: c?.type === "TransferContract" ? (outgoing ? -amount : amount) : 0, + asset: null, // null = the chain's native coin kind: c?.type || "Contract", }; }).filter((t) => t.txid); diff --git a/bundled-addons/aegis/panel.html b/bundled-addons/aegis/panel.html index da094776..44291c13 100644 --- a/bundled-addons/aegis/panel.html +++ b/bundled-addons/aegis/panel.html @@ -35,8 +35,8 @@ .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; } + .bal .sub { color: var(--dim); font-size: 11.5px; display: flex; align-items: center; gap: 8px; } + .bal .sub .netlbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; } /* 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 @@ -79,6 +79,16 @@ #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; } + .histfilter { display: flex; align-items: center; gap: 14px; padding: 0 2px 10px; + border-bottom: 1px solid var(--line); margin-bottom: 8px; font-size: 12px; } + .histfilter[hidden] { display: none; } + /* Assets card rows (0.9.2). The native coin leads the list; a symbol + claimed by several contracts gets a LOOK-ALIKE tag so a borrowed + ticker can't pass for the real token. */ + .tx.asset { padding: 7px 8px; border-radius: 6px; } + .tx.asset:hover { background: rgba(255,255,255,.04); } + .tx.asset.native { background: rgb(from var(--acid, #d6ff3d) r g b / .06); } + .ttag.tdupe { background: rgba(224,90,90,.18); color: #f6768a; cursor: help; } .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 @@ -99,6 +109,13 @@ #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; } + /* Per-wallet actions promoted into the header's status row (0.9.2). */ + .hdracts { margin-left: auto; display: inline-flex; gap: 4px; } + .hdract { background: transparent; border: 1px solid var(--line); color: var(--dim); + border-radius: 999px; padding: 1px 9px; font: inherit; font-size: 10.5px; + cursor: pointer; line-height: 1.5; } + .hdract:hover { border-color: var(--acid, #d6ff3d); color: var(--acid, #d6ff3d); } + .hdract[hidden] { display: none; } .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; } @@ -198,7 +215,8 @@ .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; } + .qrwrap { display: grid; place-items: center; padding: 12px; background: #fff; border-radius: 10px; margin-top: 12px; } + .qrwrap[hidden] { display: none; } 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; } @@ -567,6 +585,14 @@
connecting… + + + + +
@@ -595,19 +621,22 @@
-
+
Receiving address
—
+ - -
+
@@ -679,6 +708,14 @@