Skip to content

Instantly share code, notes, and snippets.

@sc0Vu
Last active July 23, 2021 02:08
Show Gist options
  • Save sc0Vu/2a140f2bd934d273c43a6b8edec60d2f to your computer and use it in GitHub Desktop.
Save sc0Vu/2a140f2bd934d273c43a6b8edec60d2f to your computer and use it in GitHub Desktop.

Revisions

  1. sc0Vu revised this gist Jul 23, 2021. 1 changed file with 68 additions and 62 deletions.
    130 changes: 68 additions & 62 deletions balancer_v2.ts
    Original file line number Diff line number Diff line change
    @@ -12,76 +12,82 @@ import {

    const abi = require('./abi')
    const addr = '0xBA12222222228d8Ba445958a75a0704d566BF2C8'

    const provider = new JsonRpcProvider(
    `https://mainnet.infura.io/v3/${process.env.INFURA}`
    `https://mainnet.infura.io/v3/${process.env.INFURA}`
    )
    const DAI = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
    const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
    let sor: SOR2

    async function initSor2(): Promise<SOR2> {
    const network = await provider.getNetwork()
    const chainId = network.chainId
    const maxPools = 100
    const disableOptions: DisabledOptions = {
    isOverRide: false,
    disabledTokens: []
    }
    const poolsSourceV2 = `https://storageapi.fleek.co/johngrantuk-team-bucket/poolsV2.json`
    const subgraphPoolsV2 = `https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2`
    const sor2 = new SOR2(
    provider,
    gasPrice,
    maxPools,
    chainId,
    poolsSourceV2,
    swapCost,
    disableOptions
    )
    const subgraphPools = await fetchSubgraphPools(subgraphPoolsV2)
    const isPoolFetched = await sor2.fetchPools(true, subgraphPools)
    if (!isPoolFetched) throw new Error('Should fetch pool')
    return sor2
    }
    async function swap(swapType: SwapTypes, tokenIn: string, tokenOut: string, amountIn: BigNumber, gasPrice: BigNumber, swapCost: BigNumber) {
    const network = await provider.getNetwork()
    const chainId = network.chainId
    const maxPools = 100
    const disableOptions: DisabledOptions = {
    isOverRide: false,
    disabledTokens: []
    }
    const poolsSourceV2 = `https://storageapi.fleek.co/johngrantuk-team-bucket/poolsV2.json`
    const subgraphPoolsV2 = `https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2`
    const sor2 = new SOR2(
    provider,
    gasPrice,
    maxPools,
    chainId,
    poolsSourceV2,
    swapCost,
    disableOptions
    )
    const subgraphPools = await fetchSubgraphPools(subgraphPoolsV2)
    const isPoolFetched = await sor2.fetchPools(true, subgraphPools)
    if (!isPoolFetched) throw new Error('Should fetch pool')
    const swapOptions: SwapOptions = {
    poolTypeFilter: PoolFilter.All,
    timestamp: Math.floor(Date.now() / 1000)
    }
    await sor2.setCostOutputToken(
    tokenOut,
    6,
    swapCost
    )
    const swapInfo2 = await sor2.getSwaps(
    tokenIn,
    tokenOut,
    swapType,
    amountIn,
    swapOptions
    )
    if (!sor) {
    sor = await initSor2()
    }
    const swapOptions: SwapOptions = {
    poolTypeFilter: PoolFilter.All,
    timestamp: Math.floor(Date.now() / 1000)
    }
    await sor.setCostOutputToken(
    tokenOut,
    6,
    swapCost
    )
    const swapInfo2 = await sor.getSwaps(
    tokenIn,
    tokenOut,
    swapType,
    amountIn,
    swapOptions
    )

    const vault = new Contract(addr, abi, provider)
    const vault = new Contract(addr, abi, provider)

    if (swapInfo2.swaps.length > 1) {
    console.log('Multi hop')
    } else {
    console.log('Single hop')
    }
    console.log('Swap return:')
    console.log(swapInfo2)
    const amounts = await vault.callStatic[
    'queryBatchSwap(uint8,(bytes32,uint256,uint256,uint256,bytes)[],address[],(address,bool,address,bool))'
    ](
    swapType,
    swapInfo2.swaps,
    swapInfo2.tokenAddresses,
    [
    addr,
    false,
    addr,
    false
    ]
    )
    console.log('Query result:')
    console.log(amounts.map((a) => a.toString()))
    if (swapInfo2.swaps.length > 1) {
    console.log('Multi hop')
    } else {
    console.log('Single hop')
    }
    console.log('Swap return:')
    console.log(swapInfo2)
    const amounts = await vault.callStatic[
    'queryBatchSwap(uint8,(bytes32,uint256,uint256,uint256,bytes)[],address[],(address,bool,address,bool))'
    ](
    swapType,
    swapInfo2.swaps,
    swapInfo2.tokenAddresses,
    [
    addr,
    false,
    addr,
    false
    ]
    )
    console.log('Query result:')
    console.log(amounts.map((a) => a.toString()))
    }

    const amountIn = new BigNumber('1')
  2. sc0Vu revised this gist Jul 22, 2021. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions abi.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    [{"inputs":[{"internalType":"contract IAuthorizer","name":"authorizer","type":"address"},{"internalType":"contract IWETH","name":"weth","type":"address"},{"internalType":"uint256","name":"pauseWindowDuration","type":"uint256"},{"internalType":"uint256","name":"bufferPeriodDuration","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IAuthorizer","name":"newAuthorizer","type":"address"}],"name":"AuthorizerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ExternalBalanceTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IFlashLoanRecipient","name":"recipient","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"FlashLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"int256","name":"delta","type":"int256"}],"name":"InternalBalanceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"PausedStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"liquidityProvider","type":"address"},{"indexed":false,"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"int256[]","name":"deltas","type":"int256[]"},{"indexed":false,"internalType":"uint256[]","name":"protocolFeeAmounts","type":"uint256[]"}],"name":"PoolBalanceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"assetManager","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"int256","name":"cashDelta","type":"int256"},{"indexed":false,"internalType":"int256","name":"managedDelta","type":"int256"}],"name":"PoolBalanceManaged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"poolAddress","type":"address"},{"indexed":false,"internalType":"enum IVault.PoolSpecialization","name":"specialization","type":"uint8"}],"name":"PoolRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"RelayerApprovalChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":true,"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"name":"TokensDeregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"assetManagers","type":"address[]"}],"name":"TokensRegistered","type":"event"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IVault.SwapKind","name":"kind","type":"uint8"},{"components":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"uint256","name":"assetInIndex","type":"uint256"},{"internalType":"uint256","name":"assetOutIndex","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct IVault.BatchSwapStep[]","name":"swaps","type":"tuple[]"},{"internalType":"contract IAsset[]","name":"assets","type":"address[]"},{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"internalType":"struct IVault.FundManagement","name":"funds","type":"tuple"},{"internalType":"int256[]","name":"limits","type":"int256[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"batchSwap","outputs":[{"internalType":"int256[]","name":"assetDeltas","type":"int256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"name":"deregisterTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address payable","name":"recipient","type":"address"},{"components":[{"internalType":"contract IAsset[]","name":"assets","type":"address[]"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"internalType":"struct IVault.ExitPoolRequest","name":"request","type":"tuple"}],"name":"exitPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IFlashLoanRecipient","name":"recipient","type":"address"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"flashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"getActionId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAuthorizer","outputs":[{"internalType":"contract IAuthorizer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"name":"getInternalBalance","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNextNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPausedState","outputs":[{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"uint256","name":"pauseWindowEndTime","type":"uint256"},{"internalType":"uint256","name":"bufferPeriodEndTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"}],"name":"getPool","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"enum IVault.PoolSpecialization","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"getPoolTokenInfo","outputs":[{"internalType":"uint256","name":"cash","type":"uint256"},{"internalType":"uint256","name":"managed","type":"uint256"},{"internalType":"uint256","name":"lastChangeBlock","type":"uint256"},{"internalType":"address","name":"assetManager","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"}],"name":"getPoolTokens","outputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"balances","type":"uint256[]"},{"internalType":"uint256","name":"lastChangeBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProtocolFeesCollector","outputs":[{"internalType":"contract ProtocolFeesCollector","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"relayer","type":"address"}],"name":"hasApprovedRelayer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"contract IAsset[]","name":"assets","type":"address[]"},{"internalType":"uint256[]","name":"maxAmountsIn","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"}],"internalType":"struct IVault.JoinPoolRequest","name":"request","type":"tuple"}],"name":"joinPool","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"enum IVault.PoolBalanceOpKind","name":"kind","type":"uint8"},{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IVault.PoolBalanceOp[]","name":"ops","type":"tuple[]"}],"name":"managePoolBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"enum IVault.UserBalanceOpKind","name":"kind","type":"uint8"},{"internalType":"contract IAsset","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct IVault.UserBalanceOp[]","name":"ops","type":"tuple[]"}],"name":"manageUserBalance","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"enum IVault.SwapKind","name":"kind","type":"uint8"},{"components":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"uint256","name":"assetInIndex","type":"uint256"},{"internalType":"uint256","name":"assetOutIndex","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct IVault.BatchSwapStep[]","name":"swaps","type":"tuple[]"},{"internalType":"contract IAsset[]","name":"assets","type":"address[]"},{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"internalType":"struct IVault.FundManagement","name":"funds","type":"tuple"}],"name":"queryBatchSwap","outputs":[{"internalType":"int256[]","name":"","type":"int256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IVault.PoolSpecialization","name":"specialization","type":"uint8"}],"name":"registerPool","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"address[]","name":"assetManagers","type":"address[]"}],"name":"registerTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IAuthorizer","name":"newAuthorizer","type":"address"}],"name":"setAuthorizer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"relayer","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setRelayerApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"poolId","type":"bytes32"},{"internalType":"enum IVault.SwapKind","name":"kind","type":"uint8"},{"internalType":"contract IAsset","name":"assetIn","type":"address"},{"internalType":"contract IAsset","name":"assetOut","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct IVault.SingleSwap","name":"singleSwap","type":"tuple"},{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"bool","name":"fromInternalBalance","type":"bool"},{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"bool","name":"toInternalBalance","type":"bool"}],"internalType":"struct IVault.FundManagement","name":"funds","type":"tuple"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountCalculated","type":"uint256"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]
  3. sc0Vu created this gist Jul 22, 2021.
    96 changes: 96 additions & 0 deletions balancer_v2.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,96 @@
    import BigNumber from 'bignumber.js'
    import { Contract } from 'ethers'
    import { JsonRpcProvider } from '@ethersproject/providers'
    import {
    SOR as SOR2,
    SwapTypes,
    DisabledOptions,
    SwapOptions,
    PoolFilter,
    fetchSubgraphPools
    } from '@balancer-labs/sor2'

    const abi = require('./abi')
    const addr = '0xBA12222222228d8Ba445958a75a0704d566BF2C8'

    const provider = new JsonRpcProvider(
    `https://mainnet.infura.io/v3/${process.env.INFURA}`
    )
    const DAI = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
    const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'

    async function swap(swapType: SwapTypes, tokenIn: string, tokenOut: string, amountIn: BigNumber, gasPrice: BigNumber, swapCost: BigNumber) {
    const network = await provider.getNetwork()
    const chainId = network.chainId
    const maxPools = 100
    const disableOptions: DisabledOptions = {
    isOverRide: false,
    disabledTokens: []
    }
    const poolsSourceV2 = `https://storageapi.fleek.co/johngrantuk-team-bucket/poolsV2.json`
    const subgraphPoolsV2 = `https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-v2`
    const sor2 = new SOR2(
    provider,
    gasPrice,
    maxPools,
    chainId,
    poolsSourceV2,
    swapCost,
    disableOptions
    )
    const subgraphPools = await fetchSubgraphPools(subgraphPoolsV2)
    const isPoolFetched = await sor2.fetchPools(true, subgraphPools)
    if (!isPoolFetched) throw new Error('Should fetch pool')
    const swapOptions: SwapOptions = {
    poolTypeFilter: PoolFilter.All,
    timestamp: Math.floor(Date.now() / 1000)
    }
    await sor2.setCostOutputToken(
    tokenOut,
    6,
    swapCost
    )
    const swapInfo2 = await sor2.getSwaps(
    tokenIn,
    tokenOut,
    swapType,
    amountIn,
    swapOptions
    )

    const vault = new Contract(addr, abi, provider)

    if (swapInfo2.swaps.length > 1) {
    console.log('Multi hop')
    } else {
    console.log('Single hop')
    }
    console.log('Swap return:')
    console.log(swapInfo2)
    const amounts = await vault.callStatic[
    'queryBatchSwap(uint8,(bytes32,uint256,uint256,uint256,bytes)[],address[],(address,bool,address,bool))'
    ](
    swapType,
    swapInfo2.swaps,
    swapInfo2.tokenAddresses,
    [
    addr,
    false,
    addr,
    false
    ]
    )
    console.log('Query result:')
    console.log(amounts.map((a) => a.toString()))
    }

    const amountIn = new BigNumber('1')
    const gasPrice = new BigNumber('30000000000')
    const swapCost = new BigNumber('1000000')
    console.log('Swap 1 usdc to ? dai')
    swap(SwapTypes.SwapExactIn, USDC, DAI, amountIn, gasPrice, swapCost)
    .then(() => {
    console.log('Swap ? usdc to 1 dai')
    return swap(SwapTypes.SwapExactOut, USDC, DAI, amountIn, gasPrice, swapCost)
    })
    .catch(console.error)