Skip to content

feat: add wallet-scoped activity storage#103

Merged
ovitrif merged 7 commits into
masterfrom
feat/wallet-scoped-activity
Jun 19, 2026
Merged

feat: add wallet-scoped activity storage#103
ovitrif merged 7 commits into
masterfrom
feat/wallet-scoped-activity

Conversation

@ben-kaufman

Copy link
Copy Markdown
Collaborator

Summary

  • Add wallet_id to activity, activity tag, and transaction detail data so multiple wallets can safely store overlapping activity IDs or transaction IDs.
  • Rebuild activity-related primary keys and migrations around wallet scope, defaulting pre-existing rows to the default Bitkit wallet ID.
  • Update activity/tag/transaction-detail APIs to accept wallet IDs where scope matters, while keeping global queries global where intended.
  • Harden tests for wallet-scoped collisions, migrations, tag backup/restore, transaction details, and preserving tags/seen state through upserts.
  • Update activity docs/examples and regenerate iOS, Android, and Python bindings with the minor version bump to 0.3.0.

Closes #102.

Validation

  • cargo test modules::activity passed: 155 tests
  • ./build.sh -r --minor all performed the version bump; after the initial sandbox DNS failure, ./build.sh all completed successfully
  • Android Maven local publish check passed during the build
  • git diff --check passed

@ben-kaufman ben-kaufman marked this pull request as ready for review June 19, 2026 09:03
@ovitrif

ovitrif commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Seems ok architecturally;

Though if noticed that it still looks up for pre-activity metadata by address or payment id only, then writes the tags into the wallet of the activity being inserted.

I reproduced this with Codex using the Python binding: metadata added for an address was attached to a hardware-wallet-1 activity with the same address.

Could we add wallet_id to PreActivityMetadata and pre_activity_metadata, default legacy rows to bitkit, and scope lookup/delete by wallet too?

@ovitrif

ovitrif commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

The top-level README still shows the old activity signatures without wallet_id, but this PR changes the exported activity API. Could we update this section too and mention get_default_wallet_id() so consumers following the root docs get the scoped API?

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed the latest push. The original PreActivityMetadata wallet-scope issue and the root README activity API docs issue are mostly addressed. I found a few follow-up points:

  1. src/modules/activity/implementation.rs:897

Could we make the bulk upsert path apply pending pre-activity metadata too? insert_activity transfers and deletes metadata, but upsert_onchain_activities, upsert_lightning_activities, and upsert_activities just write rows. I reproduced this through the Python binding: metadata tags stay pending and the inserted activity has no tags after upsert_onchain_activities. Android watcher sync is likely to use this bulk path, so hardware activities would miss the same tags and metadata support this PR is adding.

  1. src/modules/activity/implementation.rs:2546

Could we include is_receive = 1 in the address lookup used for received onchain transfers? Right now a metadata row for the same address with is_receive = false is selected for a received activity, then cleanup leaves it behind because it only deletes is_receive = 1. I reproduced this through the Python binding: the received activity got the sent-only tag and the pending row remained.

  1. src/lib.rs:1685

Should is_address_used take a wallet_id now too? It still counts any onchain activity matching address across all wallets. I reproduced a hardware-only activity making is_address_used(address) return true even though the default wallet had no matching activity. That can make the Bitkit wallet treat a hardware-wallet address as already used.

  1. src/modules/activity/README.md:286

Could we re-check these examples against the generated bindings? The Kotlin enum payloads are under v1, so foundActivity.txId and foundActivity.preimage will not compile, and there is an extra } after the catch block. The Python sample also omits required OnchainActivity fields like contact, created_at, updated_at, and seen_at, and some get_activities calls omit nullable parameters that the generated Python API still requires.

Local checks:

  • cargo fmt --check: passed
  • cargo test modules::activity: passed, 159 tests

Leaving this as a neutral review.

@ben-kaufman

Copy link
Copy Markdown
Collaborator Author

Thanks Ovi, pushed a follow-up in 8cde6b8 covering the review points:

  1. Bulk upserts now apply pending pre-activity metadata after the DB transaction commits for both onchain and lightning paths, so watcher-style restores/syncs attach tags and clear pending metadata the same way inserts do.
  2. Received onchain metadata lookup is now constrained to is_receive = 1. I also tightened add/restore replacement semantics so receive metadata only replaces previous receive metadata for the same wallet/address, while sent metadata using the same address can coexist.
  3. I left is_address_used(address) global intentionally. Since an address is globally unique, if any wallet has used it then it is used; a wallet-scoped variant feels like a separate helper/API decision rather than part of this PR.
  4. Rechecked and updated the README examples/docs: Kotlin uses enum payloads via v1, Python includes the required activity fields and nullable get_activities params, and the root/activity API docs include the wallet-scoped signatures.

Added regression coverage for the update/bulk metadata transfer and receive-address replacement cases. Latest local checks: cargo fmt --check, git diff --check, and cargo test modules::activity all pass (164 passed).

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed the latest push. The stale bulk-upsert, received-address lookup, and activity README example points are fixed in the Rust source, so I’m only leaving the two current follow-ups I could still verify.

Local checks:

  • cargo fmt --check: passed
  • git diff --check origin/master...HEAD: passed
  • cargo test modules::activity: passed, 164 tests
  • Python binding smoke test: import works, but the committed native artifact still reproduces the old metadata behavior noted below

Leaving this as a neutral review.

Comment thread bindings/python/bitkitcore/__init__.py
Comment thread src/modules/activity/implementation.rs Outdated
@ovitrif ovitrif changed the title Add wallet-scoped activity storage feat: add wallet-scoped activity storage Jun 19, 2026

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, thanks for addressing the follow-ups.

@ovitrif ovitrif merged commit cc1ff06 into master Jun 19, 2026
@ovitrif ovitrif deleted the feat/wallet-scoped-activity branch June 19, 2026 17:46
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.

feat: add wallet-scoped hardware wallet activities

3 participants