AUDIT4-1 fix: switch tx_status from Koios /tx_info to /tx_status

The old impl called Koios /tx_info to learn confirmation state. For
confirmed txs that endpoint streams the full tx body — multi-MB on
complex txs, hundreds of KB on trivial ones — and the public Koios
endpoint either rate-limits or chunks slowly enough to escape our
10s reqwest timeout. Result: wallet_tx_status hung 120s+ and the
container subprocess died, surfaced 2026-05-04 audit-4 phase C7.

Fix: call the lighter /tx_status endpoint, which returns a single
{tx_hash, num_confirmations} record per tx — bytes, not MB.

API change: TxStatus::Confirmed { block_height, epoch } becomes
TxStatus::Confirmed { num_confirmations }. The endpoint doesn't
return block_height / epoch anyway; num_confirmations is what
callers actually want for polling-until-final flows. wallet_tx_status
docstring updated to spell out the three returnable shapes.

Tests: drops the KoiosTxInfo-shape unit tests, adds
parses_koios_tx_status_shapes covering the three live response
shapes we observed (confirmed-with-count, known-but-no-confs,
empty array).
This commit is contained in:
Sulkta 2026-05-04 20:45:10 -07:00
parent 6ed378a486
commit 7cb70db12b
3 changed files with 52 additions and 49 deletions

View file

@ -65,19 +65,16 @@ pub struct Balance {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "status", rename_all = "snake_case")]
pub enum TxStatus {
/// Confirmed on-chain with a block height.
Confirmed {
block_height: u64,
epoch: Option<u64>,
},
/// Koios returned a record but no block_height — the tx is in
/// the chain backend's mempool but not yet in a confirmed block.
/// (L-3 audit fix: previously this case was lumped in with
/// Confirmed and rendered as `Confirmed { block_height: None }`,
/// which is misleading.)
/// Confirmed on-chain with `num_confirmations` blocks built on
/// top of it (1 = just landed, ~15 = practically final on
/// preprod, ≥3 stake-pool epochs = absolute finality on mainnet).
Confirmed { num_confirmations: u64 },
/// Koios's `/tx_status` returned a record for this tx but with
/// `num_confirmations: null` — the tx is known to the backend
/// (some node accepted it) but is not yet in a block.
Pending,
/// Not seen by the chain backend (not in mempool, not confirmed,
/// possibly never submitted or rejected).
/// Not seen by the chain backend (not in any node's pool,
/// not confirmed, possibly never submitted or rejected).
NotFound,
}