Add Liquidity Guide
Using the BEX SDK, users can add liquidity using two primary methods (see AddLiquidityKind):
- Unbalanced - add liquidity with arbitrary amounts of each token
- Proportional - add liquidity with proportional amount of both tokens
Example: Adding Unbalanced Liquidity
In this example, we use the BEX SDK and Ethers.js to add single-token BERA
liquidity to a given pool.
import { ethers } from "ethers";
import {
BalancerApi,
AddLiquidity,
AddLiquidityKind,
Slippage,
} from "@berachain-foundation/berancer-sdk";
// Initialize provider and wallet
const RPC_URL = "https://rpc.berachain.com/";
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
const balancerApi = new BalancerApi("https://api.berachain.com/", 80094);
// Get pool data
const poolId =
"0xf961a8f6d8c69e7321e78d254ecafbcc3a637621000000000000000000000001";
const poolState = await balancerApi.pools.fetchPoolState(poolId);
// Prepare add liquidity input - note we're only adding one token for unbalanced
const addLiquidityInput = {
chainId: CHAIN_ID,
kind: AddLiquidityKind.Unbalanced,
rpcUrl: RPC_URL,
amountsIn: [
{
address: WBERA_TOKEN,
decimals: 18,
rawAmount: ethers.parseUnits("0.1", 18), // 0.1 BERA
},
],
};
const addLiquidity = new AddLiquidity();
// Query expected BPT out
const queryOutput = await addLiquidity.query(addLiquidityInput, poolState);
console.log(
"Expected BPT Out:",
ethers.formatUnits(queryOutput.bptOut.amount, 18)
);
// Build transaction with 1% slippage
const slippage = Slippage.fromPercentage("1");
const deadline = BigInt(Math.floor(Date.now() / 1000) + 60);
const callData = addLiquidity.buildCall({
...queryOutput,
chainId: CHAIN_ID,
sender: wallet.address,
poolId: poolState.id,
recipient: wallet.address,
wethIsEth: true,
slippage,
deadline,
});
// Send transaction
const tx = await wallet.sendTransaction({
to: callData.to,
data: callData.callData,
value: callData.value,
});
console.log("Transaction sent:", tx.hash);
const receipt = await tx.wait();
Below we breakdown the code example above.
Helper Classes
The three main helper classes we use from the SDK are:
BalancerApi
- to simplify retrieving pool data from the Pools APIAddLiquidity
- to build addLiquidity queries and transactionsSlippage
- to simplify creating limits with user defined slippage
Fetching Pool Data
After initializing the BalancerApi
class, we can fetch current pool data using fetchPoolState
.
const balancerApi = new BalancerApi("https://api.berachain.com/", 80094);
// Get pool data
const poolId =
"0xf961a8f6d8c69e7321e78d254ecafbcc3a637621000000000000000000000001";
const poolState = await balancerApi.pools.fetchPoolState(poolId);
Simulation and Slippage Setting
The AddLiquidity
class has a query
method that allows us to simulate the add liquidity transaction. This is useful for estimating the expected output and slippage. It takes in the addLiquidityInput
and poolState
as arguments.
We also set the slippage to 1% meaning the transaction reverts if we receive less than 99% of the expected output.
// Query expected BPT out
const queryOutput = await addLiquidity.query(addLiquidityInput, poolState);
// Build transaction with 1% slippage
const slippage = Slippage.fromPercentage("1");
Building the Transaction
The AddLiquidity
class has a buildCall
method that allows us to build the transaction. This method takes in the queryOutput
and address parameters.
const callData = addLiquidity.buildCall({
...queryOutput,
sender: wallet.address,
recipient: wallet.address,
wethIsEth: true,
slippage,
deadline,
});
Adding Proportional Liquidity
Adding proportional liquidity is similar to adding unbalanced liquidity, but instead of specifying the amount of each token, we specify a referenceAmount
for one of the tokens. (see AddLiquidityProportionalInput) The SDK will then calculate the amount of the other token to add based on the current pool composition.
addLiquidityInput = {
chainId,
kind: AddLiquidityKind.Proportional,
rpcUrl: RPC_URL,
referenceAmount: {
rawAmount: parseUnits(tokenAmount, tokenDecimals),
decimals: tokenDecimals,
address: tokenAddress,
},
};