Skip to content

feat: add onchain event listener#94

Merged
coreyphillips merged 11 commits into
masterfrom
feat/onchain-event-listener
May 29, 2026
Merged

feat: add onchain event listener#94
coreyphillips merged 11 commits into
masterfrom
feat/onchain-event-listener

Conversation

@coreyphillips
Copy link
Copy Markdown
Collaborator

Adds an on-chain transaction watcher for extended public keys. A caller starts a watcher for an xpub and receives typed WatcherEvents via an EventListener callback.

Description

  • New EventListener trait (#[uniffi::export(with_foreign)]) for receiving typed callbacks, implementable from Swift/Kotlin/Python.
  • New FFI functions: onchain_start_watcher, onchain_stop_watcher, onchain_stop_all_watchers.
  • New WatcherParams record: watcher_id, extended_key, electrum_url, optional network / account_type (auto-detected from the key prefix when omitted), and optional gap_limit (defaults to 20).
  • New WatcherEvent enum: TransactionsChanged { transactions, balance, tx_count, block_height, account_type }, Error { message }, Disconnected { message }, Reconnected.
  • Implementation (src/modules/onchain/listener.rs):
    • Uses Electrum blockchain.scripthash.subscribe for detection; a short-timeout ping() drains pushed notifications off the socket without a fixed poll interval.
    • Runs the wallet + Electrum client (both !Send) on one dedicated std thread per watcher rather than occupying a Tokio blocking-pool slot for the watcher's lifetime.
    • Init ordering is sync → subscribe → sync to close the sync/subscribe race window.
    • Self-healing connection: lost connections trigger a Disconnected event and an exponential-backoff reconnect (capped at 60s) that emits Reconnected; a failed resync is retried so a popped notification is never dropped.
    • Per-watcher generation guard so a tearing-down watcher can't evict a newer watcher reusing the same watcher_id.
    • Gap limit is extended automatically as new addresses are used.
  • New WatcherError variant on AccountInfoError.
  • Regenerated Android/iOS/Python bindings and bumped version to 0.1.65.

QA Notes

  • cargo check and cargo test pass.
  • Start a watcher against a known xpub on an Electrum server and confirm:
    • An initial TransactionsChanged event arrives with the current balance/history.
    • Sending a new tx to a derived address fires a TransactionsChanged update within seconds.
    • Killing/restoring the Electrum connection produces Disconnected then Reconnected events, and state resyncs afterward.
    • onchain_stop_watcher / onchain_stop_all_watchers tear the watcher(s) down cleanly.
    • Starting a second watcher with an already-active watcher_id returns a WatcherError.

@coreyphillips coreyphillips self-assigned this May 29, 2026
@coreyphillips
Copy link
Copy Markdown
Collaborator Author

  • Release created as 0.1.65 here.
  • Android PR for testing is available here.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1d78cb646

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/modules/onchain/listener.rs Outdated
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

Found two watcher issues in the review.

Comment thread src/modules/onchain/listener.rs
Comment thread src/modules/onchain/listener.rs Outdated
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

Found one small lifecycle edge in the second pass.

Comment thread src/modules/onchain/listener.rs
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

One small perf note from the BDK/electrum-client pass.

Comment thread src/modules/onchain/listener.rs
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

One design question about keeping the watcher descriptor-first.

Comment thread src/modules/onchain/listener.rs
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

One small formatting note

Comment thread src/modules/onchain/listener.rs Outdated
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

One retry pacing note from the follow-up review.

Comment thread src/modules/onchain/listener.rs Outdated
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

One startup semantics question from the architecture pass.

Comment thread src/modules/onchain/listener.rs Outdated
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

One tip-height edge case from the architecture pass.

Comment thread src/modules/onchain/listener.rs Outdated
@coreyphillips coreyphillips requested a review from ben-kaufman May 29, 2026 16:38
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

One small subscription nit.

Comment thread src/modules/onchain/listener.rs Outdated
@coreyphillips coreyphillips requested a review from ben-kaufman May 29, 2026 17:20
Copy link
Copy Markdown
Collaborator

@ben-kaufman ben-kaufman left a comment

Choose a reason for hiding this comment

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

LGTM, would be good to update to more descriptor focus architecture as a follow up.

@coreyphillips
Copy link
Copy Markdown
Collaborator Author

coreyphillips commented May 29, 2026

I'll bump the version and rebuild.

  • New v0.1.66 release here.

@coreyphillips coreyphillips merged commit c504822 into master May 29, 2026
1 check passed
@coreyphillips coreyphillips deleted the feat/onchain-event-listener branch May 29, 2026 17:58
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.

2 participants