Buy and Sell Order Complete workflow example

From previous page Buy/Sell orders workflow was explained theoretically, this page will show various examples of a complete workflow using codes. Make sure you have read and understand previous page.

Since Currency is needed to create Buy order and Security is needed to create Sell Order and Getting Currency token is easier from various faucet for testnet and markets for mainnets. We will start the workflow with a Buy Order(to buy security using currency gotten from faucet or bought) then proceed to Claim the Buy order that has been Matched(Trade) to get Security then creating a Sell order(to sell the security and get currency back) and finally Claim the Matched Sell Order(Trade) to get back Currency. please read previous page if you don't understand how all these steps are connected in the workflow.

/** Import Pool and ERC20 contract and ethers **/

//Common Js
const { Pool, ERC20 } = require('@verified-network/verified-sdk'); 
const { ethers } = require('ethers');
//ES Module
import { Pool } from '@verified-network/verified-sdk'
import { ethers } from 'ethers';

/** Initialize Pool Contract and abi encoder**/
    const providerOrSigner = 'provider or signer'  //can be investorWalletProvider from Wallet and Contracts page or Signer from web wallets
    const poolContract = new Pool(providerOrSigner);
    const abiCoder = new ethers.utils.AbiCoder();

/** Format Swap Arguments **/
//note arguments marked as general arguments are arguments that are needed for both swap and batchSwap
    //general arguments
    const swapType = 'Market or Limit' //type of swap best to use 'Market' (so it will trade faster for this example)
    const poolId = 'id of pool to swap from in bytes' //e.g 0x1c54eb0a8bea5eeaf07b1b6d2238baf4bf6d6a4800000000000000000000009a
    const swapKind = 'string 0 or 1' //SwapExactIn = 0 or SwapExactOun = 1; best to use '0' all the time
    const assetIn = 'address of token to swap in(token from)' //will be currency since it's buy order
    const assetOut = 'address of token out' //same as poolAddress(VPT token) e.g 0x1c54eb0a8BEa5eEaf07b1b6d2238BAf4BF6D6a48
    const amount = 'string(amount) of token in' //must be in same decimal places with token in. see best calculation below
    //const amount = (amountRaw * 10 ** assetInDecimals).toString(); where amountRaw = whole number like 1, 2 and assetInDecimals is result of decimals() call on assest in ERC20 contract.  
    let userData;
    //There are 2 types of swap.
    // 1. Market: swap without price will be traded at current market price.
    if(swapType === "Market") {
        userData = "0x" //null abi encoded parameter of [bytes32, uint]
        //same as abiCoder.encode(["bytes32", "uint"],[]);
    }
    // 2. Limit: swap with price, will be traded at price specified.
    if(swapType === "Limit") {
        const priceWei = 'number(amount) of price in wei' //must be in 18 decimals(wei decimals)
        userData = abiCoder.encode(
          ["bytes32", "uint256"],
          [ethers.utils.formatBytes32String("Limit"), priceWei]
        );
    }
    //general argument 4: Deadline
     const deadline = 'string deadline of transaction' //e.g '999999999999999999'(infinity) or very high number in string
    const funds = {
        sender: 'investor/sender address', //address of swap sender
        fromInternalBalance: false, //boolean must be false not to use internal balance
        recipient: 'investor/sender address', //address of swap receiver
        toInternalBalance: false, //boolean must be false not to use internal balance
     }
/** Call approve on assest in contract so vault can have access to it **/
const assetInContract = new ERC20(providerOrSigner, assetIn);
const balancerVault = '0xBA12222222228d8Ba445958a75a0704d566BF2C8' //general vault address for all network
let isApproved = false;
 await assetInContract
    .approve(balancerVault, amount)
    .then((res) => {
      if (res && res.status === 0) {
        //handle successful approve
        console.log("approve succesful with hash: ", res.response.hash);
        isApproved = true;
      }
    })
    .catch((err) => {
      //handle approve error
      console.error("approve failed with error: ", err);
    });
