Swapping
Integrations
Javascript SDK
Swap Assets
Execute Swap

Execute Swap

Alternatively, calling the swap() function in the Chainflip Vault contracts allows to initiate a swap immediately. The swap is then triggered without the need of a Deposit Channel and therefore, no Broker is necessary.

Using smart contract calls is faster than requesting a deposit address but also more expensive (more gas involved on approving token and amount allowance).

With this method, there's no fixed period of time subject to expiration.

Learn more in Direct Vault Trades section.

executeSwap()

Initiates a swap for the given parameters. For ERC-20 tokens, this method will request approval to use the tokens when the allowance is lower than the transfer amount.

executeSwap(
  params: ExecuteSwapParams,
  txOpts: TransactionOptions = {},
): Promise<TransactionHash>

The ExecuteSwapParams has the following format:

type ExecuteSwapParams =
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "ETH";
      destChain: "Ethereum";
      destAddress: `0x${string}`;
      destAsset: "FLIP" | "USDC";
    }
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "ETH";
      destChain: "Polkadot";
      destAddress: string;
      destAsset: "DOT";
    }
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "ETH";
      destChain: "Bitcoin";
      destAddress: string;
      destAsset: "BTC";
    }
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "FLIP";
      destChain: "Ethereum";
      destAddress: `0x${string}`;
      destAsset: "USDC" | "ETH";
    }
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "USDC";
      destChain: "Ethereum";
      destAddress: `0x${string}`;
      destAsset: "FLIP" | "ETH";
    }
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "FLIP" | "USDC";
      destChain: "Polkadot";
      destAddress: string;
      destAsset: "DOT";
    }
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "FLIP" | "USDC";
      destChain: "Bitcoin";
      destAddress: string;
      destAsset: "BTC";
    };

The amount param will always be in the base unit of the source asset, i.e. for ETH it will be Wei.
If no srcAsset is provided, the source asset is native ETH.

The TransactionOptions allow to control the submitted transaction:

type TransactionOptions = {
  gasLimit?: bigint;
  gasPrice?: bigint;
  maxFeePerGas?: bigint;
  maxPriorityFeePerGas?: bigint;
  nonce?: number;
  wait?: number; // number of confirmations before the method returns the transaction hash
};

Example

import { Chains, Assets } from "@chainflip/sdk/swap";
 
// Swaps 1 Ether for Bitcoin
const transactionHash = await swapSDK.executeSwap({
  amount: (1e18).toString(), // 1 ETH
  destChain: Chains.Bitcoin,
  destAsset: Assets.BTC,
  destAddress: "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
});

The resulting transactionHash can be used in Get Status.

executeSwap() with Cross-Chain Message (CCM)

Additionally, the Chainflip vault smart contract has a call() function that allows passing an additional `message` property to the destination chain. This enables to call a smart contract on the destination chain.

This enhanced composability allows any protocol to seamlessly integrate with Chainflip.

Initiates a swap for the given parameters and calls the destination address with the given message.

For ERC-20 tokens, make sure the token allowance is enough to cover the transfer amount.

The executeSwap method can call this smart contract function when passed a ccmMetadata object with the rest of the ExecuteSwapParams.

type CcmMetadata = {
  message: string;
  gasBudget: string;
};
 
type ExecuteSwapParams =
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "ETH";
      destChain: "Ethereum";
      destAddress: `0x${string}`;
      destAsset: "FLIP" | "USDC";
      ccmMetadata: CcmMetadata;
    }
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "FLIP";
      destChain: "Ethereum";
      destAddress: `0x${string}`;
      destAsset: "USDC" | "ETH";
      ccmMetadata: CcmMetadata;
    }
  | {
      amount: string;
      srcChain: "Ethereum";
      srcAsset: "USDC";
      destChain: "Ethereum";
      destAddress: `0x${string}`;
      destAsset: "FLIP" | "ETH";
      ccmMetadata: CcmMetadata;
    };

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

The message param is a HEX-encoded sequence of bytes that should be passed with the swapped assets and should be shorter than 10k bytes.

Message Receiver

Anyone looking to integrate Chainflip must implement the Solidity function signature below on the destination address. See EVM integration for more details.

function cfReceive(
    uint32 srcChain,
    bytes calldata srcAddress,
    bytes calldata message,
    address token,
    uint256 amount
) external payable;

If the destination address is not a contract or the contract call fails, the Chainflip protocol won't submit the transaction to the destination chain.

This can lead to a loss of funds.

Example

This is how the executeSwap() function looks like with a cross chain message :

import { Chains, Assets } from "@chainflip/sdk/swap";
 
// Swaps 1000 USDC for ETH and pass a message
const transactionHash = await sdk.executeSwap({
  amount: (1000e6).toString(), // 1000 USDC
  destChain: Chains.Ethereum,
  destAsset: Assets.ETH,
  srcAsset: Assets.USDC,
  destAddress: "0x1234567890abcdef1234567890abcdef12345678",
  ccmMetadata: {
    message: "0xdeadc0de", // should be shorter than 10k bytes
    gasBudget: (1e6).toString(), // 1 USDC will be swapped for ETH to pay for gas
  },
});

The resulting transactionHash can be used in Get Status.