@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,389 @@
1
+ import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions'
2
+ import { normalizeSuiAddress } from '@mysten/sui/utils'
3
+ import BN from 'bn.js'
4
+ import { d, DETAILS_KEYS, extractStructTagFromType, IModule, TickMath, U64_MAX, ZERO } from '@cetusprotocol/common-sdk'
5
+ import Decimal from 'decimal.js'
6
+ import { ConfigErrorCode, handleMessageError, SwapErrorCode } from '../errors/errors'
7
+ import { CetusClmmSDK } from '../sdk'
8
+ import {
9
+ CalculateRatesParams,
10
+ CalculateRatesResult,
11
+ PreSwapParams,
12
+ PreSwapWithMultiPoolParams,
13
+ SwapGasEstimateArg,
14
+ SwapParams,
15
+ TransPreSwapWithMultiPoolParams,
16
+ } from '../types/clmm_type'
17
+ import { computeSwap, SplitPath, transClmmpoolDataWithoutTicks } from '../types/clmmpool'
18
+ import { ClmmFetcherModule } from '../types/sui'
19
+ import { findAdjustCoin } from '../utils/positionUtils'
20
+ import { SwapUtils } from '../utils/swapUtils'
21
+ export const AMM_SWAP_MODULE = 'amm_swap'
22
+ export const POOL_STRUCT = 'Pool'
23
+
24
+ /**
25
+ * Helper class to help interact with clmm pool swap with a swap router interface.
26
+ */
27
+ export class SwapModule implements IModule<CetusClmmSDK> {
28
+ protected _sdk: CetusClmmSDK
29
+
30
+ constructor(sdk: CetusClmmSDK) {
31
+ this._sdk = sdk
32
+ }
33
+
34
+ get sdk() {
35
+ return this._sdk
36
+ }
37
+
38
+ calculateSwapFee(paths: SplitPath[]) {
39
+ let fee = d(0)
40
+ paths.forEach((item) => {
41
+ const pathCount = item.base_paths.length
42
+ if (pathCount > 0) {
43
+ const path = item.base_paths[0]
44
+ const fee_rate = path.label === 'Cetus' ? new Decimal(path.fee_rate).div(10 ** 6) : new Decimal(path.fee_rate).div(10 ** 9)
45
+ const feeAmount = d(path.input_amount)
46
+ .div(10 ** path.from_decimal)
47
+ .mul(fee_rate)
48
+ fee = fee.add(feeAmount)
49
+ if (pathCount > 1) {
50
+ const path2 = item.base_paths[1]
51
+ const price1 = path.direction ? path.current_price : new Decimal(1).div(path.current_price)
52
+ const price2 = path2.direction ? path2.current_price : new Decimal(1).div(path2.current_price)
53
+ const feeRate2 = path2.label === 'Cetus' ? new Decimal(path2.fee_rate).div(10 ** 6) : new Decimal(path2.fee_rate).div(10 ** 9)
54
+
55
+ const feeAmount2 = d(path2.output_amount)
56
+ .div(10 ** path2.to_decimal)
57
+ .mul(feeRate2)
58
+ const fee2 = feeAmount2.div(price1.mul(price2))
59
+ fee = fee.add(fee2)
60
+ }
61
+ }
62
+ })
63
+
64
+ return fee.toString()
65
+ }
66
+
67
+ calculateSwapPriceImpact(paths: SplitPath[]) {
68
+ let impactValue = d(0)
69
+ paths.forEach((item) => {
70
+ const pathCount = item.base_paths.length
71
+ if (pathCount === 1) {
72
+ const path = item.base_paths[0]
73
+ const output_amount = d(path.output_amount).div(10 ** path.to_decimal)
74
+ const input_amount = d(path.input_amount).div(10 ** path.from_decimal)
75
+ const rate = output_amount.div(input_amount)
76
+ const cprice = path.direction ? new Decimal(path.current_price) : new Decimal(1).div(path.current_price)
77
+ impactValue = impactValue.add(this.calculateSingleImpact(rate, cprice))
78
+ }
79
+ if (pathCount === 2) {
80
+ const path = item.base_paths[0]
81
+ const path2 = item.base_paths[1]
82
+ const cprice1 = path.direction ? new Decimal(path.current_price) : new Decimal(1).div(path.current_price)
83
+ const cprice2 = path2.direction ? new Decimal(path2.current_price) : new Decimal(1).div(path2.current_price)
84
+ const cprice = cprice1.mul(cprice2)
85
+ const output_amount = new Decimal(path2.output_amount).div(10 ** path2.to_decimal)
86
+ const input_amount = new Decimal(path.input_amount).div(10 ** path.from_decimal)
87
+ const rate = output_amount.div(input_amount)
88
+ impactValue = impactValue.add(this.calculateSingleImpact(rate, cprice))
89
+ }
90
+ })
91
+
92
+ return impactValue.toString()
93
+ }
94
+
95
+ private calculateSingleImpact = (rate: Decimal, c_price: Decimal) => {
96
+ // ((cprice - rate)/cprice)*100
97
+ return c_price.minus(rate).div(c_price).mul(100)
98
+ }
99
+
100
+ /**
101
+ * Performs a pre-swap with multiple pools.
102
+ *
103
+ * @param {PreSwapWithMultiPoolParams} params The parameters for the pre-swap.
104
+ * @returns {Promise<SwapWithMultiPoolData>} A promise that resolves to the swap data.
105
+ */
106
+ async preSwapWithMultiPool(params: PreSwapWithMultiPoolParams) {
107
+ const { integrate } = this.sdk.sdkOptions
108
+ const tx = new Transaction()
109
+
110
+ const typeArguments = [params.coin_type_a, params.coin_type_b]
111
+ for (let i = 0; i < params.pool_ids.length; i += 1) {
112
+ const args = [tx.object(params.pool_ids[i]), tx.pure.bool(params.a2b), tx.pure.bool(params.by_amount_in), tx.pure.u64(params.amount)]
113
+ tx.moveCall({
114
+ target: `${integrate.published_at}::${ClmmFetcherModule}::calculate_swap_result`,
115
+ arguments: args,
116
+ typeArguments,
117
+ })
118
+ }
119
+
120
+ const simulateRes = await this.sdk.FullClient.devInspectTransactionBlock({
121
+ transactionBlock: tx,
122
+ sender: normalizeSuiAddress('0x0'),
123
+ })
124
+ if (simulateRes.error != null) {
125
+ handleMessageError(
126
+ ConfigErrorCode.InvalidConfig,
127
+ `pre swap with multi pools error code: ${simulateRes.error ?? 'unknown error'}, please check config and params`,
128
+ {
129
+ [DETAILS_KEYS.METHOD_NAME]: 'preSwapWithMultiPool',
130
+ [DETAILS_KEYS.REQUEST_PARAMS]: {
131
+ params,
132
+ },
133
+ }
134
+ )
135
+ }
136
+
137
+ const valueData: any = simulateRes.events?.filter((item: any) => {
138
+ return extractStructTagFromType(item.type).name === `CalculatedSwapResultEvent`
139
+ })
140
+ if (valueData.length === 0) {
141
+ return null
142
+ }
143
+
144
+ if (valueData.length !== params.pool_ids.length) {
145
+ handleMessageError(SwapErrorCode.ParamsLengthNotEqual, 'valueData.length !== params.pools.length', {
146
+ [DETAILS_KEYS.METHOD_NAME]: 'preSwapWithMultiPool',
147
+ [DETAILS_KEYS.REQUEST_PARAMS]: {
148
+ params,
149
+ },
150
+ })
151
+ }
152
+ let tempMaxAmount = params.by_amount_in ? ZERO : U64_MAX
153
+ let tempIndex = 0
154
+ for (let i = 0; i < valueData.length; i += 1) {
155
+ if (valueData[i].parsedJson.data.is_exceed) {
156
+ continue
157
+ }
158
+
159
+ if (params.by_amount_in) {
160
+ const amount = new BN(valueData[i].parsedJson.data.amount_out)
161
+ if (amount.gt(tempMaxAmount)) {
162
+ tempIndex = i
163
+ tempMaxAmount = amount
164
+ }
165
+ } else {
166
+ const amount = new BN(valueData[i].parsedJson.data.amount_out)
167
+ if (amount.lt(tempMaxAmount)) {
168
+ tempIndex = i
169
+ tempMaxAmount = amount
170
+ }
171
+ }
172
+ }
173
+
174
+ return this.transformSwapWithMultiPoolData(
175
+ {
176
+ pool_address: params.pool_ids[tempIndex],
177
+ a2b: params.a2b,
178
+ by_amount_in: params.by_amount_in,
179
+ amount: params.amount,
180
+ coin_type_a: params.coin_type_a,
181
+ coin_type_b: params.coin_type_b,
182
+ },
183
+ valueData[tempIndex].parsedJson
184
+ )
185
+ }
186
+
187
+ /**
188
+ * Performs a pre-swap.
189
+ *
190
+ * @param {PreSwapParams} params The parameters for the pre-swap.
191
+ * @returns {Promise<PreSwapParams>} A promise that resolves to the swap data.
192
+ */
193
+ async preSwap(params: PreSwapParams) {
194
+ const { integrate } = this.sdk.sdkOptions
195
+
196
+ const tx = new Transaction()
197
+
198
+ const typeArguments = [params.coin_type_a, params.coin_type_b]
199
+ const args = [tx.object(params.pool.id), tx.pure.bool(params.a2b), tx.pure.bool(params.by_amount_in), tx.pure.u64(params.amount)]
200
+
201
+ tx.moveCall({
202
+ target: `${integrate.published_at}::${ClmmFetcherModule}::calculate_swap_result`,
203
+ arguments: args,
204
+ typeArguments,
205
+ })
206
+
207
+ const simulateRes = await this.sdk.FullClient.devInspectTransactionBlock({
208
+ transactionBlock: tx,
209
+ sender: normalizeSuiAddress('0x0'),
210
+ })
211
+ if (simulateRes.error != null) {
212
+ return handleMessageError(
213
+ ConfigErrorCode.InvalidConfig,
214
+ `preSwap error code: ${simulateRes.error ?? 'unknown error'}, please check config and params`,
215
+ {
216
+ [DETAILS_KEYS.METHOD_NAME]: 'preSwap',
217
+ [DETAILS_KEYS.REQUEST_PARAMS]: {
218
+ params,
219
+ },
220
+ }
221
+ )
222
+ }
223
+
224
+ const valueData: any = simulateRes.events?.filter((item: any) => {
225
+ return extractStructTagFromType(item.type).name === `CalculatedSwapResultEvent`
226
+ })
227
+ if (valueData.length === 0) {
228
+ return handleMessageError(
229
+ ConfigErrorCode.InvalidConfig,
230
+ `preSwap error code: ${simulateRes.error ?? 'unknown error'}, please check config and params`,
231
+ {
232
+ [DETAILS_KEYS.METHOD_NAME]: 'preSwap',
233
+ [DETAILS_KEYS.REQUEST_PARAMS]: {
234
+ params,
235
+ },
236
+ }
237
+ )
238
+ }
239
+ return this.transformSwapData(params, valueData[0].parsedJson.data)
240
+ }
241
+
242
+ private transformSwapData(params: PreSwapParams, data: any) {
243
+ const estimatedAmountIn = data.amount_in && data.fee_amount ? new BN(data.amount_in).add(new BN(data.fee_amount)).toString() : ''
244
+ return {
245
+ pool_address: params.pool.id,
246
+ current_sqrt_price: params.current_sqrt_price,
247
+ estimated_amount_in: estimatedAmountIn,
248
+ estimated_amount_out: data.amount_out,
249
+ estimated_end_sqrt_price: data.after_sqrt_price,
250
+ estimated_fee_amount: data.fee_amount,
251
+ is_exceed: data.is_exceed,
252
+ amount: params.amount,
253
+ a2b: params.a2b,
254
+ by_amount_in: params.by_amount_in,
255
+ }
256
+ }
257
+
258
+ private transformSwapWithMultiPoolData(params: TransPreSwapWithMultiPoolParams, json_data: any) {
259
+ const { data } = json_data
260
+
261
+ console.log('json data. ', data)
262
+
263
+ const estimatedAmountIn = data.amount_in && data.fee_amount ? new BN(data.amount_in).add(new BN(data.fee_amount)).toString() : ''
264
+ return {
265
+ pool_address: params.pool_address,
266
+ estimated_amount_in: estimatedAmountIn,
267
+ estimated_amount_out: data.amount_out,
268
+ estimated_end_sqrt_price: data.after_sqrt_price,
269
+ estimated_start_sqrt_price: data.step_results[0].current_sqrt_price,
270
+ estimated_fee_amount: data.fee_amount,
271
+ is_exceed: data.is_exceed,
272
+ amount: params.amount,
273
+ a2b: params.a2b,
274
+ by_amount_in: params.by_amount_in,
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Calculates the rates for a swap.
280
+ * @param {CalculateRatesParams} params The parameters for the calculation.
281
+ * @returns {CalculateRatesResult} The results of the calculation.
282
+ */
283
+ calculateRates(params: CalculateRatesParams): CalculateRatesResult {
284
+ const { current_pool } = params
285
+ const poolData = transClmmpoolDataWithoutTicks(current_pool)
286
+
287
+ let ticks
288
+ if (params.a2b) {
289
+ ticks = params.swap_ticks.sort((a, b) => {
290
+ return b.index - a.index
291
+ })
292
+ } else {
293
+ ticks = params.swap_ticks.sort((a, b) => {
294
+ return a.index - b.index
295
+ })
296
+ }
297
+
298
+ const swapResult = computeSwap(params.a2b, params.by_amount_in, params.amount, poolData, ticks)
299
+
300
+ let isExceed = false
301
+ if (params.by_amount_in) {
302
+ isExceed = swapResult.amount_in.lt(params.amount)
303
+ } else {
304
+ isExceed = swapResult.amount_out.lt(params.amount)
305
+ }
306
+ const sqrtPriceLimit = SwapUtils.getDefaultSqrtPriceLimit(params.a2b)
307
+ if (params.a2b && swapResult.next_sqrt_price.lt(sqrtPriceLimit)) {
308
+ isExceed = true
309
+ }
310
+
311
+ if (!params.a2b && swapResult.next_sqrt_price.gt(sqrtPriceLimit)) {
312
+ isExceed = true
313
+ }
314
+
315
+ let extraComputeLimit = 0
316
+ if (swapResult.cross_tick_num > 6 && swapResult.cross_tick_num < 40) {
317
+ extraComputeLimit = 22000 * (swapResult.cross_tick_num - 6)
318
+ }
319
+
320
+ if (swapResult.cross_tick_num > 40) {
321
+ isExceed = true
322
+ }
323
+
324
+ const prePrice = TickMath.sqrtPriceX64ToPrice(poolData.current_sqrt_price, params.decimals_a, params.decimals_b).toNumber()
325
+ const afterPrice = TickMath.sqrtPriceX64ToPrice(swapResult.next_sqrt_price, params.decimals_a, params.decimals_b).toNumber()
326
+
327
+ const priceImpactPct = (Math.abs(prePrice - afterPrice) / prePrice) * 100
328
+
329
+ return {
330
+ estimated_amount_in: swapResult.amount_in,
331
+ estimated_amount_out: swapResult.amount_out,
332
+ estimated_end_sqrt_price: swapResult.next_sqrt_price,
333
+ estimated_fee_amount: swapResult.fee_amount,
334
+ is_exceed: isExceed,
335
+ extra_compute_limit: extraComputeLimit,
336
+ amount: params.amount,
337
+ a2b: params.a2b,
338
+ by_amount_in: params.by_amount_in,
339
+ price_impact_pct: priceImpactPct,
340
+ }
341
+ }
342
+
343
+ /**
344
+ * create swap transaction payload
345
+ * @param params
346
+ * @param gas_estimate_arg When the fix input amount is SUI, gasEstimateArg can control whether to recalculate the number of SUI to prevent insufficient gas.
347
+ * If this parameter is not passed, gas estimation is not performed
348
+ * @returns
349
+ */
350
+ async createSwapPayload(params: SwapParams, gas_estimate_arg?: SwapGasEstimateArg): Promise<Transaction> {
351
+ const all_coin_asset = await this._sdk.FullClient.getOwnerCoinAssets(this.sdk.getSenderAddress())
352
+
353
+ if (gas_estimate_arg) {
354
+ const { is_adjust_coin_a, is_adjust_coin_b } = findAdjustCoin(params)
355
+
356
+ if ((params.a2b && is_adjust_coin_a) || (!params.a2b && is_adjust_coin_b)) {
357
+ const tx = await SwapUtils.buildSwapTransactionForGas(this._sdk, params, all_coin_asset, gas_estimate_arg)
358
+ return tx
359
+ }
360
+ }
361
+
362
+ return SwapUtils.buildSwapTransaction(this.sdk, params, all_coin_asset)
363
+ }
364
+
365
+ /**
366
+ * create swap transaction without transfer coins payload
367
+ * @param params
368
+ * @param gas_estimate_arg When the fix input amount is SUI, gasEstimateArg can control whether to recalculate the number of SUI to prevent insufficient gas.
369
+ * If this parameter is not passed, gas estimation is not performed
370
+ * @returns tx and coin ABs
371
+ */
372
+ async createSwapWithoutTransferCoinsPayload(
373
+ params: SwapParams,
374
+ gas_estimate_arg?: SwapGasEstimateArg
375
+ ): Promise<{ tx: Transaction; coin_ab_s: TransactionObjectArgument[] }> {
376
+ const all_coin_asset = await this._sdk.FullClient.getOwnerCoinAssets(this.sdk.getSenderAddress())
377
+
378
+ if (gas_estimate_arg) {
379
+ const { is_adjust_coin_a, is_adjust_coin_b } = findAdjustCoin(params)
380
+
381
+ if ((params.a2b && is_adjust_coin_a) || (!params.a2b && is_adjust_coin_b)) {
382
+ const res = await SwapUtils.buildSwapTransactionWithoutTransferCoinsForGas(this._sdk, params, all_coin_asset, gas_estimate_arg)
383
+ return res
384
+ }
385
+ }
386
+
387
+ return SwapUtils.buildSwapTransactionWithoutTransferCoins(this.sdk, params, all_coin_asset)
388
+ }
389
+ }
package/src/sdk.ts ADDED
@@ -0,0 +1,131 @@
1
+ import type { BaseSdkOptions, Package } from '@cetusprotocol/common-sdk'
2
+ import { SdkWrapper } from '@cetusprotocol/common-sdk'
3
+ import { ConfigModule, RewarderModule } from './modules'
4
+ import { PoolModule } from './modules/poolModule'
5
+ import { PositionModule } from './modules/positionModule'
6
+ import { SwapModule } from './modules/swapModule'
7
+ import { ClmmConfig } from './types/clmm_type'
8
+ import { CetusConfigs } from './types/config_type'
9
+ import { clmmMainnet } from './config/mainnet'
10
+ import { clmmTestnet } from './config/testnet'
11
+
12
+ /**
13
+ * Represents options and configurations for an SDK.
14
+ */
15
+ export interface SdkOptions extends BaseSdkOptions {
16
+ /**
17
+ * Package containing Cetus protocol configurations.
18
+ */
19
+ cetus_config: Package<CetusConfigs>
20
+
21
+ /**
22
+ * Package containing Cryptocurrency Liquidity Mining Module (CLMM) pool configurations.
23
+ */
24
+ clmm_pool: Package<ClmmConfig>
25
+
26
+ /**
27
+ * Package containing integration-related configurations.
28
+ */
29
+ integrate: Package
30
+
31
+ /**
32
+ * The URL for the swap count
33
+ */
34
+ stats_pools_url?: string
35
+ }
36
+
37
+ /**
38
+ * The entry class of CetusClmmSDK, which is almost responsible for all interactions with CLMM.
39
+ */
40
+ export class CetusClmmSDK extends SdkWrapper<SdkOptions> {
41
+ /**
42
+ * Provide interact with clmm pools with a pool router interface.
43
+ */
44
+ protected _pool: PoolModule
45
+
46
+ /**
47
+ * Provide interact with a position rewarder interface.
48
+ */
49
+ protected _rewarder: RewarderModule
50
+
51
+ /**
52
+ * Provide interact with a pool swap router interface.
53
+ */
54
+ protected _swap: SwapModule
55
+
56
+ /**
57
+ * Provide interact with clmm position with a position router interface.
58
+ */
59
+ protected _position: PositionModule
60
+
61
+ /**
62
+ * Provide interact with clmm pool and coin and launchpad pool config
63
+ */
64
+ protected _config: ConfigModule
65
+
66
+ constructor(options: SdkOptions) {
67
+ super(options)
68
+
69
+ this._swap = new SwapModule(this)
70
+ this._pool = new PoolModule(this)
71
+ this._position = new PositionModule(this)
72
+ this._config = new ConfigModule(this)
73
+ this._rewarder = new RewarderModule(this)
74
+ }
75
+
76
+ /**
77
+ * Getter for the Pool property.
78
+ * @returns {PoolModule} The Pool property value.
79
+ */
80
+ get Pool(): PoolModule {
81
+ return this._pool
82
+ }
83
+
84
+ /**
85
+ * Getter for the Position property.
86
+ * @returns {PositionModule} The Position property value.
87
+ */
88
+ get Position(): PositionModule {
89
+ return this._position
90
+ }
91
+
92
+ /**
93
+ * Getter for the CetusConfig property.
94
+ * @returns {ConfigModule} The CetusConfig property value.
95
+ */
96
+ get CetusConfig(): ConfigModule {
97
+ return this._config
98
+ }
99
+
100
+ /**
101
+ * Getter for the Rewarder property.
102
+ * @returns {RewarderModule} The Rewarder property value.
103
+ */
104
+ get Rewarder(): RewarderModule {
105
+ return this._rewarder
106
+ }
107
+
108
+ /**
109
+ * Getter for the Swap property.
110
+ * @returns {SwapModule} The Swap property value.
111
+ */
112
+ get Swap(): SwapModule {
113
+ return this._swap
114
+ }
115
+
116
+ static createSDK(options: BaseSdkOptions): CetusClmmSDK {
117
+ const { env = 'mainnet' } = options
118
+ return env === 'mainnet'
119
+ ? CetusClmmSDK.createCustomSDK({ ...clmmMainnet, ...options })
120
+ : CetusClmmSDK.createCustomSDK({ ...clmmTestnet, ...options })
121
+ }
122
+
123
+ /**
124
+ * Create a custom SDK instance with the given options
125
+ * @param options The options for the SDK
126
+ * @returns An instance of CetusBurnSDK
127
+ */
128
+ static createCustomSDK<T extends BaseSdkOptions>(options: T & SdkOptions): CetusClmmSDK {
129
+ return new CetusClmmSDK(options)
130
+ }
131
+ }