Giter Site home page Giter Site logo

curve-js's Introduction

Curve JS

Setup

Install from npm:

npm install @curvefi/api

Init

import curve from "@curvefi/api";

(async () => {
    // 1. Dev
    await curve.init('JsonRpc', {url: 'http://localhost:8545/', privateKey: ''}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0, chainId: 1 });
    // OR
    await curve.init('JsonRpc', {}, {}); // In this case JsonRpc url, privateKey, fee data and chainId will be specified automatically

    // 2. Infura
    await curve.init("Infura", { network: "homestead", apiKey: <INFURA_KEY> }, { chainId: 1 });
    
    // 3. Web3 provider
    await curve.init('Web3', { externalProvider: <WEB3_PROVIDER> }, { chainId: 1 });
    
    // Fetch factory pools
    await curve.factory.fetchPools();
    await curve.crvUSDFactory.fetchPools();
    await curve.EYWAFactory.fetchPools();
    await curve.cryptoFactory.fetchPools();
    await curve.twocryptoFactory.fetchPools();
    await curve.tricryptoFactory.fetchPools();
    await curve.stableNgFactory.fetchPools(); 
})()

Note 1. chainId parameter is optional, but you must specify it in the case you use Metamask on localhost network, because Metamask has that bug

Note 2. Web3 init requires the address. Therefore, it can be initialized only after receiving the address.

Wrong ❌️

import type { FunctionComponent } from 'react'
import { useState, useMemo } from 'react'
import { providers } from 'ethers'
import Onboard from 'bnc-onboard'
import type { Wallet } from 'bnc-onboard/dist/src/interfaces'
import curve from '@curvefi/api'

    ...

const WalletProvider: FunctionComponent = ({ children }) => {
    const [wallet, setWallet] = useState<Wallet>()
    const [provider, setProvider] = useState<providers.Web3Provider>()
    const [address, setAddress] = useState<string>()

    const networkId = 1

    const onboard = useMemo(
        () =>
            Onboard({
                dappId: DAPP_ID,
                networkId,

                subscriptions: {
                    address: (address) => {
                        setAddress(address)
                    },

                    wallet: (wallet) => {
                        setWallet(wallet)
                        if (wallet.provider) {
                            curve.init("Web3", { externalProvider: wallet.provider }, { chainId: networkId })
                        }
                    },
                },
                walletSelect: {
                    wallets: wallets,
                },
            }),
        []
    )

    ...

Right ✔️

import type { FunctionComponent } from 'react'
import { useState, useMemo, useEffect } from 'react'
import { providers } from 'ethers'
import Onboard from 'bnc-onboard'
import type { Wallet } from 'bnc-onboard/dist/src/interfaces'
import curve from '@curvefi/api'

    ...

const WalletProvider: FunctionComponent = ({ children }) => {
    const [wallet, setWallet] = useState<Wallet>()
    const [provider, setProvider] = useState<providers.Web3Provider>()
    const [address, setAddress] = useState<string>()

    const networkId = 1

    const onboard = useMemo(
        () =>
            Onboard({
                dappId: DAPP_ID,
                networkId,

                subscriptions: {
                    address: (address) => {
                        setAddress(address)
                    },

                    wallet: (wallet) => {
                        setWallet(wallet)
                    },
                },
                walletSelect: {
                    wallets: wallets,
                },
            }),
        []
    )

    useEffect(() => {
        if (address && wallet?.provider) {
            curve.init("Web3", { externalProvider: wallet.provider }, { chainId: networkId })
        }
    }, [address, wallet?.provider]);

    ...

Notes

  • 1 Amounts can be passed in args either as numbers or strings.
  • 2 depositOrWithdrawBonus and swapPriceImpact methods return %, e. g. 0 < bonus/priceImpact <= 100
  • 3 Slippage arg should be passed as %, e. g. 0 < slippage <= 100

General methods

import curve from "@curvefi/api";

(async () => {
    await curve.getTVL();
    // 7870819849.685552
    await curve.getVolume();
    // {
    //     totalVolume: 514893871.3481678,
    //     cryptoVolume: 162757004.96876568,
    //     cryptoShare: 31.609815930147377
    // }

    const balances1 = await curve.getBalances(['DAI', 'sUSD']);
    // OR const balances1 = await curve.getBalances(['0x6B175474E89094C44Da98b954EedeAC495271d0F', '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51']);
    console.log(balances1);
    // [ '10000.0', '0.0' ]

    // You can specify addresses
    const balances2 = await curve.getBalances(['aDAI', 'aSUSD'], "0x0063046686E46Dc6F15918b61AE2B121458534a5", "0x66aB6D9362d4F35596279692F0251Db635165871");
    // OR const balances2 = await curve.getBalances(['0x028171bCA77440897B824Ca71D1c56caC55b68A3', '0x6c5024cd4f8a59110119c56f8933403a539555eb'], ["0x0063046686E46Dc6F15918b61AE2B121458534a5", "0x66aB6D9362d4F35596279692F0251Db635165871"]);
    console.log(balances2);
    // {
    //     '0x0063046686E46Dc6F15918b61AE2B121458534a5': [ '0.0', '0.0' ],
    //     '0x66aB6D9362d4F35596279692F0251Db635165871': [ '0.0', '0.0' ]
    // }

    
    const spender = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7" // 3pool swap address

    await curve.getAllowance(["DAI", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], curve.signerAddress, spender);
    // [ '0.0', '0.0' ]
    await curve.hasAllowance(["DAI", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], ['1000', '1000'], curve.signerAddress, spender);
    // false
    await curve.ensureAllowance(["DAI", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], ['1000', '1000'], spender);
    // [
    //     '0xb0cada2a2983dc0ed85a26916d32b9caefe45fecde47640bd7d0e214ff22aed3',
    //     '0x00ea7d827b3ad50ce933e96c579810cd7e70d66a034a86ec4e1e10005634d041'
    // ]
})()

Pools

Available pools

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    await curve.factory.fetchPools();
    await curve.crvUSDFactory.fetchPools();
    await curve.EYWAFactory.fetchPools();
    await curve.cryptoFactory.fetchPools();
    await curve.twocryptoFactory.fetchPools();
    await curve.tricryptoFactory.fetchPools();
    await curve.stableNgFactory.fetchPools();

    curve.getMainPoolList();
    // [
    //     'compound', 'usdt',    'y',          'busd',
    //     'susd',     'pax',     'ren',        'sbtc',
    //     'hbtc',     '3pool',   'gusd',       'husd',
    //     'usdk',     'usdn',    'musd',       'rsv',
    //     'tbtc',     'dusd',    'pbtc',       'bbtc',
    //     'obtc',     'seth',    'eurs',       'ust',
    //     'aave',     'steth',   'saave',      'ankreth',
    //     'usdp',     'ib',      'link',       'tusd',
    //     'frax',     'lusd',    'busdv2',     'reth',
    //     'alusd',    'mim',     'tricrypto2', 'eurt',
    //     'eurtusd',  'eursusd', 'crveth',     'rai',
    //     'cvxeth',   'xautusd', 'spelleth',   'teth',
    //     '2pool',    '4pool'
    // ]
    
    curve.factory.getPoolList();
    // [
    //     'factory-v2-0',   'factory-v2-2',   'factory-v2-3',   'factory-v2-4',
    //     'factory-v2-5',   'factory-v2-6',   'factory-v2-7',   'factory-v2-8',
    //     'factory-v2-9',   'factory-v2-10',  'factory-v2-11',  'factory-v2-14',
    //     'factory-v2-15',  'factory-v2-17',  'factory-v2-18',  'factory-v2-19',
    //     'factory-v2-21',  'factory-v2-22',  'factory-v2-23',  'factory-v2-24',
    //     'factory-v2-25',  'factory-v2-26',  'factory-v2-27',  'factory-v2-28',
    //     'factory-v2-29',  'factory-v2-30',  'factory-v2-31',  'factory-v2-32',
    //     'factory-v2-33',  'factory-v2-34',  'factory-v2-35',  'factory-v2-36',
    //     'factory-v2-37',  'factory-v2-38',  'factory-v2-39',  'factory-v2-40',
    //     'factory-v2-41',  'factory-v2-42',  'factory-v2-43',  'factory-v2-44',
    //     'factory-v2-45',  'factory-v2-46',  'factory-v2-47',  'factory-v2-48',
    //     'factory-v2-49',  'factory-v2-50',  'factory-v2-51',  'factory-v2-52',
    //     'factory-v2-53',  'factory-v2-54',  'factory-v2-55',  'factory-v2-56',
    //     'factory-v2-57',  'factory-v2-58',  'factory-v2-59',  'factory-v2-60',
    //     'factory-v2-61',  'factory-v2-62',  'factory-v2-63',  'factory-v2-64',
    //     'factory-v2-65',  'factory-v2-66',  'factory-v2-67',  'factory-v2-68',
    //     'factory-v2-69',  'factory-v2-70',  'factory-v2-71',  'factory-v2-72',
    //     'factory-v2-73',  'factory-v2-74',  'factory-v2-75',  'factory-v2-76',
    //     'factory-v2-77',  'factory-v2-78',  'factory-v2-79',  'factory-v2-80',
    //     'factory-v2-81',  'factory-v2-82',  'factory-v2-83',  'factory-v2-84',
    //     'factory-v2-85',  'factory-v2-86',  'factory-v2-87',  'factory-v2-88',
    //     'factory-v2-89',  'factory-v2-90',  'factory-v2-91',  'factory-v2-92',
    //     'factory-v2-93',  'factory-v2-94',  'factory-v2-95',  'factory-v2-96',
    //     'factory-v2-97',  'factory-v2-98',  'factory-v2-99',  'factory-v2-100',
    //     'factory-v2-101', 'factory-v2-102', 'factory-v2-103', 'factory-v2-104',
    //     ... 27 more items
    // ]

    curve.crvUSDFactory.getPoolList();
    // ['factory-crvusd-0',  'factory-crvusd-1',  'factory-crvusd-2', 'factory-crvusd-3']

    // On Fantom network
    curve.EYWAFactory.getPoolList();
    // ['factory-eywa-0',  'factory-eywa-1',  'factory-eywa-2', 'factory-eywa-3']
    
    curve.cryptoFactory.getPoolList();
    // [
    //     'factory-crypto-0',  'factory-crypto-1',  'factory-crypto-2',
    //     'factory-crypto-3',  'factory-crypto-4',  'factory-crypto-5',
    //     'factory-crypto-6',  'factory-crypto-7',  'factory-crypto-8',
    //     'factory-crypto-9',  'factory-crypto-10', 'factory-crypto-11',
    //     'factory-crypto-12', 'factory-crypto-13', 'factory-crypto-14',
    //     'factory-crypto-15', 'factory-crypto-16', 'factory-crypto-17',
    //     'factory-crypto-18', 'factory-crypto-19', 'factory-crypto-20',
    //     'factory-crypto-21', 'factory-crypto-22', 'factory-crypto-23',
    //     'factory-crypto-24', 'factory-crypto-25', 'factory-crypto-26',
    //     'factory-crypto-27', 'factory-crypto-28', 'factory-crypto-29',
    //     'factory-crypto-30', 'factory-crypto-31', 'factory-crypto-32',
    //     'factory-crypto-33', 'factory-crypto-34', 'factory-crypto-35',
    //     'factory-crypto-36', 'factory-crypto-37', 'factory-crypto-38',
    //     'factory-crypto-39', 'factory-crypto-40', 'factory-crypto-41',
    //     'factory-crypto-42', 'factory-crypto-43', 'factory-crypto-44',
    //     'factory-crypto-45', 'factory-crypto-46', 'factory-crypto-47',
    //     'factory-crypto-48', 'factory-crypto-49', 'factory-crypto-50',
    //     'factory-crypto-51', 'factory-crypto-52', 'factory-crypto-53',
    //     'factory-crypto-54', 'factory-crypto-55', 'factory-crypto-56',
    //     'factory-crypto-57', 'factory-crypto-58', 'factory-crypto-59',
    //     'factory-crypto-60', 'factory-crypto-61', 'factory-crypto-62'
    // ]

    curve.twocryptoFactory.getPoolList();
    // ['factory-twocrypto-0', 'factory-twocrypto-1']
    
    curve.tricryptoFactory.getPoolList();
    // ['factory-tricrypto-0', 'factory-tricrypto-1']

    curve.stableNgFactory.getPoolList();
    // ['factory-stable-ng-0', 'factory-stable-ng-1']
    
    curve.getPoolList();
    // [
    //     'compound',      'usdt',          'y',             'busd',
    //     'susd',          'pax',           'ren',           'sbtc',
    //     'hbtc',          '3pool',         'gusd',          'husd',
    //     'usdk',          'usdn',          'musd',          'rsv',
    //     'tbtc',          'dusd',          'pbtc',          'bbtc',
    //     'obtc',          'seth',          'eurs',          'ust',
    //     'aave',          'steth',         'saave',         'ankreth',
    //     'usdp',          'ib',            'link',          'tusd',
    //     'frax',          'lusd',          'busdv2',        'reth',
    //     'alusd',         'mim',           'tricrypto2',    'eurt',
    //     'eurtusd',       'eursusd',       'crveth',        'rai',
    //     'cvxeth',        'xautusd',       'spelleth',      'teth',
    //     '2pool',         '4pool',         'fraxusdc',      'euroc',
    //     'frxeth',        'sbtc2',         'fraxusdp',      'wbeth',
    //     'factory-v2-2',  'factory-v2-3',  'factory-v2-5',  'factory-v2-7',
    //     'factory-v2-9',  'factory-v2-10', 'factory-v2-11', 'factory-v2-14',
    //     'factory-v2-21', 'factory-v2-22', 'factory-v2-23', 'factory-v2-24',
    //     'factory-v2-25', 'factory-v2-27', 'factory-v2-28', 'factory-v2-29',
    //     'factory-v2-30', 'factory-v2-31', 'factory-v2-32', 'factory-v2-33',
    //     'factory-v2-34', 'factory-v2-35', 'factory-v2-37', 'factory-v2-38',
    //     'factory-v2-41', 'factory-v2-42', 'factory-v2-43', 'factory-v2-44',
    //     'factory-v2-45', 'factory-v2-47', 'factory-v2-48', 'factory-v2-49',
    //     'factory-v2-50', 'factory-v2-51', 'factory-v2-52', 'factory-v2-53',
    //     'factory-v2-55', 'factory-v2-56', 'factory-v2-57', 'factory-v2-58',
    //     'factory-v2-59', 'factory-v2-60', 'factory-v2-61', 'factory-v2-62',
    //     ... 493 more items
    // ]
})()

Pool fields

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    await curve.factory.fetchPools();
    await curve.crvUSDFactory.fetchPools();
    await curve.EYWAFactory.fetchPools();
    await curve.cryptoFactory.fetchPools();
    await curve.twocryptoFactory.fetchPools();
    await curve.tricryptoFactory.fetchPools();
    await curve.stableNgFactory.fetchPools();
    
    const pool = curve.getPool('factory-v2-11');

    pool.id;
    // factory-v2-11
    pool.name;
    // FEI Metapool
    pool.fullName;
    // Curve.fi Factory USD Metapool: FEI Metapool
    pool.symbol;
    // FEI3CRV3CRV-f
    pool.referenceAsset;
    // USD
    pool.address;
    // 0x06cb22615ba53e60d67bf6c341a0fd5e718e1655
    pool.lpToken;
    // 0x06cb22615ba53e60d67bf6c341a0fd5e718e1655
    pool.gauge;
    // 0xdc69d4cb5b86388fff0b51885677e258883534ae
    pool.zap;
    // 0xa79828df1850e8a3a3064576f380d90aecdd3359
    pool.sRewardContract;
    // null
    pool.rewardContract;
    // null
    pool.isPlain;
    // false
    pool.isLending;
    // false
    pool.isMeta;
    // true
    pool.isCrypto;
    // false
    pool.isFake;
    // false
    pool.isFactory;
    // true
    pool.basePool;
    // 3pool
    pool.underlyingCoins;
    // [ 'FEI', 'DAI', 'USDC', 'USDT' ]
    pool.wrappedCoins;
    // [ 'FEI', '3Crv' ]
    pool.underlyingCoinAddresses;
    // [
    //     '0x956f47f50a910163d8bf957cf5846d573e7f87ca',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7'
    // ]
    pool.wrappedCoinAddresses;
    // [
    //     '0x956f47f50a910163d8bf957cf5846d573e7f87ca',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490'
    // ]
    pool.underlyingDecimals;
    // [ 18, 18, 6, 6 ]
    pool.wrappedDecimals;
    // [ 18, 18 ]
    pool.useLending;
    // [ false, false, false, false ]
    pool.inApi;
    // true
    await pool.isGaugeKilled();
    // false
    await pool.gaugeStatus();
    // null OR
    //{
    //      rewardsNeedNudging: false,
    //      areCrvRewardsStuckInBridge: false,
    //
    // }
})()

Wallet balances for pool

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    
    const saave = curve.getPool('saave');
    
    // 1. Current address (signer) balances

    await saave.wallet.balances();
    // {
    //     lpToken: '0.0',
    //     gauge: '0.0',
    //     '0x6B175474E89094C44Da98b954EedeAC495271d0F': '10000.0',
    //     '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '10000.0',
    //     '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '10000.00017727177059715',
    //     '0x6c5024cd4f8a59110119c56f8933403a539555eb': '10000.000080108429034461'
    // }


    await saave.wallet.lpTokenBalances();
    // { lpToken: '0.0', gauge: '0.0' }

    await saave.wallet.underlyingCoinBalances();
    // {
    //     '0x6B175474E89094C44Da98b954EedeAC495271d0F': '10000.0',
    //     '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '10000.0'
    // }

    await saave.wallet.wrappedCoinBalances();
    // {
    //     '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '10000.00017727177059715',
    //     '0x6c5024cd4f8a59110119c56f8933403a539555eb': '10000.000080108429034461'
    // }

    await saave.wallet.allCoinBalances();
    // {
    //     '0x6B175474E89094C44Da98b954EedeAC495271d0F': '10000.0',
    //     '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '10000.0',
    //     '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '10000.00017727177059715',
    //     '0x6c5024cd4f8a59110119c56f8933403a539555eb': '10000.000080108429034461'
    // }


    // 2. For every method above you can specify the address
    
    await saave.wallet.balances("0x0063046686E46Dc6F15918b61AE2B121458534a5");
    // {
    //     lpToken: '0.0',
    //     gauge: '0.0',
    //     '0x6B175474E89094C44Da98b954EedeAC495271d0F': '0.0',
    //     '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '0.0',
    //     '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '0.0',
    //     '0x6c5024cd4f8a59110119c56f8933403a539555eb': '0.0'
    // }

    // Or several addresses
    await saave.wallet.balances("0x0063046686E46Dc6F15918b61AE2B121458534a5", "0x66aB6D9362d4F35596279692F0251Db635165871");
    // {
    //     '0x0063046686E46Dc6F15918b61AE2B121458534a5': {
    //         lpToken: '0.0',
    //         gauge: '0.0',
    //         '0x6B175474E89094C44Da98b954EedeAC495271d0F': '0.0',
    //         '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '0.0',
    //         '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '0.0',
    //         '0x6c5024cd4f8a59110119c56f8933403a539555eb': '0.0'
    //     },
    //     '0x66aB6D9362d4F35596279692F0251Db635165871': {
    //         lpToken: '0.0',
    //         gauge: '0.0',
    //         '0x6B175474E89094C44Da98b954EedeAC495271d0F': '10000.0',
    //         '0x57Ab1ec28D129707052df4dF418D58a2D46d5f51': '10000.0',
    //         '0x028171bCA77440897B824Ca71D1c56caC55b68A3': '10000.00017727177059715',
    //         '0x6c5024cd4f8a59110119c56f8933403a539555eb': '10000.000080108429034461'
    //     }
    // }
})()

Stats

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    
    
    // --- COMPOUND ---

    const compound = curve.getPool('compound');
    
    await compound.stats.parameters();
    // {
    //     lpTokenSupply: '66658430.461661546713781772',
    //     virtualPrice: '1.107067773320466717',
    //     fee: '0.04',
    //     adminFee: '0.02',
    //     A: '4500',
    //     future_A: '4500',
    //     initial_A: undefined,
    //     future_A_time: undefined,
    //     initial_A_time: undefined,
    //     gamma: undefined
    // }
    
    await compound.stats.underlyingBalances();
    // [ '66625943.103442629270215258', '33124832.500932' ]
    
    await compound.stats.wrappedBalances();
    // [ '3026076723.05777297', '1464830413.37972924' ]

    await compound.stats.totalLiquidity();
    // 99836271.3031733

    // --- STETH ---
    
    const steth = curve.getPool('steth');
    
    await steth.stats.volume();
    // 174737430.35185483

    await steth.stats.baseApy();
    // { day: '3.1587592896017647', week: '2.6522145719060752' } (as %)
    
    await steth.stats.tokenApy();
    // [ '0.5918', '1.4796' ] (as %)
    
    await steth.stats.rewardsApy();
    // [
    //     {
    //         gaugeAddress: '0x182b723a58739a9c974cfdb385ceadb237453c28',
    //         tokenAddress: '0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32',
    //         tokenPrice: 1.023,
    //         name: 'Lido DAO Token',
    //         symbol: 'LDO',
    //         decimals: '18',
    //         apy: 2.6446376845647155 (as %)
    //     }
    // ]
    
})()

Deposit

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });

    const pool = curve.getPool('mim');

    
    // --- UNDERLYING ---

    
    await pool.wallet.underlyingCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '10000.0',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '10000.0',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '10000.0',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '10000.0',
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '0.0', gauge: '0.0' }

    await pool.depositBalancedAmounts();
    // [
    //     '10000.000000000000000000',
    //     '785.167649368248476094',
    //     '771.263652',
    //     '2234.662927'
    // ]
    await pool.depositExpected([100, 100, 100, 100]);
    // 397.546626854200557344
    await pool.depositBonus([100, 100, 100, 100]);
    // 0.04489060058668274
    await pool.depositIsApproved([100, 100, 100, 100]);
    // false
    await pool.depositApprove([100, 100, 100, 100]);
    // [
    //     '0xd3bb4266a9004b4c42d41984d65cce65050a216564dcefa852bbe29f0466bc32',
    //     '0xb2e67fb6cc0d4cef18e918bccf85248a30aa5c318220e8c3887f5f936599e639',
    //     '0x6d523d348ef1dc24e4a61830476f3c5e4450e8e2c91d903f9e0272efc73f5af8',
    //     '0xe2c7bd884b91011791d0e979b9511ca035efee60a5c23b7f5623d490250ca4b2'
    // ]
    await pool.deposit(['100', '100', '100', '100'], 0.1); // slippage = 0.1 %
    // 0x8202a2fd645d6b9bc2c6f47aa3475d61bcfd5905def125e8287cb47f3f86db75
    
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9900.0',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9900.0',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9900.0',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '9900.0',
    // }
    // { lpToken: '397.465346370726773487', gauge: '0.0' }
    
    
    // --- WRAPPED ---
    
    
    await pool.wallet.wrappedCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9900.0',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '100000.0'
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '397.465346370726773487', gauge: '0.0' }
    
    await pool.depositWrappedBalancedAmounts();
    // [ '9900.000000000000000000', '3674.037213475177850341' ]
    await pool.depositWrappedExpected(['100', '100']);
    // 200.853415578798484973
    await pool.depositWrappedBonus([100, 100]);
    // 0.5057286575144729
    await pool.depositWrappedIsApproved([100, 100]);
    // false
    await pool.depositWrappedApprove([100, 100]);
    // [
    //     '0xe8eb519833d417dcd8da1ee3c4fcadf30dece560b7e1977a5f78c995f8e72b4b',
    //     '0xd7d02b26a052f755bed033a880745ff58775d4668d7620042b6e5973e90ba574'
    // ]
    await pool.depositWrapped([100, 100], 0.1); // slippage = 0.1 %
    // 0x78b943a9a1082cd07ddb0225b070e934740448bfa10444b00cd00e7368ad0601
    
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9800.0',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '99900.0'
    // }
    // { lpToken: '598.300246031617065027', gauge: '0.0' }
})()

Staking

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const pool = curve.getPool('mim');
    
    const balances = await pool.wallet.lpTokenBalances() as IDict<string>;
    // { lpToken: '598.300246031617065027', gauge: '0.0' }
    
    await pool.stakeIsApproved(balances.lpToken);
    // false
    await pool.stakeApprove(balances.lpToken);
    // [
    //     '0x9d5011800bb4afe82b3a97a56a55762f11b5e999c1de908f38a66f7425c0b0d0'
    // ]
    await pool.stake(balances.lpToken);
    // 0xf884b798be15295f090476eb9d13c46d09d8c05dc0e05d822a34120fa641f645

    await pool.wallet.lpTokenBalances();
    // { lpToken: '0.0', gauge: '598.300246031617065027' }
    
    await pool.unstake(balances.lpToken);
    // 0x802b96921f2fabb433e02489315850a81c1a2e180cd05d84a6d71ce9fc624020

    await pool.wallet.lpTokenBalances();
    // { lpToken: '598.300246031617065027', gauge: '0.0' }
})()

Withdraw

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });

    const pool = curve.getPool('mim');

    // --- UNDERLYING ---

    await pool.wallet.underlyingCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9800.0',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9900.0',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9900.0',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '9900.0'
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '598.300246031617065027', gauge: '0.0' }

    await pool.withdrawExpected(10);
    // [
    //     '7.299072252784503555',
    //     '0.573101727634383933',
    //     '0.562953',
    //     '1.631103'
    // ]
    await pool.withdrawIsApproved(10);
    // false
    await pool.withdrawApprove(10);
    // [
    //     '0xbc72529f860eab00ae6e72234a68c48c9bfa8e093813ecf6796d46de419badca'
    // ]
    await pool.withdraw('10', 0.1); // slippage = 0.1 %
    // 0x4dc3add45566e0f3404c2fa0b7aa27203688833ffbe9b985f36bf785d19e4fad

    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9807.299072252784503555',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9900.573101727634383932',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9900.562953',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '9901.631102'
    // }
    // { lpToken: '588.300246031617065027', gauge: '0.0' }

    // --- WRAPPED ---

    await pool.wallet.wrappedCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9807.299072252784503555',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '99900.0'
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '588.300246031617065027', gauge: '0.0' }

    await pool.withdrawWrappedExpected('10');
    // [ '7.299072252784503555', '2.708796226980363129' ]
    await pool.withdrawWrapped(10); // slippage = 0.5 % by default
    // 0x61f7b602bc52d20fdf473c8dd8cbea12f11918fdbd74c496235887c70321395a
    
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9814.59814450556900711',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '99902.708796226980363129'
    // }
    // { lpToken: '578.300246031617065027', gauge: '0.0' }
})()

Withdraw imbalance

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });

    const pool = curve.getPool('mim');

    // --- UNDERLYING ---

    await pool.wallet.underlyingCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9814.59814450556900711',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9900.573101727634383932',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9900.562953',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '9901.631102'
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '578.300246031617065027', gauge: '0.0' }

    await pool.withdrawImbalanceExpected(['10', '10', '10', '10']);
    // 39.754662629184493064
    await pool.withdrawImbalanceBonus(['10', '10', '10', '10']);
    // -0.04487324436377509
    await pool.withdrawImbalanceIsApproved(['10', '10', '10', '10']);
    // true
    await pool.withdrawImbalanceApprove(['10', '10', '10', '10']);
    // []
    await pool.withdrawImbalance(['10', '10', '10', '10'], 0.1); // slippage = 0.1 %
    // 0xfba4dfb47cd5692ef01608e7b04439ec211cb28430b488e60fee5cadb77ac321

    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9824.59814450556900711',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9910.573101727634383932',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9910.562953',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '9911.631102'
    // }
    // { lpToken: '538.537454267261447723', gauge: '0.0' }

    // --- WRAPPED ---

    await pool.wallet.wrappedCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9824.59814450556900711',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '99902.708796226980363129'
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '538.537454267261447723', gauge: '0.0' }

    await pool.withdrawImbalanceWrappedExpected(['10', '10']);
    // 20.085341556879117658
    await pool.withdrawImbalanceWrappedBonus(['10', '10']);
    // -0.5031837243343519
    await pool.withdrawImbalanceWrapped(['10', '10'], 0.1); // slippage = 0.1 %
    // 0xb9e6174695152d7dbe274fec969ffd2d62c994cdbf58455e9954cddd0a8f7189

    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9834.59814450556900711',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '99912.708796226980363129'
    // }
    // { lpToken: '518.450261119283204342', gauge: '0.0' }
})()

