Skip to content

Sell card and bank withdrawals through a Chainflip offramp lane - #87

Open
minato-32 wants to merge 6 commits into
mainfrom
feat/offramp-chainflip-lanes
Open

minato-32 wants to merge 6 commits into
mainfrom
feat/offramp-chainflip-lanes

Conversation

@minato-32

@minato-32 minato-32 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Why

Meld may have no provider that buys an Asset Hub asset in some regions. This keeps today's direct sale and adds a second way to sell: the CASH is redeemed for USDT, Chainflip swaps it to Solana USDC and pays it straight to the Meld provider's deposit address, and the provider pays out fiat.

Which way a sale goes

The quote reads the adapter's merged off-ramp catalog (GET /supported/offramp/corridors, GET /supported/offramp?country=). Each region's payout method names the lane that serves it, in the adapter's configured priority order:

  • DOT_ASSETHUB (or no lane): today's direct sale, unchanged.
  • USDC_SOLANA (or USDT_SOLANA): the Chainflip swap sale.
  • Anything else: no provider can pay out.

Needs paritytech/onramp-adapter-service-community#9, deployed with USDC_SOLANA in supported.offramp_lanes. Without it the catalog is unreachable and every region falls back to today's direct sale.

Swap sale flow

  1. Quote (sizeSwapSale): CASH → PSM redeem → USDT on the key, less 0.2% and the key's 0.1 USDT fee → Chainflip quote → 0.5% fill-or-kill floor, cut to 4 decimals → Meld sell quote in the lane's code.
  2. Sale (startSale): the sale carries lane; the hand-off runs the psm tier.
  3. Deposit: accepted only in the lane's currency and exact amount.
  4. Pay (paySale → openSwapSaleChannel): re-sized on today's quote; if the floor still covers the promise, a Chainflip channel (Asset Hub USDT → lane, paid to the provider's address, refunded to the key) is opened as handoff.swap; otherwise the sale ends with nothing taken.
  5. Worker: lands at least swap.amount USDT, checks Chainflip's channel pays the provider's address, sweeps all USDT into it (fee in USDT), follows Chainflip then Meld. A failed swap's refund is awaited up to 2 hours and sent home through the pool.

Networks

  • Test builds quote and open the swap on Perseverance; mainnet builds on mainnet. The onramp's Chainflip network is unchanged.
  • Perseverance does not watch Paseo Asset Hub Next, so on a test build the key's payment never reaches the channel and the test USDT is lost; the dev Skip ends the rail.
  • Meld's sandbox only quotes a sale, so a real end-to-end sale needs a mainnet build.

Known limits

  • What Chainflip delivers above the floor (up to ~0.5%) goes to the provider.
  • Providers that check the sending wallet (Banxa) cannot be used on the swap path.
  • A provider refund on Solana has no address of ours to land on.
  • Meld codes are USDC_SOLANA / USDT_SOLANA. Meld sandbox quotes USDC but not USDT on Solana, so the swap lane is USDC.
  • DOT_ASSETHUB has no Meld sell routes today, so every region currently resolves to the swap lane.

Tests

pnpm test, pnpm typecheck, pnpm typecheck:packages, pnpm format:check and pnpm build:worker pass locally. New: swap sizing and channel opening, worker swap sale, Chainflip-then-Meld status, off-ramp catalog reads, lane choice; additions to the sale reducer, Meld sell, Chainflip channel, sweep and offramp package tests.

…framp lane

Where Meld has no provider for an Asset Hub asset, a card or bank sale can go
through an offramp lane (VITE_MELD_SELL_LANE=usdt-solana | usdc-solana). The
CASH is redeemed for USDT through the PSM, the key sweeps it into a Chainflip
channel, and Chainflip pays the lane's asset straight to the Meld provider's
deposit address.

- packages/offramp: the lane catalog and the fill-or-kill floor a sale commits
  to.
- Quote: the USDT the PSM lands, a Chainflip quote on the least the key holds,
  and Meld quoted on its 0.5% floor in the lane's currency.
- Pay: the page re-sizes on today's quote and opens the Chainflip channel to
  the provider's address only while the floor still covers the promise.
- Worker: lands at least the quoted USDT, checks Chainflip's channel pays the
  provider, sweeps USDT (fee in USDT), follows Chainflip then Meld, and sends a
  failed swap's refund home through the pool.
- Test builds quote and open the swap on Perseverance; mainnet builds on
  mainnet. The onramp's Chainflip network is unchanged.
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

pr87-getcash.paseo · logs

https://pr87-getcash.paseo.li

…e off-ramp catalog

The sale quote reads the adapter's merged off-ramp catalog instead of one
destination's sell catalog. Each region's payout method names the lane that
serves it: today's Asset Hub sale (DOT_ASSETHUB) where a provider buys it,
otherwise a Chainflip lane such as USDT_SOL. The direct sale is unchanged; the
swap sale only runs where the catalog says no provider buys the Asset Hub asset.

Drops the VITE_MELD_SELL_LANE flag, its build input and the preview override.
Meld's CRYPTO_OFFRAMP catalog names the Solana stablecoins USDT_SOLANA and
USDC_SOLANA, with the same mint contracts as the lanes.
…irst

The adapter now lists every lane that routes a payout method. The page
tries them best first (the direct Asset Hub sale, then USDC on Arbitrum,
then USDC on Solana) and falls through to the next when a lane's
providers give no usable quote. VITE_OFFRAMP_LANES sets the order and
turns a chain off by leaving it out.

Each lane keeps its own buffers: the slippage the swap may lose, and
headroom over Chainflip's egress fee so the sale commits only what
lands.
@minato-32
minato-32 marked this pull request as ready for review October 9, 2026 10:12
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