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

@ -466,7 +466,7 @@ impl WalletService {
#[tool(
name = "wallet_tx_status",
description = "Poll a submitted transaction's confirmation status. Args: tx_hash (hex). Returns JSON {status: confirmed|not_found, block_height?, epoch?}."
description = "Poll a submitted transaction's confirmation status. Args: tx_hash (hex). Returns JSON {status: confirmed|pending|not_found, num_confirmations?}. `confirmed` means the tx has at least 1 block built on top; `pending` means a node has accepted it but it's not yet in a block; `not_found` means no node knows about it (rejected, never submitted, or still propagating)."
)]
async fn wallet_tx_status(
&self,