/**Call swap or batchSwap on Pool contract **/
    //Option 1: Swap: for single swap
    //Option 1(swap) argument 1: This type of swap with 'kind' works for swap, for batchSwap it does not have 'kind'.
     const swap = {
         poolId: poolId,
         kind: swapKind,
         assetIn: assetIn,
         assetOut: assetOut,
         amount: amount,
         userData: userData
     }
     //Option 1(swap) argument 2:
     const limit = 'string of amountIn limit' //e.g '0' or amount of token in(can be the same as amount or leave it as '0')
    if(isApproved) {
        //begining of parameters needed for web wallet(metamsk) only//
      const VPTAddress = 'VPT address the same with pool address'
      const accountAddress = 'user/investor address' 
      const VPTContract = new ERC20(providerOrSigner, VPTAddress);
      const VPTBalanceBeforeSwap = await VPTContract.balanceOf(accountAddress);
       //end of parameters needed for web wallet(metamsk) only//
        await poolContract.swap(swap, funds, limit, deadline).then((res) => {
        const swapResponse = res.response;
        if(swapResponse.status === 0) { 
            //status 0 means succesful transaction
            console.log("swap successful with transaction hash: ", swapResponse.hash)
            //the code below is for project using web wallets(metamask) only
            //it will add VPT to users token lists.
            if (Number(VPTBalanceBeforeSwap.response.result) <= 0) {
              const provider = 'web wallet(metamask) provider' //it must be web wallet provider signer won't work.
              await provider.request({
                method: "wallet_watchAsset",
                params: {
                  type: "ERC20",
                  options: {
                    address: VPTAddress,
                    symbol: "VPT",
                    decimals: 18,
                  },
                },
              }).then((_res) => {
                  console.log("VPT added to token list succesfully")
              }).catch((err) => {
                  console.error("Error while adding VPT to token list: ", err)
              });
        }else{
            //status 1 means failed transaction
            console.error("Unexpected error occured while calling swap function with message: ", swapResponse.message || swapResponse.reason)
        }
    }).catch((err) => {
        console.error("Swap failed with error: ", err)
    })
    }
    
    //=======================//
    
    //Option 2: (batchSwap): single and multiple swaps. reconmended it cost less gas **/
    //call getPoolTokens to get pool tokens list.
    const poolTokensResponse = await poolContract.getPoolTokens(poolId);
    const assests = poolTokensResponse.response.result; //array of tokens address(includes security, currency and pool addrress)
    const assetInIndex = assests.findIndex((tkn) => {
        return tkn.toLowerCase() === assetIn.toLowerCase();
    });//batchswap takes assetInindex(index of tokenIn in assests array) unlike swap with assetIn(address of token in)
    const assetOutIndex = poolTokens.tokens.findIndex((tkn) => {
    return tkn.toLowerCase() === assetOut.toLowerCase();
    });//batchswap takes assetOutindex(index of token out in assests array) unlike swap with assetOut(address of token out)
    //Option2(batchSwap) argument 1:
    let batchSwap = {
        poolId: poolId, //the same with poolId above
        assetInIndex: assetInIndex.toString(), //string of token in index
        assetOutIndex: assetOutIndex.toString(), //string of token out index
        amount: amount, //the same with amount above.
        userData: userData //the same with userData above
    } //does not have 'kind' like swap argument
    //Option 2(batchSwap) argument 2:
    let limits = new Array(3).fill("0"); //batchswap takes limits in array of number(as string) unlike swap with limit as on number(as string)
    limits[assetInIndex] = amount; //update the limit for index of token in. amount must be string
    const swaps = [batchSwap] //batchSwap takes swaps in array. add more swap for multiple swaps
    if(isApproved) {
      //begining of parameters needed for web wallet(metamsk) only//
      const VPTAddress = 'VPT address the same with pool address'
      const accountAddress = 'user/investor address' 
      const VPTContract = new ERC20(providerOrSigner, VPTAddress);
      const VPTBalanceBeforeSwap = await VPTContract.balanceOf(accountAddress);
       //end of parameters needed for web wallet(metamsk) only//
      await poolContract.batchswap(swapKind, swaps, assests, funds, limits, deadline).then((res) => {
        const batchSwapResponse = res.response;
        if(batchSwapResponse.status === 0) {
             //status 0 means succesful transaction
            console.log("batchswap successful with transaction hash: ", batchSwapResponse.hash)
            //the code below is for project using web wallets(metamask) only
            //it will add VPT to users token lists.
            if (Number(VPTBalanceBeforeSwap.response.result) <= 0) {
              const provider = 'web wallet(metamask) provider' //it must be web wallet provider signer won't work.
              await provider.request({
                method: "wallet_watchAsset",
                params: {
                  type: "ERC20",
                  options: {
                    address: VPTAddress,
                    symbol: "VPT",
                    decimals: 18,
                  },
                },
              }).then((_res) => {
                  console.log("VPT added to token list succesfully")
              }).catch((err) => {
                  console.error("Error while adding VPT to token list: ", err)
              });
            }
        }else{
            //status 1 means failed transaction
            console.error("Unexpected error occured while calling batchswap function with message: ", batchSwapResponse.message || batchSwapResponse.reason)
        }
    }).catch((err) => {
        console.error("Batchswap failed with error: ", err)
    }  
    }

The Above code will create a Buy Market or Limit order, depending on the userData used, and after that user will received VPT(Verified Pool Token). Now user will wait till the order created is matched and a trade occurs to move to next step which is Settling Buy Trade(claiming Security token using VPT)

/** Import Pool contract and ethers **/

//Common Js
const { Pool, ERC20 } = require('@verified-network/verified-sdk'); 
const { ethers } = require('ethers');
//ES Module
import { Pool } from '@verified-network/verified-sdk'
import { ethers } from 'ethers';

/** Initialize Pool Contract and abi encoder**/
    const providerOrSigner = 'provider or signer'  //can be investorWalletProvider from Wallet and Contracts page or Signer from web wallets
    const poolContract = new Pool(providerOrSigner);
    const abiCoder = new ethers.utils.AbiCoder();

/** Get User all trades and format swap and batchSwap arguments **/
//note arguments marked as general arguments are arguments that are needed for both swap and batchSwap
    //general arguments
    const poolAddress = 'pool address'
    const account = 'user/sender address'
    const securityAddress = 'address of security to claim'
    const verifiedPoolAbi 'array of verified pool abi' //contact verified Network team for this
    const verifiedOrderBookAbi = 'array of verified orderbook abi' //contact verified Network team for this
    const verifiedPoolContract = new ethers.Contract(poolAddress, verifiedPoolAbi, providerOrSigner);
    const verifiedOrderBookAddress = await verifiedPoolContract._orderbook();
    const verifiedOrderBookContract = new ethers.Contract(verifiedOrderBookAddress, verifiedOrderBookAbi, providerOrSigner);
    let allTradesTime = awaitsverifiedOrderBookContract.getTrades();
    allTradesTime = allTrades.filter((val) => val !== "0");
    const lastTradeTime = allTradesTime[allTradesTime.length - 1];
    const lastTradeInfo = await verifiedOrderBookContract.getOrder(account, Number(lastTradeTime));
    const isParty = lastTradeInfo.partyAddress.toLowerCase() === account.toLowerCase();
    const orderRef = isParty ? lastTradeInfo.partyRef: lastTradeInfo.counterpartyRef;
    const lastTradeDetails = await verifiedOrderBookContract.getOrder(orderRef)
    const isSecurityTokenIn = lastTradeDetails.tokenIn.toLowerCase() === securityAddress.toLowerCase();
    const amount = isSecurityTokenIn ? lastTradeInfo.securityTraded.toString() : lastTradeInfo.currencyTraded.toString();
    const poolId = 'id of pool to swap from in bytes' //e.g 0x1c54eb0a8bea5eeaf07b1b6d2238baf4bf6d6a4800000000000000000000009a
    const swapKind = 'string 0 or 1' //SwapExactIn = 0 or SwapExactOun = 1; best to use '0' all the time
    const assetIn = 'VPT address same as pool address' //same as poolAddress(VPT token) e.g 0x1c54eb0a8BEa5eEaf07b1b6d2238BAf4BF6D6a48
    const assetOut = 'Security address' //since we want to settle buy order asset out is security, if we want to a settle sell order it will be currency
    const userData = abiCoder.encode(
      ["bytes32", "uint"],
      [ethers.utils.formatBytes32String(""), lastTradeInfo.dt]
    );
   const deadline = 'string deadline of transaction' //e.g '999999999999999999'(infinity) or very high number in string
    const funds = {
        sender: 'investor/sender address', //address of swap sender
        fromInternalBalance: false, //boolean must be false not to use internal balance
        recipient: 'investor/sender address', //address of swap receiver
        toInternalBalance: false, //boolean must be false not to use internal balance
     }
/** Call approve on assest in contract so vault can have access to it **/
const assetInContract = new ERC20(providerOrSigner, assetIn);
const balancerVault = '0xBA12222222228d8Ba445958a75a0704d566BF2C8' //general vault address for all network
let isApproved = false;
 await assetInContract
    .approve(balancerVault, amount)
    .then((res) => {
      if (res && res.status === 0) {
        //handle successful approve
        console.log("approve succesful with hash: ", res.response.hash);
        isApproved = true;
      }
    })
    .catch((err) => {
      //handle approve error
      console.error("approve failed with error: ", err);
    });
/**Call swap or batchSwap on Pool contract **/
    //Option 1: Swap: for single swap
    //Option 1(swap) argument 1: This type of swap with 'kind' works for swap, for batchSwap it does not have 'kind'.
     const swap = {
         poolId: poolId,
         kind: swapKind,
         assetIn: assetIn,
         assetOut: assetOut,
         amount: amount,
         userData: userData
     }
     //Option 1(swap) argument 2:
     const limit = 'string of amountIn limit' //e.g '0' or amount of token in(can be the same as amount or leave it as '0')
     
/** Call swap or batchSwap on Pool contract **/
    //Swap: for single swap
    await poolContract.swap(swap, funds, limit, deadline).then((res) => {
        const swapResponse = res.response;
        if(swapResponse.status === 0) { 
            //status 0 means succesful transaction
            console.log("Settle trade successful with transaction hash: ", swapResponse.hash)
        }else{
            //status 1 means failed transaction
            console.error("Unexpected error occured while settling trade with message: ", swapResponse.message || swapResponse.reason)
        }
    }).catch((err) => {
        console.error("Settle trade failed with error: ", err)
    })
    
    //batchSwap: single and multiple swaps. cost less gas
    //call getPoolTokens to get pool tokens list.
    const poolTokensResponse = await poolContract.getPoolTokens(poolId);
    const assests = poolTokensResponse.response.result; //array of tokens address(includes security, currency and pool addrress)
    const assetInIndex = assests.findIndex((tkn) => {
        return tkn.toLowerCase() === assetIn.toLowerCase();
    });//batchswap takes assetInindex(index of tokenIn in assests array) unlike swap with assetIn(address of token in)
    const assetOutIndex = poolTokens.tokens.findIndex((tkn) => {
    return tkn.toLowerCase() === assetOut.toLowerCase();
    });//batchswap takes assetOutindex(index of token out in assests array) unlike swap with assetOut(address of token out)
    let limits = new Array(3).fill("0"); //batchswap takes limits in array of numbers unlike swap with limit as number
    limits[assetInIndex] = amount; //update the limit for index of token in.
    let batchSwap = {
        poolId: poolId,
        assetInIndex: assetInIndex.toString(),
        assetOutIndex: assetOutIndex.toString(),
        amount: amount, //the same with amount above.
        userData: userData //the same with userData above
    } //does not have 'kind' like swap argument
    const swaps = [batchSwap] //batchSwap takes swaps in array. add more swap for multiple swaps
    await poolContract.batchswap(swapKind, swaps, assests, funds, limits, deadline).then((res) => {
        const batchSwapResponse = res.response;
        if(batchSwapResponse.status === 0) {
             //status 0 means succesful transaction
            console.log("settle trade successful with transaction hash: ", batchSwapResponse.hash)
        }else{
            //status 1 means failed transaction
            console.error("Unexpected error occured while settling trade with message: ", batchSwapResponse.message || batchSwapResponse.reason)
        }
    }).catch((err) => {
        console.error("Settle trade failed with error: ", err)
    }

The Above code will create a Claim Trade Order which will settle the previous Buy Order created. User will receive Security after the order is successful. For next step we will create a Buy order with the security received from this Settle trade.

/** Import Pool and ERC20 contract and ethers **/

//Common Js
const { Pool, ERC20 } = require('@verified-network/verified-sdk'); 
const { ethers } = require('ethers');
//ES Module
import { Pool } from '@verified-network/verified-sdk'
import { ethers } from 'ethers';

/** Initialize Pool Contract and abi encoder**/
    const providerOrSigner = 'provider or signer'  //can be investorWalletProvider from Wallet and Contracts page or Signer from web wallets
    const poolContract = new Pool(providerOrSigner);
    const abiCoder = new ethers.utils.AbiCoder();

/** Format Swap Arguments **/
//note arguments marked as general arguments are arguments that are needed for both swap and batchSwap
    //general arguments
    const swapType = 'Market or Limit' //type of swap best to use 'Market' (so it will trade faster for this example)
    const poolId = 'id of pool to swap from in bytes' //e.g 0x1c54eb0a8bea5eeaf07b1b6d2238baf4bf6d6a4800000000000000000000009a
    const swapKind = 'string 0 or 1' //SwapExactIn = 0 or SwapExactOun = 1; best to use '0' all the time
    const assetIn = 'address of token to swap in(token from)' //will be security address since it's a sell order
    const assetOut = 'address of token out' //same as poolAddress(VPT) e.g 0x1c54eb0a8BEa5eEaf07b1b6d2238BAf4BF6D6a48
    const amount = 'string(amount) of token in' //must be in same decimal places with token in. see best calculation below
    //const amount = (amountRaw * 10 ** assetInDecimals).toString(); where amountRaw = whole number like 1, 2 and assetInDecimals is result of decimals() call on assest in ERC20 contract.  
    let userData;
    //There are 2 types of swap.
    // 1. Market: swap without price will be traded at current market price.
    if(swapType === "Market") {
        userData = "0x" //null abi encoded parameter of [bytes32, uint]
        //same as abiCoder.encode(["bytes32", "uint"],[]);
    }
    // 2. Limit: swap with price, will be traded at price specified.
    if(swapType === "Limit") {
        const priceWei = 'number(amount) of price in wei' //must be in 18 decimals(wei decimals)
        userData = abiCoder.encode(
          ["bytes32", "uint256"],
          [ethers.utils.formatBytes32String("Limit"), priceWei]
        );
    }
    //general argument 4: Deadline
     const deadline = 'string deadline of transaction' //e.g '999999999999999999'(infinity) or very high number in string
    const funds = {
        sender: 'investor/sender address', //address of swap sender
        fromInternalBalance: false, //boolean must be false not to use internal balance
        recipient: 'investor/sender address', //address of swap receiver
        toInternalBalance: false, //boolean must be false not to use internal balance
     }
/** Call approve on assest in contract so vault can have access to it **/
const assetInContract = new ERC20(providerOrSigner, assetIn);
const balancerVault = '0xBA12222222228d8Ba445958a75a0704d566BF2C8' //general vault address for all network
let isApproved = false;
 await assetInContract
    .approve(balancerVault, amount)
    .then((res) => {
      if (res && res.status === 0) {
        //handle successful approve
        console.log("approve succesful with hash: ", res.response.hash);
        isApproved = true;
      }
    })
    .catch((err) => {
      //handle approve error
      console.error("approve failed with error: ", err);
    });
/**Call swap or batchSwap on Pool contract **/
    //Option 1: Swap: for single swap
    //Option 1(swap) argument 1: This type of swap with 'kind' works for swap, for batchSwap it does not have 'kind'.
     const swap = {
         poolId: poolId,
         kind: swapKind,
         assetIn: assetIn,
         assetOut: assetOut,
         amount: amount,
         userData: userData
     }
     //Option 1(swap) argument 2:
     const limit = 'string of amountIn limit' //e.g '0' or amount of token in(can be the same as amount or leave it as '0')
    if(isApproved) {
        //begining of parameters needed for web wallet(metamsk) only//
      const VPTAddress = 'VPT address the same with pool address'
      const accountAddress = 'user/investor address' 
      const VPTContract = new ERC20(providerOrSigner, VPTAddress);
      const VPTBalanceBeforeSwap = await VPTContract.balanceOf(accountAddress);
       //end of parameters needed for web wallet(metamsk) only//
        await poolContract.swap(swap, funds, limit, deadline).then((res) => {
        const swapResponse = res.response;
        if(swapResponse.status === 0) { 
            //status 0 means succesful transaction
            console.log("swap successful with transaction hash: ", swapResponse.hash)
            //the code below is for project using web wallets(metamask) only
            //it will add VPT to users token lists.
            if (Number(VPTBalanceBeforeSwap.response.result) <= 0) {
              const provider = 'web wallet(metamask) provider' //it must be web wallet provider signer won't work.
              await provider.request({
                method: "wallet_watchAsset",
                params: {
                  type: "ERC20",
                  options: {
                    address: VPTAddress,
                    symbol: "VPT",
                    decimals: 18,
                  },
                },
              }).then((_res) => {
                  console.log("VPT added to token list succesfully")
              }).catch((err) => {
                  console.error("Error while adding VPT to token list: ", err)
              });
        }else{
            //status 1 means failed transaction
            console.error("Unexpected error occured while calling swap function with message: ", swapResponse.message || swapResponse.reason)
        }
    }).catch((err) => {
        console.error("Swap failed with error: ", err)
    })
    }
    
    //=======================//
    
    //Option 2: (batchSwap): single and multiple swaps. reconmended it cost less gas **/
    //call getPoolTokens to get pool tokens list.
    const poolTokensResponse = await poolContract.getPoolTokens(poolId);
    const assests = poolTokensResponse.response.result; //array of tokens address(includes security, currency and pool addrress)
    const assetInIndex = assests.findIndex((tkn) => {
        return tkn.toLowerCase() === assetIn.toLowerCase();
    });//batchswap takes assetInindex(index of tokenIn in assests array) unlike swap with assetIn(address of token in)
    const assetOutIndex = poolTokens.tokens.findIndex((tkn) => {
    return tkn.toLowerCase() === assetOut.toLowerCase();
    });//batchswap takes assetOutindex(index of token out in assests array) unlike swap with assetOut(address of token out)
    //Option2(batchSwap) argument 1:
    let batchSwap = {
        poolId: poolId, //the same with poolId above
        assetInIndex: assetInIndex.toString(), //string of token in index
        assetOutIndex: assetOutIndex.toString(), //string of token out index
        amount: amount, //the same with amount above.
        userData: userData //the same with userData above
    } //does not have 'kind' like swap argument
    //Option 2(batchSwap) argument 2:
    let limits = new Array(3).fill("0"); //batchswap takes limits in array of number(as string) unlike swap with limit as on number(as string)
    limits[assetInIndex] = amount; //update the limit for index of token in. amount must be string
    const swaps = [batchSwap] //batchSwap takes swaps in array. add more swap for multiple swaps
    if(isApproved) {
      //begining of parameters needed for web wallet(metamsk) only//
      const VPTAddress = 'VPT address the same with pool address'
      const accountAddress = 'user/investor address' 
      const VPTContract = new ERC20(providerOrSigner, VPTAddress);
      const VPTBalanceBeforeSwap = await VPTContract.balanceOf(accountAddress);
       //end of parameters needed for web wallet(metamsk) only//
      await poolContract.batchswap(swapKind, swaps, assests, funds, limits, deadline).then((res) => {
        const batchSwapResponse = res.response;
        if(batchSwapResponse.status === 0) {
             //status 0 means succesful transaction
            console.log("batchswap successful with transaction hash: ", batchSwapResponse.hash)
            //the code below is for project using web wallets(metamask) only
            //it will add VPT to users token lists.
            if (Number(VPTBalanceBeforeSwap.response.result) <= 0) {
              const provider = 'web wallet(metamask) provider' //it must be web wallet provider signer won't work.
              await provider.request({
                method: "wallet_watchAsset",
                params: {
                  type: "ERC20",
                  options: {
                    address: VPTAddress,
                    symbol: "VPT",
                    decimals: 18,
                  },
                },
              }).then((_res) => {
                  console.log("VPT added to token list succesfully")
              }).catch((err) => {
                  console.error("Error while adding VPT to token list: ", err)
              });
            }
        }else{
            //status 1 means failed transaction
            console.error("Unexpected error occured while calling batchswap function with message: ", batchSwapResponse.message || batchSwapResponse.reason)
        }
    }).catch((err) => {
        console.error("Batchswap failed with error: ", err)
    }  
    }

The Above code will create a Sell Market or Limit order, depending on the userData used, and after that user will received VPT(Verified Pool Token). Now user will wait till the sell order created is matched and a trade occurs to move to the final step of the workflow which is Settling Sell Trade(claiming Currency token using VPT)

/** Import Pool contract and ethers **/

//Common Js
const { Pool, ERC20 } = require('@verified-network/verified-sdk'); 
const { ethers } = require('ethers');
//ES Module
import { Pool } from '@verified-network/verified-sdk'
import { ethers } from 'ethers';

/** Initialize Pool Contract and abi encoder**/
    const providerOrSigner = 'provider or signer'  //can be investorWalletProvider from Wallet and Contracts page or Signer from web wallets
    const poolContract = new Pool(providerOrSigner);
    const abiCoder = new ethers.utils.AbiCoder();

/** Get User all trades and format swap and batchSwap arguments **/
//note arguments marked as general arguments are arguments that are needed for both swap and batchSwap
    //general arguments
    const poolAddress = 'pool address'
    const account = 'user/sender address'
    const securityAddress = 'address of security to claim'
    const verifiedPoolAbi 'array of verified pool abi' //contact verified Network team for this
    const verifiedOrderBookAbi = 'array of verified orderbook abi' //contact verified Network team for this
    const verifiedPoolContract = new ethers.Contract(poolAddress, verifiedPoolAbi, providerOrSigner);
    const verifiedOrderBookAddress = await verifiedPoolContract._orderbook();
    const verifiedOrderBookContract = new ethers.Contract(verifiedOrderBookAddress, verifiedOrderBookAbi, providerOrSigner);
    let allTradesTime = awaitsverifiedOrderBookContract.getTrades();
    allTradesTime = allTrades.filter((val) => val !== "0");
    const lastTradeTime = allTradesTime[allTradesTime.length - 1];
    const lastTradeInfo = await verifiedOrderBookContract.getOrder(account, Number(lastTradeTime));
    const isParty = lastTradeInfo.partyAddress.toLowerCase() === account.toLowerCase();
    const orderRef = isParty ? lastTradeInfo.partyRef: lastTradeInfo.counterpartyRef;
    const lastTradeDetails = await verifiedOrderBookContract.getOrder(orderRef)
    const isSecurityTokenIn = lastTradeDetails.tokenIn.toLowerCase() === securityAddress.toLowerCase();
    const amount = isSecurityTokenIn ? lastTradeInfo.securityTraded.toString() : lastTradeInfo.currencyTraded.toString();
    const poolId = 'id of pool to swap from in bytes' //e.g 0x1c54eb0a8bea5eeaf07b1b6d2238baf4bf6d6a4800000000000000000000009a
    const swapKind = 'string 0 or 1' //SwapExactIn = 0 or SwapExactOun = 1; best to use '0' all the time
    const assetIn = 'VPT address same as pool address' //same as poolAddress(VPT token) e.g 0x1c54eb0a8BEa5eEaf07b1b6d2238BAf4BF6D6a48
    const assetOut = 'Currency address' //since we want to settle sell order asset out is currency, if we want to settle a buy order it will be security
    const userData = abiCoder.encode(
      ["bytes32", "uint"],
      [ethers.utils.formatBytes32String(""), lastTradeInfo.dt]
    );
   const deadline = 'string deadline of transaction' //e.g '999999999999999999'(infinity) or very high number in string
    const funds = {
        sender: 'investor/sender address', //address of swap sender
        fromInternalBalance: false, //boolean must be false not to use internal balance
        recipient: 'investor/sender address', //address of swap receiver
        toInternalBalance: false, //boolean must be false not to use internal balance
     }
/** Call approve on assest in contract so vault can have access to it **/
const assetInContract = new ERC20(providerOrSigner, assetIn);
const balancerVault = '0xBA12222222228d8Ba445958a75a0704d566BF2C8' //general vault address for all network
let isApproved = false;
 await assetInContract
    .approve(balancerVault, amount)
    .then((res) => {
      if (res && res.status === 0) {
        //handle successful approve
        console.log("approve succesful with hash: ", res.response.hash);
        isApproved = true;
      }
    })
    .catch((err) => {
      //handle approve error
      console.error("approve failed with error: ", err);
    });
/**Call swap or batchSwap on Pool contract **/
    //Option 1: Swap: for single swap
    //Option 1(swap) argument 1: This type of swap with 'kind' works for swap, for batchSwap it does not have 'kind'.
     const swap = {
         poolId: poolId,
         kind: swapKind,
         assetIn: assetIn,
         assetOut: assetOut,
         amount: amount,
         userData: userData
     }
     //Option 1(swap) argument 2:
     const limit = 'string of amountIn limit' //e.g '0' or amount of token in(can be the same as amount or leave it as '0')
     
/** Call swap or batchSwap on Pool contract **/
    //Swap: for single swap
    await poolContract.swap(swap, funds, limit, deadline).then((res) => {
        const swapResponse = res.response;
        if(swapResponse.status === 0) { 
            //status 0 means succesful transaction
            console.log("Settle trade successful with transaction hash: ", swapResponse.hash)
        }else{
            //status 1 means failed transaction
            console.error("Unexpected error occured while settling trade with message: ", swapResponse.message || swapResponse.reason)
        }
    }).catch((err) => {
        console.error("Settle trade failed with error: ", err)
    })
    
    //batchSwap: single and multiple swaps. cost less gas
    //call getPoolTokens to get pool tokens list.
    const poolTokensResponse = await poolContract.getPoolTokens(poolId);
    const assests = poolTokensResponse.response.result; //array of tokens address(includes security, currency and pool addrress)
    const assetInIndex = assests.findIndex((tkn) => {
        return tkn.toLowerCase() === assetIn.toLowerCase();
    });//batchswap takes assetInindex(index of tokenIn in assests array) unlike swap with assetIn(address of token in)
    const assetOutIndex = poolTokens.tokens.findIndex((tkn) => {
    return tkn.toLowerCase() === assetOut.toLowerCase();
    });//batchswap takes assetOutindex(index of token out in assests array) unlike swap with assetOut(address of token out)
    let limits = new Array(3).fill("0"); //batchswap takes limits in array of numbers unlike swap with limit as number
    limits[assetInIndex] = amount; //update the limit for index of token in.
    let batchSwap = {
        poolId: poolId,
        assetInIndex: assetInIndex.toString(),
        assetOutIndex: assetOutIndex.toString(),
        amount: amount, //the same with amount above.
        userData: userData //the same with userData above
    } //does not have 'kind' like swap argument
    const swaps = [batchSwap] //batchSwap takes swaps in array. add more swap for multiple swaps
    await poolContract.batchswap(swapKind, swaps, assests, funds, limits, deadline).then((res) => {
        const batchSwapResponse = res.response;
        if(batchSwapResponse.status === 0) {
             //status 0 means succesful transaction
            console.log("settle trade successful with transaction hash: ", batchSwapResponse.hash)
        }else{
            //status 1 means failed transaction
            console.error("Unexpected error occured while settling trade with message: ", batchSwapResponse.message || batchSwapResponse.reason)
        }
    }).catch((err) => {
        console.error("Settle trade failed with error: ", err)
    }

Last updated