Skip to main content

Transfering between layers

The following guide illustrates how a developer can make use of the blockchain data and map it into the entities provided by Composable SDK.

The first part of the code represented by creating the contracts, will be re-used as it's similar to previous example

Constructing the necessary data#

Before anything else, you need to import our 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''

assign your ethereum provider (Infura is illustrated below)

const mainnetProvider = ew ethers.providers.StaticJsonRpcProvider(  "https://mainnet.infura.io/v3/<infura_key>");
const polygonProvider = ew ethers.providers.StaticJsonRpcProvider(  "https://polygon-mainnet.infura.io/v3/<infura_key>");

construct your contract objects

const sourceChainId: number = 1;const destinationChainId: number = 137;const usdcDecimals = 6;
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);
const mainnetUsdcContract = new ethers.Contract(erc20.usdc.abi, erc20.mainnet.usdc.address, mainnetProvider);const polygonUsdcContract = new ethers.Contract(erc20.usdc.abi, erc20.polygon.usdc.address, polygonProvider);
const mainnetUSDC = new Token(sourceChainId, mainnetUsdcContract.address, usdcDecimals, 'USDC', 'USD Coin');const polygonUSDC = new Token(destinationChainId, polygonUsdcContract.address, usdcDecimals, 'USDC', 'USD Coin');

we now have all the objects we need to interact with the blockchain, fetch data and construct our SDK entities that can be used later in our code. We start with defining our generic methods that will fetch blockchain data and maps result into the SupportedToken entity


// the following method calls our API to retrieve the list of supported tokensasync function getSupportedTokens() {  const response = await axios.get("https://sdk-api.composable.finance/v1/tokens/supported");  const result = response.data as {    crossChainId: string;    chainId: number;    address: string;    decimals: number;    symbol: string;  }[];
  return result.map(    (t) => new Token(t.chainId, t.address, t.decimals, t.symbol, t.symbol)  );}

// the following method retrieves an array of SupportedToken entitiesasync function getPoolMutables(vaultContract: ethers.Contract, tokens: Token[]) {  let supportedTokens: { [s: string]: SupportedToken<Token> } = {};  for (let i = 0; i < tokens.length; i++) {    const token = tokens[i];
    const [maxDeposit, minDeposit, liq] = await Promise.all([      vaultContract.maxAssetTransferSize(token.address),      vaultContract.minAssetTransferSize(token.address),      vaultContract.getCurrentTokenLiquidity(token.address),    ]);
    supportedTokens[token.address] = new SupportedToken(      token,      CurrencyAmount.fromRawAmount(token, maxDeposit.toString()),      CurrencyAmount.fromRawAmount(token, minDeposit.toString()),      CurrencyAmount.fromRawAmount(token, liq.toString())    );  }  return supportedTokens;}

// the following method retrieves a Vault entityasync function getPoolImmutables(vaultContract: ethers.Contract, tokens: Token[]) {  const [    maxFee,    minFee,    maxTransferDelay,    minTransferDelay,    paused,    feeThreshold,  ] = await Promise.all([    vaultContract.maxFee(),    vaultContract.minFee(),    vaultContract.maxTransferDelay(),    vaultContract.minTransferDelay(),    vaultContract.paused(),    vaultContract.feeThreshold(),  ]);
  const supportedTokens = await getPoolMutables(c, tokens);  const result = new Vault(    (await vaultContract.provider.getNetwork()).chainId,    paused,    minTransferDelay.toString(),    maxTransferDelay.toString(),    minFee.toString(),    maxFee.toString(),    feeThreshold.toString(),    supportedTokens  );  return result;}

we now have methods necessary to build the Transfer entity easily, as shown in the example below

const fetchEverything = async () => {
  //fetch and map supported tokens  const supportedTokens = await getSupportedTokens();
  //fetch and create vaults  const mainnetVaultEntity = await getPoolImmutables(      mainnetL2VaultContract,      supportedTokens.filter((t) => t.chainId === 1)  );  const polygonVaultEntity = await getPoolImmutables(      polygonL2VaultContract,      supportedTokens.filter((t) => t.chainId === 137)  );
  const directionEntity = new Direction(    { vault: mainnetVaultEntity, token: mainnetUSDC },    { vault: polygonVaultEntity, token: polygonUSDC }  );
  const destinationAddress = "<YOUR-WALLET-FROM-DESTINATION-CHAIN-HERE>";  const transferAmount = CurrencyAmount.fromRawAmount(mainnetUSDC, "100000000"); //100 USDC  const transferDelay = 100; //we assume minDelay < 100 < maxDelay
  const transfer = new Transfer(directionEntity, transferAmount, destinationAddress, transferDelay);
  const t = new Transfer(    directionEntity,    CurrencyAmount.fromRawAmount(mainnetUSDC, "10000000000000000"),    "0xd19f4f7c9dF8C6Bd134840BBcB9063588B9B5054",    1800  );
}