Skip to content

feat: preserve transaction status (mempool/IS-locked/confirmed/chain-locked) in TransactionRecord #569

@lklimek

Description

@lklimek

User Story

As a wallet application developer, I want TransactionRecord to carry the transaction's lifecycle status (mempool → IS-locked → confirmed → chain-locked) so that I can display meaningful status indicators to users without re-deriving state from height/block_hash fields.

Problem

TransactionContext already distinguishes Mempool, InBlock, and InChainLockedBlock — but record_transaction() in ManagedAccount discards the variant after extracting height/block_hash:

// managed_account/mod.rs:385-390
let tx_record = TransactionRecord {
    height: context.block_height(),      // Some(h) or None
    block_hash: context.block_hash(),    // Some(hash) or None
    // TransactionContext variant is lost here
    ...
};

Consumers (like dash-evo-tool) can only infer height.is_some() → confirmed vs unconfirmed, losing the richer status information that was available at recording time.

Requested Changes

1. Add status field to TransactionRecord

pub struct TransactionRecord {
    // ... existing fields ...
    /// Transaction lifecycle status
    pub status: TransactionContext,
}

Preserve the TransactionContext that's already passed to record_transaction().

2. Set Utxo.is_instantlocked on InstantSend lock receipt

The is_instantlocked field exists on Utxo and is used in coin selection (is_spendable(), coin_selection.rs), but is never set to true — it's initialized as false in Utxo::new() and no code path flips it.

When SyncEvent::InstantLockReceived fires, UTXOs belonging to the locked transaction should be updated.

3. Add status to WalletEvent::TransactionReceived

WalletEvent::TransactionReceived {
    // ... existing fields ...
    status: TransactionContext,
}

So consumers know if a received transaction is mempool/confirmed/chain-locked without re-querying the wallet.

4. (Nice to have) Add WalletEvent::TransactionStatusChanged

WalletEvent::TransactionStatusChanged {
    wallet_id: WalletId,
    txid: Txid,
    old_status: TransactionContext,
    new_status: TransactionContext,
}

Fires on status transitions (Mempool → IS-locked → Confirmed → ChainLocked), enabling reactive UI updates.

Context

dash-evo-tool PR dashpay/dash-evo-tool#776 integrates the MempoolManager with BloomFilter strategy. With mempool tracking active, the wallet now sees unconfirmed transactions — but we cannot distinguish them from IS-locked transactions in the UI because the status information is discarded upstream.

We're adding a TransactionStatus enum on the evo-tool side and inferring what we can from height, but full lifecycle tracking requires these upstream changes.

🤖 Co-authored by Claudius the Magnificent AI Agent

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions