@cetusprotocol/dlmm-sdk 0.0.1

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 (44) hide show
  1. package/.turbo/turbo-build.log +10423 -0
  2. package/README.md +646 -0
  3. package/dist/index.d.mts +1015 -0
  4. package/dist/index.d.ts +1015 -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/package.json +35 -0
  10. package/src/config/index.ts +2 -0
  11. package/src/config/mainnet.ts +25 -0
  12. package/src/config/testnet.ts +30 -0
  13. package/src/errors/errors.ts +40 -0
  14. package/src/index.ts +8 -0
  15. package/src/modules/configModule.ts +184 -0
  16. package/src/modules/index.ts +1 -0
  17. package/src/modules/partnerModule.ts +302 -0
  18. package/src/modules/poolModule.ts +578 -0
  19. package/src/modules/positionModule.ts +888 -0
  20. package/src/modules/rewardModule.ts +175 -0
  21. package/src/modules/swapModule.ts +129 -0
  22. package/src/sdk.ts +88 -0
  23. package/src/types/constants.ts +23 -0
  24. package/src/types/dlmm.ts +445 -0
  25. package/src/types/index.ts +2 -0
  26. package/src/utils/binUtils.ts +552 -0
  27. package/src/utils/feeUtils.ts +92 -0
  28. package/src/utils/index.ts +5 -0
  29. package/src/utils/parseData.ts +519 -0
  30. package/src/utils/strategyUtils.ts +121 -0
  31. package/src/utils/weightUtils.ts +510 -0
  32. package/tests/add_liquidity_bidask.test.ts +180 -0
  33. package/tests/add_liquidity_curve.test.ts +244 -0
  34. package/tests/add_liquidity_spot.test.ts +262 -0
  35. package/tests/bin.test.ts +80 -0
  36. package/tests/config.test.ts +51 -0
  37. package/tests/partner.test.ts +74 -0
  38. package/tests/pool.test.ts +174 -0
  39. package/tests/position.test.ts +76 -0
  40. package/tests/remove_liquidity.test.ts +137 -0
  41. package/tests/swap.test.ts +96 -0
  42. package/tests/tsconfig.json +26 -0
  43. package/tsconfig.json +5 -0
  44. package/tsup.config.ts +9 -0
package/README.md ADDED
@@ -0,0 +1,646 @@
1
+ # @cetusprotocol/dlmm-sdk
2
+
3
+ The SDK provides a DLMM (Dynamic Liquidity Market Maker) module for specialized liquidity operations with different modes to suit various trading strategies. This module enables users to perform complex liquidity operations with flexibility in how they want to manage their positions.
4
+
5
+ ## Getting Started
6
+
7
+ ## How to Use the DLMM SDK?
8
+
9
+ ### Installation
10
+
11
+ To start using the `DLMM SDK`, you first need to install it in your TypeScript project:
12
+
13
+ ```bash
14
+ npm install @cetusprotocol/dlmm-sdk
15
+ ```
16
+
17
+ ### Setup
18
+
19
+ Import the SDK into the TypeScript file where you intend to use it:
20
+
21
+ ```typescript
22
+ import { CetusDlmmSDK } from '@cetusprotocol/dlmm-sdk'
23
+ ```
24
+
25
+ ### Initializing the SDK
26
+
27
+ Initialize the SDK with the required configuration parameters. This typically includes setting up the network if needed.
28
+
29
+ If you would like to use the mainnet network and the official Sui rpc url, you can do so as follows:
30
+
31
+ ```typescript
32
+ const sdk = CetusDlmmSDK.createSDK()
33
+ ```
34
+
35
+ If you wish to set your own full node URL or network (You have the option to select either 'mainnet' or 'testnet' for the network), you can do so as follows:
36
+
37
+ ```typescript
38
+ const env = 'mainnet'
39
+ const full_rpc_url = 'YOUR_FULL_NODE_URL'
40
+
41
+ const sdk = CetusDlmmSDK.createSDK({ env })
42
+ ```
43
+
44
+ If you wish to set your own full node URL or SuiClient, you can do so as follows:
45
+
46
+ ```typescript
47
+ const sdk = CetusDlmmSDK.createSDK({ env, sui_client })
48
+ // or
49
+ const sdk = CetusDlmmSDK.createSDK({ env, full_rpc_url })
50
+ ```
51
+
52
+ ## Usage
53
+
54
+ After linking your wallet, if you need use your wallet address to do something, you should set it by `sdk.setSenderAddress`.
55
+
56
+ ```typescript
57
+ const wallet = 'YOUR_WALLET_ADDRESS'
58
+
59
+ sdk.setSenderAddress(wallet)
60
+ ```
61
+
62
+ if you need to change your rpc url, you can do so as follows:
63
+
64
+ ```typescript
65
+ const new_rpc_url = 'YOUR_NEW_FULL_NODE_URL'
66
+
67
+ sdk.updateFullRpcUrl(new_rpc_url)
68
+ ```
69
+
70
+ ### Common Parameters
71
+
72
+ - `pool_id`: The ID of the liquidity pool
73
+ - `bin_id`: The ID of the bin in the pool
74
+ - `bin_step`: The step size between bins
75
+ - `coin_type_a` & `coin_type_b`: Coin type identifiers for the trading pair
76
+ - `coin_decimal_a` & `coin_decimal_b`: Decimal places for each coin type
77
+
78
+ ### 1. Pool Operations
79
+
80
+ #### Get Pool Information
81
+
82
+ ```typescript
83
+ // Get all pools
84
+ const pools = await sdk.Pool.getPools()
85
+
86
+ // Get specific pool
87
+ const pool = await sdk.Pool.getPool(pool_id)
88
+
89
+ // Get specific pools by their IDs
90
+ const assign_pools = await sdk.Pool.getAssignPoolList([
91
+ '0x...',
92
+ // Add more pool IDs as needed
93
+ ])
94
+
95
+ // Get bin information
96
+ const bin_info = await sdk.Pool.getBinInfo(pool_id, bin_id, bin_step)
97
+
98
+ // Get pool bin information
99
+ const pool_bin_info = await sdk.Pool.getPoolBinInfo(pool_id)
100
+
101
+ // Get bin step configurations
102
+ const bin_step_configs = await sdk.Pool.getBinStepConfigs()
103
+
104
+ // Get pool transaction list
105
+ const pool_transactions = await sdk.Pool.getPoolTransactionList({
106
+ pool_id: '0x...',
107
+ pagination_args: { limit: 10 }
108
+ })
109
+ ```
110
+
111
+ #### Create Pool
112
+
113
+ There are two ways to create a pool:
114
+
115
+ **Method 1: Create Pool Only**
116
+
117
+ ```typescript
118
+ // Create a new pool without adding liquidity
119
+ const bin_step = 2
120
+ const base_factor = 10000
121
+ const price = '1.1'
122
+ const active_id = BinUtils.getBinIdFromPrice(price, bin_step, true, 6, 6)
123
+
124
+ const tx = new Transaction()
125
+ await sdk.Pool.createPoolPayload({
126
+ active_id,
127
+ bin_step,
128
+ coin_type_a: '0x...::usdc::USDC',
129
+ coin_type_b: '0x...::usdt::USDT',
130
+ base_factor,
131
+ }, tx)
132
+ ```
133
+
134
+ **Method 2: Create Pool and Add Liquidity in One Transaction**
135
+
136
+ ```typescript
137
+ // Create pool and add liquidity in one transaction
138
+ const bin_step = 2
139
+ const base_factor = 10000
140
+ const price = '1.1'
141
+ const active_id = BinUtils.getBinIdFromPrice(price, bin_step, true, 6, 6)
142
+
143
+ // Calculate liquidity distribution
144
+ const bin_infos = sdk.Position.calculateAddLiquidityInfo({
145
+ active_id,
146
+ bin_step,
147
+ lower_bin_id: active_id - 10,
148
+ upper_bin_id: active_id + 10,
149
+ amount_a_in_active_bin: '0',
150
+ amount_b_in_active_bin: '0',
151
+ strategy_type: StrategyType.Spot,
152
+ coin_amount: '10000000',
153
+ fix_amount_a: true,
154
+ })
155
+
156
+ const createAndAddTx = await sdk.Pool.createPoolAndAddLiquidityPayload({
157
+ active_id,
158
+ lower_bin_id: active_id - 10,
159
+ upper_bin_id: active_id + 10,
160
+ bin_step,
161
+ bin_infos,
162
+ coin_type_a: '0x14a71d857b34677a7d57e0feb303df1adb515a37780645ab763d42ce8d1a5e48::usdc::USDC',
163
+ coin_type_b: '0x14a71d857b34677a7d57e0feb303df1adb515a37780645ab763d42ce8d1a5e48::eth::ETH',
164
+ strategy_type: StrategyType.Spot,
165
+ use_bin_infos: false,
166
+ base_factor,
167
+ })
168
+ ```
169
+
170
+ ### 2. Position Operations
171
+
172
+ #### Get Position Information
173
+
174
+ ```typescript
175
+ // Get owner's position list
176
+ const positions = await sdk.Position.getOwnerPositionList(wallet)
177
+
178
+ // Get specific position
179
+ const position = await sdk.Position.getPosition(position_id)
180
+ ```
181
+
182
+ ### 3. Fee Operations
183
+
184
+ #### Fee and Reward Calculation
185
+
186
+ To calculate fees and rewards for a position, you can use the `fetchPositionFeeAndReward` method. This method allows you to get both fee and reward data for one or multiple positions:
187
+
188
+ ```typescript
189
+ // First get the pool information
190
+ const pool = await sdk.Pool.getPool(pool_id)
191
+ const { id, coin_type_a, coin_type_b, reward_manager } = pool
192
+
193
+ // Fetch fee and reward data
194
+ const { feeData, rewardData } = await sdk.Position.fetchPositionFeeAndReward([
195
+ {
196
+ pool_id: id,
197
+ position_id: position_id,
198
+ reward_coins: reward_manager.rewards.map((reward) => reward.reward_coin),
199
+ coin_type_a,
200
+ coin_type_b,
201
+ },
202
+ ])
203
+
204
+ // feeData structure
205
+ // {
206
+ // [position_id]: {
207
+ // position_id: string,
208
+ // fee_owned_a: string, // Amount of token A fees owned
209
+ // fee_owned_b: string // Amount of token B fees owned
210
+ // }
211
+ // }
212
+
213
+ // rewardData structure
214
+ // {
215
+ // [position_id]: {
216
+ // position_id: string,
217
+ // rewards: {
218
+ // [coin_type]: string // Amount of reward tokens owned
219
+ // }
220
+ // }
221
+ // }
222
+ ```
223
+
224
+ #### Fee Collection
225
+
226
+ You can collect fees from your positions in several ways:
227
+
228
+ 1. **Collect Fees and Rewards Together**:
229
+ ```typescript
230
+ // Build collect fee and reward transaction
231
+ const tx = await sdk.Position.collectRewardAndFeePayload([{
232
+ pool_id,
233
+ position_id,
234
+ reward_coins: reward_manager.rewards.map((reward) => reward.reward_coin),
235
+ coin_type_a,
236
+ coin_type_b
237
+ }])
238
+
239
+ // Simulate or send the transaction
240
+ const sim_result = await sdk.FullClient.sendSimulationTransaction(tx, wallet)
241
+ ```
242
+
243
+ ### 4. Liquidity Operations
244
+
245
+ #### Add Liquidity
246
+
247
+ There are three strategies for adding liquidity: Spot, BidAsk, and Curve. Here's how to use each:
248
+
249
+ 1. **Spot Strategy**:
250
+ ```typescript
251
+ // Get pool information
252
+ const pool = await sdk.Pool.getPool(pool_id)
253
+ const { active_id, bin_step, bin_manager } = pool
254
+
255
+ // Get amounts in active bin if it's within the range
256
+ const amounts_in_active_bin = await sdk.Position.getActiveBinIfInRange(
257
+ bin_manager.bin_manager_handle,
258
+ lower_bin_id,
259
+ upper_bin_id,
260
+ active_id,
261
+ bin_step
262
+ )
263
+
264
+ // Calculate liquidity distribution
265
+ const calculateOption = {
266
+ amount_a: '1000000',
267
+ amount_b: '1200000',
268
+ active_id,
269
+ bin_step,
270
+ lower_bin_id: -10,
271
+ upper_bin_id: 10,
272
+ amount_a_in_active_bin: amounts_in_active_bin?.amount_a || '0',
273
+ amount_b_in_active_bin: amounts_in_active_bin?.amount_b || '0',
274
+ strategy_type: StrategyType.Spot
275
+ }
276
+ const bin_infos = sdk.Position.calculateAddLiquidityInfo(calculateOption)
277
+
278
+ // For new position
279
+ const addOption = {
280
+ pool_id,
281
+ bin_infos,
282
+ coin_type_a: pool.coin_type_a,
283
+ coin_type_b: pool.coin_type_b,
284
+ lower_bin_id: -10,
285
+ upper_bin_id: 10,
286
+ active_id
287
+ }
288
+ const tx = sdk.Position.addLiquidityPayload(addOption)
289
+
290
+ // For existing position
291
+ const addOption = {
292
+ pool_id,
293
+ bin_infos,
294
+ coin_type_a: pool.coin_type_a,
295
+ coin_type_b: pool.coin_type_b,
296
+ active_id,
297
+ position_id,
298
+ collect_fee: true,
299
+ reward_coins: []
300
+ }
301
+ const tx = sdk.Position.addLiquidityPayload(addOption)
302
+ ```
303
+
304
+ Note: The `amount_a_in_active_bin` and `amount_b_in_active_bin` parameters are used to calculate the correct liquidity distribution when the active bin is within your position's range. These values are obtained using the `getActiveBinIfInRange` method, which:
305
+ 1. Checks if the active bin is within your specified range
306
+ 2. Returns the amounts of both tokens in the active bin if it is within range
307
+ 3. Returns undefined if the active bin is outside the range
308
+
309
+ 2. **BidAsk Strategy**:
310
+ ```typescript
311
+ // Similar to Spot strategy but with different strategy_type
312
+ const calculateOption = {
313
+ amount_a: '1000000',
314
+ amount_b: '1200000',
315
+ active_id,
316
+ bin_step,
317
+ lower_bin_id: -10,
318
+ upper_bin_id: 10,
319
+ amount_a_in_active_bin: '0',
320
+ amount_b_in_active_bin: '0',
321
+ strategy_type: StrategyType.BidAsk
322
+ }
323
+ ```
324
+
325
+ 3. **Curve Strategy**:
326
+ ```typescript
327
+ // Similar to Spot strategy but with different strategy_type
328
+ const calculateOption = {
329
+ amount_a: '1000000',
330
+ amount_b: '1200000',
331
+ active_id,
332
+ bin_step,
333
+ lower_bin_id: -10,
334
+ upper_bin_id: 10,
335
+ amount_a_in_active_bin: '0',
336
+ amount_b_in_active_bin: '0',
337
+ strategy_type: StrategyType.Curve
338
+ }
339
+ ```
340
+
341
+ 4. **Fixed Amount Strategy**:
342
+ ```typescript
343
+ // Calculate with fixed amount of one token
344
+ const calculateOption = {
345
+ coin_amount: '1000000',
346
+ fix_amount_a: true, // true for token A, false for token B
347
+ active_id,
348
+ bin_step,
349
+ lower_bin_id: -10,
350
+ upper_bin_id: 10,
351
+ amount_a_in_active_bin: '0',
352
+ amount_b_in_active_bin: '0',
353
+ strategy_type: StrategyType.Spot // or BidAsk or Curve
354
+ }
355
+ ```
356
+
357
+ 5. **Add Liquidity with Price**:
358
+ ```typescript
359
+ // Add liquidity with specific price range
360
+ const addOption = {
361
+ pool_id,
362
+ bin_infos,
363
+ coin_type_a: pool.coin_type_a,
364
+ coin_type_b: pool.coin_type_b,
365
+ price_base_coin: 'coin_a',
366
+ price: price.toString(),
367
+ lower_price,
368
+ upper_price,
369
+ bin_step,
370
+ amount_a_in_active_bin: amounts_in_active_bin?.amount_a || '0',
371
+ amount_b_in_active_bin: amounts_in_active_bin?.amount_b || '0',
372
+ strategy_type: StrategyType.Spot,
373
+ decimals_a: 6,
374
+ decimals_b: 6,
375
+ max_bin_slippage: 0.01,
376
+ }
377
+ const tx = sdk.Position.addLiquidityWithPricePayload(addOption)
378
+ ```
379
+
380
+ #### Remove Liquidity
381
+
382
+ There are two ways to remove liquidity:
383
+
384
+ 1. **Remove with Both Amounts**:
385
+ ```typescript
386
+ // Get position and pool information
387
+ const pool = await sdk.Pool.getPool(pool_id)
388
+ const position = await sdk.Position.getPosition(position_id)
389
+ const { active_id, bin_step, bin_manager } = pool
390
+
391
+ // Get active bin information
392
+ const active_bin = await sdk.Pool.getBinInfo(bin_manager.bin_manager_handle, active_id, bin_step)
393
+ const liquidity_shares_data = parseLiquidityShares(position.liquidity_shares, bin_step, position.lower_bin_id, active_bin)
394
+
395
+ // Calculate removal amounts
396
+ const calculateOption = {
397
+ bins: liquidity_shares_data.bins,
398
+ active_id,
399
+ fix_amount_a: true,
400
+ coin_amount: '100000'
401
+ }
402
+ const bin_infos = sdk.Position.calculateRemoveLiquidityInfo(calculateOption)
403
+
404
+ // Build and send transaction
405
+ const removeOption = {
406
+ pool_id,
407
+ bin_infos,
408
+ coin_type_a: pool.coin_type_a,
409
+ coin_type_b: pool.coin_type_b,
410
+ position_id,
411
+ slippage: 0.01,
412
+ reward_coins: []
413
+ }
414
+ const tx = sdk.Position.removeLiquidityPayload(removeOption)
415
+ ```
416
+
417
+ 2. **Remove Only One Token**:
418
+ ```typescript
419
+ const calculateOption = {
420
+ bins: liquidity_shares_data.bins,
421
+ active_id,
422
+ is_only_a: true, // true for token A, false for token B
423
+ coin_amount: '100000'
424
+ }
425
+ ```
426
+
427
+ #### Close Position
428
+
429
+ ```typescript
430
+ // Close position (This will collect all fees, rewards and remove all liquidity)
431
+ const tx = sdk.Position.closePositionPayload({
432
+ pool_id,
433
+ position_id,
434
+ coin_type_a,
435
+ coin_type_b,
436
+ reward_coins: pool.reward_manager.rewards.map(reward => reward.reward_coin) // Required: Must include all reward coin types from the pool
437
+ })
438
+
439
+ // Simulate or send the transaction
440
+ const sim_result = await sdk.FullClient.sendSimulationTransaction(tx, wallet)
441
+ ```
442
+
443
+ Note: Closing a position will:
444
+ 1. Collect all accumulated fees
445
+ 2. Collect all pending rewards (must include all reward coins from the pool)
446
+ 3. Remove all liquidity from the position
447
+ 4. Delete the position
448
+
449
+ ### 5. Swap Operations
450
+
451
+ ```typescript
452
+ // Get pool information
453
+ const pool = await sdk.Pool.getPool(pool_id)
454
+ const { coin_type_a, coin_type_b } = pool
455
+
456
+ // Get swap quote
457
+ const quote_obj = await sdk.Swap.preSwapQuote({
458
+ pool_id,
459
+ a2b: true, // true for A to B, false for B to A
460
+ by_amount_in: true, // true for exact input, false for exact output
461
+ in_amount: '2000000',
462
+ coin_type_a,
463
+ coin_type_b
464
+ })
465
+
466
+ // Build and send swap transaction
467
+ const tx = sdk.Swap.swapPayload({
468
+ coin_type_a,
469
+ coin_type_b,
470
+ quote_obj,
471
+ by_amount_in: true,
472
+ slippage: 0.01
473
+ })
474
+ ```
475
+
476
+ ### 6. Partner Operations
477
+
478
+ #### Partner Management
479
+
480
+ ```typescript
481
+ // Get partner list
482
+ const partnerList = await sdk.Partner.getPartnerList()
483
+
484
+ // Get specific partner
485
+ const partner = await sdk.Partner.getPartner(partner_id)
486
+
487
+ // Get partner capability ID
488
+ const partnerCapId = await sdk.Partner.getPartnerCapId(account, partner_id)
489
+
490
+ // Get partner balance
491
+ const partnerBalance = await sdk.Partner.getPartnerBalance(partner_id)
492
+
493
+ // Create partner
494
+ const start_time = Math.floor(Date.now() / 1000) + 5000
495
+ const tx = sdk.Partner.createPartnerPayload({
496
+ name: 'test partner',
497
+ ref_fee_rate: 0.01,
498
+ start_time,
499
+ end_time: start_time + 9 * 24 * 3600,
500
+ recipient: account,
501
+ })
502
+
503
+ // Update referral fee rate
504
+ const updateFeeTx = await sdk.Partner.updateRefFeeRatePayload({
505
+ partner_id: '0x9d171399393e3cbedffc24269eb606e735fb56fee17c15153eb5e2d5274a3677',
506
+ ref_fee_rate: 0.02,
507
+ })
508
+
509
+ // Update time range
510
+ const start_time = Math.floor(Date.now() / 1000)
511
+ const updateTimeTx = await sdk.Partner.updateTimeRangePayload({
512
+ partner_id: '0x9d171399393e3cbedffc24269eb606e735fb56fee17c15153eb5e2d5274a3677',
513
+ start_time,
514
+ end_time: start_time + 10 * 7 * 24 * 3600,
515
+ })
516
+ ```
517
+
518
+ ### 7. Reward Operations
519
+
520
+ #### Reward Management
521
+
522
+ ```typescript
523
+ // Initialize rewards for a pool
524
+ const initTx = sdk.Reward.initRewardPayload({
525
+ pool_id,
526
+ reward_coin_types: ['0x2::sui::SUI', '0x5::usdc::USDC']
527
+ })
528
+
529
+ // Add reward to a pool
530
+ const addRewardTx = sdk.Reward.addRewardPayload({
531
+ pool_id,
532
+ reward_coin_type: '0x2::sui::SUI',
533
+ reward_amount: '1000000',
534
+ end_time_seconds: Math.floor(Date.now() / 1000) + 30 * 24 * 3600, // 30 days
535
+ start_time_seconds: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now
536
+ })
537
+
538
+ // Update reward access (public/private)
539
+ const accessTx = sdk.Reward.updateRewardAccessPayload({
540
+ pool_id,
541
+ type: 'to_public', // or 'to_private'
542
+ })
543
+
544
+ // Manage reward whitelist
545
+ const whitelistTx = sdk.Reward.updateRewardWhiteListPayload({
546
+ reward_coin_types: ['0x2::sui::SUI'],
547
+ type: 'add' // or 'remove'
548
+ })
549
+ ```
550
+
551
+ ### 8. Bin Operations
552
+
553
+ The SDK provides utility functions for working with bins and prices through the `BinUtils` class:
554
+
555
+ ```typescript
556
+ import { BinUtils } from '@cetusprotocol/dlmm-sdk'
557
+
558
+ // Convert price to bin ID
559
+ const binId = BinUtils.getBinIdFromPrice(
560
+ '1040.07', // price
561
+ 2, // bin step
562
+ true, // is base coin A
563
+ 6, // decimals for coin A
564
+ 9 // decimals for coin B
565
+ )
566
+
567
+ // Convert bin ID to price
568
+ const price = BinUtils.getPriceFromBinId(
569
+ -4787, // bin ID
570
+ 2, // bin step
571
+ 6, // decimals for coin A
572
+ 9 // decimals for coin B
573
+ )
574
+
575
+ // Get Q price from bin ID
576
+ const q_price = BinUtils.getQPriceFromId(
577
+ -4400, // bin ID
578
+ 100 // bin step
579
+ )
580
+
581
+ // Get price per lamport from Q price
582
+ const price_per_lamport = BinUtils.getPricePerLamportFromQPrice(q_price)
583
+
584
+ // Get liquidity from amounts
585
+ const liquidity = BinUtils.getLiquidity('0', '266666', '18431994054197767090')
586
+
587
+ // Get amount A from liquidity
588
+ const amountA = BinUtils.getAmountAFromLiquidity('4101094304427826916657468', '18461505896777422276')
589
+
590
+ // Get amount B from liquidity
591
+ const amountB = BinUtils.getAmountBFromLiquidity('4919119455159831291232256')
592
+
593
+ // Get amounts from liquidity with ratio
594
+ const [amountA, amountB] = BinUtils.getAmountsFromLiquidityWithRatio(
595
+ '4510099798813469403250688',
596
+ '18446744073709551616',
597
+ 0.9 // ratio
598
+ )
599
+
600
+ // Split bin liquidity info
601
+ const split_bin_infos = BinUtils.splitBinLiquidityInfo(bin_infos, 0, 70)
602
+ ```
603
+
604
+ These utility functions are particularly useful when:
605
+ - Setting up price ranges for liquidity positions
606
+ - Calculating optimal bin ranges for trading strategies
607
+ - Converting between different price representations
608
+ - Managing liquidity distributions across bins
609
+
610
+ ### 9. Advanced Operations
611
+
612
+ #### Validate Active ID Slippage
613
+
614
+ ```typescript
615
+ // Validate that the active ID hasn't moved too much
616
+ const isValid = await sdk.Position.validateActiveIdSlippage({
617
+ pool_id,
618
+ active_id,
619
+ max_bin_slippage: 0.01
620
+ })
621
+ ```
622
+
623
+ #### Update Position Fee and Rewards
624
+
625
+ ```typescript
626
+ // Update position fee and reward information
627
+ await sdk.Position.updatePositionFeeAndRewards({
628
+ pool_id,
629
+ position_id,
630
+ coin_type_a,
631
+ coin_type_b
632
+ })
633
+ ```
634
+
635
+ ## More About Cetus
636
+
637
+ Use the following links to learn more about Cetus:
638
+
639
+ Learn more about working with Cetus in the [Cetus Documentation](https://cetus-1.gitbook.io/cetus-docs).
640
+
641
+ Join the Cetus community on [Cetus Discord](https://discord.com/channels/1009749448022315008/1009751382783447072).
642
+
643
+ ## License
644
+
645
+ MIT
646
+