Skip to content
SwapDK is a powerful suite of tools for building blockchain applications.

THORChain Features

THORChain provides advanced DeFi features beyond simple swaps. SwapDK includes full support for these features through the THORChain plugin.

To use THORChain features, you need:

  1. A connected wallet with RUNE
  2. SwapDK initialized with the THORChain plugin (included by default)
// @noErrorValidation
import { createSwapKit, Chain, FeeOption } from "@swapdk/sdk";
const swapDK = createSwapKit();
await swapDK.connectKeystore([Chain.THORChain], "your mnemonic phrase");

THORChain uses an asymmetric liquidity model where you can provide single-sided or dual-sided liquidity.

// @noErrorValidation
import { AssetValue } from "@swapdk/sdk";
const runeAmount = AssetValue.from({ asset: "THOR.RUNE", value: 100 });
const ethAmount = AssetValue.from({ asset: "ETH.ETH", value: 0.5 });
const result = await swapDK.thorchain.addLiquidity({
baseAssetValue: runeAmount,
assetValue: ethAmount,
baseAssetAddr: swapDK.getAddress(Chain.THORChain),
assetAddr: swapDK.getAddress(Chain.Ethereum),
mode: "sym",
});
console.log("RUNE tx:", result.baseAssetTx);
console.log("ETH tx:", result.assetTx);
// @noErrorValidation
const runeOnly = await swapDK.thorchain.addLiquidity({
baseAssetValue: runeAmount,
assetValue: AssetValue.from({ asset: "BTC.BTC", value: 0 }),
baseAssetAddr: swapDK.getAddress(Chain.THORChain),
mode: "baseAsset",
});
const btcAmount = AssetValue.from({ asset: "BTC.BTC", value: 0.1 });
const btcOnly = await swapDK.thorchain.addLiquidity({
baseAssetValue: AssetValue.from({ asset: "THOR.RUNE", value: 0 }),
assetValue: btcAmount,
assetAddr: swapDK.getAddress(Chain.Bitcoin),
mode: "asset",
});

For creating a new liquidity position (bootstrapping a pool):

// @noErrorValidation
const result = await swapDK.thorchain.createLiquidity({
baseAssetValue: runeAmount,
assetValue: ethAmount,
});
console.log("RUNE tx:", result.baseAssetTx);
console.log("Asset tx:", result.assetTx);

For more granular control, you can add liquidity parts separately:

// @noErrorValidation
const poolAddress = "BTC.BTC";
await swapDK.thorchain.addLiquidityPart({
assetValue: btcAmount,
poolAddress,
address: swapDK.getAddress(Chain.Bitcoin),
symmetric: true,
});
// @noErrorValidation
const withdrawTx = await swapDK.thorchain.withdraw({
assetValue: AssetValue.from({ asset: "BTC.BTC", value: 0 }),
percent: 50,
from: "sym",
to: "sym",
});
const runeToSym = await swapDK.thorchain.withdraw({
assetValue: AssetValue.from({ asset: "ETH.ETH", value: 0 }),
percent: 100,
from: "baseAsset",
to: "sym",
});
const toAssetOnly = await swapDK.thorchain.withdraw({
assetValue: AssetValue.from({ asset: "BTC.BTC", value: 0 }),
percent: 25,
from: "sym",
to: "asset",
});
// @noErrorValidation
import { SwapKitApi } from "@swapdk/helpers/api";
const thorAddress = swapDK.getAddress(Chain.THORChain);
const position = await SwapKitApi.thorchainMidgard.getLiquidityPosition(
thorAddress
);
console.log("Pools:", position.pools);
console.log("Total value USD:", position.totalValueUSD);

THORNames are human-readable aliases for wallet addresses across all supported chains.

// @noErrorValidation
const thorname = "myname";
const years = 1;
const details = await SwapKitApi.thorchainMidgard.getTHORNameDetails(thorname);
if (details.owner) {
console.log("THORName already taken");
return;
}
const registrationFee = AssetValue.from({
asset: "THOR.RUNE",
value: years + 0.02,
});
const registerTx = await swapDK.thorchain.registerName({
assetValue: registrationFee,
name: thorname,
chain: "THOR",
address: swapDK.getAddress(Chain.THORChain),
owner: swapDK.getAddress(Chain.THORChain),
preferredAsset: "ETH.ETH",
});

Configure which asset you want to receive when someone sends to your THORName:

// @noErrorValidation
const preferredAsset = AssetValue.from({
asset: "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
value: 0,
});
const setPreferredTx = await swapDK.thorchain.registerPreferredAsset({
assetValue: AssetValue.from({ chain: Chain.THORChain }),
name: thorname,
ownerAddress: swapDK.getAddress(Chain.THORChain),
payoutAddress: swapDK.getAddress(Chain.Ethereum),
});

Set addresses for different chains:

