One row per Utila transaction — the analogue of solana_transaction, and
immutable for the same reason it is.
A transaction is written if and only if it reached the chain, which is
why there is no state column. Utila hands us terminal states, so the test
runs once, at a known-final moment: a confirmed transaction gets a full row,
one that reverted on chain gets a fee-only row (it burned gas), and anything
that never reached the chain — declined, cancelled, dropped, expired,
AML-declined — moved nothing, cost nothing, and gets no row.
Existence in this table is the state. Storing it would be storing a
constant: a row means the chain took money, and the only question a reader
ever asks is how much. Nothing pending is recorded and no row ever changes
after insert, which is what makes the write onConflictDoNothing on
(vault_id, utila_id) exactly as solana_transaction does — and that is
what lets the webhook fast path and the scheduled poll backstop race safely
without coordinating.
See docs/proposals/UTILA_TRANSACTION_SYNC.md § 3.1 and § 3.5.
One row per Utila transaction — the analogue of
solana_transaction, and immutable for the same reason it is.A transaction is written if and only if it reached the chain, which is why there is no
statecolumn. Utila hands us terminal states, so the test runs once, at a known-final moment: a confirmed transaction gets a full row, one that reverted on chain gets a fee-only row (it burned gas), and anything that never reached the chain — declined, cancelled, dropped, expired, AML-declined — moved nothing, cost nothing, and gets no row.Existence in this table is the state. Storing it would be storing a constant: a row means the chain took money, and the only question a reader ever asks is how much. Nothing pending is recorded and no row ever changes after insert, which is what makes the write
onConflictDoNothingon(vault_id, utila_id)exactly assolana_transactiondoes — and that is what lets the webhook fast path and the scheduled poll backstop race safely without coordinating.See docs/proposals/UTILA_TRANSACTION_SYNC.md § 3.1 and § 3.5.