Swapping Guide
How to do Swaps Using THORChain
This guide builds on the Integration Overview and is specific for Swaps.

1. Displaying available pairs

Use the /pools endpoint of Midgard to retrieve all swappable assets on THORChain. Exampe is BTC Pool.

2. Calculating/Display Swap Fees

There are several types of fees included in a swap transaction:
  • Slippage (read more here)
  • Network fees
  • Affiliate fees

Calculating Slippage %

Slippage fees tax the user for how much the transaction will unbalance the pool, and is crucial to THORChain's CLP model. The formula for slippage is:
slippage=inputAmount(inputAmount+inputBalance) slippage = \frac{inputAmount}{(inputAmount + inputBalance)}
The result will be in basis points, so multiply by 100 to get the percentage
For a "double swap" (i.e. a swap between two non-RUNE assets) this formula will be used
twice, once for each pool the swap interacts with.
Midgard returns all values with 8 decimals places, so your user-entered from the amount
will need to be converted to the same.
Here's a reference implementation of calculating slip for a double swap:
// Calculate swap output with slippage
function calcSwapOutput(inputAmount, pool, toRune) {
// formula: (inputAmount * inputBalance * outputBalance) / (inputAmount + inputBalance) ^ 2
const inputBalance = toRune ? pool.assetBalance : pool.runeBalance // input is asset if toRune
const outputBalance = toRune ? pool.runeBalance : pool.assetBalance // output is rune if toRune
const numerator = inputAmount * inputBalance * outputBalance
const denominator = Math.pow((inputAmount + inputBalance), 2)
const result = numerator / denominator
return result
}
// Calculate swap slippage
function calcSwapSlip(inputAmount, pool, toRune) {
// formula: (inputAmount) / (inputAmount + inputBalance)
const inputBalance = toRune ? pool.assetBalance : pool.runeBalance// input is asset if toRune
const result = inputAmount / (inputAmount + inputBalance)
return result
}
// Calculate swap slippage for double swap
function calcDoubleSwapSlip(inputAmount, pool1, pool2) {
// formula: calcSwapSlip1(input1) + calcSwapSlip2(calcSwapOutput1 => input2)
const swapSlip1 = calcSwapSlip(inputAmount, pool1, true)
const r = calcSwapOutput(inputAmount, pool1, true)
const swapSlip2 = calcSwapSlip(r, pool2, false)
const result = swapSlip1 + swapSlip2
return result
}

Calculating Network Fees

The gas_rate property can be used to estimate network fees for each chain the swap interacts with. For example, if the swap is BTC -> ETH the swap will incur fees on the bitcoin network and Ethereum network.
The gas_rate property works differently on each chain "type" (e.g. EVM, UTXO, BFT).
Including an Affiliate Fee
In the swap transaction you build for your users you can include an affiliate fee for your exchange (accepted in $RUNE or a synthetic asset, so you will need a $RUNE address).

3. Building the swap transaction

Now that you've calculated/displayed all relevant fees to your user and they've entered the final swap params, you can build and submit the swap transaction.

The Swap Memo

Format:
SWAP:<ASSET>:<DESTADDR>:<LIM>:<AFFILIATEADDR>:<FEE>
  • ASSET - the destination asset (read about asset notation here)
  • DESTADDR - the destination address
  • LIM - Minimum of the destination asset to receive. If the swap results in less, it will be cancelled and refunded. Formatted with 8 decimals
  • AFFILIATEADDR - Address to pay an affiliate fee (must be native THORChain address)
  • FEE - affiliate fee basis points (0 - 10,000)

4. Submit the transaction

Now that the swap transaction is built, the user will sign with their wallet and you'll submit to the source chain. Each chain has a different process for broadcasting a transaction. You can use XChainJS (which wraps each chain's client libraries) to sign/broadcast TXs, or you can use your preferred client library. Find the XChain libraries here.

5. Understanding Swap Processing

All swaps are queued at execution time are processed and the end of each block. At the end of each block, queued swaps are put in a list and assigned a score based on their value to the network. The list is then ordered based on the score descending then the swap list is executed sequentially. There is also a swap limit per block, if the list size is greater than the swap limit, the remainder of the swaps are queued for the next block.

A Note on Delayed Outbound

THORChain has a throttling mechanism for large outbound transactions and high-volume situations. If your user swaps with size into an asset that is not a native THORChain asset, the outbound transaction may be delayed up to 1 hour, which you'll want to display to your user.
You can check the /queue/scheduled endpoint to see if the outbound transaction for the swap is delayed. The response will include a THORChain block height at which the transaction will be sent out.