Collect a liquidity position

In this example, we first fetch all liquidities of an account, then select one of it and collect fee or decreased token from it.

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

1. Fetch liquidity positions

 1const chain:BaseChain = initialChainTable[ChainId.BSC]
 2const rpc = 'https://bsc-dataseed2.defibit.io/'
 3console.log('rpc: ', rpc)
 4const web3 = new Web3(new Web3.providers.HttpProvider(rpc))
 5const account =  web3.eth.accounts.privateKeyToAccount(privateKey)
 6console.log('address: ', account.address)
 7
 8const liquidityManagerAddress = '0x93C22Fbeff4448F2fb6e432579b0638838Ff9581'
 9const liquidityManagerContract = getLiquidityManagerContract(liquidityManagerAddress, web3)
10
11console.log('liquidity manager address: ', liquidityManagerAddress)
12
13const testAAddress = '0xCFD8A067e1fa03474e79Be646c5f6b6A27847399'
14const testBAddress = '0xAD1F11FBB288Cd13819cCB9397E59FAAB4Cdc16F'
15
16const testA = await fetchToken(testAAddress, chain, web3)
17const testB = await fetchToken(testBAddress, chain, web3)
18const fee = 2000 // 2000 means 0.2%
19
20const liquidities = await fetchLiquiditiesOfAccount(
21    chain,
22    web3,
23    liquidityManagerContract,
24    account.address,
25    [testA]
26)
27console.log('liquidity len: ', liquidities.length)
28console.log('liquidity: ', liquidities)

The code above is nearly the same as Fetch liquidity positions, you can view more detailed explains through this link

2. Select one of your liquidity positions to collect

1const liquidity0 = liquidities[0]

of course one can only collect his/her liquidity, cannot collect others.

3. Set max amount of tokenX and tokenY you would collect

 1const tokenA = liquidity0.tokenX
 2const tokenB = liquidity0.tokenY
 3
 4const maxAmountA = liquidity0.remainTokenX
 5const maxAmountB = liquidity0.remainTokenY
 6
 7console.log('tokenA: ', tokenA)
 8console.log('tokenB: ', tokenB)
 9
10console.log('maxAmountA: ', maxAmountA)
11console.log('maxAmountB: ', maxAmountB)

4. Get calling of getCollectLiquidityCall

 1const gasPrice = '5000000000'
 2
 3const {collectLiquidityCalling, options} = getCollectLiquidityCall(
 4    liquidityManagerContract,
 5    account.address,
 6    chain,
 7    {
 8        tokenId: liquidity0.tokenId,
 9        tokenA,
10        tokenB,
11        maxAmountA,
12        maxAmountB
13    } as CollectLiquidityParam,
14    gasPrice
15)

the function getCollectLiquidityCall(…) has following params

 1/**
 2 * @param liquidityManagerContract: web3.eth.Contract, the liquidity manager contract obj
 3 * @param account: string, string of owner's address
 4 * @param chain: BaseChain, the obj describing chain we are using
 5 * @param params: CollectLiquidityParam, specify two tokens and max undecimal amount you want to collect
 6 * @param gasPrice: string| number, gas price
 7 */
 8 export const getCollectLiquidityCall = (
 9    liquidityManagerContract: Contract,
10    account: string,
11    chain: BaseChain,
12    params: CollectLiquidityParam,
13    gasPrice: number | string
14)

we should notice that, if tokenX or tokenY is chain token (like ETH on ethereum or BNB on bsc), we should specify one or some fields in CollectLiquidityParam to indicate sdk collecting in form of Chain Token or collecting in form of Wrapped Chain Token (like WETH on ethereum or WBNB on bsc).

In the sdk version 1.1.* or before, one should specify a field named strictERC20Token to indicate that. true for collecting in form of Wrapped Chain Token, false for collecting in form of Chain Token. In the sdk version 1.2.* or later, you have two ways to indicate sdk.

The first way is as before, specifing strictERC20Token field. The second way is specifing strictERC20Token as undefined and specifying the corresponding token in this param as WETH or ETH.

5. Estimate gas (optional)

of course you can skip this step if you don’t want to limit gas

1const gasLimit = await collectLiquidityCalling.estimateGas(options)
2console.log('gas limit: ', gasLimit)

6. Send transaction!

for metamask or other explorer’s wallet provider, you can easily write

1await collectLiquidityCalling.send({...options, gas: gasLimit})

otherwise, you could use following code

 1// sign transaction
 2const signedTx = await web3.eth.accounts.signTransaction(
 3    {
 4        ...options,
 5        to: liquidityManagerAddress,
 6        data: collectLiquidityCalling.encodeABI(),
 7        gas: new BigNumber(gasLimit * 1.1).toFixed(0, 2),
 8    },
 9    privateKey
10)
11// send transaction
12const tx = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
13console.log('tx: ', tx);

after sending transaction, we will successfully collect token from the liqudity (if no revert occurred)