@alcorexchange/alcor-swap-sdk 1.0.395 → 1.0.397

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.
@@ -198,14 +198,9 @@ let Pool = exports.Pool = /*#__PURE__*/function () {
198
198
  }, {
199
199
  key: "swap",
200
200
  value: function swap(zeroForOne, amountSpecified, sqrtPriceLimitX64) {
201
- if (!sqrtPriceLimitX64) sqrtPriceLimitX64 = zeroForOne ? _tickMath.TickMath.MIN_SQRT_RATIO + _internalConstants.ONE : _tickMath.TickMath.MAX_SQRT_RATIO - _internalConstants.ONE;
202
- if (zeroForOne) {
203
- (0, _tinyInvariant.default)(sqrtPriceLimitX64 > _tickMath.TickMath.MIN_SQRT_RATIO, "RATIO_MIN");
204
- (0, _tinyInvariant.default)(sqrtPriceLimitX64 < this.sqrtPriceX64, "RATIO_CURRENT");
205
- } else {
206
- (0, _tinyInvariant.default)(sqrtPriceLimitX64 < _tickMath.TickMath.MAX_SQRT_RATIO, "RATIO_MAX");
207
- (0, _tinyInvariant.default)(sqrtPriceLimitX64 > this.sqrtPriceX64, "RATIO_CURRENT");
208
- }
201
+ const sqrtPriceLimit = sqrtPriceLimitX64 || (zeroForOne ? _tickMath.TickMath.MIN_SQRT_RATIO + _internalConstants.ONE : _tickMath.TickMath.MAX_SQRT_RATIO - _internalConstants.ONE);
202
+
203
+ // Убираем проверки invariant в продакшене, если данные гарантированно валидны
209
204
  const exactInput = amountSpecified >= _internalConstants.ZERO;
210
205
  const state = {
211
206
  amountSpecifiedRemaining: amountSpecified,
@@ -214,17 +209,17 @@ let Pool = exports.Pool = /*#__PURE__*/function () {
214
209
  tick: this.tickCurrent,
215
210
  liquidity: this.liquidity
216
211
  };
217
- while (state.amountSpecifiedRemaining !== _internalConstants.ZERO && state.sqrtPriceX64 != sqrtPriceLimitX64) {
218
- const step = {};
219
- step.sqrtPriceStartX64 = state.sqrtPriceX64;
212
+ while (state.amountSpecifiedRemaining !== _internalConstants.ZERO && state.sqrtPriceX64 !== sqrtPriceLimit) {
213
+ const step = {
214
+ sqrtPriceStartX64: state.sqrtPriceX64
215
+ };
216
+
217
+ // Оптимизация вызова nextInitializedTickWithinOneWord
220
218
  [step.tickNext, step.initialized] = this.tickDataProvider.nextInitializedTickWithinOneWord(state.tick, zeroForOne, this.tickSpacing);
221
- if (step.tickNext < _tickMath.TickMath.MIN_TICK) {
222
- step.tickNext = _tickMath.TickMath.MIN_TICK;
223
- } else if (step.tickNext > _tickMath.TickMath.MAX_TICK) {
224
- step.tickNext = _tickMath.TickMath.MAX_TICK;
225
- }
219
+ step.tickNext = Math.max(_tickMath.TickMath.MIN_TICK, Math.min(step.tickNext, _tickMath.TickMath.MAX_TICK));
226
220
  step.sqrtPriceNextX64 = _tickMath.TickMath.getSqrtRatioAtTick(step.tickNext);
227
- [state.sqrtPriceX64, step.amountIn, step.amountOut, step.feeAmount] = _swapMath.SwapMath.computeSwapStep(state.sqrtPriceX64, (zeroForOne ? step.sqrtPriceNextX64 < sqrtPriceLimitX64 : step.sqrtPriceNextX64 > sqrtPriceLimitX64) ? sqrtPriceLimitX64 : step.sqrtPriceNextX64, state.liquidity, state.amountSpecifiedRemaining, this.fee);
221
+ const targetPrice = (zeroForOne ? step.sqrtPriceNextX64 < sqrtPriceLimit : step.sqrtPriceNextX64 > sqrtPriceLimit) ? sqrtPriceLimit : step.sqrtPriceNextX64;
222
+ [state.sqrtPriceX64, step.amountIn, step.amountOut, step.feeAmount] = _swapMath.SwapMath.computeSwapStep(state.sqrtPriceX64, targetPrice, state.liquidity, state.amountSpecifiedRemaining, this.fee);
228
223
  if (exactInput) {
229
224
  state.amountSpecifiedRemaining = state.amountSpecifiedRemaining - (step.amountIn + step.feeAmount);
230
225
  state.amountCalculated = state.amountCalculated - step.amountOut;
@@ -243,11 +238,9 @@ let Pool = exports.Pool = /*#__PURE__*/function () {
243
238
  state.tick = _tickMath.TickMath.getTickAtSqrtRatio(state.sqrtPriceX64);
244
239
  }
245
240
  }
246
- const amountA = zeroForOne == exactInput ? amountSpecified - state.amountSpecifiedRemaining : state.amountCalculated;
247
- const amountB = zeroForOne == exactInput ? state.amountCalculated : amountSpecified - state.amountSpecifiedRemaining;
248
241
  return {
249
- amountA,
250
- amountB,
242
+ amountA: zeroForOne === exactInput ? amountSpecified - state.amountSpecifiedRemaining : state.amountCalculated,
243
+ amountB: zeroForOne === exactInput ? state.amountCalculated : amountSpecified - state.amountSpecifiedRemaining,
251
244
  sqrtPriceX64: state.sqrtPriceX64,
252
245
  liquidity: state.liquidity,
253
246
  tickCurrent: state.tick
@@ -320,25 +320,19 @@ let Trade = exports.Trade = /*#__PURE__*/function () {
320
320
  let inputAmount;
321
321
  let outputAmount;
322
322
  if (tradeType === _internalConstants.TradeType.EXACT_INPUT) {
323
- (0, _tinyInvariant.default)(amount.currency.equals(route.input), 'INPUT');
324
- amounts[0] = amount;
323
+ amounts[0] = amount; // Переиспользуем amount напрямую
325
324
  for (let i = 0; i < route.tokenPath.length - 1; i++) {
326
- const pool = route.pools[i];
327
- const outputAmount = pool.getOutputAmount(amounts[i]);
328
- amounts[i + 1] = outputAmount;
325
+ amounts[i + 1] = route.pools[i].getOutputAmount(amounts[i]);
329
326
  }
330
- inputAmount = _fractions.CurrencyAmount.fromFractionalAmount(route.input, amount.numerator, amount.denominator);
331
- outputAmount = _fractions.CurrencyAmount.fromFractionalAmount(route.output, amounts[amounts.length - 1].numerator, amounts[amounts.length - 1].denominator);
327
+ inputAmount = amount; // Без создания нового объекта
328
+ outputAmount = amounts[amounts.length - 1];
332
329
  } else {
333
- (0, _tinyInvariant.default)(amount.currency.equals(route.output), 'OUTPUT');
334
330
  amounts[amounts.length - 1] = amount;
335
331
  for (let i = route.tokenPath.length - 1; i > 0; i--) {
336
- const pool = route.pools[i - 1];
337
- const inputAmount = pool.getInputAmount(amounts[i]);
338
- amounts[i - 1] = inputAmount;
332
+ amounts[i - 1] = route.pools[i - 1].getInputAmount(amounts[i]);
339
333
  }
340
- inputAmount = _fractions.CurrencyAmount.fromFractionalAmount(route.input, amounts[0].numerator, amounts[0].denominator);
341
- outputAmount = _fractions.CurrencyAmount.fromFractionalAmount(route.output, amount.numerator, amount.denominator);
334
+ inputAmount = amounts[0];
335
+ outputAmount = amount;
342
336
  }
343
337
  return new Trade({
344
338
  routes: [{
@@ -496,24 +490,32 @@ let Trade = exports.Trade = /*#__PURE__*/function () {
496
490
  minSplits: 1,
497
491
  maxSplits: 10
498
492
  };
499
- // TODO Need rafactor
500
493
  (0, _tinyInvariant.default)(_routes.length > 0, 'ROUTES');
501
494
  (0, _tinyInvariant.default)(percents.length > 0, 'PERCENTS');
502
495
 
503
- // Compute routes for all percents for all routes
504
- const percentToTrades = {};
496
+ // Предварительно вычисляем splitAmount для всех процентов
497
+ const percentToAmount = new Map();
505
498
  for (const percent of percents) {
506
- const splitAmount = amount.multiply(percent).divide(100);
507
- for (const route of _routes) {
499
+ percentToAmount.set(percent, amount.multiply(percent).divide(100));
500
+ }
501
+
502
+ // Используем Map вместо объекта для лучшей производительности
503
+ const percentToTrades = new Map();
504
+ for (const percent of percents) {
505
+ percentToTrades.set(percent, []);
506
+ }
507
+
508
+ // Оптимизируем внутренний цикл - группируем вычисления по маршрутам
509
+ for (const route of _routes) {
510
+ // Для каждого маршрута проходим по всем процентам
511
+ for (const percent of percents) {
512
+ const splitAmount = percentToAmount.get(percent);
508
513
  try {
509
514
  const trade = Trade.fromRoute(route, splitAmount, tradeType, percent);
510
- if (!trade.inputAmount.greaterThan(0) || !trade.priceImpact.greaterThan(0)) continue;
511
- if (!percentToTrades[percent]) {
512
- percentToTrades[percent] = [];
515
+ if (trade.inputAmount.greaterThan(0) && trade.priceImpact.greaterThan(0)) {
516
+ percentToTrades.get(percent).push(trade);
513
517
  }
514
- percentToTrades[percent].push(trade);
515
518
  } catch (error) {
516
- // not enough liquidity in this pair
517
519
  if (error.isInsufficientReservesError || error.isInsufficientInputAmountError) {
518
520
  continue;
519
521
  }
@@ -521,7 +523,13 @@ let Trade = exports.Trade = /*#__PURE__*/function () {
521
523
  }
522
524
  }
523
525
  }
524
- const bestTrades = (0, _getBestSwapRoute.getBestSwapRoute)(tradeType, percentToTrades, percents, swapConfig);
526
+
527
+ // Преобразуем Map обратно в объект для совместимости с getBestSwapRoute
528
+ const percentToTradesObj = {};
529
+ percentToTrades.forEach((trades, percent) => {
530
+ percentToTradesObj[percent] = trades;
531
+ });
532
+ const bestTrades = (0, _getBestSwapRoute.getBestSwapRoute)(tradeType, percentToTradesObj, percents, swapConfig);
525
533
  if (!bestTrades) return null;
526
534
  const routes = bestTrades.map(_ref7 => {
527
535
  let {
@@ -1,8 +1,5 @@
1
1
  import JSBI from "jsbi";
2
2
  export declare abstract class FullMath {
3
- /**
4
- * Cannot be constructed.
5
- */
6
3
  private constructor();
7
4
  static mulDivRoundingUp(a: JSBI, b: JSBI, denominator: JSBI): JSBI;
8
5
  }
@@ -4,26 +4,45 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.FullMath = void 0;
7
- var _internalConstants = require("../internalConstants");
8
7
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
9
8
  function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
10
9
  function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
11
10
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
12
11
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
12
+ const ZERO = 0n;
13
+ const ONE = 1n;
13
14
  let FullMath = exports.FullMath = /*#__PURE__*/function () {
14
- /**
15
- * Cannot be constructed.
16
- */
17
15
  function FullMath() {
18
16
  _classCallCheck(this, FullMath);
19
17
  }
20
18
  return _createClass(FullMath, null, [{
21
19
  key: "mulDivRoundingUp",
22
20
  value: function mulDivRoundingUp(a, b, denominator) {
21
+ // Check for division by zero
22
+ if (denominator === ZERO) {
23
+ throw new Error("Division by zero");
24
+ }
25
+
26
+ // Early return for zero inputs
27
+ if (a === ZERO || b === ZERO) {
28
+ return ZERO;
29
+ }
30
+
31
+ // Early return if denominator is one
32
+ if (denominator === ONE) {
33
+ return a * b;
34
+ }
35
+
36
+ // Calculate product, quotient, and remainder
23
37
  const product = a * b;
24
- let result = product / denominator;
25
- if (product % denominator !== _internalConstants.ZERO) result = result + _internalConstants.ONE;
26
- return result;
38
+ const quotient = product / denominator;
39
+ const remainder = product % denominator;
40
+
41
+ // Round up if there’s a non-zero remainder
42
+ if (remainder !== ZERO) {
43
+ return quotient + ONE;
44
+ }
45
+ return quotient;
27
46
  }
28
47
  }]);
29
48
  }();
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getBestSwapRoute = getBestSwapRoute;
7
- var _lodash = _interopRequireDefault(require("lodash"));
8
7
  var _queue = _interopRequireDefault(require("mnemonist/queue"));
9
8
  var _fixedReverseHeap = _interopRequireDefault(require("mnemonist/fixed-reverse-heap"));
10
9
  var _internalConstants = require("../internalConstants");
@@ -14,16 +13,38 @@ function getBestSwapRoute(routeType, percentToQuotes, percents) {
14
13
  minSplits: 1,
15
14
  maxSplits: 8
16
15
  };
17
- const percentToSortedQuotes = _lodash.default.mapValues(percentToQuotes, routeQuotes => {
18
- return routeQuotes.sort((routeQuoteA, routeQuoteB) => {
19
- if (routeType == _internalConstants.TradeType.EXACT_INPUT) {
20
- return routeQuoteA.outputAmount.greaterThan(routeQuoteB.outputAmount) ? -1 : 1;
21
- } else {
22
- return routeQuoteA.inputAmount.lessThan(routeQuoteB.inputAmount) ? -1 : 1;
16
+ // Извлекаем уникальные пулы из всех маршрутов
17
+ const allPools = [...new Set(Object.values(percentToQuotes).flatMap(routes => routes.flatMap(r => r.route.pools)))];
18
+
19
+ // Создаем битовую карту для пулов
20
+ const poolToBit = new Map();
21
+ let bitCounter = 0;
22
+ for (const pool of allPools) {
23
+ poolToBit.set(pool.id, 1 << bitCounter++);
24
+ }
25
+
26
+ // Предвычисляем маски для всех маршрутов
27
+ const routeToMask = new Map();
28
+ for (const routes of Object.values(percentToQuotes)) {
29
+ for (const route of routes) {
30
+ let mask = 0;
31
+ for (const pool of route.route.pools) {
32
+ mask |= poolToBit.get(pool.id);
23
33
  }
24
- });
25
- });
26
- const quoteCompFn = routeType == _internalConstants.TradeType.EXACT_INPUT ? (a, b) => a.greaterThan(b) : (a, b) => a.lessThan(b);
34
+ routeToMask.set(route, mask);
35
+ }
36
+ }
37
+
38
+ // Сортируем маршруты для каждого процента
39
+ const percentToSortedQuotes = {};
40
+ for (const percent in percentToQuotes) {
41
+ percentToSortedQuotes[percent] = percentToQuotes[percent].sort((a, b) => routeType === _internalConstants.TradeType.EXACT_INPUT ? a.outputAmount.greaterThan(b.outputAmount) ? -1 : 1 : a.inputAmount.lessThan(b.inputAmount) ? -1 : 1);
42
+ }
43
+
44
+ // Функция сравнения для типа торговли
45
+ const quoteCompFn = routeType === _internalConstants.TradeType.EXACT_INPUT ? (a, b) => a.greaterThan(b) : (a, b) => a.lessThan(b);
46
+
47
+ // Функция суммирования CurrencyAmount
27
48
  const sumFn = currencyAmounts => {
28
49
  let sum = currencyAmounts[0];
29
50
  for (let i = 1; i < currencyAmounts.length; i++) {
@@ -33,17 +54,17 @@ function getBestSwapRoute(routeType, percentToQuotes, percents) {
33
54
  };
34
55
  let bestQuote;
35
56
  let bestSwap;
36
- const bestSwapsPerSplit = new _fixedReverseHeap.default(Array, (a, b) => {
37
- return quoteCompFn(a.quote, b.quote) ? -1 : 1;
38
- }, 3);
57
+
58
+ // Храним лучшие маршруты для каждого уровня разбиения (максимум 3)
59
+ const bestSwapsPerSplit = new _fixedReverseHeap.default(Array, (a, b) => quoteCompFn(a.quote, b.quote) ? -1 : 1, 3);
39
60
  const {
40
61
  minSplits,
41
62
  maxSplits
42
63
  } = swapRouteConfig;
43
- if (!percentToSortedQuotes[100] || minSplits > 1) {
44
- console.log({
45
- percentToSortedQuotes: _lodash.default.mapValues(percentToSortedQuotes, p => p.length)
46
- }, 'Did not find a valid route without any splits. Continuing search anyway.');
64
+
65
+ // Проверяем наличие маршрута для 100% и инициализируем начальные данные
66
+ if (!percentToSortedQuotes[100] || percentToSortedQuotes[100].length === 0 || minSplits > 1) {
67
+ console.log('Did not find a valid route without any splits. Continuing search anyway.');
47
68
  } else {
48
69
  bestQuote = percentToSortedQuotes[100][0].outputAmount;
49
70
  bestSwap = [percentToSortedQuotes[100][0]];
@@ -54,37 +75,36 @@ function getBestSwapRoute(routeType, percentToQuotes, percents) {
54
75
  });
55
76
  }
56
77
  }
78
+
79
+ // Очередь для обработки комбинаций маршрутов
57
80
  const queue = new _queue.default();
58
- if (percents.length === 0) return null; // Handle empty percents array
81
+ if (percents.length === 0) return null;
59
82
 
83
+ // Инициализируем очередь с топ-2 маршрутами для каждого процента
60
84
  for (let i = percents.length - 1; i >= 0; i--) {
61
85
  const percent = percents[i];
62
- if (!percentToSortedQuotes[percent]) {
63
- console.log('continue', {
64
- percent
86
+ if (!percentToSortedQuotes[percent] || percentToSortedQuotes[percent].length === 0) continue;
87
+ const topRoutes = percentToSortedQuotes[percent].slice(0, 2);
88
+ if (topRoutes[0]) {
89
+ queue.enqueue({
90
+ curRoutes: [topRoutes[0]],
91
+ percentIndex: i,
92
+ remainingPercent: 100 - percent,
93
+ special: false
65
94
  });
66
- continue;
67
95
  }
68
- queue.enqueue({
69
- curRoutes: [percentToSortedQuotes[percent][0]],
70
- percentIndex: i,
71
- remainingPercent: 100 - percent,
72
- special: false
73
- });
74
- if (!percentToSortedQuotes[percent] || !percentToSortedQuotes[percent][1]) {
75
- console.log('continue2', {
76
- percent
96
+ if (topRoutes[1]) {
97
+ queue.enqueue({
98
+ curRoutes: [topRoutes[1]],
99
+ percentIndex: i,
100
+ remainingPercent: 100 - percent,
101
+ special: true
77
102
  });
78
- continue;
79
103
  }
80
- queue.enqueue({
81
- curRoutes: [percentToSortedQuotes[percent][1]],
82
- percentIndex: i,
83
- remainingPercent: 100 - percent,
84
- special: true
85
- });
86
104
  }
87
105
  let splits = 1;
106
+
107
+ // Основной цикл поиска лучших маршрутов
88
108
  while (queue.size > 0) {
89
109
  bestSwapsPerSplit.clear();
90
110
  let layer = queue.size;
@@ -105,21 +125,16 @@ function getBestSwapRoute(routeType, percentToQuotes, percents) {
105
125
  } = queue.dequeue();
106
126
  for (let i = percentIndex; i >= 0; i--) {
107
127
  const percentA = percents[i];
108
- if (percentA > remainingPercent) {
109
- continue;
110
- }
111
- if (!percentToSortedQuotes[percentA]) {
112
- continue;
113
- }
128
+ if (percentA > remainingPercent) continue;
129
+ if (!percentToSortedQuotes[percentA] || percentToSortedQuotes[percentA].length === 0) continue;
114
130
  const candidateRoutesA = percentToSortedQuotes[percentA];
115
- const routeWithQuoteA = findFirstRouteNotUsingUsedPools(curRoutes, candidateRoutesA);
116
- if (!routeWithQuoteA) {
117
- continue;
118
- }
131
+ const routeWithQuoteA = findFirstRouteNotUsingUsedPools(curRoutes, candidateRoutesA, routeToMask);
132
+ if (!routeWithQuoteA) continue;
119
133
  const remainingPercentNew = remainingPercent - percentA;
120
- const curRoutesNew = [...curRoutes, routeWithQuoteA];
121
- if (remainingPercentNew == 0 && splits >= minSplits) {
122
- const quotesNew = _lodash.default.map(curRoutesNew, r => r.outputAmount);
134
+ const curRoutesNew = curRoutes.slice();
135
+ curRoutesNew.push(routeWithQuoteA);
136
+ if (remainingPercentNew === 0 && splits >= minSplits) {
137
+ const quotesNew = curRoutesNew.map(r => r.outputAmount);
123
138
  const quoteNew = sumFn(quotesNew);
124
139
  bestSwapsPerSplit.push({
125
140
  quote: quoteNew,
@@ -141,18 +156,23 @@ function getBestSwapRoute(routeType, percentToQuotes, percents) {
141
156
  }
142
157
  }
143
158
  if (!bestSwap) {
144
- console.log(`Could not find a valid swap`);
159
+ console.log('Could not find a valid swap');
145
160
  return null;
146
161
  }
147
- const quote = sumFn(_lodash.default.map(bestSwap, routeWithValidQuote => routeWithValidQuote.outputAmount));
162
+ const quote = sumFn(bestSwap.map(routeWithValidQuote => routeWithValidQuote.outputAmount));
148
163
  const routeWithQuotes = bestSwap.sort((routeAmountA, routeAmountB) => routeAmountB.outputAmount.greaterThan(routeAmountA.outputAmount) ? 1 : -1);
149
164
  return routeWithQuotes;
150
165
  }
151
- const findFirstRouteNotUsingUsedPools = (usedRoutes, candidateRoutes) => {
152
- const usedPools = new Set();
153
- usedRoutes.forEach(r => r.route.pools.forEach(pool => usedPools.add(pool.id)));
166
+
167
+ // Вспомогательная функция для поиска маршрута без пересекающихся пулов
168
+ const findFirstRouteNotUsingUsedPools = (usedRoutes, candidateRoutes, routeToMask) => {
169
+ let usedMask = 0;
170
+ for (const route of usedRoutes) {
171
+ usedMask |= routeToMask.get(route);
172
+ }
154
173
  for (const candidate of candidateRoutes) {
155
- if (candidate.route.pools.every(pool => !usedPools.has(pool.id))) {
174
+ const candidateMask = routeToMask.get(candidate);
175
+ if ((candidateMask & usedMask) === 0) {
156
176
  return candidate;
157
177
  }
158
178
  }
@@ -4,10 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.SqrtPriceMath = void 0;
7
- var _tinyInvariant = _interopRequireDefault(require("tiny-invariant"));
8
7
  var _internalConstants = require("../internalConstants");
9
8
  var _fullMath = require("./fullMath");
10
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
9
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
12
10
  function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
13
11
  function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
@@ -36,7 +34,13 @@ let SqrtPriceMath = exports.SqrtPriceMath = /*#__PURE__*/function () {
36
34
  }
37
35
  const numerator1 = liquidity << 64n;
38
36
  const numerator2 = sqrtRatioUX64 - sqrtRatioLX64;
39
- return roundUp ? _fullMath.FullMath.mulDivRoundingUp(_fullMath.FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioUX64), _internalConstants.ONE, sqrtRatioLX64) : numerator1 * numerator2 / sqrtRatioUX64 / sqrtRatioLX64;
37
+ if (roundUp) {
38
+ const mul1 = _fullMath.FullMath.mulDivRoundingUp(numerator1, numerator2, sqrtRatioUX64);
39
+ return _fullMath.FullMath.mulDivRoundingUp(mul1, _internalConstants.ONE, sqrtRatioLX64);
40
+ } else {
41
+ const mul1 = numerator1 * numerator2 / sqrtRatioUX64;
42
+ return mul1 / sqrtRatioLX64;
43
+ }
40
44
  }
41
45
  }, {
42
46
  key: "getAmountBDelta",
@@ -44,20 +48,23 @@ let SqrtPriceMath = exports.SqrtPriceMath = /*#__PURE__*/function () {
44
48
  if (sqrtRatioLX64 > sqrtRatioUX64) {
45
49
  [sqrtRatioLX64, sqrtRatioUX64] = [sqrtRatioUX64, sqrtRatioLX64];
46
50
  }
47
- return roundUp ? _fullMath.FullMath.mulDivRoundingUp(liquidity, sqrtRatioUX64 - sqrtRatioLX64, _internalConstants.Q64) : liquidity * (sqrtRatioUX64 - sqrtRatioLX64) / _internalConstants.Q64;
51
+ const diff = sqrtRatioUX64 - sqrtRatioLX64;
52
+ if (roundUp) {
53
+ return _fullMath.FullMath.mulDivRoundingUp(liquidity, diff, _internalConstants.Q64);
54
+ } else {
55
+ return liquidity * diff / _internalConstants.Q64;
56
+ }
48
57
  }
49
58
  }, {
50
59
  key: "getNextSqrtPriceFromInput",
51
60
  value: function getNextSqrtPriceFromInput(sqrtPX64, liquidity, amountIn, zeroForOne) {
52
- (0, _tinyInvariant.default)(sqrtPX64 > _internalConstants.ZERO);
53
- (0, _tinyInvariant.default)(liquidity > _internalConstants.ZERO);
61
+ // Убраны invariant для ускорения, если данные валидны
54
62
  return zeroForOne ? this.getNextSqrtPriceFromAmountARoundingUp(sqrtPX64, liquidity, amountIn, true) : this.getNextSqrtPriceFromAmountBRoundingDown(sqrtPX64, liquidity, amountIn, true);
55
63
  }
56
64
  }, {
57
65
  key: "getNextSqrtPriceFromOutput",
58
66
  value: function getNextSqrtPriceFromOutput(sqrtPX64, liquidity, amountOut, zeroForOne) {
59
- (0, _tinyInvariant.default)(sqrtPX64 > _internalConstants.ZERO);
60
- (0, _tinyInvariant.default)(liquidity > _internalConstants.ZERO);
67
+ // Убраны invariant для ускорения, если данные валидны
61
68
  return zeroForOne ? this.getNextSqrtPriceFromAmountBRoundingDown(sqrtPX64, liquidity, amountOut, false) : this.getNextSqrtPriceFromAmountARoundingUp(sqrtPX64, liquidity, amountOut, false);
62
69
  }
63
70
  }, {
@@ -66,18 +73,18 @@ let SqrtPriceMath = exports.SqrtPriceMath = /*#__PURE__*/function () {
66
73
  if (amount === _internalConstants.ZERO) return sqrtPX64;
67
74
  const numerator1 = liquidity << 64n;
68
75
  if (add) {
69
- let product = multiplyIn128(amount, sqrtPX64);
76
+ const product = multiplyIn128(amount, sqrtPX64);
70
77
  if (product / amount === sqrtPX64) {
71
78
  const denominator = addIn128(numerator1, product);
72
79
  if (denominator >= numerator1) {
73
80
  return _fullMath.FullMath.mulDivRoundingUp(numerator1, sqrtPX64, denominator);
74
81
  }
75
82
  }
76
- return _fullMath.FullMath.mulDivRoundingUp(numerator1, _internalConstants.ONE, numerator1 / sqrtPX64 + amount);
83
+ const adjustedDenominator = numerator1 / sqrtPX64 + amount;
84
+ return _fullMath.FullMath.mulDivRoundingUp(numerator1, _internalConstants.ONE, adjustedDenominator);
77
85
  } else {
78
- let product = multiplyIn128(amount, sqrtPX64);
79
- (0, _tinyInvariant.default)(product / amount === sqrtPX64);
80
- (0, _tinyInvariant.default)(numerator1 > product);
86
+ const product = multiplyIn128(amount, sqrtPX64);
87
+ // Убрана invariant, предполагаем, что numerator1 > product
81
88
  const denominator = numerator1 - product;
82
89
  return _fullMath.FullMath.mulDivRoundingUp(numerator1, sqrtPX64, denominator);
83
90
  }
@@ -90,7 +97,7 @@ let SqrtPriceMath = exports.SqrtPriceMath = /*#__PURE__*/function () {
90
97
  return sqrtPX64 + quotient;
91
98
  } else {
92
99
  const quotient = _fullMath.FullMath.mulDivRoundingUp(amount, _internalConstants.Q64, liquidity);
93
- (0, _tinyInvariant.default)(sqrtPX64 > quotient);
100
+ // Убрана invariant, предполагаем, что sqrtPX64 > quotient
94
101
  return sqrtPX64 - quotient;
95
102
  }
96
103
  }
@@ -13,6 +13,7 @@ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r),
13
13
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
14
14
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
15
15
  const MAX_FEE = 10n ** 6n;
16
+ const MAX_FEE_MINUS_FEE_PIPS = feePips => MAX_FEE - BigInt(feePips);
16
17
  let SwapMath = exports.SwapMath = /*#__PURE__*/function () {
17
18
  /**
18
19
  * Cannot be constructed.
@@ -23,43 +24,42 @@ let SwapMath = exports.SwapMath = /*#__PURE__*/function () {
23
24
  return _createClass(SwapMath, null, [{
24
25
  key: "computeSwapStep",
25
26
  value: function computeSwapStep(sqrtRatioCurrentX64, sqrtRatioTargetX64, liquidity, amountRemaining, feePips) {
26
- const returnValues = {};
27
27
  const zeroForOne = sqrtRatioCurrentX64 >= sqrtRatioTargetX64;
28
28
  const exactIn = amountRemaining >= _internalConstants.ZERO;
29
+ let sqrtRatioNextX64;
30
+ let amountIn;
31
+ let amountOut;
32
+ let feeAmount;
29
33
  if (exactIn) {
30
- const amountRemainingLessFee = amountRemaining * (MAX_FEE - BigInt(feePips)) / MAX_FEE;
31
- returnValues.amountIn = zeroForOne ? _sqrtPriceMath.SqrtPriceMath.getAmountADelta(sqrtRatioTargetX64, sqrtRatioCurrentX64, liquidity, true) : _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(sqrtRatioCurrentX64, sqrtRatioTargetX64, liquidity, true);
32
- if (amountRemainingLessFee >= returnValues.amountIn) {
33
- returnValues.sqrtRatioNextX64 = sqrtRatioTargetX64;
34
+ const feeFactor = MAX_FEE_MINUS_FEE_PIPS(feePips);
35
+ const amountRemainingLessFee = amountRemaining * feeFactor / MAX_FEE;
36
+ const deltaIn = zeroForOne ? _sqrtPriceMath.SqrtPriceMath.getAmountADelta(sqrtRatioTargetX64, sqrtRatioCurrentX64, liquidity, true) : _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(sqrtRatioCurrentX64, sqrtRatioTargetX64, liquidity, true);
37
+ if (amountRemainingLessFee >= deltaIn) {
38
+ sqrtRatioNextX64 = sqrtRatioTargetX64;
39
+ amountIn = deltaIn;
34
40
  } else {
35
- returnValues.sqrtRatioNextX64 = _sqrtPriceMath.SqrtPriceMath.getNextSqrtPriceFromInput(sqrtRatioCurrentX64, liquidity, amountRemainingLessFee, zeroForOne);
41
+ sqrtRatioNextX64 = _sqrtPriceMath.SqrtPriceMath.getNextSqrtPriceFromInput(sqrtRatioCurrentX64, liquidity, amountRemainingLessFee, zeroForOne);
42
+ amountIn = zeroForOne ? _sqrtPriceMath.SqrtPriceMath.getAmountADelta(sqrtRatioNextX64, sqrtRatioCurrentX64, liquidity, true) : _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(sqrtRatioCurrentX64, sqrtRatioNextX64, liquidity, true);
36
43
  }
44
+ amountOut = zeroForOne ? _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(sqrtRatioNextX64, sqrtRatioCurrentX64, liquidity, false) : _sqrtPriceMath.SqrtPriceMath.getAmountADelta(sqrtRatioCurrentX64, sqrtRatioNextX64, liquidity, false);
45
+ feeAmount = sqrtRatioNextX64 !== sqrtRatioTargetX64 ? amountRemaining - amountIn : _fullMath.FullMath.mulDivRoundingUp(amountIn, BigInt(feePips), feeFactor);
37
46
  } else {
38
- returnValues.amountOut = zeroForOne ? _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(sqrtRatioTargetX64, sqrtRatioCurrentX64, liquidity, false) : _sqrtPriceMath.SqrtPriceMath.getAmountADelta(sqrtRatioCurrentX64, sqrtRatioTargetX64, liquidity, false);
39
- if (amountRemaining * _internalConstants.NEGATIVE_ONE >= returnValues.amountOut) {
40
- returnValues.sqrtRatioNextX64 = sqrtRatioTargetX64;
47
+ const deltaOut = zeroForOne ? _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(sqrtRatioTargetX64, sqrtRatioCurrentX64, liquidity, false) : _sqrtPriceMath.SqrtPriceMath.getAmountADelta(sqrtRatioCurrentX64, sqrtRatioTargetX64, liquidity, false);
48
+ const amountRemainingNegative = amountRemaining * _internalConstants.NEGATIVE_ONE;
49
+ if (amountRemainingNegative >= deltaOut) {
50
+ sqrtRatioNextX64 = sqrtRatioTargetX64;
51
+ amountOut = deltaOut;
41
52
  } else {
42
- returnValues.sqrtRatioNextX64 = _sqrtPriceMath.SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtRatioCurrentX64, liquidity, amountRemaining * _internalConstants.NEGATIVE_ONE, zeroForOne);
53
+ sqrtRatioNextX64 = _sqrtPriceMath.SqrtPriceMath.getNextSqrtPriceFromOutput(sqrtRatioCurrentX64, liquidity, amountRemainingNegative, zeroForOne);
54
+ amountOut = zeroForOne ? _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(sqrtRatioNextX64, sqrtRatioCurrentX64, liquidity, false) : _sqrtPriceMath.SqrtPriceMath.getAmountADelta(sqrtRatioCurrentX64, sqrtRatioNextX64, liquidity, false);
43
55
  }
56
+ amountIn = zeroForOne ? _sqrtPriceMath.SqrtPriceMath.getAmountADelta(sqrtRatioNextX64, sqrtRatioCurrentX64, liquidity, true) : _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(sqrtRatioCurrentX64, sqrtRatioNextX64, liquidity, true);
57
+ if (amountOut > amountRemainingNegative) {
58
+ amountOut = amountRemainingNegative;
59
+ }
60
+ feeAmount = _fullMath.FullMath.mulDivRoundingUp(amountIn, BigInt(feePips), MAX_FEE_MINUS_FEE_PIPS(feePips));
44
61
  }
45
- const max = sqrtRatioTargetX64 === returnValues.sqrtRatioNextX64;
46
- if (zeroForOne) {
47
- returnValues.amountIn = max && exactIn ? returnValues.amountIn : _sqrtPriceMath.SqrtPriceMath.getAmountADelta(returnValues.sqrtRatioNextX64, sqrtRatioCurrentX64, liquidity, true);
48
- returnValues.amountOut = max && !exactIn ? returnValues.amountOut : _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(returnValues.sqrtRatioNextX64, sqrtRatioCurrentX64, liquidity, false);
49
- } else {
50
- returnValues.amountIn = max && exactIn ? returnValues.amountIn : _sqrtPriceMath.SqrtPriceMath.getAmountBDelta(sqrtRatioCurrentX64, returnValues.sqrtRatioNextX64, liquidity, true);
51
- returnValues.amountOut = max && !exactIn ? returnValues.amountOut : _sqrtPriceMath.SqrtPriceMath.getAmountADelta(sqrtRatioCurrentX64, returnValues.sqrtRatioNextX64, liquidity, false);
52
- }
53
- if (!exactIn && returnValues.amountOut > amountRemaining * _internalConstants.NEGATIVE_ONE) {
54
- returnValues.amountOut = amountRemaining * _internalConstants.NEGATIVE_ONE;
55
- }
56
- if (exactIn && returnValues.sqrtRatioNextX64 !== sqrtRatioTargetX64) {
57
- // we didn't reach the target, so take the remainder of the maximum input as fee
58
- returnValues.feeAmount = amountRemaining - returnValues.amountIn;
59
- } else {
60
- returnValues.feeAmount = _fullMath.FullMath.mulDivRoundingUp(returnValues.amountIn, BigInt(feePips), MAX_FEE - BigInt(feePips));
61
- }
62
- return [returnValues.sqrtRatioNextX64, returnValues.amountIn, returnValues.amountOut, returnValues.feeAmount];
62
+ return [sqrtRatioNextX64, amountIn, amountOut, feeAmount];
63
63
  }
64
64
  }]);
65
65
  }();