aboutsummaryrefslogtreecommitdiffstats
path: root/src/ark
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-03 14:05:21 -0700
committerAdam Soltys <[email protected]>2026-08-03 14:05:21 -0700
commit95c898f91d2f8ea1ef693624a542eb7fa8cadbb9 (patch)
tree50b5ac19788f6001bb29a2f5710293d7691da59b /src/ark
parentcdd34e88be8a58c1cc9fa3d0cfbbd02b23439629 (diff)
downloadcoinosv3-95c898f91d2f8ea1ef693624a542eb7fa8cadbb9.tar.gz
coinosv3-95c898f91d2f8ea1ef693624a542eb7fa8cadbb9.zip
A freshly imported wallet shows history, not a celebration
Importing a seed on a second device replayed "Payment received!" for a payment that had arrived on the first one. The two-hour recency guard couldn't catch it: a movement is stamped with the moment THIS device discovered it, so on a fresh device the entire history looks like it just landed — a week-old payment would have celebrated too. A wallet whose ark state didn't exist on this device now treats its first catch-up as history and acknowledges it, so only what turns up afterwards is news. Reopening an existing wallet is unaffected, and a payment that lands while you're watching still celebrates. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
Diffstat (limited to 'src/ark')
-rw-r--r--src/ark/manager.js16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/ark/manager.js b/src/ark/manager.js
index 5617cf1..01de06f 100644
--- a/src/ark/manager.js
+++ b/src/ark/manager.js
@@ -88,7 +88,14 @@ export class ArkManager {
// ---- lifecycle ----
async init() {
- this.state = this.storage.load() || EMPTY_STATE();
+ const loaded = this.storage.load();
+ this.state = loaded || EMPTY_STATE();
+ // A wallet opening on a device for the first time (a fresh import, a new
+ // browser) is about to discover its whole history at once, and every
+ // movement it records gets stamped with the moment it was found — so
+ // without this, a week-old payment looks like it just arrived. Mark the
+ // first catch-up as history: only what turns up afterwards is news.
+ if (!loaded) this.state.baselinePending = true;
// drop duplicate receive movements (same vtxo) left by the former
// poll/stream race; the vtxo set itself was always deduped
const seen = new Set();
@@ -211,10 +218,17 @@ export class ArkManager {
// Read new mailbox messages, fully validate incoming vtxos, then push any
// in-flight actions forward.
async sync() {
+ const baselining = !!this.state.baselinePending;
const mailbox = this._mailboxKey();
const { messages } = await readMailbox(this.arkUrl, mailbox, this.state.mailboxCheckpoint);
let changed = false;
for (const m of messages) changed = (await this._processMailboxMessage(m)) || changed;
+ // Everything the first catch-up found is history, not news.
+ if (baselining) {
+ this.state.receiveAckTs = Date.now();
+ delete this.state.baselinePending;
+ changed = true;
+ }
if (changed) this._save();
await this.resumePending();
}