// @noErrorValidation
const updateBtcTx = await swapDK.thorchain.registerName({
assetValue: AssetValue.from({ chain: Chain.THORChain }),
name: thorname,
chain: "BTC",
address: swapDK.getAddress(Chain.Bitcoin),
owner: swapDK.getAddress(Chain.THORChain),
});
const chainMap = {
[Chain.Ethereum]: "ETH",
[Chain.Bitcoin]: "BTC",
[Chain.BinanceSmartChain]: "BSC",
};
for (const [chain, chainId] of Object.entries(chainMap)) {
await swapDK.thorchain.registerName({
assetValue: AssetValue.from({ chain: Chain.THORChain }),
name: thorname,
chain: chainId,
address: swapDK.getAddress(chain as Chain),
owner: swapDK.getAddress(Chain.THORChain),
});
}
// @noErrorValidation
const thornameDetails = await SwapKitApi.thorchainMidgard.getTHORNameDetails(
"myname"
);
console.log("Owner:", thornameDetails.owner);
console.log("Preferred asset:", thornameDetails.preferredAsset);
console.log("Aliases:", thornameDetails.aliases);
const ethAddress = thornameDetails.aliases.find(
(a) => a.chain === "ETH"
)?.address;

For node operators, SwapDK provides bond management functions.

// @noErrorValidation
import { MemoType } from "@swapdk/sdk";
const bondAmount = AssetValue.from({ asset: "THOR.RUNE", value: 100000 });
const nodeAddress = "thor1abc...";
const bondTx = await swapDK.thorchain.nodeAction({
type: MemoType.BOND,
assetValue: bondAmount,
address: nodeAddress,
});
// @noErrorValidation
const unbondTx = await swapDK.thorchain.nodeAction({
type: MemoType.UNBOND,
assetValue: AssetValue.from({ asset: "THOR.RUNE", value: 50000 }),
address: nodeAddress,
});
const leaveTx = await swapDK.thorchain.nodeAction({
type: MemoType.LEAVE,
address: nodeAddress,
});

For advanced users, deposit directly to THORChain with custom memos:

// @noErrorValidation
const customDeposit = await swapDK.thorchain.deposit({
assetValue: AssetValue.from({ asset: "BTC.BTC", value: 0.1 }),
recipient: "",
memo: "SWAP:ETH.ETH:thor1...",
});
const poolDeposit = await swapDK.thorchain.depositToPool({
assetValue: AssetValue.from({ asset: "ETH.ETH", value: 1 }),
memo: "ADD:ETH.ETH:thor1...",
feeOptionKey: FeeOption.Fast,
});
const protocolDeposit = await swapDK.thorchain.depositToProtocol({
assetValue: AssetValue.from({ asset: "THOR.RUNE", value: 10 }),
memo: "BOND:thor1nodeaddress...",
});

For EVM chains, THORChain requires token approvals before deposits:

// @noErrorValidation
const isApproved = await swapDK.thorchain.isAssetValueApproved({
assetValue: AssetValue.from({
asset: "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
value: 1000,
}),
});
if (!isApproved) {
const approveTx = await swapDK.thorchain.approveAssetValue({
assetValue: AssetValue.from({
asset: "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
value: 1000,
}),
});
console.log("Approval tx:", approveTx);
}

Maya is a fork of THORChain with similar features. SwapDK supports Maya through the Maya plugin:

// @noErrorValidation
const mayaPosition = await SwapKitApi.mayachainMidgard.getLiquidityPosition(
swapDK.getAddress(Chain.Maya)
);

Get inbound addresses and gas rates for any supported chain:

// @noErrorValidation
const btcInbound = await swapDK.thorchain.getInboundDataByChain(Chain.Bitcoin);
console.log("BTC vault address:", btcInbound.address);
console.log("BTC router:", btcInbound.router);
console.log("Gas rate:", btcInbound.gas_rate);
console.log("Chain halted:", btcInbound.halted);
const chains = [Chain.Ethereum, Chain.Bitcoin, Chain.BinanceSmartChain];
for (const chain of chains) {
const inbound = await swapDK.thorchain.getInboundDataByChain(chain);
if (inbound.halted) {
console.log(`${chain} is currently halted`);
}
}

Before adding liquidity or making swaps:

// @noErrorValidation
const pools = await SwapKitApi.thorchainMidgard.getPools();
const btcPool = pools.find((p) => p.asset === "BTC.BTC");
if (btcPool?.status !== "Available") {
console.log("Pool not available");
return;
}

For large liquidity operations:

// @noErrorValidation
const quote = await SwapKitApi.getSwapQuote({
sellAsset: "THOR.RUNE",
sellAmount: "1000000000000",
buyAsset: "BTC.BTC",
});
const slippage = quote.routes[0].fees.slippage;
console.log(`Slippage: ${slippage}%`);

Track THORChain transactions:

// @noErrorValidation
const txStatus = await SwapKitApi.getTrackerDetails({
txHash: "ABCD...",
chain: "THOR",
});
if (txStatus.status === "completed") {
console.log("Transaction successful");
}

Here’s a complete list of THORChain plugin methods:

  • deposit() - Direct deposit with custom parameters
  • depositToPool() - Deposit to specific pool with memo
  • depositToProtocol() - Simplified protocol deposits
  • addLiquidity() - Add symmetric or asymmetric liquidity
  • addLiquidityPart() - Add liquidity with granular control
  • createLiquidity() - Bootstrap new liquidity pools
  • withdraw() - Withdraw liquidity positions
  • registerName() - Register or update THORNames
  • registerPreferredAsset() - Set preferred payout asset
  • nodeAction() - Bond, unbond, or leave as node operator
  • approveAssetValue() - Approve tokens for router
  • isAssetValueApproved() - Check approval status
  • getInboundDataByChain() - Get vault addresses and gas rates
  • swap() - Execute swaps (used internally by SwapDK)