<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinosv3.git/src/wallet.js, branch master</title>
<subtitle>coinos v3 — bitcoin, Ark, Lightning and nostr wallet (web + Android)</subtitle>
<id>https://git.coinos.io/coinosv3.git/atom?h=master</id>
<link rel='self' href='https://git.coinos.io/coinosv3.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/'/>
<updated>2026-10-08T17:11:48Z</updated>
<entry>
<title>Savings scan looks 20 addresses past the last used one (BIP-44 gap limit) instead of stopping at the first unused address, so a seed restored from another wallet shows coins sitting past a gap; the window of 20 is probed in parallel, the empty look-ahead tail isn't kept, and the next fresh address is one past the highest used (never a hole another wallet left)</title>
<updated>2026-10-08T17:11:48Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-08T17:11:48Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=35f7e2f2ca967c24f26c6eadd73c2222ad252e52'/>
<id>urn:sha1:35f7e2f2ca967c24f26c6eadd73c2222ad252e52</id>
<content type='text'>
Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Rebuildable caches move from localStorage to IndexedDB (cache-store.js)</title>
<updated>2026-10-07T14:24:33Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-07T14:24:33Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=78cf670939133fc4f656f0f42b21a59431a53842'/>
<id>urn:sha1:78cf670939133fc4f656f0f42b21a59431a53842</id>
<content type='text'>
localStorage is ~5M characters per site whatever the device, and a phone
had filled it. Profiles, faceless list, reports, follow packs, profile
pages, relay lists, the moderation baseline, community directory, link
previews, video sizes/probes and search profiles (~3M on that phone) now
live in IndexedDB, which shares the site's disk allowance (GBs).

cacheStorage keeps localStorage's string API: reads from memory,
coalesced write-behind, flushed on hide. Copies migrate on open and are
removed once written. Boot waits for it (max 3s) beside the Ark store;
caches read at construction re-merge on ready; an early write can't
replace the stored copy. A copy an older build writes to localStorage
later moves in on first ask. Wallet wipes reach it; private mode stays on
localStorage. Read markers, drafts, follows, note threads and sync
outboxes stay in localStorage on purpose (cross-tab consistency, early
server-rendered seeding). Also asks navigator.storage.persist().

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Copy: no more em dashes, anywhere people read.</title>
<updated>2026-09-27T22:07:30Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-27T22:07:30Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=e6035849f9b88bdd8cd665b868bbe121fa77e538'/>
<id>urn:sha1:e6035849f9b88bdd8cd665b868bbe121fa77e538</id>
<content type='text'>
Every English string, the translations, the README and the messages the code
shows people now break with a full stop, a colon or a comma instead. Only
console logs and the "—" placeholder for an empty cell keep the dash.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
</content>
</entry>
<entry>
<title>Feed scroll: stop re-parsing the whole messages state per row per repaint.</title>
<updated>2026-09-27T06:11:20Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-27T06:11:20Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=dbf755968827b0d75f5e30d35a6c90da3cdc1aa2'/>
<id>urn:sha1:dbf755968827b0d75f5e30d35a6c90da3cdc1aa2</id>
<content type='text'>
A CPU profile of a 44 s scroll on Adam's tab: 21 of 27 busy seconds in
loadFeatureState — every read parsed the multi-megabyte messages blob from
localStorage and re-hashed the seed for its key, and the mute/spam checks
read it for every row on every repaint. Now the cache key is hashed once
per identity, the messages state is parsed once per tick (a write refreshes
the copy; the copy is dropped on account switch), and the profile blob
stays parsed in memory and is written back once per burst instead of being
parsed and re-serialized for each of thirty profiles landing mid-scroll.
Videos preload metadata only: a window of autoplaying players was
streaming 20 MB during the same scroll.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
</content>
</entry>
<entry>
<title>Ark state moves to IndexedDB: raw bytes on disk, memory-fronted, write-behind.</title>
<updated>2026-09-10T14:18:09Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-10T14:18:09Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=af4810e2ec8e454e4bb616c685e907eaee04c874'/>
<id>urn:sha1:af4810e2ec8e454e4bb616c685e907eaee04c874</id>
<content type='text'>
localStorage held a deep wallet's ark state as ~700KB of JSON (UTF-16 on
disk), parsed on every boot and stringified on every save, and the wallet
cache blob carried a second ~600KB copy. src/ark/store.js keeps the state
in IndexedDB (db coinos-ark) with each coin's signed bytes as a Uint8Array,
fronted by an in-memory map so loadArkState/saveArkState stay synchronous:
reads return clones, writes coalesce (200ms) and flush immediately when the
page hides. Existing localStorage copies migrate on first open (newest _rev
wins) and are removed only after the IndexedDB write completed; no
IndexedDB means localStorage exactly as before. Records keep their
btc-wallet-cache:&lt;id&gt;:ark… keys, and a wallet wipe clears both stores via
the new per-feature wipeCache hook.

