Skip to main content

Swap

note

The guide below will provide an example of a swap from THORChain network to THORChain network, but you can do the same on any network supported by THORSwap aggregation protocol.

Let's assume that you want to exchange 100 THOR for BTC at the best exchange rate on the market. First, let's make a request to the THORSwap Pathfinder API to get a quote for our trade.

Here are the input parameters:

const quoteParams = {
sellToken: 'ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044',
buyToken: 'BTC.BTC',
sellAmount: '100',
senderAddress: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
recipientAddress: 'bc1qcalsdh8v03f5xztc04gzqlkqhx2y07dakv7f5c'
}

Fetch quote

Now let's call the Pathfinder API and fetch the quote data that will be used later on to make the swap.

const fetch = require('node-fetch');

const quoteParams = {
sellToken: 'ETH.THOR-0xa5f2211b9b8170f694421f2046281775e8468044',
buyToken: 'BTC.BTC',
sellAmount: '100',
senderAddress: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
recipientAddress: 'bc1qcalsdh8v03f5xztc04gzqlkqhx2y07dakv7f5c'
}

const baseUrl = `https://api.thorswap.net/aggregator`;
const paramsStr = new URLSearchParams(quoteParams).toString();

function fetchQuote() {
return fetch(`${baseUrl}/tokens/quote?${paramsStr}`)
.then(res => res.json())
}

const quote = await fetchQuote();

console.log(quote);

After making this request, you will see the something like the below response in the console.

  {
"quoteId": "f68576ab-72fd-4e36-a990-e0d538d49226",
"contract": "0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146",
"contractMethod": null,
"contractInfo": "Send transaction directly to THORChain for this TC-TC transaction.",
"path": "ETH.THOR -> BTC.BTC",
"complete": true,
"providers": [
"THORCHAIN"
],
"subProviders": [
"THORCHAIN"
],
"calldata": {
"fromAsset": "ETH.THOR-0XA5F2211B9B8170F694421F2046281775E8468044",
"userAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
"assetAddress": "0xa5f2211b9b8170f694421f2046281775e8468044",
"amountIn": "100000000000000000000",
"amountOut": "98170",
"amountOutMin": "39261",
"memo": "=:BTC.BTC:bc1qcalsdh8v03f5xztc04gzqlkqhx2y07dakv7f5c:39:t:0",
"tcVault": "0x6248a3d049df6d3a262e40b99a4c9816ad55384d",
"tcRouter": "0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146"
},
"estimatedTime": 615,
"expectedOutput": "0.0004417013100403109559",
"expectedOutputMaxSlippage": "0.000392616244538295408105",
"routes": [
{
"path": "ETH.THOR -> ETH.ETH -> BTC.BTC",
"providers": [
"ONEINCH",
"THORCHAIN"
],
"subProviders": [
"THORCHAIN"
],
"swaps": {
"ETH": [
[
{
"from": "ETH.THOR",
"fromTokenAddress": "0xa5f2211b9b8170f694421f2046281775e8468044",
"toTokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"to": "ETH.WETH",
"parts": [
{
"provider": "SUSHI",
"percentage": 100
}
]
}
]
],
"THOR": [
[
{
"from": "ETH.ETH",
"to": "BTC.BTC",
"parts": [
{
"provider": "THORCHAIN",
"percentage": 100
}
]
}
]
]
},
"expectedOutput": "0.000260262252140565551876",
"expectedOutputMaxSlippage": "0.000211583737655380186876",
"optimal": false,
"complete": true,
"fees": {
"ETH": [
{
"asset": "ETH.ETH",
"networkFee": 0.0022,
"networkFeeUSD": 3.7046010538098524,
"affiliateFee": 0,
"affiliateFeeUSD": 0
}
],
"THOR": [
{
"type": "inbound",
"asset": "ETH.ETH",
"networkFee": 0.0022,
"networkFeeUSD": 3.7046010538098524,
"affiliateFee": 0,
"affiliateFeeUSD": 0
},
{
"type": "outbound",
"asset": "BTC.BTC",
"networkFee": 0.00054,
"networkFeeUSD": 11.542941673022398,
"affiliateFee": 0,
"affiliateFeeUSD": 0
}
]
},
"meta": {
"sellChain": "ETH",
"sellChainGasRate": "30",
"buyChain": "BTC",
"buyChainGasRate": "27",
"quoteMode": "ERC20-TC"
},
"calldata": {
"tcRouter": "0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146",
"tcVault": "0x6248a3d049df6d3a262e40b99a4c9816ad55384d",
"tcMemo": "=:BTC.BTC:bc1qcalsdh8v03f5xztc04gzqlkqhx2y07dakv7f5c:21",
"token": "0xa5f2211b9b8170f694421f2046281775e8468044",
"amount": "100000000000000000000",
"router": "0x1111111254fb6c44bAC0beD2854e76F90643097d",
"data": "0x2e95b6c8000000000000000000000000a5f2211b9b8170f694421f2046281775e84680440000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000000000000000000000000000029d641e59b712e0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000140000000000000003b6d03403d3f13f2529ec3c84b2940155effbf9b39a8f3eccfee7c08",
"deadline": "1660915579"
},
"contract": "0xd31f7e39afECEc4855fecc51b693F9A0Cec49fd2",
"contractMethod": "swapIn",
"contractInfo": "THORSwap generic smart contract on Ethereum network for this ERC20-TC transaction."
},
{
"path": "ETH.THOR -> ETH.ETH -> BTC.BTC",
"providers": [
"SUSHISWAP",
"THORCHAIN"
],
"subProviders": [
"THORCHAIN"
],
"swaps": {
"ETH": [
[
{
"fromTokenAddress": "0xa5f2211b9b8170f694421f2046281775e8468044",
"from": "ETH.THOR",
"toTokenAddress": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"to": "ETH.WETH",
"parts": [
{
"provider": "SUSHISWAP",
"percentage": 100
}
]
}
]
],
"THOR": [
[
{
"from": "ETH.ETH",
"to": "BTC.BTC",
"parts": [
{
"provider": "THORCHAIN",
"percentage": 100
}
]
}
]
]
},
"expectedOutput": "0.000260262252140565551876",
"expectedOutputMaxSlippage": "0.000211583737655380186876",
"optimal": false,
"complete": true,
"fees": {
"ETH": [
{
"asset": "ETH.ETH",
"networkFee": 0.0022,
"networkFeeUSD": 3.7046010538098524,
"affiliateFee": 0,
"affiliateFeeUSD": 0
}
],
"THOR": [
{
"type": "inbound",
"asset": "ETH.ETH",
"networkFee": 0.0022,
"networkFeeUSD": 3.7046010538098524,
"affiliateFee": 0,
"affiliateFeeUSD": 0
},
{
"type": "outbound",
"asset": "BTC.BTC",
"networkFee": 0.00054,
"networkFeeUSD": 11.542941673022398,
"affiliateFee": 0,
"affiliateFeeUSD": 0
}
]
},
"meta": {
"sellChain": "ETH",
"sellChainGasRate": "30",
"buyChain": "BTC",
"buyChainGasRate": "27",
"quoteMode": "ERC20-TC"
},
"calldata": {
"tcRouter": "0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146",
"tcVault": "0x6248a3d049df6d3a262e40b99a4c9816ad55384d",
"tcMemo": "=:BTC.BTC:bc1qcalsdh8v03f5xztc04gzqlkqhx2y07dakv7f5c:21",
"token": "0xa5f2211b9b8170f694421f2046281775e8468044",
"amount": "100000000000000000000",
"amountOutMin": "21158",
"deadline": "1660915579"
},
"contract": "0x0F2CD5dF82959e00BE7AfeeF8245900FC4414199",
"contractMethod": "swapIn",
"contractInfo": "THORSwap generic smart contract on Ethereum network for this ERC20-TC transaction."
},
{
"path": "ETH.THOR -> ETH.ETH -> BTC.BTC",
"providers": [
"ZEROX",
"THORCHAIN"
],
"subProviders": [
"THORCHAIN"
],
"swaps": {
"ETH": [
[
{
"fromTokenAddress": "0xa5f2211b9b8170f694421f2046281775e8468044",
"toTokenAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"from": "ETH.THOR",
"to": "ETH.WETH",
"parts": [
{
"provider": "SushiSwap",
"percentage": 100
}
]
}
]
],
"THOR": [
[
{
"from": "ETH.ETH",
"to": "BTC.BTC",
"parts": [
{
"provider": "THORCHAIN",
"percentage": 100
}
]
}
]
]
},
"expectedOutput": "0.000260262252140565551876",
"expectedOutputMaxSlippage": "0.000211583737655380186876",
"optimal": false,
"complete": true,
"fees": {
"ETH": [
{
"asset": "ETH.ETH",
"networkFee": 0.0022,
"networkFeeUSD": 3.7046010538098524,
"affiliateFee": 0,
"affiliateFeeUSD": 0
}
],
"THOR": [
{
"type": "inbound",
"asset": "ETH.ETH",
"networkFee": 0.0022,
"networkFeeUSD": 3.7046010538098524,
"affiliateFee": 0,
"affiliateFeeUSD": 0
},
{
"type": "outbound",
"asset": "BTC.BTC",
"networkFee": 0.00054,
"networkFeeUSD": 11.542941673022398,
"affiliateFee": 0,
"affiliateFeeUSD": 0
}
]
},
"meta": {
"sellChain": "ETH",
"sellChainGasRate": "30",
"buyChain": "BTC",
"buyChainGasRate": "27",
"quoteMode": "ERC20-TC"
},
"calldata": {
"tcRouter": "0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146",
"tcVault": "0x6248a3d049df6d3a262e40b99a4c9816ad55384d",
"tcMemo": "=:BTC.BTC:bc1qcalsdh8v03f5xztc04gzqlkqhx2y07dakv7f5c:21",
"token": "0xa5f2211b9b8170f694421f2046281775e8468044",
"amount": "100000000000000000000",
"router": "0xDef1C0ded9bec7F1a1670819833240f027b25EfF",
"data": "0xd9627aa400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000000000000000000000000000029d641e59b712e00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a5f2211b9b8170f694421f2046281775e8468044000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee869584cd0000000000000000000000001000000000000000000000000000000000000011000000000000000000000000000000000000000000000097ed73496e62ff8369",
"deadline": "1660915579"
},
"contract": "0xd31f7e39afECEc4855fecc51b693F9A0Cec49fd2",
"contractMethod": "swapIn",
"contractInfo": "THORSwap generic smart contract on Ethereum network for this ERC20-TC transaction."
},
{
"path": "ETH.THOR -> BTC.BTC",
"providers": [
"THORCHAIN"
],
"subProviders": [
"THORCHAIN"
],
"swaps": {
"THOR": [
[
{
"from": "ETH.THOR",
"fromTokenAddress": "0xa5f2211b9b8170f694421f2046281775e8468044",
"to": "BTC.BTC",
"parts": [
{
"provider": "THORCHAIN",
"percentage": 100
}
]
}
]
]
},
"expectedOutput": "0.0004417013100403109559",
"expectedOutputMaxSlippage": "0.000392616244538295408105",
"optimal": true,
"complete": true,
"fees": {
"THOR": [
{
"type": "inbound",
"asset": "ETH.ETH",
"networkFee": 0.0022,
"networkFeeUSD": 3.7046010538098524,
"affiliateFee": 0,
"affiliateFeeUSD": 0
},
{
"type": "outbound",
"asset": "BTC.BTC",
"networkFee": 0.00054,
"networkFeeUSD": 11.542941673022398,
"affiliateFee": 0,
"affiliateFeeUSD": 0
}
]
},
"meta": {
"sellChain": "ETH",
"sellChainGasRate": "30",
"buyChain": "BTC",
"buyChainGasRate": "27",
"quoteMode": "TC-TC"
},
"calldata": {
"fromAsset": "ETH.THOR-0XA5F2211B9B8170F694421F2046281775E8468044",
"userAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
"assetAddress": "0xa5f2211b9b8170f694421f2046281775e8468044",
"amountIn": "100000000000000000000",
"amountOut": "98170",
"amountOutMin": "39261",
"memo": "=:BTC.BTC:bc1qcalsdh8v03f5xztc04gzqlkqhx2y07dakv7f5c:39:t:0",
"tcVault": "0x6248a3d049df6d3a262e40b99a4c9816ad55384d",
"tcRouter": "0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146"
},
"contract": "0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146",
"contractMethod": null,
"contractInfo": "Send transaction directly to THORChain for this TC-TC transaction."
}
],
"meta": {
"sellChain": "ETH",
"sellChainGasRate": "30",
"buyChain": "BTC",
"buyChainGasRate": "27",
"quoteMode": "TC-TC"
},
"fees": {
"THOR": [
{
"type": "inbound",
"asset": "ETH.ETH",
"networkFee": 0.0022,
"networkFeeUSD": 3.7046010538098524,
"affiliateFee": 0,
"affiliateFeeUSD": 0
},
{
"type": "outbound",
"asset": "BTC.BTC",
"networkFee": 0.00054,
"networkFeeUSD": 11.542941673022398,
"affiliateFee": 0,
"affiliateFeeUSD": 0
}
]
}
}

