aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/ark.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-10 07:09:45 -0700
committerAdam Soltys <[email protected]>2026-09-10 07:09:45 -0700
commit6113cf567fa0830233d5c3d524361f24a3f78caa (patch)
treef5ce3bf5e45602547d983797b57b94c8d7ae7dc5 /src/features/ark.js
parent435e9886620deff3d66286e3b85e97ed8f5fae53 (diff)
downloadcoinosv3-6113cf567fa0830233d5c3d524361f24a3f78caa.tar.gz
coinosv3-6113cf567fa0830233d5c3d524361f24a3f78caa.zip
Ark: persist vtxo bytes as base64 (a third smaller than hex); hex still read, hex still on the wire.
The live coins' signed bytes are most of a deep wallet's state — 560KB of hex, which localStorage then holds as UTF-16. vtxoBytesToStr/FromStr in proto.js persist base64 and read either form, _addVtxo writes base64, and pruneArkState converts hex to base64 on every save, so an existing state migrates itself the first time it saves. Measured on a live deep wallet: 904KB → 665KB (-26%), all 41 coins decoding identically. The sync wire (slimArkForSync) keeps sending hex for now: a device still on an older build would otherwise fail to decode every coin merged from a newer one. Flip it once pre-2026-09-10 builds are gone. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01Nw1Dijik1tLVKRM1WkU7xE
Diffstat (limited to 'src/features/ark.js')
-rw-r--r--src/features/ark.js12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/features/ark.js b/src/features/ark.js
index a5264ad..1dcfa8c 100644
--- a/src/features/ark.js
+++ b/src/features/ark.js
@@ -10,7 +10,7 @@ import { ArkManager } from '../ark/manager.js';
import { loadBg, saveBg, buildBg, disarmSiblingRecords } from '../nwc-bg.js';
import { boardFee, p2trAddress } from '../ark/board.js';
import { maybeBolt11, maybeLnInvoice, lnSendFee } from '../ark/lightning.js';
-import { decodeVtxo, getVtxoStatus, VTXO_STATE_SPENT, concatBytes } from '../ark/proto.js';
+import { decodeVtxo, getVtxoStatus, VTXO_STATE_SPENT, concatBytes, vtxoBytesFromStr, vtxoBytesToHex } from '../ark/proto.js';
import { signedExitTxs, exitTxVsizes, buildBumpChild, buildExitClaim, submitPackage } from '../ark/exit.js';
import { utxoId } from '../wallet.js';
import {
@@ -65,7 +65,7 @@ export function installArkWallet(wallet) {
_arkVtxoOwner(st) {
const v = (st?.vtxos || []).find((x) => x.bytes);
if (!v) return null;
- try { return decodeVtxo(hex.decode(v.bytes)).serverPubkey; } catch { return null; }
+ try { return decodeVtxo(vtxoBytesFromStr(v.bytes)).serverPubkey; } catch { return null; }
},
// Park state under the server that actually owns it, until the URL for
// that server is selected and can adopt it.
@@ -116,7 +116,7 @@ export function installArkWallet(wallet) {
let owner = st.serverPubkey || null;
if (!owner) {
const v = (st.vtxos || []).find((x) => x.bytes);
- if (v) { try { owner = decodeVtxo(hex.decode(v.bytes)).serverPubkey; } catch {} }
+ if (v) { try { owner = decodeVtxo(vtxoBytesFromStr(v.bytes)).serverPubkey; } catch {} }
}
if (owner && owner !== serverPubkey) return null; // belongs to another ASP
if (!owner) return null; // can't prove ownership: leave it
@@ -147,7 +147,11 @@ export function slimArkForSync(s) {
// Spent stubs and done actions are pure history and grow forever — cap
// them (newest kept) so the sync event's size is bounded for life.
vtxos: (() => {
- const live = (s.vtxos || []).filter((v) => v.state !== 'spent');
+ // On the wire the bytes stay HEX for now: a device still on a build
+ // that only reads hex would otherwise fail to decode every coin merged
+ // from this one. Flip to base64 once builds before 2026-09-10 are gone.
+ const live = (s.vtxos || []).filter((v) => v.state !== 'spent')
+ .map((v) => (v.bytes ? { ...v, bytes: vtxoBytesToHex(v.bytes) } : v));
const stubs = (s.vtxos || []).filter((v) => v.state === 'spent').slice(-200)
.map((v) => ({ id: v.id, amountSat: v.amountSat, state: 'spent', keyIndex: v.keyIndex, expiryHeight: v.expiryHeight }));
return [...live, ...stubs];