Withdraw one coin

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });

    const pool = curve.getPool('mim');

    
    // --- UNDERLYING ---

    
    await pool.wallet.underlyingCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9834.59814450556900711',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9910.573101727634383932',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9910.562953',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '9911.631102'
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '518.450261119283204342', gauge: '0.0' }

    const underlyingExpected = await pool.withdrawOneCoinExpected(10, 'DAI');
    // OR const underlyingExpected = await pool.withdrawOneCoinExpected('10', '0x6B175474E89094C44Da98b954EedeAC495271d0F');
    // OR const underlyingExpected = await pool.withdrawOneCoinExpected('10', 1);
    console.log(underlyingExpected);
    // 10.053583529099204888
    await pool.withdrawOneCoinBonus(10, 'DAI');
    // -0.1256449500769996
    await pool.withdrawOneCoinIsApproved(10);
    // true
    await pool.withdrawOneCoinApprove(10);
    // []
    const underlyingTx = await pool.withdrawOneCoin(10, 'DAI', 0.1);
    // OR const underlyingTx = await pool.withdrawOneCoin('10', '0x6B175474E89094C44Da98b954EedeAC495271d0F');
    // OR const underlyingTx = await pool.withdrawOneCoin('10', 1);
    console.log(underlyingTx);
    //0x5b4c5ec49f53719b5440355439a2cad445935895b5c1034ae6092ebbe17f0328

    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9834.59814450556900711',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9920.62668525673358882',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9910.562953',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '9911.631102'
    // }
    // { lpToken: '508.450261119283204342', gauge: '0.0' }

    
    // --- WRAPPED ---

    
    await pool.wallet.wrappedCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9834.59814450556900711',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '99912.708796226980363129'
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '508.450261119283204342', gauge: '0.0' }

    const wrappedExpected = await pool.withdrawOneCoinWrappedExpected('10', 'MIM');
    // OR const wrappedExpected = await pool.withdrawOneCoinWrappedExpected('10', '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3');
    // OR const wrappedExpected = await pool.withdrawOneCoinWrappedExpected('10', 0);
    console.log(wrappedExpected)
    // 10.066854269984687383
    await pool.withdrawOneCoinWrappedBonus(10, 'MIM');
    // 0.5893939242941038
    const wrappedTx = await pool.withdrawOneCoinWrapped('10', 'MIM', 0.1);
    // OR await pool.withdrawOneCoinWrapped('10', '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3');
    // OR await pool.withdrawOneCoinWrapped('10', 0);
    console.log(wrappedTx);
    // 0xf82af519a3e4f0743c89fd1e93982934f1a2dde721221b00dd474f6b0a24f7f2

    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9844.664998775553694493',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '99912.708796226980363129'
    // }
    // { lpToken: '498.450261119283204342', gauge: '0.0' }
})()

Swap

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });

    const pool = curve.getPool('mim');

    
    // --- UNDERLYING ---

    
    await pool.wallet.underlyingCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9844.882755243317396535',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9930.611305190224186298',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9910.562953',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '9911.631102'
    // }

    const underlyingExpected = await pool.swapExpected('MIM','DAI', 10);
    // OR const underlyingExpected = await pool.swapExpected('0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3', '0x6B175474E89094C44Da98b954EedeAC495271d0F', '10');
    // OR const underlyingExpected = await pool.swapExpected(0, 1, '10');
    console.log(underlyingExpected);
    // 9.984619933234026875
    const underlyingRequired = await pool.swapRequired('MIM', 'DAI', 10);
    // OR const underlyingRequired = await pool.swapRequired('0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3', '0x6B175474E89094C44Da98b954EedeAC495271d0F', '10');
    // OR const underlyingRequired = await pool.swapRequired(0, 1, '10');
    console.log(underlyingRequired);
    //10.049378645129545758
    const underlyingPriceImpact = await pool.swapPriceImpact('MIM','DAI', 10);
    // OR const underlyingPriceImpact = await pool.swapPriceImpact('0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3', '0x6B175474E89094C44Da98b954EedeAC495271d0F', '10');
    // OR const underlyingPriceImpact = await pool.swapPriceImpact(0, 1, '10');
    console.log(underlyingPriceImpact);
    // 0.000026 (as %)
    await pool.swapIsApproved('MIM', 10);
    // true
    await pool.swapApprove('MIM', 10);
    // []
    const swapTx = await pool.swap('MIM','DAI', 10, 0.1);
    // OR const swapTx = await pool.swap('0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3', '0x6B175474E89094C44Da98b954EedeAC495271d0F', '10');
    // OR const swapTx = await pool.swap(0, 1, 10);
    console.log(swapTx);
    // 0xbcd0d1248e6a8571c2a45d4f7095bc1fece479b6e87219cdd7d239c4e1e0ca32

    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9834.882755243317396535',
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9940.595925123458213173',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9910.562953',
    //     '0xdac17f958d2ee523a2206206994597c13d831ec7': '9911.631102'
    // }

    
    // --- WRAPPED ---

    
    await pool.wallet.wrappedCoinBalances();
    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9834.882755243317396535',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '99902.708796226980363129'
    // }

    const wrappedExpected = await pool.swapWrappedExpected('3crv','MIM', 10);
    // OR const wrappedExpected = await pool.swapWrappedExpected('0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490', '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3', '10');
    // OR const wrappedExpected = await pool.swapWrappedExpected(1, 0, '10');
    console.log(wrappedExpected);
    // 10.217756467720521951
    const wrappedRequired = await pool.swapWrappedRequired('3crv', 'MIM', 10);
    // OR const wrappedRequired = await pool.swapWrappedRequired('0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490', '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3', '10');
    // OR const wrappedRequired = await pool.swapWrappedRequired(1, 0, '10');
    console.log(wrappedRequired);
    //9.702940994847188442
    const wrappedPriceImpact = await pool.swapWrappedPriceImpact('3crv','MIM', 10);
    // OR const wrappedPriceImpact = await pool.swapWrappedPriceImpact('0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490', '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3', '10');
    // OR const wrappedPriceImpact = await pool.swapWrappedPriceImpact(1, 0, '10');
    console.log(wrappedPriceImpact);
    // 0.000081 (as %)
    await pool.swapWrappedIsApproved('3crv', 10);
    // true
    await pool.swapWrappedApprove('3crv', 10);
    // []
    const swapWrappedTx = await pool.swapWrapped('3crv','MIM', 10, 0.1);
    // OR const swapWrappedTx = await pool.swapWrapped('0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490', '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3', '10');
    // OR const swapWrappedTx = await pool.swapWrapped(1, 0, '10');
    console.log(swapWrappedTx);
    // 0x59ff5e44f083b57a1f612c1ad5ac7d3fe68b4c753ddd6400ab8bd6437485288c

    // {
    //     '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3': '9845.100511711037918486',
    //     '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490': '99892.708796226980363129'
    // }
})()

Deposit & Stake

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    
    curve.hasDepositAndStake()
    // true
    
    const pool = curve.getPool('compound');
    const amounts = [1000, 1000];

    
    // --- UNDERLYING ---
    
    
    await pool.wallet.underlyingCoinBalances();
    // {
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '10000.0',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '10000.0',
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '0.0', gauge: '0.0' }
    
    await pool.depositAndStakeExpected(amounts);
    // 1820.604572902286288394
    await pool.depositAndStakeBonus(amounts);
    // 0.0030482584681188
    await pool.depositAndStakeIsApproved(amounts);
    // false
    await pool.depositAndStakeApprove(amounts);
    // [
    //     '0xb363c95fb8e63f724d6a05dfa756ede38132ce3fc8faf80306d925856996669c',
    //     '0x53d01fd54fb607091c67f8b39ff9e2e7670396d831b856b1979caaa6ac6ea37b',
    //     '0xd69ca27c30fa6e5ba927d0382987f142895481710439dae358a1daeeb01c7248'
    // ]
    await pool.depositAndStake(amounts);
    // 0x3ec53842120be75f51e907803da844f4d3e8435766e0c25a40700085ed5b56c4

    // {
    //     '0x6b175474e89094c44da98b954eedeac495271d0f': '9000.0',
    //     '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': '9000.0',
    // }
    // { lpToken: '0.0', gauge: '1820.556829935710883568' }

    
    // --- WRAPPED ---
    
    
    await pool.wallet.wrappedCoinBalances();
    // {
    //     '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643': '10000.0',
    //     '0x39aa39c021dfbae8fac545936693ac917d5e7563': '10000.0'
    // }
    await pool.wallet.lpTokenBalances();
    // { lpToken: '0.0', gauge: '1820.556829935710883568' }

    await pool.depositAndStakeWrappedExpected(amounts);
    // 40.328408669183101673
    await pool.depositAndStakeWrappedBonus(amounts);
    // 0.46040576921447873
    await pool.depositAndStakeWrappedIsApproved(amounts);
    // false
    await pool.depositAndStakeWrappedApprove(amounts);
    // [
    //     '0x53035c46f877ed4d156aff5aee0f8e04c0e0701e40651e9e55f41976919b093d',
    //     '0x4743386669a6a21fbe09805ae50e281db22cf518d681ee1e5d0f81a1d761e79b',
    //     '0x8580b6bd88dfd0eeab77480e50d82ba14922fd4b431b0123a7ac425236e1db3a'
    // ]
    await pool.depositAndStakeWrapped(amounts);
    // 0xdb73e3176ab876806f99f71d70ad6ee93d7a865c15faa062ebaba2011b94b315

    // {
    //     '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643': '9000.0',
    //     '0x39aa39c021dfbae8fac545936693ac917d5e7563': '9000.0'
    // }
    // { lpToken: '0.0', gauge: '1860.884096082215274556' }
})();

Router

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    await curve.factory.fetchPools();
    await curve.crvUSDFactory.fetchPools();
    await curve.EYWAFactory.fetchPools();
    await curve.cryptoFactory.fetchPools();
    await curve.twocryptoFactory.fetchPools();
    await curve.tricryptoFactory.fetchPools();
    await curve.stableNgFactory.fetchPools();

    curve.hasRouter();
    // true

    await curve.getBalances(['DAI', 'CRV']);
    // [ '9900.0', '100049.744832225238317557' ]

    const { route, output } = await curve.router.getBestRouteAndOutput('DAI', 'CRV', '1000');
    // OR await curve.router.getBestRouteAndOutput('0x6B175474E89094C44Da98b954EedeAC495271d0F', '0xD533a949740bb3306d119CC777fa900bA034cd52', '1000');
    const expected = await curve.router.expected('DAI', 'CRV', '1000');
    // OR await curve.router.expected('0x6B175474E89094C44Da98b954EedeAC495271d0F', '0xD533a949740bb3306d119CC777fa900bA034cd52', '1000');
    const required = await curve.router.required('DAI', 'CRV', expected);
    // OR await curve.router.required('0x6B175474E89094C44Da98b954EedeAC495271d0F', '0xD533a949740bb3306d119CC777fa900bA034cd52', expected);
    const priceImpact = await curve.router.priceImpact('DAI', 'CRV', '1000');
    // OR await curve.router.priceImpact('0x6B175474E89094C44Da98b954EedeAC495271d0F', '0xD533a949740bb3306d119CC777fa900bA034cd52', '1000');
    const args = curve.router.getArgs(route);

    console.log(route, output, expected, required, priceImpact, args);
    // route = [
    //     {
    //         poolId: 'mim',
    //         swapAddress: '0x5a6a4d54456819380173272a5e8e9b9904bdf41b',
    //         inputCoinAddress: '0x6b175474e89094c44da98b954eedeac495271d0f',
    //         outputCoinAddress: '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3',
    //         swapParams: [ 1, 0, 2, 1, 4 ],
    //         poolAddress: '0x5a6a4d54456819380173272a5e8e9b9904bdf41b',
    //         basePool: '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
    //         baseToken: '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490',
    //         secondBasePool: '0x0000000000000000000000000000000000000000',
    //         secondBaseToken: '0x0000000000000000000000000000000000000000'
    //     },
    //     {
    //         poolId: 'factory-crvusd-6',
    //         swapAddress: '0xbe426b0f37c112dd20d5866769c8034171567b31',
    //         inputCoinAddress: '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3',
    //         outputCoinAddress: '0xf939e0a03fb07f59a73314e73794be0e57ac1b4e',
    //         swapParams: [ 0, 1, 1, 1, 2 ],
    //         poolAddress: '0xbe426b0f37c112dd20d5866769c8034171567b31',
    //         basePool: '0x0000000000000000000000000000000000000000',
    //         baseToken: '0x0000000000000000000000000000000000000000',
    //         secondBasePool: '0x0000000000000000000000000000000000000000',
    //         secondBaseToken: '0x0000000000000000000000000000000000000000'
    //     },
    //     {
    //         poolId: 'factory-tricrypto-4',
    //         swapAddress: '0x4ebdf703948ddcea3b11f675b4d1fba9d2414a14',
    //         inputCoinAddress: '0xf939e0a03fb07f59a73314e73794be0e57ac1b4e',
    //         outputCoinAddress: '0xd533a949740bb3306d119cc777fa900ba034cd52',
    //         swapParams: [ 0, 2, 1, 3, 3 ],
    //         poolAddress: '0x4ebdf703948ddcea3b11f675b4d1fba9d2414a14',
    //         basePool: '0x0000000000000000000000000000000000000000',
    //         baseToken: '0x0000000000000000000000000000000000000000',
    //         secondBasePool: '0x0000000000000000000000000000000000000000',
    //         secondBaseToken: '0x0000000000000000000000000000000000000000'
    //     }
    // ]
    // 
    // output = expected = 2359.161199223806107003
    // required = 999.898950158673335108
    // priceImpact = 0.158012 %
    //
    // args = {
    //     _route: [
    //         '0x6b175474e89094c44da98b954eedeac495271d0f',
    //         '0x5a6a4d54456819380173272a5e8e9b9904bdf41b',
    //         '0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3',
    //         '0xbe426b0f37c112dd20d5866769c8034171567b31',
    //         '0xf939e0a03fb07f59a73314e73794be0e57ac1b4e',
    //         '0x4ebdf703948ddcea3b11f675b4d1fba9d2414a14',
    //         '0xd533a949740bb3306d119cc777fa900ba034cd52',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000'
    //     ],
    //         _swapParams: [
    //         [ 1, 0, 2, 1, 4 ],
    //         [ 0, 1, 1, 1, 2 ],
    //         [ 0, 2, 1, 3, 3 ],
    //         [ 0, 0, 0, 0, 0 ],
    //         [ 0, 0, 0, 0, 0 ]
    //     ],
    //         _pools: [
    //         '0x5a6a4d54456819380173272a5e8e9b9904bdf41b',
    //         '0xbe426b0f37c112dd20d5866769c8034171567b31',
    //         '0x4ebdf703948ddcea3b11f675b4d1fba9d2414a14',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000'
    //     ],
    //         _basePools: [
    //         '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000'
    //     ],
    //         _baseTokens: [
    //         '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000'
    //     ],
    //         _secondBasePools: [
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000'
    //     ],
    //         _secondBaseTokens: [
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000',
    //         '0x0000000000000000000000000000000000000000'
    //     ]
    // }


    await curve.router.isApproved('DAI', 1000);
    // false
    await curve.router.approve('DAI', 1000);
    // [
    //     '0xc111e471715ae6f5437e12d3b94868a5b6542cd7304efca18b5782d315760ae5'
    // ]
    const swapTx = await curve.router.swap('DAI', 'CRV', '1000');
    // OR const swapTx = await curve.router.swap('0x6B175474E89094C44Da98b954EedeAC495271d0F', '0xD533a949740bb3306d119CC777fa900bA034cd52', '1000');
    console.log(swapTx.hash);
    // 0xc7ba1d60871c0295ac5471bb602c37ec0f00a71543b3a041308ebd91833f26ba
    const swappedAmount = await curve.router.getSwappedAmount(swapTx, 'CRV');
    // 1573.668171170839785062

    await curve.getBalances(['DAI', 'CRV']);
    // [ '8900.0', '100428.626463428100672494' ]
})()

