@cetusprotocol/sui-clmm-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 (64) hide show
  1. package/.turbo/turbo-build.log +11100 -0
  2. package/README.md +108 -0
  3. package/dist/index.d.mts +2251 -0
  4. package/dist/index.d.ts +2251 -0
  5. package/dist/index.js +13 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/index.mjs +13 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/docs/add_liquidity.md +145 -0
  10. package/docs/close_position.md +57 -0
  11. package/docs/collect_fees.md +37 -0
  12. package/docs/create_clmm_pool.md +228 -0
  13. package/docs/error_code.md +69 -0
  14. package/docs/get_clmm_pools.md +92 -0
  15. package/docs/get_positions.md +70 -0
  16. package/docs/get_reward.md +53 -0
  17. package/docs/get_ticks.md +39 -0
  18. package/docs/migrate_to_version_6.0.md +143 -0
  19. package/docs/open_position.md +224 -0
  20. package/docs/partner_swap.md +60 -0
  21. package/docs/pre_swap.md +136 -0
  22. package/docs/remove_liquidity.md +124 -0
  23. package/docs/swap.md +153 -0
  24. package/docs/utils.md +85 -0
  25. package/package.json +37 -0
  26. package/src/config/index.ts +2 -0
  27. package/src/config/mainnet.ts +41 -0
  28. package/src/config/testnet.ts +40 -0
  29. package/src/errors/errors.ts +93 -0
  30. package/src/errors/index.ts +1 -0
  31. package/src/index.ts +10 -0
  32. package/src/math/apr.ts +167 -0
  33. package/src/math/index.ts +1 -0
  34. package/src/modules/configModule.ts +540 -0
  35. package/src/modules/index.ts +5 -0
  36. package/src/modules/poolModule.ts +1066 -0
  37. package/src/modules/positionModule.ts +932 -0
  38. package/src/modules/rewarderModule.ts +430 -0
  39. package/src/modules/swapModule.ts +389 -0
  40. package/src/sdk.ts +131 -0
  41. package/src/types/clmm_type.ts +1002 -0
  42. package/src/types/clmmpool.ts +366 -0
  43. package/src/types/config_type.ts +241 -0
  44. package/src/types/index.ts +8 -0
  45. package/src/types/sui.ts +124 -0
  46. package/src/types/token_type.ts +189 -0
  47. package/src/utils/common.ts +426 -0
  48. package/src/utils/index.ts +3 -0
  49. package/src/utils/positionUtils.ts +434 -0
  50. package/src/utils/swapUtils.ts +499 -0
  51. package/tests/add_liquidity.test.ts +121 -0
  52. package/tests/add_liquidity_fix_token.test.ts +182 -0
  53. package/tests/apr.test.ts +71 -0
  54. package/tests/cetus_config.test.ts +26 -0
  55. package/tests/collect_fees.test.ts +11 -0
  56. package/tests/pool.test.ts +267 -0
  57. package/tests/position.test.ts +145 -0
  58. package/tests/remove_liquidity.test.ts +119 -0
  59. package/tests/rewarder.test.ts +60 -0
  60. package/tests/sdk_config.test.ts +49 -0
  61. package/tests/swap.test.ts +254 -0
  62. package/tests/tsconfig.json +26 -0
  63. package/tsconfig.json +5 -0
  64. package/tsup.config.ts +10 -0
