Skip to content

DPNS departure tracking is session-scoped, so username ownership and marketplace departure classification cannot both stay correct #5019

Open

Description

@romchornyi

Expected Behavior

When a wallet-owned identity loses a DPNS name (sold, transferred or deleted outside the wallet), the local owned-name list drops it, and the marketplace sweep still classifies the departure (sale / transfer / deletion, history, sale-triggered balance refresh). This holds across restarts and failed sweep passes. A stale snapshot from the previous owner never changes the new owner's state.

Current Behavior

The DPNS marketplace sweep discovers departures only from ManagedIdentity.dpns_names and the session-scoped dpns_name_states (departure_candidates, sync_dpns_marketplace). dpns_name_states starts empty on every load (manager/load.rs). The owned-name list is therefore both the current-ownership record and the only durable departure trigger, and no choice for username fetches keeps both correct:

  1. Prune on a complete username fetch. Ownership is right, but a label pruned before the next sweep loses its only trigger. An in-memory pending-departure queue was tried in fix(sdk): keep the chosen DPNS name across wallet sync #4978 (78b0e0e); it does not survive a restart or a failed resolution.
  2. Keep labels for wallet-owned identities (fix(sdk): keep the chosen DPNS name across wallet sync #4978 as merged, apply_fetched_dpns_names). Departures stay with the sweep, but:
    • A complete refresh_dpns_names() (loading.rs) with an empty result leaves the departed name in the list while marketplace sync is not running (DpnsSyncManager is not auto-started), and later snapshots keep advertising it as owned.
    • After an external A→B transfer, B's username sync rebinds the name row to B. Any later snapshot of A (for example a balance refresh) still carries the name, so the Swift persister rebinds the row back to A and clears B's mainDpnsName (rebind branch). The erased selection cannot be reconstructed.

Possible Solution

Separate the two concerns:

  • Departure work becomes durable. Persist pending departures alongside the ownership snapshot, e.g. a changeset / IdentityEntry field carried through FFI and restored on load. The sweep acknowledges an entry only after its reconciliation is durably applied, and keeps failed entries for later passes without blocking others.
  • Username fetches prune freely once departures are durable. A complete fetch then updates current ownership for wallet-owned identities too, and stale snapshots stop carrying departed names.
  • Rebinds become reversible. Clear another identity's selection only on confirmed departure evidence, not on a snapshot rebind; otherwise keep the selection and let read-time ownership (ownedMainDpnsName) hide it.

Steps to Reproduce (for bugs)

Found by code review of #4978 (review at c8ce2d8), not reproduced on a network. The review's scenarios:

  1. Wallet-owned identity holds alice; alice leaves it externally; call refresh_dpns_names() with marketplace sync not started. dpns_names still contains alice.
  2. Identities A and B in one wallet; alice transfers A→B externally; B's username sync runs; the user selects alice for B; a balance refresh for A emits a snapshot. The row rebinds to A and B's selection is cleared.

Context

Follow-up to #4978 (chosen DPNS name lost on every relaunch, support ticket 32382). The ticket's scenario is fixed and verified there. This issue covers ownership and departure edge cases the review surfaced, which need a durable departure store rather than another trade-off inside that PR.

Your Environment

platform v4.3-dev with #4978 (c8ce2d8b24), rs-platform-wallet + swift-sdk; testnet.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions