@uniswap/router-sdk 1.0.0-beta.4 → 1.0.0-beta.8

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.
package/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # Alpha software
2
+
3
+ The latest version of the SDK is used in production in the Uniswap Interface,
4
+ but it is considered Alpha software and may contain bugs or change significantly between patch versions.
5
+ If you have questions about how to use the SDK, please reach out in the `#dev-chat` channel of the Discord.
6
+ Pull requests welcome!
7
+
8
+ # Uniswap Swap Router SDK
9
+
10
+ This SDK is meant to facilitate interactions with the contracts in [swap-router-contracts](https://github.com/Uniswap/swap-router-contracts).
@@ -0,0 +1,22 @@
1
+ import { Interface } from '@ethersproject/abi';
2
+ import { Currency, Token } from '@uniswap/sdk-core';
3
+ export declare enum ApprovalTypes {
4
+ NOT_REQUIRED = 0,
5
+ MAX = 1,
6
+ MAX_MINUS_ONE = 2,
7
+ ZERO_THEN_MAX = 3,
8
+ ZERO_THEN_MAX_MINUS_ONE = 4
9
+ }
10
+ export declare abstract class ApproveAndCall {
11
+ static INTERFACE: Interface;
12
+ /**
13
+ * Cannot be constructed.
14
+ */
15
+ private constructor();
16
+ static encodeApproveMax(token: Token): string;
17
+ static encodeApproveMaxMinusOne(token: Token): string;
18
+ static encodeApproveZeroThenMax(token: Token): string;
19
+ static encodeApproveZeroThenMaxMinusOne(token: Token): string;
20
+ static encodeCallPositionManager(calldatas: string[]): string;
21
+ static encodeApprove(token: Currency, approvalType: ApprovalTypes): string;
22
+ }
@@ -2,11 +2,13 @@ import { Route as V2RouteSDK, Pair } from '@uniswap/v2-sdk';
2
2
  import { Route as V3RouteSDK, Pool } from '@uniswap/v3-sdk';
3
3
  import { Protocol } from './protocol';
4
4
  import { Currency, Price, Token } from '@uniswap/sdk-core';
5
- export interface IRoute<TInput extends Currency, TOutput extends Currency, TPool extends (Pool | Pair)> {
5
+ export interface IRoute<TInput extends Currency, TOutput extends Currency, TPool extends Pool | Pair> {
6
6
  protocol: Protocol;
7
7
  pools: TPool[];
8
8
  path: Token[];
9
9
  midPrice: Price<TInput, TOutput>;
10
+ input: TInput;
11
+ output: TOutput;
10
12
  }
11
13
  export declare class RouteV2<TInput extends Currency, TOutput extends Currency> extends V2RouteSDK<TInput, TOutput> implements IRoute<TInput, TOutput, Pair> {
12
14
  readonly protocol: Protocol;
@@ -1,9 +1,9 @@
1
1
  import { Currency, CurrencyAmount, Percent, Price, TradeType } from '@uniswap/sdk-core';
2
+ import { Pair, Route as V2RouteSDK } from '@uniswap/v2-sdk';
3
+ import { Pool, Route as V3RouteSDK } from '@uniswap/v3-sdk';
2
4
  import { IRoute } from './route';
3
- import { Route as V2RouteSDK, Pair } from '@uniswap/v2-sdk';
4
- import { Route as V3RouteSDK, Pool } from '@uniswap/v3-sdk';
5
5
  export declare class Trade<TInput extends Currency, TOutput extends Currency, TTradeType extends TradeType> {
6
- readonly routes: IRoute<TInput, TOutput, (Pair | Pool)>[];
6
+ readonly routes: IRoute<TInput, TOutput, Pair | Pool>[];
7
7
  readonly tradeType: TTradeType;
8
8
  private _outputAmount;
9
9
  private _inputAmount;
@@ -12,7 +12,7 @@ export declare class Trade<TInput extends Currency, TOutput extends Currency, TT
12
12
  * make up the trade. May consist of swaps in v2 or v3.
13
13
  */
14
14
  readonly swaps: {
15
- route: IRoute<TInput, TOutput, (Pair | Pool)>;
15
+ route: IRoute<TInput, TOutput, Pair | Pool>;
16
16
  inputAmount: CurrencyAmount<TInput>;
17
17
  outputAmount: CurrencyAmount<TOutput>;
18
18
  }[];
@@ -1,15 +1,15 @@
1
- import JSBI from 'jsbi';
2
1
  import { Interface } from '@ethersproject/abi';
3
- import { FeeOptions } from '@uniswap/v3-sdk';
4
2
  import { Token } from '@uniswap/sdk-core';
3
+ import { FeeOptions } from '@uniswap/v3-sdk';
4
+ import JSBI from 'jsbi';
5
5
  export declare abstract class PaymentsExtended {
6
6
  static INTERFACE: Interface;
7
7
  /**
8
8
  * Cannot be constructed.
9
9
  */
10
10
  private constructor();
11
- private static encodeFeeBips;
12
11
  static encodeUnwrapWETH9(amountMinimum: JSBI, recipient?: string, feeOptions?: FeeOptions): string;
13
12
  static encodeSweepToken(token: Token, amountMinimum: JSBI, recipient?: string, feeOptions?: FeeOptions): string;
14
13
  static encodePull(token: Token, amount: JSBI): string;
14
+ static encodeWrapETH(amount: JSBI): string;
15
15
  }
@@ -6,13 +6,14 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau
6
6
 
7
7
  var JSBI = _interopDefault(require('jsbi'));
8
8
  var abi = require('@ethersproject/abi');
9
- var v3Sdk = require('@uniswap/v3-sdk');
10
9
  var IMulticallExtended_json = require('@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IMulticallExtended.sol/IMulticallExtended.json');
11
- var IPeripheryPaymentsWithFeeExtended_json = require('@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IPeripheryPaymentsWithFeeExtended.sol/IPeripheryPaymentsWithFeeExtended.json');
10
+ var v3Sdk = require('@uniswap/v3-sdk');
12
11
  var sdkCore = require('@uniswap/sdk-core');
13
- var invariant = _interopDefault(require('tiny-invariant'));
12
+ var IPeripheryPaymentsWithFeeExtended_json = require('@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IPeripheryPaymentsWithFeeExtended.sol/IPeripheryPaymentsWithFeeExtended.json');
14
13
  var ISwapRouter02_json = require('@uniswap/swap-router-contracts/artifacts/contracts/interfaces/ISwapRouter02.sol/ISwapRouter02.json');
15
14
  var v2Sdk = require('@uniswap/v2-sdk');
15
+ var invariant = _interopDefault(require('tiny-invariant'));
16
+ var IApproveAndCall_json = require('@uniswap/swap-router-contracts/artifacts/contracts/interfaces/IApproveAndCall.sol/IApproveAndCall.json');
16
17
 
17
18
  var MSG_SENDER = '0x0000000000000000000000000000000000000000';
18
19
  var ADDRESS_THIS = '0x0000000000000000000000000000000000000001';
@@ -45,7 +46,7 @@ var MulticallExtended = /*#__PURE__*/function () {
45
46
  } // this means the validation value should be a previousBlockhash
46
47
 
47
48
 
48
- if (typeof validation === 'string') {
49
+ if (typeof validation === 'string' && validation.startsWith('0x')) {
49
50
  var previousBlockhash = validateAndParseBytes32(validation);
50
51
  return MulticallExtended.INTERFACE.encodeFunctionData('multicall(bytes32,bytes[])', [previousBlockhash, calldatas]);
51
52
  } else {
@@ -58,16 +59,16 @@ var MulticallExtended = /*#__PURE__*/function () {
58
59
  }();
59
60
  MulticallExtended.INTERFACE = /*#__PURE__*/new abi.Interface(IMulticallExtended_json.abi);
60
61
 
62
+ function encodeFeeBips(fee) {
63
+ return v3Sdk.toHex(fee.multiply(10000).quotient);
64
+ }
65
+
61
66
  var PaymentsExtended = /*#__PURE__*/function () {
62
67
  /**
63
68
  * Cannot be constructed.
64
69
  */
65
70
  function PaymentsExtended() {}
66
71
 
67
- PaymentsExtended.encodeFeeBips = function encodeFeeBips(fee) {
68
- return v3Sdk.toHex(fee.multiply(10000).quotient);
69
- };
70
-
71
72
  PaymentsExtended.encodeUnwrapWETH9 = function encodeUnwrapWETH9(amountMinimum, recipient, feeOptions) {
72
73
  // if there's a recipient, just pass it along
73
74
  if (typeof recipient === 'string') {
@@ -75,7 +76,7 @@ var PaymentsExtended = /*#__PURE__*/function () {
75
76
  }
76
77
 
77
78
  if (!!feeOptions) {
78
- var feeBips = this.encodeFeeBips(feeOptions.fee);
79
+ var feeBips = encodeFeeBips(feeOptions.fee);
79
80
  var feeRecipient = sdkCore.validateAndParseAddress(feeOptions.recipient);
80
81
  return PaymentsExtended.INTERFACE.encodeFunctionData('unwrapWETH9WithFee(uint256,uint256,address)', [v3Sdk.toHex(amountMinimum), feeBips, feeRecipient]);
81
82
  } else {
@@ -90,7 +91,7 @@ var PaymentsExtended = /*#__PURE__*/function () {
90
91
  }
91
92
 
92
93
  if (!!feeOptions) {
93
- var feeBips = this.encodeFeeBips(feeOptions.fee);
94
+ var feeBips = encodeFeeBips(feeOptions.fee);
94
95
  var feeRecipient = sdkCore.validateAndParseAddress(feeOptions.recipient);
95
96
  return PaymentsExtended.INTERFACE.encodeFunctionData('sweepTokenWithFee(address,uint256,uint256,address)', [token.address, v3Sdk.toHex(amountMinimum), feeBips, feeRecipient]);
96
97
  } else {
@@ -102,6 +103,10 @@ var PaymentsExtended = /*#__PURE__*/function () {
102
103
  return PaymentsExtended.INTERFACE.encodeFunctionData('pull', [token.address, v3Sdk.toHex(amount)]);
103
104
  };
104
105
 
106
+ PaymentsExtended.encodeWrapETH = function encodeWrapETH(amount) {
107
+ return PaymentsExtended.INTERFACE.encodeFunctionData('wrapETH', [v3Sdk.toHex(amount)]);
108
+ };
109
+
105
110
  return PaymentsExtended;
106
111
  }();
107
112
  PaymentsExtended.INTERFACE = /*#__PURE__*/new abi.Interface(IPeripheryPaymentsWithFeeExtended_json.abi);
@@ -212,6 +217,72 @@ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
212
217
  throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
213
218
  }
214
219
 
220
+ var ApprovalTypes;
221
+
222
+ (function (ApprovalTypes) {
223
+ ApprovalTypes[ApprovalTypes["NOT_REQUIRED"] = 0] = "NOT_REQUIRED";
224
+ ApprovalTypes[ApprovalTypes["MAX"] = 1] = "MAX";
225
+ ApprovalTypes[ApprovalTypes["MAX_MINUS_ONE"] = 2] = "MAX_MINUS_ONE";
226
+ ApprovalTypes[ApprovalTypes["ZERO_THEN_MAX"] = 3] = "ZERO_THEN_MAX";
227
+ ApprovalTypes[ApprovalTypes["ZERO_THEN_MAX_MINUS_ONE"] = 4] = "ZERO_THEN_MAX_MINUS_ONE";
228
+ })(ApprovalTypes || (ApprovalTypes = {}));
229
+
230
+ var ApproveAndCall = /*#__PURE__*/function () {
231
+ /**
232
+ * Cannot be constructed.
233
+ */
234
+ function ApproveAndCall() {}
235
+
236
+ ApproveAndCall.encodeApproveMax = function encodeApproveMax(token) {
237
+ return ApproveAndCall.INTERFACE.encodeFunctionData('approveMax', [token.address]);
238
+ };
239
+
240
+ ApproveAndCall.encodeApproveMaxMinusOne = function encodeApproveMaxMinusOne(token) {
241
+ return ApproveAndCall.INTERFACE.encodeFunctionData('approveMaxMinusOne', [token.address]);
242
+ };
243
+
244
+ ApproveAndCall.encodeApproveZeroThenMax = function encodeApproveZeroThenMax(token) {
245
+ return ApproveAndCall.INTERFACE.encodeFunctionData('approveZeroThenMax', [token.address]);
246
+ };
247
+
248
+ ApproveAndCall.encodeApproveZeroThenMaxMinusOne = function encodeApproveZeroThenMaxMinusOne(token) {
249
+ return ApproveAndCall.INTERFACE.encodeFunctionData('approveZeroThenMaxMinusOne', [token.address]);
250
+ };
251
+
252
+ ApproveAndCall.encodeCallPositionManager = function encodeCallPositionManager(calldatas) {
253
+ !(calldatas.length > 0) ? invariant(false, 'NULL_CALLDATA') : void 0;
254
+
255
+ if (calldatas.length == 1) {
256
+ return ApproveAndCall.INTERFACE.encodeFunctionData('callPositionManager', calldatas);
257
+ } else {
258
+ var encodedMulticall = v3Sdk.NonfungiblePositionManager.INTERFACE.encodeFunctionData('multicall', [calldatas]);
259
+ return ApproveAndCall.INTERFACE.encodeFunctionData('callPositionManager', [encodedMulticall]);
260
+ }
261
+ };
262
+
263
+ ApproveAndCall.encodeApprove = function encodeApprove(token, approvalType) {
264
+ switch (approvalType) {
265
+ case ApprovalTypes.MAX:
266
+ return ApproveAndCall.encodeApproveMax(token.wrapped);
267
+
268
+ case ApprovalTypes.MAX_MINUS_ONE:
269
+ return ApproveAndCall.encodeApproveMaxMinusOne(token.wrapped);
270
+
271
+ case ApprovalTypes.ZERO_THEN_MAX:
272
+ return ApproveAndCall.encodeApproveZeroThenMax(token.wrapped);
273
+
274
+ case ApprovalTypes.ZERO_THEN_MAX_MINUS_ONE:
275
+ return ApproveAndCall.encodeApproveZeroThenMaxMinusOne(token.wrapped);
276
+
277
+ default:
278
+ throw 'Error: invalid ApprovalType';
279
+ }
280
+ };
281
+
282
+ return ApproveAndCall;
283
+ }();
284
+ ApproveAndCall.INTERFACE = /*#__PURE__*/new abi.Interface(IApproveAndCall_json.abi);
285
+
215
286
  function createCommonjsModule(fn, module) {
216
287
  return module = { exports: {} }, fn(module, module.exports), module.exports;
217
288
  }
@@ -1047,7 +1118,43 @@ var Trade = /*#__PURE__*/function () {
1047
1118
  });
1048
1119
  }
1049
1120
 
1050
- this.tradeType = tradeType;
1121
+ this.tradeType = tradeType; // each route must have the same input and output currency
1122
+
1123
+ var inputCurrency = this.swaps[0].inputAmount.currency;
1124
+ var outputCurrency = this.swaps[0].outputAmount.currency;
1125
+ !this.swaps.every(function (_ref2) {
1126
+ var route = _ref2.route;
1127
+ return inputCurrency.wrapped.equals(route.input.wrapped);
1128
+ }) ? invariant(false, 'INPUT_CURRENCY_MATCH') : void 0;
1129
+ !this.swaps.every(function (_ref3) {
1130
+ var route = _ref3.route;
1131
+ return outputCurrency.wrapped.equals(route.output.wrapped);
1132
+ }) ? invariant(false, 'OUTPUT_CURRENCY_MATCH') : void 0; // pools must be unique inter protocols
1133
+
1134
+ var numPools = this.swaps.map(function (_ref4) {
1135
+ var route = _ref4.route;
1136
+ return route.pools.length;
1137
+ }).reduce(function (total, cur) {
1138
+ return total + cur;
1139
+ }, 0);
1140
+ var poolAddressSet = new Set();
1141
+
1142
+ for (var _iterator3 = _createForOfIteratorHelperLoose(this.swaps), _step3; !(_step3 = _iterator3()).done;) {
1143
+ var _route2 = _step3.value.route;
1144
+
1145
+ for (var _iterator4 = _createForOfIteratorHelperLoose(_route2.pools), _step4; !(_step4 = _iterator4()).done;) {
1146
+ var pool = _step4.value;
1147
+
1148
+ if (_route2.protocol == exports.Protocol.V3) {
1149
+ poolAddressSet.add(v3Sdk.Pool.getAddress(pool.token0, pool.token1, pool.fee));
1150
+ } else {
1151
+ var pair = pool;
1152
+ poolAddressSet.add(v2Sdk.Pair.getAddress(pair.token0, pair.token1));
1153
+ }
1154
+ }
1155
+ }
1156
+
1157
+ !(numPools == poolAddressSet.size) ? invariant(false, 'POOLS_DUPLICATED') : void 0;
1051
1158
  }
1052
1159
 
1053
1160
  var _proto = Trade.prototype;
@@ -1105,7 +1212,7 @@ var Trade = /*#__PURE__*/function () {
1105
1212
 
1106
1213
  Trade.fromRoutes = /*#__PURE__*/function () {
1107
1214
  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;
1215
+ var populatedV2Routes, populatedV3Routes, _iterator5, _step5, _step5$value, routev2, amount, v2Trade, inputAmount, outputAmount, _iterator6, _step6, _step6$value, routev3, _amount, v3Trade, _inputAmount2, _outputAmount2;
1109
1216
 
1110
1217
  return runtime_1.wrap(function _callee$(_context) {
1111
1218
  while (1) {
@@ -1114,8 +1221,8 @@ var Trade = /*#__PURE__*/function () {
1114
1221
  populatedV2Routes = [];
1115
1222
  populatedV3Routes = [];
1116
1223
 
1117
- for (_iterator3 = _createForOfIteratorHelperLoose(v2Routes); !(_step3 = _iterator3()).done;) {
1118
- _step3$value = _step3.value, routev2 = _step3$value.routev2, amount = _step3$value.amount;
1224
+ for (_iterator5 = _createForOfIteratorHelperLoose(v2Routes); !(_step5 = _iterator5()).done;) {
1225
+ _step5$value = _step5.value, routev2 = _step5$value.routev2, amount = _step5$value.amount;
1119
1226
  v2Trade = new v2Sdk.Trade(routev2, amount, tradeType);
1120
1227
  inputAmount = v2Trade.inputAmount, outputAmount = v2Trade.outputAmount;
1121
1228
  populatedV2Routes.push({
@@ -1125,15 +1232,15 @@ var Trade = /*#__PURE__*/function () {
1125
1232
  });
1126
1233
  }
1127
1234
 
1128
- _iterator4 = _createForOfIteratorHelperLoose(v3Routes);
1235
+ _iterator6 = _createForOfIteratorHelperLoose(v3Routes);
1129
1236
 
1130
1237
  case 4:
1131
- if ((_step4 = _iterator4()).done) {
1238
+ if ((_step6 = _iterator6()).done) {
1132
1239
  _context.next = 13;
1133
1240
  break;
1134
1241
  }
1135
1242
 
1136
- _step4$value = _step4.value, routev3 = _step4$value.routev3, _amount = _step4$value.amount;
1243
+ _step6$value = _step6.value, routev3 = _step6$value.routev3, _amount = _step6$value.amount;
1137
1244
  _context.next = 8;
1138
1245
  return v3Sdk.Trade.fromRoute(routev3, _amount, tradeType);
1139
1246
 
@@ -1240,8 +1347,8 @@ var Trade = /*#__PURE__*/function () {
1240
1347
  }
1241
1348
 
1242
1349
  var inputCurrency = this.swaps[0].inputAmount.currency;
1243
- var totalInputFromRoutes = this.swaps.map(function (_ref2) {
1244
- var inputAmount = _ref2.inputAmount;
1350
+ var totalInputFromRoutes = this.swaps.map(function (_ref5) {
1351
+ var inputAmount = _ref5.inputAmount;
1245
1352
  return inputAmount;
1246
1353
  }).reduce(function (total, cur) {
1247
1354
  return total.add(cur);
@@ -1257,8 +1364,8 @@ var Trade = /*#__PURE__*/function () {
1257
1364
  }
1258
1365
 
1259
1366
  var outputCurrency = this.swaps[0].outputAmount.currency;
1260
- var totalOutputFromRoutes = this.swaps.map(function (_ref3) {
1261
- var outputAmount = _ref3.outputAmount;
1367
+ var totalOutputFromRoutes = this.swaps.map(function (_ref6) {
1368
+ var outputAmount = _ref6.outputAmount;
1262
1369
  return outputAmount;
1263
1370
  }).reduce(function (total, cur) {
1264
1371
  return total.add(cur);
@@ -1290,10 +1397,10 @@ var Trade = /*#__PURE__*/function () {
1290
1397
 
1291
1398
  var spotOutputAmount = sdkCore.CurrencyAmount.fromRawAmount(this.outputAmount.currency, 0);
1292
1399
 
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;
1400
+ for (var _iterator7 = _createForOfIteratorHelperLoose(this.swaps), _step7; !(_step7 = _iterator7()).done;) {
1401
+ var _step7$value = _step7.value,
1402
+ route = _step7$value.route,
1403
+ inputAmount = _step7$value.inputAmount;
1297
1404
  var midPrice = route.midPrice;
1298
1405
  spotOutputAmount = spotOutputAmount.add(midPrice.quote(inputAmount));
1299
1406
  }
@@ -1318,18 +1425,16 @@ var SwapRouter = /*#__PURE__*/function () {
1318
1425
  */
1319
1426
  function SwapRouter() {}
1320
1427
 
1321
- SwapRouter.encodeV2Swap = function encodeV2Swap(trade, options, routerMustCustody) {
1428
+ SwapRouter.encodeV2Swap = function encodeV2Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck) {
1322
1429
  var amountIn = v3Sdk.toHex(trade.maximumAmountIn(options.slippageTolerance).quotient);
1323
1430
  var amountOut = v3Sdk.toHex(trade.minimumAmountOut(options.slippageTolerance).quotient);
1324
1431
  var path = trade.route.path.map(function (token) {
1325
1432
  return token.address;
1326
1433
  });
1327
- var recipient = routerMustCustody ? ADDRESS_THIS : options.recipient ? sdkCore.validateAndParseAddress(options.recipient) : MSG_SENDER;
1434
+ var recipient = routerMustCustody ? ADDRESS_THIS : typeof options.recipient === 'undefined' ? MSG_SENDER : sdkCore.validateAndParseAddress(options.recipient);
1328
1435
 
1329
1436
  if (trade.tradeType === sdkCore.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];
1437
+ var exactInputParams = [amountIn, performAggregatedSlippageCheck ? 0 : amountOut, path, recipient];
1333
1438
  return SwapRouter.INTERFACE.encodeFunctionData('swapExactTokensForTokens', exactInputParams);
1334
1439
  } else {
1335
1440
  var exactOutputParams = [amountOut, amountIn, path, recipient];
@@ -1337,7 +1442,7 @@ var SwapRouter = /*#__PURE__*/function () {
1337
1442
  }
1338
1443
  };
1339
1444
 
1340
- SwapRouter.encodeV3Swap = function encodeV3Swap(trade, options, routerMustCustody) {
1445
+ SwapRouter.encodeV3Swap = function encodeV3Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck) {
1341
1446
  var calldatas = [];
1342
1447
 
1343
1448
  for (var _iterator = _createForOfIteratorHelperLoose(trade.swaps), _step; !(_step = _iterator()).done;) {
@@ -1349,7 +1454,7 @@ var SwapRouter = /*#__PURE__*/function () {
1349
1454
  var amountOut = v3Sdk.toHex(trade.minimumAmountOut(options.slippageTolerance, outputAmount).quotient); // flag for whether the trade is single hop or not
1350
1455
 
1351
1456
  var singleHop = route.pools.length === 1;
1352
- var recipient = routerMustCustody ? ADDRESS_THIS : options.recipient ? sdkCore.validateAndParseAddress(options.recipient) : MSG_SENDER;
1457
+ var recipient = routerMustCustody ? ADDRESS_THIS : typeof options.recipient === 'undefined' ? MSG_SENDER : sdkCore.validateAndParseAddress(options.recipient);
1353
1458
 
1354
1459
  if (singleHop) {
1355
1460
  if (trade.tradeType === sdkCore.TradeType.EXACT_INPUT) {
@@ -1359,7 +1464,7 @@ var SwapRouter = /*#__PURE__*/function () {
1359
1464
  fee: route.pools[0].fee,
1360
1465
  recipient: recipient,
1361
1466
  amountIn: amountIn,
1362
- amountOutMinimum: amountOut,
1467
+ amountOutMinimum: performAggregatedSlippageCheck ? 0 : amountOut,
1363
1468
  sqrtPriceLimitX96: 0
1364
1469
  };
1365
1470
  calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('exactInputSingle', [exactInputSingleParams]));
@@ -1383,7 +1488,7 @@ var SwapRouter = /*#__PURE__*/function () {
1383
1488
  path: path,
1384
1489
  recipient: recipient,
1385
1490
  amountIn: amountIn,
1386
- amountOutMinimum: amountOut
1491
+ amountOutMinimum: performAggregatedSlippageCheck ? 0 : amountOut
1387
1492
  };
1388
1493
  calldatas.push(SwapRouter.INTERFACE.encodeFunctionData('exactInput', [exactInputParams]));
1389
1494
  } else {
@@ -1399,15 +1504,9 @@ var SwapRouter = /*#__PURE__*/function () {
1399
1504
  }
1400
1505
 
1401
1506
  return calldatas;
1402
- }
1403
- /**
1404
- * Produces the on-chain method name to call and the hex encoded parameters to pass as arguments for a given trade.
1405
- * @param trade to produce call parameters for
1406
- * @param options options for the call parameters
1407
- */
1408
- ;
1507
+ };
1409
1508
 
1410
- SwapRouter.swapCallParameters = function swapCallParameters(trades, options) {
1509
+ SwapRouter.encodeSwaps = function encodeSwaps(trades, options, isSwapAndAdd) {
1411
1510
  // If dealing with an instance of the aggregated Trade object, unbundle it to individual V2Trade and V3Trade objects.
1412
1511
  if (trades instanceof Trade) {
1413
1512
  !trades.swaps.every(function (swap) {
@@ -1440,6 +1539,9 @@ var SwapRouter = /*#__PURE__*/function () {
1440
1539
  trades = [trades];
1441
1540
  }
1442
1541
 
1542
+ var numberOfTrades = trades.reduce(function (numberOfTrades, trade) {
1543
+ return numberOfTrades + (trade instanceof v3Sdk.Trade ? trade.swaps.length : 1);
1544
+ }, 0);
1443
1545
  var sampleTrade = trades[0]; // All trades should have the same starting/ending currency and trade type
1444
1546
 
1445
1547
  !trades.every(function (trade) {
@@ -1452,25 +1554,19 @@ var SwapRouter = /*#__PURE__*/function () {
1452
1554
  return trade.tradeType === sampleTrade.tradeType;
1453
1555
  }) ? invariant(false, 'TRADE_TYPE_DIFF') : void 0;
1454
1556
  var calldatas = [];
1455
- var ZERO_IN = sdkCore.CurrencyAmount.fromRawAmount(sampleTrade.inputAmount.currency, 0);
1456
- var ZERO_OUT = sdkCore.CurrencyAmount.fromRawAmount(sampleTrade.outputAmount.currency, 0);
1457
- var totalAmountOut = trades.reduce(function (sum, trade) {
1458
- return sum.add(trade.minimumAmountOut(options.slippageTolerance));
1459
- }, ZERO_OUT);
1460
1557
  var inputIsNative = sampleTrade.inputAmount.currency.isNative;
1461
- var outputIsNative = sampleTrade.outputAmount.currency.isNative; // flag for whether a refund needs to happen
1462
- // 1. when paying in ETH, but with an uncertain input amount
1558
+ var outputIsNative = sampleTrade.outputAmount.currency.isNative; // flag for whether we want to perform an aggregated slippage check
1559
+ // 1. when there are >2 exact input trades. this is only a heuristic,
1560
+ // as it's still more gas-expensive even in this case, but has benefits
1561
+ // in that the reversion probability is lower
1463
1562
 
1464
- var mustRefund = inputIsNative && sampleTrade.tradeType === sdkCore.TradeType.EXACT_OUTPUT; // flag for whether funds should be send first to the router
1563
+ var performAggregatedSlippageCheck = sampleTrade.tradeType === sdkCore.TradeType.EXACT_INPUT && numberOfTrades > 2; // flag for whether funds should be send first to the router
1465
1564
  // 1. when receiving ETH (which much be unwrapped from WETH)
1466
1565
  // 2. when a fee on the output is being taken
1467
- // 3. when there are >1 exact input trades. this one isn't strictly necessary,
1468
- // but typically we want to perform an aggregated slippage check
1566
+ // 3. when performing swap and add
1567
+ // 4. when performing an aggregated slippage check
1469
1568
 
1470
- var routerMustCustody = outputIsNative || !!options.fee || trades.length > 1 && sampleTrade.tradeType === sdkCore.TradeType.EXACT_INPUT;
1471
- var totalValue = inputIsNative ? trades.reduce(function (sum, trade) {
1472
- return sum.add(trade.maximumAmountIn(options.slippageTolerance));
1473
- }, ZERO_IN) : ZERO_IN; // encode permit if necessary
1569
+ var routerMustCustody = outputIsNative || !!options.fee || !!isSwapAndAdd || performAggregatedSlippageCheck; // encode permit if necessary
1474
1570
 
1475
1571
  if (options.inputTokenPermit) {
1476
1572
  !sampleTrade.inputAmount.currency.isToken ? invariant(false, 'NON_TOKEN_PERMIT') : void 0;
@@ -1481,36 +1577,144 @@ var SwapRouter = /*#__PURE__*/function () {
1481
1577
  var trade = _step3.value;
1482
1578
 
1483
1579
  if (trade instanceof v2Sdk.Trade) {
1484
- calldatas.push(SwapRouter.encodeV2Swap(trade, options, routerMustCustody));
1580
+ calldatas.push(SwapRouter.encodeV2Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck));
1485
1581
  } else {
1486
- for (var _iterator4 = _createForOfIteratorHelperLoose(SwapRouter.encodeV3Swap(trade, options, routerMustCustody)), _step4; !(_step4 = _iterator4()).done;) {
1582
+ for (var _iterator4 = _createForOfIteratorHelperLoose(SwapRouter.encodeV3Swap(trade, options, routerMustCustody, performAggregatedSlippageCheck)), _step4; !(_step4 = _iterator4()).done;) {
1487
1583
  var calldata = _step4.value;
1488
1584
  calldatas.push(calldata);
1489
1585
  }
1490
1586
  }
1491
- } // unwrap
1587
+ }
1588
+
1589
+ var ZERO_IN = sdkCore.CurrencyAmount.fromRawAmount(sampleTrade.inputAmount.currency, 0);
1590
+ var ZERO_OUT = sdkCore.CurrencyAmount.fromRawAmount(sampleTrade.outputAmount.currency, 0);
1591
+ var totalAmountOut = trades.reduce(function (sum, trade) {
1592
+ return sum.add(trade.minimumAmountOut(options.slippageTolerance));
1593
+ }, ZERO_OUT);
1594
+ var totalAmountIn = trades.reduce(function (sum, trade) {
1595
+ return sum.add(trade.maximumAmountIn(options.slippageTolerance));
1596
+ }, ZERO_IN);
1597
+ return {
1598
+ calldatas: calldatas,
1599
+ sampleTrade: sampleTrade,
1600
+ routerMustCustody: routerMustCustody,
1601
+ inputIsNative: inputIsNative,
1602
+ outputIsNative: outputIsNative,
1603
+ totalAmountIn: totalAmountIn,
1604
+ totalAmountOut: totalAmountOut
1605
+ };
1606
+ }
1607
+ /**
1608
+ * Produces the on-chain method name to call and the hex encoded parameters to pass as arguments for a given trade.
1609
+ * @param trade to produce call parameters for
1610
+ * @param options options for the call parameters
1611
+ */
1612
+ ;
1492
1613
 
1614
+ SwapRouter.swapCallParameters = function swapCallParameters(trades, options) {
1615
+ var _SwapRouter$encodeSwa = SwapRouter.encodeSwaps(trades, options),
1616
+ calldatas = _SwapRouter$encodeSwa.calldatas,
1617
+ sampleTrade = _SwapRouter$encodeSwa.sampleTrade,
1618
+ routerMustCustody = _SwapRouter$encodeSwa.routerMustCustody,
1619
+ inputIsNative = _SwapRouter$encodeSwa.inputIsNative,
1620
+ outputIsNative = _SwapRouter$encodeSwa.outputIsNative,
1621
+ totalAmountIn = _SwapRouter$encodeSwa.totalAmountIn,
1622
+ totalAmountOut = _SwapRouter$encodeSwa.totalAmountOut; // unwrap or sweep
1493
1623
 
1494
- if (routerMustCustody) {
1495
- // if all trades are exact output, we can save gas by not passing a slippage check
1496
- var canOmitSlippageCheck = sampleTrade.tradeType === sdkCore.TradeType.EXACT_OUTPUT;
1497
- var amountNecessary = canOmitSlippageCheck ? ZERO$1 : totalAmountOut.quotient;
1498
1624
 
1625
+ if (routerMustCustody) {
1499
1626
  if (outputIsNative) {
1500
- calldatas.push(PaymentsExtended.encodeUnwrapWETH9(amountNecessary, options.recipient, options.fee));
1627
+ calldatas.push(PaymentsExtended.encodeUnwrapWETH9(totalAmountOut.quotient, options.recipient, options.fee));
1501
1628
  } else {
1502
- calldatas.push(PaymentsExtended.encodeSweepToken(sampleTrade.outputAmount.currency.wrapped, amountNecessary, options.recipient, options.fee));
1629
+ calldatas.push(PaymentsExtended.encodeSweepToken(sampleTrade.outputAmount.currency.wrapped, totalAmountOut.quotient, options.recipient, options.fee));
1503
1630
  }
1504
- } // refund
1631
+ } // must refund when paying in ETH, but with an uncertain input amount
1505
1632
 
1506
1633
 
1507
- if (mustRefund) {
1634
+ if (inputIsNative && sampleTrade.tradeType === sdkCore.TradeType.EXACT_OUTPUT) {
1508
1635
  calldatas.push(v3Sdk.Payments.encodeRefundETH());
1509
1636
  }
1510
1637
 
1511
1638
  return {
1512
1639
  calldata: MulticallExtended.encodeMulticall(calldatas, options.deadlineOrPreviousBlockhash),
1513
- value: v3Sdk.toHex(totalValue.quotient)
1640
+ value: v3Sdk.toHex(inputIsNative ? totalAmountIn.quotient : ZERO$1)
1641
+ };
1642
+ }
1643
+ /**
1644
+ * Produces the on-chain method name to call and the hex encoded parameters to pass as arguments for a given trade.
1645
+ * @param trade to produce call parameters for
1646
+ * @param options options for the call parameters
1647
+ */
1648
+ ;
1649
+
1650
+ SwapRouter.swapAndAddCallParameters = function swapAndAddCallParameters(trades, options, position, addLiquidityOptions, tokenInApprovalType, tokenOutApprovalType) {
1651
+ var _SwapRouter$encodeSwa2 = SwapRouter.encodeSwaps(trades, options, true),
1652
+ calldatas = _SwapRouter$encodeSwa2.calldatas,
1653
+ inputIsNative = _SwapRouter$encodeSwa2.inputIsNative,
1654
+ outputIsNative = _SwapRouter$encodeSwa2.outputIsNative,
1655
+ sampleTrade = _SwapRouter$encodeSwa2.sampleTrade,
1656
+ totalAmountSwapped = _SwapRouter$encodeSwa2.totalAmountIn,
1657
+ totalAmountOut = _SwapRouter$encodeSwa2.totalAmountOut;
1658
+
1659
+ var chainId = sampleTrade.route.chainId;
1660
+ var zeroForOne = position.pool.token0 === totalAmountSwapped.currency.wrapped;
1661
+
1662
+ var _SwapRouter$getPositi = SwapRouter.getPositionAmounts(position, zeroForOne),
1663
+ positionAmountIn = _SwapRouter$getPositi.positionAmountIn,
1664
+ positionAmountOut = _SwapRouter$getPositi.positionAmountOut; // if tokens are native they will be converted to WETH9
1665
+
1666
+
1667
+ var tokenIn = inputIsNative ? sdkCore.WETH9[chainId] : positionAmountIn.currency.wrapped;
1668
+ var tokenOut = outputIsNative ? sdkCore.WETH9[chainId] : positionAmountOut.currency.wrapped; // if swap output does not make up whole outputTokenBalanceDesired, pull in remaining tokens for adding liquidity
1669
+
1670
+ var amountOutRemaining = positionAmountOut.subtract(totalAmountOut.wrapped);
1671
+
1672
+ if (amountOutRemaining.greaterThan(sdkCore.CurrencyAmount.fromRawAmount(positionAmountOut.currency, 0))) {
1673
+ // if output is native, this means the remaining portion is included as native value in the transaction
1674
+ // and must be wrapped. Otherwise, pull in remaining ERC20 token.
1675
+ outputIsNative ? calldatas.push(PaymentsExtended.encodeWrapETH(amountOutRemaining.quotient)) : calldatas.push(PaymentsExtended.encodePull(tokenOut, amountOutRemaining.quotient));
1676
+ } // if input is native, convert to WETH9, else pull ERC20 token
1677
+
1678
+
1679
+ inputIsNative ? calldatas.push(PaymentsExtended.encodeWrapETH(positionAmountIn.quotient)) : calldatas.push(PaymentsExtended.encodePull(tokenIn, positionAmountIn.quotient)); // approve token balances to NFTManager
1680
+
1681
+ if (tokenInApprovalType !== ApprovalTypes.NOT_REQUIRED) calldatas.push(ApproveAndCall.encodeApprove(tokenIn, tokenInApprovalType));
1682
+ if (tokenOutApprovalType !== ApprovalTypes.NOT_REQUIRED) calldatas.push(ApproveAndCall.encodeApprove(tokenOut, tokenOutApprovalType)); // encode NFTManager add liquidity
1683
+
1684
+ calldatas.push(ApproveAndCall.encodeCallPositionManager([v3Sdk.NonfungiblePositionManager.addCallParameters(position, addLiquidityOptions).calldata])); // sweep remaining tokens
1685
+
1686
+ inputIsNative ? calldatas.push(PaymentsExtended.encodeUnwrapWETH9(ZERO$1)) : calldatas.push(PaymentsExtended.encodeSweepToken(tokenIn, ZERO$1));
1687
+ outputIsNative ? calldatas.push(PaymentsExtended.encodeUnwrapWETH9(ZERO$1)) : calldatas.push(PaymentsExtended.encodeSweepToken(tokenOut, ZERO$1));
1688
+ var value;
1689
+
1690
+ if (inputIsNative) {
1691
+ value = totalAmountSwapped.wrapped.add(positionAmountIn.wrapped).quotient;
1692
+ } else if (outputIsNative) {
1693
+ value = amountOutRemaining.quotient;
1694
+ } else {
1695
+ value = ZERO$1;
1696
+ }
1697
+
1698
+ return {
1699
+ calldata: MulticallExtended.encodeMulticall(calldatas, options.deadlineOrPreviousBlockhash),
1700
+ value: value.toString()
1701
+ };
1702
+ };
1703
+
1704
+ SwapRouter.getPositionAmounts = function getPositionAmounts(position, zeroForOne) {
1705
+ var _position$mintAmounts = position.mintAmounts,
1706
+ amount0 = _position$mintAmounts.amount0,
1707
+ amount1 = _position$mintAmounts.amount1;
1708
+ var currencyAmount0 = sdkCore.CurrencyAmount.fromRawAmount(position.pool.token0, amount0);
1709
+ var currencyAmount1 = sdkCore.CurrencyAmount.fromRawAmount(position.pool.token1, amount1);
1710
+
1711
+ var _ref = zeroForOne ? [currencyAmount0, currencyAmount1] : [currencyAmount1, currencyAmount0],
1712
+ positionAmountIn = _ref[0],
1713
+ positionAmountOut = _ref[1];
1714
+
1715
+ return {
1716
+ positionAmountIn: positionAmountIn,
1717
+ positionAmountOut: positionAmountOut
1514
1718
  };
1515
1719
  };
1516
1720