@paraswap/dex-lib 3.6.2 → 3.6.3

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.
Files changed (109) hide show
  1. package/build/dex/aave-v1/aave-v1.d.ts +1 -2
  2. package/build/dex/aave-v1/aave-v1.js +0 -23
  3. package/build/dex/aave-v1/aave-v1.js.map +1 -1
  4. package/build/dex/compound.js +1 -1
  5. package/build/dex/compound.js.map +1 -1
  6. package/build/dex/etherfi/etherfi.d.ts +26 -0
  7. package/build/dex/etherfi/etherfi.js +96 -0
  8. package/build/dex/etherfi/etherfi.js.map +1 -0
  9. package/build/dex/index.js +2 -0
  10. package/build/dex/index.js.map +1 -1
  11. package/build/dex/maverick-v2/config.d.ts +2 -2
  12. package/build/dex/maverick-v2/config.js +16 -9
  13. package/build/dex/maverick-v2/config.js.map +1 -1
  14. package/build/dex/maverick-v2/maverick-math/maverick-basic-math.js +3 -3
  15. package/build/dex/maverick-v2/maverick-math/maverick-basic-math.js.map +1 -1
  16. package/build/dex/maverick-v2/maverick-math/maverick-bin-math.js +4 -4
  17. package/build/dex/maverick-v2/maverick-math/maverick-bin-math.js.map +1 -1
  18. package/build/dex/maverick-v2/maverick-math/maverick-math.js +3 -3
  19. package/build/dex/maverick-v2/maverick-math/maverick-math.js.map +1 -1
  20. package/build/dex/maverick-v2/maverick-math/maverick-pool-math.js +13 -13
  21. package/build/dex/maverick-v2/maverick-math/maverick-pool-math.js.map +1 -1
  22. package/build/dex/maverick-v2/maverick-math/maverick-swap-math.js +1 -1
  23. package/build/dex/maverick-v2/maverick-math/maverick-swap-math.js.map +1 -1
  24. package/build/dex/maverick-v2/maverick-math/maverick-tick-math.js +4 -4
  25. package/build/dex/maverick-v2/maverick-math/maverick-tick-math.js.map +1 -1
  26. package/build/dex/maverick-v2/maverick-math/maverick-twa-math.js +3 -3
  27. package/build/dex/maverick-v2/maverick-math/maverick-twa-math.js.map +1 -1
  28. package/build/dex/maverick-v2/maverick-v2-pool.d.ts +12 -9
  29. package/build/dex/maverick-v2/maverick-v2-pool.js +71 -16
  30. package/build/dex/maverick-v2/maverick-v2-pool.js.map +1 -1
  31. package/build/dex/maverick-v2/maverick-v2.d.ts +4 -8
  32. package/build/dex/maverick-v2/maverick-v2.js +62 -90
  33. package/build/dex/maverick-v2/maverick-v2.js.map +1 -1
  34. package/build/dex/maverick-v2/types.d.ts +1 -2
  35. package/build/dex/platypus/platypus.d.ts +1 -2
  36. package/build/dex/platypus/platypus.js +0 -45
  37. package/build/dex/platypus/platypus.js.map +1 -1
  38. package/build/dex/sdai/config.d.ts +11 -0
  39. package/build/dex/sdai/config.js +21 -0
  40. package/build/dex/sdai/config.js.map +1 -0
  41. package/build/dex/sdai/constants.d.ts +2 -0
  42. package/build/dex/sdai/constants.js +6 -0
  43. package/build/dex/sdai/constants.js.map +1 -0
  44. package/build/dex/sdai/scripts/validate-state.js +102 -0
  45. package/build/dex/sdai/scripts/validate-state.js.map +1 -0
  46. package/build/dex/sdai/sdai-pool.d.ts +16 -0
  47. package/build/dex/sdai/sdai-pool.js +85 -0
  48. package/build/dex/sdai/sdai-pool.js.map +1 -0
  49. package/build/dex/sdai/sdai.d.ts +51 -0
  50. package/build/dex/sdai/sdai.js +172 -0
  51. package/build/dex/sdai/sdai.js.map +1 -0
  52. package/build/dex/sdai/types.d.ts +21 -0
  53. package/build/dex/sdai/types.js +11 -0
  54. package/build/dex/sdai/types.js.map +1 -0
  55. package/build/dex/sdai/utils.d.ts +4 -0
  56. package/build/dex/sdai/utils.js +39 -0
  57. package/build/dex/sdai/utils.js.map +1 -0
  58. package/build/dex/stable-pool.js +8 -1
  59. package/build/dex/stable-pool.js.map +1 -1
  60. package/build/dex/swaap-v1/swaap-v1.d.ts +1 -2
  61. package/build/dex/swaap-v1/swaap-v1.js +0 -14
  62. package/build/dex/swaap-v1/swaap-v1.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/abi/maverick-v2/MaverickV2Pool.json +1234 -0
  65. package/src/abi/maverick-v2/MaverickV2PoolLens.json +1232 -0
  66. package/src/abi/maverick-v2/MaverickV2Quoter.json +278 -0
  67. package/src/dex/index.ts +2 -0
  68. package/src/dex/maverick-v2/config.ts +28 -0
  69. package/src/dex/maverick-v2/maverick-math/maverick-basic-math.ts +152 -0
  70. package/src/dex/maverick-v2/maverick-math/maverick-bin-math.ts +288 -0
  71. package/src/dex/maverick-v2/maverick-math/maverick-delta-math.ts +32 -0
  72. package/src/dex/maverick-v2/maverick-math/maverick-math.ts +30 -0
  73. package/src/dex/maverick-v2/maverick-math/maverick-pool-lib.ts +42 -0
  74. package/src/dex/maverick-v2/maverick-math/maverick-pool-math.ts +709 -0
  75. package/src/dex/maverick-v2/maverick-math/maverick-swap-math.ts +199 -0
  76. package/src/dex/maverick-v2/maverick-math/maverick-tick-math.ts +171 -0
  77. package/src/dex/maverick-v2/maverick-math/maverick-twa-math.ts +54 -0
  78. package/src/dex/maverick-v2/maverick-v2-e2e.test.ts +193 -0
  79. package/src/dex/maverick-v2/maverick-v2-events.test.ts +112 -0
  80. package/src/dex/maverick-v2/maverick-v2-integration.test.ts +283 -0
  81. package/src/dex/maverick-v2/maverick-v2-pool.ts +346 -0
  82. package/src/dex/maverick-v2/maverick-v2.ts +380 -0
  83. package/src/dex/maverick-v2/types.ts +151 -0
  84. package/tests/constants-e2e.ts +2 -2
  85. package/.vscode/launch.json +0 -53
  86. package/.vscode/settings.json +0 -2
  87. package/.vscode/tasks.json +0 -15
  88. package/build/abi/uniswap-v3/AlienBaseV3Router.abi.json +0 -52
  89. package/build/abi/wombat/pool.json +0 -1289
  90. package/build/dex/aave-v2/tokens-avalanche.json +0 -44
  91. package/build/dex/aave-v2/tokens-mainnet.json +0 -188
  92. package/build/dex/aave-v2/tokens-polygon.json +0 -44
  93. package/build/dex/maker-psm/scripts/gem.abi.json +0 -136
  94. package/build/dex/maker-psm/scripts/validate-state.d.ts +0 -0
  95. package/build/dex/maker-psm/scripts/validate-state.js +0 -185
  96. package/build/dex/maker-psm/scripts/validate-state.js.map +0 -1
  97. package/build/dex/maker-psm/scripts/vat.abi.json +0 -243
  98. package/build/dex/solidly-v3/scripts/check-event-pool-event.js +0 -53
  99. package/build/dex/solidly-v3/scripts/check-event-pool-event.js.map +0 -1
  100. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.d.ts +0 -17
  101. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js +0 -64
  102. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js.map +0 -1
  103. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.d.ts +0 -17
  104. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js +0 -79
  105. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js.map +0 -1
  106. package/src/dex/maker-psm/scripts/gem.abi.json +0 -136
  107. package/src/dex/maker-psm/scripts/validate-state.ts +0 -221
  108. package/src/dex/maker-psm/scripts/vat.abi.json +0 -243
  109. /package/build/dex/{solidly-v3/scripts/check-event-pool-event.d.ts → sdai/scripts/validate-state.d.ts} +0 -0
@@ -0,0 +1,709 @@
1
+ import {
2
+ PoolState,
3
+ MoveData,
4
+ Tick,
5
+ Bin,
6
+ TickData,
7
+ RemoveLiquidityParams,
8
+ AddLiquidityParams,
9
+ AddLiquidityInfo,
10
+ } from '../types';
11
+ import { BI_POWS } from '../../../bigint-constants';
12
+ import { _require } from '../../../utils';
13
+ import { MaverickBasicMath } from './maverick-basic-math';
14
+ import { MaverickMath } from './maverick-math';
15
+ import { Delta, MaverickDeltaMath } from './maverick-delta-math';
16
+ import { TwaMath } from './maverick-twa-math';
17
+ import { MaverickSwapMath } from './maverick-swap-math';
18
+ import { MaverickBinMath } from './maverick-bin-math';
19
+ import { MaverickPoolLib } from './maverick-pool-lib';
20
+ import { MaverickTickMath } from './maverick-tick-math';
21
+
22
+ export class MaverickPoolMath {
23
+ state: PoolState;
24
+ tokenAScale: bigint;
25
+ tokenBScale: bigint;
26
+ timestamp: bigint;
27
+
28
+ constructor(
29
+ private feeAIn: bigint,
30
+ private feeBIn: bigint,
31
+ private lookback: bigint,
32
+ private tickSpacing: bigint,
33
+ private protocolFeeRatioD3: bigint,
34
+ private activeTick: bigint,
35
+ private tokenADecimals: bigint,
36
+ private tokenBDecimals: bigint,
37
+ ) {
38
+ this.state = {
39
+ activeTick: this.activeTick,
40
+ reserveA: 0n,
41
+ reserveB: 0n,
42
+ lastTwaD8: 0n,
43
+ lastLogPriceD8: 0n,
44
+ lastTimestamp: 0n,
45
+ binCounter: 0n,
46
+ bins: {},
47
+ ticks: {},
48
+ };
49
+ this.tokenAScale = MaverickMath.scale(this.tokenADecimals);
50
+ this.tokenBScale = MaverickMath.scale(this.tokenBDecimals);
51
+ this.timestamp = 0n;
52
+ }
53
+
54
+ advanceTime(delta: bigint) {
55
+ this.timestamp += delta;
56
+ }
57
+
58
+ combine(self: Delta, delta: Delta) {
59
+ if (!self.skipCombine) {
60
+ self.deltaInBinInternal += delta.deltaInBinInternal;
61
+ self.deltaInErc += delta.deltaInErc;
62
+ self.deltaOutErc += delta.deltaOutErc;
63
+ }
64
+ self.excess = delta.excess;
65
+ self.swappedToMaxPrice = delta.swappedToMaxPrice;
66
+ self.fractionalPart = delta.fractionalPart;
67
+ }
68
+
69
+ estimateSwap(
70
+ state: PoolState,
71
+ amount: bigint,
72
+ tokenAIn: boolean,
73
+ exactOutput: boolean,
74
+ tickLimit: bigint,
75
+ ): [bigint, bigint] {
76
+ this.setState(state);
77
+ let delta: Delta = {
78
+ deltaInBinInternal: 0n,
79
+ deltaInErc: 0n,
80
+ deltaOutErc: 0n,
81
+ excess: amount,
82
+ tokenAIn: tokenAIn,
83
+ exactOutput: exactOutput,
84
+ swappedToMaxPrice: false,
85
+ skipCombine: false,
86
+ tickLimit: tickLimit,
87
+ sqrtLowerTickPrice: 0n,
88
+ sqrtUpperTickPrice: 0n,
89
+ sqrtPrice: 0n,
90
+ fractionalPart: 0n,
91
+ };
92
+
93
+ let startingTick = this.state.activeTick;
94
+ if (
95
+ (startingTick > tickLimit && tokenAIn) ||
96
+ (startingTick < tickLimit && !tokenAIn)
97
+ ) {
98
+ throw 'Beyond Swap Limit';
99
+ }
100
+
101
+ let inScale = tokenAIn ? this.tokenAScale : this.tokenBScale;
102
+ let outScale = tokenAIn ? this.tokenBScale : this.tokenAScale;
103
+
104
+ delta.excess = !exactOutput
105
+ ? MaverickMath.tokenScaleToAmmScale(amount, inScale)
106
+ : MaverickMath.tokenScaleToAmmScale(amount, outScale);
107
+
108
+ delta.tokenAIn = tokenAIn;
109
+ delta.exactOutput = exactOutput;
110
+ delta.tickLimit = tickLimit;
111
+
112
+ while (delta.excess != 0n) {
113
+ let newDelta = this.swapTick(delta);
114
+ this.combine(delta, newDelta);
115
+ }
116
+
117
+ let amountIn = MaverickMath.ammScaleToTokenScale(
118
+ delta.deltaInErc,
119
+ inScale,
120
+ exactOutput || delta.swappedToMaxPrice,
121
+ );
122
+
123
+ let amountOut = MaverickMath.ammScaleToTokenScale(
124
+ delta.deltaOutErc,
125
+ outScale,
126
+ false,
127
+ );
128
+
129
+ return [amountIn, amountOut];
130
+ }
131
+
132
+ swap(
133
+ state: PoolState,
134
+ timestamp: bigint,
135
+ amount: bigint,
136
+ tokenAIn: boolean,
137
+ exactOutput: boolean,
138
+ tickLimit: bigint,
139
+ ): [bigint, bigint] {
140
+ this.timestamp = timestamp;
141
+ this.setState(state);
142
+ let delta: Delta = {
143
+ deltaInBinInternal: 0n,
144
+ deltaInErc: 0n,
145
+ deltaOutErc: 0n,
146
+ excess: amount,
147
+ tokenAIn: tokenAIn,
148
+ exactOutput: exactOutput,
149
+ swappedToMaxPrice: false,
150
+ skipCombine: false,
151
+ tickLimit: tickLimit,
152
+ sqrtLowerTickPrice: 0n,
153
+ sqrtUpperTickPrice: 0n,
154
+ sqrtPrice: 0n,
155
+ fractionalPart: 0n,
156
+ };
157
+
158
+ let startingTick = this.state.activeTick;
159
+ if (
160
+ (startingTick > tickLimit && tokenAIn) ||
161
+ (startingTick < tickLimit && !tokenAIn)
162
+ ) {
163
+ throw 'Beyond Swap Limit';
164
+ }
165
+
166
+ let inScale = tokenAIn ? this.tokenAScale : this.tokenBScale;
167
+ let outScale = tokenAIn ? this.tokenBScale : this.tokenAScale;
168
+
169
+ delta.excess = !exactOutput
170
+ ? MaverickMath.tokenScaleToAmmScale(amount, inScale)
171
+ : MaverickMath.tokenScaleToAmmScale(amount, outScale);
172
+
173
+ delta.tokenAIn = tokenAIn;
174
+ delta.exactOutput = exactOutput;
175
+ delta.tickLimit = tickLimit;
176
+
177
+ while (delta.excess != 0n) {
178
+ let newDelta = this.swapTick(delta);
179
+ this.combine(delta, newDelta);
180
+ }
181
+
182
+ let amountIn = MaverickMath.ammScaleToTokenScale(
183
+ delta.deltaInErc,
184
+ inScale,
185
+ exactOutput || delta.swappedToMaxPrice,
186
+ );
187
+
188
+ let amountOut = MaverickMath.ammScaleToTokenScale(
189
+ delta.deltaOutErc,
190
+ outScale,
191
+ false,
192
+ );
193
+
194
+ let lastTwaD8 = this.state.lastTwaD8;
195
+
196
+ TwaMath.updateValue(
197
+ this.state,
198
+ this.state.activeTick * BI_POWS[8] + delta.fractionalPart,
199
+ this.lookback,
200
+ this.timestamp,
201
+ );
202
+
203
+ this.moveBins(
204
+ startingTick,
205
+ this.state.activeTick,
206
+ lastTwaD8,
207
+ this.state.lastTwaD8,
208
+ 5n * BI_POWS[7],
209
+ );
210
+
211
+ let newInternalBalance = tokenAIn
212
+ ? this.state.reserveA + amountIn
213
+ : this.state.reserveB + amountIn;
214
+
215
+ [this.state.reserveA, this.state.reserveB] = tokenAIn
216
+ ? [newInternalBalance, this.state.reserveB - amountOut]
217
+ : [this.state.reserveA - amountOut, newInternalBalance];
218
+
219
+ return [amountIn, amountOut];
220
+ }
221
+
222
+ moveBins(
223
+ startingActiveTick: bigint,
224
+ activeTick: bigint,
225
+ lastTwapD8: bigint,
226
+ newTwapD8: bigint,
227
+ boundary: bigint,
228
+ ) {
229
+ let newTwap = MaverickBasicMath.floorD8Unchecked(newTwapD8 - boundary);
230
+ let lastTwap = MaverickBasicMath.floorD8Unchecked(lastTwapD8 - boundary);
231
+
232
+ if (activeTick > startingActiveTick || newTwap > lastTwap) {
233
+ let moveData: MoveData = {
234
+ kind: 0n,
235
+ tickSearchStart: 0n,
236
+ tickSearchEnd: 0n,
237
+ tickLimit: 0n,
238
+ firstBinTick: 0n,
239
+ firstBinId: 0n,
240
+ mergeBinBalance: 0n,
241
+ totalReserveA: 0n,
242
+ totalReserveB: 0n,
243
+ mergeBins: {},
244
+ counter: 0n,
245
+ };
246
+
247
+ moveData.tickLimit = MaverickBasicMath.min(activeTick - 1n, newTwap);
248
+
249
+ if (lastTwap - 1n < moveData.tickLimit) {
250
+ moveData.tickSearchStart = lastTwap - 1n;
251
+ moveData.tickSearchEnd = moveData.tickLimit;
252
+ moveData.kind = 1n;
253
+ this.moveDirection(moveData);
254
+ moveData.kind = 3n;
255
+ this.moveDirection(moveData);
256
+
257
+ // will never move both directions in one swap
258
+ return;
259
+ }
260
+ }
261
+
262
+ newTwap = MaverickBasicMath.floorD8Unchecked(newTwapD8 + boundary);
263
+ lastTwap = MaverickBasicMath.floorD8Unchecked(lastTwapD8 + boundary);
264
+
265
+ if (activeTick < startingActiveTick || newTwap < lastTwap) {
266
+ let moveData: MoveData = {
267
+ kind: 0n,
268
+ tickSearchStart: 0n,
269
+ tickSearchEnd: 0n,
270
+ tickLimit: 0n,
271
+ firstBinTick: 0n,
272
+ firstBinId: 0n,
273
+ mergeBinBalance: 0n,
274
+ totalReserveA: 0n,
275
+ totalReserveB: 0n,
276
+ mergeBins: {},
277
+ counter: 0n,
278
+ };
279
+
280
+ moveData.tickLimit = MaverickBasicMath.max(newTwap, activeTick + 1n);
281
+
282
+ if (moveData.tickLimit < lastTwap + 1n) {
283
+ moveData.tickSearchStart = moveData.tickLimit;
284
+ moveData.tickSearchEnd = lastTwap + 1n;
285
+ moveData.kind = 2n;
286
+ this.moveDirection(moveData);
287
+ moveData.kind = 3n;
288
+ this.moveDirection(moveData);
289
+ }
290
+ }
291
+ }
292
+
293
+ moveDirection(moveData: MoveData) {
294
+ moveData.firstBinTick = 0n;
295
+ moveData.firstBinId = 0n;
296
+ moveData.mergeBinBalance = 0n;
297
+ moveData.totalReserveA = 0n;
298
+ moveData.totalReserveB = 0n;
299
+ moveData.counter = 0n;
300
+
301
+ this.getMovementBinsInRange(moveData);
302
+
303
+ if (
304
+ moveData.firstBinId === 0n ||
305
+ (moveData.counter === 1n && moveData.tickLimit === moveData.firstBinTick)
306
+ ) {
307
+ return;
308
+ }
309
+
310
+ let firstBin = this.state.bins[moveData.firstBinId.toString()];
311
+ let firstBinTickState = this.state.ticks[moveData.firstBinTick.toString()];
312
+ this.mergeBinsInList(firstBin, firstBinTickState, moveData);
313
+ if (moveData.tickLimit != moveData.firstBinTick) {
314
+ this.moveBinToNewTick(
315
+ firstBin,
316
+ firstBinTickState,
317
+ this.state.ticks[moveData.tickLimit.toString()],
318
+ moveData,
319
+ );
320
+ }
321
+ }
322
+
323
+ getMovementBinsInRange(moveData: MoveData) {
324
+ for (
325
+ let tick = moveData.tickSearchStart;
326
+ tick <= moveData.tickSearchEnd;
327
+ tick++
328
+ ) {
329
+ if (moveData.counter === 3n) return;
330
+ let binId = this.binIdByTickKind(tick, moveData.kind);
331
+ if (binId === 0n) continue;
332
+ moveData.mergeBins[moveData.counter.toString()] = binId;
333
+ moveData.counter++;
334
+ if (moveData.firstBinId === 0n || binId < moveData.firstBinId) {
335
+ moveData.firstBinId = binId;
336
+ moveData.firstBinTick = tick;
337
+ }
338
+ }
339
+ }
340
+
341
+ binIdByTickKind(tick: bigint, kind: bigint): bigint {
342
+ return (
343
+ this.state.ticks[tick.toString()]?.binIdsByTick[kind.toString()] || 0n
344
+ );
345
+ }
346
+
347
+ moveBinToNewTick(
348
+ firstBin: Bin,
349
+ startingTickState: Tick,
350
+ endingTickState: Tick,
351
+ moveData: MoveData,
352
+ ) {
353
+ let [firstBinA, firstBinB] = MaverickPoolLib.binReserves(
354
+ firstBin,
355
+ startingTickState,
356
+ );
357
+
358
+ startingTickState.reserveA = MaverickBasicMath.clip(
359
+ startingTickState.reserveA,
360
+ firstBinA,
361
+ );
362
+ startingTickState.reserveB = MaverickBasicMath.clip(
363
+ startingTickState.reserveB,
364
+ firstBinB,
365
+ );
366
+ startingTickState.totalSupply = MaverickBasicMath.clip(
367
+ startingTickState.totalSupply,
368
+ firstBin.tickBalance,
369
+ );
370
+ startingTickState.binIdsByTick[moveData.kind.toString()] = 0n;
371
+ if (this.state.ticks[firstBin.tick.toString()].totalSupply === 0n) {
372
+ delete this.state.ticks[firstBin.tick.toString()];
373
+ }
374
+ endingTickState.binIdsByTick[moveData.kind.toString()] =
375
+ moveData.firstBinId;
376
+ firstBin.tick = moveData.tickLimit;
377
+ let deltaTickBalance;
378
+ if (firstBinA > firstBinB) {
379
+ deltaTickBalance = MaverickBasicMath.mulDivDown(
380
+ firstBinA,
381
+ MaverickBasicMath.max(1n, endingTickState.totalSupply),
382
+ endingTickState.reserveA,
383
+ );
384
+ } else {
385
+ deltaTickBalance = MaverickBasicMath.mulDivDown(
386
+ firstBinB,
387
+ MaverickBasicMath.max(1n, endingTickState.totalSupply),
388
+ endingTickState.reserveB,
389
+ );
390
+ }
391
+
392
+ endingTickState.reserveA += firstBinA;
393
+ endingTickState.reserveB += firstBinB;
394
+ firstBin.tickBalance = deltaTickBalance;
395
+ endingTickState.totalSupply += deltaTickBalance;
396
+ }
397
+
398
+ mergeBinsInList(firstBin: Bin, firstBinTickState: Tick, moveData: MoveData) {
399
+ let mergeOccured;
400
+
401
+ for (let i = 0; i < moveData.counter; i++) {
402
+ let binId = moveData.mergeBins[i];
403
+ if (binId === moveData.firstBinId) continue;
404
+ mergeOccured = true;
405
+
406
+ let [binA, binB, mergeBinBalance] = this.mergeAndDecommissionBin(
407
+ binId,
408
+ moveData.firstBinId,
409
+ firstBin,
410
+ firstBinTickState,
411
+ moveData.kind,
412
+ );
413
+
414
+ moveData.totalReserveA += binA;
415
+ moveData.totalReserveB += binB;
416
+ moveData.mergeBinBalance += mergeBinBalance;
417
+ }
418
+
419
+ if (mergeOccured) {
420
+ MaverickBinMath.addLiquidityByReserves(
421
+ firstBin,
422
+ firstBinTickState,
423
+ moveData.totalReserveA,
424
+ moveData.totalReserveB,
425
+ moveData.mergeBinBalance,
426
+ );
427
+ }
428
+ }
429
+
430
+ mergeAndDecommissionBin(
431
+ binIdToBeMerged: bigint,
432
+ parentBinId: bigint,
433
+ parentBin: Bin,
434
+ parentBinTick: Tick,
435
+ kind: bigint,
436
+ ): [bigint, bigint, bigint] {
437
+ let bin = this.state.bins[binIdToBeMerged.toString()];
438
+ let tick = this.state.ticks[bin.tick.toString()];
439
+
440
+ let [binA, binB] = MaverickPoolLib.binReserves(bin, tick);
441
+ bin.mergeId = parentBinId;
442
+
443
+ let mergeBinBalance = MaverickBinMath.lpBalancesFromDeltaReserve(
444
+ parentBin,
445
+ parentBinTick,
446
+ binA,
447
+ binB,
448
+ );
449
+ bin.mergeBinBalance = mergeBinBalance;
450
+
451
+ tick.totalSupply = MaverickBasicMath.clip(
452
+ tick.totalSupply,
453
+ bin.tickBalance,
454
+ );
455
+ tick.reserveA = MaverickBasicMath.clip(tick.reserveA, binA);
456
+ tick.reserveB = MaverickBasicMath.clip(tick.reserveB, binB);
457
+ delete tick.binIdsByTick[kind.toString()];
458
+
459
+ return [binA, binB, mergeBinBalance];
460
+ }
461
+
462
+ removeLiquidity(
463
+ state: PoolState,
464
+ timestamp: bigint,
465
+ params: RemoveLiquidityParams,
466
+ ) {
467
+ this.timestamp = timestamp;
468
+ this.setState(state);
469
+
470
+ for (let i = 0; i < params.binIds.length; i++) {
471
+ let bin = this.state.bins[params.binIds[i].toString()];
472
+ let [deltaA, deltaB] = MaverickBinMath.removeLiquidity(
473
+ bin,
474
+ this.state.ticks,
475
+ this.state.bins,
476
+ params.amounts[i],
477
+ );
478
+
479
+ this.state.reserveA -= MaverickMath.ammScaleToTokenScale(
480
+ deltaA,
481
+ this.tokenAScale,
482
+ false,
483
+ );
484
+ this.state.reserveB -= MaverickMath.ammScaleToTokenScale(
485
+ deltaB,
486
+ this.tokenBScale,
487
+ false,
488
+ );
489
+ }
490
+ }
491
+
492
+ getOrCreateBin(kind: bigint, tick: bigint): [bigint, Bin] {
493
+ let binId = this.binIdByTickKind(tick, kind);
494
+
495
+ let bin;
496
+ if (binId === 0n) {
497
+ this.state.binCounter++;
498
+ binId = this.state.binCounter;
499
+ bin = {
500
+ tick: tick,
501
+ kind: kind,
502
+ mergeBinBalance: 0n,
503
+ mergeId: 0n,
504
+ totalSupply: 0n,
505
+ tickBalance: 0n,
506
+ };
507
+ this.state.bins[binId.toString()] = bin;
508
+ if (!this.state.ticks[tick.toString()]) {
509
+ this.state.ticks[tick.toString()] = {
510
+ reserveA: 0n,
511
+ reserveB: 0n,
512
+ totalSupply: 0n,
513
+ binIdsByTick: {},
514
+ };
515
+ }
516
+ this.state.ticks[tick.toString()].binIdsByTick[kind.toString()] = binId;
517
+ }
518
+
519
+ if (!bin) bin = this.state.bins[binId.toString()];
520
+
521
+ return [binId, bin];
522
+ }
523
+
524
+ migrateBinUpStack(binId: bigint, maxRecursion: bigint) {
525
+ let bin = this.state.bins[binId.toString()];
526
+ MaverickBinMath.migrateBinsUpStack(bin, this.state.bins, maxRecursion);
527
+ }
528
+
529
+ setState(state: PoolState) {
530
+ let activeTick = this.state.activeTick;
531
+ let value = this.state.activeTick * BI_POWS[8] + 5n * BI_POWS[7];
532
+ this.state = state;
533
+
534
+ if (this.state.lastTimestamp === 0n) {
535
+ this.state.activeTick = activeTick;
536
+ this.state.lastTwaD8 = value;
537
+ this.state.lastLogPriceD8 = value;
538
+ this.state.lastTimestamp = this.timestamp;
539
+ }
540
+ }
541
+
542
+ addLiquidity(
543
+ state: PoolState,
544
+ timestamp: bigint,
545
+ params: AddLiquidityParams,
546
+ ) {
547
+ this.timestamp = timestamp;
548
+ this.setState(state);
549
+ let addLiquidityInfo: AddLiquidityInfo = {
550
+ deltaA: 0n,
551
+ deltaB: 0n,
552
+ tickLtActive: false,
553
+ tickSpacing: this.tickSpacing,
554
+ tick: 0n,
555
+ };
556
+
557
+ let tokenAAmount = 0n;
558
+ let tokenBAmount = 0n;
559
+
560
+ for (let i = 0; i < params.ticks.length; i++) {
561
+ addLiquidityInfo.tick = params.ticks[i];
562
+ let [binId, bin] = this.getOrCreateBin(params.kind, params.ticks[i]);
563
+ addLiquidityInfo.tickLtActive =
564
+ addLiquidityInfo.tick < this.state.activeTick;
565
+
566
+ MaverickBinMath.addLiquidity(
567
+ bin,
568
+ this.state.ticks[bin.tick.toString()],
569
+ params.amounts[i],
570
+ addLiquidityInfo,
571
+ );
572
+
573
+ if (addLiquidityInfo.deltaA === 0n && addLiquidityInfo.deltaB === 0n) {
574
+ throw 'zero liquidity added';
575
+ }
576
+
577
+ tokenAAmount += addLiquidityInfo.deltaA;
578
+ tokenBAmount += addLiquidityInfo.deltaB;
579
+ }
580
+
581
+ this.state.reserveA += MaverickMath.ammScaleToTokenScale(
582
+ tokenAAmount,
583
+ this.tokenAScale,
584
+ true,
585
+ );
586
+ this.state.reserveB += MaverickMath.ammScaleToTokenScale(
587
+ tokenBAmount,
588
+ this.tokenBScale,
589
+ true,
590
+ );
591
+ }
592
+
593
+ tickSqrtPriceAndLiquidity(tick: bigint): [bigint, bigint, bigint, TickData] {
594
+ let tickState = this.state.ticks[tick.toString()];
595
+ let output: TickData = {
596
+ currentReserveA: tickState.reserveA,
597
+ currentReserveB: tickState.reserveB,
598
+ currentLiquidity: 0n,
599
+ };
600
+
601
+ let [sqrtLowerTickPrice, sqrtUpperTickPrice] =
602
+ MaverickTickMath.tickSqrtPrices(this.tickSpacing, tick);
603
+
604
+ let sqrtPrice;
605
+ [sqrtPrice, output.currentLiquidity] =
606
+ MaverickTickMath.getTickSqrtPriceAndL(
607
+ output.currentReserveA,
608
+ output.currentReserveB,
609
+ sqrtLowerTickPrice,
610
+ sqrtUpperTickPrice,
611
+ );
612
+
613
+ return [sqrtLowerTickPrice, sqrtUpperTickPrice, sqrtPrice, output];
614
+ }
615
+
616
+ swapTick(delta: Delta): Delta {
617
+ let tickData: TickData;
618
+ let newDelta;
619
+ let activeTick = this.state.activeTick;
620
+ if (MaverickDeltaMath.pastMaxTick(delta, activeTick)) {
621
+ this.state.activeTick += delta.tokenAIn ? -1n : 1n;
622
+ return delta;
623
+ }
624
+
625
+ while (
626
+ (this.state.ticks[activeTick.toString()]?.reserveA || 0n) === 0n &&
627
+ (this.state.ticks[activeTick.toString()]?.reserveB || 0n) === 0n
628
+ ) {
629
+ activeTick += delta.tokenAIn ? 1n : -1n;
630
+
631
+ if (MaverickDeltaMath.pastMaxTick(delta, activeTick)) {
632
+ this.state.activeTick += delta.tokenAIn ? 1n : -1n;
633
+ return delta;
634
+ }
635
+ }
636
+
637
+ [
638
+ delta.sqrtLowerTickPrice,
639
+ delta.sqrtUpperTickPrice,
640
+ delta.sqrtPrice,
641
+ tickData,
642
+ ] = this.tickSqrtPriceAndLiquidity(activeTick);
643
+
644
+ this.state.activeTick = activeTick;
645
+
646
+ newDelta = delta.exactOutput
647
+ ? MaverickSwapMath.computeSwapExactOut(
648
+ delta.sqrtPrice,
649
+ tickData,
650
+ delta.excess,
651
+ delta.tokenAIn,
652
+ this.fee(delta.tokenAIn),
653
+ this.protocolFeeRatioD3,
654
+ )
655
+ : MaverickSwapMath.computeSwapExactIn(
656
+ delta.sqrtPrice,
657
+ tickData,
658
+ delta.excess,
659
+ delta.tokenAIn,
660
+ this.fee(delta.tokenAIn),
661
+ this.protocolFeeRatioD3,
662
+ );
663
+
664
+ if (newDelta.excess === 0n) {
665
+ MaverickSwapMath.computeEndPrice(delta, newDelta, tickData);
666
+ }
667
+
668
+ this.allocateSwapValuesToTick(
669
+ newDelta,
670
+ delta.tokenAIn,
671
+ this.state.activeTick,
672
+ );
673
+
674
+ if (newDelta.excess != 0n) {
675
+ this.state.activeTick = delta.tokenAIn
676
+ ? this.state.activeTick + 1n
677
+ : this.state.activeTick - 1n;
678
+ }
679
+
680
+ return newDelta;
681
+ }
682
+
683
+ fee(tokenAIn: boolean): bigint {
684
+ return tokenAIn ? this.feeAIn : this.feeBIn;
685
+ }
686
+
687
+ allocateSwapValuesToTick(delta: Delta, tokenAIn: boolean, tick: bigint) {
688
+ let tickState = this.state.ticks[tick.toString()];
689
+ let reserveA = tickState.reserveA;
690
+ let reserveB = tickState.reserveB;
691
+
692
+ if (tokenAIn) {
693
+ reserveA = reserveA + delta.deltaInBinInternal;
694
+ reserveB =
695
+ delta.excess > 0n
696
+ ? 0n
697
+ : MaverickBasicMath.clip(reserveB, delta.deltaOutErc);
698
+ } else {
699
+ reserveA =
700
+ delta.excess > 0n
701
+ ? 0n
702
+ : MaverickBasicMath.clip(reserveA, delta.deltaOutErc);
703
+ reserveB = reserveB + delta.deltaInBinInternal;
704
+ }
705
+
706
+ tickState.reserveA = reserveA;
707
+ tickState.reserveB = reserveB;
708
+ }
709
+ }