Skip to main content

Transfering between layers

The following guide illustrates how a developer can make use of the SDK to initiate crosschain transfer. This example uses Ethers library to interact with blockchain nodes.

This example shows how to initiate transfer of USDC from Ethereum Mainnet to Polygon Mainnet. Click here to see all supported networks. To get the supported networks and tokens programmaticaly refer to our API docs.

Before anything else, import v1-sdk-typescript and v1-sdk-protocols npm packages into your application. The latter provides the ABIs and addresses of the contracts used by Mosaic under the hood.

import composable from "@composable-finance/v1-sdk-protocols";import erc20  from "@composable-finance/v1-sdk-protocols";import {  Currency,  CurrencyAmount,  Direction,  Vault,  Token,} from "@composable-finance/v1-sdk-typescript";import { ethers } from "ethers";

Initializing Ethers#

Initialize blockchain provider for both source and destination network

const mainnetProvider = new ethers.providers.StaticJsonRpcProvider(  "<ETH_MAINNET_NODE_JSON_RPC_URL_HERE>");
const polygonProvider = new ethers.providers.StaticJsonRpcProvider(  "<POLY_MAINNET_NODE_JSON_RPC_URL_HERE>");

Initialize contracts retrieving addresses and ABIs using composable interface of the v1-sdk-protocols

const mainnetL2VaultContract = new ethers.Contract(  composable.mainnet.L2Vault.address,  composable.mainnet.L2Vault.abi,  mainnetProvider);const polygonL2VaultContract = new ethers.Contract(  composable.polygon.L2Vault.address,  composable.polygon.L2Vault.abi,  polygonProvider);

Initializing SDK's entities#

We start with the Token entity

const mainnetUSDC = new Token(  1,  erc20.mainnet.usdc.address,  6,  "USDC",  "USD Coin"); // USDC on Ethereum mainnetconst polygonUSDC = new Token(  137,  erc20.polygon.usdc.address,  6,  "USDC",  "USD Coin"); // USDC on Polygon mainnet

continue with SupportedToken entity

//we need to query `l2vaultContract` for the actual dataconst mainnetMinUsdcDeposit = await mainnetL2VaultContract.minAssetTransferSize(  erc20.mainnet.usdc.address);const mainnetMaxUsdcDeposit = await mainnetL2VaultContract.maxAssetTransferSize(  erc20.polygon.usdc.address);const mainnetVaultLiquidity =  await mainnetL2VaultContract.getCurrentTokenLiquidity(    erc20.mainnet.usdc.address  );const polygonMinUsdcDeposit = await polygonL2VaultContract.minAssetTransferSize(  erc20.polygon.usdc.address);const polygonMaxUsdcDeposit = await polygonL2VaultContract.maxAssetTransferSize(  erc20.mainnet.usdc.address);const polygonVaultLiquidity =  await polygonL2VaultContract.getCurrentTokenLiquidity(    erc20.polygon.usdc.address  );
const mainnetUsdcSupportedToken = new SupportedToken(  mainnetUSDC,  CurrencyAmount.fromRawAmount(mainnetUSDC, mainnetMinUsdcDeposit), // min deposit  CurrencyAmount.fromRawAmount(mainnetUSDC, mainnetMaxUsdcDeposit), // max deposit  CurrencyAmount.fromRawAmount(mainnetUSDC, mainnetVaultLiquidity) // available liquidity);const polygonUsdcSupportedToken = new SupportedToken(  polygonUSDC,  CurrencyAmount.fromRawAmount(polygonUSDC, polygonMinUsdcDeposit), // min deposit  CurrencyAmount.fromRawAmount(polygonUSDC, polygonMaxUsdcDeposit), // max deposit  CurrencyAmount.fromRawAmount(polygonUSDC, polygonVaultLiquidity) // available liquidity);

finish with the Vault entity

const mainnetMinDelay = await mainnetL2VaultContract.minTransferDelay();const mainnetMaxDelay = await mainnetL2VaultContract.maxTransferDelay();const mainnetMinFee = await mainnetL2VaultContract.minFee();const mainnetMaxFee = await mainnetL2VaultContract.maxFee();const mainnetFeeThreshold = await mainnetL2VaultContract.feeThreshold();const polygonMinDelay = await polygonL2VaultContract.minTransferDelay();const polygonMaxDelay = await polygonL2VaultContract.maxTransferDelay();const polygonMinFee = await polygonL2VaultContract.minFee();const polygonMaxFee = await polygonL2VaultContract.maxFee();const polygonFeeThreshold = await polygonL2VaultContract.feeThreshold();
const mainnetVault = new Vault(  1, //chainId  mainnetMinDelay, //minTransferDelay  mainnetMaxDelay, //maxTransferDelay  mainnetMinFee, //minFee  mainnetMaxFee, //maxFee  mainnetFeeThreshold, //feeThreshold  [mainnetUsdcSupportedToken] //supportedTokens);
const polygonVault = new Vault(  137, //chainId  polygonMinDelay, //minTransferDelay  polygonMaxDelay, //maxTransferDelay  polygonMinFee, //minFee  polygonMaxFee, //maxFee  polygonFeeThreshold, //feeThreshold  [polygonUsdcSupportedToken] //supportedTokens);

after constructing Vault, we need a Direction entity

const direction = new Direction(  { mainnetVault, mainnetUSDC },  { polygonVault, polygonUSDC });

we are now ready to create the Transfer object

const destinationAddress = "<YOUR-WALLET-FROM-DESTINATION-CHAIN-HERE>";const transferAmount = CurrencyAmount.fromRawAmount(mainnetUSDC, "100000000"); // 100 USDCconst transferDelay = 1800; // time in seconds user is willing to wait till their transfer is completed
const transfer = new Transfer(  direction,  transferAmount,  destinationAddress,  transferDelay);
// verify your data by callingtransfer.verifyTransfer();
// calculate fee by callingconst fee = transfer.calculateFee();

Transfer object that holds valid data that can be used in your application. For example, to initiate a crosslayer transfer, you could do

await mainnetL2VaultContract.depositERC20(  transferAmount,  transfer.direction.from.token.address,  transfer.destinationAddress,  transfer.direction.to.token.chainId,  transfer.transferDelay);