@uniswap/router-sdk 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,17 +2,20 @@ import JSBI from 'jsbi';
2
2
  import { Interface } from '@ethersproject/abi';
3
3
  import invariant from 'tiny-invariant';
4
4
  import { abi } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IApproveAndCall.sol/IApproveAndCall.json';
5
- import { NonfungiblePositionManager, toHex, Multicall, Payments, Route as Route$1, Pool, Trade as Trade$1, encodeRouteToPath, SelfPermit, Position } from '@uniswap/v3-sdk';
5
+ import { NonfungiblePositionManager, toHex, Multicall, Payments, Pool, Route as Route$1, Trade as Trade$1, encodeRouteToPath, SelfPermit, Position } from '@uniswap/v3-sdk';
6
6
  import { abi as abi$1 } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IMulticallExtended.sol/IMulticallExtended.json';
7
- import { validateAndParseAddress, TradeType, Fraction, CurrencyAmount, Price, Percent, WETH9 } from '@uniswap/sdk-core';
7
+ import { validateAndParseAddress, Price, Fraction, CurrencyAmount, Percent, TradeType, sortedInsert, WETH9 } from '@uniswap/sdk-core';
8
8
  import { abi as abi$2 } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IPeripheryPaymentsWithFeeExtended.sol/IPeripheryPaymentsWithFeeExtended.json';
9
9
  import { abi as abi$3 } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/ISwapRouter02.sol/ISwapRouter02.json';
10
- import { Route, Pair, Trade as Trade$2 } from '@uniswap/v2-sdk';
10
+ import { Pair, Route, Trade as Trade$2 } from '@uniswap/v2-sdk';
11
+ import { pack } from '@ethersproject/solidity';
11
12
 
12
13
  var MSG_SENDER = '0x0000000000000000000000000000000000000001';
13
14
  var ADDRESS_THIS = '0x0000000000000000000000000000000000000002';
14
15
  var ZERO = /*#__PURE__*/JSBI.BigInt(0);
15
- var ONE = /*#__PURE__*/JSBI.BigInt(1);
16
+ var ONE = /*#__PURE__*/JSBI.BigInt(1); // = 1 << 23 or 100000000000000000000000
17
+
18
+ var V2_FEE_PATH_PLACEHOLDER = 8388608;
16
19
 
17
20
  var ApprovalTypes;
18
21
 
@@ -275,6 +278,24 @@ function _createClass(Constructor, protoProps, staticProps) {
275
278
  return Constructor;
276
279
  }
277
280
 
281
+ function _extends() {
282
+ _extends = Object.assign || function (target) {
283
+ for (var i = 1; i < arguments.length; i++) {
284
+ var source = arguments[i];
285
+
286
+ for (var key in source) {
287
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
288
+ target[key] = source[key];
289
+ }
290
+ }
291
+ }
292
+
293
+ return target;
294
+ };
295
+
296
+ return _extends.apply(this, arguments);
297
+ }
298
+
278
299
  function _inheritsLoose(subClass, superClass) {
279
300
  subClass.prototype = Object.create(superClass.prototype);
280
301
  subClass.prototype.constructor = subClass;
@@ -1089,11 +1110,692 @@ try {
1089
1110
  }
1090
1111
  });
1091
1112
 
1113
+ /**
1114
+ * Represents a list of pools or pairs through which a swap can occur
1115
+ * @template TInput The input token
1116
+ * @template TOutput The output token
1117
+ */
1118
+
1119
+ var MixedRouteSDK = /*#__PURE__*/function () {
1120
+ /**
1121
+ * Creates an instance of route.
1122
+ * @param pools An array of `TPool` objects (pools or pairs), ordered by the route the swap will take
1123
+ * @param input The input token
1124
+ * @param output The output token
1125
+ */
1126
+ function MixedRouteSDK(pools, input, output) {
1127
+ this._midPrice = null;
1128
+ !(pools.length > 0) ? process.env.NODE_ENV !== "production" ? invariant(false, 'POOLS') : invariant(false) : void 0;
1129
+ var chainId = pools[0].chainId;
1130
+ var allOnSameChain = pools.every(function (pool) {
1131
+ return pool.chainId === chainId;
1132
+ });
1133
+ !allOnSameChain ? process.env.NODE_ENV !== "production" ? invariant(false, 'CHAIN_IDS') : invariant(false) : void 0;
1134
+ var wrappedInput = input.wrapped;
1135
+ !pools[0].involvesToken(wrappedInput) ? process.env.NODE_ENV !== "production" ? invariant(false, 'INPUT') : invariant(false) : void 0;
1136
+ !pools[pools.length - 1].involvesToken(output.wrapped) ? process.env.NODE_ENV !== "production" ? invariant(false, 'OUTPUT') : invariant(false) : void 0;
1137
+ /**
1138
+ * Normalizes token0-token1 order and selects the next token/fee step to add to the path
1139
+ * */
1140
+
1141
+ var tokenPath = [wrappedInput];
1142
+
1143
+ for (var _iterator = _createForOfIteratorHelperLoose(pools.entries()), _step; !(_step = _iterator()).done;) {
1144
+ var _step$value = _step.value,
1145
+ i = _step$value[0],
1146
+ pool = _step$value[1];
1147
+ var currentInputToken = tokenPath[i];
1148
+ !(currentInputToken.equals(pool.token0) || currentInputToken.equals(pool.token1)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'PATH') : invariant(false) : void 0;
1149
+ var nextToken = currentInputToken.equals(pool.token0) ? pool.token1 : pool.token0;
1150
+ tokenPath.push(nextToken);
1151
+ }
1152
+
1153
+ this.pools = pools;
1154
+ this.path = tokenPath;
1155
+ this.input = input;
1156
+ this.output = output != null ? output : tokenPath[tokenPath.length - 1];
1157
+ }
1158
+
1159
+ _createClass(MixedRouteSDK, [{
1160
+ key: "chainId",
1161
+ get: function get() {
1162
+ return this.pools[0].chainId;
1163
+ }
1164
+ /**
1165
+ * Returns the mid price of the route
1166
+ */
1167
+
1168
+ }, {
1169
+ key: "midPrice",
1170
+ get: function get() {
1171
+ if (this._midPrice !== null) return this._midPrice;
1172
+ var price = this.pools.slice(1).reduce(function (_ref, pool) {
1173
+ var nextInput = _ref.nextInput,
1174
+ price = _ref.price;
1175
+ return nextInput.equals(pool.token0) ? {
1176
+ nextInput: pool.token1,
1177
+ price: price.multiply(pool.token0Price)
1178
+ } : {
1179
+ nextInput: pool.token0,
1180
+ price: price.multiply(pool.token1Price)
1181
+ };
1182
+ }, this.pools[0].token0.equals(this.input.wrapped) ? {
1183
+ nextInput: this.pools[0].token1,
1184
+ price: this.pools[0].token0Price
1185
+ } : {
1186
+ nextInput: this.pools[0].token0,
1187
+ price: this.pools[0].token1Price
1188
+ }).price;
1189
+ return this._midPrice = new Price(this.input, this.output, price.denominator, price.numerator);
1190
+ }
1191
+ }]);
1192
+
1193
+ return MixedRouteSDK;
1194
+ }();
1195
+
1196
+ /**
1197
+ * Trades comparator, an extension of the input output comparator that also considers other dimensions of the trade in ranking them
1198
+ * @template TInput The input token, either Ether or an ERC-20
1199
+ * @template TOutput The output token, either Ether or an ERC-20
1200
+ * @template TTradeType The trade type, either exact input or exact output
1201
+ * @param a The first trade to compare
1202
+ * @param b The second trade to compare
1203
+ * @returns A sorted ordering for two neighboring elements in a trade array
1204
+ */
1205
+
1206
+ function tradeComparator(a, b) {
1207
+ // must have same input and output token for comparison
1208
+ !a.inputAmount.currency.equals(b.inputAmount.currency) ? process.env.NODE_ENV !== "production" ? invariant(false, 'INPUT_CURRENCY') : invariant(false) : void 0;
1209
+ !a.outputAmount.currency.equals(b.outputAmount.currency) ? process.env.NODE_ENV !== "production" ? invariant(false, 'OUTPUT_CURRENCY') : invariant(false) : void 0;
1210
+
1211
+ if (a.outputAmount.equalTo(b.outputAmount)) {
1212
+ if (a.inputAmount.equalTo(b.inputAmount)) {
1213
+ // consider the number of hops since each hop costs gas
1214
+ var aHops = a.swaps.reduce(function (total, cur) {
1215
+ return total + cur.route.path.length;
1216
+ }, 0);
1217
+ var bHops = b.swaps.reduce(function (total, cur) {
1218
+ return total + cur.route.path.length;
1219
+ }, 0);
1220
+ return aHops - bHops;
1221
+ } // trade A requires less input than trade B, so A should come first
1222
+
1223
+
1224
+ if (a.inputAmount.lessThan(b.inputAmount)) {
1225
+ return -1;
1226
+ } else {
1227
+ return 1;
1228
+ }
1229
+ } else {
1230
+ // tradeA has less output than trade B, so should come second
1231
+ if (a.outputAmount.lessThan(b.outputAmount)) {
1232
+ return 1;
1233
+ } else {
1234
+ return -1;
1235
+ }
1236
+ }
1237
+ }
1238
+ /**
1239
+ * Represents a trade executed against a set of routes where some percentage of the input is
1240
+ * split across each route.
1241
+ *
1242
+ * Each route has its own set of pools. Pools can not be re-used across routes.
1243
+ *
1244
+ * Does not account for slippage, i.e., changes in price environment that can occur between
1245
+ * the time the trade is submitted and when it is executed.
1246
+ * @notice This class is functionally the same as the `Trade` class in the `@uniswap/v3-sdk` package, aside from typing and some input validation.
1247
+ * @template TInput The input token, either Ether or an ERC-20
1248
+ * @template TOutput The output token, either Ether or an ERC-20
1249
+ * @template TTradeType The trade type, either exact input or exact output
1250
+ */
1251
+
1252
+ var MixedRouteTrade = /*#__PURE__*/function () {
1253
+ /**
1254
+ * Construct a trade by passing in the pre-computed property values
1255
+ * @param routes The routes through which the trade occurs
1256
+ * @param tradeType The type of trade, exact input or exact output
1257
+ */
1258
+ function MixedRouteTrade(_ref) {
1259
+ var routes = _ref.routes,
1260
+ tradeType = _ref.tradeType;
1261
+ var inputCurrency = routes[0].inputAmount.currency;
1262
+ var outputCurrency = routes[0].outputAmount.currency;
1263
+ !routes.every(function (_ref2) {
1264
+ var route = _ref2.route;
1265
+ return inputCurrency.wrapped.equals(route.input.wrapped);
1266
+ }) ? process.env.NODE_ENV !== "production" ? invariant(false, 'INPUT_CURRENCY_MATCH') : invariant(false) : void 0;
1267
+ !routes.every(function (_ref3) {
1268
+ var route = _ref3.route;
1269
+ return outputCurrency.wrapped.equals(route.output.wrapped);
1270
+ }) ? process.env.NODE_ENV !== "production" ? invariant(false, 'OUTPUT_CURRENCY_MATCH') : invariant(false) : void 0;
1271
+ var numPools = routes.map(function (_ref4) {
1272
+ var route = _ref4.route;
1273
+ return route.pools.length;
1274
+ }).reduce(function (total, cur) {
1275
+ return total + cur;
1276
+ }, 0);
1277
+ var poolAddressSet = new Set();
1278
+
1279
+ for (var _iterator = _createForOfIteratorHelperLoose(routes), _step; !(_step = _iterator()).done;) {
1280
+ var route = _step.value.route;
1281
+
1282
+ for (var _iterator2 = _createForOfIteratorHelperLoose(route.pools), _step2; !(_step2 = _iterator2()).done;) {
1283
+ var pool = _step2.value;
1284
+ pool instanceof Pool ? poolAddressSet.add(Pool.getAddress(pool.token0, pool.token1, pool.fee)) : poolAddressSet.add(Pair.getAddress(pool.token0, pool.token1));
1285
+ }
1286
+ }
1287
+
1288
+ !(numPools == poolAddressSet.size) ? process.env.NODE_ENV !== "production" ? invariant(false, 'POOLS_DUPLICATED') : invariant(false) : void 0;
1289
+ !(tradeType === TradeType.EXACT_INPUT) ? process.env.NODE_ENV !== "production" ? invariant(false, 'TRADE_TYPE') : invariant(false) : void 0;
1290
+ this.swaps = routes;
1291
+ this.tradeType = tradeType;
1292
+ }
1293
+ /**
1294
+ * @deprecated Deprecated in favor of 'swaps' property. If the trade consists of multiple routes
1295
+ * this will return an error.
1296
+ *
1297
+ * When the trade consists of just a single route, this returns the route of the trade,
1298
+ * i.e. which pools the trade goes through.
1299
+ */
1300
+
1301
+
1302
+ /**
1303
+ * Constructs a trade by simulating swaps through the given route
1304
+ * @template TInput The input token, either Ether or an ERC-20.
1305
+ * @template TOutput The output token, either Ether or an ERC-20.
1306
+ * @template TTradeType The type of the trade, either exact in or exact out.
1307
+ * @param route route to swap through
1308
+ * @param amount the amount specified, either input or output, depending on tradeType
1309
+ * @param tradeType whether the trade is an exact input or exact output swap
1310
+ * @returns The route
1311
+ */
1312
+ MixedRouteTrade.fromRoute =
1313
+ /*#__PURE__*/
1314
+ function () {
1315
+ var _fromRoute = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(route, amount, tradeType) {
1316
+ var amounts, inputAmount, outputAmount, i, pool, _yield$pool$getOutput, _outputAmount;
1317
+
1318
+ return runtime_1.wrap(function _callee$(_context) {
1319
+ while (1) {
1320
+ switch (_context.prev = _context.next) {
1321
+ case 0:
1322
+ amounts = new Array(route.path.length);
1323
+ !(tradeType === TradeType.EXACT_INPUT) ? process.env.NODE_ENV !== "production" ? invariant(false, 'TRADE_TYPE') : invariant(false) : void 0;
1324
+ !amount.currency.equals(route.input) ? process.env.NODE_ENV !== "production" ? invariant(false, 'INPUT') : invariant(false) : void 0;
1325
+ amounts[0] = amount.wrapped;
1326
+ i = 0;
1327
+
1328
+ case 5:
1329
+ if (!(i < route.path.length - 1)) {
1330
+ _context.next = 15;
1331
+ break;
1332
+ }
1333
+
1334
+ pool = route.pools[i];
1335
+ _context.next = 9;
1336
+ return pool.getOutputAmount(amounts[i]);
1337
+
1338
+ case 9:
1339
+ _yield$pool$getOutput = _context.sent;
1340
+ _outputAmount = _yield$pool$getOutput[0];
1341
+ amounts[i + 1] = _outputAmount;
1342
+
1343
+ case 12:
1344
+ i++;
1345
+ _context.next = 5;
1346
+ break;
1347
+
1348
+ case 15:
1349
+ inputAmount = CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
1350
+ outputAmount = CurrencyAmount.fromFractionalAmount(route.output, amounts[amounts.length - 1].numerator, amounts[amounts.length - 1].denominator);
1351
+ return _context.abrupt("return", new MixedRouteTrade({
1352
+ routes: [{
1353
+ inputAmount: inputAmount,
1354
+ outputAmount: outputAmount,
1355
+ route: route
1356
+ }],
1357
+ tradeType: tradeType
1358
+ }));
1359
+
1360
+ case 18:
1361
+ case "end":
1362
+ return _context.stop();
1363
+ }
1364
+ }
1365
+ }, _callee);
1366
+ }));
1367
+
1368
+ function fromRoute(_x, _x2, _x3) {
1369
+ return _fromRoute.apply(this, arguments);
1370
+ }
1371
+
1372
+ return fromRoute;
1373
+ }()
1374
+ /**
1375
+ * Constructs a trade from routes by simulating swaps
1376
+ *
1377
+ * @template TInput The input token, either Ether or an ERC-20.
1378
+ * @template TOutput The output token, either Ether or an ERC-20.
1379
+ * @template TTradeType The type of the trade, either exact in or exact out.
1380
+ * @param routes the routes to swap through and how much of the amount should be routed through each
1381
+ * @param tradeType whether the trade is an exact input or exact output swap
1382
+ * @returns The trade
1383
+ */
1384
+ ;
1385
+
1386
+ MixedRouteTrade.fromRoutes =
1387
+ /*#__PURE__*/
1388
+ function () {
1389
+ var _fromRoutes = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(routes, tradeType) {
1390
+ var populatedRoutes, _iterator3, _step3, _step3$value, route, amount, amounts, inputAmount, outputAmount, i, pool, _yield$pool$getOutput2, _outputAmount2;
1391
+
1392
+ return runtime_1.wrap(function _callee2$(_context2) {
1393
+ while (1) {
1394
+ switch (_context2.prev = _context2.next) {
1395
+ case 0:
1396
+ populatedRoutes = [];
1397
+ !(tradeType === TradeType.EXACT_INPUT) ? process.env.NODE_ENV !== "production" ? invariant(false, 'TRADE_TYPE') : invariant(false) : void 0;
1398
+ _iterator3 = _createForOfIteratorHelperLoose(routes);
1399
+
1400
+ case 3:
1401
+ if ((_step3 = _iterator3()).done) {
1402
+ _context2.next = 26;
1403
+ break;
1404
+ }
1405
+
1406
+ _step3$value = _step3.value, route = _step3$value.route, amount = _step3$value.amount;
1407
+ amounts = new Array(route.path.length);
1408
+ inputAmount = void 0;
1409
+ outputAmount = void 0;
1410
+ !amount.currency.equals(route.input) ? process.env.NODE_ENV !== "production" ? invariant(false, 'INPUT') : invariant(false) : void 0;
1411
+ inputAmount = CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
1412
+ amounts[0] = CurrencyAmount.fromFractionalAmount(route.input.wrapped, amount.numerator, amount.denominator);
1413
+ i = 0;
1414
+
1415
+ case 12:
1416
+ if (!(i < route.path.length - 1)) {
1417
+ _context2.next = 22;
1418
+ break;
1419
+ }
1420
+
1421
+ pool = route.pools[i];
1422
+ _context2.next = 16;
1423
+ return pool.getOutputAmount(amounts[i]);
1424
+
1425
+ case 16:
1426
+ _yield$pool$getOutput2 = _context2.sent;
1427
+ _outputAmount2 = _yield$pool$getOutput2[0];
1428
+ amounts[i + 1] = _outputAmount2;
1429
+
1430
+ case 19:
1431
+ i++;
1432
+ _context2.next = 12;
1433
+ break;
1434
+
1435
+ case 22:
1436
+ outputAmount = CurrencyAmount.fromFractionalAmount(route.output, amounts[amounts.length - 1].numerator, amounts[amounts.length - 1].denominator);
1437
+ populatedRoutes.push({
1438
+ route: route,
1439
+ inputAmount: inputAmount,
1440
+ outputAmount: outputAmount
1441
+ });
1442
+
1443
+ case 24:
1444
+ _context2.next = 3;
1445
+ break;
1446
+
1447
+ case 26:
1448
+ return _context2.abrupt("return", new MixedRouteTrade({
1449
+ routes: populatedRoutes,
1450
+ tradeType: tradeType
1451
+ }));
1452
+
1453
+ case 27:
1454
+ case "end":
1455
+ return _context2.stop();
1456
+ }
1457
+ }
1458
+ }, _callee2);
1459
+ }));
1460
+
1461
+ function fromRoutes(_x4, _x5) {
1462
+ return _fromRoutes.apply(this, arguments);
1463
+ }
1464
+
1465
+ return fromRoutes;
1466
+ }()
1467
+ /**
1468
+ * Creates a trade without computing the result of swapping through the route. Useful when you have simulated the trade
1469
+ * elsewhere and do not have any tick data
1470
+ * @template TInput The input token, either Ether or an ERC-20
1471
+ * @template TOutput The output token, either Ether or an ERC-20
1472
+ * @template TTradeType The type of the trade, either exact in or exact out
1473
+ * @param constructorArguments The arguments passed to the trade constructor
1474
+ * @returns The unchecked trade
1475
+ */
1476
+ ;
1477
+
1478
+ MixedRouteTrade.createUncheckedTrade = function createUncheckedTrade(constructorArguments) {
1479
+ return new MixedRouteTrade(_extends({}, constructorArguments, {
1480
+ routes: [{
1481
+ inputAmount: constructorArguments.inputAmount,
1482
+ outputAmount: constructorArguments.outputAmount,
1483
+ route: constructorArguments.route
1484
+ }]
1485
+ }));
1486
+ }
1487
+ /**
1488
+ * Creates a trade without computing the result of swapping through the routes. Useful when you have simulated the trade
1489
+ * elsewhere and do not have any tick data
1490
+ * @template TInput The input token, either Ether or an ERC-20
1491
+ * @template TOutput The output token, either Ether or an ERC-20
1492
+ * @template TTradeType The type of the trade, either exact in or exact out
1493
+ * @param constructorArguments The arguments passed to the trade constructor
1494
+ * @returns The unchecked trade
1495
+ */
1496
+ ;
1497
+
1498
+ MixedRouteTrade.createUncheckedTradeWithMultipleRoutes = function createUncheckedTradeWithMultipleRoutes(constructorArguments) {
1499
+ return new MixedRouteTrade(constructorArguments);
1500
+ }
1501
+ /**
1502
+ * Get the minimum amount that must be received from this trade for the given slippage tolerance
1503
+ * @param slippageTolerance The tolerance of unfavorable slippage from the execution price of this trade
1504
+ * @returns The amount out
1505
+ */
1506
+ ;
1507
+
1508
+ var _proto = MixedRouteTrade.prototype;
1509
+
1510
+ _proto.minimumAmountOut = function minimumAmountOut(slippageTolerance, amountOut) {
1511
+ if (amountOut === void 0) {
1512
+ amountOut = this.outputAmount;
1513
+ }
1514
+
1515
+ !!slippageTolerance.lessThan(ZERO) ? process.env.NODE_ENV !== "production" ? invariant(false, 'SLIPPAGE_TOLERANCE') : invariant(false) : void 0; /// does not support exactOutput, as enforced in the constructor
1516
+
1517
+ var slippageAdjustedAmountOut = new Fraction(ONE).add(slippageTolerance).invert().multiply(amountOut.quotient).quotient;
1518
+ return CurrencyAmount.fromRawAmount(amountOut.currency, slippageAdjustedAmountOut);
1519
+ }
1520
+ /**
1521
+ * Get the maximum amount in that can be spent via this trade for the given slippage tolerance
1522
+ * @param slippageTolerance The tolerance of unfavorable slippage from the execution price of this trade
1523
+ * @returns The amount in
1524
+ */
1525
+ ;
1526
+
1527
+ _proto.maximumAmountIn = function maximumAmountIn(slippageTolerance, amountIn) {
1528
+ if (amountIn === void 0) {
1529
+ amountIn = this.inputAmount;
1530
+ }
1531
+
1532
+ !!slippageTolerance.lessThan(ZERO) ? process.env.NODE_ENV !== "production" ? invariant(false, 'SLIPPAGE_TOLERANCE') : invariant(false) : void 0;
1533
+ return amountIn; /// does not support exactOutput
1534
+ }
1535
+ /**
1536
+ * Return the execution price after accounting for slippage tolerance
1537
+ * @param slippageTolerance the allowed tolerated slippage
1538
+ * @returns The execution price
1539
+ */
1540
+ ;
1541
+
1542
+ _proto.worstExecutionPrice = function worstExecutionPrice(slippageTolerance) {
1543
+ return new Price(this.inputAmount.currency, this.outputAmount.currency, this.maximumAmountIn(slippageTolerance).quotient, this.minimumAmountOut(slippageTolerance).quotient);
1544
+ }
1545
+ /**
1546
+ * Given a list of pools, and a fixed amount in, returns the top `maxNumResults` trades that go from an input token
1547
+ * amount to an output token, making at most `maxHops` hops.
1548
+ * Note this does not consider aggregation, as routes are linear. It's possible a better route exists by splitting
1549
+ * the amount in among multiple routes.
1550
+ * @param pools the pools to consider in finding the best trade
1551
+ * @param nextAmountIn exact amount of input currency to spend
1552
+ * @param currencyOut the desired currency out
1553
+ * @param maxNumResults maximum number of results to return
1554
+ * @param maxHops maximum number of hops a returned trade can make, e.g. 1 hop goes through a single pool
1555
+ * @param currentPools used in recursion; the current list of pools
1556
+ * @param currencyAmountIn used in recursion; the original value of the currencyAmountIn parameter
1557
+ * @param bestTrades used in recursion; the current list of best trades
1558
+ * @returns The exact in trade
1559
+ */
1560
+ ;
1561
+
1562
+ MixedRouteTrade.bestTradeExactIn =
1563
+ /*#__PURE__*/
1564
+ function () {
1565
+ var _bestTradeExactIn = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee3(pools, currencyAmountIn, currencyOut, _temp, // used in recursion.
1566
+ currentPools, nextAmountIn, bestTrades) {
1567
+ var _ref5, _ref5$maxNumResults, maxNumResults, _ref5$maxHops, maxHops, amountIn, tokenOut, i, pool, amountOut, _yield$pool$getOutput3, poolsExcludingThisPool;
1568
+
1569
+ return runtime_1.wrap(function _callee3$(_context3) {
1570
+ while (1) {
1571
+ switch (_context3.prev = _context3.next) {
1572
+ case 0:
1573
+ _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;
1574
+
1575
+ if (currentPools === void 0) {
1576
+ currentPools = [];
1577
+ }
1578
+
1579
+ if (nextAmountIn === void 0) {
1580
+ nextAmountIn = currencyAmountIn;
1581
+ }
1582
+
1583
+ if (bestTrades === void 0) {
1584
+ bestTrades = [];
1585
+ }
1586
+
1587
+ !(pools.length > 0) ? process.env.NODE_ENV !== "production" ? invariant(false, 'POOLS') : invariant(false) : void 0;
1588
+ !(maxHops > 0) ? process.env.NODE_ENV !== "production" ? invariant(false, 'MAX_HOPS') : invariant(false) : void 0;
1589
+ !(currencyAmountIn === nextAmountIn || currentPools.length > 0) ? process.env.NODE_ENV !== "production" ? invariant(false, 'INVALID_RECURSION') : invariant(false) : void 0;
1590
+ amountIn = nextAmountIn.wrapped;
1591
+ tokenOut = currencyOut.wrapped;
1592
+ i = 0;
1593
+
1594
+ case 10:
1595
+ if (!(i < pools.length)) {
1596
+ _context3.next = 49;
1597
+ break;
1598
+ }
1599
+
1600
+ pool = pools[i]; // pool irrelevant
1601
+
1602
+ if (!(!pool.token0.equals(amountIn.currency) && !pool.token1.equals(amountIn.currency))) {
1603
+ _context3.next = 14;
1604
+ break;
1605
+ }
1606
+
1607
+ return _context3.abrupt("continue", 46);
1608
+
1609
+ case 14:
1610
+ if (!(pool instanceof Pair)) {
1611
+ _context3.next = 17;
1612
+ break;
1613
+ }
1614
+
1615
+ if (!(pool.reserve0.equalTo(ZERO) || pool.reserve1.equalTo(ZERO))) {
1616
+ _context3.next = 17;
1617
+ break;
1618
+ }
1619
+
1620
+ return _context3.abrupt("continue", 46);
1621
+
1622
+ case 17:
1623
+ amountOut = void 0;
1624
+ _context3.prev = 18;
1625
+ _context3.next = 22;
1626
+ return pool.getOutputAmount(amountIn);
1627
+
1628
+ case 22:
1629
+ _yield$pool$getOutput3 = _context3.sent;
1630
+ amountOut = _yield$pool$getOutput3[0];
1631
+ _context3.next = 31;
1632
+ break;
1633
+
1634
+ case 26:
1635
+ _context3.prev = 26;
1636
+ _context3.t0 = _context3["catch"](18);
1637
+
1638
+ if (!_context3.t0.isInsufficientInputAmountError) {
1639
+ _context3.next = 30;
1640
+ break;
1641
+ }
1642
+
1643
+ return _context3.abrupt("continue", 46);
1644
+
1645
+ case 30:
1646
+ throw _context3.t0;
1647
+
1648
+ case 31:
1649
+ if (!(amountOut.currency.isToken && amountOut.currency.equals(tokenOut))) {
1650
+ _context3.next = 42;
1651
+ break;
1652
+ }
1653
+
1654
+ _context3.t1 = sortedInsert;
1655
+ _context3.t2 = bestTrades;
1656
+ _context3.next = 36;
1657
+ return MixedRouteTrade.fromRoute(new MixedRouteSDK([].concat(currentPools, [pool]), currencyAmountIn.currency, currencyOut), currencyAmountIn, TradeType.EXACT_INPUT);
1658
+
1659
+ case 36:
1660
+ _context3.t3 = _context3.sent;
1661
+ _context3.t4 = maxNumResults;
1662
+ _context3.t5 = tradeComparator;
1663
+ (0, _context3.t1)(_context3.t2, _context3.t3, _context3.t4, _context3.t5);
1664
+ _context3.next = 46;
1665
+ break;
1666
+
1667
+ case 42:
1668
+ if (!(maxHops > 1 && pools.length > 1)) {
1669
+ _context3.next = 46;
1670
+ break;
1671
+ }
1672
+
1673
+ 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
1674
+
1675
+ _context3.next = 46;
1676
+ return MixedRouteTrade.bestTradeExactIn(poolsExcludingThisPool, currencyAmountIn, currencyOut, {
1677
+ maxNumResults: maxNumResults,
1678
+ maxHops: maxHops - 1
1679
+ }, [].concat(currentPools, [pool]), amountOut, bestTrades);
1680
+
1681
+ case 46:
1682
+ i++;
1683
+ _context3.next = 10;
1684
+ break;
1685
+
1686
+ case 49:
1687
+ return _context3.abrupt("return", bestTrades);
1688
+
1689
+ case 50:
1690
+ case "end":
1691
+ return _context3.stop();
1692
+ }
1693
+ }
1694
+ }, _callee3, null, [[18, 26]]);
1695
+ }));
1696
+
1697
+ function bestTradeExactIn(_x6, _x7, _x8, _x9, _x10, _x11, _x12) {
1698
+ return _bestTradeExactIn.apply(this, arguments);
1699
+ }
1700
+
1701
+ return bestTradeExactIn;
1702
+ }();
1703
+
1704
+ _createClass(MixedRouteTrade, [{
1705
+ key: "route",
1706
+ get: function get() {
1707
+ !(this.swaps.length == 1) ? process.env.NODE_ENV !== "production" ? invariant(false, 'MULTIPLE_ROUTES') : invariant(false) : void 0;
1708
+ return this.swaps[0].route;
1709
+ }
1710
+ /**
1711
+ * The input amount for the trade assuming no slippage.
1712
+ */
1713
+
1714
+ }, {
1715
+ key: "inputAmount",
1716
+ get: function get() {
1717
+ if (this._inputAmount) {
1718
+ return this._inputAmount;
1719
+ }
1720
+
1721
+ var inputCurrency = this.swaps[0].inputAmount.currency;
1722
+ var totalInputFromRoutes = this.swaps.map(function (_ref6) {
1723
+ var inputAmount = _ref6.inputAmount;
1724
+ return inputAmount;
1725
+ }).reduce(function (total, cur) {
1726
+ return total.add(cur);
1727
+ }, CurrencyAmount.fromRawAmount(inputCurrency, 0));
1728
+ this._inputAmount = totalInputFromRoutes;
1729
+ return this._inputAmount;
1730
+ }
1731
+ /**
1732
+ * The output amount for the trade assuming no slippage.
1733
+ */
1734
+
1735
+ }, {
1736
+ key: "outputAmount",
1737
+ get: function get() {
1738
+ if (this._outputAmount) {
1739
+ return this._outputAmount;
1740
+ }
1741
+
1742
+ var outputCurrency = this.swaps[0].outputAmount.currency;
1743
+ var totalOutputFromRoutes = this.swaps.map(function (_ref7) {
1744
+ var outputAmount = _ref7.outputAmount;
1745
+ return outputAmount;
1746
+ }).reduce(function (total, cur) {
1747
+ return total.add(cur);
1748
+ }, CurrencyAmount.fromRawAmount(outputCurrency, 0));
1749
+ this._outputAmount = totalOutputFromRoutes;
1750
+ return this._outputAmount;
1751
+ }
1752
+ /**
1753
+ * The price expressed in terms of output amount/input amount.
1754
+ */
1755
+
1756
+ }, {
1757
+ key: "executionPrice",
1758
+ get: function get() {
1759
+ var _this$_executionPrice;
1760
+
1761
+ return (_this$_executionPrice = this._executionPrice) != null ? _this$_executionPrice : this._executionPrice = new Price(this.inputAmount.currency, this.outputAmount.currency, this.inputAmount.quotient, this.outputAmount.quotient);
1762
+ }
1763
+ /**
1764
+ * Returns the percent difference between the route's mid price and the price impact
1765
+ */
1766
+
1767
+ }, {
1768
+ key: "priceImpact",
1769
+ get: function get() {
1770
+ if (this._priceImpact) {
1771
+ return this._priceImpact;
1772
+ }
1773
+
1774
+ var spotOutputAmount = CurrencyAmount.fromRawAmount(this.outputAmount.currency, 0);
1775
+
1776
+ for (var _iterator4 = _createForOfIteratorHelperLoose(this.swaps), _step4; !(_step4 = _iterator4()).done;) {
1777
+ var _step4$value = _step4.value,
1778
+ route = _step4$value.route,
1779
+ inputAmount = _step4$value.inputAmount;
1780
+ var midPrice = route.midPrice;
1781
+ spotOutputAmount = spotOutputAmount.add(midPrice.quote(inputAmount));
1782
+ }
1783
+
1784
+ var priceImpact = spotOutputAmount.subtract(this.outputAmount).divide(spotOutputAmount);
1785
+ this._priceImpact = new Percent(priceImpact.numerator, priceImpact.denominator);
1786
+ return this._priceImpact;
1787
+ }
1788
+ }]);
1789
+
1790
+ return MixedRouteTrade;
1791
+ }();
1792
+
1092
1793
  var Protocol;
