From dc42daaf139685aac3421a3aa8386893ff872d8b Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 2 Sep 2026 17:30:19 -0700 Subject: The 200ms of secp256k1 hiding in every repaint: the depth advisory priced a full uncooperative exit — every hop of every coin, an EC tweak per hop — on each wallet render; the estimate now memoizes on coin set + feerate, and decoded vtxos cache by id (bytes are immutable). Profiled on a real phone: point add/double/wNAF was 1.3s of a 4.3s six-tab-switch trace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr --- src/ark/manager.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/ark') diff --git a/src/ark/manager.js b/src/ark/manager.js index 9731dd6..a190480 100644 --- a/src/ark/manager.js +++ b/src/ark/manager.js @@ -187,7 +187,16 @@ export class ArkManager { }); return true; } - _decoded(v) { return decodeVtxo(hex.decode(v.bytes)); } + _decoded(v) { + // vtxo bytes are immutable per id — parse once. The depth advisory and + // fee estimates decode every coin on every render without this. + const hit = this._decodeCache && this._decodeCache.get(v.id); + if (hit) return hit; + const d = decodeVtxo(hex.decode(v.bytes)); + (this._decodeCache ||= new Map()).set(v.id, d); + if (this._decodeCache.size > 200) this._decodeCache.delete(this._decodeCache.keys().next().value); + return d; + } // ---- chain adapter (esplora REST, same API the wallet already speaks) ---- // -- cgit v1.2.3