import { Protocol } from '@uniswap/router-sdk';
import { Token, CurrencyAmount } from '@uniswap/sdk-core';
import { ChainId, StaticV2SubgraphProvider, UniswapMulticallProvider, OnChainQuoteProvider, AlphaRouter, routeAmountsToString } from '@uniswap/smart-order-router';
import JSBI from 'jsbi';
import { i as isExactInput, N as NO_ROUTE } from './index-6ef8305b.js';
import 'buffer';
import 'jotai';
import 'jotai/utils';
import 'react';
import 'jotai/immer';
import 'tiny-invariant';
import '@uniswap/v2-sdk';
import '@uniswap/v3-sdk';
import '@ethersproject/units';
import '@ethersproject/abi';
import '@ethersproject/providers';
import '@web3-react/core';
import '@web3-react/eip1193';
import '@web3-react/empty';
import '@web3-react/url';
import '@web3-react/types';
import 'react/jsx-dev-runtime';
import '@uniswap/redux-multicall';
import '@ethersproject/address';
import '@ethersproject/constants';
import '@ethersproject/contracts';
import '@reduxjs/toolkit/query/react';
import '@reduxjs/toolkit';
import 'qs';
import 'ethers/lib/utils';
import 'firebase/database';
import 'firebase/app';
import 'ethers';
import '@brydge-network/token-list';
import '@ethersproject/hash';
import 'cids';
import 'multicodec';
import 'multihashes';
import 'polished';
import 'styled-components';
import 'wcag-contrast';
import 'rebass';
import 'react-feather';
import 'wicg-inert';
import 'react-dom';
import 'popper-max-size-modifier';
import 'react-popper';
import '@babel/runtime/helpers/slicedToArray';
import '@babel/runtime/helpers/defineProperty';
import 'node-vibrant/lib/bundle.js';
import 'setimmediate';
import '@babel/runtime/helpers/classCallCheck';
import '@babel/runtime/helpers/createClass';
import '@babel/runtime/helpers/inherits';
import '@babel/runtime/helpers/possibleConstructorReturn';
import '@babel/runtime/helpers/getPrototypeOf';
import '@babel/runtime/helpers/objectWithoutProperties';
import 'react-virtualized-auto-sizer';
import 'react-window';
import '@ethersproject/bytes';
import '@ethersproject/bignumber';
import 'make-plural/plurals';
import 'react-redux';
import 'redux';

const AUTO_ROUTER_SUPPORTED_CHAINS = Object.values(ChainId).filter(chainId => Number.isInteger(chainId));
function isAutoRouterSupportedChain(chainId) {
  return Boolean(chainId && AUTO_ROUTER_SUPPORTED_CHAINS.includes(chainId));
}

