Skip to content

fix(bitcoin-wallet-snap): repair drifted wallets with a one-time full rescan - #226

Open
jeremytsng wants to merge 3 commits into
mainfrom
fix/btc-snap-one-time-rescan
Open

fix(bitcoin-wallet-snap): repair drifted wallets with a one-time full rescan#226
jeremytsng wants to merge 3 commits into
mainfrom
fix/btc-snap-one-time-rescan

Conversation

@jeremytsng

@jeremytsng jeremytsng commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Explanation

Last of three PRs splitting #201 per review feedback. Stacked on #225.

The wide address scan runs exactly once in an account's life — at creation. A wallet whose funds landed outside the revealed set before the reveal-at-sign fix (#225) stays wrong forever; nothing in the product re-searches. Two support cases (0.09 BTC and 6.9 BTC) sat in exactly that state until the users recovered manually.

This PR adds a one-time repair, deliberately not a recurring job:

  • The first regular sync after this update schedules one full scan per existing account (FullScanAccount background events), then sets a rescanV1 state marker and never repeats. The scan uses the BIP44 gap from fix(bitcoin-wallet-snap): use BIP44 gap limit for full account scans #224.
  • Ordering is deliberate: schedule first, mark after. A crash mid-loop causes duplicate scans on retry — idempotent and bounded — instead of silently losing the repair.
  • Repair scans emit a Missed Transactions Discovered tracking event per transaction routine sync did not know about. This is the acceptance metric for the stack: its rate should go to zero. Creation-time scans do not emit it, so expected discovery never pollutes the signal.
  • Cleanup along the way: the duplicated settle-aggregation block in CronHandler became one typed #finishSync helper, removing a Record<string, any>.

Recurring coverage (periodic rescans, all-account sync) is out of scope pending an infra discussion on Esplora load: a recurring full scan costs roughly 40 requests per account per run across the fleet, and the drifted-wallet population is a one-time problem.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

@jeremytsng
jeremytsng requested a review from a team as a code owner August 27, 2026 17:32
@jeremytsng
jeremytsng force-pushed the fix/btc-snap-reveal-at-sign branch from 276f370 to cdd693d Compare August 28, 2026 05:09
@jeremytsng
jeremytsng force-pushed the fix/btc-snap-one-time-rescan branch from d63b758 to 215d451 Compare August 28, 2026 05:10
@jeremytsng
jeremytsng force-pushed the fix/btc-snap-reveal-at-sign branch from cdd693d to 3895731 Compare August 31, 2026 07:04
@jeremytsng
jeremytsng force-pushed the fix/btc-snap-one-time-rescan branch from 27561ee to 5b9d467 Compare August 31, 2026 07:06
@jeremytsng
jeremytsng force-pushed the fix/btc-snap-reveal-at-sign branch from 3895731 to f9c6c84 Compare August 31, 2026 08:43
@jeremytsng
jeremytsng force-pushed the fix/btc-snap-one-time-rescan branch from 5b9d467 to 5da96b6 Compare August 31, 2026 15:17
@jeremytsng
jeremytsng force-pushed the fix/btc-snap-reveal-at-sign branch 2 times, most recently from 9157cca to a9a3dde Compare September 7, 2026 08:19
Base automatically changed from fix/btc-snap-reveal-at-sign to main September 7, 2026 09:27
… rescan

A full scan runs only once in an account's life, at creation, so a
wallet whose funds landed outside the revealed set stays wrong forever.
The first regular sync after this update schedules one full scan per
existing account, gated by a rescanV1 state marker set after scheduling
so a crash retries with duplicate scans instead of silently skipping
the repair. Repair scans emit a Scan Discovered Missed Transactions
tracking event for each transaction routine sync did not know about,
which measures whether the coverage fixes hold in the field.
@jeremytsng
jeremytsng force-pushed the fix/btc-snap-one-time-rescan branch from 5da96b6 to 3f694c2 Compare September 8, 2026 06:33
@Battambang

Copy link
Copy Markdown
Contributor

Sonar is mentioning '../entities' imported multiple times. in packages/bitcoin-wallet-snap/src/handlers/CronHandler.ts file.
Would be nice to address.

@Battambang

Copy link
Copy Markdown
Contributor

This new event Scan Discovered Missed Transactions is emitted but is never tracked because it is not registered in the emitTrackingEvent method. It needs to be added there:

@Battambang

Copy link
Copy Markdown
Contributor

Also if a new event is created, it needs to be referenced in Segment through Segment schema repo: https://github.com/Consensys/segment-schema

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Repair events can be permanently skipped, and SnapClientAdapter currently discards the new telemetry event.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a one-time full rescan to repair drifted Bitcoin accounts and track missed transactions.

Changes:

  • Schedules repair scans and records completion state.
  • Adds missed-transaction telemetry.
  • Refactors sync result handling and expands tests/changelog.
File summaries
File Description
CronHandler.ts Implements repair scheduling, telemetry, and sync aggregation.
CronHandler.test.ts Tests repair scheduling and transaction tracking.
entities/snap.ts Defines the new tracking event.
CHANGELOG.md Documents repair and telemetry behavior.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/bitcoin-wallet-snap/src/handlers/CronHandler.ts Outdated
Comment thread packages/bitcoin-wallet-snap/src/handlers/CronHandler.ts Outdated
@Battambang

Copy link
Copy Markdown
Contributor

This new event Scan Discovered Missed Transactions is emitted but is never tracked because it is not registered in the emitTrackingEvent method. It needs to be added there:

Also referenced by Copilot: #226 (comment)

…s telemetry

The one-time repair marked itself complete as soon as its background
scans were scheduled, so a scan consumed while the client was locked, or
one that failed, left the wallet unrepaired forever. The marker now holds
the list of accounts still pending, fixed at first run so later-created
accounts never join it. Each sync run repairs one pending account and
removes it only after the scan succeeds; deleted accounts are pruned and
a malformed marker reinitialises the list. Once the list is empty the
repair path costs one state read per run.

SnapClientAdapter now maps Scan Discovered Missed Transactions to a
tracking message; the event previously fell through to the assertion
default and was swallowed before reaching snap_trackEvent.

Collapse the duplicated ../entities imports in CronHandler.
@jeremytsng

Copy link
Copy Markdown
Contributor Author

Also if a new event is created, it needs to be referenced in Segment through Segment schema repo: https://github.com/Consensys/segment-schema

https://github.com/Consensys/segment-schema/pull/733

…sactions Discovered

Match the segment-schema definition: Object + Past-tense Verb name, and
send the on-chain hash as transaction_hash for this event.
@sonarqubecloud

sonarqubecloud Bot commented Sep 9, 2026

Copy link
Copy Markdown

@Battambang Battambang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job also with the new metric event handled in the Segment schema repo.

@Battambang

Battambang commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

@jeremytsng Could you please also make a preview build for testing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bitcoin-wallet-snap] bug: wallet balance drops to zero during pending transactions (unconfirmed change UTXOs not displayed)

3 participants