Chainflip JavaScript SDK
getChains
Returns the list of available chains or destination chains for the provided sourceChain
.
function getChains(sourceChain?: Chain): Promise<ChainData[]>;
type ChainData = {
chain: Chain;
name: string;
evmChainId: number | undefined;
isMainnet: boolean;
requiredBlockConfirmations: number | undefined;
maxRetryDurationBlocks: number | undefined;
};
Param | Description | Data type |
---|---|---|
sourceChain (optional) | Chain ID that allows to filter the returned array to contain only destination chains for the given chain. | Chain |
Example
If a sourceChain
is provided, it returns the supported swap destination chains for that specific source chain.
import { Chains } from "@chainflip/sdk/swap";
console.log(await swapSDK.getChains(Chains.Polkadot));
// console output:
[
{
chain: "Ethereum",
name: "Ethereum",
evmChainId: 1,
isMainnet: true,
requiredBlockConfirmations: 5,
maxRetryDurationBlocks: 0,
},
{
chain: "Bitcoin",
name: "Bitcoin",
evmChainId: undefined,
isMainnet: true,
requiredBlockConfirmations: 2,
maxRetryDurationBlocks: 0,
},
];
getAssets
Fetches the list of available assets for the given chain
.
function getAssets(chain?: Chain): Promise<AssetData[]>;
type AssetData = {
chainflipId: string;
asset: Asset;
chain: Chain;
contractAddress: string | undefined;
decimals: number;
name: string;
symbol: string;
isMainnet: boolean;
minimumSwapAmount: string;
maximumSwapAmount: string | null;
minimumEgressAmount: string;
};
Param | Description | Data type |
---|---|---|
chain (optional) | The ID of the chain | Chain |
Example
import { Chains } from "@chainflip/sdk/swap";
console.log(await swapSDK.getAssets(Chains.Ethereum));
// console output:
[
{
chainflipId: 'Eth',
asset: 'ETH',
chain: 'Ethereum',
contractAddress: undefined,
decimals: 18,
name: 'Ether',
symbol: 'ETH',
isMainnet: true,
minimumSwapAmount: '10000000000000000',
maximumSwapAmount: null,
minimumEgressAmount: '1'
},
...,
{
chainflipId: 'Usdc',
asset: 'USDC',
chain: 'Ethereum',
contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
decimals: 6,
name: 'USDC',
symbol: 'USDC',
isMainnet: true,
minimumSwapAmount: '20000000',
maximumSwapAmount: null,
minimumEgressAmount: '1'
},
]
getQuoteV2
Fetches the quotes for swapping tokens based on the provided quoteRequest
and an options
argument.
Currently quotes can be either a regular quotes or a DCA quotes.
function getQuoteV2(
quoteRequest: QuoteRequest,
options?: RequestOptions
): Promise<QuoteResponseV2>;
type QuoteRequest = {
srcChain: Chain;
srcAsset: Asset;
destChain: Chain;
destAsset: Asset;
amount: string;
isVaultSwap?: boolean;
brokerCommissionBps?: number;
affiliateBrokers?: { account: string; commissionBps: number }[];
ccmParams?: { gasBudget: string; messageLengthBytes: number };
};
type RequestOptions = {
signal?: AbortSignal;
};
Param | Description | Data type |
---|---|---|
quoteRequest | Object containing the quote request parameters. You can find the interface definition below. | Object |
options (optional) | Options related to the HTTP request. | { signal?: AbortSignal } |
The quoteRequest
object describes the swap for which a quote is returned.
Param | Description | Data type |
---|---|---|
srcChain | Source chain for the swap | Chain |
destChain | Destination chain for the swap | Chain |
srcAsset | Asset to be swapped from the source chain | Asset |
destAsset | Asset to be received on the destination chain | Asset |
amount | Amount of the source token to be swapped, represented in the base unit of the source token | string |
brokerCommissionBps (optional) | Commission charged by the broker in basis points. If given, the value will be used instead of the brokerCommissionBps passed when initializing the SDK instance | number |
affiliateBrokers (optional) | Array of objects describing the affiliate brokers that charge a commission | Array |
isVaultSwap (optional) | Flag for requesting a quote for a vault swap. Network related fees can be different for vault swaps compared to channel swaps | boolean |
ccmParams (optional) | Additional params for requesting a quote for a CCM swap. This is only used to increase the accuracy of the broadcast fee estimation for CCM swaps. A rough estimation of the values is good enough if the actual values are unknown at this stage. | Object |
Result type
type QuoteResponseV2 = {
srcChain: Chain;
srcAsset: Asset;
destChain: Chain;
destAsset: Asset;
amount: string;
isVaultSwap?: boolean;
brokerCommissionBps?: number;
affiliateBrokers?: { account: string; commissionBps: number }[];
ccmParams?: { gasBudget: string; messageLengthBytes: number };
quotes: QuoteDetails &
{
/** only present if there is a boost opportunity for the requested swap amount */
boostQuote?: BoostedQuoteDetails;
type: "REGULAR" | "DCA";
}[];
};
type QuoteDetails = {
intermediateAmount?: string;
egressAmount: string;
includedFees: SwapFee[];
poolInfo: PoolInfo[];
/** recommended tolerance to prevent refunds while protecting against big price movements based on current market conditions */
recommendedSlippageTolerancePercent: number;
/** recommended live price slippage tolerance to help improve the execution price of a swap based on the global index price. If undefined, live price protection is not available for the asset pair */
recommendedLivePriceSlippageTolerancePercent: number | undefined;
/** recommended amount of minutes to retry a swap that has failed to meet the provided slippage tolerance */
recommendedRetryDurationMinutes: number;
/** see below */
lowLiquidityWarning: boolean | undefined;
/** total estimated time until destination asset is received by the user */
estimatedDurationSeconds: number;
estimatedDurationsSeconds: {
/** estimated time for a deposit to be witnessed */
deposit: number;
/** estimated time for a swap to be fully executed */
swap: number;
/** estimated time until the output transaction is included in a block */
egress: number;
};
/** estimated price of the swap at amm level (does not include deposit/broadcast fee) */
estimatedPrice: string;
/** only present if the quote is a DCA quote */
dcaParams?: {
numberOfChunks: number;
chunkIntervalBlocks: number;
};
};
interface BoostedQuoteDetails extends QuoteDetails {
/** estimated fee (in bps) that the user has to pay (from the deposit amount) to get this swap boosted */
estimatedBoostFeeBps: number;
}
lowLiquidityWarning
: This value is true if the difference in the chainflip
swap rate (excluding fees) is lower than the global index rate of the swap by
more than a certain threshold (currently set to 5%). This suggets there is not
enough liquidity in the pool.
The intermediate amount is the value of the first swap leg. In this case, BTC > ETH requires both BTC/USDC and USDC/ETH pools (or legs). Learn more about Chainflip’s $USDC Denominated Pools.
Example
import { SwapSDK, Chains, Assets } from "@chainflip/sdk/swap";
const quoteRequest = {
srcChain: Chains.Ethereum,
srcAsset: Assets.USDC,
destChain: Chains.Solana,
destAsset: Assets.SOL,
amount: (50e6).toString(), // 50 USDC
brokerCommissionBps: 100, // 100 basis point = 1%
affiliateBrokers: [
{
account: "cFM8kRvLBXagj6ZXvrt7wCM4jGmHvb5842jTtXXg3mRHjrvKy",
commissionBps: 50,
},
],
};
const swapSDK = new SwapSDK({
enabledFeatures: { dca: true }, // enable DCA feature when initiating the SDK to receive DCA quotes
});
console.log(await swapSDK.getQuoteV2(quoteRequest));
// console output:
{
srcChain: 'Ethereum',
srcAsset: 'USDC',
destChain: 'Solana',
destAsset: 'SOL',
amount: '50000000',
dcaEnabled: true,
quotes: [
{
egressAmount: '309311018',
recommendedSlippageTolerancePercent: 0.5,
recommendedLivePriceSlippageTolerancePercent: 0.125,
recommendedRetryDurationMinutes: 5,
includedFees: [
{ type: 'INGRESS', chain: 'Ethereum', asset: 'USDC', amount: '1395704' },
{ type: 'NETWORK', chain: 'Ethereum', asset: 'USDC', amount: '48604' },
{ type: 'BROKER', chain: 'Ethereum', asset: 'USDC', amount: '728335' },
{ type: 'EGRESS', chain: 'Solana', asset: 'SOL', amount: '14000' },
],
lowLiquidityWarning: true,
poolInfo: [
{
baseAsset: { chain: 'Solana', asset: 'SOL' },
quoteAsset: { chain: 'Ethereum', asset: 'USDC' },
fee: { chain: 'Ethereum', asset: 'USDC', amount: '24302' },
},
],
estimatedDurationsSeconds: { deposit: 90, swap: 12, egress: 90.6 },
estimatedDurationSeconds: 192.6,
estimatedPrice: '0.00636414974511718059',
type: 'REGULAR',
srcAsset: { chain: 'Ethereum', asset: 'USDC' },
destAsset: { chain: 'Solana', asset: 'SOL' },
depositAmount: '50000000',
isVaultSwap: false,
},
{
egressAmount: '309311018',
recommendedSlippageTolerancePercent: 0.5,
recommendedLivePriceSlippageTolerancePercent: 0.125,
includedFees: [
{ type: 'INGRESS', chain: 'Ethereum', asset: 'USDC', amount: '1395704' },
{ type: 'NETWORK', chain: 'Ethereum', asset: 'USDC', amount: '48604' },
{ type: 'BROKER', chain: 'Ethereum', asset: 'USDC', amount: '728335' },
{ type: 'EGRESS', chain: 'Solana', asset: 'SOL', amount: '14000' },
],
lowLiquidityWarning: true,
poolInfo: [
{
baseAsset: { chain: 'Solana', asset: 'SOL' },
quoteAsset: { chain: 'Ethereum', asset: 'USDC' },
fee: { chain: 'Ethereum', asset: 'USDC', amount: '24302' },
},
],
estimatedDurationsSeconds: { deposit: 90, swap: 142, egress: 90.6 },
estimatedDurationSeconds: 192.6,
estimatedPrice: '0.00636414974511718059',
type: 'REGULAR',
srcAsset: { chain: 'Ethereum', asset: 'USDC' },
destAsset: { chain: 'Solana', asset: 'SOL' },
depositAmount: '50000000',
isVaultSwap: false,
dcaParams: {
chunkIntervalBlocks: 2,
numberOfChunks: 22,
},
},
],
}
requestDepositAddressV2
Chainflip allows to open a deposit channel for a given set of swap details. This deposit channel is assigned to a unique address on the source chain of the swap and allows users to initiate the swap by sending the source asset to this address. Deposit channels expire after a fixed period of time (24hs).
Once a deposit channel is open, the user can send the funds from any wallet to its deposit address to initiate the swap process. No need to connect a wallet. Compared to vault swaps, using deposit channels can be cheaper for the user because it doesn’t require token approvals.
Learn more about deposit channels in the Deposit Channels & Brokers documentation.
Requests a deposit address for the given DepositAddressRequestV2
.
This method uses the broker_request_swap_deposit_address
RPC method of the configured Broker API
to open a deposit channel.
function requestDepositAddressV2(
depositAddressRequest: DepositAddressRequestV2
): Promise<DepositAddressResponse>;
type DepositAddressRequestV2 = {
quote: Quote;
destAddress: string;
fillOrKillParams: {
retryDurationBlocks: number;
refundAddress: string;
slippageTolerancePercent: number;
livePriceSlippageTolerancePercent?: number | false;
};
srcAddress?: string;
brokerCommissionBps?: number;
affiliateBrokers?: {
account: `cF${string}` | `0x${string}`;
commissionBps: number;
}[];
ccmParams?: {
gasBudget: string;
message: string;
additionalData?: string;
};
};
The depositAddressRequest
object describes the swap for which a deposit address is requested.
Param | Description | Data type |
---|---|---|
quote | The object returned by getQuoteV2. This object will be used to set the input and output assets, the DCA parameters (if it is a DCA quote), and the boost parameters (if it is a boost quote). | Quote |
destAddress | Address where the swapped tokens will be sent to on the destination chain. | string |
fillOrKillParams | Parameters to set a minimum accepted price. This protects the swapper against price changes between a quote and the execution of a swap. | Object |
brokerCommissionBps (optional) | Commission charged by the broker creating the channel, in basis points. This option is only available when the SDK is initialized with a brokerUrl | number |
affiliateBrokers (optional) | An array of objects defining affiliate accounts that take a commission in addition to brokerCommissionBps . This option is only available when the SDK is initialized with a brokerUrl | Array |
ccmParams (optional) | Optional parameters for passing a message to a reciever contract/program on the destination chain. | Object |
Result type
type DepositAddressRequestV2 = {
srcChain: Chain;
srcAsset: Asset;
destChain: Chain;
destAsset: Asset;
amount: string;
destAddress: string;
ccmParams?: {
gasBudget: string;
message: string;
additionalData?: string;
};
maxBoostFeeBps?: number;
srcAddress?: string;
dcaParams?: {
numberOfChunks: number;
chunkIntervalBlocks: number;
};
fillOrKillParams: {
retryDurationBlocks: number;
refundAddress: string;
slippageTolerancePercent: number;
livePriceSlippageTolerancePercent?: number | false;
};
depositChannelId: string;
depositAddress: string;
brokerCommissionBps: number;
affiliateBrokers?: {
account: `cF${string}` | `0x${string}`;
commissionBps: number;
}[];
depositChannelExpiryBlock: bigint;
estimatedDepositChannelExpiryTime: number | undefined;
channelOpeningFee: bigint;
};
Configure your Broker API
If you want to earn broker fees or use affiliates, you need to run your own Broker API. You can configure the URL of your Broker API when initializing the SDK.
import { SwapSDK } from "@chainflip/sdk/swap";
const sdk = new SwapSDK({
network: "perseverance",
broker: { url: "https://my.broker.io" },
});
Example
Regular Deposit Address
import { Chains, Assets } from "@chainflip/sdk/swap";
const { quotes } = await swapSDK.getQuoteV2({
srcChain: Chains.Ethereum,
srcAsset: Assets.ETH,
destChain: Chains.Bitcoin,
destAsset: Assets.BTC,
amount: (1.5e18).toString(), // 1.5 ETH
});
const quote = quotes.find((quote) => quote.type === "REGULAR");
const swapDepositAddressRequest = {
quote,
destAddress: "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
fillOrKillParams: {
refundAddress: "0xa56A6be23b6Cf39D9448FF6e897C29c41c8fbDFF", // address to which assets are refunded
retryDurationMinutes: quote.recommendedRetryDurationMinutes, // use recommended retry duration from quote
slippageTolerancePercent: quote.recommendedSlippageTolerancePercent, // use recommended slippage tolerance from quote
livePriceSlippageTolerancePercent:
quote.recommendedLivePriceSlippageTolerancePercent, // use recommended live price slippage tolerance from quote
},
brokerCommissionBps: 100, // 100 basis point = 1%
affiliateBrokers: [
{
account: "cFM8kRvLBXagj6ZXvrt7wCM4jGmHvb5842jTtXXg3mRHjrvKy",
commissionBps: 50,
},
], // total commission 150 bps = 1.5%
};
console.log(await swapSDK.requestDepositAddressV2(swapDepositAddressRequest));
// console output:
{
srcAsset: 'ETH',
srcChain: 'Ethereum',
destAsset: 'BTC',
destChain: 'Bitcoin',
srcAddress: undefined,
destAddress: 'bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq',
dcaParams: undefined,
fillOrKillParams: {
slippageTolerancePercent: 0.5,
refundAddress: '0xa56A6be23b6Cf39D9448FF6e897C29c41c8fbDFF',
retryDurationBlocks: 100
},
maxBoostFeeBps: 0,
ccmParams: undefined,
amount: '1500000000000000000', // 1.5 ETH
depositChannelId: '6739624-Ethereum-2562', // Identifies the deposit channel for this swap
depositAddress: '0x6284c66ebf4110ae3cc4da45fb9b1c2143417092', // Address where funds need to be deposited to start the swap
brokerCommissionBps: 100,
affiliateBrokers: [
{ account: 'cFM8kRvLBXagj6ZXvrt7wCM4jGmHvb5842jTtXXg3mRHjrvKy', commissionBps: 50 }
],
depositChannelExpiryBlock: 21930372n,
estimatedDepositChannelExpiryTime: 1630000000, // Estimated expiry time of the deposit channel
channelOpeningFee: 0n
}
Boostable Deposit Address
Check the Introduction to Boost section for more information about the Boost feature.
import { Chains, Assets } from "@chainflip/sdk/swap";
const { quotes } = await swapSDK.getQuoteV2({
srcChain: Chains.Bitcoin,
srcAsset: Assets.BTC,
destChain: Chains.Ethereum,
destAsset: Assets.ETH,
amount: (1.5e8).toString(), // 1.5 BTC
});
const quote = quotes.find((quote) => quote.type === "REGULAR");
const swapDepositAddressRequest = {
// `boostQuote` may be undefined depending on asset and liquidity conditions
quote: quote.boostQuote,
destAddress: "0xa56A6be23b6Cf39D9448FF6e897C29c41c8fbDFF",
fillOrKillParams: {
refundAddress: "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
retryDurationBlocks: 100,
slippageTolerancePercent: quote.recommendedSlippageTolerancePercent,
livePriceSlippageTolerancePercent:
quote.recommendedLivePriceSlippageTolerancePercent,
},
};
console.log(await swapSDK.requestDepositAddressV2(swapDepositAddressRequest));
DCA deposit address
Check the Dollar Cost Average section for more information about the DCA feature.
import { Chains, Assets } from "@chainflip/sdk/swap";
const { quotes } = await swapSDK.getQuoteV2({
srcChain: Chains.Ethereum,
srcAsset: Assets.ETH,
destChain: Chains.Bitcoin,
destAsset: Assets.BTC,
amount: (1.5e18).toString(), // 1.5 ETH
});
// ❗ the DCA feature must be enabled when the SDK is instantiated to receive DCA quotes ❗
const quote = quotes.find((quote) => quote.type === "DCA");
const swapDepositAddressRequest = {
quote,
destAddress: "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
brokerCommissionBps: 100,
fillOrKillParams: {
refundAddress: "0xa56A6be23b6Cf39D9448FF6e897C29c41c8fbDFF",
retryDurationBlocks: 100,
slippageTolerancePercent: quote.recommendedSlippageTolerancePercent,
livePriceSlippageTolerancePercent:
quote.recommendedLivePriceSlippageTolerancePercent,
},
};
console.log(await swapSDK.requestDepositAddressV2(swapDepositAddressRequest));
encodeVaultSwapData
Vault swaps are initiated by sending a transaction that encodes the details of the swap in the transaction data to the Chainflip vault on the source chain directly. This allows to initiate swaps without waiting for a deposit address to be generated.
Vault swap transactions need to encode the swap details in a specific format supported by the protocol. The user needs to sign and submit this transaction to initiate a swap. Therefore, applications usually require users to connect their wallet to initiate vault swaps.
Compared to deposit channel swaps, the vault swap process is similar to the swap process of other decentralized exchanges and therefore might be easier to integrate into existing applications.
Learn more about vault swaps in the Vault Swaps documentation.
Returns the unsigned transaction data for the given VaultSwapRequest
.
This method uses the broker_request_swap_parameter_encoding
RPC method of the configured Broker API.
function encodeVaultSwapData(
vaultSwapRequest: VaultSwapRequest
): Promise<VaultSwapResponse>;
type VaultSwapRequest = {
quote: Quote;
destAddress: string;
fillOrKillParams: {
retryDurationBlocks: number;
refundAddress: string;
slippageTolerancePercent: number;
livePriceSlippageTolerancePercent?: number | false;
};
srcAddress?: string;
brokerAccount?: `cF${string}`;
brokerCommissionBps?: number;
affiliateBrokers?: {
account: `cF${string}` | `0x${string}`;
commissionBps: number;
}[];
ccmParams?: {
gasBudget: string;
message: string;
additionalData?: string;
};
extraParams?: { seed?: string };
};
The vaultSwapRequest
object describes the swap for which the vault swap data is encoded.
Param | Description | Data type |
---|---|---|
quote | The object returned by getQuoteV2 . This object will be used to set the input and output assets, the DCA parameters (if it is a DCA quote), and the boost parameters (if it is a boost quote). | Quote |
destAddress | Address where the swapped tokens will be sent to on the destination chain. | string |
fillOrKillParams | Parameters to set a minimum accepted price. This allows to protect against price changes between a quote and the execution of a swap (also known as slippage protection). | Object |
srcAddress (optional) | Address that will sign and send the vault swap transaction. This parameter is required to encode vault swaps starting from Solana. | string |
brokerAccount (optional) | Broker account that recieves the commission for the swap. | string |
brokerCommissionBps (optional) | Commission charged by the broker of the swap, in basis points. This option is only available when setting a brokerAccount or the SDK is initialized with a brokerUrl | number |
affiliateBrokers (optional) | An array of objects defining affiliate accounts that take a commission in addition to brokerCommissionBps . This option is only available when setting a brokerAccount or the SDK is initialized with a brokerUrl | Array |
ccmParams (optional) | Optional parameters for passing a message to a reciever contract/program on the destination chain. | Object |
extraParams (optional) | Additional data that is required for encoding vault swap transaction data for specific chains. For swaps starting from Solana, a seed can be set optionally. If no seed is set, a random one will be generated on the fly. | string |
Result type
type VaultSwapResponse =
| {
chain: "Bitcoin";
nulldataPayload: string;
depositAddress: string;
}
| {
chain: "Ethereum" | "Arbitrum";
calldata: string;
value: bigint;
to: string;
sourceTokenAddress?: string | undefined;
}
| {
chain: "Solana";
programId: string;
accounts: {
pubkey: string;
isSigner: boolean;
isWritable: boolean;
}[];
data: string;
};
Example
Ethereum vault swap
import { Chains, Assets } from "@chainflip/sdk/swap";
import { getDefaultProvider, Wallet, Contract } from "ethers";
const wallet = new Wallet(
process.env.SECRET_KEY,
getDefaultProvider("sepolia")
);
const { quotes } = await swapSDK.getQuoteV2({
srcChain: Chains.Ethereum,
srcAsset: Assets.USDC,
destChain: Chains.Bitcoin,
destAsset: Assets.BTC,
isVaultSwap: true,
amount: (500e6).toString(), // 500 USDC
});
const quote = quotes.find((quote) => quote.type === "DCA");
const vaultSwapRequest = {
quote,
srcAddress: wallet.address,
destAddress: "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
fillOrKillParams: {
refundAddress: wallet.address, // address to which assets are refunded
retryDurationBlocks: 100, // 100 blocks * 6 seconds = 10 minutes before deposits are refunded
slippageTolerancePercent: quote.recommendedSlippageTolerancePercent, // use recommended slippage tolerance from quote
livePriceSlippageTolerancePercent:
quote.recommendedLivePriceSlippageTolerancePercent, // use recommended live price slippage tolerance from quote
},
};
const vaultSwapData = await swapSDK.encodeVaultSwapData(vaultSwapRequest);
console.log(vaultSwapData);
// approve chainflip vault to spend erc20 token
if (vaultSwapData.sourceTokenAddress) {
const sourceTokenContract = new Contract(
vaultSwapData.sourceTokenAddress,
["function approve(address spender, uint256 value) returns (bool)"],
wallet
);
const approvalTx = await sourceTokenContract.approve(
vaultSwapData.to,
quote.depositAmount
);
await approvalTx.wait();
}
const swapTx = await wallet.sendTransaction({
to: vaultSwapData.to,
data: vaultSwapData.calldata,
value: vaultSwapData.value,
});
const receipt = await swapTx.wait(); // wait for transaction to be included in a block
// status will be available after the transaction is included in a block
const status = await swapSDK.getStatusV2({ id: receipt.hash });
// console output:
{
chain: 'Ethereum',
to: '0x36ead71325604dc15d35fae584d7b50646d81753',
calldata: '0xdd68734500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000014cb583c817964a2c527608f8b813a4c9bddb559a9000000000000000000000000000000000000000000000000000000000000000000000000000000000000005e0064000000cb583c817964a2c527608f8b813a4c9bddb559a945f572d5916d163cccbef285e25d4bde2400000000000000000000000000000000009e8d88ae895c9b37b2dead9757a3452f7c2299704d91ddfa444d87723f94fe0c0000000000',
value: 0n,
sourceTokenAddress: '0x1c7d4b196cb0c7b01d743fbc6116a902379c7238'
}
Bitcoin vault swap (Boosted)
import { Chains, Assets } from "@chainflip/sdk/swap";
import Client from "bitcoin-core";
import * as bitcoin from "bitcoinjs-lib";
import ECPairFactory from "ecpair";
import * as secp256k1 from "tiny-secp256k1";
const keypair = ECPairFactory(secp256k1).fromWIF(process.env.WALLET_WIF);
const network = bitcoin.networks.testnet;
const walletAddress = bitcoin.payments.p2wpkh({
pubkey: Buffer.from(keypair.publicKey),
network,
}).address;
bitcoin.initEccLib(secp256k1);
const { quotes } = await swapSDK.getQuoteV2({
srcChain: Chains.Bitcoin,
srcAsset: Assets.BTC,
destChain: Chains.Ethereum,
destAsset: Assets.ETH,
isVaultSwap: true,
amount: (0.015e8).toString(), // 0.015 BTC
});
// `boostQuote` may be undefined depending on asset and liquidity conditions
const quote = quotes.find((quote) => quote.type === "REGULAR").boostQuote;
const vaultSwapRequest = {
quote,
srcAddress: walletAddress,
destAddress: "0xa56A6be23b6Cf39D9448FF6e897C29c41c8fbDFF",
fillOrKillParams: {
refundAddress: walletAddress,
retryDurationBlocks: 100,
slippageTolerancePercent: quote.recommendedSlippageTolerancePercent,
livePriceSlippageTolerancePercent:
quote.recommendedLivePriceSlippageTolerancePercent,
},
};
const vaultSwapData = await swapSDK.encodeVaultSwapData(vaultSwapRequest);
console.log(vaultSwapData);
export const rpcClient = new Client({
host: "https://bitcoin-testnet-rpc.publicnode.com",
});
const inputUxto = {
txId: "4403c8d3b752a3aa0757031239a82ce92d67fadc1bb4a35f80ace660499edd55",
outIndex: 2,
};
const inputTx = bitcoin.Transaction.fromHex(
await rpcClient.command("getrawtransaction", inputUxto.txId)
);
const txFeeSats = 1000;
const tx = new bitcoin.Psbt({ network })
.addInput({
hash: inputTx.getHash(),
index: inputUxto.outIndex,
nonWitnessUtxo: inputTx.toBuffer(),
sequence: 0xfffffffd, // enable replace-by-fee
})
.addOutput({
// first output needs to spend assets to deposit address
address: vaultSwapData.depositAddress,
value: Number(quote.depositAmount),
})
.addOutput({
// second output needs to return encoded vault details using the OP_RETURN opcode
script: bitcoin.payments.embed({
data: [
Buffer.from(vaultSwapData.nulldataPayload.replace("0x", ""), "hex"),
],
network,
}).output,
value: 0,
})
.addOutput({
// third output defines the refund address for the swap
address: walletAddress,
value:
inputTx.outs[inputUxto.outIndex].value -
Number(quote.depositAmount) -
txFeeSats,
})
.signInput(0, {
publicKey: Buffer.from(keypair.publicKey),
sign: (hash) => Buffer.from(keypair.sign(hash)),
})
.finalizeAllInputs()
.extractTransaction();
await rpcClient.command("sendrawtransaction", tx.toHex());
// status will be available once the transaction is in the mempool
const status = await swapSDK.getStatusV2({ id: tx.getId() });
// console output:
{
chain: 'Bitcoin',
nulldataPayload: '0x0001a56a6be23b6cf39d9448ff6e897c29c41c8fbdff640029a43fc140746a5e000000000000000001000200000000',
depositAddress: 'tb1pxu6h02gundytrfvlrxtjylkqmfv072ljtqcfvwclh37cx4eq7chqq6zmng'
}
The changeAddress
, which is included in the change UTXO as the third output, is mandatory because the Chainflip protocol needs a refund address in case the swap is refunded.
Per the Bitcoin protocol, the change UTXO amount cannot be zero and must be larger than Bitcoin’s dust threshold for the change address type. Therefore it is not possible to swap the entire amount of the input UTXOs, a dust amount needs to be sent to the change address.
Solana vault swap
import { Chains, Assets } from "@chainflip/sdk/swap";
import { randomBytes } from "crypto";
import {
PublicKey,
Keypair,
sendAndConfirmTransaction,
TransactionInstruction,
Transaction,
Connection,
clusterApiUrl,
} from "@solana/web3.js";
import bs58 from "bs58";
const keypair = Keypair.fromSecretKey(
bs58.decode(process.env.SECRET_KEY_BASE58)
);
const { quotes } = await swapSDK.getQuoteV2({
srcChain: Chains.Solana,
srcAsset: Assets.SOL,
destChain: Chains.Ethereum,
destAsset: Assets.ETH,
isVaultSwap: true,
amount: (1.5e9).toString(), // 1.5 SOL
});
const quote = quotes.find((quote) => quote.type === "REGULAR");
const vaultSwapRequest = {
quote,
srcAddress: keypair.publicKey.toBase58(),
destAddress: "0xa56A6be23b6Cf39D9448FF6e897C29c41c8fbDFF",
fillOrKillParams: {
refundAddress: keypair.publicKey.toBase58(),
retryDurationBlocks: 100,
slippageTolerancePercent: quote.recommendedSlippageTolerancePercent,
livePriceSlippageTolerancePercent:
quote.recommendedLivePriceSlippageTolerancePercent,
},
extraParams: {
seed: randomBytes(32).toString("hex"),
},
};
const vaultSwapData = await swapSDK.encodeVaultSwapData(vaultSwapRequest);
console.log(vaultSwapData);
const transaction = new Transaction().add(
new TransactionInstruction({
keys: vaultSwapData.accounts.map((account) => ({
pubkey: new PublicKey(account.pubkey),
isSigner: account.isSigner,
isWritable: account.isWritable,
})),
programId: new PublicKey(vaultSwapData.programId),
data: Buffer.from(vaultSwapData.data.slice(2), "hex"),
})
);
const signature = await sendAndConfirmTransaction(
new Connection(clusterApiUrl("devnet"), "confirmed"),
transaction,
[keypair]
);
// status will be available after the transaction is included in a block
const status = await swapSDK.getStatusV2({ id: signature });
// console output:
{
chain: 'Solana',
programId: 'DeL6iGV5RWrWh7cPoEa7tRHM8XURAaB4vPjfX5qVyuWE',
data: '0xa3265ce2f3698dc4002f6859000000000100000014000000c64722ad9613851b10e26ff8118a7696a0f956f201000000006a000000000a0000009e0d6a70e12d54edf90971cc977fa26a1d3bb4b0b26e72470171c36b0006b01f000000100000000000000000000000000000000000000000000000000000000000009059e6d854b769a505d01148af212bf8cb7f8469a7153edce8dcaedd9d299125000000200000004a7b9c2f1e8d3a5b6c4f9e2d7a1b3c8f0e5d9a2c6b4f7e1d3a8b5c9f2e0d6a30',
accounts: [
{
pubkey: 'GpTqSHz4JzQimjfDiBgDhJzYcTonj3t6kMhKTigCKHfc',
isSigner: false,
isWritable: false
},
...
]
}
encodeCfParameters
It is recommended to encode Vault swaps using the SDK’s method to encode the Vault Swap data. However, some integrators might want to manually execute the smart contract call to initiate Vault Swaps.
As documented in the
encoding-reference, a
cf_parameters
bytes variable needs to be encoded as part of the Vault Swap
initiation via a smart contract call. While that can be encoded manually, the
SDK provides a method to encode it for convenience.
The encodeCfParameters
function returns the hex-encoded CF parameters. This method uses the
broker_encode_cf_parameters
RPC method of the configured
Broker API.
interface EncodeCfParametersRequest {
quote: Quote | BoostQuote;
srcAddress?: string;
destAddress: string;
fillOrKillParams: FillOrKillParamsWithMinPrice | FillOrKillParamsWithSlippage;
affiliateBrokers?: {
account: `cF${string}` | `0x${string}`;
commissionBps: number;
}[];
ccmParams?: CcmParams;
brokerAccount?: `cF${string}`;
brokerCommissionBps?: number;
}
class SwapSDK {
encodeCfParameters(
cfParameters: EncodeCfParametersRequest
): Promise<`0x${string}`>;
}
The cfParameters
object describes the swap for which the CF parameters data is encoded.
Param | Description | Data type |
---|---|---|
quote | The object returned by getQuoteV2 This object will be used to set the input and output assets, the DCA parameters (if it is a DCA quote), and the boost parameters (if it is a boost quote). | Quote |
destAddress | Address where the swapped tokens will be sent to on the destination chain. | string |
fillOrKillParams | Parameters to set a minimum accepted price This allows to protect against price changes between a quote and the execution of a swap (also known as slippage protection). | Object |
srcAddress (optional) | Address that will sign and send the vault swap transaction. This parameter is required to encode vault swaps starting from Solana. | string |
brokerAccount (optional) | account that receives the commission for the swap. | string |
brokerCommissionBps (optional) | Commission charged by the broker of the swap, in basis points. This option is only available when setting a brokerAccount or the SDK is initialized with a brokerUrl | number |
affiliateBrokers (optional) | An array of objects defining affiliate accounts that take a commission in addition to brokerCommissionBps . This option is only available when setting a brokerAccount or the SDK is initialized with a brokerUrl | Array |
ccmParams (optional) | Optional parameters for passing a message to a reciever contract/program on the destination chain. | Object |
Result type
The method returns bytes as a hex-encoded string that can be passed to the State Chain.
Example
import { Chains, Assets, SwapSDK } from "@chainflip/sdk/swap";
const swapSDK = new SwapSDK({ network: "perseverance" });
const {
quotes: [quote],
} = await swapSDK.getQuoteV2({
srcChain: Chains.Ethereum,
srcAsset: Assets.USDC,
destChain: Chains.Bitcoin,
destAsset: Assets.BTC,
amount: (500e6).toString(), // 500 USDC
});
const vaultSwapRequest = {
quote,
destAddress: "tb1q65700ylwuua9669umxdep76a69jy3tfh55llf5",
fillOrKillParams: {
refundAddress: "0x36ead71325604dc15d35fae584d7b50646d81753", // address to which assets are refunded
retryDurationBlocks: 100, // 100 blocks * 6 seconds = 10 minutes before deposits are refunded
slippageTolerancePercent: quote.recommendedSlippageTolerancePercent, // use recommended slippage tolerance from quote
livePriceSlippageTolerancePercent:
quote.recommendedLivePriceSlippageTolerancePercent, // use recommended live price slippage tolerance from quote
},
};
const vaultSwapData = await swapSDK.encodeCfParameters(vaultSwapRequest);
console.log(vaultSwapData);
// console output:
"0x006400000036ead71325604dc15d35fae584d7b50646d81753b8b06ebc3b32569bff571d39d21918010000000000000000000000000000000000009e8d88ae895c9b37b2dead9757a3452f7c2299704d91ddfa444d87723f94fe0c000000";
getStatusV2
Fetches the status of an ongoing swap based on the provided swapStatusRequest
argument.
function getStatusV2(
swapStatusRequest: SwapStatusRequest,
options?: RequestOptions
): Promise<SwapStatusResponseV2>;
type SwapStatusRequest = {
id: string;
};
type RequestOptions = {
signal?: AbortSignal;
};
The SwapStatusRequest
object includes the following arguments:
Param | Description | Data type |
---|---|---|
id | One of the following: - The depositChannelId from the Request deposit address method- The transactionHash from the Encode vault swap data method | string |
Result type
interface Boost {
maxBoostFeeBps: number;
effectiveBoostFeeBps: number | undefined;
boostedAt: number | undefined;
boostedBlockIndex: string | undefined;
skippedAt: number | undefined;
skippedBlockIndex: string | undefined;
}
interface DepositChannelFields {
id: string;
createdAt: number;
brokerCommissionBps: number;
depositAddress: string;
srcChainExpiryBlock: string;
estimatedExpiryTime: number;
expectedDepositAmount: string;
isExpired: boolean;
openedThroughBackend: boolean;
affiliateBrokers: AffiliateBroker[];
fillOrKillParams: FillOrKillParams | undefined;
dcaParams: DcaParams | undefined;
}
interface DepositFields {
amount: string;
txRef: string | undefined;
txConfirmations: number | undefined;
witnessedAt: number | undefined;
witnessedBlockIndex: string | undefined;
failure: Failure | undefined;
failedAt: number | undefined;
failedBlockIndex: string | undefined;
}
interface PaidFee {
type: "NETWORK" | "INGRESS" | "EGRESS" | "BROKER" | "BOOST" | "LIQUIDITY";
chain: Chain;
asset: Asset;
amount: string;
}
interface SwapFields {
originalInputAmount: string;
remainingInputAmount: string;
swappedInputAmount: string;
swappedOutputAmount: string;
regular?: {
inputAmount: string;
outputAmount: string;
scheduledAt: number;
scheduledBlockIndex: string;
executedAt?: number;
executedBlockIndex?: string;
retryCount: 0;
};
dca?: {
lastExecutedChunk: {
inputAmount: string;
outputAmount: string;
scheduledAt: number;
scheduledBlockIndex: string;
executedAt: number;
executedBlockIndex: string;
retryCount: number;
} | null;
currentChunk: {
inputAmount: string;
scheduledAt: number;
scheduledBlockIndex: string;
retryCount: number;
} | null;
executedChunks: number;
remainingChunks: number;
};
}
interface EgressFields {
amount: string;
scheduledAt: number;
scheduledBlockIndex: string;
txRef: string | undefined;
witnessedAt: number | undefined;
witnessedBlockIndex: string | undefined;
failure: Failure | undefined;
failedAt: number | undefined;
failedBlockIndex: string | undefined;
}
interface SwapStatusResponseCommonFields {
swapId: string;
srcChain: Chain;
srcAsset: Asset;
destChain: Chain;
destAsset: Asset;
destAddress: string;
depositChannel: DepositChannelFields | undefined;
ccmParams: CcmParams | undefined;
boost: Boost | undefined;
fees: PaidFee[];
estimatedDurationSeconds: number | null | undefined; // total estimated time until destination asset is received by the user
estimatedDurationsSeconds: {
deposit: number; // estimated time for a deposit to be witnessed
swap: number; // estimated time for a swap to be fully executed
egress: number; // estimated time until the output transaction is included in a block
};
srcChainRequiredBlockConfirmations: number | null;
}
interface Waiting extends SwapStatusResponseCommonFields {
depositChannel: DepositChannelFields;
}
interface Receiving extends SwapStatusResponseCommonFields {
deposit: DepositFields;
}
interface Swapping extends Receiving {
swap: SwapFields;
}
interface Sending extends Receiving {
swap: SwapFields;
swapEgress: EgressFields | undefined;
refundEgress: EgressFields | undefined;
}
export type SwapStatusResponseV2 =
| ({
state: "WAITING";
} & Waiting)
| ({
state: "RECEIVING";
} & Receiving)
| ({
state: "SWAPPING";
} & Swapping)
| ({
state: "SENDING";
} & Sending)
| ({
state: "SENT";
} & Sending)
| ({
state: "COMPLETED";
} & Sending)
| ({
state: "FAILED";
} & Sending);
Example
const swapStatusRequest = {
id: "6726421-Bitcoin-34009", // depositChannelId / swapId / transactionId
};
console.log(await swapSDK.getStatusV2(swapStatusRequest));
// console output:
{
state: 'COMPLETED',
swapId: '332925',
srcAsset: 'BTC',
srcChain: 'Bitcoin',
destAsset: 'USDC',
destChain: 'Ethereum',
destAddress: '0xbbfefb09727136a6c3ddd28bd4abdf259b9351c1',
srcChainRequiredBlockConfirmations: 2,
estimatedDurationsSeconds: { deposit: 1806, swap: 12, egress: 102 },
estimatedDurationSeconds: 1920,
brokers: [
{ account: 'cFJZVRaybb2PBwxTiAiRLiQfHY4KPB3RpJK22Q7Fhqk979aCH', commissionBps: 5 },
{ account: 'cFK6mYjpajcwPDZ7JUsac8XUoVSJnhjL43ZMZW7YoN8HE4dD8', commissionBps: 60 },
],
fees: [
{ type: 'NETWORK', chain: 'Ethereum', asset: 'USDC', amount: '52965555' },
{ type: 'LIQUIDITY', chain: 'Bitcoin', asset: 'BTC', amount: '27972' },
{ type: 'BROKER', chain: 'Ethereum', asset: 'USDC', amount: '343931842' },
{ type: 'BOOST', chain: 'Bitcoin', asset: 'BTC', amount: '28000' },
{ type: 'INGRESS', chain: 'Bitcoin', asset: 'BTC', amount: '1251' },
{ type: 'EGRESS', chain: 'Ethereum', asset: 'USDC', amount: '0' },
],
depositChannel: {
id: '6726421-Bitcoin-34009',
createdAt: 1740415452001,
brokerCommissionBps: 5,
depositAddress: 'bc1ppaxkhh5c65zypqtjl7s5j4lqqaund3lzaz27cwlhw7nvg0s84cwqv4q6pw',
srcChainExpiryBlock: '885280',
estimatedExpiryTime: 1740502800000,
isExpired: false,
openedThroughBackend: false,
affiliateBrokers: [
{ account: 'cFK6mYjpajcwPDZ7JUsac8XUoVSJnhjL43ZMZW7YoN8HE4dD8', commissionBps: 60 },
],
fillOrKillParams: {
refundAddress: 'bc1qstlcaqcds8xea7dtktdn47hng7c3lq3fa7vrtm',
minPrice: '92307.460172',
retryDurationBlocks: 150,
},
dcaParams: { numberOfChunks: 18, chunkIntervalBlocks: 2 },
},
deposit: {
amount: '55970749',
txRef: 'ba030cf99b7b01d9455c3ab87a5d87a301b67e91640fc9c76014c6e5b97986d7',
witnessedAt: 1740415836000,
witnessedBlockIndex: '6726483-536',
},
swap: {
originalInputAmount: '55970749',
remainingInputAmount: '0',
swappedInputAmount: '55970749',
swappedIntermediateAmount: '0',
swappedOutputAmount: '52568658562',
dca: {
lastExecutedChunk: {
inputAmount: '3109487',
outputAmount: '2916364871',
scheduledAt: 1740416046000,
scheduledBlockIndex: '6726517-2189',
executedAt: 1740416058000,
executedBlockIndex: '6726519-1073',
retryCount: 0,
},
currentChunk: null,
executedChunks: 18,
remainingChunks: 0,
},
},
swapEgress: {
amount: '52568658562',
scheduledAt: 1740416058000,
scheduledBlockIndex: '6726519-1074',
witnessedAt: 1740416262000,
witnessedBlockIndex: '6726552-640',
txRef: '0xc8646625910babc04b1612526c27fbac68aacf6cc489affbae69d1d430f5fcb1',
},
fillOrKillParams: {
refundAddress: 'bc1qstlcaqcds8xea7dtktdn47hng7c3lq3fa7vrtm',
minPrice: '92307.460172',
retryDurationBlocks: 150,
},
dcaParams: { numberOfChunks: 18, chunkIntervalBlocks: 2 },
boost: {
effectiveBoostFeeBps: 5,
maxBoostFeeBps: 0,
boostedAt: 1740415836000,
boostedBlockIndex: '6726483-536',
},
lastStatechainUpdateAt: 1740497470820,
}
Lifecycle of a swap

getSwapLimits
Fetches the lower and upper bounds for swap amounts.
function getSwapLimits(): Promise<{
minimumSwapAmounts: ChainAssetMap<bigint>;
maximumSwapAmounts: ChainAssetMap<bigint | null>;
}>;
type ChainAssetMap<T> = {
Bitcoin: {
BTC: T;
};
Ethereum: {
ETH: T;
USDC: T;
USDT: T;
FLIP: T;
};
Polkadot: {
DOT: T;
};
Arbitrum: {
ETH: T;
USDC: T;
};
Solana: {
Sol: T;
SolUsdc: T;
};
};
In order to determine if a swap amount is within the bounds, you can check to see if the amount is greater than or equal to the minimum swap amount for the given source asset and chain and less than or equal to the maximum swap amount for the asset and chain.
These values are in the base unit of the asset, i.e. satoshis for Bitcoin, wei for Ethereum, and Planck for Polkadot, etc.
Funds sent in excess of the maximum swap amount are absorbed by the protocol and cannot be recovered.
Funds that fail to meet the minimum swap amount are also absorbed by the protocol and cannot be recovered.
Example
console.log(await swapSDK.getSwapLimits());
// console output:
{
minimumSwapAmounts: {
Bitcoin: { BTC: 70000n },
Ethereum: {
ETH: 10000000000000000n,
USDC: 20000000n,
USDT: 20000000n,
FLIP: 4000000000000000000n
},
Polkadot: { DOT: 40000000000n },
Arbitrum: {
ETH: 10000000000000000n,
USDC: 20000000n,
},
Solana: {
SOL: 0n,
SOLUSDC: 0n
}
},
maximumSwapAmounts: {
Bitcoin: { BTC: 4000000n },
Ethereum: {
ETH: 500000000000000000n,
USDC: 1000000000n,
USDT: 1000000000n,
FLIP: 200000000000000000000n
},
Polkadot: { DOT: 2000000000000n },
Arbitrum: {
ETH: 500000000000000000n,
USDC: 1000000000n,
},
Solana: {
SOL: null
SOLUSDC: null
}
}
}
getBoostLiquidity
Returns the list of available boost pools and their respective depths.
The returned list can be filtered by feeTierBps
or asset, chain
.
function getBoostLiquidity(
params:
| { feeTierBps?: number }
| { feeTierBps?: number; asset: Asset; chain: Chain }
): Promise<BoostPoolDepth[]>;
type BoostPoolDepth = {
feeTierBps: number;
availableAmount: bigint;
asset: Asset;
chain: Chain;
};
Param | Description | Data type |
---|---|---|
feeTierBps (optional) | Allows filtering of the returned list of boost pools based on their fee tier (bps) | number |
chain, asset (optional) | Allows filtering of the returned list of boost pools based on their chain asset | Chain, Asset |
Example - no filtering
If no chain, asset
or feeTierBps
is provided, it returns the full list of available boost pools with their respective depths.
console.log(await swapSDK.getBoostLiquidity());
// console output:
[
// ...
{
availableAmount: 0n,
feeTierBps: 5,
chain: "Ethereum",
asset: "FLIP",
},
{
availableAmount: 0n,
feeTierBps: 10,
chain: "Ethereum",
asset: "USDT",
},
{
availableAmount: 0n,
feeTierBps: 5,
chain: "Ethereum",
asset: "USDC",
},
{
availableAmount: 0n,
feeTierBps: 5,
chain: "Polkadot",
asset: "DOT",
},
{
availableAmount: 450695350n,
feeTierBps: 5,
chain: "Bitcoin",
asset: "BTC",
},
{
availableAmount: 0n,
feeTierBps: 5,
chain: "Arbitrum",
asset: "USDC",
},
{
availableAmount: 0n,
feeTierBps: 5,
chain: "Arbitrum",
asset: "ETH",
},
// ...
];
Example - filtering by chain asset
If a valid combination of chain, asset
is provided, it returns the available boost pools for that specific chain asset.
console.log(
await sdk.getBoostLiquidity({
asset: "BTC",
chain: "Bitcoin",
})
);
// console output:
[
{
availableAmount: 300000000n,
feeTierBps: 30,
chain: "Bitcoin",
asset: "BTC",
},
{
availableAmount: 450149304n,
feeTierBps: 10,
chain: "Bitcoin",
asset: "BTC",
},
{
availableAmount: 450695350n,
feeTierBps: 5,
chain: "Bitcoin",
asset: "BTC",
},
];
Example - filtering by fee tier (bps)
If a feeTierBps
is provided, it returns the available boost pools for that specific fee tier.
console.log(
await sdk.getBoostLiquidity({
feeTierBps: 5,
})
);
// console output:
[
// ...
{
availableAmount: 450695350n,
feeTierBps: 5,
chain: "Bitcoin",
asset: "BTC",
},
// ...
];
getChannelOpeningFees
Returns the fee in Flipperino required to open a deposit channel for a chain.
function getChannelOpeningFees(): Promise<ChainMap<bigint>>;
type ChainMap<T> = {
Bitcoin: T;
Ethereum: T;
Polkadot: T;
Arbitrum: T;
Solana: T;
};
When a broker opens a swap deposit channel, there is a fee that must be paid from the $FLIP balance of the account on the State Chain. The fee is measured in Flipperino which is the smallest unit of $FLIP (1 $FLIP = 10^18 Flipperino). This fee is determined per chain.
Example
console.log(await swapSDK.getChannelOpeningFees());
// console output:
{
Bitcoin: 0n,
Ethereum: 0n,
Polkadot: 0n,
Arbitrum: 0n,
Solana: 0n
}
getRequiredBlockConfirmations
Fetches the number of confirmations required by the protocol for each chain.
function getRequiredBlockConfirmations(): Promise<ChainMap<number | null>>;
type ChainMap<T> = {
Bitcoin: T;
Ethereum: T;
Polkadot: T;
Arbitrum: T;
Solana: T;
};
Before a transaction to a deposit address or via smart contract call can be
considered confirmed, it must be included in a certain number of blocks to limit
the risk of a “reorg” event to the protocol. The number of blocks varies by chain. Some chains,
like Polkadot, have deterministic finality and do not require any confirmations
other than being included in a block. These chains will return null
for the
number of confirmations required, while others will return a number
.
Example
console.log(await swapSDK.getRequiredBlockConfirmations());
// console output:
{
Bitcoin: 2,
Ethereum: 5,
Polkadot: null,
Arbitrum: 2,
Solana: null
}