1093
1794
 
1094
1795
  (function (Protocol) {
1095
1796
  Protocol["V2"] = "V2";
1096
1797
  Protocol["V3"] = "V3";
1798
+ Protocol["MIXED"] = "MIXED";
1097
1799
  })(Protocol || (Protocol = {}));
1098
1800
 
1099
1801
  var RouteV2 = /*#__PURE__*/function (_V2RouteSDK) {
@@ -1124,28 +1826,45 @@ var RouteV3 = /*#__PURE__*/function (_V3RouteSDK) {
1124
1826
  }
1125
1827
 
1126
1828
  return RouteV3;
1127
- }(Route$1);
1829
+ }(Route$1); // Mixed route wrapper
1830
+
1831
+ var MixedRoute = /*#__PURE__*/function (_MixedRouteSDK) {
1832
+ _inheritsLoose(MixedRoute, _MixedRouteSDK);
1833
+
1834
+ function MixedRoute(mixedRoute) {
1835
+ var _this3;
1836
+
1837
+ _this3 = _MixedRouteSDK.call(this, mixedRoute.pools, mixedRoute.input, mixedRoute.output) || this;
1838
+ _this3.protocol = Protocol.MIXED;
1839
+ return _this3;
1840
+ }
1841
+
1842
+ return MixedRoute;
1843
+ }(MixedRouteSDK);
1128
1844
 
