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

THORChain Features

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

To use THORChain features, you need:

  1. A connected wallet with RUNE
  2. SwapKit initialized with the THORChain plugin (included by default)
import { createSwapKit, Chain, FeeOption } from '@swapkit/sdk';
const swapKit = createSwapKit();
// Connect wallet for THORChain
await swapKit.connectKeystore([Chain.THORChain], 'your mnemonic phrase');

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

import { AssetValue } from '@swapkit/sdk';
// Add ETH/RUNE liquidity
const runeAmount = AssetValue.from({ asset: 'THOR.RUNE', value: 100 });
const ethAmount = AssetValue.from({ asset: 'ETH.ETH', value: 0.5 });
const result = await swapKit.thorchain.addLiquidity({
baseAssetValue: runeAmount, // RUNE amount
assetValue: ethAmount, // Asset amount
baseAssetAddr: swapKit.getAddress(Chain.THORChain),
assetAddr: swapKit.getAddress(Chain.Ethereum),
mode: 'sym' // Symmetrical mode
});
console.log('RUNE tx:', result.baseAssetTx);
console.log('ETH tx:', result.assetTx);
// Add RUNE-only liquidity
const runeOnly = await swapKit.thorchain.addLiquidity({
baseAssetValue: runeAmount,
assetValue: AssetValue.from({ asset: 'BTC.BTC', value: 0 }), // Required but can be 0
baseAssetAddr: swapKit.getAddress(Chain.THORChain),
mode: 'baseAsset' // Use 'baseAsset' for RUNE-only
});
// Add asset-only liquidity (e.g., BTC only)
const btcAmount = AssetValue.from({ asset: 'BTC.BTC', value: 0.1 });
const btcOnly = await swapKit.thorchain.addLiquidity({
baseAssetValue: AssetValue.from({ asset: 'THOR.RUNE', value: 0 }), // Required but can be 0
assetValue: btcAmount,
assetAddr: swapKit.getAddress(Chain.Bitcoin),
mode: 'asset' // Use 'asset' for asset-only
});

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

const result = await swapKit.thorchain.createLiquidity({
baseAssetValue: runeAmount, // RUNE amount
assetValue: ethAmount // Asset amount
});
console.log('RUNE tx:', result.baseAssetTx);
console.log('Asset tx:', result.assetTx);

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

const poolAddress = 'BTC.BTC'; // Pool identifier
await swapKit.thorchain.addLiquidityPart({
assetValue: btcAmount,
poolAddress,
address: swapKit.getAddress(Chain.Bitcoin), // Optional: for symmetric deposits
symmetric: true
});
// Withdraw 50% of liquidity position
const withdrawTx = await swapKit.thorchain.withdraw({
assetValue: AssetValue.from({ asset: 'BTC.BTC', value: 0 }), // Pool identifier
percent: 50, // Withdraw 50%
from: 'sym', // From position type: 'sym' | 'baseAsset' | 'asset'
to: 'sym' // To asset type: 'sym' | 'baseAsset' | 'asset'
});
// Withdraw asymmetric RUNE position to symmetric
const runeToSym = await swapKit.thorchain.withdraw({
assetValue: AssetValue.from({ asset: 'ETH.ETH', value: 0 }),
percent: 100, // Withdraw 100%
from: 'baseAsset', // From RUNE-only position
to: 'sym' // To both RUNE and ETH
});
// Withdraw to specific asset only
const toAssetOnly = await swapKit.thorchain.withdraw({
assetValue: AssetValue.from({ asset: 'BTC.BTC', value: 0 }),
percent: 25, // Withdraw 25%
from: 'sym', // From symmetric position
to: 'asset' // Receive BTC only
});
import { SwapKitApi } from '@swapkit/helpers/api';
const thorAddress = swapKit.getAddress(Chain.THORChain);
const position = await SwapKitApi.thorchainMidgard.getLiquidityPosition(thorAddress);
// Position details
console.log('Pools:', position.pools);
console.log('Total value USD:', position.totalValueUSD);

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

// Register a new THORName
const thorname = 'myname';
const years = 1; // Registration period
// Check availability
const details = await SwapKitApi.thorchainMidgard.getTHORNameDetails(thorname);
if (details.owner) {
console.log('THORName already taken');
return;
}
// Calculate registration fee (1 RUNE per year + network fee)
const registrationFee = AssetValue.from({
asset: 'THOR.RUNE',
value: years + 0.02 // 1 RUNE/year + ~0.02 network fee
});
// Register the name
const registerTx = await swapKit.thorchain.registerName({
assetValue: registrationFee,
name: thorname,
chain: 'THOR', // Chain identifier for the THORName
address: swapKit.getAddress(Chain.THORChain),
owner: swapKit.getAddress(Chain.THORChain), // Optional: different owner
preferredAsset: 'ETH.ETH' // Optional: set preferred asset
});

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

