UNPKG

@totality-fi/router-sdk

Version:
1,129 lines (1,119 loc) 96.2 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var JSBI = _interopDefault(require('jsbi')); var abi = require('@ethersproject/abi'); var invariant = _interopDefault(require('tiny-invariant')); var IApproveAndCall_json = require('@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IApproveAndCall.sol/IApproveAndCall.json'); var v3Sdk = require('@uniswap/v3-sdk'); var IMulticallExtended_json = require('@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IMulticallExtended.sol/IMulticallExtended.json'); var sdkCore = require('@uniswap/sdk-core'); var IPeripheryPaymentsWithFeeExtended_json = require('@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IPeripheryPaymentsWithFeeExtended.sol/IPeripheryPaymentsWithFeeExtended.json'); var ISwapRouter02_json = require('@uniswap/swap-router-contracts/artifacts/contracts/interfaces/ISwapRouter02.sol/ISwapRouter02.json'); var v1Sdk = require('@totality-fi/v1-sdk'); var solidity = require('@ethersproject/solidity'); var MSG_SENDER = '0x0000000000000000000000000000000000000001'; var ADDRESS_THIS = '0x0000000000000000000000000000000000000002'; var ZERO = /*#__PURE__*/JSBI.BigInt(0); var ONE = /*#__PURE__*/JSBI.BigInt(1); // = 1 << 23 or 100000000000000000000000 var V2_FEE_PATH_PLACEHOLDER = 8388608; (function (ApprovalTypes) { ApprovalTypes[ApprovalTypes["NOT_REQUIRED"] = 0] = "NOT_REQUIRED"; ApprovalTypes[ApprovalTypes["MAX"] = 1] = "MAX"; ApprovalTypes[ApprovalTypes["MAX_MINUS_ONE"] = 2] = "MAX_MINUS_ONE"; ApprovalTypes[ApprovalTypes["ZERO_THEN_MAX"] = 3] = "ZERO_THEN_MAX"; ApprovalTypes[ApprovalTypes["ZERO_THEN_MAX_MINUS_ONE"] = 4] = "ZERO_THEN_MAX_MINUS_ONE"; })(exports.ApprovalTypes || (exports.ApprovalTypes = {})); // type guard function isMint(options) { return Object.keys(options).some(function (k) { return k === 'recipient'; }); } var ApproveAndCall = /*#__PURE__*/function () { /** * Cannot be constructed. */ function ApproveAndCall() {} ApproveAndCall.encodeApproveMax = function encodeApproveMax(token) { return ApproveAndCall.INTERFACE.encodeFunctionData('approveMax', [token.address]); }; ApproveAndCall.encodeApproveMaxMinusOne = function encodeApproveMaxMinusOne(token) { return ApproveAndCall.INTERFACE.encodeFunctionData('approveMaxMinusOne', [token.address]); }; ApproveAndCall.encodeApproveZeroThenMax = function encodeApproveZeroThenMax(token) { return ApproveAndCall.INTERFACE.encodeFunctionData('approveZeroThenMax', [token.address]); }; ApproveAndCall.encodeApproveZeroThenMaxMinusOne = function encodeApproveZeroThenMaxMinusOne(token) { return ApproveAndCall.INTERFACE.encodeFunctionData('approveZeroThenMaxMinusOne', [token.address]); }; ApproveAndCall.encodeCallPositionManager = function encodeCallPositionManager(calldatas) { !(calldatas.length > 0) ? invariant(false, 'NULL_CALLDATA') : void 0; if (calldatas.length == 1) { return ApproveAndCall.INTERFACE.encodeFunctionData('callPositionManager', calldatas); } else { var encodedMulticall = v3Sdk.NonfungiblePositionManager.INTERFACE.encodeFunctionData('multicall', [calldatas]); return ApproveAndCall.INTERFACE.encodeFunctionData('callPositionManager', [encodedMulticall]); } } /** * Encode adding liquidity to a position in the nft manager contract * @param position Forcasted position with expected amount out from swap * @param minimalPosition Forcasted position with custom minimal token amounts * @param addLiquidityOptions Options for adding liquidity * @param slippageTolerance Defines maximum slippage */; ApproveAndCall.encodeAddLiquidity = function encodeAddLiquidity(position, minimalPosition, addLiquidityOptions, slippageTolerance) { var _position$mintAmounts = position.mintAmountsWithSlippage(slippageTolerance), amount0Min = _position$mintAmounts.amount0, amount1Min = _position$mintAmounts.amount1; // position.mintAmountsWithSlippage() can create amounts not dependenable in scenarios // such as range orders. Allow the option to provide a position with custom minimum amounts // for these scenarios if (JSBI.lessThan(minimalPosition.amount0.quotient, amount0Min)) { amount0Min = minimalPosition.amount0.quotient; } if (JSBI.lessThan(minimalPosition.amount1.quotient, amount1Min)) { amount1Min = minimalPosition.amount1.quotient; } if (isMint(addLiquidityOptions)) { return ApproveAndCall.INTERFACE.encodeFunctionData('mint', [{ token0: position.pool.token0.address, token1: position.pool.token1.address, fee: position.pool.fee, tickLower: position.tickLower, tickUpper: position.tickUpper, amount0Min: v3Sdk.toHex(amount0Min), amount1Min: v3Sdk.toHex(amount1Min), recipient: addLiquidityOptions.recipient }]); } else { return ApproveAndCall.INTERFACE.encodeFunctionData('increaseLiquidity', [{ token0: position.pool.token0.address, token1: position.pool.token1.address, amount0Min: v3Sdk.toHex(amount0Min), amount1Min: v3Sdk.toHex(amount1Min), tokenId: v3Sdk.toHex(addLiquidityOptions.tokenId) }]); } }; ApproveAndCall.encodeApprove = function encodeApprove(token, approvalType) { switch (approvalType) { case exports.ApprovalTypes.MAX: return ApproveAndCall.encodeApproveMax(token.wrapped); case exports.ApprovalTypes.MAX_MINUS_ONE: return ApproveAndCall.encodeApproveMaxMinusOne(token.wrapped); case exports.ApprovalTypes.ZERO_THEN_MAX: return ApproveAndCall.encodeApproveZeroThenMax(token.wrapped); case exports.ApprovalTypes.ZERO_THEN_MAX_MINUS_ONE: return ApproveAndCall.encodeApproveZeroThenMaxMinusOne(token.wrapped); default: throw 'Error: invalid ApprovalType'; } }; return ApproveAndCall; }(); ApproveAndCall.INTERFACE = /*#__PURE__*/new abi.Interface(IApproveAndCall_json.abi); function validateAndParseBytes32(bytes32) { if (!bytes32.match(/^0x[0-9a-fA-F]{64}$/)) { throw new Error(bytes32 + " is not valid bytes32."); } return bytes32.toLowerCase(); } var MulticallExtended = /*#__PURE__*/function () { /** * Cannot be constructed. */ function MulticallExtended() {} MulticallExtended.encodeMulticall = function encodeMulticall(calldatas, validation) { // if there's no validation, we can just fall back to regular multicall if (typeof validation === 'undefined') { return v3Sdk.Multicall.encodeMulticall(calldatas); } // if there is validation, we have to normalize calldatas if (!Array.isArray(calldatas)) { calldatas = [calldatas]; } // this means the validation value should be a previousBlockhash if (typeof validation === 'string' && validation.startsWith('0x')) { var previousBlockhash = validateAndParseBytes32(validation); return MulticallExtended.INTERFACE.encodeFunctionData('multicall(bytes32,bytes[])', [previousBlockhash, calldatas]); } else { var deadline = v3Sdk.toHex(validation); return MulticallExtended.INTERFACE.encodeFunctionData('multicall(uint256,bytes[])', [deadline, calldatas]); } }; return MulticallExtended; }(); MulticallExtended.INTERFACE = /*#__PURE__*/new abi.Interface(IMulticallExtended_json.abi); function encodeFeeBips(fee) { return v3Sdk.toHex(fee.multiply(10000).quotient); } var PaymentsExtended = /*#__PURE__*/function () { /** * Cannot be constructed. */ function PaymentsExtended() {} PaymentsExtended.encodeUnwrapWETH9 = function encodeUnwrapWETH9(amountMinimum, recipient, feeOptions) { // if there's a recipient, just pass it along if (typeof recipient === 'string') { return v3Sdk.Payments.encodeUnwrapWETH9(amountMinimum, recipient, feeOptions); } if (!!feeOptions) { var feeBips = encodeFeeBips(feeOptions.fee); var feeRecipient = sdkCore.validateAndParseAddress(feeOptions.recipient); return PaymentsExtended.INTERFACE.encodeFunctionData('unwrapWETH9WithFee(uint256,uint256,address)', [v3Sdk.toHex(amountMinimum), feeBips, feeRecipient]); } else { return PaymentsExtended.INTERFACE.encodeFunctionData('unwrapWETH9(uint256)', [v3Sdk.toHex(amountMinimum)]); } }; PaymentsExtended.encodeSweepToken = function encodeSweepToken(token, amountMinimum, recipient, feeOptions) { // if there's a recipient, just pass it along if (typeof recipient === 'string') { return v3Sdk.Payments.encodeSweepToken(token, amountMinimum, recipient, feeOptions); } if (!!feeOptions) { var feeBips = encodeFeeBips(feeOptions.fee); var feeRecipient = sdkCore.validateAndParseAddress(feeOptions.recipient); return PaymentsExtended.INTERFACE.encodeFunctionData('sweepTokenWithFee(address,uint256,uint256,address)', [token.address, v3Sdk.toHex(amountMinimum), feeBips, feeRecipient]); } else { return PaymentsExtended.INTERFACE.encodeFunctionData('sweepToken(address,uint256)', [token.address, v3Sdk.toHex(amountMinimum)]); } }; PaymentsExtended.encodePull = function encodePull(token, amount) { return PaymentsExtended.INTERFACE.encodeFunctionData('pull', [token.address, v3Sdk.toHex(amount)]); }; PaymentsExtended.encodeWrapETH = function encodeWrapETH(amount) { return PaymentsExtended.INTERFACE.encodeFunctionData('wrapETH', [v3Sdk.toHex(amount)]); }; return PaymentsExtended; }(); PaymentsExtended.INTERFACE = /*#__PURE__*/new abi.Interface(IPeripheryPaymentsWithFeeExtended_json.abi); function _regeneratorRuntime() { _regeneratorRuntime = function () { return exports; }; var exports = {}, Op = Object.prototype, hasOwn = Op.hasOwnProperty, defineProperty = Object.defineProperty || function (obj, key, desc) { obj[key] = desc.value; }, $Symbol = "function" == typeof Symbol ? Symbol : {}, iteratorSymbol = $Symbol.iterator || "@@iterator", asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator", toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; function define(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: !0, configurable: !0, writable: !0 }), obj[key]; } try { define({}, ""); } catch (err) { define = function (obj, key, value) { return obj[key] = value; }; } function wrap(innerFn, outerFn, self, tryLocsList) { var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator, generator = Object.create(protoGenerator.prototype), context = new Context(tryLocsList || []); return defineProperty(generator, "_invoke", { value: makeInvokeMethod(innerFn, self, context) }), generator; } function tryCatch(fn, obj, arg) { try { return { type: "normal", arg: fn.call(obj, arg) }; } catch (err) { return { type: "throw", arg: err }; } } exports.wrap = wrap; var ContinueSentinel = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var IteratorPrototype = {}; define(IteratorPrototype, iteratorSymbol, function () { return this; }); var getProto = Object.getPrototypeOf, NativeIteratorPrototype = getProto && getProto(getProto(values([]))); NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype); var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype); function defineIteratorMethods(prototype) { ["next", "throw", "return"].forEach(function (method) { define(prototype, method, function (arg) { return this._invoke(method, arg); }); }); } function AsyncIterator(generator, PromiseImpl) { function invoke(method, arg, resolve, reject) { var record = tryCatch(generator[method], generator, arg); if ("throw" !== record.type) { var result = record.arg, value = result.value; return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) { invoke("next", value, resolve, reject); }, function (err) { invoke("throw", err, resolve, reject); }) : PromiseImpl.resolve(value).then(function (unwrapped) { result.value = unwrapped, resolve(result); }, function (error) { return invoke("throw", error, resolve, reject); }); } reject(record.arg); } var previousPromise; defineProperty(this, "_invoke", { value: function (method, arg) { function callInvokeWithMethodAndArg() { return new PromiseImpl(function (resolve, reject) { invoke(method, arg, resolve, reject); }); } return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(innerFn, self, context) { var state = "suspendedStart"; return function (method, arg) { if ("executing" === state) throw new Error("Generator is already running"); if ("completed" === state) { if ("throw" === method) throw arg; return doneResult(); } for (context.method = method, context.arg = arg;;) { var delegate = context.delegate; if (delegate) { var delegateResult = maybeInvokeDelegate(delegate, context); if (delegateResult) { if (delegateResult === ContinueSentinel) continue; return delegateResult; } } if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) { if ("suspendedStart" === state) throw state = "completed", context.arg; context.dispatchException(context.arg); } else "return" === context.method && context.abrupt("return", context.arg); state = "executing"; var record = tryCatch(innerFn, self, context); if ("normal" === record.type) { if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue; return { value: record.arg, done: context.done }; } "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg); } }; } function maybeInvokeDelegate(delegate, context) { var methodName = context.method, method = delegate.iterator[methodName]; if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel; var record = tryCatch(method, delegate.iterator, context.arg); if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel; var info = record.arg; return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel); } function pushTryEntry(locs) { var entry = { tryLoc: locs[0] }; 1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry); } function resetTryEntry(entry) { var record = entry.completion || {}; record.type = "normal", delete record.arg, entry.completion = record; } function Context(tryLocsList) { this.tryEntries = [{ tryLoc: "root" }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0); } function values(iterable) { if (iterable) { var iteratorMethod = iterable[iteratorSymbol]; if (iteratorMethod) return iteratorMethod.call(iterable); if ("function" == typeof iterable.next) return iterable; if (!isNaN(iterable.length)) { var i = -1, next = function next() { for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next; return next.value = undefined, next.done = !0, next; }; return next.next = next; } } return { next: doneResult }; } function doneResult() { return { value: undefined, done: !0 }; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), defineProperty(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) { var ctor = "function" == typeof genFun && genFun.constructor; return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name)); }, exports.mark = function (genFun) { return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun; }, exports.awrap = function (arg) { return { __await: arg }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () { return this; }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) { void 0 === PromiseImpl && (PromiseImpl = Promise); var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl); return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) { return result.done ? result.value : iter.next(); }); }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () { return this; }), define(Gp, "toString", function () { return "[object Generator]"; }), exports.keys = function (val) { var object = Object(val), keys = []; for (var key in object) keys.push(key); return keys.reverse(), function next() { for (; keys.length;) { var key = keys.pop(); if (key in object) return next.value = key, next.done = !1, next; } return next.done = !0, next; }; }, exports.values = values, Context.prototype = { constructor: Context, reset: function (skipTempReset) { if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined); }, stop: function () { this.done = !0; var rootRecord = this.tryEntries[0].completion; if ("throw" === rootRecord.type) throw rootRecord.arg; return this.rval; }, dispatchException: function (exception) { if (this.done) throw exception; var context = this; function handle(loc, caught) { return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught; } for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i], record = entry.completion; if ("root" === entry.tryLoc) return handle("end"); if (entry.tryLoc <= this.prev) { var hasCatch = hasOwn.call(entry, "catchLoc"), hasFinally = hasOwn.call(entry, "finallyLoc"); if (hasCatch && hasFinally) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } else if (hasCatch) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); } else { if (!hasFinally) throw new Error("try statement without catch or finally"); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } } } }, abrupt: function (type, arg) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) { var finallyEntry = entry; break; } } finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null); var record = finallyEntry ? finallyEntry.completion : {}; return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record); }, complete: function (record, afterLoc) { if ("throw" === record.type) throw record.arg; return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel; }, finish: function (finallyLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel; } }, catch: function (tryLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc === tryLoc) { var record = entry.completion; if ("throw" === record.type) { var thrown = record.arg; resetTryEntry(entry); } return thrown; } } throw new Error("illegal catch attempt"); }, delegateYield: function (iterable, resultName, nextLoc) { return this.delegate = { iterator: values(iterable), resultName: resultName, nextLoc: nextLoc }, "next" === this.method && (this.arg = undefined), ContinueSentinel; } }, exports; } function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } /** * Represents a list of pools or pairs through which a swap can occur * @template TInput The input token * @template TOutput The output token */ var MixedRouteSDK = /*#__PURE__*/function () { /** * Creates an instance of route. * @param pools An array of `TPool` objects (pools or pairs), ordered by the route the swap will take * @param input The input token * @param output The output token */ function MixedRouteSDK(pools, input, output) { this._midPrice = null; !(pools.length > 0) ? invariant(false, 'POOLS') : void 0; var chainId = pools[0].chainId; var allOnSameChain = pools.every(function (pool) { return pool.chainId === chainId; }); !allOnSameChain ? invariant(false, 'CHAIN_IDS') : void 0; var wrappedInput = input.wrapped; !pools[0].involvesToken(wrappedInput) ? invariant(false, 'INPUT') : void 0; !pools[pools.length - 1].involvesToken(output.wrapped) ? invariant(false, 'OUTPUT') : void 0; /** * Normalizes token0-token1 order and selects the next token/fee step to add to the path * */ var tokenPath = [wrappedInput]; for (var _iterator = _createForOfIteratorHelperLoose(pools.entries()), _step; !(_step = _iterator()).done;) { var _step$value = _step.value, i = _step$value[0], pool = _step$value[1]; var currentInputToken = tokenPath[i]; !(currentInputToken.equals(pool.token0) || currentInputToken.equals(pool.token1)) ? invariant(false, 'PATH') : void 0; var nextToken = currentInputToken.equals(pool.token0) ? pool.token1 : pool.token0; tokenPath.push(nextToken); } this.pools = pools; this.path = tokenPath; this.input = input; this.output = output != null ? output : tokenPath[tokenPath.length - 1]; } _createClass(MixedRouteSDK, [{ key: "chainId", get: function get() { return this.pools[0].chainId; } /** * Returns the mid price of the route */ }, { key: "midPrice", get: function get() { if (this._midPrice !== null) return this._midPrice; var price = this.pools.slice(1).reduce(function (_ref, pool) { var nextInput = _ref.nextInput, price = _ref.price; return nextInput.equals(pool.token0) ? { nextInput: pool.token1, price: price.multiply(pool.token0Price) } : { nextInput: pool.token0, price: price.multiply(pool.token1Price) }; }, this.pools[0].token0.equals(this.input.wrapped) ? { nextInput: this.pools[0].token1, price: this.pools[0].token0Price } : { nextInput: this.pools[0].token0, price: this.pools[0].token1Price }).price; return this._midPrice = new sdkCore.Price(this.input, this.output, price.denominator, price.numerator); } }]); return MixedRouteSDK; }(); /** * Trades comparator, an extension of the input output comparator that also considers other dimensions of the trade in ranking them * @template TInput The input token, either Ether or an ERC-20 * @template TOutput The output token, either Ether or an ERC-20 * @template TTradeType The trade type, either exact input or exact output * @param a The first trade to compare * @param b The second trade to compare * @returns A sorted ordering for two neighboring elements in a trade array */ function tradeComparator(a, b) { // must have same input and output token for comparison !a.inputAmount.currency.equals(b.inputAmount.currency) ? invariant(false, 'INPUT_CURRENCY') : void 0; !a.outputAmount.currency.equals(b.outputAmount.currency) ? invariant(false, 'OUTPUT_CURRENCY') : void 0; if (a.outputAmount.equalTo(b.outputAmount)) { if (a.inputAmount.equalTo(b.inputAmount)) { // consider the number of hops since each hop costs gas var aHops = a.swaps.reduce(function (total, cur) { return total + cur.route.path.length; }, 0); var bHops = b.swaps.reduce(function (total, cur) { return total + cur.route.path.length; }, 0); return aHops - bHops; } // trade A requires less input than trade B, so A should come first if (a.inputAmount.lessThan(b.inputAmount)) { return -1; } else { return 1; } } else { // tradeA has less output than trade B, so should come second if (a.outputAmount.lessThan(b.outputAmount)) { return 1; } else { return -1; } } } /** * Represents a trade executed against a set of routes where some percentage of the input is * split across each route. * * Each route has its own set of pools. Pools can not be re-used across routes. * * Does not account for slippage, i.e., changes in price environment that can occur between * the time the trade is submitted and when it is executed. * @notice This class is functionally the same as the `Trade` class in the `@uniswap/v3-sdk` package, aside from typing and some input validation. * @template TInput The input token, either Ether or an ERC-20 * @template TOutput The output token, either Ether or an ERC-20 * @template TTradeType The trade type, either exact input or exact output */ var MixedRouteTrade = /*#__PURE__*/function () { /** * Construct a trade by passing in the pre-computed property values * @param routes The routes through which the trade occurs * @param tradeType The type of trade, exact input or exact output */ function MixedRouteTrade(_ref) { var routes = _ref.routes, tradeType = _ref.tradeType; var inputCurrency = routes[0].inputAmount.currency; var outputCurrency = routes[0].outputAmount.currency; !routes.every(function (_ref2) { var route = _ref2.route; return inputCurrency.wrapped.equals(route.input.wrapped); }) ? invariant(false, 'INPUT_CURRENCY_MATCH') : void 0; !routes.every(function (_ref3) { var route = _ref3.route; return outputCurrency.wrapped.equals(route.output.wrapped); }) ? invariant(false, 'OUTPUT_CURRENCY_MATCH') : void 0; var numPools = routes.map(function (_ref4) { var route = _ref4.route; return route.pools.length; }).reduce(function (total, cur) { return total + cur; }, 0); var poolAddressSet = new Set(); for (var _iterator = _createForOfIteratorHelperLoose(routes), _step; !(_step = _iterator()).done;) { var route = _step.value.route; for (var _iterator2 = _createForOfIteratorHelperLoose(route.pools), _step2; !(_step2 = _iterator2()).done;) { var pool = _step2.value; pool instanceof v3Sdk.Pool ? poolAddressSet.add(v3Sdk.Pool.getAddress(pool.token0, pool.token1, pool.fee)) : poolAddressSet.add(v1Sdk.Pair.getAddress(pool.token0, pool.token1)); } } !(numPools == poolAddressSet.size) ? invariant(false, 'POOLS_DUPLICATED') : void 0; !(tradeType === sdkCore.TradeType.EXACT_INPUT) ? invariant(false, 'TRADE_TYPE') : void 0; this.swaps = routes; this.tradeType = tradeType; } /** * @deprecated Deprecated in favor of 'swaps' property. If the trade consists of multiple routes * this will return an error. * * When the trade consists of just a single route, this returns the route of the trade, * i.e. which pools the trade goes through. */ /** * Constructs a trade by simulating swaps through the given route * @template TInput The input token, either Ether or an ERC-20. * @template TOutput The output token, either Ether or an ERC-20. * @template TTradeType The type of the trade, either exact in or exact out. * @param route route to swap through * @param amount the amount specified, either input or output, depending on tradeType * @param tradeType whether the trade is an exact input or exact output swap * @returns The route */ MixedRouteTrade.fromRoute = /*#__PURE__*/ function () { var _fromRoute = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(route, amount, tradeType) { var amounts, inputAmount, outputAmount, i, pool, _yield$pool$getOutput, _outputAmount; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: amounts = new Array(route.path.length); !(tradeType === sdkCore.TradeType.EXACT_INPUT) ? invariant(false, 'TRADE_TYPE') : void 0; !amount.currency.equals(route.input) ? invariant(false, 'INPUT') : void 0; amounts[0] = amount.wrapped; i = 0; case 5: if (!(i < route.path.length - 1)) { _context.next = 15; break; } pool = route.pools[i]; _context.next = 9; return pool.getOutputAmount(amounts[i]); case 9: _yield$pool$getOutput = _context.sent; _outputAmount = _yield$pool$getOutput[0]; amounts[i + 1] = _outputAmount; case 12: i++; _context.next = 5; break; case 15: inputAmount = sdkCore.CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator); outputAmount = sdkCore.CurrencyAmount.fromFractionalAmount(route.output, amounts[amounts.length - 1].numerator, amounts[amounts.length - 1].denominator); return _context.abrupt("return", new MixedRouteTrade({ routes: [{ inputAmount: inputAmount, outputAmount: outputAmount, route: route }], tradeType: tradeType })); case 18: case "end": return _context.stop(); } }, _callee); })); function fromRoute(_x, _x2, _x3) { return _fromRoute.apply(this, arguments); } return fromRoute; }() /** * Constructs a trade from routes by simulating swaps * * @template TInput The input token, either Ether or an ERC-20. * @template TOutput The output token, either Ether or an ERC-20. * @template TTradeType The type of the trade, either exact in or exact out. * @param routes the routes to swap through and how much of the amount should be routed through each * @param tradeType whether the trade is an exact input or exact output swap * @returns The trade */ ; MixedRouteTrade.fromRoutes = /*#__PURE__*/ function () { var _fromRoutes = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(routes, tradeType) { var populatedRoutes, _iterator3, _step3, _step3$value, route, amount, amounts, inputAmount, outputAmount, i, pool, _yield$pool$getOutput2, _outputAmount2; return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: populatedRoutes = []; !(tradeType === sdkCore.TradeType.EXACT_INPUT) ? invariant(false, 'TRADE_TYPE') : void 0; _iterator3 = _createForOfIteratorHelperLoose(routes); case 3: if ((_step3 = _iterator3()).done) { _context2.next = 26; break; } _step3$value = _step3.value, route = _step3$value.route, amount = _step3$value.amount; amounts = new Array(route.path.length); inputAmount = void 0; outputAmount = void 0; !amount.currency.equals(route.input) ? invariant(false, 'INPUT') : void 0; inputAmount = sdkCore.CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator); amounts[0] = sdkCore.CurrencyAmount.fromFractionalAmount(route.input.wrapped, amount.numerator, amount.denominator); i = 0; case 12: if (!(i < route.path.length - 1)) { _context2.next = 22; break; } pool = route.pools[i]; _context2.next = 16; return pool.getOutputAmount(amounts[i]); case 16: _yield$pool$getOutput2 = _context2.sent; _outputAmount2 = _yield$pool$getOutput2[0]; amounts[i + 1] = _outputAmount2; case 19: i++; _context2.next = 12; break; case 22: outputAmount = sdkCore.CurrencyAmount.fromFractionalAmount(route.output, amounts[amounts.length - 1].numerator, amounts[amounts.length - 1].denominator); populatedRoutes.push({ route: route, inputAmount: inputAmount, outputAmount: outputAmount }); case 24: _context2.next = 3; break; case 26: return _context2.abrupt("return", new MixedRouteTrade({ routes: populatedRoutes, tradeType: tradeType })); case 27: case "end": return _context2.stop(); } }, _callee2); })); function fromRoutes(_x4, _x5) { return _fromRoutes.apply(this, arguments); } return fromRoutes; }() /** * Creates a trade without computing the result of swapping through the route. Useful when you have simulated the trade * elsewhere and do not have any tick data * @template TInput The input token, either Ether or an ERC-20 * @template TOutput The output token, either Ether or an ERC-20 * @template TTradeType The type of the trade, either exact in or exact out * @param constructorArguments The arguments passed to the trade constructor * @returns The unchecked trade */ ; MixedRouteTrade.createUncheckedTrade = function createUncheckedTrade(constructorArguments) { return new MixedRouteTrade(_extends({}, constructorArguments, { routes: [{ inputAmount: constructorArguments.inputAmount, outputAmount: constructorArguments.outputAmount, route: constructorArguments.route }] })); } /** * Creates a trade without computing the result of swapping through the routes. Useful when you have simulated the trade * elsewhere and do not have any tick data * @template TInput The input token, either Ether or an ERC-20 * @template TOutput The output token, either Ether or an ERC-20 * @template TTradeType The type of the trade, either exact in or exact out * @param constructorArguments The arguments passed to the trade constructor * @returns The unchecked trade */; MixedRouteTrade.createUncheckedTradeWithMultipleRoutes = function createUncheckedTradeWithMultipleRoutes(constructorArguments) { return new MixedRouteTrade(constructorArguments); } /** * Get the minimum amount that must be received from this trade for the given slippage tolerance * @param slippageTolerance The tolerance of unfavorable slippage from the execution price of this trade * @returns The amount out */; var _proto = MixedRouteTrade.prototype; _proto.minimumAmountOut = function minimumAmountOut(slippageTolerance, amountOut) { if (amountOut === void 0) { amountOut = this.outputAmount; } !!slippageTolerance.lessThan(ZERO) ? invariant(false, 'SLIPPAGE_TOLERANCE') : void 0; /// does not support exactOutput, as enforced in the constructor var slippageAdjustedAmountOut = new sdkCore.Fraction(ONE).add(slippageTolerance).invert().multiply(amountOut.quotient).quotient; return sdkCore.CurrencyAmount.fromRawAmount(amountOut.currency, slippageAdjustedAmountOut); } /** * Get the maximum amount in that can be spent via this trade for the given slippage tolerance * @param slippageTolerance The tolerance of unfavorable slippage from the execution price of this trade * @returns The amount in */; _proto.maximumAmountIn = function maximumAmountIn(slippageTolerance, amountIn) { if (amountIn === void 0) { amountIn = this.inputAmount; } !!slippageTolerance.lessThan(ZERO) ? invariant(false, 'SLIPPAGE_TOLERANCE') : void 0; return amountIn; /// does not support exactOutput } /** * Return the execution price after accounting for slippage tolerance * @param slippageTolerance the allowed tolerated slippage * @returns The execution price */; _proto.worstExecutionPrice = function worstExecutionPrice(slippageTolerance) { return new sdkCore.Price(this.inputAmount.currency, this.outputAmount.currency, this.maximumAmountIn(slippageTolerance).quotient, this.minimumAmountOut(slippageTolerance).quotient); } /** * Given a list of pools, 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 pools the pools 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 pool * @param currentPools used in recursion; the current list of pools * @param currencyAmountIn used in recursion; the original value of the currencyAmountIn parameter * @param bestTrades used in recursion; the current list of best trades * @returns The exact in trade */; MixedRouteTrade.bestTradeExactIn = /*#__PURE__*/ function () { var _bestTradeExactIn = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(pools, currencyAmountIn, currencyOut, _temp, // used in recursion. currentPools, nextAmountIn, bestTrades) { var _ref5, _ref5$maxNumResults, maxNumResults, _ref5$maxHops, maxHops, amountIn, tokenOut, i, pool, amountOut, _yield$pool$getOutput3, poolsExcludingThisPool; return _regeneratorRuntime().wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: _ref5 = _temp === void 0 ? {} : _temp, _ref5$maxNumResults = _ref5.maxNumResults, maxNumResults = _ref5$maxNumResults === void 0 ? 3 : _ref5$maxNumResults, _ref5$maxHops = _ref5.maxHops, maxHops = _ref5$maxHops === void 0 ? 3 : _ref5$maxHops; if (currentPools === void 0) { currentPools = []; } if (nextAmountIn === void 0) { nextAmountIn = currencyAmountIn; } if (bestTrades === void 0) { bestTrades = []; } !(pools.length > 0) ? invariant(false, 'POOLS') : void 0; !(maxHops > 0) ? invariant(false, 'MAX_HOPS') : void 0; !(currencyAmountIn === nextAmountIn || currentPools.length > 0) ? invariant(false, 'INVALID_RECURSION') : void 0; amountIn = nextAmountIn.wrapped; tokenOut = currencyOut.wrapped; i = 0; case 10: if (!(i < pools.length)) { _context3.next = 49; break; } pool = pools[i]; // pool irrelevant if (!(!pool.token0.equals(amountIn.currency) && !pool.token1.equals(amountIn.currency))) { _context3.next = 14; break; } return _context3.abrupt("continue", 46); case 14: if (!(pool instanceof v1Sdk.Pair)) { _context3.next = 17; break; } if (!(pool.reserve0.equalTo(ZERO) || pool.reserve1.equalTo(ZERO))) { _context3.next = 17; break; } return _context3.abrupt("continue", 46); case 17: amountOut = void 0; _context3.prev = 18; _context3.next = 22; return pool.getOutputAmount(amountIn); case 22: _yield$pool$getOutput3 = _context3.sent; amountOut = _yield$pool$getOutput3[0]; _context3.next = 31; break; case 26: _context3.prev = 26; _context3.t0 = _context3["catch"](18); if (!_context3.t0.isInsufficientInputAmountError) { _context3.next = 30; break; } return _context3.abrupt("continue", 46); case 30: throw _context3.t0; case 31: if (!(amountOut.currency.isToken && amountOut.currency.equals(tokenOut))) { _context3.next = 42; break; } _context3.t1 = sdkCore.sortedInsert; _context3.t2 = bestTrades; _context3.next = 36; return MixedRouteTrade.fromRoute(new MixedRouteSDK([].concat(currentPools, [pool]), currencyAmountIn.currency, currencyOut), currencyAmountIn, sdkCore.TradeType.EXACT_INPUT); case 36: _context3.t3 = _context3.sent; _context3.t4 = maxNumResults; _context3.t5 = tradeComparator; (0, _context3.t1)(_context3.t2, _context3.t3, _context3.t4, _context3.t5); _context3.next = 46; break; case 42: if (!(maxHops > 1 && pools.length > 1)) { _context3.next = 46; break; } poolsExcludingThisPool = pools.slice(0, i).concat(pools.slice(i + 1, pools.length)); // otherwise, consider all the other paths that lead from this token as long as we have not exceeded maxHops _context3.next = 46; return MixedRouteTrade.bestTradeExactIn(poolsExcludingThisPool, currencyAmountIn, currencyOut, { maxNumResults: maxNumResults, maxHops: maxHops - 1 }, [].concat(currentPools, [pool]), amountOut, bestTrades); case 46: i++; _context3.next = 10; break; case 49: return _context3.abrupt("return", bestTrades); case 50: case "end": return _context3.stop(); } }, _callee3, null, [[18, 26]]); })); function bestTradeExactIn(_x6, _x7, _x8, _x9, _x10, _x11, _x12) { return _bestTradeExactIn.apply(this, arguments); } return bestTradeExactIn; }(); _createClass(MixedRouteTrade, [{ key: "route", get: function get() { !(this.swaps.length == 1) ? invariant(false, 'MULTIPLE_ROUTES') : void 0; return this.