Boosting

Lock

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });

    await curve.boosting.getCrv();
    // 100000.0
    await curve.boosting.getLockedAmountAndUnlockTime();
    // { lockedAmount: '0.0', unlockTime: 0 }
    await curve.boosting.getVeCrv();
    // 0.0
    await curve.boosting.getVeCrvPct();
    // 0.000000000000000000

    curve.boosting.isApproved(1000);
    // false 
    curve.boosting.approve(1000);
    // [
    //     '0x07f6daedb705446cb56ab42c18ba9ec5302ef5ed9c7ef0bb5c3c92493abcfc79'
    // ]
    
    curve.boosting.calcUnlockTime(365);  // now (by default) + 365 days, rounded down by WEEK
    // 1657152000000
    await curve.boosting.createLock(1000, 365);
    // 99000.0 CRV
    // { lockedAmount: '1000.0', unlockTime: 1657152000000 }
    // 248.193183980208499221
    // 0.000006190640156035

    await curve.boosting.increaseAmount('500');
    // 98500.0 CRV
    // { lockedAmount: '1500.0', unlockTime: 1657152000000 }
    // 372.289692732093137414 veCRV
    // 0.000009285953543912 veCRV %

    const { unlockTime: currentUnlockTime } = await curve.boosting.getLockedAmountAndUnlockTime();
    curve.boosting.calcUnlockTime(365, currentUnlockTime);  // currentUnlockTime + 365 days, rounded down by WEEK
    // 1688601600000
    await curve.boosting.increaseUnlockTime(365);
    // 98500.0 CRV
    // { lockedAmount: '1500.0', unlockTime: 1688601600000 }
    // 746.262271689452535192 veCRV
    // 0.000018613852077810 veCRV %
})()

Claim fees

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {});

    await curve.getBalances(['3crv']);
    // ['0.0']
    await curve.boosting.claimableFees();
    // 1.30699696445248888

    await curve.boosting.claimFees();

    await curve.getBalances(['3crv']);
    // ['1.30699696445248888']
    await curve.boosting.claimableFees();
    // 0.0
})()

Sidechain

import curve from "@curvefi/api";

(async () => {

    // --- SIDECHAIN ---

    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });

    await curve.boosting.sidechain.lastEthBlock();
    // 16931944
    
    await curve.boosting.sidechain.getAnycallBalance();
    // 0.033837278711248954
    await curve.boosting.sidechain.topUpAnycall(0.1);
    await curve.boosting.sidechain.getAnycallBalance();
    // 0.133837278711248954


    // --- MAINNET (ETHEREUM) ---

    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    await curve.boosting.sidechain.lastBlockSent(137); // Polygon
    // 17038505
    const blockToSend = await curve.boosting.sidechain.blockToSend();  // currentBlock - 128
    // 17377005
    await curve.boosting.sidechain.sendBlockhash(blockToSend, 137); // Polygon

    // --- SIDECHAIN ---
    
    // Wait until blockhash is delivered
    
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    const lastEthBlock = await curve.boosting.sidechain.lastEthBlock();
    // 17377005
    await curve.boosting.sidechain.submitProof(lastEthBlock, "0x33A4622B82D4c04a53e170c638B944ce27cffce3");
})()

CRV. Profit, claim, boosting

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const pool = curve.getPool('compound');

    await pool.depositAndStake([1000, 1000]);
    await pool.crvProfit();
    // {
    //     day: '0.01861607837347995222',
    //     week: '0.13031254861435966551',
    //     month: '0.55848235120439856649',
    //     year: '6.79486860632018255891',
    //     token: '0xd533a949740bb3306d119cc777fa900ba034cd52',
    //     symbol: 'CRV',
    //     price: 0.978134
    // }
    await pool.stats.tokenApy();
    // [ '0.3324', '0.8309' ]
    await pool.userCrvApy();
    // 0.3324
    await pool.userBoost();
    // 1.0

    await curve.boosting.createLock(10000, 365 * 4);
    await pool.depositAndStake([1000, 1000]);
    // crvProfit = {
    //     day: '0.05703837081508656944',
    //     week: '0.39926859570560598606',
    //     month: '1.7111511244525970831',
    //     year: '20.81900534750659784443',
    //     token: '0xd533a949740bb3306d119cc777fa900ba034cd52',
    //     symbol: 'CRV',
    //     price: 0.978134
    // }
    //
    // currentApy = 0.5092
    // boost = 1.532

    await pool.wallet.lpTokenBalances();
    // { lpToken: '0.0', gauge: '3610.795806899650569624' }
    await pool.maxBoostedStake();
    // 1281.660714834072909477

    // ------ Wait some time... ------
    await pool.claimableCrv();
    // 0.4085482040149887
    await pool.claimCrv();
    // claimableCrv = 0.0
})()

Rewards. Profit and claim

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    
    const pool = curve.getPool('susd');

    await pool.rewardTokens();
    // [
    //     {
    //         token: '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f',
    //         symbol: 'SNX',
    //         decimals: 18
    //     }
    // ]
    await pool.depositAndStake([1000, 1000, 1000, 1000]);
    await pool.rewardsProfit();
    // [
    //     {
    //         day: '0.02387645750842563304',
    //         week: '0.16713520255897943129',
    //         month: '0.71629372525276899123',
    //         year: '8.71490699057535605995',
    //         token: '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f',
    //         symbol: 'SNX',
    //         price: 2.61
    //     }
    // ]
    
    // ------ Wait some time... ------
    
    await pool.claimableRewards();
    // [
    //     {
    //         token: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F',
    //         symbol: 'SNX',
    //         amount: '0.000596325465987726'
    //     }
    // ]
    await pool.claimRewards();
    // claimableRewards = [
    //     {
    //         token: '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f',
    //         symbol: 'SNX',
    //         amount: '0.0'
    //     }
    // ]
})()

User balances, base profit and share

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const pool = curve.getPool('frax');

    await pool.deposit([1000, 1000, 1000, 1000]);
    // { lpToken: '3967.761942945398518479', gauge: '0.0' }
    await pool.stake(2000);
    // { lpToken: '1967.761942945398518479', gauge: '2000.0' }

    await pool.userBalances();
    // [
    //     '2489.266644542275414077',
    //     '276.21290758040371998',
    //     '280.160024',
    //     '955.058471'
    // ]
    await pool.userWrappedBalances();
    // [ '2489.266644542275414077', '1479.135765218522838249' ]
    await pool.userLiquidityUSD();
    // 4003.16466431
    await pool.baseProfit();
    // {
    //     day: '0.01476134356908610233',
    //     week: '0.1036132769753159106',
    //     month: '0.44899086689303561258',
    //     year: '5.38789040271642735101374407'
    // }
    await pool.userShare();
    // {
    //     lpUser: '3967.761942945398518479',
    //     lpTotal: '1124490985.047288488832152598',
    //     lpShare: '0.000352849600015116',
    //     gaugeUser: '2000.0',
    //     gaugeTotal: '1123703753.306098922471106555',
    //     gaugeShare: '0.000177982853053192'
    // }
})()

Gas estimation

Every non-constant method has corresponding gas estimation method. Rule: obj.method -> obj.estimateGas.method

Examples

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });
    
    const spender = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7" // 3pool swap address
    await curve.estimateGas.ensureAllowance(["DAI", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"], [1000, 1000], spender);
    // 94523
    
    const pool = curve.getPool('usdn');
    await pool.estimateGas.depositApprove(["1000", "1000", "1000", "1000"]);
    // 186042
    await pool.estimateGas.deposit(["1000", "1000", "1000", "1000"]);
    // 679238
    
    await curve.router.estimateGas.swap('DAI', "WBTC", "1000");
    // 476904
    await curve.boosting.estimateGas.createLock('1000', 365);
    // 324953
})()

Gas estimation L2

Only for OPTIMISM and BASE!

Arbitrium is also L2 network, but for estimateGas should use default method estimateGas, which return Number.

For L2 networks estimateGas return array [L2GasUsed, L1GasUsed], where L2GasUsed - gas estimate for execution transaction in current L2 network, and L1GasUsed - gas estimate for data storage in parent L1 network.

Gas Price in L1 is required to calculate the fee. You can use getGasPriceFromL1 for get Gas Price in L1.

 const L1GasPrice = await curve.getGasPriceFromL1()
 // 23348207475

Calculate fee fee = L2GasUsed*L2GasPrice + L1GasUsed*L1GasPrice

For OP and Base networks you can get L2GasPrice from curve.getGasPriceFromL2

 const L2GasPrice = await curve.getGasPriceFromL2()
 // 13161051

Factory

Fetch new pools from blockchain

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    // Fetch pools from api (if false arg is not passed)
    await curve.factory.fetchPools();
    await curve.crvUSDFactory.fetchPools();
    await curve.EYWAFactory.fetchPools();
    await curve.cryptoFactory.fetchPools();
    await curve.twocryptoFactory.fetchPools();
    await curve.tricryptoFactory.fetchPools();
    await curve.stableNgFactory.fetchPools();

    // Fetch very new pools (that haven't been added to api yet) from blockchain
    await curve.factory.fetchNewPools();
    // [ 'factory-v2-285' ]
    await curve.cryptoFactory.fetchNewPools();
    // [ 'factory-crypto-232' ]
    await curve.twocryptoFactory.fetchNewPools();
    // [ 'factory-twocrypto-2' ]
    await curve.tricryptoFactory.fetchNewPools();
    // [ 'factory-tricrypto-2' ]
    await curve.stableNgFactory.fetchNewPools();
    // [ 'factory-stable-ng-2' ]
})()

Deploy stable plain pool

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const coins = [
        "0x1456688345527bE1f37E9e627DA0837D6f08C925", // USDP
        "0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3", // MIM
        "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0", // LUSD
    ];

    // Deploy pool
    
    const deployPoolTx = await curve.factory.deployPlainPool('Test pool', 'TST', coins, 200, 0.1, 0, 1);
    // {
    //     hash: '0xb84206f6a17488459d8dfc9a9f41ae89c71d1920b7aa87ad2eefd3171ba5166c',
    //     type: 0,
    //     accessList: null,
    //     blockHash: '0xf1c7d05a7cebfe2331cca0e8ce0e7b45aac2097934a23c73f6e0b16fac0a9b5f',
    //     blockNumber: 15839419,
    //     transactionIndex: 0,
    //     confirmations: 1,
    //     from: '0x66aB6D9362d4F35596279692F0251Db635165871',
    //     gasPrice: BigNumber { _hex: '0x00', _isBigNumber: true },
    //     gasLimit: BigNumber { _hex: '0x1037c4', _isBigNumber: true },
    //     to: '0xB9fC157394Af804a3578134A6585C0dc9cc990d4',
    //         value: BigNumber { _hex: '0x00', _isBigNumber: true },
    //     nonce: 12,
    //         data: '0x52f2db69000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000001456688345527be1f37e9e627da0837d6f08c92500000000000000000000000099d8a9c45b2eca8864373a26d1459e3dff1e17f30000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000095465737420706f6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035453540000000000000000000000000000000000000000000000000000000000',
    //     r: '0x0f8f0277c982e1cf3153fd5a63a104a0338bf907fdb270589dc847c6f4b6600d',
    //     s: '0x32e2f279f759673e5254b893539cfe1258338f177e892b46e1edb7b73e869a3d',
    //     v: 38,
    //     creates: null,
    //     chainId: 1,
    //     wait: [Function (anonymous)]
    // }
    const poolAddress = await curve.factory.getDeployedPlainPoolAddress(deployPoolTx);
    // 0xa77b5d170f3aec2f72ca06490a7b9383a70ae5eb

    // Deploy gauge
    
    console.log(curve.factory.gaugeImplementation());
    // 0x5aE854b098727a9f1603A1E21c50D52DC834D846
    
    const deployGaugeTx = await curve.factory.deployGauge(poolAddress);
    // {
    //     hash: '0x8bb0eb63430e6c522c30922a833fee263816ebc0f30367d53ecfe52e17b7c3a0',
    //     type: 0,
    //     accessList: null,
    //     ...
    // }
    const gaugeAddress = await curve.factory.getDeployedGaugeAddress(deployGaugeTx);
    // 0x1400e08f1d9f5bc90ae19acd4bf81beabc9e79de

    // Deposit & Stake

    const poolId = await curve.factory.fetchRecentlyDeployedPool(poolAddress);
    // factory-v2-221
    const pool = curve.getPool(poolId);

    await pool.depositAndStake([10, 10, 10]); // Initial amounts for stable pool must be equal
    const balances = await pool.stats.underlyingBalances();
    // [ '10.0', '10.0', '10.0' ]
})()

