# Return user-facing events when applying updates after syncing

* Status: accepted
* Authors: @notmandatory
* Date: 2025-09-21
* Targeted modules: wallet
* Associated tickets/PRs: #6, #310, #319

## Context and Problem Statement

When syncing a `Wallet` with new blockchain data using `Wallet::apply_update` it does not return any value on success, 
only a `CannotConnectError` if it fails. 

Users have asked for a concise list of events that reflect if or how new blockchain data has changed the 
blockchain tip and the status of transactions relevant to the wallet's bitcoin balance. This information should also
be useful for on-chain apps who want to notify users of wallet changes after syncing.

If the end user app ends for some reason before handling the wallet events, the same wallet events should be 
regenerated when the same blockchain sync data is re-downloaded and reapplied to the wallet. 

## Decision Drivers

* Currently `Wallet::apply_update` does not return any value except a `CannotConnectError` if it fails.
* Downstream users need updates on chain tip, new transactions and transaction status changes.
* If the app doesn't process all the events before it ends the same events should be returned on a subsequent sync.
* Current downstream users requesting this feature are: LDK node (@tnull) and Bitkit (@ovitrif).
* This feature was requested in May 2024, over a year and a half ago.

## Considered Options

#### Option 1: Do nothing

Do not change anything since all the data the users require is available with the current API by comparing the 
wallet's canonical transaction list before and after applying a sync update.

**Pros:**

* No API changes are needed and user can customize the events to exactly what they need.

**Cons:**

* Users will need to duplicate the work to add this feature on every project.
* It's easier for the core BDK team to add this feature once in a way that meets most users needs.

#### Option 2: Modify the `Wallet::apply_update` to return a list of `WalletEvent`

Adds `WalletEvent` enum of user facing events that are generated when a sync update is applied to a wallet using the
existing `Wallet::apply_update` function. The `WalletEvent` enum includes an event for changes in blockchain tip and
events for changes to the status of transactions that are relevant to the wallet, including:

1. newly seen in the mempool
2. replaced in the mempool 
3. dropped from the mempool
4. confirmed in a block
5. confirmed in a new block due to a reorg
6. unconfirmed due to a reorg

Chain tip change events are generated by comparing the wallet's chain tip before and after applying an update. Wallet 
transaction events are generated by comparing a snapshot of canonical transactions.

As long as updates to the wallet are not persisted until after all events are processed by the caller then if the app
crashes for some reason and the wallet is re-sync'd a new update will re-return the same events.

The `WalletEvent` enum is non-exhaustive.

**Pros:**

* Events are always generated when a wallet update is applied.
* The user doesn't need to add this functionality themselves.
* New events can be added without a breaking change.

**Cons:**

* This can not be rolled out except as a breaking release since it changes the `Wallet::apply_update` function signature.
* If an app doesn't care about these events they must still generate them.

#### Option 3: Same as option 2 but add a new function

This option is the same as option 2 but adds a new `Wallet::apply_update_events` function to update the wallet and
return the list of `WalletEvent` enums.

**Pros:**

* Same reasons as above and does not require an API breaking release.
* Keeps option for users to update the wallet with original `Wallet::apply_update` and not get events.

**Cons:**

* Could be confusing to users which function to use, the original or new one.
* If in a future breaking release we decide to always return events we'll need to deprecate `Wallet::apply_update_events`.

#### Option 4: Create events directly from Wallet::Update

The `wallet::Update` structure passed into the `Wallet::apply_update` function contains any new transaction or 
blockchain data found in a `FullScanResponse` or `SyncResponse`. Events could be generated from only this data.

**Pros:**

* No further wallet lookups is required to create events, it would be more efficient.
* Could be implemented as a function directly on the `wallet::Update` structure, a non-breaking API change.

**Cons:**

* A `wallet::Update` only contains the blocks, tx, and anchors found during a sync or full scan. It does not show how 
  this data changes the canonical status of already known blocks and tx.

## Decision Outcome

Chosen option: 

"Option 3" for the 2.2 release because it can be delivered to users as a minor release. This option also 
lets us get user feedback and see how the events are used before forcing all users to generate them during an update.

"Option 2" for the 3.0 release to simplify the API by only using one function `apply_update` that will now return
events. 

### Positive Consequences

* The new wallet events can be used for more responsive on chain wallet UIs.

### Negative Consequences

* The down stream `bdk-ffi` and book of bdk projects will need to be updated for this new feature.

