@uniswap/router-sdk 1.0.0-beta.6 → 1.0.0-beta.7

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.
@@ -1,11 +1,11 @@
1
1
  import JSBI from 'jsbi';
2
2
  import { Interface } from '@ethersproject/abi';
3
- import { Multicall, toHex, Payments, Route as Route$1, Trade as Trade$1, encodeRouteToPath, SelfPermit } from '@uniswap/v3-sdk';
4
3
  import { abi } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IMulticallExtended.sol/IMulticallExtended.json';
4
+ import { Multicall, toHex, Payments, Route as Route$1, Pool, Trade as Trade$1, encodeRouteToPath, SelfPermit } from '@uniswap/v3-sdk';
5
5
  import { validateAndParseAddress, TradeType, Fraction, CurrencyAmount, Price, Percent } from '@uniswap/sdk-core';
6
6
  import { abi as abi$1 } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IPeripheryPaymentsWithFeeExtended.sol/IPeripheryPaymentsWithFeeExtended.json';
7
7
  import { abi as abi$2 } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/ISwapRouter02.sol/ISwapRouter02.json';
8
- import { Route, Trade as Trade$2 } from '@uniswap/v2-sdk';
8
+ import { Route, Pair, Trade as Trade$2 } from '@uniswap/v2-sdk';
9
9
  import invariant from 'tiny-invariant';
10
10
 
11
11
  var MSG_SENDER = '0x0000000000000000000000000000000000000000';
@@ -1047,7 +1047,43 @@ var Trade = /*#__PURE__*/function () {
1047
1047
  });
1048
1048
  }
1049
1049
 
1050
- this.tradeType = tradeType;
1050
+ this.tradeType = tradeType; // each route must have the same input and output currency
1051
+
1052
+ var inputCurrency = this.swaps[0].inputAmount.currency;
1053
+ var outputCurrency = this.swaps[0].outputAmount.currency;
1054
+ !this.swaps.every(function (_ref2) {
1055
+ var route = _ref2.route;
1056
+ return inputCurrency.wrapped.equals(route.input.wrapped);
1057
+ }) ? process.env.NODE_ENV !== "production" ? invariant(false, 'INPUT_CURRENCY_MATCH') : invariant(false) : void 0;
1058
+ !this.swaps.every(function (_ref3) {
1059
+ var route = _ref3.route;
1060
+ return outputCurrency.wrapped.equals(route.output.wrapped);
1061
+ }) ? process.env.NODE_ENV !== "production" ? invariant(false, 'OUTPUT_CURRENCY_MATCH') : invariant(false) : void 0; // pools must be unique inter protocols
1062
+
1063
+ var numPools = this.swaps.map(function (_ref4) {
1064
+ var route = _ref4.route;
1065
+ return route.pools.length;
1066
+ }).reduce(function (total, cur) {
1067
+ return total + cur;
1068
+ }, 0);
1069
+ var poolAddressSet = new Set();
1070
+
1071
+ for (var _iterator3 = _createForOfIteratorHelperLoose(this.swaps), _step3; !(_step3 = _iterator3()).done;) {
1072
+ var _route2 = _step3.value.route;
1073
+
1074
+ for (var _iterator4 = _createForOfIteratorHelperLoose(_route2.pools), _step4; !(_step4 = _iterator4()).done;) {
1075
+ var pool = _step4.value;
1076
+
1077
+ if (_route2.protocol == Protocol.V3) {
1078
+ poolAddressSet.add(Pool.getAddress(pool.token0, pool.token1, pool.fee));
1079
+ } else {
1080
+ var pair = pool;
1081
+ poolAddressSet.add(Pair.getAddress(pair.token0, pair.token1));
1082
+ }
1083
+ }
1084
+ }
1085
+
1086
+ !(numPools == poolAddressSet.size) ? process.env.NODE_ENV !== "production" ? invariant(false, 'POOLS_DUPLICATED') : invariant(false) : void 0;
1051
1087
  }
1052
1088
 
1053
1089
  var _proto = Trade.prototype;
@@ -1105,7 +1141,7 @@ var Trade = /*#__PURE__*/function () {
1105
1141
 
1106
1142
  Trade.fromRoutes = /*#__PURE__*/function () {
1107
1143
  var _fromRoutes = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(v2Routes, v3Routes, tradeType) {
1108
- var populatedV2Routes, populatedV3Routes, _iterator3, _step3, _step3$value, routev2, amount, v2Trade, inputAmount, outputAmount, _iterator4, _step4, _step4$value, routev3, _amount, v3Trade, _inputAmount2, _outputAmount2;
1144
+ var populatedV2Routes, populatedV3Routes, _iterator5, _step5, _step5$value, routev2, amount, v2Trade, inputAmount, outputAmount, _iterator6, _step6, _step6$value, routev3, _amount, v3Trade, _inputAmount2, _outputAmount2;
1109
1145
 
1110
1146
  return runtime_1.wrap(function _callee$(_context) {
1111
1147
  while (1) {
@@ -1114,8 +1150,8 @@ var Trade = /*#__PURE__*/function () {
1114
1150
  populatedV2Routes = [];
1115
1151
  populatedV3Routes = [];
1116
1152
 
1117
- for (_iterator3 = _createForOfIteratorHelperLoose(v2Routes); !(_step3 = _iterator3()).done;) {
1118
- _step3$value = _step3.value, routev2 = _step3$value.routev2, amount = _step3$value.amount;
1153
+ for (_iterator5 = _createForOfIteratorHelperLoose(v2Routes); !(_step5 = _iterator5()).done;) {
1154
+ _step5$value = _step5.value, routev2 = _step5$value.routev2, amount = _step5$value.amount;
1119
1155
  v2Trade = new Trade$2(routev2, amount, tradeType);
1120
1156
  inputAmount = v2Trade.inputAmount, outputAmount = v2Trade.outputAmount;
1121
1157
  populatedV2Routes.push({
@@ -1125,15 +1161,15 @@ var Trade = /*#__PURE__*/function () {
1125
1161
  });
1126
1162
  }
1127
1163
 
1128
- _iterator4 = _createForOfIteratorHelperLoose(v3Routes);
1164
+ _iterator6 = _createForOfIteratorHelperLoose(v3Routes);
1129
1165
 
1130
1166
  case 4:
1131
- if ((_step4 = _iterator4()).done) {
1167
+ if ((_step6 = _iterator6()).done) {
1132
1168
  _context.next = 13;
1133
1169
  break;
1134
1170
  }
1135
1171
 
1136
- _step4$value = _step4.value, routev3 = _step4$value.routev3, _amount = _step4$value.amount;
1172
+ _step6$value = _step6.value, routev3 = _step6$value.routev3, _amount = _step6$value.amount;
1137
1173
  _context.next = 8;
1138
1174
  return Trade$1.fromRoute(routev3, _amount, tradeType);
1139
1175
 
@@ -1240,8 +1276,8 @@ var Trade = /*#__PURE__*/function () {
1240
1276
  }
1241
1277
 
1242
1278
  var inputCurrency = this.swaps[0].inputAmount.currency;
1243
- var totalInputFromRoutes = this.swaps.map(function (_ref2) {
1244
- var inputAmount = _ref2.inputAmount;
1279
+ var totalInputFromRoutes = this.swaps.map(function (_ref5) {
1280
+ var inputAmount = _ref5.inputAmount;
1245
1281
  return inputAmount;
1246
1282
  }).reduce(function (total, cur) {
1247
1283
  return total.add(cur);
@@ -1257,8 +1293,8 @@ var Trade = /*#__PURE__*/function () {
1257
1293
  }
1258
1294
 
1259
1295
  var outputCurrency = this.swaps[0].outputAmount.currency;
1260
- var totalOutputFromRoutes = this.swaps.map(function (_ref3) {
1261
- var outputAmount = _ref3.outputAmount;
1296
+ var totalOutputFromRoutes = this.swaps.map(function (_ref6) {
1297
+ var outputAmount = _ref6.outputAmount;
1262
1298
  return outputAmount;
1263
1299
  }).reduce(function (total, cur) {
1264
1300
  return total.add(cur);
@@ -1290,10 +1326,10 @@ var Trade = /*#__PURE__*/function () {
1290
1326
 
1291
1327
  var spotOutputAmount = CurrencyAmount.fromRawAmount(this.outputAmount.currency, 0);
1292
1328
 
1293
- for (var _iterator5 = _createForOfIteratorHelperLoose(this.swaps), _step5; !(_step5 = _iterator5()).done;) {
1294
- var _step5$value = _step5.value,
1295
- route = _step5$value.route,
1296
- inputAmount = _step5$value.inputAmount;
1329
+ for (var _iterator7 = _createForOfIteratorHelperLoose(this.swaps), _step7; !(_step7 = _iterator7()).done;) {
1330
+ var _step7$value = _step7.value,
1331
+ route = _step7$value.route,
1332
+ inputAmount = _step7$value.inputAmount;
1297
1333
  var midPrice = route.midPrice;
1298
1334
  spotOutputAmount = spotOutputAmount.add(midPrice.quote(inputAmount));
1299
1335
  }
@@ -1307,7 +1343,6 @@ var Trade = /*#__PURE__*/function () {
1307
1343
  return Trade;
1308
1344
  }();
1309
1345
 
1310
- var ZERO$1 = /*#__PURE__*/JSBI.BigInt(0);
1311
1346
  /**
1312
1347
  * Represents the Uniswap V2 + V3 SwapRouter02, and has static methods for helping execute trades.
1313
1348
  */
@@ -1318,7 +1353,7 @@ var SwapRouter = /*#__PURE__*/function () {
1318
1353
  */
1319
1354
  function SwapRouter() {}
1320
1355
 
1321
- SwapRouter.encodeV2Swap = function encodeV2Swap(trade, options, routerMustCustody) {
1356
+ SwapRouter.encodeV2Swap = function encodeV2Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck) {
1322
1357
  var amountIn = toHex(trade.maximumAmountIn(options.slippageTolerance).quotient);
1323
1358
  var amountOut = toHex(trade.minimumAmountOut(options.slippageTolerance).quotient);
1324
1359
  var path = trade.route.path.map(function (token) {
@@ -1327,9 +1362,7 @@ var SwapRouter = /*#__PURE__*/function () {
1327
1362
  var recipient = routerMustCustody ? ADDRESS_THIS : typeof options.recipient === 'undefined' ? MSG_SENDER : validateAndParseAddress(options.recipient);
1328
1363
 
1329
1364
  if (trade.tradeType === TradeType.EXACT_INPUT) {
1330
- var exactInputParams = [amountIn, // save gas by only passing slippage check if we can't check it later
1331
- // not a pure win, as sometimes this will cost us more when it would have caused an earlier failure
1332
- routerMustCustody ? 0 : amountOut, path, recipient, false];
1365
+ var exactInputParams = [amountIn, performAggregatedSlippageCheck ? 0 : amountOut, path, recipient];
1333
1366
  return SwapRouter.INTERFACE.encodeFunctionData('swapExactTokensForTokens', exactInputParams);
1334
1367
  } else {
1335
1368
  var exactOutputParams = [amountOut, amountIn, path, recipient];
@@ -1337,7 +1370,7 @@ var SwapRouter = /*#__PURE__*/function () {
1337
1370
  }
1338
1371
  };
1339
1372
 
1340
- SwapRouter.encodeV3Swap = function encodeV3Swap(trade, options, routerMustCustody) {
1373
+ SwapRouter.encodeV3Swap = function encodeV3Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck) {
1341
1374
  var calldatas = [];
1342
1375
 
1343
1376
  for (var _iterator = _createForOfIteratorHelperLoose(trade.swaps), _step; !(_step = _iterator()).done;) {
@@ -1359,9 +1392,8 @@ var SwapRouter = /*#__PURE__*/function () {
1359
1392
  fee: route.pools[0].fee,
1360
1393
  recipient: recipient,
1361
1394
  amountIn: amountIn,
1362
- amountOutMinimum: amountOut,
1363
- sqrtPriceLimitX96: 0,
1364
- hasAlreadyPaid: false
1395
+ amountOutMinimum: performAggregatedSlippageCheck ? 0 : amountOut,
1396
+ sqrtPriceLimitX96: 0
1365
1397
  };
1366
1398
  calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('exactInputSingle', [exactInputSingleParams]));
1367
1399
  } else {
@@ -1384,8 +1416,7 @@ var SwapRouter = /*#__PURE__*/function () {
1384
1416
  path: path,
1385
1417
  recipient: recipient,
1386
1418
  amountIn: amountIn,
1387
- amountOutMinimum: amountOut,
1388
- hasAlreadyPaid: false
1419
+ amountOutMinimum: performAggregatedSlippageCheck ? 0 : amountOut
1389
1420
  };
1390
1421
  calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('exactInput', [exactInputParams]));
1391
1422
  } else {
@@ -1442,6 +1473,9 @@ var SwapRouter = /*#__PURE__*/function () {
1442
1473
  trades = [trades];
1443
1474
  }
1444
1475
 
1476
+ var numberOfTrades = trades.reduce(function (numberOfTrades, trade) {
1477
+ return numberOfTrades + (trade instanceof Trade$1 ? trade.swaps.length : 1);
1478
+ }, 0);
1445
1479
  var sampleTrade = trades[0]; // All trades should have the same starting/ending currency and trade type
1446
1480
 
1447
1481
  !trades.every(function (trade) {
@@ -1463,13 +1497,17 @@ var SwapRouter = /*#__PURE__*/function () {
1463
1497
  var outputIsNative = sampleTrade.outputAmount.currency.isNative; // flag for whether a refund needs to happen
1464
1498
  // 1. when paying in ETH, but with an uncertain input amount
1465
1499
 
1466
- var mustRefund = inputIsNative && sampleTrade.tradeType === TradeType.EXACT_OUTPUT; // flag for whether funds should be send first to the router
1500
+ var mustRefund = inputIsNative && sampleTrade.tradeType === TradeType.EXACT_OUTPUT; // flag for whether we want to perform an aggregated slippage check
1501
+ // 1. when there are >2 exact input trades. this is only a heuristic,
1502
+ // as it's still more gas-expensive even in this case, but has benefits
1503
+ // in that the reversion probability is lower
1504
+
1505
+ var performAggregatedSlippageCheck = sampleTrade.tradeType === TradeType.EXACT_INPUT && numberOfTrades > 2; // flag for whether funds should be send first to the router
1467
1506
  // 1. when receiving ETH (which much be unwrapped from WETH)
1468
1507
  // 2. when a fee on the output is being taken
1469
- // 3. when there are >1 exact input trades. this one isn't strictly necessary,
1470
- // but typically we want to perform an aggregated slippage check
1508
+ // 3. when performing an aggregated slippage check
1471
1509
 
1472
- var routerMustCustody = outputIsNative || !!options.fee || trades.length > 1 && sampleTrade.tradeType === TradeType.EXACT_INPUT;
1510
+ var routerMustCustody = outputIsNative || !!options.fee || performAggregatedSlippageCheck;
1473
1511
  var totalValue = inputIsNative ? trades.reduce(function (sum, trade) {
1474
1512
  return sum.add(trade.maximumAmountIn(options.slippageTolerance));
1475
1513
  }, ZERO_IN) : ZERO_IN; // encode permit if necessary
@@ -1483,25 +1521,21 @@ var SwapRouter = /*#__PURE__*/function () {
1483
1521
  var trade = _step3.value;
1484
1522
 
1485
1523
  if (trade instanceof Trade$2) {
1486
- calldatas.push(SwapRouter.encodeV2Swap(trade, options, routerMustCustody));
1524
+ calldatas.push(SwapRouter.encodeV2Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck));
1487
1525
  } else {
1488
- for (var _iterator4 = _createForOfIteratorHelperLoose(SwapRouter.encodeV3Swap(trade, options, routerMustCustody)), _step4; !(_step4 = _iterator4()).done;) {
1526
+ for (var _iterator4 = _createForOfIteratorHelperLoose(SwapRouter.encodeV3Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck)), _step4; !(_step4 = _iterator4()).done;) {
1489
1527
  var calldata = _step4.value;
1490
1528
  calldatas.push(calldata);
1491
1529
  }
1492
1530
  }
1493
- } // unwrap
1531
+ } // unwrap or sweep
1494
1532
 
1495
1533
 
1496
1534
  if (routerMustCustody) {
1497
- // if all trades are exact output, we can save gas by not passing a slippage check
1498
- var canOmitSlippageCheck = sampleTrade.tradeType === TradeType.EXACT_OUTPUT;
1499
- var amountNecessary = canOmitSlippageCheck ? ZERO$1 : totalAmountOut.quotient;
1500
-
1501
1535
  if (outputIsNative) {
1502
- calldatas.push(PaymentsExtended.encodeUnwrapWETH9(amountNecessary, options.recipient, options.fee));
1536
+ calldatas.push(PaymentsExtended.encodeUnwrapWETH9(totalAmountOut.quotient, options.recipient, options.fee));
1503
1537
  } else {
1504
- calldatas.push(PaymentsExtended.encodeSweepToken(sampleTrade.outputAmount.currency.wrapped, amountNecessary, options.recipient, options.fee));
1538
+ calldatas.push(PaymentsExtended.encodeSweepToken(sampleTrade.outputAmount.currency.wrapped, totalAmountOut.quotient, options.recipient, options.fee));
1505
1539
  }
1506
1540
  } // refund
1507
1541