Skip to content

feat!(wallet): persist wallet events - #1631

Merged
sdbondi merged 1 commit into
tari-project:developmentfrom
sdbondi:wallet-events
Nov 5, 2025
Merged

feat!(wallet): persist wallet events#1631
sdbondi merged 1 commit into
tari-project:developmentfrom
sdbondi:wallet-events

Conversation

@sdbondi

@sdbondi sdbondi commented Nov 5, 2025

Copy link
Copy Markdown
Member

Description

feat!(wallet): persist wallet events

Motivation and Context

Allows a history of wallet events to be reviewed

How Has This Been Tested?

Manually

What process can a PR reviewer use to test or verify this change?

Breaking Changes

  • None
  • Requires data directory to be deleted
  • Other - Please specify

Summary by CodeRabbit

  • New Features

    • Event logging API exposed in the SDK to persist wallet events.
    • Wallet events are now persisted to a new wallet_events table in storage.
  • Improvements

    • All wallet event types gain serialization.
    • New event fields: account change version and UTXO event account_address.
    • Human-readable formatting for strings and memos (Memo displays, MaxString Display).
    • Small docs: EncryptedData MAX_SIZE clarified.

@coderabbitai

coderabbitai Bot commented Nov 5, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Event types and event handling were moved from the services events module into the SDK models, new SDK EventsApi and storage writer support were added to persist events (DB schema and writer impl), event structs were enriched (Serialize, Display, added fields), multiple imports updated across handlers/services, and event logging calls were introduced.

Changes

