From fd9bb1d1ee0b2152ed336f3cbee4eb4e33fb22be Mon Sep 17 00:00:00 2001 From: Mike McDonald Date: Mon, 13 Feb 2023 12:43:44 -0600 Subject: [PATCH] cleanup repo for release. remove empty guides to be added later --- README.md | 11 + .../public/images/exit-swap-diagram.png} | Bin .../public/images/join-swap-diagram.png} | Bin docs/concepts/pools/more/configuration.md | 2 +- docs/guides/README.md | 21 +- docs/guides/aggregators/boosted-pools.md | 1 - .../arbitrageurs/execute-a-batch-swap.md | 7 - docs/guides/arbitrageurs/get-spot-price.md | 10 - .../utilizing-internal-balances.md | 1 - docs/guides/builders/deploy-pool.md | 1 - .../builders}/exit-pool.md | 77 +++---- docs/guides/builders/join-pool.md | 193 +++++++++++++++++- docs/guides/builders/verify-pool.md | 1 - docs/guides/integrators/format-userdata.md | 25 --- docs/reference/contracts/apis/vault.md | 4 - docs/sdk/liquidity-managment/.order | 1 - docs/sdk/liquidity-managment/join-pool.md | 189 ----------------- docs/sdk/technical-reference/helpers.md | 14 +- docs/sdk/technical-reference/relayer.md | 12 +- theme/src/client/layouts/NotFound.vue | 2 +- 20 files changed, 265 insertions(+), 307 deletions(-) create mode 100644 README.md rename docs/{sdk/liquidity-managment/2023-02-03-14-16-20.png => .vuepress/public/images/exit-swap-diagram.png} (100%) rename docs/{sdk/liquidity-managment/2023-02-03-15-13-29.png => .vuepress/public/images/join-swap-diagram.png} (100%) delete mode 100644 docs/guides/aggregators/boosted-pools.md delete mode 100644 docs/guides/arbitrageurs/execute-a-batch-swap.md delete mode 100644 docs/guides/arbitrageurs/utilizing-internal-balances.md delete mode 100644 docs/guides/builders/deploy-pool.md rename docs/{sdk/liquidity-managment => guides/builders}/exit-pool.md (83%) delete mode 100644 docs/guides/builders/verify-pool.md delete mode 100644 docs/guides/integrators/format-userdata.md delete mode 100644 docs/sdk/liquidity-managment/.order delete mode 100644 docs/sdk/liquidity-managment/join-pool.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..6cbd7a07 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Balancer Docs + +Balancer documentation built using Vuepress and extension of a custom theme. Full markdown docs can be found in the [docs](./docs/) folder. + +## Local Setup + +``` +npm install +npm run build-theme +npm run dev +``` diff --git a/docs/sdk/liquidity-managment/2023-02-03-14-16-20.png b/docs/.vuepress/public/images/exit-swap-diagram.png similarity index 100% rename from docs/sdk/liquidity-managment/2023-02-03-14-16-20.png rename to docs/.vuepress/public/images/exit-swap-diagram.png diff --git a/docs/sdk/liquidity-managment/2023-02-03-15-13-29.png b/docs/.vuepress/public/images/join-swap-diagram.png similarity index 100% rename from docs/sdk/liquidity-managment/2023-02-03-15-13-29.png rename to docs/.vuepress/public/images/join-swap-diagram.png diff --git a/docs/concepts/pools/more/configuration.md b/docs/concepts/pools/more/configuration.md index 87b666c4..9ce37068 100644 --- a/docs/concepts/pools/more/configuration.md +++ b/docs/concepts/pools/more/configuration.md @@ -10,7 +10,7 @@ Balancer is a flexibile protocol and as such there are many choices an user or p ## Pool Types -Choosing the type of pool to use is straightforward based on a few simple factors. The primary being the expected price variations between the tokens in the pool. For most non-stable assets a [Weighted Pool](/concepts/pools/weighted.md) is the right choice. For assets that are stable like stablecoins or assets that are stable against each other with a known price rate (ex: wstETH/weth), a [Composable Stable Pool](/concepts/pools/stable.md) allows for much deeper liquidity. +Choosing the type of pool to use is straightforward based on a few simple factors. The primary being the expected price variations between the tokens in the pool. For most non-stable assets a [Weighted Pool](/concepts/pools/weighted.md) is the right choice. For assets that are stable like stablecoins or assets that are stable against each other with a known price rate (ex: wstETH/weth), a [Composable Stable Pool](/concepts/pools/composable-stable.md) allows for much deeper liquidity. The Balancer Dapp has a [pool creation interface](https://app.balancer.fi/#/ethereum/pool/create) for weighted pools. For stable pool creation, reach out to our devs on [Discord](https://discord.balancer.fi/) for assistance. diff --git a/docs/guides/README.md b/docs/guides/README.md index 4022cef2..a00a4f2f 100644 --- a/docs/guides/README.md +++ b/docs/guides/README.md @@ -5,21 +5,14 @@ heroImage: /images/backgrounds/blue.png # Developer Guides ## Arbitrageurs -- [Get Spot Price of a Pool](/guides/arbitrageurs/get-spot-price.html) -- [Execute a batch swap](/guides/arbitrageurs/execute-a-batch-swap.md) -- [Deposit internal balances and swap for minimal gas]() -- [Create paths through bb-a-usd and other yield pools]() + +- [Get Spot Price of a Pool](/guides/arbitrageurs/get-spot-price.md) + ## Aggregators -- [Use the SOR to find the best swap path]() -- [Calculate swap outputs for yield pools]() -## Integrators -- [Format Data for Joins & Exits]() -- [Get the APR for a pool]() -- [Get pool and swaps data from the subgraph]() +- [Use the SOR to find the best swap path](/guides/aggregators/sor-basics.md) + ## Builders -- [Deploy a pool from a factory]() -- [Verify a pool on Etherscan]() -- [Build a protocol on top of Balancer]() -- [Join a pool from another smart contract]() \ No newline at end of file +- [Join a pool using the SDK](/guides/builders/join-pool.md) +- [Exit a pool using the SDK](/guides/builders/exit-pool.md) diff --git a/docs/guides/aggregators/boosted-pools.md b/docs/guides/aggregators/boosted-pools.md deleted file mode 100644 index b6de6049..00000000 --- a/docs/guides/aggregators/boosted-pools.md +++ /dev/null @@ -1 +0,0 @@ -# Route through Boosted Pools \ No newline at end of file diff --git a/docs/guides/arbitrageurs/execute-a-batch-swap.md b/docs/guides/arbitrageurs/execute-a-batch-swap.md deleted file mode 100644 index d4b2c8d9..00000000 --- a/docs/guides/arbitrageurs/execute-a-batch-swap.md +++ /dev/null @@ -1,7 +0,0 @@ -# Execute a Batch Swap - -## Overview - -::: info -This guide is for executing a batch swap -::: \ No newline at end of file diff --git a/docs/guides/arbitrageurs/get-spot-price.md b/docs/guides/arbitrageurs/get-spot-price.md index 7722716d..46a50c14 100644 --- a/docs/guides/arbitrageurs/get-spot-price.md +++ b/docs/guides/arbitrageurs/get-spot-price.md @@ -58,13 +58,3 @@ There are few different ways to go about getting the spot price. For example, if ### Weighted Pool Spot Price Using the SDK @[code{11-22} ts](code/sdk-spot-price.ts) - -### All Pools Spot Price Using the SDK - -### Boosted Pool Spot Price - -TODO - -### Spot Price of Complex Path - -TODO diff --git a/docs/guides/arbitrageurs/utilizing-internal-balances.md b/docs/guides/arbitrageurs/utilizing-internal-balances.md deleted file mode 100644 index 8c22e2be..00000000 --- a/docs/guides/arbitrageurs/utilizing-internal-balances.md +++ /dev/null @@ -1 +0,0 @@ -# Utilizing Internal Balances \ No newline at end of file diff --git a/docs/guides/builders/deploy-pool.md b/docs/guides/builders/deploy-pool.md deleted file mode 100644 index 295fd6ed..00000000 --- a/docs/guides/builders/deploy-pool.md +++ /dev/null @@ -1 +0,0 @@ -# Deploy a new pool \ No newline at end of file diff --git a/docs/sdk/liquidity-managment/exit-pool.md b/docs/guides/builders/exit-pool.md similarity index 83% rename from docs/sdk/liquidity-managment/exit-pool.md rename to docs/guides/builders/exit-pool.md index f9b633b2..b36ec5c0 100644 --- a/docs/sdk/liquidity-managment/exit-pool.md +++ b/docs/guides/builders/exit-pool.md @@ -2,6 +2,7 @@ title: Exiting a pool order: 2 --- + # How to exit a pool using Balancer SDK? Balancer Pool Tokens (BPT) grant you access to a share of the pool's underlying tokens. There are three ways you can redeem them: @@ -17,18 +18,19 @@ Balancer Pool Tokens (BPT) grant you access to a share of the pool's underlying Set up the SDK and get the pool with liquidity service methods as `pool` ([methods interface](https://github.com/balancer-labs/balancer-sdk/blob/master/balancer-js/src/types.ts/#L321)) ```javascript -import { BalancerSDK } from '@balancer-labs/sdk' +import { BalancerSDK } from '@balancer-labs/sdk'; const balancer = new BalancerSDK({ network: 1, // mainnet - rpcUrl: 'https://rpc.ankr.com/eth' + rpcUrl: 'https://rpc.ankr.com/eth', }); // stETH pool -const poolId = '0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080' +const poolId = + '0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080'; // Get the SDK pool with service methods -const pool = await balancer.pools.find(poolId) +const pool = await balancer.pools.find(poolId); ``` ### Single token exit @@ -39,13 +41,13 @@ Receive an equal portion of all the underlying. Use `buildExitExactBPTIn` method /** * Builds an exit calldata and returns params ready for * ethers sendTransaction call. - * + * * @param address user address exiting the pool * @param bptIn amount of BPT redeemed * @param slippage acceptable slippage in bsp, eg. 100 = 1% * @param unwrap optional, unwraps wrapped native tokens upon exit * @param token optional, address of a single token to exit to - * + * * @returns Object with ethers sendTransaction params * { * to: string @@ -91,47 +93,49 @@ const { to, data } = pool.buildExitExactTokensOut( Finally broadcast transaction using your signer. ```javascript -const signer = balancer.provider.getSigner() - -const exitReciept = await ( - await signer.sendTransaction({ to, data }) -).wait() +const signer = balancer.provider.getSigner(); +const exitReciept = await (await signer.sendTransaction({ to, data })).wait(); ``` ## Boosted pools -Exit boosted pools by swapping BPT for the underlying asset. As an example, when exiting the Stargate pool composed of STG and bbaUSD, you can exit to STG or bbaUSD BPT, but you can as well exit to DAI, USDC, or USDT as they are all part of the bbaUSD pool. +Exit boosted pools by swapping BPT for the underlying asset. As an example, when exiting the Stargate pool composed of STG and bbaUSD, you can exit to STG or bbaUSD BPT, but you can as well exit to DAI, USDC, or USDT as they are all part of the bbaUSD pool. To do that in one transaction we can use the balancer relayer contract where it's possible to use outputs from one action as inputs in the other action. For example to exit to DAI, first exit the weighted pool to bbaUSD and then swap to bbaDAI, and finally to DAI. -![](./2023-02-03-14-16-20.png) +![](/images/exit-swap-diagram.png) Balancer Vault actions accept two types of amounts: wad strings and chained references. Chained references allow a specific output of an action to be labeled so it can be used later as an input. This enables multiple actions to be linked together without knowing the intermediate token amounts. For example, the exit amount from an STG pool can be used as an input for a swap in the bbaUSD pool. To create a chained reference, use `Relayer.toChainReference` with any string as long as it's unique in a single call. ### Example script ```javascript -import { Relayer, WeightedPoolEncoder } from '@balancer-labs/sdk' +import { Relayer, WeightedPoolEncoder } from '@balancer-labs/sdk'; // Stargate bbaUSD BPT address -const stgBptAddress = '0x4ce0bd7debf13434d3ae127430e9bd4291bfb61f' +const stgBptAddress = '0x4ce0bd7debf13434d3ae127430e9bd4291bfb61f'; // Fetch BPT amount -const amount = await balancer.contracts.ERC20(stgBptAddress, signer).balanceOf(address).then(b => b.toString()) +const amount = await balancer.contracts + .ERC20(stgBptAddress, signer) + .balanceOf(address) + .then(b => b.toString()); // Setup relayer -const relayer = balancer.contracts.relayerV4.address +const relayer = balancer.contracts.relayerV4.address; // Authorise relayer to spend your vault balance // needs to be done only once -await balancer.contracts.vault.connect(signer).setRelayerApproval(address, relayer, true) +await balancer.contracts.vault + .connect(signer) + .setRelayerApproval(address, relayer, true); // Define chained reference for using the exit amount as an input in a swap -const EXIT_BBAUSD = Relayer.toChainedReference('1') +const EXIT_BBAUSD = Relayer.toChainedReference('1'); // Encode the exit action by specify type of the exit and the amount // exitExactBPTInForOneTokenOut(amountIn, indexOf a tokenOut) -const userData = WeightedPoolEncoder.exitExactBPTInForOneTokenOut(amount, 0) +const userData = WeightedPoolEncoder.exitExactBPTInForOneTokenOut(amount, 0); // Build exit const exit = Relayer.encodeExitPool({ @@ -146,7 +150,7 @@ const exit = Relayer.encodeExitPool({ toInternalBalance: true, }, outputReferences: [{ index: 0, key: EXIT_BBAUSD }], -}) +}); // Build swap const swap = Relayer.encodeBatchSwap({ @@ -154,24 +158,20 @@ const swap = Relayer.encodeBatchSwap({ swaps: [ { poolId: bbaUSD, - assetInIndex: 0, // bbaUSD + assetInIndex: 0, // bbaUSD assetOutIndex: 1, // bbaDAI amount: EXIT_BBAUSD, userData: '0x', }, { poolId: bbaDai, - assetInIndex: 1, // bbaDAI + assetInIndex: 1, // bbaDAI assetOutIndex: 2, // DAI - amount: '0', // 0 amount means the vault batchswap will use the previous step's output + amount: '0', // 0 amount means the vault batchswap will use the previous step's output userData: '0x', - } - ], - assets: [ - usdAdd, - daiAdd, - dai, + }, ], + assets: [usdAdd, daiAdd, dai], funds: { fromInternalBalance: true, recipient: address, @@ -181,19 +181,22 @@ const swap = Relayer.encodeBatchSwap({ limits: [MaxInt256, '0', '0'], // +amount for max to send, -amount for min to receive deadline: `${Math.ceil(Date.now() / 1000) + 3600}`, // 1 hour from now value: '0', - outputReferences: [] + outputReferences: [], }); // Query to make sure multicall is passing -const staticCall = await balancer.contracts.relayerV4.connect(signer).callStatic.multicall([exit, swap]); +const staticCall = await balancer.contracts.relayerV4 + .connect(signer) + .callStatic.multicall([exit, swap]); -const data = balancer.contracts.relayerV4.interface.encodeFunctionData('multicall', [ - [exit, swap] -]); +const data = balancer.contracts.relayerV4.interface.encodeFunctionData( + 'multicall', + [[exit, swap]] +); -const tx = await (await signer.sendTransaction({ to: relayer, data })).wait() +const tx = await (await signer.sendTransaction({ to: relayer, data })).wait(); ``` ### How to check limits? -TODO: Query to check how many tokens will be returned by the vault and set limits before sending transaction. \ No newline at end of file +TODO: Query to check how many tokens will be returned by the vault and set limits before sending transaction. diff --git a/docs/guides/builders/join-pool.md b/docs/guides/builders/join-pool.md index 1a57b1aa..742bd574 100644 --- a/docs/guides/builders/join-pool.md +++ b/docs/guides/builders/join-pool.md @@ -1 +1,192 @@ -# Join a pool \ No newline at end of file +--- +title: Joining a pool +order: 1 +--- + +# How to join a pool using Balancer SDK? + +Under the hood joining a pool is about depositing your ERC20 tokens to the Vault where they are used as liquidity. In exchange for providing liquidity you will receive another ERC20 tokens representing a share in the pool. We call them balancer pool tokens, or BPTs in short. When you want to exit the pool you need to send BPT to the vault and in return you will receive pool tokens. + +### Types of Pools in Balancer + +Balancer offers various pool types, with two main joining methods: + +- [Direct joins](#direct-joins) +- [Joining via swaps](#joining-via-swaps) + +Pools, which contain nested pools, can only be joined through swaps. This guide will first cover direct join pools, then provide an example of joining a pool using a swap. + +**Joining comes down to three steps:** + +1. [Approving ERC20 tokens](#erc20-approvals) so the vault can use them on your behalf (needs to be done at least once for each token) +2. [Building a join transaction](#building-a-join-transaction) and estimating how many BPTs you will receive to protect yourself from getting rekt. +3. [Send a join transaction](#send-join-transaction-with-the-joinpool-call) + +Let’s start with the project setup. Here is a complete example you can play with in replit: + + + +In this example we are going to join wETH/wstETH stable pool on mainnet. SDK supports Polygon, Arbitrum and Goerli as well. + +```javascript +import { BalancerSDK } from '@balancer-labs/sdk'; + +const balancer = new BalancerSDK({ + network: 1, // mainnet + rpcUrl: 'https://rpc.ankr.com/eth', +}); + +const signer = balancer.provider.getSigner(); + +const poolId = + '0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080'; +const pool = balancer.pools.find(poolId); +``` + +## Prerequirements + +ERC20 approvals - Balancer vault needs to be approved to use deposited tokens as liquidity. + +## Direct joins + +### Building a join transaction + +`pool.buildJoin` handles building transaction payload which can be send to the provider. It takes following parameters: + +```typescript +function buildJoin( + address: string, // address of the account joining the pool + tokens: string[], // token addresses joining the pool + amounts: string[], // amounts in uint as string + slippage: string // in basis points +) => { + to: string, // address of the vault + data: string, // encoded transaction payload + attributes: JoinPool, // decoded transaction attrs + minBPTOut: string // BPT out including slippage +} +``` + +#### Setting slippage + +Setting `slippage`, also called "limits", is a way to protect yourself from potential losses when joining a pool. It means setting a minimum BPTs that you expect to receive when you join the pool. The vault will abort in case return amount is below it. + +#### Proportional join + +While pool can be joined with any arbitrary amount, it is recommended to join with all the pool's tokens in exact proportions in order to minimize the price impact of the join. + +> This method is particularly useful for providing relatively high liquidity compared to the current pool's liquidity. It helps to minimize the slippage, which occurs when join is changing individual token balances and at the same time their prices. + +Use current pool token balances and from your wallet pick a token to calculate optimal complementary token amounts for. + +```javascript +// Out of the tokens in the pool, you pick one and set an amount. +// The helper will calculate the proportional amounts for the remaining tokens in the pool. +const { tokens, amounts } = pool.calcProportionalAmounts(token, amount); +``` + +It's important to note that the token amounts in the pool may change over time as the pool's liquidity change. + +The following snippet shows how to check the expected returned BPT price impact before depositing tokens to the Vault. + +```javascript +const priceImpact = await pool.calcPriceImpact( + amounts, + minBPTOut, + true // isJoin +); + +const impactPercentage = formatEther(priceImpact.mul(100)); +``` + +### Send join transaction with the `joinPool` call + +Building function returns to and data parameters which are all what's needed to send a transaction. Time between calling buildJoin and sending transaction should be minimal to avoid issues with outdated limits. + +```javascript +const joinReceipt = await (await signer.sendTransaction({ to, data })).wait(); +``` + +joinReceipt will contain the logs confirming all the state changes in the vault. + +## Joining via swaps + +Balancer relayer contract allows to combine swaps and joins in a single transaction. This method is particulary useful for joining a pool containing a boosted pool, for example bbaUSD, because it makes possible to join with any bbaUSD's underlying asset. + +As an example let's join the Stargate pool with DAI. First step is to swap DAI to bbaDAI to bbaUSD pool token, and then join using the output of that swap. + +![](/images/join-swap-diagram.png) + +Balancer Vault actions accept two types of amounts: wad strings and chained references. Chained references allow a specific output of an action to be labeled so it can be used later as an input. This enables multiple actions to be linked together without knowing the intermediate token amounts. For example, the swap output with a bbaUSD amount can be used as an input for a join pool. To create a chained reference, use `Relayer.toChainReference` with any string as long as it's unique in a single call. + +```javascript +import { Relayer, WeightedPoolEncoder } from '@balancer-labs/sdk'; + +const SWAP_RESULT_BBAUSD = Relayer.toChainedReference('1'); + +const swap = Relayer.encodeBatchSwap({ + swapType: 0, // exact amount in + swaps: [ + { + poolId: bbaDai, + assetInIndex: 0, // DAI + assetOutIndex: 1, // bbaDAI + amount, + userData: '0x', + }, + { + poolId: bbaUSD, + assetInIndex: 1, // bbaDAI + assetOutIndex: 2, // bbaUSD + amount: '0', // 0 amount means the vault batchswap will use the previous step's output + userData: '0x', + }, + ], + assets: [dai, bbaDAI, bbaUSD], + funds: { + fromInternalBalance: false, + recipient: address, + sender: address, + toInternalBalance: true, + }, + limits: [MaxInt256, '0', '0'], // +ve for max to send, -ve for min to receive + deadline: `${Math.ceil(Date.now() / 1000) + 3600}`, // 1 hour from now + value: '0', + outputReferences: [{ index: 2, key: SWAP_RESULT_BBAUSD }], +}); + +// Encode the join action by specify type of the join and the amount as a chained reference from a swap +// exitExactBPTInForOneTokenOut(amountIn, indexOf a tokenOut) +const userData = WeightedPoolEncoder.joinExactTokensInForBPTOut( + [SWAP_RESULT_BBAUSD, '0'], + '0' +); + +const join = Relayer.encodeJoinPool({ + poolId, + kind: 0, + sender: address, + recipient: address, + joinPoolRequest: { + assets: [usdAdd, stg], + maxAmountsIn: [MaxInt256, MaxInt256], // TODO: show how limits can be set + userData, + fromInternalBalance: true, + }, + value: '0', + outputReference: '0', +}); + +const data = balancer.contracts.relayerV4.interface.encodeFunctionData( + 'multicall', + [[swap, join]] +); + +const tx = await (await signer.sendTransaction({ to: relayer, data })).wait(); +``` + +## Notable features + +### Using native assets + +Balancer allows for the use of native assets, such as ETH, as inputs for joining and exiting pools. For example, you can join any pool containing wETH by depositing ETH and specifying "tokenIn" as `0x0000000000000000000000000000000000000000` diff --git a/docs/guides/builders/verify-pool.md b/docs/guides/builders/verify-pool.md deleted file mode 100644 index 47515211..00000000 --- a/docs/guides/builders/verify-pool.md +++ /dev/null @@ -1 +0,0 @@ -# Verify a pool on Etherscan \ No newline at end of file diff --git a/docs/guides/integrators/format-userdata.md b/docs/guides/integrators/format-userdata.md deleted file mode 100644 index b4cae2df..00000000 --- a/docs/guides/integrators/format-userdata.md +++ /dev/null @@ -1,25 +0,0 @@ -# Format Data for Joins/Exits - -::: tip -Adding or removing liquidity to a pool, commonly referred to as joins or exits, is done directly through the vault and not the indvidiual pool contracts. There are many different ways to go about joining/exiting due to the number of join/exit kinds and different types of pools. This guide will showcase several different options, so feel free to jump to the section that best matches your use case. -::: - -## Precursor - -Before diving into the guide, it's good to quickly review the entry point on the Vault to understand how all of the code in the guide boils down into this method. - -```solidity -function joinPool( - bytes32 poolId, - address sender, - address recipient, - JoinPoolRequest memory request -) external payable; - -struct JoinPoolRequest { - IAsset[] assets, - uint256[] maxAmountsIn, - bytes userData, - bool fromInternalBalance -} -``` \ No newline at end of file diff --git a/docs/reference/contracts/apis/vault.md b/docs/reference/contracts/apis/vault.md index 208cffa5..eb0a6634 100644 --- a/docs/reference/contracts/apis/vault.md +++ b/docs/reference/contracts/apis/vault.md @@ -221,10 +221,6 @@ Implemented in `Swaps`. ## Batch Swaps -::: info -For a more in-depth explanation check out the [Batch Swaps](../../../guides/arbitrageurs/execute-a-batch-swap.md) page in Guides. -::: - Batch swap "steps" specify the assets involved, "many-to-many" sources and destinations, and min/max token limits to guard against slippage. There is also an optional deadline, after which the swap will timeout and revert. These return the token "deltas" - the net result of executing each swap sequentially. ### **`batchSwap`** diff --git a/docs/sdk/liquidity-managment/.order b/docs/sdk/liquidity-managment/.order deleted file mode 100644 index e440e5c8..00000000 --- a/docs/sdk/liquidity-managment/.order +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/docs/sdk/liquidity-managment/join-pool.md b/docs/sdk/liquidity-managment/join-pool.md deleted file mode 100644 index 0a9953c4..00000000 --- a/docs/sdk/liquidity-managment/join-pool.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: Joining a pool -order: 1 ---- -# How to join a pool using Balancer SDK? - -Under the hood joining a pool is about depositing your ERC20 tokens to the Vault where they are used as liquidity. In exchange for providing liquidity you will receive another ERC20 tokens representing a share in the pool. We call them balancer pool tokens, or BPTs in short. When you want to exit the pool you need to send BPT to the vault and in return you will receive pool tokens. - -### Types of Pools in Balancer - -Balancer offers various pool types, with two main joining methods: - -* [Direct joins](#direct-joins) -* [Joining via swaps](#joining-via-swaps) - -Pools, which contain nested pools, can only be joined through swaps. This guide will first cover direct join pools, then provide an example of joining a pool using a swap. - -**Joining comes down to three steps:** - -1. [Approving ERC20 tokens](#erc20-approvals) so the vault can use them on your behalf (needs to be done at least once for each token) -2. [Building a join transaction](#building-a-join-transaction) and estimating how many BPTs you will receive to protect yourself from getting rekt. -3. [Send a join transaction](#send-join-transaction-with-the-joinpool-call) - -Let’s start with the project setup. Here is a complete example you can play with in replit: - - - -In this example we are going to join wETH/wstETH stable pool on mainnet. SDK supports Polygon, Arbitrum and Goerli as well. - -```javascript -import { BalancerSDK } from '@balancer-labs/sdk' - -const balancer = new BalancerSDK({ - network: 1, // mainnet - rpcUrl: 'https://rpc.ankr.com/eth' -}); - -const signer = balancer.provider.getSigner() - -const poolId = '0x32296969ef14eb0c6d29669c550d4a0449130230000200000000000000000080' -const pool = balancer.pools.find(poolId) -``` - -## Prerequirements - -ERC20 approvals - Balancer vault needs to be approved to use deposited tokens as liquidity. - -## Direct joins - -### Building a join transaction - -`pool.buildJoin` handles building transaction payload which can be send to the provider. It takes following parameters: -```typescript -function buildJoin( - address: string, // address of the account joining the pool - tokens: string[], // token addresses joining the pool - amounts: string[], // amounts in uint as string - slippage: string // in basis points -) => { - to: string, // address of the vault - data: string, // encoded transaction payload - attributes: JoinPool, // decoded transaction attrs - minBPTOut: string // BPT out including slippage -} -``` -#### Setting slippage - -Setting `slippage`, also called "limits", is a way to protect yourself from potential losses when joining a pool. It means setting a minimum BPTs that you expect to receive when you join the pool. The vault will abort in case return amount is below it. - -#### Proportional join - -While pool can be joined with any arbitrary amount, it is recommended to join with all the pool's tokens in exact proportions in order to minimize the price impact of the join. - ->This method is particularly useful for providing relatively high liquidity compared to the current pool's liquidity. It helps to minimize the slippage, which occurs when join is changing individual token balances and at the same time their prices. - -Use current pool token balances and from your wallet pick a token to calculate optimal complementary token amounts for. - -```javascript -// Out of the tokens in the pool, you pick one and set an amount. -// The helper will calculate the proportional amounts for the remaining tokens in the pool. -const { tokens, amounts } = pool.calcProportionalAmounts(token, amount) -``` -It's important to note that the token amounts in the pool may change over time as the pool's liquidity change. - -The following snippet shows how to check the expected returned BPT price impact before depositing tokens to the Vault. - -```javascript -const priceImpact = await pool.calcPriceImpact( - amounts, - minBPTOut, - true // isJoin -) - -const impactPercentage = formatEther( priceImpact.mul(100) ) -``` - -### Send join transaction with the `joinPool` call - -Building function returns to and data parameters which are all what's needed to send a transaction. Time between calling buildJoin and sending transaction should be minimal to avoid issues with outdated limits. - -```javascript -const joinReceipt = await ( - await signer.sendTransaction({ to, data }) -).wait() -``` - -joinReceipt will contain the logs confirming all the state changes in the vault. - -## Joining via swaps - -Balancer relayer contract allows to combine swaps and joins in a single transaction. This method is particulary useful for joining a pool containing a boosted pool, for example bbaUSD, because it makes possible to join with any bbaUSD's underlying asset. - -As an example let's join the Stargate pool with DAI. First step is to swap DAI to bbaDAI to bbaUSD pool token, and then join using the output of that swap. - -![](./2023-02-03-15-13-29.png) - -Balancer Vault actions accept two types of amounts: wad strings and chained references. Chained references allow a specific output of an action to be labeled so it can be used later as an input. This enables multiple actions to be linked together without knowing the intermediate token amounts. For example, the swap output with a bbaUSD amount can be used as an input for a join pool. To create a chained reference, use `Relayer.toChainReference` with any string as long as it's unique in a single call. - -```javascript -import { Relayer, WeightedPoolEncoder } from '@balancer-labs/sdk' - -const SWAP_RESULT_BBAUSD = Relayer.toChainedReference('1') - -const swap = Relayer.encodeBatchSwap({ - swapType: 0, // exact amount in - swaps: [ - { - poolId: bbaDai, - assetInIndex: 0, // DAI - assetOutIndex: 1, // bbaDAI - amount, - userData: '0x', - }, - { - poolId: bbaUSD, - assetInIndex: 1, // bbaDAI - assetOutIndex: 2, // bbaUSD - amount: '0', // 0 amount means the vault batchswap will use the previous step's output - userData: '0x', - }, - ], - assets: [ - dai, - bbaDAI, - bbaUSD, - ], - funds: { - fromInternalBalance: false, - recipient: address, - sender: address, - toInternalBalance: true, - }, - limits: [MaxInt256, '0', '0'], // +ve for max to send, -ve for min to receive - deadline: `${Math.ceil(Date.now() / 1000) + 3600}`, // 1 hour from now - value: '0', - outputReferences: [{ index: 2, key: SWAP_RESULT_BBAUSD }] -}); - -// Encode the join action by specify type of the join and the amount as a chained reference from a swap -// exitExactBPTInForOneTokenOut(amountIn, indexOf a tokenOut) -const userData = WeightedPoolEncoder.joinExactTokensInForBPTOut([SWAP_RESULT_BBAUSD, '0'], '0') - -const join = Relayer.encodeJoinPool({ - poolId, - kind: 0, - sender: address, - recipient: address, - joinPoolRequest: { - assets: [usdAdd, stg], - maxAmountsIn: [MaxInt256, MaxInt256], // TODO: show how limits can be set - userData, - fromInternalBalance: true, - }, - value: '0', - outputReference: '0', -}) - -const data = balancer.contracts.relayerV4.interface.encodeFunctionData('multicall', [ - [swap, join] -]); - -const tx = await (await signer.sendTransaction({ to: relayer, data })).wait() -``` - -## Notable features - -### Using native assets - -Balancer allows for the use of native assets, such as ETH, as inputs for joining and exiting pools. For example, you can join any pool containing wETH by depositing ETH and specifying "tokenIn" as `0x0000000000000000000000000000000000000000` diff --git a/docs/sdk/technical-reference/helpers.md b/docs/sdk/technical-reference/helpers.md index a1fae170..6d77d65f 100644 --- a/docs/sdk/technical-reference/helpers.md +++ b/docs/sdk/technical-reference/helpers.md @@ -3,6 +3,7 @@ ## Pool IDs ### splitPoolId + ```js /** * Splits a poolId into its components, i.e. pool address, pool specialization and its nonce @@ -12,9 +13,9 @@ export const splitPoolId = ( poolId: string ): { - address: string; - specialization: PoolSpecialization; - nonce: BigNumber; + address: string, + specialization: PoolSpecialization, + nonce: BigNumber, } => { return { address: getPoolAddress(poolId), @@ -25,6 +26,7 @@ export const splitPoolId = ( ``` ### getPoolAddress + ```js /** * Extracts a pool's address from its poolId @@ -38,6 +40,7 @@ export const getPoolAddress = (poolId: string): string => { ``` ### getPoolSpecialization + ```js /** * Extracts a pool's specialization from its poolId @@ -56,7 +59,8 @@ export const getPoolSpecialization = (poolId: string): PoolSpecialization => { ``` ### getPoolNonce -``` + +```js /** * Extracts a pool's nonce from its poolId * @param poolId - a bytes32 string of the pool's ID @@ -66,4 +70,4 @@ export const getPoolNonce = (poolId: string): BigNumber => { invariant(poolId.length === 66, 'Invalid poolId length'); return BigNumber.from(`0x${poolId.slice(46)}`); }; -``` \ No newline at end of file +``` diff --git a/docs/sdk/technical-reference/relayer.md b/docs/sdk/technical-reference/relayer.md index 85c81178..08fd4cd2 100644 --- a/docs/sdk/technical-reference/relayer.md +++ b/docs/sdk/technical-reference/relayer.md @@ -9,7 +9,7 @@ const relayer = new relayerService( ); ``` -### #swapUnwrapAaveStaticExactIn +### `swapUnwrapAaveStaticExactIn` Finds swaps for tokenIn>wrapped Aave static tokens and chains with unwrap to underlying stable. ExactIn - Exact amount of tokenIn to use in swap. @@ -37,9 +37,7 @@ async relayer.swapUnwrapAaveStaticExactIn( ): Promise ``` -[Example](./examples/relayerSwapUnwrap.ts) - -### #swapUnwrapAaveStaticExactOut +### `swapUnwrapAaveStaticExactOut` Finds swaps for tokenIn>wrapped Aave static tokens and chains with unwrap to underlying stable. ExactOut - Exact amount of tokens out are used for swaps. @@ -67,9 +65,7 @@ async relayer.swapUnwrapAaveStaticExactOut( ): Promise ``` -[Example](./examples/relayerSwapUnwrap.ts) - -### #exitPoolAndBatchSwap +### `exitPoolAndBatchSwap` Chains poolExit with batchSwap to final tokens. @@ -99,4 +95,4 @@ async relayer.exitPoolAndBatchSwap( fetchPools: FetchPoolsInput; } ): Promise -``` \ No newline at end of file +``` diff --git a/theme/src/client/layouts/NotFound.vue b/theme/src/client/layouts/NotFound.vue index fcb1c4b1..d0f8b269 100644 --- a/theme/src/client/layouts/NotFound.vue +++ b/theme/src/client/layouts/NotFound.vue @@ -19,7 +19,7 @@ const homeText = themeLocale.value.backToHome ?? 'Back to home';
-

404 test

+

404

{{ getMsg() }}