@@ -0,0 +1,366 @@
1
+ import BN from 'bn.js'
2
+ import {
3
+ asUintN,
4
+ CoinPairType,
5
+ FEE_RATE_DENOMINATOR,
6
+ getDeltaDownFromOutput,
7
+ getDeltaUpFromInput,
8
+ getNextSqrtPriceFromInput,
9
+ getNextSqrtPriceFromOutput,
10
+ MathUtil,
11
+ ZERO,
12
+ } from '@cetusprotocol/common-sdk'
13
+ import Decimal from 'decimal.js'
14
+ import { SwapUtils } from '../utils/swapUtils'
15
+ import { Pool } from './clmm_type'
16
+
17
+ export type BasePath = {
18
+ direction: boolean
19
+ label: string
20
+ pool_address: string
21
+ from_coin: string
22
+ to_coin: string
23
+ fee_rate: number
24
+ output_amount: number
25
+ input_amount: number
26
+ current_sqrt_price: BN
27
+ from_decimal: number
28
+ to_decimal: number
29
+ current_price: Decimal
30
+ }
31
+
32
+ export type SplitPath = {
33
+ percent: number
34
+ input_amount: number
35
+ output_amount: number
36
+ path_index: number
37
+ last_quote_output: number
38
+ base_paths: BasePath[]
39
+ }
40
+ /**
41
+ * Represents tick data for a liquidity pool.
42
+ */
43
+ export type TickData = {
44
+ /**
45
+ * The object identifier of the tick data.
46
+ */
47
+ object_id: string
48
+
49
+ /**
50
+ * The index of the tick.
51
+ */
52
+ index: number
53
+
54
+ /**
55
+ * The square root price value for the tick.
56
+ */
57
+ sqrt_price: BN
58
+
59
+ /**
60
+ * The net liquidity value for the tick.
61
+ */
62
+ liquidity_net: BN
63
+
64
+ /**
65
+ * The gross liquidity value for the tick.
66
+ */
67
+ liquidity_gross: BN
68
+
69
+ /**
70
+ * The fee growth outside coin A for the tick.
71
+ */
72
+ fee_growth_outside_a: BN
73
+
74
+ /**
75
+ * The fee growth outside coin B for the tick.
76
+ */
77
+ fee_growth_outside_b: BN
78
+
79
+ /**
80
+ * An array of rewarders' growth outside values for the tick.
81
+ */
82
+ rewarders_growth_outside: BN[]
83
+ }
84
+
85
+ /**
86
+ * Represents a tick for a liquidity pool.
87
+ */
88
+ export type Tick = {
89
+ /**
90
+ * The index of the tick.
91
+ */
92
+ index: Bits
93
+
94
+ /**
95
+ * The square root price value for the tick (string representation).
96
+ */
97
+ sqrt_price: string
98
+
99
+ /**
100
+ * The net liquidity value for the tick (Bits format).
101
+ */
102
+ liquidity_net: Bits
103
+
104
+ /**
105
+ * The gross liquidity value for the tick (string representation).
106
+ */
107
+ liquidity_gross: string
108
+
109
+ /**
110
+ * The fee growth outside coin A for the tick (string representation).
111
+ */
112
+ fee_growth_outside_a: string
113
+
114
+ /**
115
+ * The fee growth outside coin B for the tick (string representation).
116
+ */
117
+ fee_growth_outside_b: string
118
+
119
+ /**
120
+ * An array of rewarders' growth outside values for the tick (array of string representations).
121
+ */
122
+ rewarders_growth_outside: string[3]
123
+ }
124
+
125
+ export type SwapResult = {
126
+ amount_in: BN
127
+ amount_out: BN
128
+ fee_amount: BN
129
+ ref_amount: BN
130
+ next_sqrt_price: BN
131
+ cross_tick_num: number
132
+ }
133
+
134
+ export type SwapStepResult = {
135
+ amount_in: BN
136
+ amount_out: BN
137
+ next_sqrt_price: BN
138
+ fee_amount: BN
139
+ }
140
+
141
+ /**
142
+ * Represents bits information.
143
+ */
144
+ export type Bits = {
145
+ bits: string
146
+ }
147
+
148
+ /**
149
+ * Creates a Bits object from an index.
150
+ * @param {number | string} index - The index value.
151
+ * @returns {Bits} The created Bits object.
152
+ */
153
+ export function newBits(index: number | string): Bits {
154
+ const index_BN = new BN(index)
155
+ if (index_BN.lt(ZERO)) {
156
+ return {
157
+ bits: index_BN
158
+ .neg()
159
+ .xor(new BN(2).pow(new BN(64)).sub(new BN(1)))
160
+ .add(new BN(1))
161
+ .toString(),
162
+ }
163
+ }
164
+ return {
165
+ bits: index_BN.toString(),
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Represents data for a liquidity mining pool.
171
+ */
172
+ export type ClmmpoolData = {
173
+ current_sqrt_price: BN
174
+ current_tick_index: number
175
+ fee_growth_global_a: BN
176
+ fee_growth_global_b: BN
177
+ fee_protocol_coin_a: BN
178
+ fee_protocol_coin_b: BN
179
+ fee_rate: BN
180
+ liquidity: BN
181
+ tick_indexes: number[]
182
+ tick_spacing: number
183
+ ticks: Array<TickData>
184
+ collection_name: string
185
+ } & CoinPairType
186
+
187
+ /**
188
+ * Transforms a Pool object into ClmmpoolData format.
189
+ * @param {Pool} pool - The liquidity pool object to transform.
190
+ * @returns {ClmmpoolData} The transformed ClmmpoolData object.
191
+ */
192
+ export function transClmmpoolDataWithoutTicks(pool: Pool): ClmmpoolData {
193
+ const poolData: ClmmpoolData = {
194
+ coin_type_a: pool.coin_type_a, // string
195
+ coin_type_b: pool.coin_type_b, // string
196
+ current_sqrt_price: new BN(pool.current_sqrt_price), // BN
197
+ current_tick_index: pool.current_tick_index, // number
198
+ fee_growth_global_a: new BN(pool.fee_growth_global_a), // BN
199
+ fee_growth_global_b: new BN(pool.fee_growth_global_b), // BN
200
+ fee_protocol_coin_a: new BN(pool.fee_protocol_coin_a), // BN
201
+ fee_protocol_coin_b: new BN(pool.fee_protocol_coin_b), // BN
202
+ fee_rate: new BN(pool.fee_rate), // number
203
+ liquidity: new BN(pool.liquidity), // BN
204
+ tick_indexes: [], // number[]
205
+ tick_spacing: Number(pool.tick_spacing), // number
206
+ ticks: [], // Array<TickData>
207
+ collection_name: '',
208
+ }
209
+ return poolData
210
+ }
211
+
212
+ /**
213
+ * Simulate per step of swap on every tick.
214
+ *
215
+ * @param currentSqrtPrice
216
+ * @param targetSqrtPrice
217
+ * @param liquidity
218
+ * @param amount
219
+ * @param feeRate
220
+ * @param byAmountIn
221
+ * @returns
222
+ */
223
+ export function computeSwapStep(
224
+ currentSqrtPrice: BN,
225
+ targetSqrtPrice: BN,
226
+ liquidity: BN,
227
+ amount: BN,
228
+ feeRate: BN,
229
+ byAmountIn: boolean
230
+ ): SwapStepResult {
231
+ if (liquidity === ZERO) {
232
+ return {
233
+ amount_in: ZERO,
234
+ amount_out: ZERO,
235
+ next_sqrt_price: targetSqrtPrice,
236
+ fee_amount: ZERO,
237
+ }
238
+ }
239
+ const a2b = currentSqrtPrice.gte(targetSqrtPrice)
240
+ let amountIn: BN
241
+ let amountOut: BN
242
+ let nextSqrtPrice: BN
243
+ let feeAmount: BN
244
+ if (byAmountIn) {
245
+ const amountRemain = MathUtil.checkMulDivFloor(
246
+ amount,
247
+ MathUtil.checkUnsignedSub(FEE_RATE_DENOMINATOR, feeRate),
248
+ FEE_RATE_DENOMINATOR,
249
+ 64
250
+ )
251
+ const maxAmountIn = getDeltaUpFromInput(currentSqrtPrice, targetSqrtPrice, liquidity, a2b)
252
+ if (maxAmountIn.gt(amountRemain)) {
253
+ amountIn = amountRemain
254
+ feeAmount = MathUtil.checkUnsignedSub(amount, amountRemain)
255
+ nextSqrtPrice = getNextSqrtPriceFromInput(currentSqrtPrice, liquidity, amountRemain, a2b)
256
+ } else {
257
+ amountIn = maxAmountIn
258
+ feeAmount = MathUtil.checkMulDivCeil(amountIn, feeRate, FEE_RATE_DENOMINATOR.sub(feeRate), 64)
259
+ nextSqrtPrice = targetSqrtPrice
260
+ }
261
+ amountOut = getDeltaDownFromOutput(currentSqrtPrice, nextSqrtPrice, liquidity, a2b)
262
+ } else {
263
+ const maxAmountOut = getDeltaDownFromOutput(currentSqrtPrice, targetSqrtPrice, liquidity, a2b)
264
+ if (maxAmountOut.gt(amount)) {
265
+ amountOut = amount
266
+ nextSqrtPrice = getNextSqrtPriceFromOutput(currentSqrtPrice, liquidity, amount, a2b)
267
+ } else {
268
+ amountOut = maxAmountOut
269
+ nextSqrtPrice = targetSqrtPrice
270
+ }
271
+ amountIn = getDeltaUpFromInput(currentSqrtPrice, nextSqrtPrice, liquidity, a2b)
272
+ feeAmount = MathUtil.checkMulDivCeil(amountIn, feeRate, FEE_RATE_DENOMINATOR.sub(feeRate), 64)
273
+ }
274
+ return {
275
+ amount_in: amountIn,
276
+ amount_out: amountOut,
277
+ next_sqrt_price: nextSqrtPrice,
278
+ fee_amount: feeAmount,
279
+ }
280
+ }
281
+
282
+ /**
283
+ * Simulate swap by imput lots of ticks.
284
+ * @param aToB
285
+ * @param byAmountIn
286
+ * @param amount
287
+ * @param poolData
288
+ * @param swapTicks
289
+ * @returns
290
+ */
291
+ export function computeSwap(
292
+ aToB: boolean,
293
+ byAmountIn: boolean,
294
+ amount: BN,
295
+ poolData: ClmmpoolData,
296
+ swapTicks: Array<TickData>
297
+ ): SwapResult {
298
+ let remainAmount = amount
299
+ let currentLiquidity = poolData.liquidity
300
+ let { current_sqrt_price } = poolData
301
+ const swapResult: SwapResult = {
302
+ amount_in: ZERO,
303
+ amount_out: ZERO,
304
+ fee_amount: ZERO,
305
+ ref_amount: ZERO,
306
+ next_sqrt_price: ZERO,
307
+ cross_tick_num: 0,
308
+ }
309
+ let target_sqrt_price
310
+ let signed_liquidity_change
311
+ const sqrt_price_limit = SwapUtils.getDefaultSqrtPriceLimit(aToB)
312
+ for (const tick of swapTicks) {
313
+ if (aToB && poolData.current_tick_index < tick.index) {
314
+ continue
315
+ }
316
+ if (!aToB && poolData.current_tick_index >= tick.index) {
317
+ continue
318
+ }
319
+ if (tick === null) {
320
+ continue
321
+ }
322
+ if ((aToB && sqrt_price_limit.gt(tick.sqrt_price)) || (!aToB && sqrt_price_limit.lt(tick.sqrt_price))) {
323
+ target_sqrt_price = sqrt_price_limit
324
+ } else {
325
+ target_sqrt_price = tick.sqrt_price
326
+ }
327
+
328
+ const stepResult = computeSwapStep(current_sqrt_price, target_sqrt_price, currentLiquidity, remainAmount, poolData.fee_rate, byAmountIn)
329
+
330
+ if (!stepResult.amount_in.eq(ZERO)) {
331
+ remainAmount = byAmountIn
332
+ ? remainAmount.sub(stepResult.amount_in.add(stepResult.fee_amount))
333
+ : remainAmount.sub(stepResult.amount_out)
334
+ }
335
+
336
+ swapResult.amount_in = swapResult.amount_in.add(stepResult.amount_in)
337
+ swapResult.amount_out = swapResult.amount_out.add(stepResult.amount_out)
338
+ swapResult.fee_amount = swapResult.fee_amount.add(stepResult.fee_amount)
339
+ if (stepResult.next_sqrt_price.eq(tick.sqrt_price)) {
340
+ signed_liquidity_change = tick.liquidity_net.mul(new BN(-1))
341
+
342
+ if (aToB) {
343
+ if (MathUtil.is_neg(signed_liquidity_change)) {
344
+ currentLiquidity = currentLiquidity.add(new BN(asUintN(BigInt(signed_liquidity_change.toString()), 128)))
345
+ } else {
346
+ currentLiquidity = currentLiquidity.add(signed_liquidity_change)
347
+ }
348
+ } else if (MathUtil.is_neg(signed_liquidity_change)) {
349
+ currentLiquidity = currentLiquidity.sub(new BN(asUintN(BigInt(signed_liquidity_change.toString()), 128)))
350
+ } else {
351
+ currentLiquidity = currentLiquidity.sub(signed_liquidity_change)
352
+ }
353
+
354
+ current_sqrt_price = tick.sqrt_price
355
+ } else {
356
+ current_sqrt_price = stepResult.next_sqrt_price
357
+ }
358
+ swapResult.cross_tick_num += 1
359
+ if (remainAmount.eq(ZERO)) {
360
+ break
361
+ }
362
+ }
363
+ swapResult.amount_in = swapResult.amount_in.add(swapResult.fee_amount)
364
+ swapResult.next_sqrt_price = current_sqrt_price
365
+ return swapResult
366
+ }
@@ -0,0 +1,241 @@
1
+ import type { SuiObjectIdType } from '@cetusprotocol/common-sdk'
2
+
3
+ /**
4
+ * Represents configurations specific to the Cetus protocol.
5
+ */
6
+ export type CetusConfigs = {
7
+ /**
8
+ * The object identifier of the coin list.
9
+ */
10
+ coin_list_id: SuiObjectIdType
11
+
12
+ /**
13
+ * The object identifier of the coin list handle.
14
+ */
15
+ coin_list_handle: SuiObjectIdType
16
+
17
+ /**
18
+ * The object identifier of the launchpad pools.
19
+ */
20
+ launchpad_pools_id: SuiObjectIdType
21
+
22
+ /**
23
+ * The object identifier of the launchpad pools handle.
24
+ */
25
+ launchpad_pools_handle: SuiObjectIdType
26
+
27
+ /**
28
+ * The object identifier of the CLMM (Cryptocurrency Liquidity Mining Module) pools.
29
+ */
30
+ clmm_pools_id: SuiObjectIdType
31
+
32
+ /**
33
+ * The object identifier of the CLMM pools handle.
34
+ */
35
+ clmm_pools_handle: SuiObjectIdType
36
+
37
+ /**
38
+ * The object identifier of the admin cap.
39
+ */
40
+ admin_cap_id: SuiObjectIdType
41
+
42
+ /**
43
+ * The object identifier of the global configuration.
44
+ */
45
+ global_config_id: SuiObjectIdType
46
+ }
47
+
48
+ /**
49
+ * Represents configuration data for a cryptocurrency coin.
50
+ */
51
+ export type CoinConfig = {
52
+ /**
53
+ * The unique identifier of the coin.
54
+ */
55
+ id: string
56
+
57
+ /**
58
+ * The name of the coin.
59
+ */
60
+ name: string
61
+
62
+ /**
63
+ * The symbol of the coin.
64
+ */
65
+ symbol: string
66
+
67
+ /**
68
+ * The address associated with the coin.
69
+ */
70
+ address: string
71
+
72
+ /**
73
+ * The Pyth identifier of the coin.
74
+ */
75
+ pyth_id: string
76
+
77
+ /**
78
+ * The project URL related to the coin.
79
+ */
80
+ project_url: string
81
+
82
+ /**
83
+ * The URL to the logo image of the coin.
84
+ */
85
+ logo_url: string
86
+
87
+ /**
88
+ * The number of decimal places used for the coin.
89
+ */
90
+ decimals: number
91
+
92
+ /**
93
+ * Additional properties for the coin configuration.
94
+ */
95
+ } & Record<string, any>
96
+
97
+ /**
98
+ * Represents configuration data for a CLMM pool.
99
+ */
100
+ export type ClmmPoolConfig = {
101
+ /**
102
+ * The unique identifier of the CLMM pool.
103
+ */
104
+ id: string
105
+
106
+ /**
107
+ * Indicates if the CLMM pool is closed.
108
+ */
109
+ is_closed: boolean
110
+
111
+ /**
112
+ * Indicates if the rewarder for the CLMM pool is shown.
113
+ */
114
+ is_show_rewarder: boolean
115
+
116
+ /**
117
+ * The address of the CLMM pool.
118
+ */
119
+ pool_address: string
120
+
121
+ /**
122
+ * The type of the CLMM pool.
123
+ */
124
+ pool_type: string
125
+
126
+ /**
127
+ * The project URL related to the CLMM pool.
128
+ */
129
+ project_url: string
130
+
131
+ /**
132
+ * Indicates if rewarder 1 is shown for the CLMM pool.
133
+ */
134
+ show_rewarder_1: boolean
135
+
136
+ /**
137
+ * Indicates if rewarder 2 is shown for the CLMM pool.
138
+ */
139
+ show_rewarder_2: boolean
140
+
141
+ /**
142
+ * Indicates if rewarder 3 is shown for the CLMM pool.
143
+ */
144
+ show_rewarder_3: boolean
145
+
146
+ /**
147
+ * Additional properties for the CLMM pool configuration.
148
+ */
149
+ } & Record<string, any>
150
+
151
+ /**
152
+ * Represents configuration data for a launchpad pool.
153
+ */
154
+ export type LaunchpadPoolConfig = {
155
+ /**
156
+ * The object identifier of the launchpad pool.
157
+ */
158
+ id: SuiObjectIdType
159
+
160
+ /**
161
+ * Indicates if the settlement is shown for the launchpad pool.
162
+ */
163
+ show_settle: boolean
164
+
165
+ /**
166
+ * The symbol of the coin associated with the launchpad pool.
167
+ */
168
+ coin_symbol: string
169
+
170
+ /**
171
+ * The name of the coin associated with the launchpad pool.
172
+ */
173
+ coin_name: string
174
+
175
+ /**
176
+ * The icon of the coin associated with the launchpad pool.
177
+ */
178
+ coin_icon: string
179
+
180
+ /**
181
+ * An array of banner URLs for the launchpad pool.
182
+ */
183
+ banners: string[]
184
+
185
+ /**
186
+ * The introduction text for the launchpad pool.
187
+ */
188
+ introduction: string
189
+
190
+ /**
191
+ * Indicates if the launchpad pool is closed.
192
+ */
193
+ is_closed: boolean
194
+
195
+ /**
196
+ * The address of the launchpad pool.
197
+ */
198
+ pool_address: string
199
+
200
+ /**
201
+ * The project details for the launchpad pool.
202
+ */
203
+ project_details: string
204
+
205
+ /**
206
+ * The regulation details for the launchpad pool.
207
+ */
208
+ regulation: string
209
+
210
+ /**
211
+ * An array of social media links for the launchpad pool.
212
+ */
213
+ social_media: {
214
+ name: string
215
+ link: string
216
+ }[]
217
+
218
+ /**
219
+ * The terms and conditions for the launchpad pool.
220
+ */
221
+ terms: string
222
+
223
+ /**
224
+ * The tokenomics information for the launchpad pool.
225
+ */
226
+ tokenomics: string
227
+
228
+ /**
229
+ * The website URL for the launchpad pool.
230
+ */
231
+ website: string
232
+
233
+ /**
234
+ * The terms and conditions for the white list of the launchpad pool.
235
+ */
236
+ white_list_terms: string
237
+
238
+ /**
239
+ * Additional properties for the launchpad pool configuration.
240
+ */
241
+ } & Record<string, any>
@@ -0,0 +1,8 @@
1
+ import Decimal from 'decimal.js'
2
+
3
+ export type BigNumber = Decimal.Value | number | string
4
+
5
+ export * from './clmm_type'
6
+ export * from './clmmpool'
7
+ export * from './config_type'
8
+ export * from './sui'