Deploy stable-ng plain pool

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const coins = [
        "0xae7ab96520de3a18e5e111b5eaab095312d7fe84", // stETH
        "0xac3e018457b222d93114458476f3e3416abbe38f", // sfrxETH
    ];

    //0 = Standard, 1 = Oracle, 2 = Rebasing, 3 = ERC4626
    const assetTypes = [2, 1] as Array<0 | 1 | 2 | 3>;

    const oracleAddresses = [
        '0x0000000000000000000000000000000000000000',
        '0xac3e018457b222d93114458476f3e3416abbe38f',
    ];

    const methodNames = [
        '',
        'pricePerShare',
    ];
    // OR 
    //const methodNames = [
    //  '0x00000000',
    //  'pricePerShare',
    //];
    
    
    // Deploy pool
    
    const deployPoolTx = await curve.stableNgFactory.deployPlainPool('Test pool', 'test', coins, 5, 0.05, 5, assetTypes, 0, 600, oracleAddresses, methodNames);
    // {
    //     accessList:null
    //     blockHash: "0x981c86a28d1e4a675dae3e14868d62683c02c7906082ba78f5304a45cfd55c38"
    //     blockNumber: 18628729
    //     chainId: 1n
    //     data: "0x5bcd3d83000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000004c4b40000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000095465737420706f6f6c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000474657374000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000ae7ab96520de3a18e5e111b5eaab095312d7fe84000000000000000000000000ac3e018457b222d93114458476f3e3416abbe38f00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d8a452bc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac3e018457b222d93114458476f3e3416abbe38f"
    //     from: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
    //     gasLimit: 7046085n
    //     gasPrice: 0n
    //     hash: "0xcbd866d6c4c6294b33d5797bdbf5666aad99a4f7fd461f472aeb95121929242b"
    //     index: undefined
    //     maxFeePerGas: null
    //     maxPriorityFeePerGas: null
    //     nonce: 565
    //     to: "0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf"
    //     type: 0
    //     value: 0n
    // }
    
    const poolAddress = await curve.stableNgFactory.getDeployedPlainPoolAddress(deployPoolTx);
    // 0x0816bc9ced716008c88bb8940c297e9c9167755e
    
    // Deploy gauge

    const deployGaugeTx = await curve.stableNgFactory.deployGauge(poolAddress);
    // {
    //     hash: '0x8bb0eb63430e6c522c30922a833fee263816ebc0f30367d53ecfe52e17b7c3a0',
    //     type: 0,
    //     accessList: null,
    //     ...
    // }
    const gaugeAddress = await curve.stableNgFactory.getDeployedGaugeAddress(deployGaugeTx);
    // 0x1400e08f1d9f5bc90ae19acd4bf81beabc9e79de

    //For sidechain
    const salt = '15'
    //salt - unical random string
    const deployGaugeSidechain = await curve.stableNgFactory.deployGaugeSidechain(poolAddress, salt);
    // ContractTransactionResponse {
    //     provider: JsonRpcProvider {},
    //     blockNumber: 17393463,
    //     blockHash: '0x7f393493d7eb30b39aeef3118b51925426946eb83b72b18946f0da8c7bec40a0',
    //     ...
    // }
    const gaugeSidechainAddress = await curve.stableNgFactory.getDeployedGaugeAddress(deployGaugeSidechain);
    // 0x60d3d7ebbc44dc810a743703184f062d00e6db7e
    //After that should be deployed mirror gauge on mainnet with same salt
    //const gaugeMirrorTx = await curve.stableNgFactory.deployGaugeMirror(sidechainId, salt);
    //const deployedGaugeMirrorAddress = await curve.stableNgFactory.getDeployedGaugeMirrorAddressByTx(gaugeMirrorTx);
    //OR
    //const deployedGaugeMirrorAddress = await curve.stableNgFactory.getDeployedGaugeMirrorAddress(sidechainId);
})()

Deploy stable meta pool

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const basePool = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7";  // 3pool address
    const coin = "0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3"; // MIM

    // Deploy pool
    
    const deployPoolTx = await curve.factory.deployMetaPool(basePool, 'Test pool', 'TST', coin, 200, 0.1, 0);
    // {
    //     hash: '0xac49dead008ccc04988e513a8502dea35bad721b0c79fa1503054541ee51ea90',
    //     type: 0,
    //     accessList: null,
    //     ...
    // }
    const poolAddress = await curve.factory.getDeployedMetaPoolAddress(deployPoolTx);
    // 0xd87f26c2f658657779e452dd043df9b2751ae7c4

    // Deploy gauge

    console.log(curve.factory.gaugeImplementation());
    // 0x5aE854b098727a9f1603A1E21c50D52DC834D846
    
    const deployGaugeTx = await curve.factory.deployGauge(poolAddress);
    // {
    //     hash: '0x37a53a08d6c71095de8c25bcd4a01b39beec35990f77c7b98355bd064511541f',
    //     type: 0,
    //     accessList: null,
    //     ...
    // }

    const gaugeAddress = await curve.factory.getDeployedGaugeAddress(deployGaugeTx);
    // 0x326290a1b0004eee78fa6ed4f1d8f4b2523ab669

    // Get created pool

    const poolId = await curve.factory.fetchRecentlyDeployedPool(poolAddress);
    // factory-v2-222
    const pool = curve.getPool(poolId);

    // Deposit & Stake Wrapped
    
    await pool.depositAndStakeWrapped([10, 10]); // Initial wrapped amounts for stable metapool must be equal
    const balances = await pool.stats.wrappedBalances();
    // [ '10.0', '10.0' ]

    // Or deposit & Stake Underlying

    // const amounts = pool.metaUnderlyingSeedAmounts(30);
    // [ '30', '10.000000000000000000', '10.000000', '10.000000' ]
    // await pool.depositAndStake(amounts);
    // [ '30.0', '9.272021785560442569', '8.927595', '11.800485' ]
})()

Deploy stable-ng meta pool

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const basePool = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7";  // 3pool address
    const coin = "0xac3e018457b222d93114458476f3e3416abbe38f"; // sfrxETH
    const oracleAddress = '0xac3e018457b222d93114458476f3e3416abbe38f';
    const methodName = 'pricePerShare';

    // Deploy pool

    const deployPoolTx = curve.stableNgFactory.deployMetaPool(basePool, 'Test pool', 'test', coin, 5, 0.05, 5, 600, 1, 0, methodName, oracleAddress);
    // OR const deployPoolTx = curve.stableNgFactory.deployMetaPool(basePool, 'Test pool', 'test',coin, 5, 0.05, 5, 600, 1);
    // {
    //     accessList: null
    //     blockHash: "0xff6f39ee2dae6940d8a061925bd67d9e1e85947f85a7d65c1eef81abdbba023d"
    //     blockNumber: 18628730
    //     chainId: 1n
    //     data: "0xdf8c5d73000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c7000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000ac3e018457b222d93114458476f3e3416abbe38f000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000004c4b400000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000025800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d8a452bc00000000000000000000000000000000000000000000000000000000000000000000000000000000ac3e018457b222d93114458476f3e3416abbe38f00000000000000000000000000000000000000000000000000000000000000095465737420706f6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047465737400000000000000000000000000000000000000000000000000000000"
    //     from: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
    //     gasLimit: 7215295n
    //     gasPrice: 0n
    //     hash: "0xdada197e9264ea5697216e68eaae8304f45d490a10e230023bbb32568df622f5"
    //     index: undefined
    //     maxFeePerGas: null
    //     maxPriorityFeePerGas: null
    //     nonce: 566
    //     to: "0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf"
    //     type: 0
    //     value: 0n
    // }
    const poolAddress = await curve.factory.getDeployedMetaPoolAddress(deployPoolTx);
    // 0xd3797c5da2cf2db453b995fb8f7a9199f4106ad9

    // Deploy gauge

    const deployGaugeTx = await curve.stableNgFactory.deployGauge(poolAddress);
    // {
    //     hash: '0x37a53a08d6c71095de8c25bcd4a01b39beec35990f77c7b98355bd064511541f',
    //     type: 0,
    //     accessList: null,
    //     ...
    // }

    const gaugeAddress = await curve.stableNgFactory.getDeployedGaugeAddress(deployGaugeTx);
    // 0x326290a1b0004eee78fa6ed4f1d8f4b2523ab669

    //For sidechain
    const salt = '15'
    //salt - unical random string
    const deployGaugeSidechain = await curve.stableNgFactory.deployGaugeSidechain(poolAddress, salt);
    // ContractTransactionResponse {
    //     provider: JsonRpcProvider {},
    //     blockNumber: 17393463,
    //     blockHash: '0x7f393493d7eb30b39aeef3118b51925426946eb83b72b18946f0da8c7bec40a0',
    //     ...
    // }
    const gaugeSidechainAddress = await curve.stableNgFactory.getDeployedGaugeAddress(deployGaugeSidechain);
    // 0x60d3d7ebbc44dc810a743703184f062d00e6db7e
    //After that should be deployed mirror gauge on mainnet with same salt
    //const gaugeMirrorTx = await curve.stableNgFactory.deployGaugeMirror(sidechainId, salt);
    //const deployedGaugeMirrorAddress = await curve.stableNgFactory.getDeployedGaugeMirrorAddressByTx(gaugeMirrorTx);
    //OR
    //const deployedGaugeMirrorAddress = await curve.stableNgFactory.getDeployedGaugeMirrorAddress(sidechainId);

Deploy crypto pool

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const coins = [
        "0xC581b735A1688071A1746c968e0798D642EDE491", // EURT
        "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
    ];

    // Deploy pool
    
    const deployPoolTx = await curve.cryptoFactory.deployPool(
        "Test crypto pool",
        "TCP",
        coins,
        400000,
        0.0000725,
        0.25,
        0.45,
        0.000002,
        0.00023,
        0.000146,
        600,
        1500
    );
    // {
    //     hash: '0x406900448e537f2fd5c833a4f62a81305b9567e71f870772e10c72271bd78c37',
    //     type: 0,
    //     accessList: null,
    //     ...
    // }
    const poolAddress = await curve.cryptoFactory.getDeployedPoolAddress(deployPoolTx);
    // 0xe01a9ecdb0aaabe2f12a25a0d289480debf09e89
    
    // Deploy gauge

    console.log(curve.cryptoFactory.gaugeImplementation());
    // 0xdc892358d55d5Ae1Ec47a531130D62151EBA36E5
    
    const deployGaugeTx = await curve.cryptoFactory.deployGauge(poolAddress);
    // {
    //     hash: '0x406900448e537f2fd5c833a4f62a81305b9567e71f870772e10c72271bd78c37',
    //     type: 0,
    //     accessList: null,
    //     ...
    // }
    const gaugeAddress = await curve.factory.getDeployedGaugeAddress(deployGaugeTx);
    // 0x0b4f303a4434647dbf257e3ae4fb134259f3d4fa

    // Deposit & Stake

    const poolId = await curve.cryptoFactory.fetchRecentlyDeployedPool(poolAddress);
    // factory-crypto-155
    const pool = curve.getPool(poolId);

    const amounts = await pool.cryptoSeedAmounts(30); // Initial amounts for crypto pools must have the ratio corresponding to initialPrice
    // [ '30', '0.02' ]
    await pool.depositAndStake(amounts);
    const underlyingBalances = await pool.stats.underlyingBalances();
    // [ '30.0', '0.02' ]
})()

Deploy twocrypto pool

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const coins = [
        "0xC581b735A1688071A1746c968e0798D642EDE491", // EURT
        "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
    ];

    // Deploy pool
    
    const deployPoolTx = await curve.twocryptoFactory.deployPool(
        "Test crypto pool",
        "TCP",
        coins,
        400000,
        0.0000725,
        0.25,
        0.45,
        0.000002,
        0.00023,
        0.000146,
        600,
        1500
    );
    // {
    //     hash: '0x406900448e537f2fd5c833a4f62a81305b9567e71f870772e10c72271bd78c37',
    //     type: 0,
    //     accessList: null,
    //     ...
    // }
    const poolAddress = await curve.twocryptoFactory.getDeployedPoolAddress(deployPoolTx);
    // 0xe01a9ecdb0aaabe2f12a25a0d289480debf09e89
    
    // Deposit & Stake

    const poolId = await curve.twocryptoFactory.fetchRecentlyDeployedPool(poolAddress);
    // factory-twocrypto-155
    const pool = curve.getPool(poolId);

    const amounts = await pool.cryptoSeedAmounts(30); // Initial amounts for crypto pools must have the ratio corresponding to initialPrice
    // [ '30', '0.02' ]
    await pool.depositAndStake(amounts);
    const underlyingBalances = await pool.stats.underlyingBalances();
    // [ '30.0', '0.02' ]
})()