1129
1845
  var Trade = /*#__PURE__*/function () {
1130
1846
  // construct a trade across v2 and v3 routes from pre-computed amounts
1131
1847
  function Trade(_ref) {
1132
1848
  var v2Routes = _ref.v2Routes,
1133
1849
  v3Routes = _ref.v3Routes,
1134
- tradeType = _ref.tradeType;
1850
+ tradeType = _ref.tradeType,
1851
+ mixedRoutes = _ref.mixedRoutes;
1135
1852
  this.swaps = [];
1136
1853
  this.routes = []; // wrap v2 routes
1137
1854
 
1138
1855
  for (var _iterator = _createForOfIteratorHelperLoose(v2Routes), _step; !(_step = _iterator()).done;) {
1139
1856
  var _step$value = _step.value,
1140
1857
  routev2 = _step$value.routev2,
1141
- inputAmount = _step$value.inputAmount,
1142
- outputAmount = _step$value.outputAmount;
1143
- var route = new RouteV2(routev2);
1144
- this.routes.push(route);
1858
+ _inputAmount = _step$value.inputAmount,
1859
+ _outputAmount = _step$value.outputAmount;
1860
+
1861
+ var _route = new RouteV2(routev2);
1862
+
1863
+ this.routes.push(_route);
1145
1864
  this.swaps.push({
1146
- route: route,
1147
- inputAmount: inputAmount,
1148
- outputAmount: outputAmount
1865
+ route: _route,
1866
+ inputAmount: _inputAmount,
1867
+ outputAmount: _outputAmount
1149
1868
  });
1150
1869
  } // wrap v3 routes
1151
1870
 
@@ -1153,17 +1872,34 @@ var Trade = /*#__PURE__*/function () {
1153
1872
  for (var _iterator2 = _createForOfIteratorHelperLoose(v3Routes), _step2; !(_step2 = _iterator2()).done;) {
1154
1873
  var _step2$value = _step2.value,
1155
1874
  routev3 = _step2$value.routev3,
1156
- _inputAmount = _step2$value.inputAmount,
1157
- _outputAmount = _step2$value.outputAmount;
1875
+ _inputAmount2 = _step2$value.inputAmount,
1876
+ _outputAmount2 = _step2$value.outputAmount;
1158
1877
 
1159
- var _route = new RouteV3(routev3);
1878
+ var _route2 = new RouteV3(routev3);
1160
1879
 
1161
- this.routes.push(_route);
1880
+ this.routes.push(_route2);
1162
1881
  this.swaps.push({
1163
- route: _route,
1164
- inputAmount: _inputAmount,
1165
- outputAmount: _outputAmount
1882
+ route: _route2,
1883
+ inputAmount: _inputAmount2,
1884
+ outputAmount: _outputAmount2
1166
1885
  });
1886
+ } // wrap mixedRoutes
1887
+
1888
+
1889
+ if (mixedRoutes) {
1890
+ for (var _iterator3 = _createForOfIteratorHelperLoose(mixedRoutes), _step3; !(_step3 = _iterator3()).done;) {
1891
+ var _step3$value = _step3.value,
1892
+ mixedRoute = _step3$value.mixedRoute,
1893
+ inputAmount = _step3$value.inputAmount,
1894
+ outputAmount = _step3$value.outputAmount;
1895
+ var route = new MixedRoute(mixedRoute);
1896
+ this.routes.push(route);
1897
+ this.swaps.push({
1898
+ route: route,
1899
+ inputAmount: inputAmount,
1900
+ outputAmount: outputAmount
1901
+ });
1902
+ }
1167
1903
  }
1168
1904
 
1169
1905
  this.tradeType = tradeType; // each route must have the same input and output currency
@@ -1187,17 +1923,19 @@ var Trade = /*#__PURE__*/function () {
1187
1923
  }, 0);
1188
1924
  var poolAddressSet = new Set();
1189
1925
 
1190
- for (var _iterator3 = _createForOfIteratorHelperLoose(this.swaps), _step3; !(_step3 = _iterator3()).done;) {
1191
- var _route2 = _step3.value.route;
1926
+ for (var _iterator4 = _createForOfIteratorHelperLoose(this.swaps), _step4; !(_step4 = _iterator4()).done;) {
1927
+ var _route3 = _step4.value.route;
1192
1928
 
1193
- for (var _iterator4 = _createForOfIteratorHelperLoose(_route2.pools), _step4; !(_step4 = _iterator4()).done;) {
1194
- var pool = _step4.value;
1929
+ for (var _iterator5 = _createForOfIteratorHelperLoose(_route3.pools), _step5; !(_step5 = _iterator5()).done;) {
1930
+ var pool = _step5.value;
1195
1931
 
1196
- if (_route2.protocol == Protocol.V3) {
1932
+ if (pool instanceof Pool) {
1197
1933
  poolAddressSet.add(Pool.getAddress(pool.token0, pool.token1, pool.fee));
1198
- } else {
1934
+ } else if (pool instanceof Pair) {
1199
1935
  var pair = pool;
1200
1936
  poolAddressSet.add(Pair.getAddress(pair.token0, pair.token1));
1937
+ } else {
1938
+ throw new Error('Unexpected pool type in route when constructing trade object');
1201
1939
  }
1202
1940
  }
1203
1941
  }
@@ -1259,8 +1997,8 @@ var Trade = /*#__PURE__*/function () {
1259
1997
  };
1260
1998
 
1261
1999
  Trade.fromRoutes = /*#__PURE__*/function () {
1262
- var _fromRoutes = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(v2Routes, v3Routes, tradeType) {
1263
- var populatedV2Routes, populatedV3Routes, _iterator5, _step5, _step5$value, routev2, amount, v2Trade, inputAmount, outputAmount, _iterator6, _step6, _step6$value, routev3, _amount, v3Trade, _inputAmount2, _outputAmount2;
2000
+ var _fromRoutes = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(v2Routes, v3Routes, tradeType, mixedRoutes) {
2001
+ var populatedV2Routes, populatedV3Routes, populatedMixedRoutes, _iterator6, _step6, _step6$value, routev2, _amount, v2Trade, _inputAmount3, _outputAmount3, _iterator7, _step7, _step7$value, routev3, _amount2, v3Trade, _inputAmount4, _outputAmount4, _iterator8, _step8, _step8$value, mixedRoute, amount, mixedRouteTrade, inputAmount, outputAmount;
1264
2002
 
1265
2003
  return runtime_1.wrap(function _callee$(_context) {
1266
2004
  while (1) {
@@ -1268,51 +2006,84 @@ var Trade = /*#__PURE__*/function () {
1268
2006
  case 0:
1269
2007
  populatedV2Routes = [];
1270
2008
  populatedV3Routes = [];
2009
+ populatedMixedRoutes = [];
1271
2010
 
1272
- for (_iterator5 = _createForOfIteratorHelperLoose(v2Routes); !(_step5 = _iterator5()).done;) {
1273
- _step5$value = _step5.value, routev2 = _step5$value.routev2, amount = _step5$value.amount;
1274
- v2Trade = new Trade$2(routev2, amount, tradeType);
1275
- inputAmount = v2Trade.inputAmount, outputAmount = v2Trade.outputAmount;
2011
+ for (_iterator6 = _createForOfIteratorHelperLoose(v2Routes); !(_step6 = _iterator6()).done;) {
2012
+ _step6$value = _step6.value, routev2 = _step6$value.routev2, _amount = _step6$value.amount;
2013
+ v2Trade = new Trade$2(routev2, _amount, tradeType);
2014
+ _inputAmount3 = v2Trade.inputAmount, _outputAmount3 = v2Trade.outputAmount;
1276
2015
  populatedV2Routes.push({
1277
2016
  routev2: routev2,
1278
- inputAmount: inputAmount,
1279
- outputAmount: outputAmount
2017
+ inputAmount: _inputAmount3,
2018
+ outputAmount: _outputAmount3
1280
2019
  });
1281
2020
  }
1282
2021
 
1283
- _iterator6 = _createForOfIteratorHelperLoose(v3Routes);
2022
+ _iterator7 = _createForOfIteratorHelperLoose(v3Routes);
1284
2023
 
1285
- case 4:
1286
- if ((_step6 = _iterator6()).done) {
1287
- _context.next = 13;
2024
+ case 5:
2025
+ if ((_step7 = _iterator7()).done) {
2026
+ _context.next = 14;
1288
2027
  break;
1289
2028
  }
1290
2029
 
1291
- _step6$value = _step6.value, routev3 = _step6$value.routev3, _amount = _step6$value.amount;
1292
- _context.next = 8;
1293
- return Trade$1.fromRoute(routev3, _amount, tradeType);
2030
+ _step7$value = _step7.value, routev3 = _step7$value.routev3, _amount2 = _step7$value.amount;
2031
+ _context.next = 9;
2032
+ return Trade$1.fromRoute(routev3, _amount2, tradeType);
1294
2033
 
1295
- case 8:
2034
+ case 9:
1296
2035
  v3Trade = _context.sent;
1297
- _inputAmount2 = v3Trade.inputAmount, _outputAmount2 = v3Trade.outputAmount;
2036
+ _inputAmount4 = v3Trade.inputAmount, _outputAmount4 = v3Trade.outputAmount;
1298
2037
  populatedV3Routes.push({
1299
2038
  routev3: routev3,
1300
- inputAmount: _inputAmount2,
1301
- outputAmount: _outputAmount2
2039
+ inputAmount: _inputAmount4,
2040
+ outputAmount: _outputAmount4
1302
2041
  });
1303
2042
 
1304
- case 11:
1305
- _context.next = 4;
2043
+ case 12:
2044
+ _context.next = 5;
1306
2045
  break;
1307
2046
 
1308
- case 13:
2047
+ case 14:
2048
+ if (!mixedRoutes) {
2049
+ _context.next = 25;
2050
+ break;
2051
+ }
2052
+
2053
+ _iterator8 = _createForOfIteratorHelperLoose(mixedRoutes);
2054
+
2055
+ case 16:
2056
+ if ((_step8 = _iterator8()).done) {
2057
+ _context.next = 25;
2058
+ break;
2059
+ }
2060
+
2061
+ _step8$value = _step8.value, mixedRoute = _step8$value.mixedRoute, amount = _step8$value.amount;
2062
+ _context.next = 20;
2063
+ return MixedRouteTrade.fromRoute(mixedRoute, amount, tradeType);
2064
+
2065
+ case 20:
2066
+ mixedRouteTrade = _context.sent;
2067
+ inputAmount = mixedRouteTrade.inputAmount, outputAmount = mixedRouteTrade.outputAmount;
2068
+ populatedMixedRoutes.push({
2069
+ mixedRoute: mixedRoute,
2070
+ inputAmount: inputAmount,
2071
+ outputAmount: outputAmount
2072
+ });
2073
+
2074
+ case 23:
2075
+ _context.next = 16;
2076
+ break;
2077
+
2078
+ case 25:
1309
2079
  return _context.abrupt("return", new Trade({
1310
2080
  v2Routes: populatedV2Routes,
1311
2081
  v3Routes: populatedV3Routes,
2082
+ mixedRoutes: populatedMixedRoutes,
1312
2083
  tradeType: tradeType
1313
2084
  }));
1314
2085
 
1315
- case 14:
2086
+ case 26:
1316
2087
  case "end":
1317
2088
  return _context.stop();
1318
2089
  }
@@ -1320,7 +2091,7 @@ var Trade = /*#__PURE__*/function () {
1320
2091
  }, _callee);
1321
2092
  }));
1322
2093
 
1323
- function fromRoutes(_x, _x2, _x3) {
2094
+ function fromRoutes(_x, _x2, _x3, _x4) {
1324
2095
  return _fromRoutes.apply(this, arguments);
1325
2096
  }
1326
2097
 
@@ -1329,14 +2100,18 @@ var Trade = /*#__PURE__*/function () {
1329
2100
 
1330
2101
  Trade.fromRoute = /*#__PURE__*/function () {
1331
2102
  var _fromRoute = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee2(route, amount, tradeType) {
1332
- var v2Routes, v3Routes, v2Trade, inputAmount, outputAmount, v3Trade, _inputAmount3, _outputAmount3;
2103
+ var v2Routes, v3Routes, mixedRoutes, v2Trade, inputAmount, outputAmount, v3Trade, _inputAmount5, _outputAmount5, mixedRouteTrade, _inputAmount6, _outputAmount6;
1333
2104
 
1334
2105
  return runtime_1.wrap(function _callee2$(_context2) {
1335
2106
  while (1) {
1336
2107
  switch (_context2.prev = _context2.next) {
1337
2108
  case 0:
2109
+ v2Routes = [];
2110
+ v3Routes = [];
2111
+ mixedRoutes = [];
2112
+
1338
2113
  if (!(route instanceof Route)) {
1339
- _context2.next = 7;
2114
+ _context2.next = 9;
1340
2115
  break;
1341
2116
  }
1342
2117
 
@@ -1347,32 +2122,61 @@ var Trade = /*#__PURE__*/function () {
1347
2122
  inputAmount: inputAmount,
1348
2123
  outputAmount: outputAmount
1349
2124
  }];
1350
- v3Routes = [];
1351
- _context2.next = 13;
2125
+ _context2.next = 26;
1352
2126
  break;
1353
2127
 
1354
- case 7:
1355
- _context2.next = 9;
2128
+ case 9:
2129
+ if (!(route instanceof Route$1)) {
2130
+ _context2.next = 17;
2131
+ break;
2132
+ }
2133
+
2134
+ _context2.next = 12;
1356
2135
  return Trade$1.fromRoute(route, amount, tradeType);
1357
2136
 
1358
- case 9:
2137
+ case 12:
1359
2138
  v3Trade = _context2.sent;
1360
- _inputAmount3 = v3Trade.inputAmount, _outputAmount3 = v3Trade.outputAmount;
2139
+ _inputAmount5 = v3Trade.inputAmount, _outputAmount5 = v3Trade.outputAmount;
1361
2140
  v3Routes = [{
1362
2141
  routev3: route,
1363
- inputAmount: _inputAmount3,
1364
- outputAmount: _outputAmount3
2142
+ inputAmount: _inputAmount5,
2143
+ outputAmount: _outputAmount5
1365
2144
  }];
1366
- v2Routes = [];
2145
+ _context2.next = 26;
2146
+ break;
2147
+
2148
+ case 17:
2149
+ if (!(route instanceof MixedRouteSDK)) {
2150
+ _context2.next = 25;
2151
+ break;
2152
+ }
2153
+
2154
+ _context2.next = 20;
2155
+ return MixedRouteTrade.fromRoute(route, amount, tradeType);
2156
+
2157
+ case 20:
2158
+ mixedRouteTrade = _context2.sent;
2159
+ _inputAmount6 = mixedRouteTrade.inputAmount, _outputAmount6 = mixedRouteTrade.outputAmount;
2160
+ mixedRoutes = [{
2161
+ mixedRoute: route,
2162
+ inputAmount: _inputAmount6,
2163
+ outputAmount: _outputAmount6
2164
+ }];
2165
+ _context2.next = 26;
2166
+ break;
2167
+
2168
+ case 25:
2169
+ throw new Error('Invalid route type');
1367
2170
 
1368
- case 13:
2171
+ case 26:
1369
2172
  return _context2.abrupt("return", new Trade({
1370
2173
  v2Routes: v2Routes,
1371
2174
  v3Routes: v3Routes,
2175
+ mixedRoutes: mixedRoutes,
1372
2176
  tradeType: tradeType
1373
2177
  }));
1374
2178
 
1375
- case 14:
2179
+ case 27:
1376
2180
  case "end":
1377
2181
  return _context2.stop();
1378
2182
  }
@@ -1380,7 +2184,7 @@ var Trade = /*#__PURE__*/function () {
1380
2184
  }, _callee2);
1381
2185
  }));
1382
2186
 
1383
- function fromRoute(_x4, _x5, _x6) {
2187
+ function fromRoute(_x5, _x6, _x7) {
1384
2188
  return _fromRoute.apply(this, arguments);
1385
2189
  }
1386
2190
 
@@ -1445,10 +2249,10 @@ var Trade = /*#__PURE__*/function () {
1445
2249
 
1446
2250
  var spotOutputAmount = CurrencyAmount.fromRawAmount(this.outputAmount.currency, 0);
1447
2251
 
1448
- for (var _iterator7 = _createForOfIteratorHelperLoose(this.swaps), _step7; !(_step7 = _iterator7()).done;) {
1449
- var _step7$value = _step7.value,
1450
- route = _step7$value.route,
1451
- inputAmount = _step7$value.inputAmount;
2252
+ for (var _iterator9 = _createForOfIteratorHelperLoose(this.swaps), _step9; !(_step9 = _iterator9()).done;) {
2253
+ var _step9$value = _step9.value,
2254
+ route = _step9$value.route,
2255
+ inputAmount = _step9$value.inputAmount;
1452
2256
  var midPrice = route.midPrice;
1453
2257
  spotOutputAmount = spotOutputAmount.add(midPrice.quote(inputAmount));
1454
2258
  }
@@ -1462,6 +2266,97 @@ var Trade = /*#__PURE__*/function () {
1462
2266
  return Trade;
1463
2267
  }();
1464
2268
 
2269
+ /**
2270
+ * Converts a route to a hex encoded path
2271
+ * @notice only supports exactIn route encodings
2272
+ * @param route the mixed path to convert to an encoded path
2273
+ * @returns the exactIn encoded path
2274
+ */
2275
+
2276
+ function encodeMixedRouteToPath(route) {
2277
+ var firstInputToken = route.input.wrapped;
2278
+
2279
+ var _route$pools$reduce = route.pools.reduce(function (_ref, pool, index) {
2280
+ var inputToken = _ref.inputToken,
2281
+ path = _ref.path,
2282
+ types = _ref.types;
2283
+ var outputToken = pool.token0.equals(inputToken) ? pool.token1 : pool.token0;
2284
+
2285
+ if (index === 0) {
2286
+ return {
2287
+ inputToken: outputToken,
2288
+ types: ['address', 'uint24', 'address'],
2289
+ path: [inputToken.address, pool instanceof Pool ? pool.fee : V2_FEE_PATH_PLACEHOLDER, outputToken.address]
2290
+ };
2291
+ } else {
2292
+ return {
2293
+ inputToken: outputToken,
2294
+ types: [].concat(types, ['uint24', 'address']),
2295
+ path: [].concat(path, [pool instanceof Pool ? pool.fee : V2_FEE_PATH_PLACEHOLDER, outputToken.address])
2296
+ };
2297
+ }
2298
+ }, {
2299
+ inputToken: firstInputToken,
2300
+ path: [],
2301
+ types: []
2302
+ }),
2303
+ path = _route$pools$reduce.path,
2304
+ types = _route$pools$reduce.types;
2305
+
2306
+ return pack(types, path);
2307
+ }
2308
+
2309
+ /**
2310
+ * Utility function to return each consecutive section of Pools or Pairs in a MixedRoute
2311
+ * @param route
2312
+ * @returns a nested array of Pools or Pairs in the order of the route
2313
+ */
2314
+
2315
+ var partitionMixedRouteByProtocol = function partitionMixedRouteByProtocol(route) {
2316
+ var acc = [];
2317
+ var left = 0;
2318
+ var right = 0;
2319
+
2320
+ while (right < route.pools.length) {
2321
+ if (route.pools[left] instanceof Pool && route.pools[right] instanceof Pair || route.pools[left] instanceof Pair && route.pools[right] instanceof Pool) {
2322
+ acc.push(route.pools.slice(left, right));
2323
+ left = right;
2324
+ } // seek forward with right pointer
2325
+
2326
+
2327
+ right++;
2328
+
2329
+ if (right === route.pools.length) {
2330
+ /// we reached the end, take the rest
2331
+ acc.push(route.pools.slice(left, right));
2332
+ }
2333
+ }
2334
+
2335
+ return acc;
2336
+ };
2337
+ /**
2338
+ * Simple utility function to get the output of an array of Pools or Pairs
2339
+ * @param pools
2340
+ * @param firstInputToken
2341
+ * @returns the output token of the last pool in the array
2342
+ */
2343
+
2344
+ var getOutputOfPools = function getOutputOfPools(pools, firstInputToken) {
2345
+ var _pools$reduce = pools.reduce(function (_ref, pool) {
2346
+ var inputToken = _ref.inputToken;
2347
+ if (!pool.involvesToken(inputToken)) throw new Error('PATH');
2348
+ var outputToken = pool.token0.equals(inputToken) ? pool.token1 : pool.token0;
2349
+ return {
2350
+ inputToken: outputToken
2351
+ };
2352
+ }, {
2353
+ inputToken: firstInputToken
2354
+ }),
2355
+ outputToken = _pools$reduce.inputToken;
2356
+
2357
+ return outputToken;
2358
+ };
2359
+
1465
2360
  var ZERO$1 = /*#__PURE__*/JSBI.BigInt(0);
1466
2361
  var REFUND_ETH_PRICE_IMPACT_THRESHOLD = /*#__PURE__*/new Percent( /*#__PURE__*/JSBI.BigInt(50), /*#__PURE__*/JSBI.BigInt(100));
1467
2362
  /**
@@ -1473,6 +2368,15 @@ var SwapRouter = /*#__PURE__*/function () {
1473
2368
  * Cannot be constructed.
1474
2369
  */
1475
2370
  function SwapRouter() {}
2371
+ /**
2372
+ * @notice Generates the calldata for a Swap with a V2 Route.
2373
+ * @param trade The V2Trade to encode.
2374
+ * @param options SwapOptions to use for the trade.
2375
+ * @param routerMustCustody Flag for whether funds should be sent to the router
2376
+ * @param performAggregatedSlippageCheck Flag for whether we want to perform an aggregated slippage check
2377
+ * @returns A string array of calldatas for the trade.
2378
+ */
2379
+
1476
2380
 
1477
2381
  SwapRouter.encodeV2Swap = function encodeV2Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck) {
1478
2382
  var amountIn = toHex(trade.maximumAmountIn(options.slippageTolerance).quotient);
@@ -1489,7 +2393,16 @@ var SwapRouter = /*#__PURE__*/function () {
1489
2393
  var exactOutputParams = [amountOut, amountIn, path, recipient];
1490
2394
  return SwapRouter.INTERFACE.encodeFunctionData('swapTokensForExactTokens', exactOutputParams);
1491
2395
  }
1492
- };
2396
+ }
2397
+ /**
2398
+ * @notice Generates the calldata for a Swap with a V3 Route.
2399
+ * @param trade The V3Trade to encode.
2400
+ * @param options SwapOptions to use for the trade.
2401
+ * @param routerMustCustody Flag for whether funds should be sent to the router
2402
+ * @param performAggregatedSlippageCheck Flag for whether we want to perform an aggregated slippage check
2403
+ * @returns A string array of calldatas for the trade.
2404
+ */
2405
+ ;
1493
2406
 
1494
2407
  SwapRouter.encodeV3Swap = function encodeV3Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck) {
1495
2408
  var calldatas = [];
@@ -1552,36 +2465,145 @@ var SwapRouter = /*#__PURE__*/function () {
1552
2465
  }
1553
2466
  }
1554
2467
 
2468
+ return calldatas;
2469
+ }
2470
+ /**
2471
+ * @notice Generates the calldata for a MixedRouteSwap. Since single hop routes are not MixedRoutes, we will instead generate
2472
+ * them via the existing encodeV3Swap and encodeV2Swap methods.
2473
+ * @param trade The MixedRouteTrade to encode.
2474
+ * @param options SwapOptions to use for the trade.
2475
+ * @param routerMustCustody Flag for whether funds should be sent to the router
2476
+ * @param performAggregatedSlippageCheck Flag for whether we want to perform an aggregated slippage check
2477
+ * @returns A string array of calldatas for the trade.
2478
+ */
2479
+ ;
2480
+
2481
+ SwapRouter.encodeMixedRouteSwap = function encodeMixedRouteSwap(trade, options, routerMustCustody, performAggregatedSlippageCheck) {
2482
+ var calldatas = [];
2483
+ !(trade.tradeType === TradeType.EXACT_INPUT) ? process.env.NODE_ENV !== "production" ? invariant(false, 'TRADE_TYPE') : invariant(false) : void 0;
2484
+
2485
+ for (var _iterator2 = _createForOfIteratorHelperLoose(trade.swaps), _step2; !(_step2 = _iterator2()).done;) {
2486
+ var _step2$value = _step2.value,
2487
+ route = _step2$value.route,
2488
+ inputAmount = _step2$value.inputAmount,
2489
+ outputAmount = _step2$value.outputAmount;
2490
+ var amountIn = toHex(trade.maximumAmountIn(options.slippageTolerance, inputAmount).quotient);
2491
+ var amountOut = toHex(trade.minimumAmountOut(options.slippageTolerance, outputAmount).quotient); // flag for whether the trade is single hop or not
2492
+
2493
+ var singleHop = route.pools.length === 1;
2494
+ var recipient = routerMustCustody ? ADDRESS_THIS : typeof options.recipient === 'undefined' ? MSG_SENDER : validateAndParseAddress(options.recipient);
2495
+
2496
+ var mixedRouteIsAllV3 = function mixedRouteIsAllV3(route) {
2497
+ return route.pools.every(function (pool) {
2498
+ return pool instanceof Pool;
2499
+ });
2500
+ };
2501
+
2502
+ if (singleHop) {
2503
+ /// For single hop, since it isn't really a mixedRoute, we'll just mimic behavior of V3 or V2
2504
+ /// We don't use encodeV3Swap() or encodeV2Swap() because casting the trade to a V3Trade or V2Trade is overcomplex
2505
+ if (mixedRouteIsAllV3(route)) {
2506
+ var exactInputSingleParams = {
2507
+ tokenIn: route.path[0].address,
2508
+ tokenOut: route.path[1].address,
2509
+ fee: route.pools[0].fee,
2510
+ recipient: recipient,
2511
+ amountIn: amountIn,
2512
+ amountOutMinimum: performAggregatedSlippageCheck ? 0 : amountOut,
2513
+ sqrtPriceLimitX96: 0
2514
+ };
2515
+ calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('exactInputSingle', [exactInputSingleParams]));
2516
+ } else {
2517
+ var path = route.path.map(function (token) {
2518
+ return token.address;
2519
+ });
2520
+ var exactInputParams = [amountIn, performAggregatedSlippageCheck ? 0 : amountOut, path, recipient];
2521
+ calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('swapExactTokensForTokens', exactInputParams));
2522
+ }
2523
+ } else {
2524
+ (function () {
2525
+ var sections = partitionMixedRouteByProtocol(route);
2526
+
2527
+ var isLastSectionInRoute = function isLastSectionInRoute(i) {
2528
+ return i === sections.length - 1;
2529
+ };
2530
+
2531
+ var outputToken = void 0;
2532
+ var inputToken = route.input.wrapped;
2533
+
2534
+ for (var i = 0; i < sections.length; i++) {
2535
+ var section = sections[i]; /// Now, we get output of this section
2536
+
2537
+ outputToken = getOutputOfPools(section, inputToken);
2538
+ var newRouteOriginal = new MixedRouteSDK([].concat(section), section[0].token0.equals(inputToken) ? section[0].token0 : section[0].token1, outputToken);
2539
+ var newRoute = new MixedRoute(newRouteOriginal); /// Previous output is now input
2540
+
2541
+ inputToken = outputToken;
2542
+
2543
+ if (mixedRouteIsAllV3(newRoute)) {
2544
+ var _path = encodeMixedRouteToPath(newRoute);
2545
+
2546
+ var _exactInputParams = {
2547
+ path: _path,
2548
+ // By default router holds funds until the last swap, then it is sent to the recipient
2549
+ // special case exists where we are unwrapping WETH output, in which case `routerMustCustody` is set to true
2550
+ // and router still holds the funds. That logic bundled into how the value of `recipient` is calculated
2551
+ recipient: isLastSectionInRoute(i) ? recipient : ADDRESS_THIS,
2552
+ amountIn: i == 0 ? amountIn : 0,
2553
+ amountOutMinimum: !isLastSectionInRoute(i) ? 0 : amountOut
2554
+ };
2555
+ calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('exactInput', [_exactInputParams]));
2556
+ } else {
2557
+ var _exactInputParams2 = [i == 0 ? amountIn : 0, !isLastSectionInRoute(i) ? 0 : amountOut, newRoute.path.map(function (token) {
2558
+ return token.address;
2559
+ }), isLastSectionInRoute(i) ? recipient : ADDRESS_THIS];
2560
+ calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('swapExactTokensForTokens', _exactInputParams2));
2561
+ }
2562
+ }
2563
+ })();
2564
+ }
2565
+ }
2566
+
1555
2567
  return calldatas;
1556
2568
  };
1557
2569
 
1558
2570
  SwapRouter.encodeSwaps = function encodeSwaps(trades, options, isSwapAndAdd) {
1559
- // If dealing with an instance of the aggregated Trade object, unbundle it to individual V2Trade and V3Trade objects.
2571
+ // If dealing with an instance of the aggregated Trade object, unbundle it to individual trade objects.
1560
2572
  if (trades instanceof Trade) {
1561
2573
  !trades.swaps.every(function (swap) {
1562
- return swap.route.protocol == Protocol.V3 || swap.route.protocol == Protocol.V2;
2574
+ return swap.route.protocol == Protocol.V3 || swap.route.protocol == Protocol.V2 || swap.route.protocol == Protocol.MIXED;
1563
2575
  }) ? process.env.NODE_ENV !== "production" ? invariant(false, 'UNSUPPORTED_PROTOCOL') : invariant(false) : void 0;
1564
- var v2Andv3Trades = [];
2576
+ var individualTrades = [];
1565
2577
 
1566
- for (var _iterator2 = _createForOfIteratorHelperLoose(trades.swaps), _step2; !(_step2 = _iterator2()).done;) {
1567
- var _step2$value = _step2.value,
1568
- route = _step2$value.route,
1569
- inputAmount = _step2$value.inputAmount,
1570
- outputAmount = _step2$value.outputAmount;
2578
+ for (var _iterator3 = _createForOfIteratorHelperLoose(trades.swaps), _step3; !(_step3 = _iterator3()).done;) {
2579
+ var _step3$value = _step3.value,
2580
+ route = _step3$value.route,
2581
+ inputAmount = _step3$value.inputAmount,
2582
+ outputAmount = _step3$value.outputAmount;
1571
2583
 
1572
2584
  if (route.protocol == Protocol.V2) {
1573
- v2Andv3Trades.push(new Trade$2(route, trades.tradeType == TradeType.EXACT_INPUT ? inputAmount : outputAmount, trades.tradeType));
2585
+ individualTrades.push(new Trade$2(route, trades.tradeType == TradeType.EXACT_INPUT ? inputAmount : outputAmount, trades.tradeType));
1574
2586
  } else if (route.protocol == Protocol.V3) {
1575
- v2Andv3Trades.push(Trade$1.createUncheckedTrade({
2587
+ individualTrades.push(Trade$1.createUncheckedTrade({
2588
+ route: route,
2589
+ inputAmount: inputAmount,
2590
+ outputAmount: outputAmount,
2591
+ tradeType: trades.tradeType
2592
+ }));
2593
+ } else if (route.protocol == Protocol.MIXED) {
2594
+ individualTrades.push( /// we can change the naming of this function on MixedRouteTrade if needed
2595
+ MixedRouteTrade.createUncheckedTrade({
1576
2596
  route: route,
1577
2597
  inputAmount: inputAmount,
1578
2598
  outputAmount: outputAmount,
1579
2599
  tradeType: trades.tradeType
1580
2600
  }));
2601
+ } else {
2602
+ throw new Error('UNSUPPORTED_TRADE_PROTOCOL');
1581
2603
  }
1582
2604
  }
1583
2605
 
1584
- trades = v2Andv3Trades;
2606
+ trades = individualTrades;
1585
2607
  }
1586
2608
 
1587
2609
  if (!Array.isArray(trades)) {
@@ -1589,7 +2611,7 @@ var SwapRouter = /*#__PURE__*/function () {
1589
2611
  }
1590
2612
 
1591
2613
  var numberOfTrades = trades.reduce(function (numberOfTrades, trade) {
1592
- return numberOfTrades + (trade instanceof Trade$1 ? trade.swaps.length : 1);
2614
+ return numberOfTrades + (trade instanceof Trade$1 || trade instanceof MixedRouteTrade ? trade.swaps.length : 1);
1593
2615
  }, 0);
1594
2616
  var sampleTrade = trades[0]; // All trades should have the same starting/ending currency and trade type
1595
2617
 
@@ -1622,16 +2644,23 @@ var SwapRouter = /*#__PURE__*/function () {
1622
2644
  calldatas.push(SelfPermit.encodePermit(sampleTrade.inputAmount.currency, options.inputTokenPermit));
1623
2645
  }
1624
2646
 
1625
- for (var _iterator3 = _createForOfIteratorHelperLoose(trades), _step3; !(_step3 = _iterator3()).done;) {
1626
- var trade = _step3.value;
2647
+ for (var _iterator4 = _createForOfIteratorHelperLoose(trades), _step4; !(_step4 = _iterator4()).done;) {
2648
+ var trade = _step4.value;
1627
2649
 
1628
2650
  if (trade instanceof Trade$2) {
1629
2651
  calldatas.push(SwapRouter.encodeV2Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck));
1630
- } else {
1631
- for (var _iterator4 = _createForOfIteratorHelperLoose(SwapRouter.encodeV3Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck)), _step4; !(_step4 = _iterator4()).done;) {
1632
- var calldata = _step4.value;
2652
+ } else if (trade instanceof Trade$1) {
2653
+ for (var _iterator5 = _createForOfIteratorHelperLoose(SwapRouter.encodeV3Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck)), _step5; !(_step5 = _iterator5()).done;) {
2654
+ var calldata = _step5.value;
1633
2655
  calldatas.push(calldata);
1634
2656
  }
2657
+ } else if (trade instanceof MixedRouteTrade) {
2658
+ for (var _iterator6 = _createForOfIteratorHelperLoose(SwapRouter.encodeMixedRouteSwap(trade, options, routerMustCustody, performAggregatedSlippageCheck)), _step6; !(_step6 = _iterator6()).done;) {
2659
+ var _calldata = _step6.value;
2660
+ calldatas.push(_calldata);
2661
+ }
2662
+ } else {
2663
+ throw new Error('Unsupported trade object');
1635
2664
  }
1636
2665
  }
1637
2666
 
@@ -1659,7 +2688,7 @@ var SwapRouter = /*#__PURE__*/function () {
1659
2688
  }
1660
2689
  /**
1661
2690
  * Produces the on-chain method name to call and the hex encoded parameters to pass as arguments for a given trade.
1662
- * @param trade to produce call parameters for
2691
+ * @param trades to produce call parameters for
1663
2692
  * @param options options for the call parameters
1664
2693
  */
1665
2694
  ;
@@ -1696,7 +2725,7 @@ var SwapRouter = /*#__PURE__*/function () {
1696
2725
  }
1697
2726
  /**
1698
2727
  * Produces the on-chain method name to call and the hex encoded parameters to pass as arguments for a given trade.
1699
- * @param trade to produce call parameters for
2728
+ * @param trades to produce call parameters for
1700
2729
  * @param options options for the call parameters
1701
2730
  */
1702
2731
  ;
@@ -1808,5 +2837,5 @@ var SwapRouter = /*#__PURE__*/function () {
1808
2837
  }();
1809
2838
  SwapRouter.INTERFACE = /*#__PURE__*/new Interface(abi$3);
1810
2839
 
1811
- export { ADDRESS_THIS, ApprovalTypes, ApproveAndCall, MSG_SENDER, MulticallExtended, ONE, PaymentsExtended, Protocol, RouteV2, RouteV3, SwapRouter, Trade, ZERO, isMint };
2840
+ export { ADDRESS_THIS, ApprovalTypes, ApproveAndCall, MSG_SENDER, MixedRoute, MixedRouteSDK, MulticallExtended, ONE, PaymentsExtended, Protocol, RouteV2, RouteV3, SwapRouter, Trade, V2_FEE_PATH_PLACEHOLDER, ZERO, encodeMixedRouteToPath, getOutputOfPools, isMint, partitionMixedRouteByProtocol };
1812
2841
  //# sourceMappingURL=router-sdk.esm.js.map