The ark cache extension is now syncOnly: it still rides the sync snapshot
(and the Blossom blob) but the local wallet cache no longer embeds it —
measured on a live wallet the cache blob went from 655KB to 10KB.

Verified in the live tab: all wallets migrated, bytes raw on disk, balance
and coin set unchanged, localStorage ark keys gone. tools/ark-store-test.js
covers migration by _rev, clone-on-read, write-behind, wipe and fallback.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01Nw1Dijik1tLVKRM1WkU7xE
</content>
</entry>
<entry>
<title>A snapshot only counts on its own network: the seed-keyed cache stops showing mainnet money under a mutinynet flag, and staging forgives the mainnet default it stamped before it knew better</title>
<updated>2026-08-17T21:44:26Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-17T21:44:26Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=00a0be5fcd8157f145c63df44982b4f74960c815'/>
<id>urn:sha1:00a0be5fcd8157f145c63df44982b4f74960c815</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
</content>
</entry>
<entry>
<title>Own entropy means owned outcome: the typed text alone derives the seed, so re-typing it is an import on any device — the warn-box says what that guarantee costs, and Regenerate bows out of a deterministic job</title>
<updated>2026-08-17T18:16:25Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-17T18:16:25Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=6a78f8fefe71e636c847e1402b08b1d60483565b'/>
<id>urn:sha1:6a78f8fefe71e636c847e1402b08b1d60483565b</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
</content>
</entry>
<entry>
<title>The seed takes dice: an optional entropy field folds open on the generate step, hashed with the device's own randomness so it can only strengthen the phrase — and the forget option now says all data, which is what it takes</title>
<updated>2026-08-17T15:12:34Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-17T15:12:34Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=b62ca1099ff996e333015142cb712687737d4637'/>
<id>urn:sha1:b62ca1099ff996e333015142cb712687737d4637</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
</content>
</entry>
<entry>
<title>Wallets go flat: every Spending and Savings is a top-level wallet in the switcher, named for its purpose, renamable apart — and a new wallet can carry its own seed or live at the next BIP84 account of one you already back up</title>
<updated>2026-08-15T21:32:28Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-15T21:32:28Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=643046319fa9a393374fc2348381d9505fe143eb'/>
<id>urn:sha1:643046319fa9a393374fc2348381d9505fe143eb</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
</content>
</entry>
<entry>
<title>Gift records belong to one wallet, not to the browser</title>
<updated>2026-08-04T03:15:16Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-04T03:15:16Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=d59d667d3e4c6edb42b8a42fd120a1bdd96a58db'/>
<id>urn:sha1:d59d667d3e4c6edb42b8a42fd120a1bdd96a58db</id>
<content type='text'>
giftRecords() caches the parsed blob on the wallet object, but the app
runs a single Wallet for its lifetime and load() never dropped that
cache. Switching wallets carried the old wallet's gift links into the
new one, where they all rendered as claimed — none of their outpoints
are live in a wallet that never issued them — and the first save wrote
them back under the new wallet's key.

Clear the cache on load alongside the other two gift caches, and forget
records whose funding tx isn't in this wallet's own history, to clean up
what earlier builds already misfiled.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
</content>
</entry>
</feed>
