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.
/** 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)
}
}Last updated