UNPKG

@razorlabs/amm-sdk

Version:

🛠 An SDK for building applications on top of RazorDEX.

744 lines (738 loc) • 30.3 kB
'use strict'; var tsSdk = require('@aptos-labs/ts-sdk'); var swapSdkCore = require('@razorlabs/swap-sdk-core'); var invariant5 = require('tiny-invariant'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var invariant5__default = /*#__PURE__*/_interopDefault(invariant5); // src/constants.ts var ZERO_PERCENT = new swapSdkCore.Percent("0"); var ONE_HUNDRED_PERCENT = new swapSdkCore.Percent("1"); var AMM_MODULE_ADDRESS = "0xc4e68f29fa608d2630d11513c8de731b09a975f2f75ea945160491b9bfd36992"; var AMM_SIGNER = "0xf317511756cb5bd755a7456ad900974645788926742b39d81771e17cd54b1c80"; var FACTORY_ADDRESS = `${AMM_MODULE_ADDRESS}::amm_factory`; var FACTORY_ADDRESS_MAP = { [swapSdkCore.ChainId.BARDOCK_TESTNET]: FACTORY_ADDRESS, [swapSdkCore.ChainId.MAINNET]: FACTORY_ADDRESS }; var WMOVE = { [swapSdkCore.ChainId.BARDOCK_TESTNET]: new swapSdkCore.Token( swapSdkCore.ChainId.BARDOCK_TESTNET, tsSdk.AccountAddress.A.toStringLong(), 8, "MOVE", "Move Coin", "https://movementlabs.xyz" ), [swapSdkCore.ChainId.MAINNET]: new swapSdkCore.Token( swapSdkCore.ChainId.MAINNET, tsSdk.AccountAddress.A.toStringLong(), 8, "MOVE", "Move Coin", "https://movementlabs.xyz" ) }; var WNATIVE = { [swapSdkCore.ChainId.BARDOCK_TESTNET]: WMOVE[swapSdkCore.ChainId.BARDOCK_TESTNET], [swapSdkCore.ChainId.MAINNET]: WMOVE[swapSdkCore.ChainId.MAINNET] }; var NATIVE = { [swapSdkCore.ChainId.BARDOCK_TESTNET]: { name: "Move Coin", symbol: "MOVE", decimals: 8 }, [swapSdkCore.ChainId.MAINNET]: { name: "Move Coin", symbol: "MOVE", decimals: 8 } }; // src/trade.ts function isTradeBetter(tradeA, tradeB, minimumDelta = ZERO_PERCENT) { if (tradeA && !tradeB) return false; if (tradeB && !tradeA) return true; if (!tradeA || !tradeB) return void 0; if (tradeA.tradeType !== tradeB.tradeType || !tradeA.inputAmount.currency.equals(tradeB.inputAmount.currency) || !tradeA.outputAmount.currency.equals(tradeB.outputAmount.currency)) { throw new Error("Trades are not comparable"); } if (minimumDelta.equalTo(ZERO_PERCENT)) { return tradeA.executionPrice.lessThan(tradeB.executionPrice); } return tradeA.executionPrice.asFraction.multiply(minimumDelta.add(ONE_HUNDRED_PERCENT)).lessThan(tradeB.executionPrice); } var _Move = class _Move extends swapSdkCore.NativeCurrency { constructor(chainId) { super(chainId, 8, "MOVE", "Move Coin"); } get wrapped() { const wmove = WMOVE[this.chainId]; invariant5__default.default(!!wmove, "WRAPPED"); return wmove; } static onChain(chainId) { if (!this._moveCache[chainId]) { this._moveCache[chainId] = new _Move(chainId); } return this._moveCache[chainId]; } equals(other) { return other.isNative && other.chainId === this.chainId; } }; _Move._moveCache = {}; var Move = _Move; var getPairSeed = (token0, token1) => { const validatedToken0Address = tsSdk.AccountAddress.from(token0.address).toStringLong(); const validatedToken1Address = tsSdk.AccountAddress.from(token1.address).toStringLong(); if (token0.sortsBefore(token1)) { return validatedToken0Address + validatedToken1Address.slice(2); } else { return validatedToken1Address + validatedToken0Address.slice(2); } }; var computePairAddress = ({ tokenA, tokenB }) => { const rawSeed = getPairSeed(tokenA, tokenB); const seed = tsSdk.Hex.fromHexInput(rawSeed).toUint8Array(); const account = tsSdk.AccountAddress.from(AMM_SIGNER); const address = tsSdk.createObjectAddress(account, seed); return address.toString(); }; var Pair = class _Pair { static getAddress(tokenA, tokenB) { return computePairAddress({ tokenA, tokenB }); } constructor(currencyAmountA, tokenAmountB) { const tokenAmounts = currencyAmountA.currency.sortsBefore(tokenAmountB.currency) ? [currencyAmountA, tokenAmountB] : [tokenAmountB, currencyAmountA]; this.liquidityToken = new swapSdkCore.Token( tokenAmounts[0].currency.chainId, _Pair.getAddress(tokenAmounts[0].currency, tokenAmounts[1].currency), 8, "RAZOR LP", `Razor ${tokenAmounts[0].currency.symbol}-${tokenAmounts[1].currency.symbol} LP` ); this.tokenAmounts = tokenAmounts; } /** * Returns true if the token is either token0 or token1 * @param token to check */ involvesToken(token) { return token.equals(this.token0) || token.equals(this.token1); } /** * Returns the current mid price of the pair in terms of token0, i.e. the ratio of reserve1 to reserve0 */ get token0Price() { const result = this.tokenAmounts[1].divide(this.tokenAmounts[0]); return new swapSdkCore.Price(this.token0, this.token1, result.denominator, result.numerator); } /** * Returns the current mid price of the pair in terms of token1, i.e. the ratio of reserve0 to reserve1 */ get token1Price() { const result = this.tokenAmounts[0].divide(this.tokenAmounts[1]); return new swapSdkCore.Price(this.token1, this.token0, result.denominator, result.numerator); } /** * Return the price of the given token in terms of the other token in the pair. * @param token token to return price of */ priceOf(token) { invariant5__default.default(this.involvesToken(token), "TOKEN"); return token.equals(this.token0) ? this.token0Price : this.token1Price; } /** * Returns the chain ID of the tokens in the pair. */ get chainId() { return this.token0.chainId; } get token0() { return this.tokenAmounts[0].currency; } get token1() { return this.tokenAmounts[1].currency; } get reserve0() { return this.tokenAmounts[0]; } get reserve1() { return this.tokenAmounts[1]; } reserveOf(token) { invariant5__default.default(this.involvesToken(token), "TOKEN"); return token.equals(this.token0) ? this.reserve0 : this.reserve1; } getOutputAmount(inputAmount) { invariant5__default.default(this.involvesToken(inputAmount.currency), "TOKEN"); if (this.reserve0.quotient === swapSdkCore.ZERO || this.reserve1.quotient === swapSdkCore.ZERO) { throw new swapSdkCore.InsufficientReservesError(); } const inputReserve = this.reserveOf(inputAmount.currency); const outputReserve = this.reserveOf(inputAmount.currency.equals(this.token0) ? this.token1 : this.token0); const inputAmountWithFee = inputAmount.quotient * swapSdkCore._9975; const numerator = inputAmountWithFee * outputReserve.quotient; const denominator = inputReserve.quotient * swapSdkCore._10000 + inputAmountWithFee; const outputAmount = swapSdkCore.CurrencyAmount.fromRawAmount( inputAmount.currency.equals(this.token0) ? this.token1 : this.token0, numerator / denominator ); if (outputAmount.quotient === swapSdkCore.ZERO) { throw new swapSdkCore.InsufficientInputAmountError(); } return [outputAmount, new _Pair(inputReserve.add(inputAmount), outputReserve.subtract(outputAmount))]; } getInputAmount(outputAmount) { invariant5__default.default(this.involvesToken(outputAmount.currency), "TOKEN"); if (this.reserve0.quotient === swapSdkCore.ZERO || this.reserve1.quotient === swapSdkCore.ZERO || outputAmount.quotient >= this.reserveOf(outputAmount.currency).quotient) { throw new swapSdkCore.InsufficientReservesError(); } const outputReserve = this.reserveOf(outputAmount.currency); const inputReserve = this.reserveOf(outputAmount.currency.equals(this.token0) ? this.token1 : this.token0); const numerator = inputReserve.quotient * outputAmount.quotient * swapSdkCore._10000; const denominator = outputReserve.quotient - outputAmount.quotient * swapSdkCore._9975; const inputAmount = swapSdkCore.CurrencyAmount.fromRawAmount( outputAmount.currency.equals(this.token0) ? this.token1 : this.token0, numerator / denominator + swapSdkCore.ONE ); return [inputAmount, new _Pair(inputReserve.add(inputAmount), outputReserve.subtract(outputAmount))]; } getLiquidityMinted(totalSupply, tokenAmountA, tokenAmountB) { invariant5__default.default(totalSupply.currency.equals(this.liquidityToken), "LIQUIDITY"); const tokenAmounts = tokenAmountA.currency.sortsBefore(tokenAmountB.currency) ? [tokenAmountA, tokenAmountB] : [tokenAmountB, tokenAmountA]; invariant5__default.default(tokenAmounts[0].currency.equals(this.token0) && tokenAmounts[1].currency.equals(this.token1), "TOKEN"); let liquidity; if (totalSupply.quotient === swapSdkCore.ZERO) { liquidity = swapSdkCore.sqrt(tokenAmounts[0].quotient * tokenAmounts[1].quotient) - swapSdkCore.MINIMUM_LIQUIDITY; } else { const amount0 = tokenAmounts[0].quotient * totalSupply.quotient / this.reserve0.quotient; const amount1 = tokenAmounts[1].quotient * totalSupply.quotient / this.reserve1.quotient; liquidity = amount0 <= amount1 ? amount0 : amount1; } if (!(liquidity > swapSdkCore.ZERO)) { throw new swapSdkCore.InsufficientInputAmountError(); } return swapSdkCore.CurrencyAmount.fromRawAmount(this.liquidityToken, liquidity); } getLiquidityValue(token, totalSupply, liquidity, feeOn = false, kLast) { invariant5__default.default(this.involvesToken(token), "TOKEN"); invariant5__default.default(totalSupply.currency.equals(this.liquidityToken), "TOTAL_SUPPLY"); invariant5__default.default(liquidity.currency.equals(this.liquidityToken), "LIQUIDITY"); invariant5__default.default(liquidity.quotient <= totalSupply.quotient, "LIQUIDITY"); let totalSupplyAdjusted; if (!feeOn) { totalSupplyAdjusted = totalSupply; } else { invariant5__default.default(!!kLast, "K_LAST"); const kLastParsed = BigInt(kLast); if (!(kLastParsed === swapSdkCore.ZERO)) { const rootK = swapSdkCore.sqrt(this.reserve0.quotient * this.reserve1.quotient); const rootKLast = swapSdkCore.sqrt(kLastParsed); if (rootK > rootKLast) { const numerator = totalSupply.quotient * (rootK - rootKLast); const denominator = rootK * swapSdkCore.FIVE + rootKLast; const feeLiquidity = numerator / denominator; totalSupplyAdjusted = totalSupply.add(swapSdkCore.CurrencyAmount.fromRawAmount(this.liquidityToken, feeLiquidity)); } else { totalSupplyAdjusted = totalSupply; } } else { totalSupplyAdjusted = totalSupply; } } if (totalSupply.equalTo(0)) { return swapSdkCore.CurrencyAmount.fromRawAmount(token, 0); } return swapSdkCore.CurrencyAmount.fromRawAmount( token, liquidity.quotient * this.reserveOf(token).quotient / totalSupplyAdjusted.quotient ); } }; function getNetworkRPCUrl(chainId) { switch (chainId) { case swapSdkCore.ChainId.BARDOCK_TESTNET: return "https://rpc.sentio.xyz/movement-testnet/v1"; default: return "https://rpc.sentio.xyz/movement/v1"; } } function getNetworkIndexerUrl(chainId) { switch (chainId) { case swapSdkCore.ChainId.BARDOCK_TESTNET: return "https://rpc.sentio.xyz/movement-testnet-indexer/v1/graphql"; default: return "https://rpc.sentio.xyz/movement-indexer/v1/graphql"; } } function getDefaultProvider(chainId) { const config = new tsSdk.AptosConfig({ fullnode: getNetworkRPCUrl(chainId), indexer: getNetworkIndexerUrl(chainId) }); const provider = new tsSdk.Aptos(config); return provider; } var getReserves = (pairAddress) => { return { typeArguments: [], functionArguments: [pairAddress], function: `${AMM_MODULE_ADDRESS}::amm_pair::get_reserves` }; }; var TOKEN_DECIMALS_CACHE = { [swapSdkCore.ChainId.BARDOCK_TESTNET]: {} }; var Fetcher = class { /** * Cannot be constructed. */ constructor() { } /** * Fetch information for a given token on the given chain, using the given provider. * @param chainId chain of the token * @param address address of the token on the chain * @param provider provider used to fetch the token * @param symbol optional symbol of the token * @param name optional name of the token */ static async fetchTokenData(chainId, address, provider = getDefaultProvider(chainId), symbol, name) { const parsedDecimals = typeof TOKEN_DECIMALS_CACHE?.[chainId]?.[address] === "number" ? TOKEN_DECIMALS_CACHE[chainId][address] : await provider.fungibleAsset.getFungibleAssetMetadataByAssetType({ assetType: address }).then(({ decimals }) => { TOKEN_DECIMALS_CACHE = { ...TOKEN_DECIMALS_CACHE, [chainId]: { ...TOKEN_DECIMALS_CACHE?.[chainId], [address]: decimals } }; return decimals; }); return new swapSdkCore.Token(chainId, address, parsedDecimals, symbol, name); } /** * Fetches information about a pair and constructs a pair from the given two tokens. * @param tokenA first token * @param tokenB second token * @param provider the provider to use to fetch the data */ static async fetchPairData(tokenA, tokenB, provider = getDefaultProvider(tokenA.chainId)) { invariant5__default.default(tokenA.chainId === tokenB.chainId, "CHAIN_ID"); const address = Pair.getAddress(tokenA, tokenB); const [reserves0, reserves1, _] = await provider.view({ payload: getReserves(address) }); const balances = tokenA.sortsBefore(tokenB) ? [reserves0, reserves1] : [reserves1, reserves0]; return new Pair( swapSdkCore.CurrencyAmount.fromRawAmount(tokenA, balances[0]), swapSdkCore.CurrencyAmount.fromRawAmount(tokenB, balances[1]) ); } }; var Route = class { constructor(pairs, input, output) { this._midPrice = null; invariant5__default.default(pairs.length > 0, "PAIRS"); const chainId = pairs[0].chainId; invariant5__default.default( pairs.every((pair) => pair.chainId === chainId), "CHAIN_IDS" ); const wrappedInput = input.wrapped; invariant5__default.default(pairs[0].involvesToken(wrappedInput), "INPUT"); invariant5__default.default(typeof output === "undefined" || pairs[pairs.length - 1].involvesToken(output.wrapped), "OUTPUT"); const path = [wrappedInput]; for (const [i, pair] of pairs.entries()) { const currentInput = path[i]; invariant5__default.default(currentInput.equals(pair.token0) || currentInput.equals(pair.token1), "PATH"); const output2 = currentInput.equals(pair.token0) ? pair.token1 : pair.token0; path.push(output2); } this.pairs = pairs; this.path = path; this.input = input; this.output = output; } get midPrice() { if (this._midPrice !== null) return this._midPrice; const prices = []; for (const [i, pair] of this.pairs.entries()) { prices.push( this.path[i].equals(pair.token0) ? new swapSdkCore.Price(pair.reserve0.currency, pair.reserve1.currency, pair.reserve0.quotient, pair.reserve1.quotient) : new swapSdkCore.Price(pair.reserve1.currency, pair.reserve0.currency, pair.reserve1.quotient, pair.reserve0.quotient) ); } const reduced = prices.slice(1).reduce((accumulator, currentValue) => accumulator.multiply(currentValue), prices[0]); return this._midPrice = new swapSdkCore.Price(this.input, this.output, reduced.denominator, reduced.numerator); } get chainId() { return this.pairs[0].chainId; } }; function inputOutputComparator(a, b) { invariant5__default.default(a.inputAmount.currency.equals(b.inputAmount.currency), "INPUT_CURRENCY"); invariant5__default.default(a.outputAmount.currency.equals(b.outputAmount.currency), "OUTPUT_CURRENCY"); if (a.outputAmount.equalTo(b.outputAmount)) { if (a.inputAmount.equalTo(b.inputAmount)) { return 0; } if (a.inputAmount.lessThan(b.inputAmount)) { return -1; } return 1; } if (a.outputAmount.lessThan(b.outputAmount)) { return 1; } return -1; } function tradeComparator(a, b) { const ioComp = inputOutputComparator(a, b); if (ioComp !== 0) { return ioComp; } if (a.priceImpact.lessThan(b.priceImpact)) { return -1; } if (a.priceImpact.greaterThan(b.priceImpact)) { return 1; } return a.route.path.length - b.route.path.length; } var Trade = class _Trade { /** * Constructs an exact in trade with the given amount in and route * @param route route of the exact in trade * @param amountIn the amount being passed in */ static exactIn(route, amountIn) { return new _Trade(route, amountIn, swapSdkCore.TradeType.EXACT_INPUT); } /** * Constructs an exact out trade with the given amount out and route * @param route route of the exact out trade * @param amountOut the amount returned by the trade */ static exactOut(route, amountOut) { return new _Trade(route, amountOut, swapSdkCore.TradeType.EXACT_OUTPUT); } constructor(route, amount, tradeType) { this.route = route; this.tradeType = tradeType; const tokenAmounts = new Array(route.path.length); if (tradeType === swapSdkCore.TradeType.EXACT_INPUT) { invariant5__default.default(amount.currency.equals(route.input), "INPUT"); tokenAmounts[0] = amount.wrapped; for (let i = 0; i < route.path.length - 1; i++) { const pair = route.pairs[i]; const [outputAmount] = pair.getOutputAmount(tokenAmounts[i]); tokenAmounts[i + 1] = outputAmount; } this.inputAmount = swapSdkCore.CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator); this.outputAmount = swapSdkCore.CurrencyAmount.fromFractionalAmount( route.output, tokenAmounts[tokenAmounts.length - 1].numerator, tokenAmounts[tokenAmounts.length - 1].denominator ); } else { invariant5__default.default(amount.currency.equals(route.output), "OUTPUT"); tokenAmounts[tokenAmounts.length - 1] = amount.wrapped; for (let i = route.path.length - 1; i > 0; i--) { const pair = route.pairs[i - 1]; const [inputAmount] = pair.getInputAmount(tokenAmounts[i]); tokenAmounts[i - 1] = inputAmount; } this.inputAmount = swapSdkCore.CurrencyAmount.fromFractionalAmount( route.input, tokenAmounts[0].numerator, tokenAmounts[0].denominator ); this.outputAmount = swapSdkCore.CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator); } this.executionPrice = new swapSdkCore.Price( this.inputAmount.currency, this.outputAmount.currency, this.inputAmount.quotient, this.outputAmount.quotient ); this.priceImpact = swapSdkCore.computePriceImpact(route.midPrice, this.inputAmount, this.outputAmount); } /** * Get the minimum amount that must be received from this trade for the given slippage tolerance * @param slippageTolerance tolerance of unfavorable slippage from the execution price of this trade */ minimumAmountOut(slippageTolerance) { invariant5__default.default(!slippageTolerance.lessThan(swapSdkCore.ZERO), "SLIPPAGE_TOLERANCE"); if (this.tradeType === swapSdkCore.TradeType.EXACT_OUTPUT) { return this.outputAmount; } const slippageAdjustedAmountOut = new swapSdkCore.Fraction(swapSdkCore.ONE).add(slippageTolerance).invert().multiply(this.outputAmount.quotient).quotient; return swapSdkCore.CurrencyAmount.fromRawAmount(this.outputAmount.currency, slippageAdjustedAmountOut); } /** * Get the maximum amount in that can be spent via this trade for the given slippage tolerance * @param slippageTolerance tolerance of unfavorable slippage from the execution price of this trade */ maximumAmountIn(slippageTolerance) { invariant5__default.default(!slippageTolerance.lessThan(swapSdkCore.ZERO), "SLIPPAGE_TOLERANCE"); if (this.tradeType === swapSdkCore.TradeType.EXACT_INPUT) { return this.inputAmount; } const slippageAdjustedAmountIn = new swapSdkCore.Fraction(swapSdkCore.ONE).add(slippageTolerance).multiply(this.inputAmount.quotient).quotient; return swapSdkCore.CurrencyAmount.fromRawAmount(this.inputAmount.currency, slippageAdjustedAmountIn); } /** * Given a list of pairs, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token * amount to an output token, making at most `maxHops` hops. * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting * the amount in among multiple routes. * @param pairs the pairs to consider in finding the best trade * @param nextAmountIn exact amount of input currency to spend * @param currencyOut the desired currency out * @param maxNumResults maximum number of results to return * @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pair * @param currentPairs used in recursion; the current list of pairs * @param currencyAmountIn used in recursion; the original value of the currencyAmountIn parameter * @param bestTrades used in recursion; the current list of best trades */ static bestTradeExactIn(pairs, currencyAmountIn, currencyOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPairs = [], nextAmountIn = currencyAmountIn, bestTrades = []) { invariant5__default.default(pairs.length > 0, "PAIRS"); invariant5__default.default(maxHops > 0, "MAX_HOPS"); invariant5__default.default(currencyAmountIn === nextAmountIn || currentPairs.length > 0, "INVALID_RECURSION"); const amountIn = nextAmountIn.wrapped; const tokenOut = currencyOut.wrapped; for (let i = 0; i < pairs.length; i++) { const pair = pairs[i]; if (!pair.token0.equals(amountIn.currency) && !pair.token1.equals(amountIn.currency)) continue; if (pair.reserve0.equalTo(swapSdkCore.ZERO) || pair.reserve1.equalTo(swapSdkCore.ZERO)) continue; let amountOut; try { ; [amountOut] = pair.getOutputAmount(amountIn); } catch (error) { if (error.isInsufficientInputAmountError) { continue; } throw error; } if (amountOut.currency.equals(tokenOut)) { swapSdkCore.sortedInsert( bestTrades, new _Trade( new Route([...currentPairs, pair], currencyAmountIn.currency, currencyOut), currencyAmountIn, swapSdkCore.TradeType.EXACT_INPUT ), maxNumResults, tradeComparator ); } else if (maxHops > 1 && pairs.length > 1) { const pairsExcludingThisPair = pairs.slice(0, i).concat(pairs.slice(i + 1, pairs.length)); _Trade.bestTradeExactIn( pairsExcludingThisPair, currencyAmountIn, currencyOut, { maxNumResults, maxHops: maxHops - 1 }, [...currentPairs, pair], amountOut, bestTrades ); } } return bestTrades; } /** * Return the execution price after accounting for slippage tolerance * @param slippageTolerance the allowed tolerated slippage */ worstExecutionPrice(slippageTolerance) { return new swapSdkCore.Price( this.inputAmount.currency, this.outputAmount.currency, this.maximumAmountIn(slippageTolerance).quotient, this.minimumAmountOut(slippageTolerance).quotient ); } /** * similar to the above method but instead targets a fixed output amount * given a list of pairs, and a fixed amount out, returns the top `maxNumResults` trades that go from an input token * to an output token amount, making at most `maxHops` hops * note this does not consider aggregation, as routes are linear. it's possible a better route exists by splitting * the amount in among multiple routes. * @param pairs the pairs to consider in finding the best trade * @param currencyIn the currency to spend * @param nextAmountOut the exact amount of currency out * @param maxNumResults maximum number of results to return * @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pair * @param currentPairs used in recursion; the current list of pairs * @param currencyAmountOut used in recursion; the original value of the currencyAmountOut parameter * @param bestTrades used in recursion; the current list of best trades */ static bestTradeExactOut(pairs, currencyIn, currencyAmountOut, { maxNumResults = 3, maxHops = 3 } = {}, currentPairs = [], nextAmountOut = currencyAmountOut, bestTrades = []) { invariant5__default.default(pairs.length > 0, "PAIRS"); invariant5__default.default(maxHops > 0, "MAX_HOPS"); invariant5__default.default(currencyAmountOut === nextAmountOut || currentPairs.length > 0, "INVALID_RECURSION"); const amountOut = nextAmountOut.wrapped; const tokenIn = currencyIn.wrapped; for (let i = 0; i < pairs.length; i++) { const pair = pairs[i]; if (!pair.token0.equals(amountOut.currency) && !pair.token1.equals(amountOut.currency)) continue; if (pair.reserve0.equalTo(swapSdkCore.ZERO) || pair.reserve1.equalTo(swapSdkCore.ZERO)) continue; let amountIn; try { ; [amountIn] = pair.getInputAmount(amountOut); } catch (error) { if (error.isInsufficientReservesError) { continue; } throw error; } if (amountIn.currency.equals(tokenIn)) { swapSdkCore.sortedInsert( bestTrades, new _Trade( new Route([pair, ...currentPairs], currencyIn, currencyAmountOut.currency), currencyAmountOut, swapSdkCore.TradeType.EXACT_OUTPUT ), maxNumResults, tradeComparator ); } else if (maxHops > 1 && pairs.length > 1) { const pairsExcludingThisPair = pairs.slice(0, i).concat(pairs.slice(i + 1, pairs.length)); _Trade.bestTradeExactOut( pairsExcludingThisPair, currencyIn, currencyAmountOut, { maxNumResults, maxHops: maxHops - 1 }, [pair, ...currentPairs], amountIn, bestTrades ); } } return bestTrades; } }; var _Native = class _Native extends swapSdkCore.NativeCurrency { constructor({ chainId, decimals, name, symbol }) { super(chainId, decimals, symbol, name); } get wrapped() { const wnative = WNATIVE[this.chainId]; invariant5__default.default(!!wnative, "WRAPPED"); return wnative; } static onChain(chainId) { if (chainId in this.cache) { return this.cache[chainId]; } invariant5__default.default(!!NATIVE[chainId], "NATIVE_CURRENCY"); const { decimals, name, symbol } = NATIVE[chainId]; return this.cache[chainId] = new _Native({ chainId, decimals, symbol, name }); } equals(other) { return other.isNative && other.chainId === this.chainId; } }; _Native.cache = {}; var Native = _Native; var Router = class { /** * Cannot be constructed. */ constructor() { } /** * Produces the on-chain method name to call and the hex encoded parameters to pass as arguments for a given trade. * @param trade to produce call parameters for * @param options options for the call parameters */ static swapCallParameters(trade, options) { const moveIn = trade.inputAmount.currency.isNative; const moveOut = trade.outputAmount.currency.isNative; invariant5__default.default(!(moveIn && moveOut), "MOVE_IN_OUT"); invariant5__default.default(!("ttl" in options) || options.ttl > 0, "TTL"); const to = options.recipient; const amountIn = Number(trade.maximumAmountIn(options.allowedSlippage).quotient.toString()); const amountOut = Number(trade.minimumAmountOut(options.allowedSlippage).quotient.toString()); const path = trade.route.path.map((token) => token.address); const deadline = "ttl" in options ? Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3) + options.ttl : options.deadline; let methodName; let args; switch (trade.tradeType) { case swapSdkCore.TradeType.EXACT_INPUT: if (moveIn) { methodName = "swap_exact_move_for_tokens"; args = [amountIn, amountOut, path, to, deadline]; } else if (moveOut) { methodName = "swap_exact_tokens_for_move"; args = [amountIn, amountOut, path, to, deadline]; } else { methodName = "swap_exact_tokens_for_tokens"; args = [amountIn, amountOut, path, to, deadline]; } break; case swapSdkCore.TradeType.EXACT_OUTPUT: if (moveIn) { methodName = "swap_move_for_exact_tokens"; args = [amountIn, amountOut, path, to, deadline]; } else if (moveOut) { methodName = "swap_tokens_for_exact_move"; args = [amountOut, amountIn, path, to, deadline]; } else { methodName = "swap_tokens_for_exact_tokens"; args = [amountOut, amountIn, path, to, deadline]; } break; } return { methodName, args }; } }; exports.AMM_MODULE_ADDRESS = AMM_MODULE_ADDRESS; exports.AMM_SIGNER = AMM_SIGNER; exports.FACTORY_ADDRESS = FACTORY_ADDRESS; exports.FACTORY_ADDRESS_MAP = FACTORY_ADDRESS_MAP; exports.Fetcher = Fetcher; exports.Move = Move; exports.NATIVE = NATIVE; exports.Native = Native; exports.ONE_HUNDRED_PERCENT = ONE_HUNDRED_PERCENT; exports.Pair = Pair; exports.Route = Route; exports.Router = Router; exports.Trade = Trade; exports.WMOVE = WMOVE; exports.WNATIVE = WNATIVE; exports.ZERO_PERCENT = ZERO_PERCENT; exports.computePairAddress = computePairAddress; exports.getDefaultProvider = getDefaultProvider; exports.getNetworkIndexerUrl = getNetworkIndexerUrl; exports.getNetworkRPCUrl = getNetworkRPCUrl; exports.getReserves = getReserves; exports.inputOutputComparator = inputOutputComparator; exports.isTradeBetter = isTradeBetter; exports.tradeComparator = tradeComparator; Object.keys(swapSdkCore).forEach(function (k) { if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, { enumerable: true, get: function () { return swapSdkCore[k]; } }); }); //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map