Skip to content

feat(exchange): add Chainflip provider - #1512

Draft
CumpsD wants to merge 1 commit into
cypherstack:stagingfrom
CumpsD:chainflip-baas-provider
Draft

CumpsD wants to merge 1 commit into
cypherstack:stagingfrom
CumpsD:chainflip-baas-provider

Conversation

@CumpsD

@CumpsD CumpsD commented Nov 12, 2026 •

Copy link
Copy Markdown

What this adds

A Chainflip exchange provider in lib/services/exchange/chainflip/, served through the Chainflip broker API at chainflip-broker.io ("BaaS" below), registered in Exchange.fromName, exchangesWithTorSupport, the provider selector, the currency cache and the trade-tracking view. It offers the Chainflip assets Stack Wallet holds (BTC, ETH, SOL, and the default USDC/USDT tokens on Ethereum and Solana) from the live BaaS GET /assets catalog, quotes via GET /quotes-native, opens deposit channels via GET /swap, and follows status by swap id or deposit channel.

  • Floating-rate only: fixed-rate and reversed quotes return explicit typed declines; no floating quote is dressed as fixed and no reversed quote is fabricated.
  • Exact native-unit conversion (including 18-decimal usdt.bsc/bnb.bsc; amounts finer than the asset's decimals are rejected, not truncated), and a real minimum from minimalAmountNative plus BaaS's hard quote cap.
  • Tor: the production onion endpoint (chainflip37gkyf3nkgufkolp2grpbchoysvro57wz3d3kurhhyj4zad.onion) through the existing SOCKS proxy, and membership of exchangesWithTorSupport. Clearnet uses https://chainflip-broker.io.
  • Statuses use the wallet's existing vocabulary (Waiting, Confirming, Exchanging, Sending, Completed, Failed, Refunded), so the trade card, colours and notifications render them correctly. BaaS reports refunds as completed with a refundEgress; a full refund maps to Refunded, a partial refund stays Completed with the refund in Trade.other, as is fallbackEgress.
  • Slippage floor: minimumPrice is the quote's estimatedPrice × (1 − recommended slippage), floored. An estimate is reused only for the same pair and amount; otherwise the trade requotes.
  • getTrades returns a typed "not supported" response: BaaS /swaps lists every swap under the partner key (all users of a build), not this wallet's trades. Like the other providers, the app does not call it.
  • Icon: the Color logomark (Logo/Logomark/CF-Original.svg) from Chainflip's official brand kit, unmodified.
  • Memo guard: a supplied destination or refund memo is rejected before any network call; the provider never silently drops a tag the recipient may need.

Key placement

The partner API key is a gitignored per-build constant kChainflipApiKey in lib/external_api_keys.dart, created by scripts/prebuild.sh, exactly like the seven sibling providers. The public GPLv3 source carries no credential; Cypher Stack's official builds carry their partner key. If you would rather not embed it, the alternative is a Cypher Stack-hosted proxy; the provider only reads the constant. With the constant empty, /assets still loads and keyed calls return an explicit "API key is not configured" decline; a test pins that path.

⚠️ Build note for maintainers: scripts/prebuild.sh only writes the template when lib/external_api_keys.dart is absent, so an existing keys file (and the CHANGE_NOW secret that CI decodes) needs const kChainflipApiKey = ""; (or the real key) appended, or the build fails to compile. The CI no-secret fallback and scripts/prebuild.ps1 templates are updated in this PR.

Scope and honesty

  • No Monero (BaaS has none).
  • Only assets Stack Wallet holds are offered. Chainflip also supports e.g. ETH on Arbitrum, USDT on BSC/Tron and Asset Hub; they are left out because "Send from" matches wallets by ticker, and adding them safely would need changes to shared exchange code.
  • No DCA, Boost or vault swaps; the UI has no surface for them.
  • No changes to the BaaS API.

Verification

  • dart format --output=none --set-exit-if-changed on the changed files: clean.

  • dart analyze on the changed files: no new issues (the remaining infos on touched lines are pre-existing deprecated color: usages that the formatter re-wrapped).

  • flutter test test/services/exchange/chainflip/: 29/29 pass.

  • Existing exchange-layer tests (test/services/exchange, test/models/exchange, test/pages/exchange_view, test/screen_tests/exchange): 63/63 pass.

  • Full flutter test: 1019 passed, 8 skipped, 3 failed. The 3 failures are setUpAll in test/wallets/{owned_input_signatures,receiving_address_index,spark_message}_test.dart, which cannot load libsecp256k1.so in a local build without native dependencies; none of those files are touched here.

  • API-contract evidence, gathered against the broker's full catalog rather than through this provider: a testnet quote matrix with every Chainflip chain as source and destination, and production /assets returning 20 assets without a key. The provider narrows those 20 to the 7 Stack Wallet holds.

  • The matrix was gathered with Python/urllib directly against the API, not through the Dart provider; with kChainflipApiKey empty, no provider code path has executed against a live endpoint. The unit tests inject a fake HTTP client. The evidence proves the API contract and the mapping logic separately, never together.

  • Upstream CI has not run on this PR yet: the fork's Test workflow runs are waiting for maintainer approval (action_required).

Draft status

This is a draft until the two human gates are done: a real end-to-end swap through a locally built wallet, and a quote plus channel-open over Tor. No key value or commission/earnings figure is included.

@CumpsD CumpsD changed the title feat(exchange): add Chainflip BaaS provider feat(exchange): add Chainflip provider Nov 13, 2026
@CumpsD
CumpsD force-pushed the chainflip-baas-provider branch from 79bff91 to ca9951b Compare November 13, 2026 01:09
Add a Chainflip exchange provider backed by the Chainflip broker API at
chainflip-broker.io.

- Offers the Chainflip assets Stack Wallet holds: BTC, ETH, SOL, and the
  default USDC/USDT tokens on Ethereum and Solana, from the live /assets
  catalog. Exact native-unit conversion, real minimums and the API's hard
  maximum.
- Floating-rate quotes via /quotes-native; fixed-rate and reversed quotes
  are declined explicitly. An estimate is reused only for the same pair and
  amount; minimumPrice is the quote's estimatedPrice minus the recommended
  slippage, floored.
- Deposit channels via /swap and status via /status-by-id or
  /status-by-deposit-channel, mapped onto the wallet's status vocabulary;
  only a full refund is reported as Refunded. Destination/refund memos are
  rejected.
- Tor: the production onion through the Tor proxy, listed in
  exchangesWithTorSupport.
- getTrades is declined: the broker's /swaps lists the whole partner's
  swaps, not this wallet's.
- Per-build key kChainflipApiKey in the gitignored external_api_keys.dart,
  added to the prebuild templates and the CI no-secret fallback.
- Icon: the Color logomark from Chainflip's official brand kit.
@CumpsD
CumpsD force-pushed the chainflip-baas-provider branch from ca9951b to 3469b6e Compare November 13, 2026 01:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant