Swapping
Integrations
Javascript SDK
Swap Assets
Request deposit address
Request Deposit Address V2

Request Deposit Address V2

The ability to create a unique deposit address that is reserved for a user during a fixed period of time (24hs) provides a lot of flexibility and is a unique feature of the Chainflip protocol.

Once the deposit address is available, the user can send the funds from any wallet(s) to trigger the swap process. No need to connect a wallet.

Sending funds to a deposit address is cheaper than a smart contract call, as no token approvals are required.

Learn more on Deposit Channels & Brokers section.

requestDepositAddressV2

Requests a deposit address based on the provided DepositAddressRequestV2.

requestDepositAddressV2(
  depositAddressRequest: DepositAddressRequestV2
): Promise<DepositAddressResponse>

The depositAddressRequest object describes the swap for which a deposit address is requested.

ParamDescriptionData type
quote(required)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(required)Address where the swapped tokens will be sent to on the destination chainstring
brokerCommissionBps(optional)Commission charged by the broker creating the channel, in basis points. If given, this value will be used instead of the brokerCommissionBps value used when initializing the SDK. This option is only available when the SDK is initialized with a brokerUrlnumber
affiliateBrokers(optional)An array of objects defining affiliate broker accounts that take a commission in addition to brokerCommissionBps. This option is only available when the SDK is initialized with a brokerUrlArray
ccmParams(optional)Optional metadata for triggering a smart contract call on the destination chain.Object
fillOrKillParams(optional)Optional metadata for setting a minimum accepted price for swaps through the deposit channel. This allows to protect against price changes between a quote and the execution of a swap (also known as slippage protection). These parameters are required when requesting a DCA deposit channel.Object

Example

Regular Deposit Address

import { Chains, Assets } from "@chainflip/sdk/swap";
 
const { quotes } = await swapSDK.getQuoteV2({
  srcChain: Chains.Ethereum,
  destChain: Chains.Bitcoin,
  srcAsset: Assets.ETH,
  destAsset: Assets.BTC,
  amount: (1.5e18).toString(), // 1.5 ETH
});
 
const quote = quotes.find((quote) => quote.type === 'REGULAR');
 
const swapDepositAddressRequest = {
  quote,
  destAddress: "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
  brokerCommissionBps: 100, // 100 basis point = 1%
  affiliateBrokers: [
    { account: "cFM8kRvLBXagj6ZXvrt7wCM4jGmHvb5842jTtXXg3mRHjrvKy", commissionBps: 50 }
  ], // total commission 150 bps = 1.5%
};
console.log(await swapSDK.requestDepositAddressV2(swapDepositAddressRequest));

Boostable Deposit Address

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
});
 
// `boostQuote` may be undefined depending on asset and liquidity conditions
const { boostQuote } = quotes.find((quote) => quote.type === 'REGULAR');
 
const swapDepositAddressRequest = {
  quote: boostQuote,
  destAddress: "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
};
console.log(await swapSDK.requestDepositAddressV2(swapDepositAddressRequest));

The amount will always be in the base unit of the source asset, i.e. for ETH it will be Wei.

Sample Response

{
  "srcChain": "Ethereum",
  "destChain": "Bitcoin",
  "srcAsset": "ETH",
  "destAsset": "BTC",
  "destAddress": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
  "amount": "1500000000000000000", // 1.5 ETH
  "depositChannelId": "1234567890", // Identifies the deposit channel for this swap
  "depositAddress": "0x1234567890abcdef1234567890abcdef12345678", // Address where funds need to be deposited to start the swap
  "depositChannelBrokerCommissionBps": 100,
  "depositChannelAffiliateBrokers": [
    { "account": "cFM8kRvLBXagj6ZXvrt7wCM4jGmHvb5842jTtXXg3mRHjrvKy", "commissionBps": 50 }
  ],
  "estimatedDepositChannelExpiryTime": 1630000000, // Estimated expiry time of the deposit channel
  "maxBoostFeeBps": 10 // Boost fee bps limit set upon channel creation. 0 by default
}

fillOrKillParams: Slippage Protection

The optional fillOrKillParams object sets a minimum accepted price for swaps triggered through the deposit channel.

This allows to protect against price changes between a quote and the execution of a swap (also known as slippage protection). If the minimum price cannot be met with the available liquidity during the specified number of blocks, deposited assets will be refunded to the specified refund address.

A slippage tolerance can be specified by using the slippageTolerancePercent property. slippageTolerancePercent must be a number between 0 and 100. This percent is used together with the estimatedPrice from the quote to calculate a minimum price for the channel, e.g.:

const minimumPrice = quote.estimatedPrice * (1 - Number(slippageTolerancePercent) / 100);

The slippage tolerance is applied relative to the QUOTED price and not the market or index rate. Prices are checked on the AMM level and do not include deposit or broadcast fees.

Alternatively, you can manually provide a minPrice value. The minimum price is the ratio between the human readable destination amount and the human readable source amount, e.g. 3500 for a swap from ETH to USDC if you want to receive after least 3500 USDC per ETH. You can use the formula above to calculate the minimum price using on the estimatedPrice from the quote.

Refunds are subject to a broadcast fee on the source chain to pay for the transactions sent by the Chainflip protocol. Any boost or deposit fee paid will not be refunded.

ParamDescriptionData type
slippageTolerancePercent(required)The percent of slippage that is acceptable for the swap. The `estimatedPrice` field from the `quote` is used to calculate the minimum price for the channel.This field must be left out when specifying a `minPrice`.string
minPrice(required)Minimum accepted price for swaps triggered through the deposit channel.This field must be left out when specifying a `slippageTolerancePercent`.string
refundAddress(required)Address on the source chain to which the refund will be sent, if the minimum price cannot be met.string
retryDurationBlocks(required)Number of State Chain blocks after which a deposit is refunded, if the minimum price cannot be met. One State Chain block corresponds to 6 seconds.number

Example

import { Chains, Assets } from "@chainflip/sdk/swap";
 
const { quotes } = await swapSDK.getQuoteV2({
  srcChain: Chains.Ethereum,
  destChain: Chains.Bitcoin,
  srcAsset: Assets.ETH,
  destAsset: Assets.BTC,
  amount: (1.5e18).toString(), // 1.5 ETH
});
 
const quote = quotes.find((quote) => quote.type === 'REGULAR');
 
const swapDepositAddressRequest = {
  quote,
  destAddress: "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
  brokerCommissionBps: 100, // 100 basis point = 1%
  fillOrKillParams: {
    slippageTolerancePercent: 1, // 1% slippage tolerance from quoted price
    refundAddress: '0xa56A6be23b6Cf39D9448FF6e897C29c41c8fbDFF', // address to which assets are refunded
    retryDurationBlocks: 100, // 100 blocks * 6 seconds = 10 minutes before deposits are refunded
  },
};
console.log(await swapSDK.requestDepositAddressV2(swapDepositAddressRequest));

DCA channel

See DCA

DCA channels must be set in conjunction with fillOrKillParams. This causes the minPrice to apply to each individual chunk in the overall swap. If a chunk fails to meet the minPrice, it will retry according to retryDurationBlocks until it does. If it does not meet it, the entire swap is retired. The swapped amount is egressed and anything that was not swapped is refunded back to the refundAddress.

import { Chains, Assets } from "@chainflip/sdk/swap";
 
const { quotes } = await swapSDK.getQuoteV2({
  srcChain: Chains.Ethereum,
  destChain: Chains.Bitcoin,
  srcAsset: Assets.ETH,
  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, // 100 basis point = 1%
  // ❗ `fillOrKillParams` are required when requesting a DCA deposit channel ❗
  fillOrKillParams: {
    slippageTolerancePercent: 1, // 1% slippage tolerance from quoted price
    refundAddress: '0xa56A6be23b6Cf39D9448FF6e897C29c41c8fbDFF', // address to which assets are refunded
    retryDurationBlocks: 100, // 100 blocks * 6 seconds = 10 minutes before deposits are refunded
  },
};
console.log(await swapSDK.requestDepositAddressV2(swapDepositAddressRequest));

Boostable DCA channel

Just like the regular quote, DCA quotes can also have a boostQuote property that will open a boostable deposit channel.

import { Chains, Assets } from "@chainflip/sdk/swap";
 
const { quotes } = await swapSDK.getQuoteV2({
  srcChain: Chains.Ethereum,
  destChain: Chains.Bitcoin,
  srcAsset: Assets.ETH,
  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 ❗
// `boostQuote` may be undefined depending on asset and liquidity conditions
const { boostQuote } = quotes.find((quote) => quote.type === 'DCA');
 
const swapDepositAddressRequest = {
  quote: boostQuote,
  destAddress: "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
  brokerCommissionBps: 100, // 100 basis point = 1%
  // ❗ `fillOrKillParams` are required when requesting a DCA deposit channel ❗
  fillOrKillParams: {
    slippageTolerancePercent: 1, // 1% slippage tolerance from quoted price
    refundAddress: '0xa56A6be23b6Cf39D9448FF6e897C29c41c8fbDFF', // address to which assets are refunded
    retryDurationBlocks: 100, // 100 blocks * 6 seconds = 10 minutes before deposits are refunded
  },
};
console.log(await swapSDK.requestDepositAddressV2(swapDepositAddressRequest));

ccmParams: Cross-Chain Messaging (CCM)

The optional ccmParams object enables executing a smart contract call on the destination chain and has the following properties:

ParamDescriptionData type
message(required)Message that is passed to the destination address on the destination chain. The message should be shorter than 10k bytes.string
gasBudget(required)Gas budget for the call on the destination chain. This amount is based on the source asset and will be subtracted from the input amount and swapped to pay for gas.number

Example

import { Chains, Assets } from "@chainflip/sdk/swap";
 
const { quotes } = await swapSDK.getQuoteV2({
  srcChain: Chains.Bitcoin,
  destChain: Chains.Ethereum,
  srcAsset: Assets.BTC,
  destAsset: Assets.ETH,
  amount: (1e8).toString(), // 1 BTC
});
 
const quote = quotes.find((quote) => quote.type === 'REGULAR');
 
const callDepositAddressRequest = {
  quote,
  destAddress: "0x2f41dd5dEe1BcF767139b6bB6e27673aE90061b5",
  ccmParams: {
    message: "0xdeadc0de",
    gasBudget: (0.001e8).toString(), // 0.001 BTC will be swapped for ETH to pay for gas
  },
};
console.log(await swapSDK.requestDepositAddressV2(callDepositAddressRequest));

The amount and gasBudget will always be in the base unit of the source asset, i.e. for ETH it will be Wei.

Sample Response

{
  "srcChain": "Bitcoin",
  "destChain": "Ethereum",
  "srcAsset": "BTC",
  "destAsset": "ETH",
  "destAddress": "0x2f41dd5dEe1BcF767139b6bB6e27673aE90061b5",
  "amount": "100000000", // 1 BTC
  "ccmParams": {
    "message": "0xdeadc0de",
    "gasBudget": "100000", // 0.001 BTC will be swapped for ETH to pay for gas
  },
  "depositChannelId": "1234567890", // Identifies the deposit channel for this swap
  "depositAddress": "tb1pylj9uhsmuz7h62spprv2z2vcnx2lw9epzt4amm3j45y75r6rrd8sdx0sjf", // Address where funds need to be deposited to start the swap
  "brokerCommissionBps": 0, // Commission charged by the broker for this swap
  "estimatedDepositChannelExpiryTime": 1630000000, // Estimated expiry time of the deposit channel
}

The resulting depositChannelId can be used in Get Status.

Use Your Own Broker

The previous two examples can also be performed with your own broker, instead of the broker that is provided by the Chainflip SDK:

import { SwapSDK } from '@chainflip/sdk/swap';
 
const sdk = new SDK({
  network: 'perseverance',
  broker: {
    url: 'https://my.broker.io',
    commissionBps: 15,
  },
});
 
const { quotes } = await sdk.getQuoteV2({
  srcChain: 'Ethereum',
  destChain: 'Ethereum',
  srcAsset: 'ETH',
  destAsset: 'FLIP',
  amount: '1000000000000000000', // 1 ETH
});
 
const quote = quotes.find((quote) => quote.type === 'REGULAR');
 
const channel = await sdk.requestDepositAddressV2({
  quote,
  destAddress: '0x1234567890abcdef1234567890abcdef12345678',
});
 
console.log(channel);
/*
  {
    srcAsset: 'ETH',
    srcChain: 'Ethereum',
    destAsset: 'FLIP',
    destChain: 'Ethereum',
    amount: '1000000000000000000',
    destAddress: '0x717e15853fd5f2ac6123e844c3a7c75976eaec9b',
    depositChannelId: '710643-Ethereum-615',
    depositAddress: '0x2d564a0754168cf49af604c82e84bd3a30599bf5',
    brokerCommissionBps: 15,
    estimatedDepositChannelExpiryTime: 1630000000,
  }
*/