/** A cache of AlphaRouters, which must be initialized to a specific chain/provider. */
const routersCache = new WeakMap();
function getRouter(chainId, provider) {
  const routers = routersCache.get(provider) || {};
  const cached = routers[chainId];
  if (cached) return cached;

  // V2 is unsupported for chains other than mainnet.
  // TODO(zzmp): Upstream to @uniswap/smart-order-router, exporting an enum of supported v2 chains for clarity.
  let v2SubgraphProvider;
  if (chainId !== ChainId.MAINNET) {
    v2SubgraphProvider = new StaticV2SubgraphProvider(chainId);
  }

  // V3 computes on-chain, so the quoter must have gas limits appropriate to the provider.
  // Most defaults are fine, but polygon needs a lower gas limit.
  // TODO(zzmp): Upstream to @uniswap/smart-order-router, possibly making this easier to modify
  // (eg allowing configuration without an instance to avoid duplicating multicall2Provider).
  let onChainQuoteProvider;
  let multicall2Provider;
  if ([ChainId.POLYGON, ChainId.POLYGON_MUMBAI].includes(chainId)) {
    multicall2Provider = new UniswapMulticallProvider(chainId, provider, 375_000);
    // See https://github.com/Uniswap/smart-order-router/blob/98c58bdee9981fd9ffac9e7d7a97b18302d5f77a/src/routers/alpha-router/alpha-router.ts#L464-L487
    onChainQuoteProvider = new OnChainQuoteProvider(chainId, provider, multicall2Provider, {
      retries: 2,
      minTimeout: 100,
      maxTimeout: 1000
    }, {
      multicallChunk: 10,
      gasLimitPerCall: 5_000_000,
      quoteMinSuccessRate: 0.1
    }, {
      gasLimitOverride: 5_000_000,
      multicallChunk: 5
    }, {
      gasLimitOverride: 6_250_000,
      multicallChunk: 4
    });
  }
  const router = new AlphaRouter({
    chainId,
    provider,
    v2SubgraphProvider,
    multicall2Provider,
    onChainQuoteProvider
  });
  routers[chainId] = router;
  routersCache.set(provider, routers);
  return router;
}
async function getQuote(_ref, router, routerConfig) {
  let {
    tradeType,
    chainId,
    tokenIn,
    tokenOut,
    amount: amountRaw
  } = _ref;
  const currencyIn = new Token(tokenIn.chainId, tokenIn.address, tokenIn.decimals, tokenIn.symbol);
  const currencyOut = new Token(tokenOut.chainId, tokenOut.address, tokenOut.decimals, tokenOut.symbol);
  const baseCurrency = isExactInput(tradeType) ? currencyIn : currencyOut;
  const quoteCurrency = isExactInput(tradeType) ? currencyOut : currencyIn;
  const amount = CurrencyAmount.fromRawAmount(baseCurrency, JSBI.BigInt(amountRaw));
  const route = await router.route(amount, quoteCurrency, tradeType, /*swapConfig=*/undefined, routerConfig);
  if (!route) return NO_ROUTE;
  return transformSwapRouteToGetQuoteResult({
    ...route,
    routeString: routeAmountsToString(route.route)
  });
}
async function getClientSideQuote(_ref2, routerConfig) {
  let {
    tokenInAddress,
    tokenInChainId,
    tokenInDecimals,
    tokenInSymbol,
    tokenOutAddress,
    tokenOutChainId,
    tokenOutDecimals,
    tokenOutSymbol,
    amount,
    tradeType,
    provider
  } = _ref2;
  if (!isAutoRouterSupportedChain(tokenInChainId)) {
    throw new Error(`Router does not support this token's chain (chainId: ${tokenInChainId}).`);
  }
  const router = getRouter(tokenInChainId, provider);
  return getQuote({
    tradeType,
    chainId: tokenInChainId,
    tokenIn: {
      address: tokenInAddress,
      chainId: tokenInChainId,
      decimals: tokenInDecimals,
      symbol: tokenInSymbol
    },
    tokenOut: {
      address: tokenOutAddress,
      chainId: tokenOutChainId,
      decimals: tokenOutDecimals,
      symbol: tokenOutSymbol
    },
    amount
  }, router, routerConfig);
}