Swap with Xchainjs

In this Quick Start guide scenario, we are swapping between 2 assets that are both supported on THORChain. Since we are making a THORChain to THORChain swap, we can utilise the open-source xchainjs library to send our transaction through THORChain.

info

For more information about xchainjs, check out the project Github

  const { Client, getChainIds, getDefaultClientUrl } = require('@xchainjs/xchain-thorchain')
const { Network } = require('@xchainjs/xchain-client')
const { assetFromString, assetToString, assetToBase, assetAmount, formatBaseAmount } = require('@xchainjs/xchain-util')

let client, address

// Init TC client
async function connect() {
const chainIds = await getChainIds(getDefaultClientUrl())
client = new Client({
network: Network.Mainnet,
phrase: process.env.PHRASE,
chainIds
})
return true
}

async function executeTxn() {
const quote = await fetchQuote();
const calldata = quote.calldata;

const fromAsset = assetFromString(quoteParams.sellToken);
const toAsset = assetFromString(quoteParams.buyToken);
if (fromAsset == null) throw new Error(`Invalid asset ${fromAsset}`)
if (toAsset == null) throw new Error(`Invalid asset ${toAsset}`)

const amount = assetAmount(calldata.amountIn)
const memo = calldata.memo

console.log(`=== Sending transaction ===`)
console.log(`Memo: ${memo}`)
console.log(`Amount: ${formatBaseAmount(amount)}`)

const hash = await client.deposit({
walletIndex: 0,
amount,
asset: fromAsset,
memo
})

console.log(`Transaction hash: https://viewblock.io/thorchain/tx/${hash}`)
}

connect()
.then(_ => executeTxn())
.then(_ => process.exit(0))
.catch(err => {
console.error(err)
process.exit(1)
})

And that's it. We now have swapped 100 THOR into BTC using THORChain.

Github code samples

Want to see these code samples? Check out the Github repository