You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adding a chain or a swapper to the app is not the same as making it work over the public API. There are two API-side steps that are easy to miss because they live in a different package from the swapper work, and skipping either fails silently — transformQuoteStep (routes/quote/utils.ts:96) assigns transactionData: undefined without complaint, and an unlisted swapper is simply never queried.
This ticket tracks those two steps as a known, recurring implementation requirement. The per-chain and per-swapper work itself lives in Chains, Swappers, Functionality.
Step 1 — extractor coverage, per chain
extractTransactionData (packages/public-api/src/routes/quote/extractTransactionData.ts:85-103) branches on chain namespace. A namespace it doesn't handle returns undefined, and the chain is rejected as a sell asset by isExecutableSellChainId.
For each new chain namespace:
Add the TxBuildData variant in packages/swapper/src/types.ts (if absent)
Have the relevant swappers populate it at quote time
Add the extractor branch in extractTransactionData.ts
Add the wire schema in routes/quote/types.ts and packages/types/src/api.ts
Add the namespace to EXECUTABLE_CHAIN_NAMESPACES in packages/public-api/src/constants.ts — this and the extractor must widen together, or we either advertise a sell chain we can't serialize or silently drop tx data
Move the chain out of NON_SELLABLE in integration.test.ts
A swapper absent from ENABLED_SWAPPER_NAMES (packages/public-api/src/constants.ts) is never queried by /v1/swap/rates and is rejected by /v1/swap/quote, regardless of how complete its swapper-package implementation is.
For each swapper:
Confirm it emits TxBuildData in a namespace the extractor handles — not a legacy getUnsignedXTransaction endpoint, and not a bespoke step field
This ticket closes when both steps are documented somewhere a contributor adding a chain or swapper will actually encounter them — the swapper-integration contract in .claude/contracts/swapper-integration.md and the second-class-chain contract are the natural homes. Until then the steps keep getting rediscovered after the fact.
Why this exists
Adding a chain or a swapper to the app is not the same as making it work over the public API. There are two API-side steps that are easy to miss because they live in a different package from the swapper work, and skipping either fails silently —
transformQuoteStep(routes/quote/utils.ts:96) assignstransactionData: undefinedwithout complaint, and an unlisted swapper is simply never queried.This ticket tracks those two steps as a known, recurring implementation requirement. The per-chain and per-swapper work itself lives in Chains, Swappers, Functionality.
Step 1 — extractor coverage, per chain
extractTransactionData(packages/public-api/src/routes/quote/extractTransactionData.ts:85-103) branches on chain namespace. A namespace it doesn't handle returnsundefined, and the chain is rejected as a sell asset byisExecutableSellChainId.For each new chain namespace:
TxBuildDatavariant inpackages/swapper/src/types.ts(if absent)extractTransactionData.tsroutes/quote/types.tsandpackages/types/src/api.tsEXECUTABLE_CHAIN_NAMESPACESinpackages/public-api/src/constants.ts— this and the extractor must widen together, or we either advertise a sell chain we can't serialize or silently drop tx dataNON_SELLABLEinintegration.test.tsOutstanding: Tron (#12561), Sui (#12562), TON (#12563), NEAR (#12564), Starknet (#12565).
Done:
eip155,bip122,cosmos,solana.Step 2 — swapper enablement
A swapper absent from
ENABLED_SWAPPER_NAMES(packages/public-api/src/constants.ts) is never queried by/v1/swap/ratesand is rejected by/v1/swap/quote, regardless of how complete its swapper-package implementation is.For each swapper:
TxBuildDatain a namespace the extractor handles — not a legacygetUnsignedXTransactionendpoint, and not a bespoke step fieldENABLED_SWAPPER_NAMESintegration.test.tsReady today, blocked only on this step: Across (#12566), Arbitrum Bridge (#12567), deBridge (#12568).
Blocked on step 1 or on a migration: BOB Gateway (#12569), Cetus (#12570), Sun.io (#12571), AVNU (#12572), STON.fi (#12573).
Blocked on a wire shape: CoW Swap (#12559).
Definition of done
This ticket closes when both steps are documented somewhere a contributor adding a chain or swapper will actually encounter them — the swapper-integration contract in
.claude/contracts/swapper-integration.mdand the second-class-chain contract are the natural homes. Until then the steps keep getting rediscovered after the fact.