Add swaps.xyz swap provider - #480
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
3d2bdb3 to
9541abd
Compare
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 9541abd. Configure here.
9541abd to
c5ba82e
Compare
c5ba82e to
e1fae89
Compare
e1fae89 to
97ab5c4
Compare
97ab5c4 to
731100b
Compare
Integrate swaps.xyz (a MoonPay cross-chain DEX/bridge aggregator) as a new DEX swap plugin. The provider's getAction endpoint returns executable EVM calldata plus amountOut/amountOutMin and a token-approval flag, so the plugin builds an EVM spend (calldata memo + optional ERC20 approval pre-tx) modeled on the existing lifi plugin. Supports the EVM chains swaps.xyz confirms live; non-EVM VMs and unmapped chains are rejected with SwapCurrencyError.
c19f45c to
2414049
Compare
2414049 to
92f4d7b
Compare
Cover the plugin's typed swap errors end to end: drive fetchSwapQuote with a faked io and wallets and assert SwapCurrencyError, SwapBelowLimitError and SwapAboveLimitError for the guard, getAction-error and success-response paths, plus one happy-path quote and a check that an unrecognized error code stays a plain Error rather than a mis-ranked swap error.
Top-level orientation for coding agents: build/test/verify commands, the central-vs-defi plugin split, the fetchSwapQuote pipeline, the typed-error ranking contract (and when a plain Error is correct), chain mappings, the pure-and-end-to-end testing patterns, and pointers to the docs/ guides and the .cursor/agents review sub-agents.
92f4d7b to
151ec8e
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 151ec8e. Configure here.
















CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
none
Description
Integrate swaps.xyz (a MoonPay cross-chain swap aggregator) as a new swap provider.
swaps.xyz exposes a REST API (
https://api-v2.swaps.xyz/api,x-api-keyauth).getPathsanswers whether a pair is routable and with what amount limits;getActionreturns the payload that executes it. It is classified as a CENTRALIZED provider (isDex: false,src/swap/central/swapsxyz.ts): every executable payload carries a swaps.xyz server signature from their fee module, and theiralt-vmbridges have raised KYC flags, so the venue is server-gated. The Edge DEX litmus asks whether the venue can refuse you, not whether defi appears in the implementation.One plugin, one
pluginId, absorbing all route types (precedent:rango,thorchain).getAction's payload shape depends on the SOURCE chain'svmId, andfetchSwapQuoteInnerdispatches on it:vmIdevm{to, data, value, chainId}requiresTokenApprovalis set.datais'0x'on a route into a non-EVM destination, which is a plain value send to the bridge and gets no memosolana{base64Tx, recentBlockhash, payer}VersionedTransactionhanded toSolanaEnginethroughspendInfo.otherParams.unsignedTx, asrangoandlifidoalt-vm{to, toExtra, value, chainId}toExtrabecomes the chain's memo/tag when the route supplies one (XRP destination tag, XLM memo)hypercoreis rejected withSwapCurrencyError(Edge ships no currency plugin for it), as is any non-DEFAULTexecutionsType.Registration.
requiresRegisterTransactioncomes backtrueon routes swaps.xyz does not broadcast itself; their docs make it mandatory for non-EVM transactions.makeSwapPluginQuotehas no post-broadcast hook, so the plugin wraps the returned quote'sapproveand POSTs{txId, txHash}to/registerTxsonce the hash exists. A registration failure is logged and swallowed: the swap is already on chain, and throwing would report a successful swap as failed.Limits.
getPathsreturnsminAmount/maxAmountas DECIMAL strings on the source token, not the base units the API reference claims. They are scaled bysrcToken.decimalsbefore any comparison (a floor rounds up, a ceiling rounds down, so a sub-unit residue on a low-decimal token can never widen the allowed range). Amaxrequest clamps to the route ceiling instead of failing.Files:
src/swap/central/swapsxyz.ts—makeSwapsXyzPlugin. Resolves chain ids and token addresses (native = zero address on every VM), callsgetPathsthengetAction, classifies errors (unsupported chain/token/route and an unpayable destination address →SwapCurrencyError, below min / zero output →SwapBelowLimitError, over max →SwapAboveLimitError, unrecognized codes stay a plainErrorso the core does not mis-rank them), and builds the spend per route model. A pure, exportedmakeSwapsXyzSpendInfodoes the response →EdgeSpendInfotranslation for unit testing.src/mappings/swapsxyz.ts—EdgeCurrencyPluginId → numeric chainId, covering the EVM chains plus the 26 non-EVM chains both Edge and swaps.xyz ship, each cross-checked against the liveGET /getChainList.vmIddisambiguates ids that belong to an EVM sibling: 314 is taggedalt-vmand a livegetActionreturns anf1…deposit address, so it is native Filecoin, not Filecoin FEVM (this corrects the earlierfilecoinfevm → 314entry).src/index.ts— registersswapsxyz.test/swapsxyz.test.ts— unit tests for the pure spend-info construction per route model (EVM native/token, empty calldata, solana native/token, alt-vm with and without a memo) plus end-to-endfetchSwapQuotecoverage: the pre-network guards, thegetPathslimit pre-check including decimal scaling, thegetActionerror classification into each typed swap error, the success-response guards, the registration callback firing only when required, and happy-path quotes for EVM and alt-vm sources. Driven with a fakedio.fetchCorsand faked wallets, followingtest/nym.test.ts.AGENTS.md— a top-level orientation for coding agents on this repo: what the package is and why, the exact verification commands and non-obvious tooling (nycsupplies thesucrase/registerhook, so plainnpx mochacannot load TypeScript), the central-vs-defi split and why it is about the venue rather than the payload, thefetchSwapQuotepipeline, the typed-error ranking contract, and an index intodocs/. Written against theagents-mdguidance that lives in the agent orchestration tooling: kept short because the file enters every session for this repo, with the directory listing, pasted snippets, and lint-enforced style rules deliberately left out.Runtime key comes from the GUI env as
SWAPSXYZ_INIT.apiKey(wiring PR: EdgeApp/edge-react-gui#6128).Verification:
npm run verifypasses (prepare + lint + types + test). Exercised against the live swaps.xyz API end-to-end, and driven in-app on the iOS sim to a real executed swap for EACH route model — see the attached test-evidence screenshots (quote "Powered by swaps.xyz" → executed-swap success scene):Known provider constraint: swaps.xyz pays only
t3…Zcash addresses, rejectingt1…and unifiedu1…, so Zcash destinations come back asINVALID_ADDRESS_FORMATand are surfaced asSwapCurrencyError.Asana: https://app.asana.com/0/1215088146871429/1217036054017879
Note
Cursor Bugbot is generating a summary for commit 151ec8e. Configure here.