@uniswap/router-sdk 1.0.0-beta.3 → 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,12 +1,12 @@
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';
5
- import { abi as abi$1 } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IPeripheryPaymentsWithFeeExtended.sol/IPeripheryPaymentsWithFeeExtended.json';
4
+ import { Multicall, toHex, Payments, Route as Route$1, Pool, Trade as Trade$1, encodeRouteToPath, SelfPermit } from '@uniswap/v3-sdk';
6
5
  import { validateAndParseAddress, TradeType, Fraction, CurrencyAmount, Price, Percent } from '@uniswap/sdk-core';
7
- import invariant from 'tiny-invariant';
6
+ import { abi as abi$1 } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IPeripheryPaymentsWithFeeExtended.sol/IPeripheryPaymentsWithFeeExtended.json';
8
7
  import { abi as abi$2 } from '@uniswap/swap-router-contracts/artifacts/contracts/interfaces/ISwapRouter02.sol/ISwapRouter02.json';
9
- import { Route, Trade as Trade$2 } from '@uniswap/v2-sdk';
8
+ import { Route, Pair, Trade as Trade$2 } from '@uniswap/v2-sdk';
9
+ import invariant from 'tiny-invariant';
10
10
 
11
11
  var MSG_SENDER = '0x0000000000000000000000000000000000000000';
12
12
  var ADDRESS_THIS = '0x0000000000000000000000000000000000000001';
@@ -39,7 +39,7 @@ var MulticallExtended = /*#__PURE__*/function () {
39
39
  } // this means the validation value should be a previousBlockhash
40
40
 
41
41
 
42
- if (typeof validation === 'string') {
42
+ if (typeof validation === 'string' && validation.startsWith('0x')) {
43
43
  var previousBlockhash = validateAndParseBytes32(validation);
44
44
  return MulticallExtended.INTERFACE.encodeFunctionData('multicall(bytes32,bytes[])', [previousBlockhash, calldatas]);
45
45
  } else {
@@ -52,16 +52,16 @@ var MulticallExtended = /*#__PURE__*/function () {
52
52
  }();
53
53
  MulticallExtended.INTERFACE = /*#__PURE__*/new Interface(abi);
54
54
 
55
+ function encodeFeeBips(fee) {
56
+ return toHex(fee.multiply(10000).quotient);
57
+ }
58
+
55
59
  var PaymentsExtended = /*#__PURE__*/function () {
56
60
  /**
57
61
  * Cannot be constructed.
58
62
  */
59
63
  function PaymentsExtended() {}
60
64
 
61
- PaymentsExtended.encodeFeeBips = function encodeFeeBips(fee) {
62
- return toHex(fee.multiply(10000).quotient);
63
- };
64
-
65
65
  PaymentsExtended.encodeUnwrapWETH9 = function encodeUnwrapWETH9(amountMinimum, recipient, feeOptions) {
66
66
  // if there's a recipient, just pass it along
67
67
  if (typeof recipient === 'string') {
@@ -69,7 +69,7 @@ var PaymentsExtended = /*#__PURE__*/function () {
69
69
  }
70
70
 
71
71
  if (!!feeOptions) {
72
- var feeBips = this.encodeFeeBips(feeOptions.fee);
72
+ var feeBips = encodeFeeBips(feeOptions.fee);
73
73
  var feeRecipient = validateAndParseAddress(feeOptions.recipient);
74
74
  return PaymentsExtended.INTERFACE.encodeFunctionData('unwrapWETH9WithFee(uint256,uint256,address)', [toHex(amountMinimum), feeBips, feeRecipient]);
75
75
  } else {
@@ -84,7 +84,7 @@ var PaymentsExtended = /*#__PURE__*/function () {
84
84
  }
85
85
 
86
86
  if (!!feeOptions) {
87
- var feeBips = this.encodeFeeBips(feeOptions.fee);
87
+ var feeBips = encodeFeeBips(feeOptions.fee);
88
88
  var feeRecipient = validateAndParseAddress(feeOptions.recipient);
89
89
  return PaymentsExtended.INTERFACE.encodeFunctionData('sweepTokenWithFee(address,uint256,uint256,address)', [token.address, toHex(amountMinimum), feeBips, feeRecipient]);
90
90
  } else {
@@ -96,6 +96,10 @@ var PaymentsExtended = /*#__PURE__*/function () {
96
96
  return PaymentsExtended.INTERFACE.encodeFunctionData('pull', [token.address, toHex(amount)]);
97
97
  };
98
98
 
99
+ PaymentsExtended.encodeWrapETH = function encodeWrapETH(amount) {
100
+ return PaymentsExtended.INTERFACE.encodeFunctionData('wrapETH', [toHex(amount)]);
101
+ };
102
+
99
103
  return PaymentsExtended;
100
104
  }();
101
105
  PaymentsExtended.INTERFACE = /*#__PURE__*/new Interface(abi$1);
@@ -206,6 +210,13 @@ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
206
210
  throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
207
211
  }
208
212
 
213
+ var Protocol;
214
+
215
+ (function (Protocol) {
216
+ Protocol["V2"] = "V2";
217
+ Protocol["V3"] = "V3";
218
+ })(Protocol || (Protocol = {}));
219
+
209
220
  function createCommonjsModule(fn, module) {
210
221
  return module = { exports: {} }, fn(module, module.exports), module.exports;
211
222
  }
@@ -966,13 +977,6 @@ try {
966
977
  }
967
978
  });
968
979
 
969
- var Protocol;
970
-
971
- (function (Protocol) {
972
- Protocol["V2"] = "V2";
973
- Protocol["V3"] = "V3";
974
- })(Protocol || (Protocol = {}));
975
-
976
980
  var RouteV2 = /*#__PURE__*/function (_V2RouteSDK) {
977
981
  _inheritsLoose(RouteV2, _V2RouteSDK);
978
982
 
@@ -1043,7 +1047,43 @@ var Trade = /*#__PURE__*/function () {
1043
1047
  });
1044
1048
  }
1045
1049
 
1046
- 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;
1047
1087
  }
1048
1088
 
1049
1089
  var _proto = Trade.prototype;
@@ -1101,7 +1141,7 @@ var Trade = /*#__PURE__*/function () {
1101
1141
 
1102
1142
  Trade.fromRoutes = /*#__PURE__*/function () {
1103
1143
  var _fromRoutes = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(v2Routes, v3Routes, tradeType) {
1104
- 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;
1105
1145
 
1106
1146
  return runtime_1.wrap(function _callee$(_context) {
1107
1147
  while (1) {
@@ -1110,8 +1150,8 @@ var Trade = /*#__PURE__*/function () {
1110
1150
  populatedV2Routes = [];
1111
1151
  populatedV3Routes = [];
1112
1152
 
1113
- for (_iterator3 = _createForOfIteratorHelperLoose(v2Routes); !(_step3 = _iterator3()).done;) {
1114
- _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;
1115
1155
  v2Trade = new Trade$2(routev2, amount, tradeType);
1116
1156
  inputAmount = v2Trade.inputAmount, outputAmount = v2Trade.outputAmount;
1117
1157
  populatedV2Routes.push({
@@ -1121,15 +1161,15 @@ var Trade = /*#__PURE__*/function () {
1121
1161
  });
1122
1162
  }
1123
1163
 
1124
- _iterator4 = _createForOfIteratorHelperLoose(v3Routes);
1164
+ _iterator6 = _createForOfIteratorHelperLoose(v3Routes);
1125
1165
 
1126
1166
  case 4:
1127
- if ((_step4 = _iterator4()).done) {
1167
+ if ((_step6 = _iterator6()).done) {
1128
1168
  _context.next = 13;
1129
1169
  break;
1130
1170
  }
1131
1171
 
1132
- _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;
1133
1173
  _context.next = 8;
1134
1174
  return Trade$1.fromRoute(routev3, _amount, tradeType);
1135
1175
 
@@ -1236,8 +1276,8 @@ var Trade = /*#__PURE__*/function () {
1236
1276
  }
1237
1277
 
1238
1278
  var inputCurrency = this.swaps[0].inputAmount.currency;
1239
- var totalInputFromRoutes = this.swaps.map(function (_ref2) {
1240
- var inputAmount = _ref2.inputAmount;
1279
+ var totalInputFromRoutes = this.swaps.map(function (_ref5) {
1280
+ var inputAmount = _ref5.inputAmount;
1241
1281
  return inputAmount;
1242
1282
  }).reduce(function (total, cur) {
1243
1283
  return total.add(cur);
@@ -1253,8 +1293,8 @@ var Trade = /*#__PURE__*/function () {
1253
1293
  }
1254
1294
 
1255
1295
  var outputCurrency = this.swaps[0].outputAmount.currency;
1256
- var totalOutputFromRoutes = this.swaps.map(function (_ref3) {
1257
- var outputAmount = _ref3.outputAmount;
1296
+ var totalOutputFromRoutes = this.swaps.map(function (_ref6) {
1297
+ var outputAmount = _ref6.outputAmount;
1258
1298
  return outputAmount;
1259
1299
  }).reduce(function (total, cur) {
1260
1300
  return total.add(cur);
@@ -1286,10 +1326,10 @@ var Trade = /*#__PURE__*/function () {
1286
1326
 
1287
1327
  var spotOutputAmount = CurrencyAmount.fromRawAmount(this.outputAmount.currency, 0);
1288
1328
 
1289
- for (var _iterator5 = _createForOfIteratorHelperLoose(this.swaps), _step5; !(_step5 = _iterator5()).done;) {
1290
- var _step5$value = _step5.value,
1291
- route = _step5$value.route,
1292
- 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;
1293
1333
  var midPrice = route.midPrice;
1294
1334
  spotOutputAmount = spotOutputAmount.add(midPrice.quote(inputAmount));
1295
1335
  }
@@ -1303,7 +1343,6 @@ var Trade = /*#__PURE__*/function () {
1303
1343
  return Trade;
1304
1344
  }();
1305
1345
 
1306
- var ZERO$1 = /*#__PURE__*/JSBI.BigInt(0);
1307
1346
  /**
1308
1347
  * Represents the Uniswap V2 + V3 SwapRouter02, and has static methods for helping execute trades.
1309
1348
  */
@@ -1314,18 +1353,16 @@ var SwapRouter = /*#__PURE__*/function () {
1314
1353
  */
1315
1354
  function SwapRouter() {}
1316
1355
 
1317
- SwapRouter.encodeV2Swap = function encodeV2Swap(trade, options, routerMustCustody) {
1356
+ SwapRouter.encodeV2Swap = function encodeV2Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck) {
1318
1357
  var amountIn = toHex(trade.maximumAmountIn(options.slippageTolerance).quotient);
1319
1358
  var amountOut = toHex(trade.minimumAmountOut(options.slippageTolerance).quotient);
1320
1359
  var path = trade.route.path.map(function (token) {
1321
1360
  return token.address;
1322
1361
  });
1323
- var recipient = routerMustCustody ? ADDRESS_THIS : options.recipient ? validateAndParseAddress(options.recipient) : MSG_SENDER;
1362
+ var recipient = routerMustCustody ? ADDRESS_THIS : typeof options.recipient === 'undefined' ? MSG_SENDER : validateAndParseAddress(options.recipient);
1324
1363
 
1325
1364
  if (trade.tradeType === TradeType.EXACT_INPUT) {
1326
- var exactInputParams = [amountIn, // save gas by only passing slippage check if we can't check it later
1327
- // not a pure win, as sometimes this will cost us more when it would have caused an earlier failure
1328
- routerMustCustody ? 0 : amountOut, path, recipient];
1365
+ var exactInputParams = [amountIn, performAggregatedSlippageCheck ? 0 : amountOut, path, recipient];
1329
1366
  return SwapRouter.INTERFACE.encodeFunctionData('swapExactTokensForTokens', exactInputParams);
1330
1367
  } else {
1331
1368
  var exactOutputParams = [amountOut, amountIn, path, recipient];
@@ -1333,7 +1370,7 @@ var SwapRouter = /*#__PURE__*/function () {
1333
1370
  }
1334
1371
  };
1335
1372
 
1336
- SwapRouter.encodeV3Swap = function encodeV3Swap(trade, options, routerMustCustody) {
1373
+ SwapRouter.encodeV3Swap = function encodeV3Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck) {
1337
1374
  var calldatas = [];
1338
1375
 
1339
1376
  for (var _iterator = _createForOfIteratorHelperLoose(trade.swaps), _step; !(_step = _iterator()).done;) {
@@ -1345,7 +1382,7 @@ var SwapRouter = /*#__PURE__*/function () {
1345
1382
  var amountOut = toHex(trade.minimumAmountOut(options.slippageTolerance, outputAmount).quotient); // flag for whether the trade is single hop or not
1346
1383
 
1347
1384
  var singleHop = route.pools.length === 1;
1348
- var recipient = routerMustCustody ? ADDRESS_THIS : options.recipient ? validateAndParseAddress(options.recipient) : MSG_SENDER;
1385
+ var recipient = routerMustCustody ? ADDRESS_THIS : typeof options.recipient === 'undefined' ? MSG_SENDER : validateAndParseAddress(options.recipient);
1349
1386
 
1350
1387
  if (singleHop) {
1351
1388
  if (trade.tradeType === TradeType.EXACT_INPUT) {
@@ -1355,7 +1392,7 @@ var SwapRouter = /*#__PURE__*/function () {
1355
1392
  fee: route.pools[0].fee,
1356
1393
  recipient: recipient,
1357
1394
  amountIn: amountIn,
1358
- amountOutMinimum: amountOut,
1395
+ amountOutMinimum: performAggregatedSlippageCheck ? 0 : amountOut,
1359
1396
  sqrtPriceLimitX96: 0
1360
1397
  };
1361
1398
  calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('exactInputSingle', [exactInputSingleParams]));
@@ -1379,7 +1416,7 @@ var SwapRouter = /*#__PURE__*/function () {
1379
1416
  path: path,
1380
1417
  recipient: recipient,
1381
1418
  amountIn: amountIn,
1382
- amountOutMinimum: amountOut
1419
+ amountOutMinimum: performAggregatedSlippageCheck ? 0 : amountOut
1383
1420
  };
1384
1421
  calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('exactInput', [exactInputParams]));
1385
1422
  } else {
@@ -1436,6 +1473,9 @@ var SwapRouter = /*#__PURE__*/function () {
1436
1473
  trades = [trades];
1437
1474
  }
1438
1475
 
1476
+ var numberOfTrades = trades.reduce(function (numberOfTrades, trade) {
1477
+ return numberOfTrades + (trade instanceof Trade$1 ? trade.swaps.length : 1);
1478
+ }, 0);
1439
1479
  var sampleTrade = trades[0]; // All trades should have the same starting/ending currency and trade type
1440
1480
 
1441
1481
  !trades.every(function (trade) {
@@ -1457,13 +1497,17 @@ var SwapRouter = /*#__PURE__*/function () {
1457
1497
  var outputIsNative = sampleTrade.outputAmount.currency.isNative; // flag for whether a refund needs to happen
1458
1498
  // 1. when paying in ETH, but with an uncertain input amount
1459
1499
 
1460
- 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
1461
1506
  // 1. when receiving ETH (which much be unwrapped from WETH)
1462
1507
  // 2. when a fee on the output is being taken
1463
- // 3. when there are >1 exact input trades. this one isn't strictly necessary,
1464
- // but typically we want to perform an aggregated slippage check
1508
+ // 3. when performing an aggregated slippage check
1465
1509
 
1466
- var routerMustCustody = outputIsNative || !!options.fee || trades.length > 1 && sampleTrade.tradeType === TradeType.EXACT_INPUT;
1510
+ var routerMustCustody = outputIsNative || !!options.fee || performAggregatedSlippageCheck;
1467
1511
  var totalValue = inputIsNative ? trades.reduce(function (sum, trade) {
1468
1512
  return sum.add(trade.maximumAmountIn(options.slippageTolerance));
1469
1513
  }, ZERO_IN) : ZERO_IN; // encode permit if necessary
@@ -1477,25 +1521,21 @@ var SwapRouter = /*#__PURE__*/function () {
1477
1521
  var trade = _step3.value;
1478
1522
 
1479
1523
  if (trade instanceof Trade$2) {
1480
- calldatas.push(SwapRouter.encodeV2Swap(trade, options, routerMustCustody));
1524
+ calldatas.push(SwapRouter.encodeV2Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck));
1481
1525
  } else {
1482
- 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;) {
1483
1527
  var calldata = _step4.value;
1484
1528
  calldatas.push(calldata);
1485
1529
  }
1486
1530
  }
1487
- } // unwrap
1531
+ } // unwrap or sweep
1488
1532
 
1489
1533
 
1490
1534
  if (routerMustCustody) {
1491
- // if all trades are exact output, we can save gas by not passing a slippage check
1492
- var canOmitSlippageCheck = sampleTrade.tradeType === TradeType.EXACT_OUTPUT;
1493
- var amountNecessary = canOmitSlippageCheck ? ZERO$1 : totalAmountOut.quotient;
1494
-
1495
1535
  if (outputIsNative) {
1496
- calldatas.push(PaymentsExtended.encodeUnwrapWETH9(amountNecessary, options.recipient, options.fee));
1536
+ calldatas.push(PaymentsExtended.encodeUnwrapWETH9(totalAmountOut.quotient, options.recipient, options.fee));
1497
1537
  } else {
1498
- 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));
1499
1539
  }
1500
1540
  } // refund
1501
1541