Swap Query x2y With Online Data

In this chapter, we will do swap query of x2y mode with online data from bsc-test chain.

The full example code of this chapter can be spotted here.

1. some imports

first some base imports

 1import {BaseChain, ChainId, initialChainTable} from 'iziswap-sdk/lib/base/types'
 2import Web3 from 'web3';
 3import { getLiquidities, getLimitOrders, getPointDelta, getPoolContract, getPoolState } from 'iziswap-sdk/lib/pool/funcs';
 4import { getPoolAddress, getLiquidityManagerContract } from 'iziswap-sdk/lib/liquidityManager/view';
 5import { Orders } from 'iziswap-sdk/lib/swapQuery/library/Orders'
 6import { LogPowMath } from 'iziswap-sdk/lib/swapQuery/library/LogPowMath'
 7import { iZiSwapPool } from 'iziswap-sdk/lib/swapQuery/iZiSwapPool'
 8import { decimal2Amount, fetchToken } from 'iziswap-sdk/lib/base/token/token';
 9import { SwapQuery } from 'iziswap-sdk/lib/swapQuery/library/State';
10import { SwapX2YModule } from 'iziswap-sdk/lib/swapQuery/swapX2YModule'
11import JSBI from 'jsbi';

2. some basic initialization

1const chain:BaseChain = initialChainTable[ChainId.BSCTestnet]
2// test net
3const rpc = 'https://data-seed-prebsc-1-s3.binance.org:8545/'
4console.log('rpc: ', rpc)
5
6const web3 = new Web3(new Web3.providers.HttpProvider(rpc))

we can see in the above code, we will connect to bsc-test net.

3. some basic query

 1const liquidityManagerAddress = '0xDE02C26c46AC441951951C97c8462cD85b3A124c'
 2const liquidityManagerContract = getLiquidityManagerContract(liquidityManagerAddress, web3)
 3
 4const iZiAddress = '0x551197e6350936976DfFB66B2c3bb15DDB723250'.toLowerCase()
 5const BNBAddress = '0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd'.toLowerCase()
 6const iZi = await fetchToken(iZiAddress, chain, web3)
 7const BNB = await fetchToken(BNBAddress, chain, web3)
 8const fee = 2000 // 2000 means 0.2%
 9const poolAddress = await getPoolAddress(liquidityManagerContract, iZi, BNB, fee)
10
11const tokenXAddress = iZiAddress < BNBAddress ? iZiAddress : BNBAddress
12const tokenYAddress = iZiAddress < BNBAddress ? BNBAddress : iZiAddress
13
14const poolContract = getPoolContract(poolAddress, web3)
15const state = await getPoolState(poolContract)
16const pointDelta = await getPointDelta(poolContract)

We can see in the above code, iZi is tokenX and BNB is tokenY in bsc test net.

4. fetch order data from poolContract

 1const leftPoint = state.currentPoint - 5000
 2const rightPoint = state.currentPoint + 5000
 3const batchsize = 2000
 4
 5const liquidityData = await getLiquidities(poolContract, leftPoint, rightPoint, state.currentPoint, pointDelta, state.liquidity, batchsize)
 6const limitOrderData = await getLimitOrders(poolContract, leftPoint, rightPoint, pointDelta, batchsize)
 7
 8const orders: Orders.Orders = {
 9    liquidity: liquidityData.liquidities,
10    liquidityDeltaPoint: liquidityData.point,
11    sellingX: limitOrderData.sellingX,
12    sellingXPoint: limitOrderData.sellingXPoint,
13    sellingY: limitOrderData.sellingY,
14    sellingYPoint: limitOrderData.sellingYPoint
15}

The interface of getLiquidities can be viewed as following:

 1export const getLiquidities = async (
 2    pool: Contract,
 3    leftPoint: number,
 4    rightPoint: number,
 5    targetPoint: number,
 6    pointDelta: number,
 7    targetLiquidity: string,
 8    batchSize: number
 9): Promise<{
10    liquidities: JSBI[],
11    point: number[]
12}>

When we call getLiquidities, we should transfer a targetPoint with its liquidity value targetLiquidity (usually state.currentPoint and state.liquidity).

5. form pool data

 1const sqrtRate_96 = LogPowMath.getSqrtPrice(1)
 2
 3const swapQueryState: SwapQuery.State = {
 4    currentPoint: state.currentPoint,
 5    liquidity: JSBI.BigInt(state.liquidity),
 6    sqrtPrice_96: LogPowMath.getSqrtPrice(state.currentPoint),
 7    liquidityX: JSBI.BigInt(state.liquidityX)
 8}
 9
10const pool = new iZiSwapPool(swapQueryState, orders, sqrtRate_96, pointDelta, fee)

Here, state object is obtained some basic query.

6. do swap query

 1const lowPt = state.currentPoint - 1500;
 2
 3const tokenX = {
 4    address: '0x551197e6350936976DfFB66B2c3bb15DDB723250',
 5    decimal: 18
 6} as TokenInfoFormatted
 7const inputAmountStr = decimal2Amount(5, tokenX).toFixed(0)
 8
 9const {amountX, amountY} = SwapX2YModule.swapX2Y(pool, JSBI.BigInt(inputAmountStr), lowPt)
10
11console.log('cost: ', amountX.toString())
12console.log('acquire: ', amountY.toString())

Here, lowPt means lower bound of point or undecimal_price_x_by_y during swap. When we call interface like swapY2X or swapY2XDesireX, the parameter highPt means higher bound of point or undecimal_price_x_by_y during swap.

After we run codes above, amountX will store undecimal amount of tokenX during this swap and amountY will store undecimal amount of tokenY during this swap.

Notice, when we use those order data to call swapX2Y or swapX2YDesireY, we should garrentee following non-equalities:

1max(sellingYPoint[0], liquidityDeltaPoint[0]) <= lowPoint
2lowPoint <= currentPoint
3currentPoint <= liquidityDeltaPoint.last()

and if we want to call swapY2X or swapY2XDesireX, we should garrentee that.

1liquidityDeltaPoint[0] <= currentPoint
2currentPoint < highPoint
3highPoint <= min(sellingXPoint.last(), liquidityDeltaPoint.last())

otherwise, an iZiSwapError with corresponding errcode and infomation will be throwed in this interface.

If you are sure your swap will not exceed following range by limit amount or desire parameter.

1[max(sellingYPoint[0], liquidityDeltaPoint[0]), min(sellingXPoint.last(), liquidityDeltaPoint.last())]

you can add some fake data with very left or right point as guards to order data.

Notice that, when we call swapX2Y and swapX2YDesireY, amountX is amount of tokenX actually payed. When we call swapY2X and swapY2XDesireX, amountY is amount of tokenY actually payed.