From dc14cd62cde0ad53e9395c528695dbe8732d2cb8 Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Fri, 22 Nov 2024 15:42:34 -0300 Subject: [PATCH 01/10] Add approveOnPermit2 flag to forkSetup helper input --- test/lib/utils/helper.ts | 81 ++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/test/lib/utils/helper.ts b/test/lib/utils/helper.ts index 8b005627..ca52c1ab 100644 --- a/test/lib/utils/helper.ts +++ b/test/lib/utils/helper.ts @@ -77,6 +77,7 @@ export const approveToken = async ( accountAddress: Address, tokenAddress: Address, protocolVersion: 2 | 3, + approveOnPermit2 = true, amount?: bigint, deadline?: bigint, ): Promise => { @@ -101,38 +102,42 @@ export const approveToken = async ( PERMIT2[chainId], amount, ); - // Approve Router to spend account tokens using Permit2 - const routerApprovedOnPermit2 = await approveSpenderOnPermit2( - client, - accountAddress, - tokenAddress, - BALANCER_ROUTER[chainId], - amount, - deadline, - ); - // Approve BatchRouter to spend account tokens using Permit2 - const batchRouterApprovedOnPermit2 = await approveSpenderOnPermit2( - client, - accountAddress, - tokenAddress, - BALANCER_BATCH_ROUTER[chainId], - amount, - deadline, - ); - // Approve CompositeRouter to spend account tokens using Permit2 - const compositeRouterApprovedOnPermit2 = await approveSpenderOnPermit2( - client, - accountAddress, - tokenAddress, - BALANCER_COMPOSITE_LIQUIDITY_ROUTER[chainId], - amount, - deadline, - ); - approved = - permit2ApprovedOnToken && - routerApprovedOnPermit2 && - batchRouterApprovedOnPermit2 && - compositeRouterApprovedOnPermit2; + approved = permit2ApprovedOnToken; + if (approveOnPermit2) { + // Approve Router to spend account tokens using Permit2 + const routerApprovedOnPermit2 = await approveSpenderOnPermit2( + client, + accountAddress, + tokenAddress, + BALANCER_ROUTER[chainId], + amount, + deadline, + ); + // Approve BatchRouter to spend account tokens using Permit2 + const batchRouterApprovedOnPermit2 = await approveSpenderOnPermit2( + client, + accountAddress, + tokenAddress, + BALANCER_BATCH_ROUTER[chainId], + amount, + deadline, + ); + // Approve CompositeRouter to spend account tokens using Permit2 + const compositeRouterApprovedOnPermit2 = + await approveSpenderOnPermit2( + client, + accountAddress, + tokenAddress, + BALANCER_COMPOSITE_LIQUIDITY_ROUTER[chainId], + amount, + deadline, + ); + approved = + approved && + routerApprovedOnPermit2 && + batchRouterApprovedOnPermit2 && + compositeRouterApprovedOnPermit2; + } } return approved; }; @@ -142,6 +147,7 @@ export const approveTokens = async ( accountAddress: Address, tokens: Address[], protocolVersion: 2 | 3, + approveOnPermit2 = true, ): Promise => { const approvals: boolean[] = []; for (let i = 0; i < tokens.length; i++) { @@ -150,6 +156,7 @@ export const approveTokens = async ( accountAddress, tokens[i], protocolVersion, + approveOnPermit2, ); approvals.push(approved); } @@ -521,6 +528,7 @@ export async function findTokenBalanceSlot( * @param balances Balances in EVM amounts * @param isVyperMapping Whether the storage uses Vyper or Solidity mapping * @param protocolVersion Balancer vault version + * @param approveOnPermit2 Whether to approve spender on Permit2 */ export const forkSetup = async ( client: PublicWalletClient & TestActions, @@ -530,6 +538,7 @@ export const forkSetup = async ( balances: bigint[], isVyperMapping: boolean[] = Array(tokens.length).fill(false), protocolVersion: 2 | 3 = 2, + approveOnPermit2 = true, ): Promise => { await client.impersonateAccount({ address: accountAddress }); @@ -550,7 +559,13 @@ export const forkSetup = async ( isVyperMapping, ); - await approveTokens(client, accountAddress, tokens, protocolVersion); + await approveTokens( + client, + accountAddress, + tokens, + protocolVersion, + approveOnPermit2, + ); }; /** From 4eacd702a093046b6718194b819338d98dc595ce Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Fri, 22 Nov 2024 15:43:14 -0300 Subject: [PATCH 02/10] Fix add liquidity unbalanced example to match testnet deployment 10 --- examples/addLiquidity/addLiquidityUnbalanced.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/addLiquidity/addLiquidityUnbalanced.ts b/examples/addLiquidity/addLiquidityUnbalanced.ts index b4ebb5d6..a28b3d29 100644 --- a/examples/addLiquidity/addLiquidityUnbalanced.ts +++ b/examples/addLiquidity/addLiquidityUnbalanced.ts @@ -25,10 +25,10 @@ async function runAgainstFork() { const { rpcUrl } = await startFork(ANVIL_NETWORKS.SEPOLIA); const chainId = ChainId.SEPOLIA; const userAccount = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; - // 80BAL-20WETH + // 50BAL-50WETH const pool = { - id: '0x03Bf996C7BD45B3386cb41875761d45e27EaB284', - address: '0x03Bf996C7BD45B3386cb41875761d45e27EaB284' as Address, + id: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6', + address: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6' as Address, }; const amountsIn = [ { From f1e4dfb459f79939963f6df986adf4603b993331 Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Fri, 22 Nov 2024 15:43:55 -0300 Subject: [PATCH 03/10] Add addLiquidityWithPermit2Signature example --- .../addLiquidityWithPermit2Signature.ts | 171 ++++++++++++++++++ examples/lib/makeForkTx.ts | 2 + 2 files changed, 173 insertions(+) create mode 100644 examples/addLiquidity/addLiquidityWithPermit2Signature.ts diff --git a/examples/addLiquidity/addLiquidityWithPermit2Signature.ts b/examples/addLiquidity/addLiquidityWithPermit2Signature.ts new file mode 100644 index 00000000..184c703c --- /dev/null +++ b/examples/addLiquidity/addLiquidityWithPermit2Signature.ts @@ -0,0 +1,171 @@ +/** + * Example showing how to add liquidity to a pool while approving amounts through Permit2 signature. + * (Runs against a local Anvil fork) + * + * Run with: + * pnpm example ./examples/addLiquidity/addLiquidityWithPermit2Signature.ts + */ +import { + Address, + createTestClient, + http, + parseEther, + publicActions, + walletActions, +} from 'viem'; +import { + AddLiquidityInput, + AddLiquidityKind, + AddLiquidity, + BalancerApi, + ChainId, + PriceImpact, + Slippage, + TEST_API_ENDPOINT, + CHAINS, + Permit2Helper, +} from '../../src'; +import { ANVIL_NETWORKS, startFork } from '../../test/anvil/anvil-global-setup'; +import { getSlot } from 'examples/lib/getSlot'; +import { makeForkTx } from 'examples/lib/makeForkTx'; + +async function runAgainstFork() { + // User defined inputs + const { rpcUrl } = await startFork(ANVIL_NETWORKS.SEPOLIA); + const chainId = ChainId.SEPOLIA; + // 50BAL-50WETH + const pool = { + id: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6', + address: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6' as Address, + }; + const amountsIn = [ + { + rawAmount: parseEther('0.0001'), + decimals: 18, + address: '0x7b79995e5f793a07bc00c21412e50ecae098e7f9' as Address, + }, + { + rawAmount: parseEther('0.0001'), + decimals: 18, + address: '0xb19382073c7a0addbb56ac6af1808fa49e377b75' as Address, + }, + ]; + const slippage = Slippage.fromPercentage('1'); // 1% + + const client = createTestClient({ + mode: 'anvil', + chain: CHAINS[chainId], + transport: http(rpcUrl), + }) + .extend(publicActions) + .extend(walletActions); + + const userAccount = (await client.getAddresses())[0]; + + // build add liquidity call with permit2 approvals + const call = await addLiquidityWithPermit2Signature({ + client, + userAccount, + rpcUrl, + chainId, + amountsIn, + poolId: pool.id, + slippage, + }); + + // Skip Permit2 approval during fork setup so we can test approvals through signatures + const approveOnPermit2 = false; + + // Make the tx against the local fork and print the result + await makeForkTx( + call, + { + rpcUrl, + chainId, + impersonateAccount: userAccount, + forkTokens: amountsIn.map((a) => ({ + address: a.address, + slot: getSlot(chainId, a.address), + rawBalance: a.rawAmount, + })), + }, + [...amountsIn.map((a) => a.address), pool.address], + call.protocolVersion, + approveOnPermit2, + ); +} + +const addLiquidityWithPermit2Signature = async ({ + client, + userAccount, + rpcUrl, + chainId, + poolId, + amountsIn, + slippage, +}) => { + // API is used to fetch relevant pool data + const balancerApi = new BalancerApi(TEST_API_ENDPOINT, chainId); + const poolState = await balancerApi.pools.fetchPoolState(poolId); + + // Construct the AddLiquidityInput, in this case an AddLiquidityUnbalanced + const addLiquidityInput: AddLiquidityInput = { + amountsIn, + chainId, + rpcUrl, + kind: AddLiquidityKind.Unbalanced, + }; + + // Calculate price impact to ensure it's acceptable + const priceImpact = await PriceImpact.addLiquidityUnbalanced( + addLiquidityInput, + poolState, + ); + console.log(`\nPrice Impact: ${priceImpact.percentage.toFixed(2)}%`); + + // Simulate addLiquidity to get the amount of BPT out + const addLiquidity = new AddLiquidity(); + const queryOutput = await addLiquidity.query(addLiquidityInput, poolState); + + console.log('\nAdd Liquidity Query Output:'); + console.log('Tokens In:'); + queryOutput.amountsIn.map((a) => + console.log(a.token.address, a.amount.toString()), + ); + console.log(`BPT Out: ${queryOutput.bptOut.amount.toString()}`); + + // Add liquidity build call input with slippage applied to BPT amount from query output + const addLiquidityBuildCallInput = { + ...queryOutput, + slippage, + chainId, + wethIsEth: false, + }; + + // Sign permit2 approvals + const permit2 = await Permit2Helper.signAddLiquidityApproval({ + ...addLiquidityBuildCallInput, + client, + owner: userAccount, + }); + + // Build call with permit2 approvals + const call = addLiquidity.buildCallWithPermit2( + addLiquidityBuildCallInput, + permit2, + ); + + console.log('\nWith slippage applied:'); + console.log('Max tokens in:'); + call.maxAmountsIn.forEach((a) => + console.log(a.token.address, a.amount.toString()), + ); + console.log(`Min BPT Out: ${call.minBptOut.amount.toString()}`); + + return { + ...call, + protocolVersion: queryOutput.protocolVersion, + }; +}; + +export default runAgainstFork; diff --git a/examples/lib/makeForkTx.ts b/examples/lib/makeForkTx.ts index f37c3bd3..8119f5b7 100644 --- a/examples/lib/makeForkTx.ts +++ b/examples/lib/makeForkTx.ts @@ -39,6 +39,7 @@ export async function makeForkTx( }, tokensForBalanceCheck: Address[], protocolVersion: 1 | 2 | 3, + approveOnPermit2 = true, ) { const client = createTestClient({ mode: 'anvil', @@ -66,6 +67,7 @@ export async function makeForkTx( forkConfig.forkTokens.map((t) => t.rawBalance), undefined, protocolVersion, + approveOnPermit2, ); } From 08ce679cd48b7948561b3cfa5f603f75378e439c Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Fri, 22 Nov 2024 16:09:57 -0300 Subject: [PATCH 04/10] Add Permit2 Helper section to readme --- README.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0fd46497..2fe4d9d7 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Builds the addLiquidity transaction using user defined slippage. ```typescript buildCall(input: AddLiquidityBuildCallInput): AddLiquidityBuildCallOutput -```` +``` **Parameters** @@ -117,6 +117,32 @@ AddLiquidityBuildCallOutput [AddLiquidityBuildCallOutput](./src/entities/addLiquidity/types.ts#L75) - Encoded call data for addLiquidity that user can submit. ___ +### buildCallWithPermit2 + +Builds the addLiquidity transaction and approves amounts through a Permit2 signature. + +```typescript +buildCallWithPermit2(input: AddLiquidityBuildCallInput, permit2: Permit2): AddLiquidityBuildCallOutput +``` + +**Parameters** + +| Name | Type | Description | +| ------------- | ------------- | ------------ | +| input | [AddLiquidityBuildCallInput](./src/entities/addLiquidity/types.ts#L63) | Parameters required to build the call including user defined slippage | +| permit2 | [Permit2](./src/entities/permit2Helper/index.ts#L35) | Permit2 signature | +*Note: refer to [Permit2Helper](#calculateproportionalamounts) for a Permit2 helper function* + +**Returns** + +```typescript +AddLiquidityBuildCallOutput +``` + +[AddLiquidityBuildCallOutput](./src/entities/addLiquidity/types.ts#L75) - Encoded call data for addLiquidity that user can submit. +___ + + ## RemoveLiquidity This class provides functionality to: @@ -661,9 +687,11 @@ Helper functions. Given pool balances (including BPT) and a reference token amount, it calculates all other amounts proportional to the reference amount. -### Example +**Example** -See the [price impact example](/examples/priceImpact/addLiquidity.ts). +See [calculateProportionalAmounts example](/examples/utils/calculateProportionalAmounts.ts). + +**Function** ```typescript calculateProportionalAmounts( @@ -700,4 +728,47 @@ calculateProportionalAmounts( ``` Amounts proportional to the reference amount. +___ + +### Permit2 Helper + +Facilitate Permit2 signature generation. Each operation (e.g. addLiquidity, removeLiquidity, swap, ...) has its own helper that leverages the same input type of the operation itself in order to simplify signature generation. + +**Example** + +See [addLiquidityWithPermit2Signature example](/examples/addLiquidity/addLiquidityWithPermit2Signature.ts). + +**Function** + +Helper function to create a Permit2 signature for an addLiquidity operation: + +```typescript +static async signAddLiquidityApproval( + input: AddLiquidityBaseBuildCallInput & { + client: PublicWalletClient; + owner: Address; + nonces?: number[]; + expirations?: number[]; + }, + ): Promise +``` + +**Parameters** + +| Name | Type | Description | +| ------------- | ------------- | ------------ | +| input | [AddLiquidityBaseBuildCallInput](./src/entities/addLiquidity/types.ts#L62) | Add Liquidity Input | +| client | [PublicWalletClient](./src/utils/types.ts#L3) | Viem's wallet client with public actions | +| owner | Address | User address | +| nonces (optional) | number[] | Nonces for each token | +| expirations (optional) | number[] | Expirations for each token | + +**Returns** + +```typescript +Promise; +``` + +[Permit2](./src/entities/permit2Helper/index.ts#L35) - Permit2 object with metadata and encoded signature + ___ \ No newline at end of file From 6fb2f47ba47de8b646c23db0694c7d08a75ab7b1 Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Fri, 22 Nov 2024 17:57:45 -0300 Subject: [PATCH 05/10] Update makeForkTx so it accepts client as input --- examples/lib/makeForkTx.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/examples/lib/makeForkTx.ts b/examples/lib/makeForkTx.ts index 8119f5b7..3d0ab586 100644 --- a/examples/lib/makeForkTx.ts +++ b/examples/lib/makeForkTx.ts @@ -5,9 +5,10 @@ import { walletActions, Address, Hex, + TestActions, } from 'viem'; -import { CHAINS } from '../../src'; +import { CHAINS, PublicWalletClient } from '../../src'; import { forkSetup, forkSetupCowAmm, @@ -36,18 +37,22 @@ export async function makeForkTx( chainId: number; impersonateAccount: Address; forkTokens: ForkToken[]; + client?: PublicWalletClient & TestActions; }, tokensForBalanceCheck: Address[], protocolVersion: 1 | 2 | 3, approveOnPermit2 = true, ) { - const client = createTestClient({ - mode: 'anvil', - chain: CHAINS[forkConfig.chainId], - transport: http(forkConfig.rpcUrl), - }) - .extend(publicActions) - .extend(walletActions); + const client = + forkConfig.client ?? + createTestClient({ + mode: 'anvil', + chain: CHAINS[forkConfig.chainId], + transport: http(forkConfig.rpcUrl), + account: forkConfig.impersonateAccount, + }) + .extend(publicActions) + .extend(walletActions); if (protocolVersion === 1) { await forkSetupCowAmm( From b1a769f29b06c3c7e7fd2d65f386cad1d1d8a047 Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Fri, 22 Nov 2024 17:58:49 -0300 Subject: [PATCH 06/10] Add removeLiquidityWithPermitSignature example --- .../addLiquidity/addLiquidityUnbalanced.ts | 4 +- .../addLiquidityWithPermit2Signature.ts | 3 +- .../removeLiquidityWithPermitSignature.ts | 232 ++++++++++++++++++ 3 files changed, 236 insertions(+), 3 deletions(-) create mode 100644 examples/removeLiquidity/removeLiquidityWithPermitSignature.ts diff --git a/examples/addLiquidity/addLiquidityUnbalanced.ts b/examples/addLiquidity/addLiquidityUnbalanced.ts index a28b3d29..8a04f575 100644 --- a/examples/addLiquidity/addLiquidityUnbalanced.ts +++ b/examples/addLiquidity/addLiquidityUnbalanced.ts @@ -44,7 +44,7 @@ async function runAgainstFork() { ]; const slippage = Slippage.fromPercentage('1'); // 1% - const call = await addLiquidity({ + const call = await addLiquidityExample({ rpcUrl, chainId, amountsIn, @@ -70,7 +70,7 @@ async function runAgainstFork() { ); } -const addLiquidity = async ({ +export const addLiquidityExample = async ({ rpcUrl, chainId, poolId, diff --git a/examples/addLiquidity/addLiquidityWithPermit2Signature.ts b/examples/addLiquidity/addLiquidityWithPermit2Signature.ts index 184c703c..7b2995e4 100644 --- a/examples/addLiquidity/addLiquidityWithPermit2Signature.ts +++ b/examples/addLiquidity/addLiquidityWithPermit2Signature.ts @@ -1,5 +1,5 @@ /** - * Example showing how to add liquidity to a pool while approving amounts through Permit2 signature. + * Example showing how to add liquidity to a pool while approving tokens through Permit2 signature. * (Runs against a local Anvil fork) * * Run with: @@ -88,6 +88,7 @@ async function runAgainstFork() { slot: getSlot(chainId, a.address), rawBalance: a.rawAmount, })), + client, }, [...amountsIn.map((a) => a.address), pool.address], call.protocolVersion, diff --git a/examples/removeLiquidity/removeLiquidityWithPermitSignature.ts b/examples/removeLiquidity/removeLiquidityWithPermitSignature.ts new file mode 100644 index 00000000..606bab67 --- /dev/null +++ b/examples/removeLiquidity/removeLiquidityWithPermitSignature.ts @@ -0,0 +1,232 @@ +/** + * Example showing how to remove liquidity from a pool while approving tokens through Permit signature.. + * (Runs against a local Anvil fork) + * + * Run with: + * pnpm example ./examples/removeLiquidity/removeLiquidityWithPermitSignature.ts + */ +import { + Address, + createTestClient, + http, + parseEther, + publicActions, + TestActions, + walletActions, +} from 'viem'; +import { + BalancerApi, + ChainId, + CHAINS, + InputAmount, + PermitHelper, + PoolState, + PriceImpact, + PublicWalletClient, + RemoveLiquidity, + RemoveLiquidityInput, + RemoveLiquidityKind, + Slippage, + TEST_API_ENDPOINT, +} from '../../src'; +import { ANVIL_NETWORKS, startFork } from '../../test/anvil/anvil-global-setup'; +import { makeForkTx } from '../lib/makeForkTx'; +import { addLiquidityExample } from 'examples/addLiquidity/addLiquidityUnbalanced'; +import { getSlot } from 'examples/lib/getSlot'; + +async function runAgainstFork() { + // User defined inputs + const chainId = ChainId.SEPOLIA; + const { rpcUrl } = await startFork(ANVIL_NETWORKS[ChainId[chainId]]); + + const client = createTestClient({ + mode: 'anvil', + chain: CHAINS[chainId], + transport: http(rpcUrl), + }) + .extend(publicActions) + .extend(walletActions); + + const userAccount = (await client.getAddresses())[0]; + + // 50BAL-50WETH + const pool = { + id: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6', + address: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6' as Address, + }; + + const slippage = Slippage.fromPercentage('1'); // 1% + + // prepare example by adding liquidity to the pool, so we can remove it + await prepExample(rpcUrl, chainId, pool, slippage, userAccount, client); + // TODO: suppress prepExample logs to avoid poluting the console with unnecessary content + + const bptIn: InputAmount = { + rawAmount: parseEther('0.0001'), + decimals: 18, + address: pool.address, + }; + const tokenOut = '0xb19382073c7a0addbb56ac6af1808fa49e377b75'; // BAL + + const call = await removeLiquidityWithPermitSignature({ + client, + rpcUrl, + chainId, + userAccount, + bptIn, + tokenOut, + poolId: pool.id, + slippage, + }); + + // Make the tx against the local fork and print the result + await makeForkTx( + call, + { + rpcUrl, + chainId, + impersonateAccount: userAccount, + forkTokens: [ + { + address: pool.address, + slot: 0, + rawBalance: parseEther('1'), + }, + ], + client, + }, + [ + '0x7b79995e5f793a07bc00c21412e50ecae098e7f9' as Address, + '0xb19382073c7a0addbb56ac6af1808fa49e377b75' as Address, + pool.address, + ], + call.protocolVersion, + ); +} + +const removeLiquidityWithPermitSignature = async ({ + client, + rpcUrl, + chainId, + userAccount, + poolId, + bptIn, + tokenOut, + slippage, +}) => { + // API is used to fetch relevant pool data + const balancerApi = new BalancerApi(TEST_API_ENDPOINT, chainId); + const poolState: PoolState = await balancerApi.pools.fetchPoolState(poolId); + + // Construct the RemoveLiquidityInput, in this case a RemoveLiquiditySingleTokenExactIn + const removeLiquidityInput: RemoveLiquidityInput = { + chainId, + rpcUrl, + bptIn, + tokenOut, + kind: RemoveLiquidityKind.SingleTokenExactIn, + }; + + // Calculate price impact to ensure it's acceptable + const priceImpact = await PriceImpact.removeLiquidity( + removeLiquidityInput, + poolState, + ); + console.log(`\nPrice Impact: ${priceImpact.percentage.toFixed(2)}%`); + + // Simulate removing liquidity to get the tokens out + const removeLiquidity = new RemoveLiquidity(); + const queryOutput = await removeLiquidity.query( + removeLiquidityInput, + poolState, + ); + + console.log('\nRemove Liquidity Query Output:'); + console.log(`BPT In: ${queryOutput.bptIn.amount.toString()}`); + console.table({ + tokensOut: queryOutput.amountsOut.map((a) => a.token.address), + amountsOut: queryOutput.amountsOut.map((a) => a.amount), + }); + + // Remove liquidity build call input with slippage applied to amountOut from query output + const removeLiquidityBuildCallInput = { + ...queryOutput, + slippage, + chainId, + }; + + // Sign permit approvals + const permit = await PermitHelper.signRemoveLiquidityApproval({ + ...removeLiquidityBuildCallInput, + client, + owner: userAccount, + }); + + // build call with permit approvals + const call = removeLiquidity.buildCallWithPermit( + removeLiquidityBuildCallInput, + permit, + ); + + console.log('\nWith slippage applied:'); + console.log(`Max BPT In: ${call.maxBptIn.amount}`); + console.table({ + tokensOut: call.minAmountsOut.map((a) => a.token.address), + minAmountsOut: call.minAmountsOut.map((a) => a.amount), + }); + + return { + ...call, + protocolVersion: queryOutput.protocolVersion, + }; +}; + +const prepExample = async ( + rpcUrl: string, + chainId: ChainId, + pool: { id: string; address: Address }, + slippage: Slippage, + userAccount: Address, + client: PublicWalletClient & TestActions, +) => { + const amountsIn = [ + { + rawAmount: parseEther('0.01'), + decimals: 18, + address: '0x7b79995e5f793a07bc00c21412e50ecae098e7f9' as Address, + }, + { + rawAmount: parseEther('0.01'), + decimals: 18, + address: '0xb19382073c7a0addbb56ac6af1808fa49e377b75' as Address, + }, + ]; + + const addLiquidityCall = await addLiquidityExample({ + rpcUrl, + chainId, + amountsIn, + poolId: pool.id, + slippage, + }); + + // Make the tx against the local fork and print the result + await makeForkTx( + addLiquidityCall, + { + rpcUrl, + chainId, + impersonateAccount: userAccount, + forkTokens: amountsIn.map((a) => ({ + address: a.address, + slot: getSlot(chainId, a.address), + rawBalance: a.rawAmount, + })), + client, + }, + [...amountsIn.map((a) => a.address), pool.address], + addLiquidityCall.protocolVersion, + ); +}; + +export default runAgainstFork; From d0b4b8248ef851c6a300dbc1014ecd2842043824 Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Fri, 22 Nov 2024 17:59:09 -0300 Subject: [PATCH 07/10] Add Permit Helper section to readme --- README.md | 63 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2fe4d9d7..792f78d0 100644 --- a/README.md +++ b/README.md @@ -732,7 +732,9 @@ ___ ### Permit2 Helper -Facilitate Permit2 signature generation. Each operation (e.g. addLiquidity, removeLiquidity, swap, ...) has its own helper that leverages the same input type of the operation itself in order to simplify signature generation. +Balancer v3 handles token approval through Pemit2 and this helper facilitates Permit2 signature generation. + +Each operation (e.g. addLiquidity, swap, ...) has its own method that leverages the same input type of the operation itself in order to simplify signature generation. **Example** @@ -744,13 +746,13 @@ Helper function to create a Permit2 signature for an addLiquidity operation: ```typescript static async signAddLiquidityApproval( - input: AddLiquidityBaseBuildCallInput & { - client: PublicWalletClient; - owner: Address; - nonces?: number[]; - expirations?: number[]; - }, - ): Promise + input: AddLiquidityBaseBuildCallInput & { + client: PublicWalletClient; + owner: Address; + nonces?: number[]; + expirations?: number[]; + }, +): Promise ``` **Parameters** @@ -771,4 +773,49 @@ Promise; [Permit2](./src/entities/permit2Helper/index.ts#L35) - Permit2 object with metadata and encoded signature +___ + +### Permit Helper + +Balancer v3 conforms with EIP-2612 and this helper facilitates Permit signature generation. + +Each operation (e.g. removeLiquidity, removeLiquidityNested and removeLiquidityBoosted) has its own method that leverages the same input type of the operation itself in order to simplify signature generation. + +**Example** + +See [removeLiquidityWithPermitSignature example](/examples/removeLiquidity/removeLiquidityWithPermitSignature.ts). + +**Function** + +Helper function to create a Permit signature for a removeLiquidity operation: + +```typescript +static signRemoveLiquidityApproval = async ( + input: RemoveLiquidityBaseBuildCallInput & { + client: PublicWalletClient; + owner: Hex; + nonce?: bigint; + deadline?: bigint; + }, +): Promise +``` + +**Parameters** + +| Name | Type | Description | +| ------------- | ------------- | ------------ | +| input | [RemoveLiquidityBaseBuildCallInput](./src/entities/removeLiquidity/types.ts#L81) | Remove Liquidity Input | +| client | [PublicWalletClient](./src/utils/types.ts#L3) | Viem's wallet client with public actions | +| owner | Address | User address | +| nonces (optional) | number[] | Nonces for each token | +| expirations (optional) | number[] | Expirations for each token | + +**Returns** + +```typescript +Promise; +``` + +[Permit](./src/entities/permitHelper/index.ts#L30) - Permit object with metadata and encoded signature + ___ \ No newline at end of file From 2d57d243b1b3ed69dfe3c2954c7281ceb26db59e Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Wed, 27 Nov 2024 12:01:23 -0300 Subject: [PATCH 08/10] Remove duplicated readme in favor of consolidating API reference on docs-v3 --- README.md | 791 +----------------------------------------------------- 1 file changed, 6 insertions(+), 785 deletions(-) diff --git a/README.md b/README.md index 792f78d0..b05c3885 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # SDK +[![npm version](https://img.shields.io/npm/v/@balancer/sdk/latest.svg)](https://www.npmjs.com/package/@balancer/sdk/v/latest) + WIP SDK for Balancer Protocol. Interfaces may have frequent breaking changes until a stable release. ## Local Setup @@ -16,7 +18,7 @@ If your platform does not support one of the required features, it is also possi - `fetch` -> [node-fetch](https://github.com/node-fetch/node-fetch#providing-global-access) -### Testing +## Testing `pnpm test` @@ -27,7 +29,7 @@ POLYGON_RPC_URL FANTOM_RPC_URL SEPOLIA_RPC_URL ``` -**Anvil Client** +### Anvil Client To download and install the anvil client, run the following commands (MacOS): - `curl -L https://foundry.paradigm.xyz | bash` @@ -35,787 +37,6 @@ To download and install the anvil client, run the following commands (MacOS): - `source /Users/$(whoami)/.zshenv` - `foundryup` -# Documentation - -## Installation - -The [Balancer SDK](https://www.npmjs.com/package/@balancer-labs/sdk) is a Typescript/Javascript library for interfacing with the Balancer protocol and can be installed with: - -```bash -pnpm add @balancer-labs/sdk -``` - -# API - -## AddLiquidity - -This class provides functionality to: -* Perform on-chain queries to see the result of an addLiqudity operation -* Build an addLiquidity transaction, with slippage, for a consumer to submit -* Supported add types: SingleToken, Unbalanced, Proportional -* Supports Balancer V2 & V3 - -### Example - -See the [addLiqudity example](/examples/addLiquidity/addLiquidity.ts). - -### Constructor - -```typescript -const addLiquidity = new AddLiquidity(); -``` - -### Methods - -### query - -Simulate addLiquidity operation by using an onchain call. - -```typescript -query( - input: AddLiquidityInput, - poolState: PoolState -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [AddLiquidityInput](./src/entities/addLiquidity/types.ts#L38) | User defined inputs | -| poolState | [PoolState](./src/entities/types.ts#L5) | Current state of pool that liqudity is being added to | - -**Returns** - -```typescript -Promise -``` - -[AddLiquidityQueryOutput](./src/entities/addLiquidity/types.ts#L54) - Data that can be passed to `buildCall`. Includes updated `bptOut` amount. -___ - -### buildCall - -Builds the addLiquidity transaction using user defined slippage. - -```typescript -buildCall(input: AddLiquidityBuildCallInput): AddLiquidityBuildCallOutput -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [AddLiquidityBuildCallInput](./src/entities/addLiquidity/types.ts#L63) | Parameters required to build the call including user defined slippage | - -**Returns** - -```typescript -AddLiquidityBuildCallOutput -``` - -[AddLiquidityBuildCallOutput](./src/entities/addLiquidity/types.ts#L75) - Encoded call data for addLiquidity that user can submit. -___ - -### buildCallWithPermit2 - -Builds the addLiquidity transaction and approves amounts through a Permit2 signature. - -```typescript -buildCallWithPermit2(input: AddLiquidityBuildCallInput, permit2: Permit2): AddLiquidityBuildCallOutput -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [AddLiquidityBuildCallInput](./src/entities/addLiquidity/types.ts#L63) | Parameters required to build the call including user defined slippage | -| permit2 | [Permit2](./src/entities/permit2Helper/index.ts#L35) | Permit2 signature | -*Note: refer to [Permit2Helper](#calculateproportionalamounts) for a Permit2 helper function* - -**Returns** - -```typescript -AddLiquidityBuildCallOutput -``` - -[AddLiquidityBuildCallOutput](./src/entities/addLiquidity/types.ts#L75) - Encoded call data for addLiquidity that user can submit. -___ - - -## RemoveLiquidity - -This class provides functionality to: -* Perform on-chain queries to see the result of an removeLiqudity operation -* Build a removeLiquidity transaction, with slippage, for a consumer to submit -* Supported remove types: Unbalanced, SingleTokenExactOutInput, SingleTokenExactInInput, Proportional -* Supports Balancer V2 & V3 - -### Example - -See the [removeLiqudity example](/examples/removeLiquidity/removeLiquidity.ts). - -### Constructor - -```typescript -const removeLiquidity = new RemoveLiquidity(); -``` - -### Methods - -### query - -Simulate removeLiquidity operation by using an onchain call. - -```typescript -query( - input: RemoveLiquidityInput, - poolState: PoolState, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [RemoveLiquidityInput](./src/entities/removeLiquidity/types.ts#L52) | User defined inputs | -| poolState | [PoolState](./src/entities/types.ts#L5) | Current state of pool that liqudity is being removed from | - -**Returns** - -```typescript -Promise -``` - -[RemoveLiquidityQueryOutput](./src/entities/removeLiquidity/types.ts#L70) - Data that can be passed to `buildCall`. Includes updated `amountsOut` amount. -___ - -### queryRemoveLiquidityRecovery - -Calculates proportional exit using pool state. Note - this does not do an onchain query. - -```typescript -queryRemoveLiquidityRecovery( - input: RemoveLiquidityRecoveryInput, - poolState: PoolState, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [RemoveLiquidityRecoveryInput](./src/entities/removeLiquidity/types.ts#L47) | User defined inputs | -| poolState | [PoolState](./src/entities/types.ts#L5) | Current state of pool that liqudity is being removed from | - -**Returns** - -```typescript -Promise -``` - -[RemoveLiquidityQueryOutput](./src/entities/removeLiquidity/types.ts#L70) - Data that can be passed to `buildCall`. Includes updated `amountsOut` amount. -___ - -### buildCall - -Builds the removeLiquidity transaction using user defined slippage. - -```typescript -buildCall( - input: RemoveLiquidityBuildCallInput, -): RemoveLiquidityBuildCallOutput -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [RemoveLiquidityBuildCallInput](./src/entities/removeLiquidity/types.ts#L79) | Input with user defined slippage | - -**Returns** - -```typescript -RemoveLiquidityBuildCallOutput -``` - -[RemoveLiquidityBuildCallOutput](./src/entities/removeLiquidity/types.ts#L83) - Encoded call data for addLiquidity that user can submit. -___ - -## Swap - -This class provides functionality to: -* Perform on-chain queries to see the result of a Swap operation -* Build a Swap transaction, with slippage, for a consumer to submit -* Supports Balancer V2 & V3 - -### Example - -See the [swap example](/examples/swaps/swap.ts). - -### Constructor - -```typescript -const swap = new Swap(swapInput: SwapInput); -``` - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| swapInput | [SwapInput](./src/entities/swap/types.ts#L8) | Swap input including path information. | - -Note: `SwapInput` data is normally returned from an API SOR query but may be constructed manually. - -### Methods - -### query - -Gets up to date swap result by querying onchain. - -```typescript -query( - rpcUrl?: string, - block?: bigint, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| rpcUrl (optional) | string | RPC URL, e.g. Infura/Alchemy | -| block (optional) | bigint | Block no to perform the query | - -**Returns** - -```typescript -Promise -``` - -[ExactInQueryOutput](./src/entities/swap/types.ts#L44) -[ExactOutQueryOutput](./src/entities/swap/types.ts#L49) - -The upated return for the given swap, either `expectedAmountOut` or `expectedAmountIn` depending on swap kind. -___ - -### buildCall - -Builds the swap transaction using user defined slippage. - -```typescript -buildCall( - input: SwapBuildCallInput, -): SwapBuildOutputExactIn | SwapBuildOutputExactOut -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [SwapBuildCallInput](./src/entities/swap/types.ts#L21) | Input with user defined slippage | - -**Returns** - -```typescript -SwapBuildOutputExactIn | SwapBuildOutputExactOut -``` - -[SwapBuildOutputExactIn](./src/entities/swap/types.ts#L31) -[SwapBuildOutputExactOut](./src/entities/swap/types.ts#L35) - -[RemoveLiquidityBuildCallOutput](./src/entities/removeLiquidity/types.ts#L83) - Encoded call data for swap that user can submit. Includes `minAmountOut` or `maxAmountIn` depending on swap kind. -___ - -### quote - -Gives the combined return amount for all paths. Note - this always uses the original path amounts provided in constructor and does not get updated. - -```typescript -public get quote(): TokenAmount -``` - -**Returns** - -```typescript -TokenAmount -``` - -[TokenAmount](./src/entities/tokenAmount.ts) - Gives the combined return amount for all paths (output amount for givenIn, input amount for givenOut). -___ - -### inputAmount - -```typescript -public get inputAmount(): TokenAmount -``` - -**Returns** - -```typescript -TokenAmount -``` - -[TokenAmount](./src/entities/tokenAmount.ts) - Gives the combined input amount for all paths. -___ - -### outputAmount - -```typescript -public get outputAmount(): TokenAmount -``` - -**Returns** - -```typescript -TokenAmount -``` - -[TokenAmount](./src/entities/tokenAmount.ts) - Gives the combined output amount for all paths. -___ - -### queryCallData - -```typescript -public queryCallData(): string -``` - -**Returns** - -```typescript -string -``` - -Encoded query data for swap that a user can call to get an updated amount. -___ - -## PriceImpact - -This class provides helper functions to calculate Price Impact for add/remove/swap actions. -* Supports Balancer V2 & V3 - -### Example - -See the [price impact example](/examples/priceImpact/addLiquidity.ts). - -### Methods - -### addLiquiditySingleToken - -Calculate price impact on add liquidity single token operations. - -```typescript -addLiquiditySingleToken( - input: AddLiquiditySingleTokenInput, - poolState: PoolState, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [AddLiquiditySingleTokenInput](./src/entities/addLiquidity/types.ts#L27) | Same input used in the corresponding add liquidity operation | -| poolState | [PoolState](./src/entities/types.ts#L5) | Current state of pool that liqudity is being added to | - -**Returns** - -```typescript -Promise -``` - -[PriceImpactAmount](./src/entities/priceImpactAmount.ts) - Price impact for operation. -___ -### addLiquidityUnbalanced - -Calculate price impact on add liquidity unbalanced operations. - -```typescript -addLiquidityUnbalanced = async ( - input: AddLiquidityUnbalancedInput, - poolState: PoolState, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | AddLiquidityUnbalancedInput | Same input used in the corresponding add liquidity operation | -| poolState | [PoolState](./src/entities/types.ts#L5) | Current state of pool that liqudity is being added to | - -**Returns** - -```typescript -Promise -``` - -[PriceImpactAmount](./src/entities/priceImpactAmount.ts) - Price impact for operation. -___ -### addLiquidityNested - -Calculate price impact on add liquidity nested token operations. - -```typescript -addLiquidityNested = async ( - input: AddLiquidityNestedInput, - nestedPoolState: NestedPoolState, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | AddLiquidityNestedInput | Same input used in the corresponding add liquidity operation | -| nestedPoolState | [NestedPoolState](./src/entities/types.ts#L43) | Current state of nested pools | - -**Returns** - -```typescript -Promise -``` - -[PriceImpactAmount](./src/entities/priceImpactAmount.ts) - Price impact for operation. -___ - -### removeLiquidity - -Calculate price impact on remove liquidity operations. - -```typescript -removeLiquidity = async ( - input: - | RemoveLiquiditySingleTokenExactInInput - | RemoveLiquidityUnbalancedInput, - poolState: PoolState, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [RemoveLiquiditySingleTokenExactInInput](./src/entities/removeLiquidity/types.ts#L35) | Same input used in the corresponding remove liquidity operation | -| input | [RemoveLiquidityUnbalancedInput](./src/entities/removeLiquidity/types.ts#L24) | Same input used in the corresponding remove liquidity operation | -| poolState | [PoolState](./src/entities/types.ts#L5) | Current state of pool that liqudity is being removed from | - -**Returns** - -```typescript -Promise -``` - -[PriceImpactAmount](./src/entities/priceImpactAmount.ts) - Price impact for operation. -___ - -### removeLiquidityNested - -Calculate price impact on remove liquidity single token nested operations. - -```typescript -removeLiquidityNested = async ( - input: RemoveLiquidityNestedSingleTokenInput, - nestedPoolState: NestedPoolState, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [RemoveLiquidityNestedSingleTokenInput](./src/entities/removeLiquidityNested/types.ts#L15) | Same input used in the corresponding remove liquidity operation | -| nestedPoolState | [NestedPoolState](./src/entities/types.ts#L43) | Current state of nested pools | - -**Returns** - -```typescript -Promise -``` - -[PriceImpactAmount](./src/entities/priceImpactAmount.ts) - Price impact for operation. -___ - -### swap - -Calculate price impact on swap operations. - -```typescript -swap = async ( - swapInput: SwapInput, - rpcUrl?: string, - block?: bigint, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| swapInput | [SwapInput](./src/entities/swap/types.ts#L8) | Swap input including path information. | -| rpcUrl (optional) | string | RPC URL, e.g. Infura/Alchemy | -| block (optional) | bigint | Block no to perform the query | - -Note: `SwapInput` data is normally returned from an API SOR query but may be constructed manually. - -**Returns** - -```typescript -Promise -``` - -[PriceImpactAmount](./src/entities/priceImpactAmount.ts) - Price impact for operation. -___ - -## BalancerApi - -This class provides helper functions for interacting with the Balancer API. - -### Example - -See the examples for add/remove/swap linked above as these use BalancerApi to fetch required data. - -### Constructor - -```typescript -const balancerApi = new BalancerApi(balancerApiUrl: string, chainId: ChainId); -``` - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| balancerApiUrl | string | Url of Balancer API | -| chainId | [ChainId](./src/utils/constants.ts#L54) | Chain that will be queried | - -### Methods - -### pools.fetchPoolState - -Finds state of given pool. - -```typescript -pools.fetchPoolState(id: string): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| id | string | ID of pool, V2=poolId, V3=address | - -**Returns** - -```typescript -Promise -``` - -[PoolState](./src/entities/types.ts#L5) - State of given pool. -___ - -### pools.fetchPoolStateWithBalances - -Finds state of given pool including token balances and pool shares. - -```typescript -fetchPoolStateWithBalances( - id: string, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| id | string | ID of pool, V2=poolId, V3=address | - -**Returns** - -```typescript -Promise -``` - -[PoolStateWithBalances](./src/entities/types.ts#L13) - State of given pool including token balances and pool shares. -___ - -### nestedPools.fetchPoolState - -Finds state of a set of nested pools. - -```typescript -fetchNestedPoolState(id: string): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| id | string | ID of pool, V2=poolId, V3=address | - -**Returns** - -```typescript -Promise -``` - -[NestedPoolState](./src/entities/types.ts#L43) - state of a set of nested pools. -___ -### sorSwapPaths.fetchSorSwapPaths - -Finds optimised swap paths for a given swap config. - -```typescript -fetchSorSwapPaths(sorInput: SorInput): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| sorInput | [SorInput](./src/data/providers/balancer-api/modules/sorSwapPaths/index.ts#L8) | Swap configs | - -**Returns** - -```typescript -Promise -``` - -[Path[]](./src/entities/swap/paths/types.ts#L6) - optimised swap paths for the given swap. -___ - -## Utils - -Helper functions. - -### calculateProportionalAmounts - -Given pool balances (including BPT) and a reference token amount, it calculates all other amounts proportional to the reference amount. - -**Example** - -See [calculateProportionalAmounts example](/examples/utils/calculateProportionalAmounts.ts). - -**Function** - -```typescript -calculateProportionalAmounts( - pool: { - address: Address; - totalShares: HumanAmount; - tokens: { - address: Address; - balance: HumanAmount; - decimals: number - }[]; - }, - referenceAmount: InputAmount, -): { - tokenAmounts: InputAmount[]; - bptAmount: InputAmount; -} -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| pool | See above | Pool state | -| referenceAmount | [InputAmount](./src/types.ts#L43) | Ref token amount | - -**Returns** - -```typescript -{ - tokenAmounts: InputAmount[]; - bptAmount: InputAmount; -} -``` - -Amounts proportional to the reference amount. -___ - -### Permit2 Helper - -Balancer v3 handles token approval through Pemit2 and this helper facilitates Permit2 signature generation. - -Each operation (e.g. addLiquidity, swap, ...) has its own method that leverages the same input type of the operation itself in order to simplify signature generation. - -**Example** - -See [addLiquidityWithPermit2Signature example](/examples/addLiquidity/addLiquidityWithPermit2Signature.ts). - -**Function** - -Helper function to create a Permit2 signature for an addLiquidity operation: - -```typescript -static async signAddLiquidityApproval( - input: AddLiquidityBaseBuildCallInput & { - client: PublicWalletClient; - owner: Address; - nonces?: number[]; - expirations?: number[]; - }, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [AddLiquidityBaseBuildCallInput](./src/entities/addLiquidity/types.ts#L62) | Add Liquidity Input | -| client | [PublicWalletClient](./src/utils/types.ts#L3) | Viem's wallet client with public actions | -| owner | Address | User address | -| nonces (optional) | number[] | Nonces for each token | -| expirations (optional) | number[] | Expirations for each token | - -**Returns** - -```typescript -Promise; -``` - -[Permit2](./src/entities/permit2Helper/index.ts#L35) - Permit2 object with metadata and encoded signature - -___ - -### Permit Helper - -Balancer v3 conforms with EIP-2612 and this helper facilitates Permit signature generation. - -Each operation (e.g. removeLiquidity, removeLiquidityNested and removeLiquidityBoosted) has its own method that leverages the same input type of the operation itself in order to simplify signature generation. - -**Example** - -See [removeLiquidityWithPermitSignature example](/examples/removeLiquidity/removeLiquidityWithPermitSignature.ts). - -**Function** - -Helper function to create a Permit signature for a removeLiquidity operation: - -```typescript -static signRemoveLiquidityApproval = async ( - input: RemoveLiquidityBaseBuildCallInput & { - client: PublicWalletClient; - owner: Hex; - nonce?: bigint; - deadline?: bigint; - }, -): Promise -``` - -**Parameters** - -| Name | Type | Description | -| ------------- | ------------- | ------------ | -| input | [RemoveLiquidityBaseBuildCallInput](./src/entities/removeLiquidity/types.ts#L81) | Remove Liquidity Input | -| client | [PublicWalletClient](./src/utils/types.ts#L3) | Viem's wallet client with public actions | -| owner | Address | User address | -| nonces (optional) | number[] | Nonces for each token | -| expirations (optional) | number[] | Expirations for each token | - -**Returns** - -```typescript -Promise; -``` - -[Permit](./src/entities/permitHelper/index.ts#L30) - Permit object with metadata and encoded signature +## Documentation -___ \ No newline at end of file +In-depth documentation on this SDK is available at [docs-v3.balancer.fi/developer-reference/sdk](https://docs-v3.balancer.fi/developer-reference/sdk/). \ No newline at end of file From 728eee73143d48631686efd79ae911e3f3dc2b20 Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Wed, 4 Dec 2024 11:38:52 -0300 Subject: [PATCH 09/10] Update examples to match deploy11 --- examples/addLiquidity/addLiquidityUnbalanced.ts | 4 ++-- examples/addLiquidity/addLiquidityWithPermit2Signature.ts | 4 ++-- .../removeLiquidity/removeLiquidityWithPermitSignature.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/addLiquidity/addLiquidityUnbalanced.ts b/examples/addLiquidity/addLiquidityUnbalanced.ts index 8a04f575..3cc77b29 100644 --- a/examples/addLiquidity/addLiquidityUnbalanced.ts +++ b/examples/addLiquidity/addLiquidityUnbalanced.ts @@ -27,8 +27,8 @@ async function runAgainstFork() { const userAccount = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; // 50BAL-50WETH const pool = { - id: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6', - address: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6' as Address, + id: '0x2ff3b96e0057a1f25f1d62ab800554ccdb268ab8', + address: '0x2ff3b96e0057a1f25f1d62ab800554ccdb268ab8' as Address, }; const amountsIn = [ { diff --git a/examples/addLiquidity/addLiquidityWithPermit2Signature.ts b/examples/addLiquidity/addLiquidityWithPermit2Signature.ts index 7b2995e4..739ffd4a 100644 --- a/examples/addLiquidity/addLiquidityWithPermit2Signature.ts +++ b/examples/addLiquidity/addLiquidityWithPermit2Signature.ts @@ -35,8 +35,8 @@ async function runAgainstFork() { const chainId = ChainId.SEPOLIA; // 50BAL-50WETH const pool = { - id: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6', - address: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6' as Address, + id: '0x2ff3b96e0057a1f25f1d62ab800554ccdb268ab8', + address: '0x2ff3b96e0057a1f25f1d62ab800554ccdb268ab8' as Address, }; const amountsIn = [ { diff --git a/examples/removeLiquidity/removeLiquidityWithPermitSignature.ts b/examples/removeLiquidity/removeLiquidityWithPermitSignature.ts index 606bab67..2738e544 100644 --- a/examples/removeLiquidity/removeLiquidityWithPermitSignature.ts +++ b/examples/removeLiquidity/removeLiquidityWithPermitSignature.ts @@ -51,8 +51,8 @@ async function runAgainstFork() { // 50BAL-50WETH const pool = { - id: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6', - address: '0x5e54dad6c2504d63473f95d8025b763fd5b893c6' as Address, + id: '0x2ff3b96e0057a1f25f1d62ab800554ccdb268ab8', + address: '0x2ff3b96e0057a1f25f1d62ab800554ccdb268ab8' as Address, }; const slippage = Slippage.fromPercentage('1'); // 1% From 688d857c69ccb8bc978fdddefebc6bb4ed3b453d Mon Sep 17 00:00:00 2001 From: Bruno Eidam Guerios Date: Wed, 4 Dec 2024 11:43:20 -0300 Subject: [PATCH 10/10] Add changeset --- .changeset/dull-nails-love.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/dull-nails-love.md diff --git a/.changeset/dull-nails-love.md b/.changeset/dull-nails-love.md new file mode 100644 index 00000000..b64352a1 --- /dev/null +++ b/.changeset/dull-nails-love.md @@ -0,0 +1,5 @@ +--- +"@balancer/sdk": patch +--- + +Add permit and permit2 signature examples