Deploy tricrypto pool

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0 });

    const coins = [
        "0xC581b735A1688071A1746c968e0798D642EDE491", // EURT
        "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
        "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", // WBTC
    ];

    // Deploy pool
    
    const deployPoolTx = await curve.tricryptoFactory.deployPool(
        "Test tricrypto pool",
        "TTP",
        coins,
        400000,
        0.0000725,
        0.25,
        0.45,
        0.000002,
        0.00023,
        0.000146,
        600,
        [1700, 27000]
    );
    // ContractTransactionResponse {
    //     provider: JsonRpcProvider {},
    //     blockNumber: 17393463,
    //     blockHash: '0x7f393493d7eb30b39aeef3118b51925426946eb83b72b18946f0da8c7bec40a0',
    //     ...
    // }
    const poolAddress = await curve.tricryptoFactory.getDeployedPoolAddress(deployPoolTx);
    // 0x2889302a794dA87fBF1D6Db415C1492194663D13
    
    // Deploy gauge

    console.log(curve.tricryptoFactory.gaugeImplementation());
    // 0x5fC124a161d888893529f67580ef94C2784e9233
    
    //For mainnet
    const deployGaugeTx = await curve.tricryptoFactory.deployGauge(poolAddress);
    // ContractTransactionResponse {
    //     provider: JsonRpcProvider {},
    //     blockNumber: 17393463,
    //     blockHash: '0x7f393493d7eb30b39aeef3118b51925426946eb83b72b18946f0da8c7bec40a0',
    //     ...
    // }
    const gaugeAddress = await curve.factory.getDeployedGaugeAddress(deployGaugeTx);
    // 0x60d3d7ebbc44dc810a743703184f062d00e6db7e
    
    //For sidechain
    const salt = '15'
    //salt - unical random string
    const deployGaugeSidechain = await curve.tricryptoFactory.deployGaugeSidechain(poolAddress, salt);
    // ContractTransactionResponse {
    //     provider: JsonRpcProvider {},
    //     blockNumber: 17393463,
    //     blockHash: '0x7f393493d7eb30b39aeef3118b51925426946eb83b72b18946f0da8c7bec40a0',
    //     ...
    // }
    const gaugeSidechainAddress = await curve.factory.getDeployedGaugeAddress(deployGaugeSidechain);
    // 0x60d3d7ebbc44dc810a743703184f062d00e6db7e
    //After that should be deployed mirror gauge on mainnet with same salt
    //const gaugeMirrorTx = await curve.tricryptoFactory.deployGaugeMirror(sidechainId, salt);
    //const deployedGaugeMirrorAddress = await curve.tricryptoFactory.getDeployedGaugeMirrorAddressByTx(gaugeMirrorTx);
    //OR
    //const deployedGaugeMirrorAddress = await curve.tricryptoFactory.getDeployedGaugeMirrorAddress(sidechainId);
    
    // Deposit & Stake

    const poolId = await curve.tricryptoFactory.fetchRecentlyDeployedPool(poolAddress);
    // factory-tricrypto-2
    const pool = curve.getPool(poolId);

    const amounts = await pool.cryptoSeedAmounts(30); // Initial amounts for crypto pools must have the ratio corresponding to initialPrice
    // [ '30', '0.017647058823529412', '0.00111111' ]
    await pool.depositAndStake(amounts);
    const underlyingBalances = await pool.stats.underlyingBalances();
    // [ '30', '0.017647058823529412', '0.00111111' ]
})()

DAO

CRV lock & boosting

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, { gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0 });

    await curve.dao.crvSupplyStats();
    // {
    //     circulating: '937026089.656962436599201901',
    //     locked: '777800358.954796137125672741',
    //     total: '1714826448.611758573724874642',
    //     veCrv: '651092771.450194341958195502',
    //     averageLockTime: '3.3484'
    // }

    await curve.dao.userCrv();
    // 1000000.0
    const lockAmount = 10000;
    await curve.dao.crvLockApprove(lockAmount);
    // [
    //     '0x01a95eba620ce129262b3f11fc9e39d8473242c24579f4030a7d86aeeb5fbec6'
    // ]
    await curve.dao.crvLockIsApproved(lockAmount);
    // true
    curve.dao.calcCrvUnlockTime(365);
    // 1733961600000
    await curve.dao.createCrvLock(lockAmount, 365);
    // 0xcce6abef337aaef4ce95d44f50270c537197b5754a8fb8f148ccb83af5d4fab2
    await curve.dao.userVeCrv();
    // {
    //     veCrv: '2495.771816336870150904',
    //     veCrvPct: '0.000383319071017321',
    //     lockedCrv: '10000.0',
    //     unlockTime: 1733961600000
    // }
    
    const pool = curve.getPool("3pool");
    await pool.depositAndStake([1000, 1000, 1000]);
    // 0x19dc2d8483d09bb1f7fac5a8c4f4a8b425c5ed43b75f6f86bb500dc5532713b6
    await pool.userBoost();
    // 1.0355
    await pool.userCrvApy();
    // 1.3849750259023168
    await pool.userFutureBoost();
    // 1.0355
    await pool.userFutureCrvApy();
    // 1.3847834623550341

    await curve.dao.crvLockApprove(lockAmount);
    // [
    //     '0xfa9130cc15b228f58e833527a5f51a2de16916ce091cca45cd21efb20b41836b'
    // ]
    await curve.dao.increaseCrvLockedAmount(lockAmount);
    // 0x5113d94edab7551acc1bc31721135fb3a897b836f241fff1618aa9e2dd074a62
    //
    // {
    //     veCrv: '4991.53824200910306186',
    //     veCrvPct: '0.000766634619176443',
    //     lockedCrv: '20000.0',
    //     unlockTime: 1733961600000
    // }
    // 
    // Boost: 1.0355
    // APY: 1.3849750259023168
    // Future boost: 1.0709
    // Future APY: 1.4322087422285665


    const { unlockTime } = await curve.dao.userVeCrv();
    curve.dao.calcCrvUnlockTime(365, unlockTime);
    // 1765411200000
    await curve.dao.increaseCrvUnlockTime(365);
    // 0xfd51b54c871a87bcef4299d0cf64a0e23ed941f103d9ca2c9f7dccdd109c5eb3
    //
    // {
    //     veCrv: '9977.839453323127514238',
    //     veCrvPct: '0.001532453177660863',
    //     lockedCrv: '20000.0',
    //     unlockTime: 1765411200000
    // }
    //
    // Boost: 1.0355                   <------- PAY ATTENTION
    // APY: 1.3849750259023168         <------- PAY ATTENTION
    // Future boost: 1.1418            <------- PAY ATTENTION
    // Future APY: 1.526957520361982   <------- PAY ATTENTION

    // Checkpoint to adjust boost
    await pool.claimCrv();
    // 0x2dc4960bfdc9310dc773baf8a5a74942e1829591c65cc3b595b6e6fdf5e2b9bd
    //
    // Boost: 1.1418
    // APY: 1.527150636963076
    // Future boost: 1.1418
    // Future APY: 1.526957517882314

    // --- 2 years time travel ---
    
    await curve.dao.claimableFees();
    // 119.110532749090134743
    await curve.dao.claimFees();
    // 0x90354b4f8c144c194439b18b8c4a87b00b0b62847757d09faa4f475c1c8a12bf
    await curve.getBalances(['3crv']);
    // ['119.110532749090134743']

    // CRV in wallet: 980000.0
    //
    // {
    //     veCrv: '0.0',
    //     veCrvPct: '0',
    //     lockedCrv: '20000.0',
    //     unlockTime: unlockTime: 1765411200000
    // }
    await curve.dao.withdrawLockedCrv();
    // CRV in wallet: 1000000.0
    // { veCrv: '0.0', veCrvPct: '0', lockedCrv: '0.0', unlockTime: 0 }
})()

Gauge voting

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, {gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0});

    const pool1 = curve.getPool("3pool");
    const pool2 = curve.getPool("gusd");
    await curve.dao.crvLockApprove(10000);
    await curve.dao.createCrvLock(10000, 365 * 2);

    await curve.dao.getVotingGaugeList();
    // [
    //     {
    //         poolUrl: 'https://curve.fi/#/ethereum/pools/compound/swap',
    //         network: 'ethereum',
    //         gaugeAddress: '0x7ca5b0a2910b33e9759dc7ddb0413949071d7575',
    //         poolAddress: '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56',
    //         lpTokenAddress: '0x845838df265dcd2c412a1dc9e959c7d08537f8a2',
    //         poolName: 'cDAI+cUSDC (0xA2B4…)',
    //         totalVeCrv: '330001.909569364585795212',
    //         relativeWeight: '0.0518882916913238',
    //         isKilled: false
    //     },
    //     {
    //         poolUrl: 'https://curve.fi/#/ethereum/pools/usdt/swap',
    //         network: 'ethereum',
    //         gaugeAddress: '0xbc89cd85491d81c6ad2954e6d0362ee29fca8f53',
    //         poolAddress: '0x52ea46506b9cc5ef470c5bf89f17dc28bb35d85c',
    //         lpTokenAddress: '0x9fc689ccada600b6df723d9e47d84d76664a1f23',
    //         poolName: 'cDAI+cUSDC+USDT (0x52EA…)',
    //         totalVeCrv: '6223.0651613181174816',
    //         relativeWeight: '0.0',
    //         isKilled: false
    //     },
    //
    //     ...
    //
    // ]
    await curve.dao.voteForGaugeNextTime(pool1.gauge);
    // 864000000
    await curve.dao.voteForGaugeNextTime(pool2.gauge);
    // 864000000
    await curve.dao.voteForGauge(pool1.gauge, 50);  // 50%
    // 0x2397cc3d620595169567a2a45d4edd48b40862a3565613e7ac90d84a2179c068
    await curve.dao.voteForGauge(pool2.gauge, 50);  // 50%
    // 0x4413cca88ea2e3d9d209fd1217117d3f167dc216113691b33f59c8cf880c99a3
    await curve.dao.voteForGaugeNextTime(pool1.gauge);
    // 1703346606000
    await curve.dao.voteForGaugeNextTime(pool2.gauge);
    // 1703346607000
    await curve.dao.userGaugeVotes();
    // {
    //     gauges: [
    //         {
    //             userPower: '50.0',
    //             userVeCrv: '2494.292356354596179115',
    //             userFutureVeCrv: '2494.315742326215669361',
    //             expired: false,
    //             gaugeData: [Object]
    //         },
    //         {
    //             userPower: '50.0',
    //             userVeCrv: '2494.292356354596179115',
    //             userFutureVeCrv: '2494.315742326215669361',
    //             expired: false,
    //             gaugeData: [Object]
    //         }
    //     ],
    //     powerUsed: '100.0',
    //     veCrvUsed: '4988.58471270919235823'
    // }

    await curve.dao.increaseCrvUnlockTime(365 * 2);
    await curve.dao.userGaugeVotes();
    // {
    //     gauges: [
    //         {
    //             userPower: '50.0',
    //             userVeCrv: '2494.286252219639304545',        <------- PAY ATTENTION
    //             userFutureVeCrv: '4936.072662988301764545',  <------- PAY ATTENTION
    //             expired: false,
    //             gaugeData: [Object]
    //         },
    //         {
    //             userPower: '50.0',
    //             userVeCrv: '2494.286252219639304545',        <------- PAY ATTENTION
    //             userFutureVeCrv: '4936.072662988301764545',  <------- PAY ATTENTION
    //             expired: false,
    //             gaugeData: [Object]
    //         }
    //     ],
    //     powerUsed: '100.0',
    //     veCrvUsed: '4988.57250443927860909'
    // }
    // Adjust voting power
    await curve.dao.voteForGauge(pool1.gauge, 50);  // 50%
    // 0x3390467cf45572ce591bc6291a18d909be2826b8e37e07e5a9bcc327a538e6cb
    await curve.dao.voteForGauge(pool2.gauge, 50);  // 50%
    // 0x900f7c1fcf4fd04d0ebd7e9813452e0c5d5ee96b51aaa4ff11aac555accc474c
    await curve.dao.userGaugeVotes();
    // {
    //     gauges: [
    //         {
    //             userPower: '50.0',
    //             userVeCrv: '4987.4342021815414409',          <------- PAY ATTENTION
    //             userFutureVeCrv: '4936.071156773182535736',  <------- PAY ATTENTION
    //             expired: false,
    //             gaugeData: [Object]
    //         },
    //         {
    //             userPower: '50.0',
    //             userVeCrv: '4987.4342021815414409',          <------- PAY ATTENTION
    //             userFutureVeCrv: '4936.071156773182535736',  <------- PAY ATTENTION
    //             expired: false,
    //             gaugeData: [Object]
    //         }
    //     ],
    //     powerUsed: '100.0',
    //     veCrvUsed: '9974.8684043630828818'
    // }
})()

Proposal voting

import curve from "@curvefi/api";

