The swap arm of the 12-arm transaction UNION, as a view.
Same motivation as depositTransactionView: assembled inline the union
serialises well past the 16KB statement limit RDS Proxy will parse, and a
statement over that limit pins the client session to its database connection
for the rest of the session. Behind a view the runtime statement is ~90
bytes.
The caller-supplied filters live in transaction-services/queries/swap.ts as
predicates on this view's own projected columns, because a view takes no
parameters. They are plain contract-column comparisons emitted by the shared
transactionScalarConditions, so what matters here is what each filtered
column projects:
customer_id — the swap's own customer_external_id copy.
signature — the row's own receipt entry. On a quote-backed swap's one row
and a DEPOSIT swap's target credit, the MOVEUSD credit: the
SOLANA_TRANSACTION_SIGNATURE entry with no leg, one per swap. On a
DEPOSIT swap's landing, its DEPOSIT entry; on its source debit, its
SWEEP entry.
status — the swap's own.
A quote-backed swap is one row, its MOVEUSD side. A DEPOSIT swap
(source = 'DEPOSIT') is up to three: the CREDIT of what landed (sub_type
DEPOSIT), and once priced, the DEBIT of its source and the CREDIT of its
target after fees. Until priced it has no quote: its source is the deposited
token, and its entity the owner of its ledger account. Each row is one entry
of a LATERAL (VALUES …) over the swap, so the swap's joins plan once.
There is no bankIds filter — swaps don't touch a bank rail and this arm
always projects bank_id NULL.
Changing what those columns project silently changes the filters. The column
list must also stay identical to the sibling arms, or the UNION breaks.
securityInvoker is required, not cosmetic — every underlying table has RLS
enabled, and without it the view would run with the owner's row visibility
and silently bypass the querying role's policies.
The swap arm of the 12-arm transaction UNION, as a view.
Same motivation as
depositTransactionView: assembled inline the union serialises well past the 16KB statement limit RDS Proxy will parse, and a statement over that limit pins the client session to its database connection for the rest of the session. Behind a view the runtime statement is ~90 bytes.The caller-supplied filters live in
transaction-services/queries/swap.tsas predicates on this view's own projected columns, because a view takes no parameters. They are plain contract-column comparisons emitted by the sharedtransactionScalarConditions, so what matters here is what each filtered column projects:leg, one per swap. On a DEPOSIT swap's landing, itsDEPOSITentry; on its source debit, itsSWEEPentry.A quote-backed swap is one row, its MOVEUSD side. A DEPOSIT swap (
source = 'DEPOSIT') is up to three: the CREDIT of what landed (sub_typeDEPOSIT), and once priced, the DEBIT of its source and the CREDIT of its target after fees. Until priced it has no quote: its source is the deposited token, and its entity the owner of its ledger account. Each row is one entry of aLATERAL (VALUES …)over the swap, so the swap's joins plan once.There is no
bankIdsfilter — swaps don't touch a bank rail and this arm always projects bank_id NULL.Changing what those columns project silently changes the filters. The column list must also stay identical to the sibling arms, or the UNION breaks.
securityInvokeris required, not cosmetic — every underlying table has RLS enabled, and without it the view would run with the owner's row visibility and silently bypass the querying role's policies.