// Set preferred asset to USDC
const preferredAsset = AssetValue.from({
asset: 'ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
value: 0
});
const setPreferredTx = await swapKit.thorchain.registerPreferredAsset({
assetValue: AssetValue.from({ chain: Chain.THORChain }), // Min RUNE for tx
name: thorname,
ownerAddress: swapKit.getAddress(Chain.THORChain),
payoutAddress: swapKit.getAddress(Chain.Ethereum) // Where to receive USDC
});

Set addresses for different chains:

// Update Bitcoin address for THORName
const updateBtcTx = await swapKit.thorchain.registerName({
assetValue: AssetValue.from({ chain: Chain.THORChain }), // Min RUNE for tx
name: thorname,
chain: 'BTC', // Chain identifier
address: swapKit.getAddress(Chain.Bitcoin),
owner: swapKit.getAddress(Chain.THORChain)
});
// Update multiple chains
const chainMap = {
[Chain.Ethereum]: 'ETH',
[Chain.Bitcoin]: 'BTC',
[Chain.BinanceSmartChain]: 'BSC'
};
for (const [chain, chainId] of Object.entries(chainMap)) {
await swapKit.thorchain.registerName({
assetValue: AssetValue.from({ chain: Chain.THORChain }),
name: thorname,
chain: chainId,
address: swapKit.getAddress(chain as Chain),
owner: swapKit.getAddress(Chain.THORChain)
});
}
const thornameDetails = await SwapKitApi.thorchainMidgard.getTHORNameDetails('thorswap');
console.log('Owner:', thornameDetails.owner);
console.log('Preferred asset:', thornameDetails.preferredAsset);
console.log('Aliases:', thornameDetails.aliases);
// Get specific chain address
const ethAddress = thornameDetails.aliases.find(a => a.chain === 'ETH')?.address;

For node operators, SwapKit provides bond management functions.

import { MemoType } from '@swapkit/sdk';
const bondAmount = AssetValue.from({ asset: 'THOR.RUNE', value: 100000 });
const nodeAddress = 'thor1abc...'; // Your node address
const bondTx = await swapKit.thorchain.nodeAction({
type: MemoType.BOND,
assetValue: bondAmount,
address: nodeAddress
});
// Unbond specific amount
const unbondTx = await swapKit.thorchain.nodeAction({
type: MemoType.UNBOND,
assetValue: AssetValue.from({ asset: 'THOR.RUNE', value: 50000 }),
address: nodeAddress
});
// Leave (unbond all)
const leaveTx = await swapKit.thorchain.nodeAction({
type: MemoType.LEAVE,
address: nodeAddress
});

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

// Direct deposit with custom memo
const customDeposit = await swapKit.thorchain.deposit({
assetValue: AssetValue.from({ asset: 'BTC.BTC', value: 0.1 }),
recipient: '', // Empty for THORChain protocol deposits
memo: 'SWAP:ETH.ETH:thor1...' // Custom memo for any THORChain action
});
// Deposit to specific pool
const poolDeposit = await swapKit.thorchain.depositToPool({
assetValue: AssetValue.from({ asset: 'ETH.ETH', value: 1 }),
memo: 'ADD:ETH.ETH:thor1...',
feeOptionKey: FeeOption.Fast // Optional: Average, Fast, or Fastest
});
// Protocol deposit (simplified)
const protocolDeposit = await swapKit.thorchain.depositToProtocol({
assetValue: AssetValue.from({ asset: 'THOR.RUNE', value: 10 }),
memo: 'BOND:thor1nodeaddress...'
});

For EVM chains, THORChain requires token approvals before deposits:

// Check if token is approved
const isApproved = await swapKit.thorchain.isAssetValueApproved({
assetValue: AssetValue.from({
asset: 'ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
value: 1000
})
});
if (!isApproved) {
// Approve token for THORChain router
const approveTx = await swapKit.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. SwapKit supports Maya through the Maya plugin:

// Maya operations use the same interface
// Check Maya positions
const mayaPosition = await SwapKitApi.mayachainMidgard.getLiquidityPosition(
swapKit.getAddress(Chain.Maya)
);

Get inbound addresses and gas rates for any supported chain:

// Get inbound data for a specific chain
const btcInbound = await swapKit.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);
// Check multiple chains
const chains = [Chain.Ethereum, Chain.Bitcoin, Chain.BinanceSmartChain];
for (const chain of chains) {
const inbound = await swapKit.thorchain.getInboundDataByChain(chain);
if (inbound.halted) {
console.log(`${chain} is currently halted`);
}
}

Before adding liquidity or making swaps:

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:

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

Track THORChain transactions:

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 SwapKit)