(async () => {
    await curve.init('JsonRpc', {}, {gasPrice: 0, maxFeePerGas: 0, maxPriorityFeePerGas: 0});

    await curve.dao.crvLockApprove(10000);
    await curve.dao.createCrvLock(10000, 365 * 2);

    await curve.dao.getProposalList();
    // [
    //     {
    //         voteId: 0,
    //         voteType: 'PARAMETER',
    //         creator: '0xbe286d574b1ea46f54955bd856821f84dfd20b2e',
    //         startDate: 1597793388,
    //         snapshotBlock: 10687053,
    //         ipfsMetadata: 'First Parameter App Test Vote',
    //         metadata: '',
    //         votesFor: '9979599901699586154315',
    //         votesAgainst: '33980416204516651932',
    //         voteCount: 2,
    //         supportRequired: '600000000000000000',
    //         minAcceptQuorum: '150000000000000000',
    //         totalSupply: '41117044156628562074952',
    //         executed: true
    //     },
    //     {
    //         voteId: 1,
    //         voteType: 'PARAMETER',
    //         creator: '0x431e81e5dfb5a24541b5ff8762bdef3f32f96354',
    //         startDate: 1599399124,
    //         snapshotBlock: 10808256,
    //         ipfsMetadata: 'ipfs:QmdWcs2TZAPsHsnty3tzK4s3HqQDWxY1tdb6SHT3ErZzPY',
    //         metadata: 'Update y pool A from 2000 to 1000, this will allow for a greater % of DAI in the pool',
    //         votesFor: '687697469212361901850006',
    //         votesAgainst: '0',
    //         voteCount: 7,
    //         supportRequired: '600000000000000000',
    //         minAcceptQuorum: '150000000000000000',
    //         totalSupply: '3688475140972975065815236',
    //         executed: true
    //     },
    //
    //     ...
    //
    // ]
    await curve.dao.getProposal("PARAMETER", 21);
    // {
    //     voteId: 21,
    //     voteType: 'PARAMETER',
    //     creator: '0xdedf3000d83bd3550d7d2080cc48a488c93a9442',
    //     startDate: 1631370726,
    //     snapshotBlock: 13205005,
    //     ipfsMetadata: 'ipfs:QmUnYRTB1dUyz9QdX5GueQ6wfKG9J1b1m1RP7EXEYK2Yei',
    //     metadata: '"Ramp A for the OUSD factory pool to 100. Ramping occurs over 1 week.',
    //     votesFor: '138752972260900277168325110',
    //     votesAgainst: '0',
    //     voteCount: 8,
    //     supportRequired: '600000000000000000',
    //     minAcceptQuorum: '150000000000000000',
    //     totalSupply: '273553555220479055026810944',
    //     executed: true,
    //     tx: '0x1daef794f61a1508956b35e037d57a40e60cd290b76b23f7ad251f8bf7fe1f68',
    //     creatorVotingPower: 5.4902571991268546e+23,
    //     script: 'Call via agent (0x4EEb3bA4f221cA16ed4A0cC7254E2E32DF948c5f):\n' +
    // ' ├─ To: 0x8CF8Af108B3B46DDC6AD596aebb917E053F0D72b\n' +
    // ' ├─ Function: ramp_A\n' +
    // " └─ Inputs: [('address', '_pool', '0x87650D7bbfC3A9F10587d7778206671719d9910D'), ('uint256', '_future_A', 100), ('uint256', '_future_time', 1632580319)]\n",
    //     votes: [
    //         {
    //             tx: '0x84443bcf0893c9bbd95581df194be2ce746469c20e4235ec13b9cce157d6d387',
    //             voteId: 21,
    //             voter: '0x989aeb4d175e16225e39e87d0d97a3360524ad80',
    //             supports: true,
    //             stake: 9.280328082090111e+25
    //         },
    //         {
    //             tx: '0x8d1d83db418a5ef9dd6953276e53b518fa1352ec0c9c342317794c6045841014',
    //             voteId: 21,
    //             voter: '0xf89501b77b2fa6329f94f5a05fe84cebb5c8b1a0',
    //             supports: true,
    //             stake: 8.664535170896875e+24
    //         },
    //
    //         ...
    ///
    //     ]
    // }
    await curve.dao.getProposal("OWNERSHIP", 244);
    // {
    //     voteId: 244,
    //     voteType: 'OWNERSHIP',
    //     creator: '0x336c82e4f54e1a6a3adb1fb115c9a6ef3a2b2b11',
    //     startDate: 1671455975,
    //     snapshotBlock: 16218995,
    //     ipfsMetadata: 'ipfs:QmXqpz9bruFwZJ6yAWGF7EUCinc4JWdR6JeghksW2LAJ3X',
    //     metadata: 'Add gauge for GEAR/ETH pool',
    //     votesFor: '359521266860508503522139751',
    //     votesAgainst: '0',
    //     voteCount: 71,
    //     supportRequired: '510000000000000000',
    //     minAcceptQuorum: '300000000000000000',
    //     totalSupply: '563263606319370823403134500',
    //     executed: true,
    //     tx: '0x9550d32f016bfd724f76bdb794925a7ce93c71dd74c7363ff6094f4809c04103',
    //     creatorVotingPower: 2.522832425326041e+21,
    //     script: 'Call via agent (0x40907540d8a6C65c637785e8f8B742ae6b0b9968):\n' +
    // ' ├─ To: 0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB\n' +
    // ' ├─ Function: add_gauge\n' +
    // " └─ Inputs: [('address', 'addr', '0x37Efc3f05D659B30A83cf0B07522C9d08513Ca9d'), ('int128', 'gauge_type', 0), ('uint256', 'weight', 0)]\n",
    //     votes: [
    //         {
    //             tx: '0x0204eb0242be7f44a34dead65ef348b41fc703b825f2904d6cb720236fe2eaa2',
    //             voteId: 244,
    //             voter: '0x7a16ff8270133f063aab6c9977183d9e72835428',
    //             supports: true,
    //             stake: 2.651051910871892e+25
    //         },
    //         {
    //             tx: '0x057871f3c1b679e532b3823517a1204a8ea3f69e021da8c79e397061ff23c789',
    //             voteId: 244,
    //             voter: '0x9b44473e223f8a3c047ad86f387b80402536b029',
    //             supports: true,
    //             stake: 2.6993403110632674e+25
    //         },
    //
    //         ...
    //
    //     ]
    // }
    await curve.dao.voteForProposal("PARAMETER", 21, false);
    await curve.dao.voteForProposal("OWNERSHIP", 244, true);

    await curve.dao.userProposalVotes();
    // [
    //     {
    //         voteId: 21,
    //         voteType: 'PARAMETER',
    //         creator: '0xdedf3000d83bd3550d7d2080cc48a488c93a9442',
    //         startDate: 1631370726,
    //         snapshotBlock: 13205005,
    //         ipfsMetadata: 'ipfs:QmUnYRTB1dUyz9QdX5GueQ6wfKG9J1b1m1RP7EXEYK2Yei',
    //         metadata: '"Ramp A for the OUSD factory pool to 100. Ramping occurs over 1 week.',
    //         votesFor: '138752972260900277168325110',
    //         votesAgainst: '0',
    //         voteCount: 8,
    //         supportRequired: '600000000000000000',
    //         minAcceptQuorum: '150000000000000000',
    //         totalSupply: '273553555220479055026810944',
    //         executed: true,
    //         userVote: 'no'                                                          <------- PAY ATTENTION
    //     },
    //     {
    //         voteId: 244,
    //         voteType: 'OWNERSHIP',
    //         creator: '0x336c82e4f54e1a6a3adb1fb115c9a6ef3a2b2b11',
    //         startDate: 1671455975,
    //         snapshotBlock: 16218995,
    //         ipfsMetadata: 'ipfs:QmXqpz9bruFwZJ6yAWGF7EUCinc4JWdR6JeghksW2LAJ3X',
    //         metadata: 'Add gauge for GEAR/ETH pool',
    //         votesFor: '359521266860508503522139751',
    //         votesAgainst: '0',
    //         voteCount: 71,
    //         supportRequired: '510000000000000000',
    //         minAcceptQuorum: '300000000000000000',
    //         totalSupply: '563263606319370823403134500',
    //         executed: true,
    //         userVote: 'yes'                                                         <------- PAY ATTENTION
    //     },
    // ]
})()

curve-js's People

Contributors

amytsang avatar charlie-eth avatar fedorovdg avatar macket avatar michwill avatar nickkelly1 avatar onlyjousting avatar pioul avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

curve-js's Issues

#err_require_esm issue

Hi guys,

I m trying to install the lib but always get issue like this?
image

Any idea to fix it?

(stableswap-ng coin <—> lp exchange in router) Error "missing revert data" when try to swap a specific token via router on polygon network

swaps from USDC or USDM to BRZ gives a "missing revert data" error via the router on polygon
while swaps the other way works fine, from BRZ to USDM or USDC via the router (the route is the same on both cases).
a tx hash for example swap BRZ to USDM https://polygonscan.com/tx/0x1bca673c7e3e105510b22a09257fd74745cfec70f490996f0ff5bad07e401f92

Image

route is through these pools:
https://curve.fi/#/polygon/pools/factory-stable-ng-0/deposit
https://curve.fi/#/polygon/pools/factory-twocrypto-71/deposit

Support for the experimental syntax 'importAssertions' isn't currently enabled (50:80):

i am unable to import package an getting error:
Compiled with problems:
ERROR in ./node_modules/@curvefi/api/lib/boosting.js

50 | import feeDistributorViewABI from "./constants/abis/fee_distributor_view.json" assert { type: 'json' };


this issue is happening with react js, but not ni node js server.
it looks there is something with bable.


here is environment i am using:
react : v18.2.0
node: v18.17.1
tsx: v5.2.2
"@curvefi/api": "2.46.3",


modified pkg json by adding flag in react script:
"scripts": {
"dev": "node scripts/start.js --experimental-import-assertions",
"start": "serve -s build --experimental-import-assertions",
"build": "node scripts/build.js --experimental-import-assertions",
"test": "node scripts/test.js"
},

ETH Mainnet swap fails with UNPREDICTABLE_GAS_LIMIT

I am using this SDK to initiate swaps. I used code according to your README.

Problem:
I am using this code to initiate swap on ETH Mainnet.
Here is the code. I was swaping ETH for USDC
const { output } = await curve.router.getBestRouteAndOutput(tokenAAdress, tokenBAddress, '0.001'); const txHash = await curve.router.swap(tokenAAdress, tokenBAddress, tradeAmount);

Swaps however are working on Polygon.
Issue:
image

fix/ Incompatibility with forked networks with unusuals ChainID

How to reproduce :

The Curve-js lib cannot connect to forked env on exotics chainID
Deploy and Anvil with chainid: 1337
and try to init the curve object with this ⏬

curve.init(
      "JsonRpc",
      {
        url: "http://localhost;8545",
        network: "localhost",
      },
      { chainId: 1337 }
    );

Error Logs :

image
image

How to solve :

Deploy the same environment with a Chain ID 1
image

Tests throw error since version 2.32.0

Dear Curve community!
I've noticed that the package has been converted to use ESM syntax since version 2.32.0 which is real nice.
However the updated version throws an error when I'm running tests under jest:

Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    node_modules\.pnpm\@[email protected][email protected]\node_modules\@curvefi\api\lib\index.js:37
    import { PoolTemplate, getPool } from "./pools/index.js";
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import curve from '@curvefi/api';
        | ^
      2 | import { NETWORK_CONSTANTS } from '@curvefi/api/lib/curve';
      3 | import { IDict, IProfit } from '@curvefi/api/lib/interfaces';
      4 | import { PoolTemplate } from '@curvefi/api/lib/pools';

      at Runtime.createScriptFromCode (../../node_modules/.pnpm/[email protected]/node_modules/jest-runtime/build/index.js:1495:14)

I'm assuming this issue had been foreseen before you guys made the transition and I'm simply lacking the knowledge on how to make a ESM package running under jest.
Easy googling solutions with tweaks involving babel-jest, modifications in tsconfig and jest.config.ts did not unfortunately help.
I was wondering if anyone already encountered and has that issue resolved.
I'm running tests using pnpm and nx like that:
pnpm exec nx run app-name:test --test-file be/app-name/src/curve/curve.service.spec.ts --skip-nx-cache
It works pretty much same as "npx jest be/app-name/src/curve/curve.service.spec.ts" and throws exactly same error.

Thank you!

resolver or addr is not configured for ENS name

Hi, I'm trying to run the example from here https://github.com/curvefi/curve-js#router-exchange server-side using Alchemy web3 provider but I get the error below when calling routerExchange. Any help is greatly appreciated.

await curve.routerExchange('DAI', 'CRV', '1000');
Error: resolver or addr is not configured for ENS name (argument="name", value="", code=INVALID_ARGUMENT, version=contracts/5.6.1)
    REDACTED {
  reason: 'resolver or addr is not configured for ENS name',
  code: 'INVALID_ARGUMENT',
  argument: 'name',
  value: ''
}

execution reverted

Hi guys,
I could not get to the discord of the website ("impossible to accept invitation" after multiple are you human bs), I'm aware here is probably not the right place to post my issue but i'm guessing the website is using this lib

my issue is that it is impossible to make a swap on curve.fi website :

using frame wallet with librewolf on ubuntu,
trying to swap EURT,
I have approved the contract to use EURT in my wallet, but then, when clicking on swap i get this error :

execution reverted: "Synth exchange suspended. Operation prohibited" (action="estimateGas", data="0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002e53796e74682065786368616e67652073757370656e6465642e204f7065726174696f6e2070726f68696269746564000000000000000000000000000000000000", reason="Synth exchange suspended. Operation prohibited", transaction={ "data": "0x5c9c18e2000000000000000000000000c581b735a1688071a1746c968e0798d642ede491000000000000000000000000b9446c4ef5ebe66268da6700d26f96273de3d5710000000000000000000000001a7e4e63778b4f12a199c062f3efdd288afcbce8000000000000000000000000b37d6c07482bc11cd28a1f11f1a6ad7b66dec93300000000000000000000000096e61422b6a9ba0e068b6c5add4ffabc6a4aae2700000000000000000000000019b080fe1ffa0553469d20ca36219f17fcf03859000000000000000000000000d71ecff9342a5ced620049e616c5035f1db98620000000000000000000000000c011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f00000000000000000000000057ab1ec28d129707052df4df418d58a2d46d5f5100000000000000000000000094cc50e4521bd271c1a997a3a4dc815c2f920b41000000000000000000000000f939e0a03fb07f59a73314e73794be0e57ac1b4e00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000094813da200000000000000000000000000000000000000000000009073319c1d3af50a7b000000000000000000000000b9446c4ef5ebe66268da6700d26f96273de3d571000000000000000000000000b37d6c07482bc11cd28a1f11f1a6ad7b66dec93300000000000000000000000019b080fe1ffa0553469d20ca36219f17fcf03859000000000000000000000000000000000000000000000000000000000000000000000000000000000000000094cc50e4521bd271c1a997a3a4dc815c2f920b41", "from": "0xmyethwalletadrress", "to": "0xF0d4c12A5768D806021F80a262B4d39d26C58b8D" }, invocation=null, revert={ "args": [ "Synth exchange suspended. Operation prohibited" ], "name": "Error", "signature": "Error(string)" }, code=CALL_EXCEPTION, version=6.7.0)

Is it a pool on the trade route that is suspended ? I get the same no matter what other coin I try to swap my EURT to; ie for crvUSD Trade routed through:
3EURpool
EURT
agEUR
agEUR/ibEUR
agEUR
ibEUR
ibEUR/sEUR
ibEUR
sEUR
SNX exchanger
sEUR
sUSD
crvUSD/SUSD
sUSD
crvUSD

anyone here can explain or tell me where to get support please ? thanks !

edit : here is the response from https://api.curve.fi/api/getGas when clicking on swap
the error in the console (same as the one displayed on webpage) is triggered upon receiving the json.

{"success":true,"data":{"gas":{"rapid":42000000000,"fast":42000000000,"standard":42000000000,"slow":42000000000},"eip1559Gas":{"base":42597509537,"prio":[100000000,90000000,80000000,60000000],"max":[51960000000,51950000000,51940000000,51920000000]}},"generatedTimeMs":1702242043160}

API doesn't fetch the Factory Pools

Hi! Have been experiencing this issue since a couple days (this worked before). Hope anyone can help me with this.
Here is a live example of the error: Sandbox

API doesn't fetch the Factory Pools

In order to get some routes I need to fetch the Factory Pools and the Crypto Factory Pools, as stated in the docs, but since a couple days I can't fetch the Factory Pools, instead it throws an error.

Expected Behavior

Connects to the Factory Pools.

Actual Behavior

Throws this error:

TypeError: Cannot read properties of undefined (reading 'map')
     at new Interface (/src/packages/service/node_modules/@ethersproject/abi/lib/interface.js:100:65)
     at BaseContract.getInterface (/src/packages/service/node_modules/@ethersproject/contracts/lib/index.js:764:16)
     at Contract.BaseContract (/src/packages/service/node_modules/@ethersproject/contracts/lib/index.js:616:116)
     at new Contract (/src/packages/service/node_modules/@ethersproject/contracts/lib/index.js:1053:42)
     at /src/packages/service/node_modules/@curvefi/api/lib/factory/factory-api.js:113:27
     at Array.forEach (<anonymous>)
     at Curve.setFactorySwapContracts (/src/packages/service/node_modules/@curvefi/api/lib/factory/factory-api.js:110:21)
     at Curve.<anonymous> (/src/packages/service/node_modules/@curvefi/api/lib/factory/factory-api.js:186:45)
     at step (/src/packages/service/node_modules/@curvefi/api/lib/factory/factory-api.js:44:23)
     at Object.next (/src/packages/service/node_modules/@curvefi/api/lib/factory/factory-api.js:25:53)
     at fulfilled (/src/packages/service/node_modules/@curvefi/api/lib/factory/factory-api.js:16:58)
     at processTicksAndRejections (node:internal/process/task_queues:96:5)

Steps to Reproduce

Step 1: Connect to curve API with the RPC provider and specifying the chain id, 1 in this case (mainnet).

await curve.init(
    'JsonRpc',
    { url: getRpcProvider() },
    {
      chainId: 1,
    },
  );

Step 2: Try the connection to the Factory Pools.

await curve.fetchFactoryPools();

Additional Information

  • To be clear, this worked for me before, but now is throwing the error.
  • The version that I'm using is the 2.23.0, also tried the latest version 2.28.3 but facing the same error.
  • Running this on Mainnet.

Support multiple instances

Currently, it doesn't seem possible to instantiate the package for multiple networks within the same execution context. I wanted to move the routing packages and logic to the backend and provide a service that routes a swap on a given network/rpc, but I believe re-initing the curve package if 2+ requests come in simultaneously might create an issue. Perhaps it would be better to export the whole class rather that a singleton instance? I understand this would require a refactor since the curve instance is imported directly from the module, but it might be worth considering?

Support for xDAI chain?

I created a test bench for the library with xDAI:

import curve from '@curvefi/api';

(async () => {
  await curve.init(
    'JsonRpc',
    {
      url: 'https://rpc.xdaichain.com',
    },
    {
      chainId: 100,
    }
  );

  console.log(await curve.getBalances(['DAI', 'WBTC']));
  // // [ '1000.0', '0.0' ]
})();

Calling any method results in

E:\dxdao\curve-fi-bench\node_modules\@ethersproject\logger\src.ts\index.ts:225
        const error: any = new Error(message);
                           ^
Error: data out-of-bounds (length=0, offset=32, code=BUFFER_OVERRUN, version=abi/5.5.0)
    at Logger.makeError (E:\dxdao\curve-fi-bench\node_modules\@ethersproject\logger\src.ts\index.ts:225:28)
    at Logger.throwError (E:\dxdao\curve-fi-bench\node_modules\@ethersproject\logger\src.ts\index.ts:237:20)
    at Reader._peekBytes (E:\dxdao\curve-fi-bench\node_modules\@ethersproject\abi\src.ts\coders\abstract-coder.ts:184:24)
    at Reader.readBytes (E:\dxdao\curve-fi-bench\node_modules\@ethersproject\abi\src.ts\coders\abstract-coder.ts:198:26)
    at Reader.readValue (E:\dxdao\curve-fi-bench\node_modules\@ethersproject\abi\src.ts\coders\abstract-coder.ts:205:36)
    at NumberCoder.decode (E:\dxdao\curve-fi-bench\node_modules\@ethersproject\abi\src.ts\coders\number.ts:48:28)
    at E:\dxdao\curve-fi-bench\node_modules\@ethersproject\abi\src.ts\coders\array.ts:108:31
    at Array.forEach (<anonymous>)
    at unpack (E:\dxdao\curve-fi-bench\node_modules\@ethersproject\abi\src.ts\coders\array.ts:89:12)
    at TupleCoder.decode (E:\dxdao\curve-fi-bench\node_modules\@ethersproject\abi\src.ts\coders\tuple.ts:58:47) {
  reason: 'data out-of-bounds',
  code: 'BUFFER_OVERRUN',
  length: 0,
  offset: 32
}

My guess is that the library can't resolve the contract address for xDAI.

edit:

Seem like the case. The library points to mainnet's router 0xfA9a30350048B2BF66865ee20363067c66f67e58

Not working on Polygon

(async () => {

    await curve.default.init('JsonRpc', {
        url: "https://polygon-mainnet.g.alchemy.com/v2/tY30vNwB3HhGJIikCtOvL7-Mo-_6f6CY",
        privateKey
    },
    {
        chainId: 137
    });

})();

Trying to use curve-js on polygon chain. Getting the following error. Any input would be of great help.

CURVE-JS IS CONNECTED TO NETWORK: {
  name: 'matic',
  chainId: 137,
  ensAddress: null,
  _defaultProvider: null
}
E:\dev\curve\node_modules\@ethersproject\logger\lib\index.js:199
        var error = new Error(message);
                    ^

Error: resolver or addr is not configured for ENS name (argument="name", value="", code=INVALID_ARGUMENT, version=contracts/5.5.0)
    at Logger.makeError (E:\dev\curve\node_modules\@ethersproject\logger\lib\index.js:199:21)
    at Logger.throwError (E:\dev\curve\node_modules\@ethersproject\logger\lib\index.js:208:20)
    at Logger.throwArgumentError (E:\dev\curve\node_modules\@ethersproject\logger\lib\index.js:211:21)
    at E:\dev\curve\node_modules\@ethersproject\contracts\lib\index.js:109:32
    at step (E:\dev\curve\node_modules\@ethersproject\contracts\lib\index.js:48:23)
    at Object.next (E:\dev\curve\node_modules\@ethersproject\contracts\lib\index.js:29:53)
    at fulfilled (E:\dev\curve\node_modules\@ethersproject\contracts\lib\index.js:20:58)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  reason: 'resolver or addr is not configured for ENS name',
  code: 'INVALID_ARGUMENT',
  argument: 'name',
  value: ''
}

withdrawAndUnstake Missing

Hi, we are currently using curve.js to add liquidity provisioning to our own frontend.

We see that there is a depositAndStake function.

However, we do not see an equivalent unstakeAndWithdraw function. We would like our users to be able to unstake from the gauge and redeem their underlying LP tokens atomically.

Why isn't this included in the library. Oversight? Not possible?

Would it be optimal to add this function to the curve.js package, or create a helper contract to faciliate? Thanks for the help.

Add feature to return calldata only for the swap

  • I have been facing this issue so that a developer can just fetch the calldata instead of carrying out a swap.
  • Will create a PR to solve this. If seems like a useful feature to add to the sdk, it would be nice to consider the PR

Get underlying token prices for the pool

Hello,

I'm using this library to fetch data about current token balances in various pools. I'd like to access also underlying token prices as I saw it's available in the API under endpoint:
GET /api/getPools/<blockchainId>/<registryId>

Is there a way to access poolData[x].coins[x].usdPrice from this SDK?
Looks like everything else is available under pool.stats field.

Unable to set manual gasPrice

async updateFeeData(): Promise<void> {

updateFeeData() is overriding the manual gasPrice or EIP 1559 maxFeePerGas and maxPriorityFeePerGas which is set in the init() as
await curve.init('JsonRpc', {url: providerUrl, privateKey} , { gasPrice: 400, chainId: 137 );

Here the gasPrice is redundant as before calling any function like await curve.exchange(tokenFrom, tokenTo, amount);
there is an internal call to updateFeeData()

await curve.updateFeeData();
which overrides the Fee Data which it gets from the this.provider.getFeeData() which is not always desired.

Testnet mumbai issue

Hi all, I'm using your SDK to obtain SWAP details, and so far if I use it over mainnet polygon it works fine, but with testnet mumbai I have issues like

Error: Coin with address '0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa' is not available

for WETH on mumbai for example

is it supported over testnet or I'm doing something wrong here?

Supporting Viem

Viem library shows better results than ether. It has test coverage, smaller size, clearer errors, and much more. More and more projects will switch to this library.
It would be nice to add support for it so that the curve sdk can be used with Viem.

Arbitrum & Optimism support

Currently, curve.init fails when instantiating with chainId 42161 because the config in NETWORK_CONSTANTS isn't defined. Is this on the roadmap perhaps? Should be straightforward in theory

Issue with Curve Function

Hello, I'm new using Curve Finance API and also in JS. I'm trying to the replicate the same code that has been given in the example - https://github.com/curvefi/curve-js#general-methods
I'm getting this error in my console:

TypeError: curve.getTVL is not a function
    at file:///Users/new.ts:4:17
    at Generator.next (<anonymous>)
    at file:///Users/new.ts:7:71
    at new Promise (<anonymous>)
    at __awaiter (file:///Users/new.ts:3:12)
    at file:///Users/new.ts:3:13
    at file:///Users/new.ts:33:3
    at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:530:24)

Does anyone know why is it showing this error?

New AddressProvider

Contract deployed at: 0x5ffe7FB82894076ECB99A30D6A32e969e6e35E98 on the following networks:
Ethereum, Arbitrum, Optimism, Base, Bsc, Polygon, Fantom, Gnosis, Aurora, Celo, Mantle, Linea, Polygon zkEVM, Scroll, Fraxtal, Avalanche, Kava

ABI needs update:

any js interation on address provider needs to go through the new address.

mappings are fixed across all networks. See Ethereum CurveAddressProvider:

        0: Stableswap Custom Pool Registry
        1: PoolInfo Getters
        2: Exchange Router
        3: Stableswap Metapool Factory
        4: Fee Distributor
        5: Cryptoswap Custom Pool Registry
        6: Twocrypto Factory
        7: Metaregistry
        8: Stableswap crvUSD Factory
        9: 
        10: 
        11: TricryptoNG Factory
        12: StableswapNG Factory
        13: TwocryptoNG Factory
        14: Stableswap Calculations Contract
        15: Cryptoswap calculations Contract
        16: LLAMMA Factory crvUSD
        17: LLAMMA Factory OneWayLending
        18: Rate Provider
        19: CRV Token
        20: Gauge Factory
        21: Ownership Admin
        22: Parameter Admin
        23: Emergency Admin
        24: CurveDAO Vault

Add Stableswap-ng on Xlayer

math: 0x8b3EFBEfa6eD222077455d6f0DCdA3bF4f3F57A6
views: 0xd7E72f3615aa65b92A4DBdC211E296a35512988B
plain_amm: 0x87FE17697D0f14A222e8bEf386a0860eCffDD617
meta_amm: 0x1764ee18e8B3ccA4787249Ceb249356192594585
factory: 0x5eeE3091f747E60a045a2E715a4c71e600e31F6E
zap: 0x604388Bb1159AFd21eB5191cE22b4DeCdEE2Ae22

Calculate amount in based on desired amount out

In the SDKs for uniswap, sushi and other AMM DEXs, they provide price and trade functions based on a desired amount out and will calculate the amount in for you. It looks like curve only provides this functionality for the desired amount in. Is there any interest in supporting functions that take the desired amount out and calculate the amount in for you?

Llama Lend: Create Dashboard Page.

Users are interested in a page like Dashboard for Llama Lend where they can see their boost and rewards tAPR.
Image

Before UI can built this page, we will need these from API first before Dashboard can be built:

  1. User Rewards CRV APY userCrvApy
  2. User Boost function userBoost
  3. User Balances: userLiquidityUSD
  4. claimableFees (For view accounts)

Move this ticket back to FE once it is done.

getBestPoolAndOutput returns not pool address

USDC -> WETH
curve.getBestPoolAndOutput('0x2791bca1f2de4661ed88a30c99a7a9449aa84174', '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619', '1.954569')

return poolAddress '0x0000000000000000000000000000000000000000'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.