UNPKG

@iguanadex/sdk

Version:

🛠 An SDK for building applications on top of IguanaDEX.

1,572 lines (1,563 loc) • 58.2 kB
'use strict'; var chains = require('@iguanadex/chains'); var swapSdkCore = require('@iguanadex/swap-sdk-core'); var invariant5 = require('tiny-invariant'); var viem = require('viem'); var warning = require('tiny-warning'); var chains$1 = require('viem/chains'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var invariant5__default = /*#__PURE__*/_interopDefault(invariant5); var warning__default = /*#__PURE__*/_interopDefault(warning); // src/constants.ts function validateAndParseAddress(address) { try { const checksummedAddress = viem.getAddress(address); warning__default.default(address === checksummedAddress, `${address} is not checksummed.`); return checksummedAddress; } catch (error) { invariant5__default.default(false, `${address} is not a valid address.`); } } // src/entities/token.ts var ERC20Token = class extends swapSdkCore.Token { constructor(chainId, address, decimals, symbol, name, projectLink) { super(chainId, validateAndParseAddress(address), decimals, symbol, name, projectLink); } }; var OnRampCurrency = class extends swapSdkCore.BaseCurrency { constructor(chainId, address, decimals, symbol, name, projectLink) { super(chainId, decimals, symbol, name); this.address = address; this.projectLink = projectLink; this.isNative = address === "0x" && true; this.isToken = address !== "0x" && true; } /** * Returns true if the two tokens are equivalent, i.e. have the same chainId and address. * @param other other token to compare */ equals(other) { return other.isToken && this.chainId === other.chainId && this.address === other.address; } /** * Returns true if the address of this token sorts before the address of the other token * @param other other token to compare * @throws if the tokens have the same address * @throws if the tokens are on different chains */ sortsBefore(other) { if (!other.isToken) return false; invariant5__default.default(this.chainId === other.chainId, "CHAIN_IDS"); invariant5__default.default(this.address !== other.address, "ADDRESSES"); return this.address.toLowerCase() < other.address.toLowerCase(); } /** * Return this token, which does not need to be wrapped */ get wrapped() { return this; } get serialize() { return { address: this.address, chainId: this.chainId, decimals: this.decimals, symbol: this.symbol, name: this.name, projectLink: this.projectLink }; } }; // src/constants.ts var ZERO_PERCENT = new swapSdkCore.Percent("0"); var ONE_HUNDRED_PERCENT = new swapSdkCore.Percent("1"); var FACTORY_ADDRESS = "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73"; var FACTORY_ADDRESS_ETH = "0x1097053Fd2ea711dad45caCcc45EfF7548fCB362"; var FACTORY_ADDRESS_MAP = { [chains.ChainId.ETHEREUM]: FACTORY_ADDRESS_ETH, [chains.ChainId.GOERLI]: FACTORY_ADDRESS_ETH, [chains.ChainId.BSC]: FACTORY_ADDRESS, [chains.ChainId.BSC_TESTNET]: "0x6725F303b657a9451d8BA641348b6761A6CC7a17", [chains.ChainId.ARBITRUM_ONE]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E", [chains.ChainId.ARBITRUM_GOERLI]: "0x333EAE459075b1d7dE8eb57997b5d4eee5F1070a", [chains.ChainId.POLYGON_ZKEVM]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E", [chains.ChainId.POLYGON_ZKEVM_TESTNET]: "0xBA40c83026213F9cbc79998752721a0312bdB74a", [chains.ChainId.ZKSYNC]: "0xd03D8D566183F0086d8D09A84E1e30b58Dd5619d", [chains.ChainId.ZKSYNC_TESTNET]: "0x48a33610Cd0E130af2024D55F67aE72a8C51aC27", [chains.ChainId.LINEA]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E", [chains.ChainId.LINEA_TESTNET]: "0xB6FAfd4ADbCd21cF665909767e0eD0D05709abfB", [chains.ChainId.OPBNB]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E", [chains.ChainId.OPBNB_TESTNET]: "0x776e4bD2f72de2176A59465e316335aaf8ed4E8F", [chains.ChainId.BASE]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E", [chains.ChainId.BASE_TESTNET]: "0x715303D2eF7dA7FFAbF637651D71FD11d41fAf7F", [chains.ChainId.SCROLL_SEPOLIA]: "0x2B3C5df29F73dbF028BA82C33e0A5A6e5800F75e", [chains.ChainId.SEPOLIA]: "0x1bdc540dEB9Ed1fA29964DeEcCc524A8f5e2198e", [chains.ChainId.ARBITRUM_SEPOLIA]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E", [chains.ChainId.BASE_SEPOLIA]: "0x02a84c1b3BBD7401a5f7fa98a384EBC70bB5749E", [chains.ChainId.ETHERLINK_TESTNET]: "0x0D06BE87F5F18D0404380C8652b9590D145dfD07", [chains.ChainId.ETHERLINK]: "0x3eebf549D2d8839E387B63796327eE2C8f64A0C4" }; var INIT_CODE_HASH = "0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5"; var INIT_CODE_HASH_ETH = "0x57224589c67f3f30a6b0d7a1b54cf3153ab84563bc609ef41dfb34f8b2974d2d"; var INIT_CODE_HASH_MAP = { [chains.ChainId.ETHEREUM]: INIT_CODE_HASH_ETH, [chains.ChainId.GOERLI]: INIT_CODE_HASH_ETH, [chains.ChainId.BSC]: INIT_CODE_HASH, [chains.ChainId.BSC_TESTNET]: "0xd0d4c4cd0848c93cb4fd1f498d7013ee6bfb25783ea21593d5834f5d250ece66", [chains.ChainId.ARBITRUM_ONE]: INIT_CODE_HASH_ETH, [chains.ChainId.ARBITRUM_GOERLI]: INIT_CODE_HASH_ETH, [chains.ChainId.POLYGON_ZKEVM]: INIT_CODE_HASH_ETH, [chains.ChainId.POLYGON_ZKEVM_TESTNET]: INIT_CODE_HASH_ETH, [chains.ChainId.ZKSYNC]: "0x0100045707a42494392b3558029b9869f865ff9df8f375dc1bf20b0555093f43", [chains.ChainId.ZKSYNC_TESTNET]: "0x0100045707a42494392b3558029b9869f865ff9df8f375dc1bf20b0555093f43", [chains.ChainId.LINEA]: INIT_CODE_HASH_ETH, [chains.ChainId.LINEA_TESTNET]: INIT_CODE_HASH_ETH, [chains.ChainId.OPBNB]: INIT_CODE_HASH_ETH, [chains.ChainId.OPBNB_TESTNET]: INIT_CODE_HASH_ETH, [chains.ChainId.BASE]: INIT_CODE_HASH_ETH, [chains.ChainId.BASE_TESTNET]: "0xa5934690703a592a07e841ca29d5e5c79b5e22ed4749057bb216dc31100be1c0", [chains.ChainId.SCROLL_SEPOLIA]: INIT_CODE_HASH_ETH, [chains.ChainId.SEPOLIA]: INIT_CODE_HASH_ETH, [chains.ChainId.ARBITRUM_SEPOLIA]: INIT_CODE_HASH_ETH, [chains.ChainId.BASE_SEPOLIA]: INIT_CODE_HASH_ETH, [chains.ChainId.ETHERLINK]: "0xa5934690703a592a07e841ca29d5e5c79b5e22ed4749057bb216dc31100be1c0", [chains.ChainId.ETHERLINK_TESTNET]: "0xa5934690703a592a07e841ca29d5e5c79b5e22ed4749057bb216dc31100be1c0" }; var WXTZ = { [chains.ChainId.ETHERLINK_TESTNET]: new ERC20Token( chains.ChainId.ETHERLINK_TESTNET, "0xB1Ea698633d57705e93b0E40c1077d46CD6A51d8", 18, "WXTZ", "Wrapped XTZ", "https://tezos.com" ), [chains.ChainId.ETHERLINK]: new ERC20Token( chains.ChainId.ETHERLINK, "0xc9B53AB2679f573e480d01e0f49e2B5CFB7a3EAb", 18, "WXTZ", "Wrapped XTZ", "https://tezos.com" ) }; var WETH9 = { [chains.ChainId.ETHEREUM]: new ERC20Token( chains.ChainId.ETHEREUM, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.GOERLI]: new ERC20Token( chains.ChainId.GOERLI, "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.BSC]: new ERC20Token( chains.ChainId.BSC, "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", 18, "ETH", "Binance-Peg Ethereum Token", "https://ethereum.org" ), [chains.ChainId.BSC_TESTNET]: new ERC20Token( chains.ChainId.BSC, "0xE7bCB9e341D546b66a46298f4893f5650a56e99E", 18, "ETH", "ETH", "https://ethereum.org" ), [chains.ChainId.ARBITRUM_ONE]: new ERC20Token( chains.ChainId.ARBITRUM_ONE, "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.ARBITRUM_GOERLI]: new ERC20Token( chains.ChainId.ARBITRUM_GOERLI, "0xEe01c0CD76354C383B8c7B4e65EA88D00B06f36f", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.ZKSYNC]: new ERC20Token( chains.ChainId.ZKSYNC, "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.ZKSYNC_TESTNET]: new ERC20Token( chains.ChainId.ZKSYNC_TESTNET, "0x02968DB286f24cB18bB5b24903eC8eBFAcf591C0", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.POLYGON_ZKEVM]: new ERC20Token( chains.ChainId.POLYGON_ZKEVM, "0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.POLYGON_ZKEVM_TESTNET]: new ERC20Token( chains.ChainId.POLYGON_ZKEVM_TESTNET, "0x30ec47F7DFae72eA79646e6cf64a8A7db538915b", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.LINEA]: new ERC20Token( chains.ChainId.LINEA, "0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.LINEA_TESTNET]: new ERC20Token( chains.ChainId.LINEA_TESTNET, "0x2C1b868d6596a18e32E61B901E4060C872647b6C", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.OPBNB_TESTNET]: new ERC20Token( chains.ChainId.OPBNB_TESTNET, "0x584f7b986d9942B0859a1E6921efA5342A673d04", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.OPBNB]: new ERC20Token( chains.ChainId.OPBNB, "0xE7798f023fC62146e8Aa1b36Da45fb70855a77Ea", 18, "ETH", "Binance-Peg Ethereum Token", "https://ethereum.org" ), [chains.ChainId.BASE]: new ERC20Token( chains.ChainId.BASE, "0x4200000000000000000000000000000000000006", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.BASE_TESTNET]: new ERC20Token( chains.ChainId.BASE_TESTNET, "0x4200000000000000000000000000000000000006", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.SCROLL_SEPOLIA]: new ERC20Token( chains.ChainId.SCROLL_SEPOLIA, "0x5300000000000000000000000000000000000004", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.SEPOLIA]: new ERC20Token( chains.ChainId.SEPOLIA, "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.ARBITRUM_SEPOLIA]: new ERC20Token( chains.ChainId.ARBITRUM_SEPOLIA, "0x1bdc540dEB9Ed1fA29964DeEcCc524A8f5e2198e", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.BASE_SEPOLIA]: new ERC20Token( chains.ChainId.BASE_SEPOLIA, "0x4200000000000000000000000000000000000006", 18, "WETH", "Wrapped Ether", "https://weth.io" ), [chains.ChainId.ETHERLINK]: new ERC20Token( chains.ChainId.ETHERLINK, "0xfc24f770F94edBca6D6f885E12d4317320BcB401", 18, "WETH", "Wrapped Ether", "https://ethereum.org" ), [chains.ChainId.ETHERLINK_TESTNET]: new ERC20Token( chains.ChainId.ETHERLINK_TESTNET, "0x8DEF68408Bc96553003094180E5C90d9fe5b88C1", 18, "ETH", "Ether", "https://ethereum.org" ) }; var WBNB = { [chains.ChainId.ETHEREUM]: new ERC20Token( chains.ChainId.ETHEREUM, "0x418D75f65a02b3D53B2418FB8E1fe493759c7605", 18, "WBNB", "Wrapped BNB", "https://www.binance.org" ), [chains.ChainId.BSC]: new ERC20Token( chains.ChainId.BSC, "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", 18, "WBNB", "Wrapped BNB", "https://www.binance.org" ), [chains.ChainId.BSC_TESTNET]: new ERC20Token( chains.ChainId.BSC_TESTNET, "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", 18, "WBNB", "Wrapped BNB", "https://www.binance.org" ), [chains.ChainId.OPBNB_TESTNET]: new ERC20Token( chains.ChainId.OPBNB_TESTNET, "0x4200000000000000000000000000000000000006", 18, "WBNB", "Wrapped BNB", "https://www.binance.org" ), [chains.ChainId.OPBNB]: new ERC20Token( chains.ChainId.OPBNB, "0x4200000000000000000000000000000000000006", 18, "WBNB", "Wrapped BNB", "https://www.binance.org" ), [chains.ChainId.ETHERLINK]: new ERC20Token( chains.ChainId.ETHERLINK, "0xaA40A1cc1561c584B675cbD12F1423A32E2a0d8C", 18, "WBNB", "Wrapped BNB", "https://www.binance.org" ) }; var WNATIVE = { [chains.ChainId.ETHEREUM]: WETH9[chains.ChainId.ETHEREUM], [chains.ChainId.GOERLI]: WETH9[chains.ChainId.GOERLI], [chains.ChainId.BSC]: WBNB[chains.ChainId.BSC], [chains.ChainId.BSC_TESTNET]: WBNB[chains.ChainId.BSC_TESTNET], [chains.ChainId.ARBITRUM_ONE]: WETH9[chains.ChainId.ARBITRUM_ONE], [chains.ChainId.ARBITRUM_GOERLI]: WETH9[chains.ChainId.ARBITRUM_GOERLI], [chains.ChainId.POLYGON_ZKEVM]: WETH9[chains.ChainId.POLYGON_ZKEVM], [chains.ChainId.POLYGON_ZKEVM_TESTNET]: WETH9[chains.ChainId.POLYGON_ZKEVM_TESTNET], [chains.ChainId.ZKSYNC]: WETH9[chains.ChainId.ZKSYNC], [chains.ChainId.ZKSYNC_TESTNET]: WETH9[chains.ChainId.ZKSYNC_TESTNET], [chains.ChainId.LINEA]: WETH9[chains.ChainId.LINEA], [chains.ChainId.LINEA_TESTNET]: WETH9[chains.ChainId.LINEA_TESTNET], [chains.ChainId.OPBNB_TESTNET]: WBNB[chains.ChainId.OPBNB_TESTNET], [chains.ChainId.OPBNB]: WBNB[chains.ChainId.OPBNB], [chains.ChainId.BASE]: WETH9[chains.ChainId.BASE], [chains.ChainId.BASE_TESTNET]: WETH9[chains.ChainId.BASE_TESTNET], [chains.ChainId.SCROLL_SEPOLIA]: WETH9[chains.ChainId.SCROLL_SEPOLIA], [chains.ChainId.SEPOLIA]: WETH9[chains.ChainId.SEPOLIA], [chains.ChainId.ARBITRUM_SEPOLIA]: WETH9[chains.ChainId.ARBITRUM_SEPOLIA], [chains.ChainId.BASE_SEPOLIA]: WETH9[chains.ChainId.BASE_SEPOLIA], [chains.ChainId.ETHERLINK_TESTNET]: WXTZ[chains.ChainId.ETHERLINK_TESTNET], [chains.ChainId.ETHERLINK]: WXTZ[chains.ChainId.ETHERLINK] }; var ETHER = { name: "Ether", symbol: "ETH", decimals: 18 }; var BNB = { name: "Binance Chain Native Token", symbol: "BNB", decimals: 18 }; var XTZ = { name: "tez", symbol: "XTZ", decimals: 18 }; var NATIVE = { [chains.ChainId.ETHEREUM]: ETHER, [chains.ChainId.GOERLI]: { name: "Goerli Ether", symbol: "GOR", decimals: 18 }, [chains.ChainId.BSC]: BNB, [chains.ChainId.BSC_TESTNET]: { name: "Binance Chain Native Token", symbol: "tBNB", decimals: 18 }, [chains.ChainId.ARBITRUM_ONE]: ETHER, [chains.ChainId.ARBITRUM_GOERLI]: { name: "Arbitrum Goerli Ether", symbol: "AGOR", decimals: 18 }, [chains.ChainId.POLYGON_ZKEVM]: ETHER, [chains.ChainId.POLYGON_ZKEVM_TESTNET]: ETHER, [chains.ChainId.ZKSYNC]: ETHER, [chains.ChainId.ZKSYNC_TESTNET]: ETHER, [chains.ChainId.LINEA]: ETHER, [chains.ChainId.LINEA_TESTNET]: ETHER, [chains.ChainId.OPBNB]: BNB, [chains.ChainId.OPBNB_TESTNET]: { name: "Binance Chain Native Token", symbol: "tBNB", decimals: 18 }, [chains.ChainId.BASE]: ETHER, [chains.ChainId.BASE_TESTNET]: ETHER, [chains.ChainId.SCROLL_SEPOLIA]: ETHER, [chains.ChainId.SEPOLIA]: { name: "Sepolia Ether", symbol: "SEP", decimals: 18 }, [chains.ChainId.ARBITRUM_SEPOLIA]: { name: "Arbitrum Sepolia Ether", symbol: "ETH", decimals: 18 }, [chains.ChainId.BASE_SEPOLIA]: { name: "Sepolia Ether", symbol: "ETH", decimals: 18 }, [chains.ChainId.ETHERLINK_TESTNET]: XTZ, [chains.ChainId.ETHERLINK]: XTZ }; // 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 PAIR_ADDRESS_CACHE = {}; var composeKey = (token0, token1) => `${token0.chainId}-${token0.address}-${token1.address}`; function getCreate2Address(from_, salt_, initCodeHash) { const from = viem.toBytes(viem.getAddress(from_)); const salt = viem.pad(viem.isBytes(salt_) ? salt_ : viem.toBytes(salt_), { size: 32 }); return viem.getAddress(viem.slice(viem.keccak256(viem.concat([viem.toBytes("0xff"), from, salt, viem.toBytes(initCodeHash)])), 12)); } var EMPTY_INPU_HASH = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"; var ZKSYNC_PREFIX = "0x2020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494"; function getCreate2AddressZkSync(from, salt, initCodeHash) { return viem.getAddress( `0x${viem.keccak256(viem.concat([ZKSYNC_PREFIX, viem.pad(from, { size: 32 }), salt, initCodeHash, EMPTY_INPU_HASH])).slice(26)}` ); } var computePairAddress = ({ factoryAddress, tokenA, tokenB }) => { const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]; const key = composeKey(token0, token1); if (PAIR_ADDRESS_CACHE?.[key] === void 0) { const getCreate2Address_ = token0.chainId === chains.ChainId.ZKSYNC_TESTNET || token1.chainId === chains.ChainId.ZKSYNC ? getCreate2AddressZkSync : getCreate2Address; PAIR_ADDRESS_CACHE = { ...PAIR_ADDRESS_CACHE, [key]: getCreate2Address_( factoryAddress, viem.keccak256(viem.encodePacked(["address", "address"], [token0.address, token1.address])), INIT_CODE_HASH_MAP[token0.chainId] ) }; } return PAIR_ADDRESS_CACHE[key]; }; var Pair = class { static getAddress(tokenA, tokenB) { return computePairAddress({ factoryAddress: FACTORY_ADDRESS_MAP[tokenA.chainId], tokenA, tokenB }); } constructor(currencyAmountA, tokenAmountB) { const tokenAmounts = currencyAmountA.currency.sortsBefore(tokenAmountB.currency) ? [currencyAmountA, tokenAmountB] : [tokenAmountB, currencyAmountA]; this.liquidityToken = new ERC20Token( tokenAmounts[0].currency.chainId, Pair.getAddress(tokenAmounts[0].currency, tokenAmounts[1].currency), 18, "Cake-LP", "Pancake LPs" ); 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; } } return swapSdkCore.CurrencyAmount.fromRawAmount( token, liquidity.quotient * this.reserveOf(token).quotient / totalSupplyAdjusted.quotient ); } }; var Route = class { constructor(pairs, input, output) { this._midPrice = null; invariant5__default.default(pairs.length > 0, "PAIRS"); const { chainId } = pairs[0]; 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 { /** * 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 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; } }; var Native = _Native; Native.cache = {}; function toHex(currencyAmount) { return `0x${currencyAmount.quotient.toString(16)}`; } var ZERO_HEX = "0x0"; var Router = class { /** * 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 etherIn = trade.inputAmount.currency.isNative; const etherOut = trade.outputAmount.currency.isNative; invariant5__default.default(!(etherIn && etherOut), "ETHER_IN_OUT"); invariant5__default.default(!("ttl" in options) || options.ttl > 0, "TTL"); const to = validateAndParseAddress(options.recipient); const amountIn = toHex(trade.maximumAmountIn(options.allowedSlippage)); const amountOut = toHex(trade.minimumAmountOut(options.allowedSlippage)); const path = trade.route.path.map((token) => token.address); const deadline = "ttl" in options ? `0x${(Math.floor(( new Date()).getTime() / 1e3) + options.ttl).toString(16)}` : `0x${options.deadline.toString(16)}`; const useFeeOnTransfer = Boolean(options.feeOnTransfer); let methodName; let args; let value; switch (trade.tradeType) { case swapSdkCore.TradeType.EXACT_INPUT: if (etherIn) { methodName = useFeeOnTransfer ? "swapExactETHForTokensSupportingFeeOnTransferTokens" : "swapExactETHForTokens"; args = [amountOut, path, to, deadline]; value = amountIn; } else if (etherOut) { methodName = useFeeOnTransfer ? "swapExactTokensForETHSupportingFeeOnTransferTokens" : "swapExactTokensForETH"; args = [amountIn, amountOut, path, to, deadline]; value = ZERO_HEX; } else { methodName = useFeeOnTransfer ? "swapExactTokensForTokensSupportingFeeOnTransferTokens" : "swapExactTokensForTokens"; args = [amountIn, amountOut, path, to, deadline]; value = ZERO_HEX; } break; case swapSdkCore.TradeType.EXACT_OUTPUT: invariant5__default.default(!useFeeOnTransfer, "EXACT_OUT_FOT"); if (etherIn) { methodName = "swapETHForExactTokens"; args = [amountOut, path, to, deadline]; value = amountIn; } else if (etherOut) { methodName = "swapTokensForExactETH"; args = [amountOut, amountIn, path, to, deadline]; value = ZERO_HEX; } else { methodName = "swapTokensForExactTokens"; args = [amountOut, amountIn, path, to, deadline]; value = ZERO_HEX; } break; } return { methodName, args, value }; } }; var _Ether = class extends swapSdkCore.NativeCurrency { constructor(chainId) { super(chainId, 18, "ETH", "Ether"); } get wrapped() { const weth9 = WETH9[this.chainId]; invariant5__default.default(!!weth9, "WRAPPED"); return weth9; } static onChain(chainId) { if (!this._etherCache[chainId]) { this._etherCache[chainId] = new _Ether(chainId); } return this._etherCache[chainId]; } equals(other) { return other.isNative && other.chainId === this.chainId; } }; var Ether = _Ether; Ether._etherCache = {}; // src/abis/ERC20.ts var erc20ABI = [ { constant: true, inputs: [], name: "decimals", outputs: [{ name: "", type: "uint8" }], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [{ name: "", type: "address" }], name: "balanceOf", outputs: [{ name: "", type: "uint256" }], payable: false, stateMutability: "view", type: "function" } ]; // src/abis/IPancakePair.ts var pancakePairV2ABI = [ { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "owner", type: "address" }, { indexed: true, internalType: "address", name: "spender", type: "address" }, { indexed: false, internalType: "uint256", name: "value", type: "uint256" } ], name: "Approval", type: "event" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "sender", type: "address" }, { indexed: false, internalType: "uint256", name: "amount0", type: "uint256" }, { indexed: false, internalType: "uint256", name: "amount1", type: "uint256" }, { indexed: true, internalType: "address", name: "to", type: "address" } ], name: "Burn", type: "event" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "sender", type: "address" }, { indexed: false, internalType: "uint256", name: "amount0", type: "uint256" }, { indexed: false, internalType: "uint256", name: "amount1", type: "uint256" } ], name: "Mint", type: "event" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "sender", type: "address" }, { indexed: false, internalType: "uint256", name: "amount0In", type: "uint256" }, { indexed: false, internalType: "uint256", name: "amount1In", type: "uint256" }, { indexed: false, internalType: "uint256", name: "amount0Out", type: "uint256" }, { indexed: false, internalType: "uint256", name: "amount1Out", type: "uint256" }, { indexed: true, internalType: "address", name: "to", type: "address" } ], name: "Swap", type: "event" }, { anonymous: false, inputs: [ { indexed: false, internalType: "uint112", name: "reserve0", type: "uint112" }, { indexed: false, internalType: "uint112", name: "reserve1", type: "uint112" } ], name: "Sync", type: "event" }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "from", type: "address" }, { indexed: true, internalType: "address", name: "to", type: "address" }, { indexed: false, internalType: "uint256", name: "value", type: "uint256" } ], name: "Transfer", type: "event" }, { constant: true, inputs: [], name: "DOMAIN_SEPARATOR", outputs: [ { internalType: "bytes32", name: "", type: "bytes32" } ], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "MINIMUM_LIQUIDITY", outputs: [ { internalType: "uint256", name: "", type: "uint256" } ], payable: false, stateMutability: "pure", type: "function" }, { constant: true, inputs: [], name: "PERMIT_TYPEHASH", outputs: [ { internalType: "bytes32", name: "", type: "bytes32" } ], payable: false, stateMutability: "pure", type: "function" }, { constant: true, inputs: [ { internalType: "address", name: "owner", type: "address" }, { internalType: "address", name: "spender", type: "address" } ], name: "allowance", outputs: [ { internalType: "uint256", name: "", type: "uint256" } ], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [ { internalType: "address", name: "spender", type: "address" }, { internalType: "uint256", name: "value", type: "uint256" } ], name: "approve", outputs: [ { internalType: "bool", name: "", type: "bool" } ], payable: false, stateMutability: "nonpayable", type: "function" }, { constant: true, inputs: [ { internalType: "address", name: "owner", type: "address" } ], name: "balanceOf", outputs: [ { internalType: "uint256", name: "", type: "uint256" } ], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [ { internalType: "address", name: "to", type: "address" } ], name: "burn", outputs: [ { internalType: "uint256", name: "amount0", type: "uint256" }, { internalType: "uint256", name: "amount1", type: "uint256" } ], payable: false, stateMutability: "nonpayable", type: "function" }, { constant: true, inputs: [], name: "decimals", outputs: [ { internalType: "uint8", name: "", type: "uint8" } ], payable: false, stateMutability: "pure", type: "function" }, { constant: true, inputs: [], name: "factory", outputs: [ { internalType: "address", name: "", type: "address" } ], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getReserves", outputs: [ { internalType: "uint112", name: "reserve0", type: "uint112" }, { internalType: "uint112", name: "reserve1", type: "uint112" }, { internalType: "uint32", name: "blockTimestampLast", type: "uint32" } ], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [ { internalType: "address", name: "", type: "address" }, { internalType: "address", name: "", type: "address" } ], name: "initialize", outputs: [], payable: false, stateMutability: "nonpayable", type: "function" }, { constant: true, inputs: [], name: "kLast", outputs: [ { internalType: "uint256", name: "", type: "uint256" } ], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [ { internalType: "address", name: "to", type: "address" } ], name: "mint", outputs: [ { internalType: "uint256", name: "liquidity", type: "uint256" } ], payable: false, stateMutability: "nonpayable", type: "function" }, { constant: true, inputs: [], name: "name", outputs: [ { internalType: "string", name: "", type: "string" } ], payable: false, stateMutability: "pure", type: "function" }, { constant: true, inputs: [ { internalType: "address", name: "owner", type: "address" } ], name: "nonces", outputs: [ { internalType: "uint256", name: "", type: "uint256" } ], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [ { internalType: "address", name: "owner", type: "address" }, { internalType: "address", name: "spender", type: "address" }, { internalType: "uint256", name: "va