// from routing-api (https://github.com/Uniswap/routing-api/blob/main/lib/handlers/quote/quote.ts#L243-L311)
function transformSwapRouteToGetQuoteResult(_ref3) {
  let {
    quote,
    quoteGasAdjusted,
    route,
    routeString,
    estimatedGasUsed,
    estimatedGasUsedQuoteToken,
    estimatedGasUsedUSD,
    gasPriceWei,
    methodParameters,
    blockNumber,
    trade: {
      tradeType,
      inputAmount,
      outputAmount
    }
  } = _ref3;
  const routeResponse = [];
  for (const subRoute of route) {
    const {
      amount,
      quote,
      tokenPath
    } = subRoute;
    if (subRoute.protocol === Protocol.V3) {
      const pools = subRoute.route.pools;
      const curRoute = [];
      for (let i = 0; i < pools.length; i++) {
        const nextPool = pools[i];
        const tokenIn = tokenPath[i];
        const tokenOut = tokenPath[i + 1];
        let edgeAmountIn = undefined;
        if (i === 0) {
          edgeAmountIn = isExactInput(tradeType) ? amount.quotient.toString() : quote.quotient.toString();
        }
        let edgeAmountOut = undefined;
        if (i === pools.length - 1) {
          edgeAmountOut = isExactInput(tradeType) ? quote.quotient.toString() : amount.quotient.toString();
        }
        curRoute.push({
          type: 'v3-pool',
          tokenIn: {
            chainId: tokenIn.chainId,
            decimals: tokenIn.decimals,
            address: tokenIn.address,
            symbol: tokenIn.symbol
          },
          tokenOut: {
            chainId: tokenOut.chainId,
            decimals: tokenOut.decimals,
            address: tokenOut.address,
            symbol: tokenOut.symbol
          },
          fee: nextPool.fee.toString(),
          liquidity: nextPool.liquidity.toString(),
          sqrtRatioX96: nextPool.sqrtRatioX96.toString(),
          tickCurrent: nextPool.tickCurrent.toString(),
          amountIn: edgeAmountIn,
          amountOut: edgeAmountOut
        });
      }
      routeResponse.push(curRoute);
    } else if (subRoute.protocol === Protocol.V2) {
      const pools = subRoute.route.pairs;
      const curRoute = [];
      for (let i = 0; i < pools.length; i++) {
        const nextPool = pools[i];
        const tokenIn = tokenPath[i];
        const tokenOut = tokenPath[i + 1];
        let edgeAmountIn = undefined;
        if (i === 0) {
          edgeAmountIn = isExactInput(tradeType) ? amount.quotient.toString() : quote.quotient.toString();
        }
        let edgeAmountOut = undefined;
        if (i === pools.length - 1) {
          edgeAmountOut = isExactInput(tradeType) ? quote.quotient.toString() : amount.quotient.toString();
        }
        const reserve0 = nextPool.reserve0;
        const reserve1 = nextPool.reserve1;
        curRoute.push({
          type: 'v2-pool',
          tokenIn: {
            chainId: tokenIn.chainId,
            decimals: tokenIn.decimals,
            address: tokenIn.address,
            symbol: tokenIn.symbol
          },
          tokenOut: {
            chainId: tokenOut.chainId,
            decimals: tokenOut.decimals,
            address: tokenOut.address,
            symbol: tokenOut.symbol
          },
          reserve0: {
            token: {
              chainId: reserve0.currency.wrapped.chainId,
              decimals: reserve0.currency.wrapped.decimals,
              address: reserve0.currency.wrapped.address,
              symbol: reserve0.currency.wrapped.symbol
            },
            quotient: reserve0.quotient.toString()
          },
          reserve1: {
            token: {
              chainId: reserve1.currency.wrapped.chainId,
              decimals: reserve1.currency.wrapped.decimals,
              address: reserve1.currency.wrapped.address,
              symbol: reserve1.currency.wrapped.symbol
            },
            quotient: reserve1.quotient.toString()
          },
          amountIn: edgeAmountIn,
          amountOut: edgeAmountOut
        });
      }
      routeResponse.push(curRoute);
    }
  }
  const amount = isExactInput(tradeType) ? inputAmount : outputAmount;
  return {
    methodParameters,
    blockNumber: blockNumber.toString(),
    amount: amount.quotient.toString(),
    amountDecimals: amount.toExact(),
    quote: quote.quotient.toString(),
    quoteDecimals: quote.toExact(),
    quoteGasAdjusted: quoteGasAdjusted.quotient.toString(),
    quoteGasAdjustedDecimals: quoteGasAdjusted.toExact(),
    gasUseEstimateQuote: estimatedGasUsedQuoteToken.quotient.toString(),
    gasUseEstimateQuoteDecimals: estimatedGasUsedQuoteToken.toExact(),
    gasUseEstimate: estimatedGasUsed.toString(),
    gasUseEstimateUSD: estimatedGasUsedUSD.toExact(),
    gasPriceWei: gasPriceWei.toString(),
    route: routeResponse,
    routeString
  };
}

export { getClientSideQuote, transformSwapRouteToGetQuoteResult };
//# sourceMappingURL=clientSideSmartOrderRouter-b35481d9.js.map
