All checks were successful
check / check (push) Successful in 25s
A plain ERC-20 transfer produced two rows: the token-transfer row and the zero-ETH native row for the same hash. parseTx leaves method "transfer" out of the display-level contract-call case, so the merge loop's direction === "contract" test never absorbed the native side. The merge is now the pure mergeTransactions(txs, tokenTransfers) in src/shared/transactions.js, unit tested directly. It keys the native entry by hash and each token transfer by hash plus token contract, and drops the native entry when it moved no ETH and a token transfer shares its hash. A native entry that moved ETH survives beside the token rows, a zero-value native transaction with no token transfer on its hash still displays, and a display-level contract call keeps consolidating its legs into one row. The dust filter's isContractCall exemption is unchanged: it still carries approve and other zero-ETH calls that have no token row to be represented by.