Skip to content

Move unconfirmed outgoing restore eligibility semantics from Swift to platform-wallet #4700

Description

@coderabbitai

Summary

Move the transaction-context and block-height eligibility decision for unconfirmed outgoing transaction replay from the Swift SDK into platform-wallet, exposed through rs-platform-wallet-ffi.

Swift must continue to load PersistentTxo rows, resolve SwiftData relationships, preserve legacy walletId routing, and marshal selected transaction records. Swift must not decide whether a spender context is settled for spend purposes.

Rationale

PlatformWalletPersistenceHandler.buildUnconfirmedOutgoingTxRecordBuffer currently checks spender.context and spender.blockHeight to decide whether a transaction is eligible for replay. These fields encode wallet-state semantics. The current alignment with spendIsInBlock reduces drift, but it does not remove duplicate policy.

A small Rust-owned FFI predicate can make platform-wallet the single owner of this semantic rule without requiring Swift to send every SwiftData relationship to Rust.

The write-side spendIsInBlock behavior and the restore-side eligibility behavior must move together. Otherwise Swift persistence and Rust restoration can disagree about whether an input remains unspent.

Affected areas

  • packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletPersistenceHandler.swift
    • spendIsInBlock
    • buildUnconfirmedOutgoingTxRecordBuffer
  • packages/rs-platform-wallet
    • Define the authoritative settled-spend / replay-eligibility rule.
  • packages/rs-platform-wallet-ffi
    • Expose the minimal predicate required by Swift.

Required changes

  1. Add a platform-wallet API that owns the context and block-height decision used to determine whether an outgoing spender remains eligible for replay.
  2. Expose that API through rs-platform-wallet-ffi.
  3. Replace the Swift checks of spender.context and spender.blockHeight with the FFI predicate.
  4. Keep Swift-owned persistence work in Swift:
    • Find TXO-linked spenders.
    • Check persisted relationship liveness and isSpent.
    • Route legacy TXO rows through their owning account when walletId is absent.
    • Exclude asset-lock funding transactions.
    • Marshal records into UnconfirmedOutgoingTxRecordFFI.
  5. Update the write-side spendIsInBlock use so it obtains the same semantic result from the Rust-owned rule.
  6. Add Rust and Swift tests for mempool, InstantSend-locked, in-block, and invalid or inconsistent block-height combinations.

Acceptance criteria

  • platform-wallet is the only owner of transaction-context and block-height eligibility semantics for unconfirmed outgoing replay.
  • Swift does not contain an independent policy condition over PersistentTransaction.context or PersistentTransaction.blockHeight for this decision.
  • The write path and restore path use the same Rust-owned rule.
  • Swift retains only SwiftData selection, legacy-row routing, asset-lock exclusion, and FFI marshalling responsibilities.
  • Tests cover the supported context cases and prevent a future divergence.

Backlinks

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions