@alcorexchange/alcor-swap-sdk 1.0.0

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 (110) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +12 -0
  3. package/LICENSE +21 -0
  4. package/build/entities/baseCurrency.js +27 -0
  5. package/build/entities/currency.js +2 -0
  6. package/build/entities/fractions/currencyAmount.js +80 -0
  7. package/build/entities/fractions/fraction.js +117 -0
  8. package/build/entities/fractions/index.js +11 -0
  9. package/build/entities/fractions/percent.js +46 -0
  10. package/build/entities/fractions/price.js +73 -0
  11. package/build/entities/index.js +26 -0
  12. package/build/entities/pool.js +248 -0
  13. package/build/entities/position.js +364 -0
  14. package/build/entities/route.js +70 -0
  15. package/build/entities/tick.js +23 -0
  16. package/build/entities/tickDataProvider.js +30 -0
  17. package/build/entities/tickListDataProvider.js +35 -0
  18. package/build/entities/token.js +53 -0
  19. package/build/entities/trade.js +464 -0
  20. package/build/index.js +19 -0
  21. package/build/internalConstants.js +54 -0
  22. package/build/utils/computeAllRoutes.js +39 -0
  23. package/build/utils/encodeSqrtRatioX64.js +21 -0
  24. package/build/utils/fullMath.js +22 -0
  25. package/build/utils/index.js +30 -0
  26. package/build/utils/isSorted.js +18 -0
  27. package/build/utils/liquidityMath.js +23 -0
  28. package/build/utils/maxLiquidityForAmounts.js +86 -0
  29. package/build/utils/mostSignificantBit.js +27 -0
  30. package/build/utils/nearestUsableTick.js +26 -0
  31. package/build/utils/positionLibrary.js +22 -0
  32. package/build/utils/priceTickConversions.js +51 -0
  33. package/build/utils/sortedInsert.js +39 -0
  34. package/build/utils/sqrt.js +33 -0
  35. package/build/utils/sqrtPriceMath.js +92 -0
  36. package/build/utils/swapMath.js +86 -0
  37. package/build/utils/tickLibrary.js +61 -0
  38. package/build/utils/tickList.js +110 -0
  39. package/build/utils/tickMath.js +122 -0
  40. package/jest.config.js +40 -0
  41. package/nodemon.json +6 -0
  42. package/package.json +51 -0
  43. package/src/entities/baseCurrency.ts +53 -0
  44. package/src/entities/currency.ts +3 -0
  45. package/src/entities/fractions/currencyAmount.ts +129 -0
  46. package/src/entities/fractions/fraction.ts +190 -0
  47. package/src/entities/fractions/index.ts +4 -0
  48. package/src/entities/fractions/percent.ts +54 -0
  49. package/src/entities/fractions/price.ts +127 -0
  50. package/src/entities/index.ts +11 -0
  51. package/src/entities/pool.ts +399 -0
  52. package/src/entities/position.ts +591 -0
  53. package/src/entities/route.ts +84 -0
  54. package/src/entities/tick.ts +48 -0
  55. package/src/entities/tickDataProvider.ts +43 -0
  56. package/src/entities/tickListDataProvider.ts +37 -0
  57. package/src/entities/token.ts +56 -0
  58. package/src/entities/trade.ts +650 -0
  59. package/src/index.ts +3 -0
  60. package/src/internalConstants.ts +58 -0
  61. package/src/utils/computeAllRoutes.ts +64 -0
  62. package/src/utils/encodeSqrtRatioX64.ts +20 -0
  63. package/src/utils/fullMath.ts +17 -0
  64. package/src/utils/index.ts +14 -0
  65. package/src/utils/isSorted.ts +17 -0
  66. package/src/utils/liquidityMath.ts +17 -0
  67. package/src/utils/maxLiquidityForAmounts.ts +127 -0
  68. package/src/utils/mostSignificantBit.ts +25 -0
  69. package/src/utils/nearestUsableTick.ts +23 -0
  70. package/src/utils/positionLibrary.ts +37 -0
  71. package/src/utils/priceTickConversions.ts +57 -0
  72. package/src/utils/sortedInsert.ts +35 -0
  73. package/src/utils/sqrt.ts +31 -0
  74. package/src/utils/sqrtPriceMath.ts +169 -0
  75. package/src/utils/swapMath.ts +175 -0
  76. package/src/utils/tickLibrary.ts +88 -0
  77. package/src/utils/tickList.ts +147 -0
  78. package/src/utils/tickMath.ts +166 -0
  79. package/test/bestTradeExactOut.test.ts +266 -0
  80. package/test/currencyAmount.test.js +92 -0
  81. package/test/currencyAmount.test.ts +114 -0
  82. package/test/encodeSqrtRatioX64.test.ts +33 -0
  83. package/test/fixtures/pools.json +276 -0
  84. package/test/fixtures/ticks.json +608 -0
  85. package/test/fraction.test.js +87 -0
  86. package/test/fraction.test.ts +176 -0
  87. package/test/isSorted.test.ts +52 -0
  88. package/test/maxLiquidityForAmounts.test copy.ts +256 -0
  89. package/test/mostSignificantBit.test.ts +32 -0
  90. package/test/nearestUsableTick.test.ts +54 -0
  91. package/test/percent.test.js +52 -0
  92. package/test/percent.test.ts +68 -0
  93. package/test/pool.test.ts +377 -0
  94. package/test/position.test.ts +579 -0
  95. package/test/positionLibrary.test.ts +31 -0
  96. package/test/price.test.js +57 -0
  97. package/test/price.test.ts +62 -0
  98. package/test/priceTickConversions.test.ts +137 -0
  99. package/test/sqrtPriceMath.test.ts +113 -0
  100. package/test/tick.test.js +22 -0
  101. package/test/tick.test.ts +28 -0
  102. package/test/tickDataProvider.test.ts +17 -0
  103. package/test/tickLibrary.test.ts +111 -0
  104. package/test/tickList.test.ts +215 -0
  105. package/test/tickListDataProvider.test.ts +64 -0
  106. package/test/tickMath.test.ts +66 -0
  107. package/test/token.test.ts +58 -0
  108. package/test/trade.test.ts +210 -0
  109. package/test2.ts +73 -0
  110. package/tsconfig.json +24 -0
@@ -0,0 +1,579 @@
1
+ import { Token } from "entities/token";
2
+ import { Percent } from "entities/fractions/percent";
3
+ import JSBI from "jsbi";
4
+ import { FeeAmount, TICK_SPACINGS } from "internalConstants";
5
+ import { encodeSqrtRatioX64 } from "utils/encodeSqrtRatioX64";
6
+ import { nearestUsableTick } from "utils/nearestUsableTick";
7
+ import { TickMath } from "utils/tickMath";
8
+ import { Pool } from "entities/pool";
9
+ import { Position } from "entities/position";
10
+
11
+ describe.skip("Position", () => {
12
+ const USDC = new Token("contracta", 6, "USDC", "USD Coin");
13
+ const DAI = new Token("contractb", 18, "DAI", "DAI Stablecoin");
14
+ const POOL_SQRT_RATIO_START = encodeSqrtRatioX64(100e6, 100e18);
15
+ const POOL_TICK_CURRENT = TickMath.getTickAtSqrtRatio(POOL_SQRT_RATIO_START);
16
+ const TICK_SPACING = TICK_SPACINGS[FeeAmount.LOW];
17
+ const DAI_USDC_POOL = new Pool({
18
+ tokenA: DAI,
19
+ tokenB: USDC,
20
+ fee: FeeAmount.LOW,
21
+ sqrtPriceX64: POOL_SQRT_RATIO_START,
22
+ liquidity: 0,
23
+ tickCurrent: POOL_TICK_CURRENT,
24
+ ticks: []
25
+ });
26
+
27
+ it("can be constructed around 0 tick", () => {
28
+ const position = new Position({
29
+ pool: DAI_USDC_POOL,
30
+ liquidity: 1,
31
+ tickLower: -10,
32
+ tickUpper: 10,
33
+ });
34
+ expect(position.liquidity).toEqual(JSBI.BigInt(1));
35
+ });
36
+
37
+ it("can use min and max ticks", () => {
38
+ const position = new Position({
39
+ pool: DAI_USDC_POOL,
40
+ liquidity: 1,
41
+ tickLower: nearestUsableTick(TickMath.MIN_TICK, TICK_SPACING),
42
+ tickUpper: nearestUsableTick(TickMath.MAX_TICK, TICK_SPACING),
43
+ });
44
+ expect(position.liquidity).toEqual(JSBI.BigInt(1));
45
+ });
46
+
47
+ it("tick lower must be less than tick upper", () => {
48
+ expect(
49
+ () =>
50
+ new Position({
51
+ pool: DAI_USDC_POOL,
52
+ liquidity: 1,
53
+ tickLower: 10,
54
+ tickUpper: -10,
55
+ })
56
+ ).toThrow("TICK_ORDER");
57
+ });
58
+
59
+ it("tick lower cannot equal tick upper", () => {
60
+ expect(
61
+ () =>
62
+ new Position({
63
+ pool: DAI_USDC_POOL,
64
+ liquidity: 1,
65
+ tickLower: -10,
66
+ tickUpper: -10,
67
+ })
68
+ ).toThrow("TICK_ORDER");
69
+ });
70
+
71
+ it("tick lower must be multiple of tick spacing", () => {
72
+ expect(
73
+ () =>
74
+ new Position({
75
+ pool: DAI_USDC_POOL,
76
+ liquidity: 1,
77
+ tickLower: -5,
78
+ tickUpper: 10,
79
+ })
80
+ ).toThrow("TICK_LOWER");
81
+ });
82
+
83
+ it("tick lower must be greater than MIN_TICK", () => {
84
+ expect(
85
+ () =>
86
+ new Position({
87
+ pool: DAI_USDC_POOL,
88
+ liquidity: 1,
89
+ tickLower:
90
+ nearestUsableTick(TickMath.MIN_TICK, TICK_SPACING) - TICK_SPACING,
91
+ tickUpper: 10,
92
+ })
93
+ ).toThrow("TICK_LOWER");
94
+ });
95
+
96
+ it("tick upper must be multiple of tick spacing", () => {
97
+ expect(
98
+ () =>
99
+ new Position({
100
+ pool: DAI_USDC_POOL,
101
+ liquidity: 1,
102
+ tickLower: -10,
103
+ tickUpper: 15,
104
+ })
105
+ ).toThrow("TICK_UPPER");
106
+ });
107
+
108
+ it("tick upper must be less than MAX_TICK", () => {
109
+ expect(
110
+ () =>
111
+ new Position({
112
+ pool: DAI_USDC_POOL,
113
+ liquidity: 1,
114
+ tickLower: -10,
115
+ tickUpper:
116
+ nearestUsableTick(TickMath.MAX_TICK, TICK_SPACING) + TICK_SPACING,
117
+ })
118
+ ).toThrow("TICK_UPPER");
119
+ });
120
+
121
+ describe("#amountA", () => {
122
+ it("is correct for price above", () => {
123
+ expect(
124
+ new Position({
125
+ pool: DAI_USDC_POOL,
126
+ liquidity: 100e12,
127
+ tickLower:
128
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
129
+ tickUpper:
130
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
131
+ TICK_SPACING * 2,
132
+ }).amountA.quotient.toString()
133
+ ).toEqual("49949961958869841");
134
+ });
135
+ it("is correct for price below", () => {
136
+ expect(
137
+ new Position({
138
+ pool: DAI_USDC_POOL,
139
+ liquidity: 100e18,
140
+ tickLower:
141
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
142
+ TICK_SPACING * 2,
143
+ tickUpper:
144
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING,
145
+ }).amountA.quotient.toString()
146
+ ).toEqual("0");
147
+ });
148
+ it("is correct for in-range position", () => {
149
+ expect(
150
+ new Position({
151
+ pool: DAI_USDC_POOL,
152
+ liquidity: 100e18,
153
+ tickLower:
154
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
155
+ TICK_SPACING * 2,
156
+ tickUpper:
157
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
158
+ TICK_SPACING * 2,
159
+ }).amountA.quotient.toString()
160
+ ).toEqual("120054069145287995769396");
161
+ });
162
+ });
163
+
164
+ describe("#amountB", () => {
165
+ it("is correct for price above", () => {
166
+ expect(
167
+ new Position({
168
+ pool: DAI_USDC_POOL,
169
+ liquidity: 100e18,
170
+ tickLower:
171
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
172
+ tickUpper:
173
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
174
+ TICK_SPACING * 2,
175
+ }).amountB.quotient.toString()
176
+ ).toEqual("0");
177
+ });
178
+ it("is correct for price below", () => {
179
+ expect(
180
+ new Position({
181
+ pool: DAI_USDC_POOL,
182
+ liquidity: 100e18,
183
+ tickLower:
184
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
185
+ TICK_SPACING * 2,
186
+ tickUpper:
187
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING,
188
+ }).amountB.quotient.toString()
189
+ ).toEqual("49970077052");
190
+ });
191
+ it("is correct for in-range position", () => {
192
+ expect(
193
+ new Position({
194
+ pool: DAI_USDC_POOL,
195
+ liquidity: 100e18,
196
+ tickLower:
197
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
198
+ TICK_SPACING * 2,
199
+ tickUpper:
200
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
201
+ TICK_SPACING * 2,
202
+ }).amountB.quotient.toString()
203
+ ).toEqual("79831926242");
204
+ });
205
+ });
206
+
207
+ describe("#mintAmountsWithSlippage", () => {
208
+ describe("0 slippage", () => {
209
+ const slippageTolerance = new Percent(0);
210
+
211
+ it("is correct for positions below", () => {
212
+ const position = new Position({
213
+ pool: DAI_USDC_POOL,
214
+ liquidity: 100e18,
215
+ tickLower:
216
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
217
+ tickUpper:
218
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
219
+ TICK_SPACING * 2,
220
+ });
221
+
222
+ const { amountA, amountB } =
223
+ position.mintAmountsWithSlippage(slippageTolerance);
224
+ expect(amountA.toString()).toEqual("49949961958869841738198");
225
+ expect(amountB.toString()).toEqual("0");
226
+ });
227
+
228
+ it("is correct for positions above", () => {
229
+ const position = new Position({
230
+ pool: DAI_USDC_POOL,
231
+ liquidity: 100e18,
232
+ tickLower:
233
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
234
+ TICK_SPACING * 2,
235
+ tickUpper:
236
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING,
237
+ });
238
+
239
+ const { amountA, amountB } =
240
+ position.mintAmountsWithSlippage(slippageTolerance);
241
+ expect(amountA.toString()).toEqual("0");
242
+ expect(amountB.toString()).toEqual("49970077053");
243
+ });
244
+
245
+ it("is correct for positions within", () => {
246
+ const position = new Position({
247
+ pool: DAI_USDC_POOL,
248
+ liquidity: 100e18,
249
+ tickLower:
250
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
251
+ TICK_SPACING * 2,
252
+ tickUpper:
253
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
254
+ TICK_SPACING * 2,
255
+ });
256
+
257
+ const { amountA, amountB } =
258
+ position.mintAmountsWithSlippage(slippageTolerance);
259
+ expect(amountA.toString()).toEqual("120054069145287995740584");
260
+ expect(amountB.toString()).toEqual("79831926243");
261
+ });
262
+ });
263
+
264
+ describe(".05% slippage", () => {
265
+ const slippageTolerance = new Percent(5, 10000);
266
+
267
+ it("is correct for positions below", () => {
268
+ const position = new Position({
269
+ pool: DAI_USDC_POOL,
270
+ liquidity: 100e18,
271
+ tickLower:
272
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
273
+ tickUpper:
274
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
275
+ TICK_SPACING * 2,
276
+ });
277
+
278
+ const { amountA, amountB } =
279
+ position.mintAmountsWithSlippage(slippageTolerance);
280
+ expect(amountA.toString()).toEqual("49949961958869841738198");
281
+ expect(amountB.toString()).toEqual("0");
282
+ });
283
+
284
+ it("is correct for positions above", () => {
285
+ const position = new Position({
286
+ pool: DAI_USDC_POOL,
287
+ liquidity: 100e18,
288
+ tickLower:
289
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
290
+ TICK_SPACING * 2,
291
+ tickUpper:
292
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING,
293
+ });
294
+
295
+ const { amountA, amountB } =
296
+ position.mintAmountsWithSlippage(slippageTolerance);
297
+ expect(amountA.toString()).toEqual("0");
298
+ expect(amountB.toString()).toEqual("49970077053");
299
+ });
300
+
301
+ it("is correct for positions within", () => {
302
+ const position = new Position({
303
+ pool: DAI_USDC_POOL,
304
+ liquidity: 100e18,
305
+ tickLower:
306
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
307
+ TICK_SPACING * 2,
308
+ tickUpper:
309
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
310
+ TICK_SPACING * 2,
311
+ });
312
+
313
+ const { amountA, amountB } =
314
+ position.mintAmountsWithSlippage(slippageTolerance);
315
+ expect(amountA.toString()).toEqual("95063440240746211432007");
316
+ expect(amountB.toString()).toEqual("54828800461");
317
+ });
318
+ });
319
+
320
+ describe("5% slippage tolerance", () => {
321
+ const slippageTolerance = new Percent(5, 100);
322
+
323
+ it("is correct for pool at min price", () => {
324
+ const position = new Position({
325
+ pool: new Pool({
326
+ tokenA: DAI,
327
+ tokenB: USDC,
328
+ fee: FeeAmount.LOW,
329
+ sqrtPriceX64: TickMath.MIN_SQRT_RATIO,
330
+ liquidity: 0,
331
+ tickCurrent: TickMath.MIN_TICK,
332
+ ticks: []
333
+ }),
334
+ liquidity: 100e18,
335
+ tickLower:
336
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
337
+ tickUpper:
338
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
339
+ TICK_SPACING * 2,
340
+ });
341
+
342
+ const { amountA, amountB } =
343
+ position.burnAmountsWithSlippage(slippageTolerance);
344
+ expect(amountA.toString()).toEqual("49949961958869841754181");
345
+ expect(amountB.toString()).toEqual("0");
346
+ });
347
+
348
+ it("is correct for pool at max price", () => {
349
+ const position = new Position({
350
+ pool: new Pool({
351
+ tokenA: DAI,
352
+ tokenB: USDC,
353
+ fee: FeeAmount.LOW,
354
+ sqrtPriceX64: JSBI.subtract(TickMath.MAX_SQRT_RATIO, JSBI.BigInt(1)),
355
+ liquidity: 0,
356
+ tickCurrent: TickMath.MAX_TICK - 1,
357
+ ticks: []
358
+ }),
359
+ liquidity: 100e18,
360
+ tickLower:
361
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
362
+ tickUpper:
363
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
364
+ TICK_SPACING * 2,
365
+ });
366
+
367
+ const { amountA, amountB } =
368
+ position.burnAmountsWithSlippage(slippageTolerance);
369
+ expect(amountA.toString()).toEqual("0");
370
+ expect(amountB.toString()).toEqual("50045084659");
371
+ });
372
+ });
373
+ });
374
+
375
+ describe("#burnAmountsWithSlippage", () => {
376
+ describe("0 slippage", () => {
377
+ const slippageTolerance = new Percent(0);
378
+
379
+ it("is correct for positions below", () => {
380
+ const position = new Position({
381
+ pool: DAI_USDC_POOL,
382
+ liquidity: 100e18,
383
+ tickLower:
384
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
385
+ tickUpper:
386
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
387
+ TICK_SPACING * 2,
388
+ });
389
+
390
+ const { amountA, amountB } =
391
+ position.burnAmountsWithSlippage(slippageTolerance);
392
+ expect(amountA.toString()).toEqual("49949961958869841754181");
393
+ expect(amountB.toString()).toEqual("0");
394
+ });
395
+
396
+ it("is correct for positions above", () => {
397
+ const position = new Position({
398
+ pool: DAI_USDC_POOL,
399
+ liquidity: 100e18,
400
+ tickLower:
401
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
402
+ TICK_SPACING * 2,
403
+ tickUpper:
404
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING,
405
+ });
406
+
407
+ const { amountA, amountB } =
408
+ position.burnAmountsWithSlippage(slippageTolerance);
409
+ expect(amountA.toString()).toEqual("0");
410
+ expect(amountB.toString()).toEqual("49970077052");
411
+ });
412
+
413
+ it("is correct for positions within", () => {
414
+ const position = new Position({
415
+ pool: DAI_USDC_POOL,
416
+ liquidity: 100e18,
417
+ tickLower:
418
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
419
+ TICK_SPACING * 2,
420
+ tickUpper:
421
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
422
+ TICK_SPACING * 2,
423
+ });
424
+
425
+ const { amountA, amountB } =
426
+ position.burnAmountsWithSlippage(slippageTolerance);
427
+ expect(amountA.toString()).toEqual("120054069145287995769396");
428
+ expect(amountB.toString()).toEqual("79831926242");
429
+ });
430
+ });
431
+
432
+ describe(".05% slippage", () => {
433
+ const slippageTolerance = new Percent(5, 10000);
434
+
435
+ it("is correct for positions below", () => {
436
+ const position = new Position({
437
+ pool: DAI_USDC_POOL,
438
+ liquidity: 100e18,
439
+ tickLower:
440
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
441
+ tickUpper:
442
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
443
+ TICK_SPACING * 2,
444
+ });
445
+ const { amountA, amountB } =
446
+ position.burnAmountsWithSlippage(slippageTolerance);
447
+ expect(amountA.toString()).toEqual("49949961958869841754181");
448
+ expect(amountB.toString()).toEqual("0");
449
+ });
450
+
451
+ it("is correct for positions above", () => {
452
+ const position = new Position({
453
+ pool: DAI_USDC_POOL,
454
+ liquidity: 100e18,
455
+ tickLower:
456
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
457
+ TICK_SPACING * 2,
458
+ tickUpper:
459
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING,
460
+ });
461
+ const { amountA, amountB } =
462
+ position.burnAmountsWithSlippage(slippageTolerance);
463
+ expect(amountA.toString()).toEqual("0");
464
+ expect(amountB.toString()).toEqual("49970077052");
465
+ });
466
+
467
+ it("is correct for positions within", () => {
468
+ const position = new Position({
469
+ pool: DAI_USDC_POOL,
470
+ liquidity: 100e18,
471
+ tickLower:
472
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) -
473
+ TICK_SPACING * 2,
474
+ tickUpper:
475
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
476
+ TICK_SPACING * 2,
477
+ });
478
+ const { amountA, amountB } =
479
+ position.burnAmountsWithSlippage(slippageTolerance);
480
+ expect(amountA.toString()).toEqual("95063440240746211454822");
481
+ expect(amountB.toString()).toEqual("54828800460");
482
+ });
483
+ });
484
+
485
+ describe("5% slippage tolerance", () => {
486
+ const slippageTolerance = new Percent(5, 100);
487
+
488
+ it("is correct for pool at min price", () => {
489
+ const position = new Position({
490
+ pool: new Pool({
491
+ tokenA: DAI,
492
+ tokenB: USDC,
493
+ fee: FeeAmount.LOW,
494
+ sqrtPriceX64: TickMath.MIN_SQRT_RATIO,
495
+ liquidity: 0,
496
+ tickCurrent: TickMath.MIN_TICK,
497
+ ticks: []
498
+ }),
499
+ liquidity: 100e18,
500
+ tickLower:
501
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
502
+ tickUpper:
503
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
504
+ TICK_SPACING * 2,
505
+ });
506
+
507
+ const { amountA, amountB } =
508
+ position.mintAmountsWithSlippage(slippageTolerance);
509
+ expect(amountA.toString()).toEqual("49949961958869841738198");
510
+ expect(amountB.toString()).toEqual("0");
511
+ });
512
+
513
+ it("is correct for pool at max price", () => {
514
+ const position = new Position({
515
+ pool: new Pool({
516
+ tokenA: DAI,
517
+ tokenB: USDC,
518
+ fee: FeeAmount.LOW,
519
+ sqrtPriceX64: JSBI.subtract(TickMath.MAX_SQRT_RATIO, JSBI.BigInt(1)),
520
+ liquidity: 0,
521
+ tickCurrent: TickMath.MAX_TICK - 1,
522
+ ticks: []
523
+ }),
524
+ liquidity: 100e18,
525
+ tickLower:
526
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
527
+ tickUpper:
528
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) +
529
+ TICK_SPACING * 2,
530
+ });
531
+
532
+ const { amountA, amountB } =
533
+ position.mintAmountsWithSlippage(slippageTolerance);
534
+ expect(amountA.toString()).toEqual("0");
535
+ expect(amountB.toString()).toEqual("50045084660");
536
+ });
537
+ });
538
+ });
539
+
540
+ describe("#mintAmounts", () => {
541
+ it("is correct for price above", () => {
542
+ const { amountA, amountB } = new Position({
543
+ pool: DAI_USDC_POOL,
544
+ liquidity: 100e18,
545
+ tickLower:
546
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING,
547
+ tickUpper:
548
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2,
549
+ }).mintAmounts;
550
+ expect(amountA.toString()).toEqual("49949961958869841754182");
551
+ expect(amountB.toString()).toEqual("0");
552
+ });
553
+ it("is correct for price below", () => {
554
+ const { amountA, amountB } = new Position({
555
+ pool: DAI_USDC_POOL,
556
+ liquidity: 100e18,
557
+ tickLower:
558
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2,
559
+ tickUpper:
560
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING,
561
+ }).mintAmounts;
562
+ expect(amountA.toString()).toEqual("0");
563
+ expect(amountB.toString()).toEqual("49970077053");
564
+ });
565
+ it("is correct for in-range position", () => {
566
+ const { amountA, amountB } = new Position({
567
+ pool: DAI_USDC_POOL,
568
+ liquidity: 100e18,
569
+ tickLower:
570
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2,
571
+ tickUpper:
572
+ nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2,
573
+ }).mintAmounts;
574
+ // note these are rounded up
575
+ expect(amountA.toString()).toEqual("120054069145287995769397");
576
+ expect(amountB.toString()).toEqual("79831926243");
577
+ });
578
+ });
579
+ });
@@ -0,0 +1,31 @@
1
+ import JSBI from "jsbi";
2
+ import { PositionLibrary } from "utils/positionLibrary";
3
+ import { ZERO } from "internalConstants";
4
+
5
+ describe("PositionLibrary", () => {
6
+ describe("#getTokensOwed", () => {
7
+ it("0", () => {
8
+ const [tokensOwed0, tokensOwed1] = PositionLibrary.getTokensOwed(
9
+ ZERO,
10
+ ZERO,
11
+ ZERO,
12
+ ZERO,
13
+ ZERO
14
+ );
15
+ expect(tokensOwed0).toEqual(ZERO);
16
+ expect(tokensOwed1).toEqual(ZERO);
17
+ });
18
+
19
+ it("non-0", () => {
20
+ const [tokensOwed0, tokensOwed1] = PositionLibrary.getTokensOwed(
21
+ ZERO,
22
+ ZERO,
23
+ JSBI.BigInt(1),
24
+ JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(64)),
25
+ JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(64))
26
+ );
27
+ expect(tokensOwed0).toEqual(JSBI.BigInt(1));
28
+ expect(tokensOwed1).toEqual(JSBI.BigInt(1));
29
+ });
30
+ });
31
+ });
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const token_1 = require("entities/token");
4
+ const currencyAmount_1 = require("../src/entities/fractions/currencyAmount");
5
+ const price_1 = require("../src/entities/fractions/price");
6
+ describe("Price", () => {
7
+ const CONTRACT_ZERO = "contracta";
8
+ const CONTRACT_ONE = "contractb";
9
+ const t0 = new token_1.Token(CONTRACT_ZERO, 8, "ABC");
10
+ const t0_6 = new token_1.Token(CONTRACT_ZERO, 6, "BCD");
11
+ const t1 = new token_1.Token(CONTRACT_ONE, 8, "EFG");
12
+ describe("#constructor", () => {
13
+ it("array format works", () => {
14
+ const price = new price_1.Price(t0, t1, 1, 54321);
15
+ expect(price.toSignificant(5)).toEqual("54321");
16
+ expect(price.baseCurrency.equals(t0));
17
+ expect(price.quoteCurrency.equals(t1));
18
+ });
19
+ it("object format works", () => {
20
+ const price = new price_1.Price({
21
+ baseAmount: currencyAmount_1.CurrencyAmount.fromRawAmount(t0, 1),
22
+ quoteAmount: currencyAmount_1.CurrencyAmount.fromRawAmount(t1, 54321),
23
+ });
24
+ expect(price.toSignificant(5)).toEqual("54321");
25
+ expect(price.baseCurrency.equals(t0));
26
+ expect(price.quoteCurrency.equals(t1));
27
+ });
28
+ });
29
+ describe("#quote", () => {
30
+ it("returns correct value", () => {
31
+ const price = new price_1.Price(t0, t1, 1, 5);
32
+ expect(price.quote(currencyAmount_1.CurrencyAmount.fromRawAmount(t0, 10))).toEqual(currencyAmount_1.CurrencyAmount.fromRawAmount(t1, 50));
33
+ });
34
+ });
35
+ describe("#toSignificant", () => {
36
+ it("no decimals", () => {
37
+ const p = new price_1.Price(t0, t1, 123, 456);
38
+ expect(p.toSignificant(4)).toEqual("3.707");
39
+ });
40
+ it("no decimals flip ratio", () => {
41
+ const p = new price_1.Price(t0, t1, 456, 123);
42
+ expect(p.toSignificant(4)).toEqual("0.2697");
43
+ });
44
+ it("with decimal difference", () => {
45
+ const p = new price_1.Price(t0_6, t1, 123, 456);
46
+ expect(p.toSignificant(4)).toEqual("0.03707");
47
+ });
48
+ it("with decimal difference flipped", () => {
49
+ const p = new price_1.Price(t0_6, t1, 456, 123);
50
+ expect(p.toSignificant(4)).toEqual("0.002697");
51
+ });
52
+ it("with decimal difference flipped base quote flipped", () => {
53
+ const p = new price_1.Price(t1, t0_6, 456, 123);
54
+ expect(p.toSignificant(4)).toEqual("26.97");
55
+ });
56
+ });
57
+ });