fix(history): keep shielded txs in date order (they were stuck at the top)
History looked unsorted because every merged "shield" row carried confirmations=0, and the list sorts 0-conf (pending) transactions to the very top. So long-confirmed shielding transactions floated above newer ones — and when the type filter was switched off "All" they vanished (shield rows only match the "Sent" filter), which read as "transactions disappear when sorting". Root cause: the autoshield merge set the row's confirmations to min(send, recv). Both legs are the SAME transaction (one real confirmation count), but the send leg (parsed from z_viewtransaction) routinely arrives with confirmations=0, so min() picked 0. Use max() to take the populated value. Also give the sort a txid tiebreak so same-block transactions keep a stable order instead of reshuffling every time a new block bumps confirmations. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -425,7 +425,12 @@ void RenderTransactionsTab(App* app)
|
|||||||
dtx.is_shield = true;
|
dtx.is_shield = true;
|
||||||
dtx.amount = rtx.amount; // positive receive amount
|
dtx.amount = rtx.amount; // positive receive amount
|
||||||
dtx.timestamp = std::max(stx.timestamp, rtx.timestamp);
|
dtx.timestamp = std::max(stx.timestamp, rtx.timestamp);
|
||||||
dtx.confirmations = std::min(stx.confirmations, rtx.confirmations);
|
// Both legs are the SAME transaction, so they share one real confirmation
|
||||||
|
// count — but the send leg (from z_viewtransaction) often comes through
|
||||||
|
// with confirmations=0. min() would then make a long-confirmed shield look
|
||||||
|
// pending (conf==0), which the sort floats to the very top, out of date
|
||||||
|
// order. Take the populated value.
|
||||||
|
dtx.confirmations = std::max(stx.confirmations, rtx.confirmations);
|
||||||
dtx.address = rtx.address; // shielded destination
|
dtx.address = rtx.address; // shielded destination
|
||||||
dtx.from_address = stx.address.empty() ? stx.from_address : stx.address;
|
dtx.from_address = stx.address.empty() ? stx.from_address : stx.address;
|
||||||
dtx.memo = rtx.memo.empty() ? stx.memo : rtx.memo;
|
dtx.memo = rtx.memo.empty() ? stx.memo : rtx.memo;
|
||||||
@@ -456,13 +461,16 @@ void RenderTransactionsTab(App* app)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort: pending (0-conf) transactions first, then by timestamp descending
|
// Sort: pending (0-conf) transactions first, then newest-first by timestamp, with txid as
|
||||||
|
// a final deterministic tiebreak so same-block transactions keep a stable order across
|
||||||
|
// rebuilds (otherwise equal timestamps reorder every time a new block bumps confirmations).
|
||||||
std::sort(display_txns.begin(), display_txns.end(),
|
std::sort(display_txns.begin(), display_txns.end(),
|
||||||
[](const DisplayTx& a, const DisplayTx& b) {
|
[](const DisplayTx& a, const DisplayTx& b) {
|
||||||
bool aPending = (a.confirmations == 0);
|
bool aPending = (a.confirmations == 0);
|
||||||
bool bPending = (b.confirmations == 0);
|
bool bPending = (b.confirmations == 0);
|
||||||
if (aPending != bPending) return aPending;
|
if (aPending != bPending) return aPending;
|
||||||
return a.timestamp > b.timestamp;
|
if (a.timestamp != b.timestamp) return a.timestamp > b.timestamp;
|
||||||
|
return a.txid > b.txid;
|
||||||
});
|
});
|
||||||
|
|
||||||
s_display_cache_key = displayKey;
|
s_display_cache_key = displayKey;
|
||||||
|
|||||||
Reference in New Issue
Block a user