feat(api): add 22 missing Transaction variants and Unknown catchall -- fixes #41#42
Open
leftygbalogh wants to merge 2 commits intogmosx:mainfrom
Open
feat(api): add 22 missing Transaction variants and Unknown catchall -- fixes #41#42leftygbalogh wants to merge 2 commits intogmosx:mainfrom
leftygbalogh wants to merge 2 commits intogmosx:mainfrom
Conversation
added 2 commits
April 5, 2026 16:29
gmosx#41 Tests added across three production embedding paths where Transaction deserialization failure manifests: - xrpl_api/src/types/transaction.rs: 24 tests (22 per missing variant + Unknown catchall + regression guard for pre-existing variants) - xrpl_api/src/api/account_tx.rs: AccountTxResponse batch path - xrpl_api/src/api/tx.rs: TxResponse single-lookup path - xrpl_api/src/events/transaction.rs: TransactionEvent / WebSocket stream path All tests are currently failing. Implementation follows in next commit.
…ixes gmosx#41 The Transaction enum uses #[serde(tag = "TransactionType")]. 22 XRPL protocol variants activated by amendments after the enum was written were missing, causing a hard Err("unknown variant") on any payload for those types. Fix: - 22 variants added as VariantName(TransactionCommon). Each carries a BASELINE comment: variant-specific fields are not modelled and are silently dropped (progressive disclosure; field modelling follows in per-family PRs). - #[serde(other)] Unknown unit variant added as a forward-compatibility catchall. Any future or currently-unknown TransactionType string maps to Unknown instead of returning Err. - common() / common_mut() updated for all new variants. Unknown arms use unreachable!() -- callers must match on Unknown before calling common() when handling stream events defensively. Variants added by amendment family (audited against xrpl.org/amendments.html, 2026-04-05): AMM: AMMBid, AMMCreate, AMMDelete, AMMDeposit, AMMVote, AMMWithdraw Clawback: Clawback DID: DIDDelete, DIDSet Oracle: OracleDelete, OracleSet Pseudo-tx: EnableAmendment, SetFee, UNLModify XChain: XChainAccountCreateCommit, XChainAddAccountCreateAttestation, XChainAddClaimAttestation, XChainClaim, XChainCommit, XChainCreateBridge, XChainCreateClaimID, XChainModifyBridge Real-payload fixture tests (sourced from xrpl.org protocol docs, 2026-04-05): - AMMCreate: flat variant fields (Amount, Amount2, TradingFee) dropped - OracleSet: nested PriceDataSeries array dropped - XChainCreateBridge: nested XChainBridge object (4 sub-fields) dropped - AMMDeposit: multi-field mix (Asset, Asset2, Amount, Amount2) dropped
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(api): add 22 missing
Transactionvariants andUnknowncatchallProblem
The
Transactionenum inxrpl_apiuses#[serde(tag = "TransactionType")]for deserialization. 22 XRPL protocol-level transaction types were missing from the enum. When any of these types appears in an inbound payload, Serde returns a hardErr("unknown variant \"…\""), with no recovery path.In practice this means:
Transactionin the stream aborts the entireTransactionEventpipeline (the path issue Query Around TransactionType Support #41 reporter hit).account_txbatch responses abort — a single unrecognised type in theVec<AccountTransaction>fails the whole deserialization. A commented-out// pub tx: serde_json::Valueinaccount_tx.rsshows a previous developer already hit this.Transaction(e.g.,TxResponse,AccountTxResponse) is affected.Fixes #41. Related: #39.
Solution
1. 22 missing variants added
Each missing variant is added as
VariantName(TransactionCommon). This preserves deserialization of all common fields (Account,Fee,Sequence, flags, memos, signers, etc.) while silently dropping variant-specific fields.BASELINE contract — intentional lossy deserialization:
Variant-specific fields (e.g.,
AmountonAMMCreate,PriceDataSeriesonOracleSet,XChainBridgeonXChainCreateBridge) are not modelled and are silently dropped by Serde on deserialization. Each new variant carries a// BASELINE: variant-specific fields are not modelled and are silently droppedcomment to make this explicit. Callers requiring variant-specific data should deserialize toserde_json::Valueuntil those fields are modelled in follow-up PRs.Variants added by amendment family (audited against xrpl.org/amendments.html, 2026-04-05):
AMMBid,AMMCreate,AMMDelete,AMMDeposit,AMMVote,AMMWithdrawClawbackDIDDelete,DIDSetOracleDelete,OracleSetEnableAmendment,SetFee,UNLModifyXChainAccountCreateCommit,XChainAddAccountCreateAttestation,XChainAddClaimAttestation,XChainClaim,XChainCommit,XChainCreateBridge,XChainCreateClaimID,XChainModifyBridge2.
#[serde(other)] Unknownforward-compatibility catchallA
Unknownunit variant is added with#[serde(other)]. AnyTransactionTypestring not present in the enum — including future amendment-gated types — deserializes toUnknownrather than returningErr. This prevents stream and batch aborts on types that postdate this PR.Unknowncontract:Unknownis a unit variant (carries no inner data — a constraint of#[serde(other)]with an internally-tagged enum).transaction.common()andtransaction.common_mut()are unreachable onUnknownand will panic withunreachable!()if called. Callers should match onTransaction::Unknownbefore callingcommon()when handling events from unknown transaction types.3.
common()/common_mut()updatedAll 22 new named variants are handled identically to existing
TransactionCommon-wrapping variants.Unknownarms useunreachable!().Test coverage
50 tests pass, 0 failing, across the full workspace.
test_deserialize_<VariantName>test_deserialize_unknown_variant_does_not_panicUnknowncatchall — unrecognisedTransactionTypeno longer returnsErrtest_deserialize_existing_variants_still_worktest_account_tx_response_fails_on_unknown_transaction_typeAccountTxResponsebatch embedding pathtest_tx_response_fails_on_unknown_transaction_typeTxResponsesingle-lookup embedding pathtest_transaction_event_fails_on_unknown_transaction_typeTransactionEvent/ WebSocket stream pathtest_amm_create_real_payload_common_fields_correct_variant_fields_droppedAmount,Amount2,TradingFee) silently droppedtest_oracle_set_real_payload_nested_array_silently_droppedPriceDataSeriesarray silently droppedtest_x_chain_create_bridge_real_payload_nested_object_silently_droppedXChainBridgeobject silently droppedtest_amm_deposit_real_payload_multi_field_silently_droppedFixture JSON payloads are sourced from official XRPL documentation examples (xrpl.org) and verify the BASELINE lossy contract under realistic conditions.
CI
Out of scope / follow-up
Option<&TransactionCommon>return type oncommon()/common_mut()— deferred; would be a breaking public API change; warrants its own discussion.