Cohort / File(s) Summary
Handler import updates
applications/tari_walletd/src/handlers/accounts.rs, applications/tari_walletd/src/handlers/context.rs, applications/tari_walletd/src/handlers/helpers.rs, applications/tari_walletd/src/handlers/rpc.rs, applications/tari_walletd/src/handlers/transaction.rs
Repointed imports to use tari_ootle_wallet_sdk::models::{...} for event types (e.g., WalletEvent, TransactionSubmittedEvent, AuthLoginRequestEvent); no control-flow changes.
Daemon services wiring
applications/tari_walletd/src/services/mod.rs, applications/tari_walletd/src/services/template_monitor.rs
Updated WalletEvent import to tari_ootle_wallet_sdk::models and changed UtxoRecovery initialization to .with_notify(notify.clone()).run(...).
SDK models & events
crates/wallet/sdk/src/models/event.rs, crates/wallet/sdk/src/models/mod.rs
New event module exported; WalletEvent variants enriched (Serialize, Display), added WalletEventType and as_event_type(); added/updated fields (e.g., AccountChangedEvent.version, UtxoSpentEvent.account_address).
Events API & SDK surface
crates/wallet/sdk/src/apis/events.rs, crates/wallet/sdk/src/apis/mod.rs, crates/wallet/sdk/src/sdk.rs
Added EventsApi<'a, TStore> with log_event() and EventApiError; exported events module and exposed WalletSdk::event_api().
Storage trait & writer
crates/wallet/sdk/src/storage/mod.rs, crates/wallet/sdk/src/storage/writer.rs, crates/wallet/storage_sqlite/src/writer.rs, crates/wallet/storage_sqlite/src/schema.rs
Added WalletEventStoreWriter trait and required it on WriteableWalletStore::WriteTransaction<'a>; SQLite schema/table wallet_events added; implemented append_wallet_event() to persist events in writer (noted duplicated impl in diff).
Storage migrations
crates/wallet/storage_sqlite/migrations/2023-02-08-122514_initial/up.sql, crates/wallet/storage_sqlite/migrations/2025-10-29-122554_add_timeout_at_to_locks/*
Initial migration updated to add wallet_events table and locks.timeout_at; removed separate timeout_at migration files.
SDK services import & logging
crates/wallet/sdk_services/src/account_monitor/monitor.rs, crates/wallet/sdk_services/src/account_monitor/scanner.rs, crates/wallet/sdk_services/src/transaction_service/service.rs, crates/wallet/sdk_services/src/utxo_scanner/*
Consolidated event imports to tari_ootle_wallet_sdk::models; account scanner propagates account version and emits enriched AccountChangedEvent/AccountCreatedEvent; UTXO scanner emits UtxoSpentEvent.account_address; account monitor logs and persists events via event_api().log_event().
Misc. display & docs
crates/template_lib_types/src/encrypted_data.rs, crates/template_lib_types/src/max_string.rs, crates/wallet/crypto/src/memo.rs
Added doc comment for MAX_SIZE; implemented Display for MaxString<N>; added Memo::as_utf8_str() and Display impl for Memo.
Public API removal
crates/wallet/sdk_services/src/lib.rs
Removed pub mod events; from sdk_services public exports.

Sequence Diagram(s)

sequenceDiagram
    participant Scanner as Account/UTXO Scanner
    participant Monitor as Account Monitor
    participant SDK as Wallet SDK
    participant EventAPI as EventsApi
    participant Store as Wallet Store (WriteTx)
    Note over Scanner,Monitor: Event constructed (enriched with version/account_address)
    Scanner->>Monitor: emit WalletEvent
    Monitor->>EventAPI: event_api().log_event(event)
    EventAPI->>SDK: begin write transaction
    SDK->>Store: with_write_tx()
    EventAPI->>Store: append_wallet_event(event)
    Store->>Store: resolve account_id, serialize event_data
    Store->>Store: INSERT INTO wallet_events
    Store-->>SDK: commit/rollback
    SDK-->>EventAPI: result
    EventAPI-->>Monitor: ok / error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Attention points:
    • crates/wallet/storage_sqlite/src/writer.rs appears to contain duplicated impl WalletEventStoreWriter for WriteTransaction<'_> (would cause compile error).
    • Verify schema migrations (removed/merged timeout_at migration) and ensure migration ordering and deployment are correct.
    • Confirm all import updates consistently reference the new models types and that no remaining crate::events usage remains.
    • Check serialization/Display changes for backward compatibility where events are persisted/serialized.

Possibly related PRs

Poem

🐰 I hopped through code to move each note,

Events now live where models float,
Stored in tables, stamped in time,
Versions, addresses, fields in rhyme,
A tiny rabbit logs with pride. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat!(wallet): persist wallet events' clearly and specifically describes the main objective of the changeset - adding persistence of wallet events to the wallet module. The title directly relates to the core functionality introduced across multiple files.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67083a9 and 6dbea72.

📒 Files selected for processing (30)
  • applications/tari_walletd/src/handlers/accounts.rs (1 hunks)
  • applications/tari_walletd/src/handlers/context.rs (1 hunks)
  • applications/tari_walletd/src/handlers/helpers.rs (1 hunks)
  • applications/tari_walletd/src/handlers/rpc.rs (1 hunks)
  • applications/tari_walletd/src/handlers/transaction.rs (1 hunks)
  • applications/tari_walletd/src/services/mod.rs (2 hunks)
  • applications/tari_walletd/src/services/template_monitor.rs (1 hunks)
  • crates/template_lib_types/src/encrypted_data.rs (1 hunks)
  • crates/template_lib_types/src/max_string.rs (2 hunks)
  • crates/wallet/crypto/src/memo.rs (3 hunks)
  • crates/wallet/sdk/src/apis/events.rs (1 hunks)
  • crates/wallet/sdk/src/apis/mod.rs (1 hunks)
  • crates/wallet/sdk/src/models/event.rs (2 hunks)
  • crates/wallet/sdk/src/models/mod.rs (2 hunks)
  • crates/wallet/sdk/src/sdk.rs (2 hunks)
  • crates/wallet/sdk/src/storage/mod.rs (1 hunks)
  • crates/wallet/sdk/src/storage/writer.rs (2 hunks)
  • crates/wallet/sdk_services/src/account_monitor/monitor.rs (2 hunks)
  • crates/wallet/sdk_services/src/account_monitor/scanner.rs (9 hunks)
  • crates/wallet/sdk_services/src/lib.rs (0 hunks)
  • crates/wallet/sdk_services/src/transaction_service/service.rs (2 hunks)
  • crates/wallet/sdk_services/src/utxo_scanner/scanner.rs (1 hunks)
  • crates/wallet/sdk_services/src/utxo_scanner/scanner_round.rs (2 hunks)
  • crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs (1 hunks)
  • crates/wallet/sdk_services/src/utxo_scanner/worker.rs (2 hunks)
  • crates/wallet/storage_sqlite/migrations/2023-02-08-122514_initial/up.sql (2 hunks)
  • crates/wallet/storage_sqlite/migrations/2025-10-29-122554_add_timeout_at_to_locks/down.sql (0 hunks)
  • crates/wallet/storage_sqlite/migrations/2025-10-29-122554_add_timeout_at_to_locks/up.sql (0 hunks)
  • crates/wallet/storage_sqlite/src/schema.rs (4 hunks)
  • crates/wallet/storage_sqlite/src/writer.rs (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f040d7c and 67083a9.

📒 Files selected for processing (30)
  • applications/tari_walletd/src/handlers/accounts.rs (1 hunks)
  • applications/tari_walletd/src/handlers/context.rs (1 hunks)
  • applications/tari_walletd/src/handlers/helpers.rs (1 hunks)
  • applications/tari_walletd/src/handlers/rpc.rs (1 hunks)
  • applications/tari_walletd/src/handlers/transaction.rs (1 hunks)
  • applications/tari_walletd/src/services/mod.rs (2 hunks)
  • applications/tari_walletd/src/services/template_monitor.rs (1 hunks)
  • crates/template_lib_types/src/encrypted_data.rs (1 hunks)
  • crates/template_lib_types/src/max_string.rs (2 hunks)
  • crates/wallet/crypto/src/memo.rs (3 hunks)
  • crates/wallet/sdk/src/apis/events.rs (1 hunks)
  • crates/wallet/sdk/src/apis/mod.rs (1 hunks)
  • crates/wallet/sdk/src/models/event.rs (2 hunks)
  • crates/wallet/sdk/src/models/mod.rs (2 hunks)
  • crates/wallet/sdk/src/sdk.rs (2 hunks)
  • crates/wallet/sdk/src/storage/mod.rs (1 hunks)
  • crates/wallet/sdk/src/storage/writer.rs (2 hunks)
  • crates/wallet/sdk_services/src/account_monitor/monitor.rs (2 hunks)
  • crates/wallet/sdk_services/src/account_monitor/scanner.rs (9 hunks)
  • crates/wallet/sdk_services/src/lib.rs (0 hunks)
  • crates/wallet/sdk_services/src/transaction_service/service.rs (2 hunks)
  • crates/wallet/sdk_services/src/utxo_scanner/scanner.rs (1 hunks)
  • crates/wallet/sdk_services/src/utxo_scanner/scanner_round.rs (2 hunks)
  • crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs (1 hunks)
  • crates/wallet/sdk_services/src/utxo_scanner/worker.rs (2 hunks)
  • crates/wallet/storage_sqlite/migrations/2023-02-08-122514_initial/up.sql (2 hunks)
  • crates/wallet/storage_sqlite/migrations/2025-10-29-122554_add_timeout_at_to_locks/down.sql (0 hunks)
  • crates/wallet/storage_sqlite/migrations/2025-10-29-122554_add_timeout_at_to_locks/up.sql (0 hunks)
  • crates/wallet/storage_sqlite/src/schema.rs (4 hunks)
  • crates/wallet/storage_sqlite/src/writer.rs (2 hunks)
💤 Files with no reviewable changes (3)
  • crates/wallet/sdk_services/src/lib.rs
  • crates/wallet/storage_sqlite/migrations/2025-10-29-122554_add_timeout_at_to_locks/up.sql
  • crates/wallet/storage_sqlite/migrations/2025-10-29-122554_add_timeout_at_to_locks/down.sql
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-19T10:49:02.115Z
Learnt from: sdbondi
Repo: tari-project/tari-ootle PR: 1543
File: crates/common_types/src/shard_state_versions.rs:59-74
Timestamp: 2025-08-19T10:49:02.115Z
Learning: In crates/common_types/src/shard_state_versions.rs, MAX_SHARDS represents the maximum shard number + 1 (257) used for bounds checking, not the maximum capacity. The current code correctly validates that shard group end numbers don't exceed the maximum possible shard number (256).

Applied to files:

  • crates/template_lib_types/src/encrypted_data.rs
📚 Learning: 2025-11-04T10:10:24.249Z
Learnt from: sdbondi
Repo: tari-project/tari-ootle PR: 1629
File: applications/tari_walletd/src/handlers/accounts.rs:1001-1002
Timestamp: 2025-11-04T10:10:24.249Z
Learning: In applications/tari_walletd/src/handlers/accounts.rs, the expect() on Memo::new_pay_ref_and_bytes_truncate at line 1002 is safe and intentional. PayRef is validated to be at most 64 bytes during address decoding (PayRef::MAX_LEN = 64), and the function only returns None if payref exceeds 252 bytes (Memo::MAX_BYTES_LENGTH - 1). Since 64 < 252, None is impossible with a valid PayRef.

Applied to files:

  • crates/wallet/crypto/src/memo.rs
🧬 Code graph analysis (15)
crates/wallet/sdk/src/apis/mod.rs (1)
crates/engine/src/runtime/working_state.rs (1)
  • events (1313-1315)
crates/wallet/sdk_services/src/utxo_scanner/worker.rs (2)
crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs (1)
  • notify (89-93)
crates/wallet/sdk_services/src/notify.rs (1)
  • notify (21-23)
crates/template_lib_types/src/max_string.rs (4)
crates/wallet/crypto/src/memo.rs (1)
  • fmt (259-285)
crates/wallet/sdk/src/models/event.rs (2)
  • fmt (93-95)
  • fmt (174-188)
crates/wallet/sdk_services/src/utxo_scanner/worker.rs (1)
  • fmt (216-218)
crates/engine_types/src/confidential/claim.rs (1)
  • fmt (28-40)
applications/tari_walletd/src/services/mod.rs (2)
crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs (2)
  • new (43-49)
  • notify (89-93)
crates/wallet/sdk_services/src/notify.rs (2)
  • new (12-15)
  • notify (21-23)
crates/wallet/sdk_services/src/transaction_service/service.rs (3)
bindings/src/types/TransactionStatus.ts (1)
  • TransactionStatus (3-11)
crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs (1)
  • notify (89-93)
crates/wallet/sdk_services/src/notify.rs (1)
  • notify (21-23)
crates/wallet/sdk/src/storage/writer.rs (1)
crates/wallet/storage_sqlite/src/writer.rs (1)
  • append_wallet_event (1671-1715)
crates/wallet/sdk/src/apis/events.rs (2)
crates/wallet/sdk_services/src/account_monitor/monitor.rs (1)
  • is_not_found_error (309-311)
crates/wallet/sdk/src/models/event.rs (11)
  • from (33-35)
  • from (39-41)
  • from (45-47)
  • from (51-53)
  • from (57-59)
  • from (63-65)
  • from (69-71)
  • from (75-77)
  • from (81-83)
  • from (87-89)
  • from (192-205)
crates/wallet/sdk_services/src/utxo_scanner/scanner_round.rs (2)
crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs (1)
  • notify (89-93)
crates/wallet/sdk_services/src/notify.rs (1)
  • notify (21-23)
applications/tari_walletd/src/handlers/accounts.rs (3)
bindings/src/types/wallet-daemon-client/BranchAndKeyId.ts (1)
  • BranchAndKeyId (5-5)
bindings/src/types/wallet-daemon-client/KeyBranch.ts (1)
  • KeyBranch (3-10)
bindings/src/types/wallet-daemon-client/KeyId.ts (1)
  • KeyId (3-3)
crates/wallet/storage_sqlite/src/writer.rs (3)
crates/wallet/sdk/src/storage/writer.rs (1)
  • append_wallet_event (222-222)
crates/wallet/storage_sqlite/src/reader.rs (15)
  • accounts (380-382)
  • accounts (402-405)
  • accounts (418-420)
  • accounts (435-437)
  • accounts (446-448)
  • accounts (477-479)
  • accounts (498-501)
  • accounts (528-531)
  • accounts (612-615)
  • accounts (759-762)
  • accounts (806-809)
  • accounts (829-832)
  • accounts (972-975)
  • accounts (1009-1012)
  • accounts (1042-1046)
crates/wallet/sdk/src/storage/error.rs (1)
  • general (48-53)
crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs (1)
crates/wallet/sdk_services/src/notify.rs (1)
  • notify (21-23)
applications/tari_walletd/src/services/template_monitor.rs (2)
crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs (1)
  • notify (89-93)
crates/wallet/sdk_services/src/notify.rs (1)
  • notify (21-23)
crates/wallet/sdk/src/models/event.rs (8)
bindings/src/types/FinalizeResult.ts (1)
  • FinalizeResult (9-16)
bindings/src/types/UtxoAddress.ts (1)
  • UtxoAddress (4-4)
bindings/src/types/ComponentAddress.ts (1)
  • ComponentAddress (6-6)
bindings/src/types/TransactionId.ts (1)
  • TransactionId (3-3)
bindings/src/types/Account.ts (1)
  • Account (6-14)
bindings/src/types/TransactionStatus.ts (1)
  • TransactionStatus (3-11)
bindings/src/types/wallet-daemon-client/AuthLoginRequest.ts (1)
  • AuthLoginRequest (4-8)
bindings/src/types/UtxoSpent.ts (1)
  • UtxoSpent (4-4)
crates/wallet/crypto/src/memo.rs (3)
applications/tari_wallet_cli/src/command/transaction.rs (10)
  • s (808-808)
  • s (811-811)
  • s (814-814)
  • s (817-817)
  • s (820-820)
  • s (823-823)
  • s (826-826)
  • s (829-829)
  • s (832-832)
  • s (836-836)
applications/tari_walletd/web_ui/src/components/Memo.tsx (1)
  • Memo (13-49)
bindings/src/types/Memo.ts (1)
  • Memo (3-3)
crates/wallet/sdk_services/src/account_monitor/scanner.rs (1)
crates/wallet/sdk/src/sdk.rs (2)
  • accounts_api (199-206)
  • substate_api (195-197)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: check nightly
  • GitHub Check: test
  • GitHub Check: file licenses
  • GitHub Check: check stable
  • GitHub Check: clippy
  • GitHub Check: fmt
  • GitHub Check: machete
🔇 Additional comments (44)
crates/template_lib_types/src/encrypted_data.rs (1)

8-8: LGTM! Documentation improves clarity.

The added documentation comment accurately describes the MAX_SIZE constant, correctly stating the 335-byte maximum (80 bytes for encrypted data without memo + 255 bytes for memo).

applications/tari_walletd/src/services/template_monitor.rs (3)

13-13: LGTM: Import path updates align with the refactoring.

The import changes correctly reflect the movement of WalletEvent from the services layer to the models layer, consistent with the broader SDK refactor described in the PR summary.

Also applies to: 18-18


80-82: No issues found. Code is compatible.

The WalletEvent::TransactionFinalized variant and its structure are fully compatible. Verification confirms:

  • TransactionFinalizedEvent struct exists with finalize: FinalizeResult field
  • FinalizeResult struct has result: TransactionResult field
  • TransactionResult::any_accept() method exists and returns Option<&SubstateDiff>

The pattern matches existing usage throughout the codebase.


13-13: Clarify what specifically changed in this PR; concerns about event persistence are valid but lack specificity.

The review comment raises legitimate concerns about breaking changes in event persistence, but the code shown in template_monitor.rs (lines 13, 80-119) does not demonstrate what changed. Line 13 is an import, and lines 80-119 contain standard event-handling logic without modifications visible.

The actual breaking-change risk lies in the event serialization layer:

  • WalletEvent structs are marked with Serialize only—no Deserialize implementation exists
  • Events are persisted as JSON without versioning or schema tags
  • Any change to WalletEvent variant structure or payload fields will render previously persisted events unreadable

To address the concerns properly:

  1. Show the diff: What changed in the WalletEvent definition or storage schema in this PR?
  2. Migration strategy: If WalletEvent schema changed, confirm whether:
    • Backward compatibility is maintained (old JSON still deserializes), OR
    • Data directory deletion is the intended recovery path
  3. Testing: For any breaking schema change, add integration tests verifying serialization/deserialization round-trips.
crates/template_lib_types/src/max_string.rs (1)

4-8: Display for MaxString is spot on.
Delegating to the inner slice keeps formatting cheap and lets the new Memo display compile cleanly.

Also applies to: 68-71

crates/wallet/crypto/src/memo.rs (2)

121-133: Ergonomic UTF-8 accessor lands nicely.
This mirrors existing parsing logic and saves every caller from rewriting the split/UTF-8 dance while failing softly on bad data.


258-285: Display coverage across variants looks great.
The explicit invalid-encoding guard plus hex formatting will make diagnostics far clearer without risking panics.

applications/tari_walletd/src/handlers/accounts.rs (1)

33-34: Import swap aligns with the new models surface.
Thanks for consolidating the event types under tari_ootle_wallet_sdk::models.

crates/wallet/sdk/src/apis/mod.rs (1)

9-9: Nice to see events wired into the API module.
Keeps the public surface consistent with the new SDK entry points.

crates/wallet/sdk/src/sdk.rs (1)

26-27: Event API exposure looks great.
Borrowing the store matches the other API constructors and gives callers the missing hook to log events.

Also applies to: 164-166

applications/tari_walletd/src/handlers/helpers.rs (1)

13-13: LGTM! Import path updated correctly.

The import path for event types has been successfully updated to use the models module, aligning with the architectural refactor to consolidate event types.

applications/tari_walletd/src/handlers/context.rs (1)

5-5: LGTM! Import path updated correctly.

The WalletEvent import has been correctly updated to reference the models module.

crates/wallet/sdk_services/src/utxo_scanner/worker.rs (2)

15-15: LGTM! Import path updated correctly.

The WalletEvent import has been correctly updated to use the models module.


26-26: LGTM! Local imports consolidated.

The local imports have been correctly consolidated to use crate::notify and crate::utxo_scanner paths.

crates/wallet/sdk/src/models/mod.rs (2)

8-8: LGTM! Event module added to models.

This addition properly exposes the event module as part of the models layer, enabling the architectural consolidation of event types.


24-24: LGTM! Event types exported correctly.

The public re-export of event types makes them accessible via the models module, consistent with the refactoring goals.

applications/tari_walletd/src/handlers/rpc.rs (1)

5-5: LGTM! Import path updated correctly.

The AuthLoginRequestEvent import has been correctly updated to reference the models module.

crates/wallet/sdk_services/src/transaction_service/service.rs (2)

10-18: LGTM! Model imports expanded correctly.

The models import has been properly expanded to include all necessary event types, consolidating them from the previous events module.


35-35: LGTM! Notify import path updated.

The Notify import has been correctly updated to use the crate::notify path.

crates/wallet/sdk_services/src/account_monitor/monitor.rs (2)

19-19: LGTM! Import path updated correctly.

The WalletEvent import has been correctly updated to use the models module.


251-254: Event persistence added with appropriate error handling.

The addition of event logging via event_api().log_event() introduces the key new behavior of this PR—persisting wallet events for historical review. The error handling is appropriate:

  • Debug logging for event receipt helps with traceability
  • Warning on persistence failure is non-blocking, which is correct since event logging should not disrupt the main workflow
  • Errors are logged but not propagated, treating persistence as an auxiliary feature
applications/tari_walletd/src/services/mod.rs (2)

18-18: LGTM! Import path updated correctly.

The WalletEvent import has been correctly updated to reference the models module.


57-57: LGTM! UtxoRecovery wiring enhanced with event notification.

The addition of .with_notify(notify.clone()) properly wires the event notification system into the UtxoRecovery service, enabling it to emit events that will be persisted via the new event logging functionality.

crates/wallet/sdk_services/src/utxo_scanner/scanner.rs (1)

6-6: LGTM - Import path updated to reflect new module structure.

The import path for WalletEvent has been correctly updated to use the SDK models layer.

crates/wallet/sdk/src/storage/mod.rs (1)

39-42: LGTM - Trait bounds extended to enable event persistence.

The addition of WalletEventStoreWriter to the trait bounds enables write transactions to persist wallet events alongside other storage operations, maintaining transactional consistency.

crates/wallet/sdk/src/storage/writer.rs (1)

221-223: LGTM - Clean trait design for event persistence.

The WalletEventStoreWriter trait provides a focused interface for appending wallet events to storage. The implementation (visible in the SQLite writer) properly handles event serialization and account association.

crates/wallet/sdk_services/src/utxo_scanner/utxo_recovery.rs (1)

105-107: LGTM - Event emission optimized for empty batches.

The early return when the batch is empty avoids emitting unnecessary UtxoRecoveryStartedEvent and UtxoRecoveryCompletedEvent pairs. This is a sensible optimization, though it does change the observable behavior for consumers monitoring these events.

applications/tari_walletd/src/handlers/transaction.rs (1)

14-14: LGTM - Import paths updated to reflect module reorganization.

The imports correctly reference the new locations for WalletEvent (models) and TransactionServiceError (services).

crates/wallet/sdk_services/src/utxo_scanner/scanner_round.rs (1)

240-243: LGTM - Event enriched with account context.

The UtxoSpentEvent now includes the account_address field, providing better context for event consumers. This aligns with the PR's goal of enriching events with contextual information.

crates/wallet/storage_sqlite/migrations/2023-02-08-122514_initial/up.sql (1)

310-310: Consider foreign key behavior on account deletion.

The ON DELETE NO ACTION constraint means wallet events will remain if an account is deleted, which could lead to orphaned records. Verify this is intentional for audit trail purposes, or consider ON DELETE CASCADE if events should be removed with accounts.

crates/wallet/storage_sqlite/src/writer.rs (1)

1670-1716: LGTM! Event persistence implementation is solid.

The implementation correctly:

  • Extracts optional account addresses from each event variant
  • Serializes event payloads using JSON
  • Resolves account IDs from addresses when present
  • Handles missing accounts gracefully with optional()
  • Inserts event records with appropriate error handling
crates/wallet/sdk/src/apis/events.rs (3)

11-20: LGTM! API structure follows established patterns.

The EventsApi follows the same pattern as other APIs in the codebase (SubstatesApi, AccountsApi) with a store reference and simple constructor.


22-26: LGTM! Event logging implementation is correct.

The method properly delegates to the storage layer through a write transaction, ensuring events are persisted atomically.


41-51: LGTM! Error handling follows established patterns.

The error type correctly wraps WalletStorageError and delegates the IsNotFoundError trait implementation to the wrapped error.

crates/wallet/sdk_services/src/account_monitor/scanner.rs (4)

148-151: LGTM! Version tracking properly added.

The AccountChangedEvent now correctly includes the account version from the substate, enabling event consumers to track specific account state versions.


459-519: LGTM! Version tracking integrated correctly.

The changes properly:

  • Extract version from account substates (line 467)
  • Thread version through the processing logic (line 481)
  • Store account address and version tuples for later notification (line 517)

550-587: LGTM! Vault-associated account version tracking is correct.

The logic properly:

  • Checks if the account is known (line 550-557)
  • Retrieves the account substate version (lines 560-564)
  • Falls back to version 0 if account not found (line 564)
  • Includes version in updated_accounts tracking (line 587)

The fallback to version 0 is reasonable for edge cases where the account might not be in the database yet.


615-628: LGTM! Event notification properly includes version.

The notification loop correctly:

  • Iterates over updated accounts with versions
  • Constructs AccountChangedEvent with both address and version
  • Ensures downstream consumers receive complete state information
crates/wallet/sdk/src/models/event.rs (6)

19-19: LGTM! AuthLoginRequest variant now consistent with other events.

The variant now properly holds an AuthLoginRequestEvent payload, making it consistent with other WalletEvent variants and enabling proper serialization and handling.


26-30: LGTM! Event type discrimination and display are well-implemented.

The additions provide:

  • Type-level event discrimination via as_event_type() (lines 26-30)
  • Clean display formatting by delegating to WalletEventType (lines 92-96)

This is useful for logging, storage, and event filtering.

Also applies to: 92-96


98-157: LGTM! Serialization support enables event persistence.

All event structs now derive serde::Serialize, which is essential for:

  • Persisting events to the wallet_events table
  • Transmitting events over APIs
  • Logging and debugging

The serialization is consistently applied across all event types.


119-123: LGTM! Version field adds important context.

The version field in AccountChangedEvent enables consumers to:

  • Track specific account state versions
  • Correlate events with blockchain state
  • Detect and handle stale events

This aligns with the scanner changes that track and propagate version information.


153-157: LGTM! Account address context improves event utility.

Adding account_address to UtxoSpentEvent provides essential context about which account the spent UTXO belonged to, making the event more actionable for consumers.


159-206: LGTM! WalletEventType provides clean type-level event discrimination.

The implementation is well-designed:

  • Enum variants correspond 1:1 with WalletEvent variants (lines 159-171)
  • Display implementation provides consistent string representations (lines 173-189)
  • From implementation is exhaustive and correct (lines 191-206)

This enables filtering, storage, and logging without carrying event payloads.

Comment thread crates/wallet/storage_sqlite/src/schema.rs
@github-actions

github-actions Bot commented Nov 5, 2025

Copy link
Copy Markdown

Test Results (CI)

490 tests  +27   477 ✅ +14   1h 35m 25s ⏱️ + 44m 38s
 78 suites +15     0 💤 ± 0 
  2 files   + 1    13 ❌ +13 

For more details on these failures, see this check.

Results for commit 67083a9. ± Comparison against base commit f040d7c.

@sdbondi
sdbondi merged commit 9dddeb7 into tari-project:development Nov 5, 2025
9 of 12 checks passed
@sdbondi
sdbondi deleted the wallet-events branch November 5, 2025 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants