Skip to main content
Your user has funds on one chain and wants them on another, for example BTC on Bitcoin to L-USDT on Liquid. This is a chain swap. chainPairs() lists the routes on offer.

How it works

Your app creates a secret and locks funds on the source chain. The maker locks on the destination chain, to the same secret. Your app claims the maker’s lockup, which reveals the secret and lets the maker claim yours. If the maker never locks, your app refunds its own lockup. A chain swap uses two keys: a refund key for your lockup and a claim key for the maker’s.

Setup

The code on this page assumes this setup. It connects to the signet maker and loads your swap mnemonic. See Installation and Keys and recovery if you have neither yet.

Swap

1

Create the swap

The response has lockupDetails (where you lock) and claimDetails (where the maker locks for you). The SDK checks both against your keys.
2

Lock

Send exactly the expected amount to swap.lockupDetails.lockupAddress in one transaction.
3

Wait for the maker's lockup

The swap reaches transaction.server.mempool, then transaction.server.confirmed.
4

Claim the L-USDT

L-USDT pays its Liquid fee in L-BTC, so the claim is a caller-funded PSET: the SDK prepares a partial transaction, your Liquid wallet adds an L-BTC input for the fee and signs it, and the SDK finalizes it with your secret.
myLiquidWallet.fundAndSign stands for your wallet’s code: it takes the template’s pset, adds and signs an L-BTC input that covers the fee, and returns { pset, paymentOutputSecrets }. The swap ends in transaction.claimed.For a chain swap that pays out L-BTC or BTC instead, claim with claimScript.constructCooperativeClaim(preimage, params, lockupScript, refundKey.secretKey), which signs with your refund key against the lockup script, and fall back to constructClaim(preimage, { ...params, cooperative: false }) if the maker does not cooperate.

Accept a re-quote

If you locked a different amount than quoted, the maker can offer a new destination amount. Accepting it needs the swap’s swapAuth:
Without swapAuth the call fails with 401 invalid_swap_auth, and the swap expires into its refund.

If something goes wrong

Refund your lockup with lockupScript.constructRefund({ ...params, swapAuth: swap.swapAuth }), or let refundChainSwap choose between the cooperative and script paths. Your refund uses the source chain’s deadline; your claim uses the destination chain’s.
USDT-RGB is not a chain-swap asset. For BTC ↔ USDT-RGB on chain, use an atomic swap.