@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,145 @@
1
+ # Add liquidity
2
+
3
+ Once you have set a suitable tick range, you can proceed to add liquidity to this position. The quantity composition of tokens you need to add is affected by the current price of the pool and the tick interval you have chosen.
4
+
5
+ There are two situations:
6
+
7
+ 1. add liquidity with a specified liquidity
8
+ 2. add liquidity with fixed coin amount.
9
+
10
+ ## 1. add liquidity with a specified liquidity
11
+
12
+ Use `sdk.Position.createAddLiquidityPayload()` method.
13
+
14
+ ### Function Parameters
15
+
16
+ - `pool_id`: The object id about which pool you want to operation
17
+ - `pos_id`: The object id about position.
18
+ - `max_amount_a`: The max limit about used coin a amount.
19
+ - `max_amount_b`: The max limit about used coin b amount.
20
+ - `delta_liquidity`: The actual change in liquidity that has been added.
21
+ - `tick_lower`: Represents the index of the lower tick boundary
22
+ - `tick_upper`: Represents the index of the upper tick boundary
23
+ - `collect_fee`: If you already has one position, you can select collect fees while adding liquidity.
24
+ - `rewarder_coin_types`: If these not empty, it will collect rewarder in this position, if you already open the position.
25
+
26
+ ### Important Notes
27
+
28
+ ### How to Calculate `delta_liquidity`, `max_amount_a`, and `max_amount_b`
29
+
30
+ 1. you can set fixed two coin amount you want to use.
31
+ 2. use ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts() to calculated the delta_liquidity.
32
+ 3. Apply price slippage adjustment to the two coin amounts(max_amount_a and max_amount_b) calculated above by method adjustForCoinSlippage
33
+
34
+ ### Example
35
+
36
+ ```typescript
37
+ const pool = await sdk.Pool.getPool(pool_id)
38
+ const position = await sdk.Position.getPositionById(pos_id)
39
+ const cur_sqrt_price = new BN(pool.current_sqrt_price)
40
+ const lower_tick = Number(position.tick_lower_index)
41
+ const upper_tick = Number(position.tick_upper_index)
42
+
43
+ const lower_sqrt_price = TickMath.tickIndexToSqrtPriceX64(lower_tick)
44
+ const upper_sqrt_price = TickMath.tickIndexToSqrtPriceX64(upper_tick)
45
+
46
+ const slippage_tolerance = new Percentage(new BN(5), new BN(100))
47
+ const liquidity = 10000
48
+
49
+ const coin_amounts = ClmmPoolUtil.getCoinAmountFromLiquidity(new BN(liquidity), cur_sqrt_price, lower_sqrt_price, upper_sqrt_price, false)
50
+
51
+ const { coin_amount_limit_a, coin_amount_limit_b } = adjustForCoinSlippage(coin_amounts, slippage_tolerance, true)
52
+
53
+ const add_liquidity_payload_params: AddLiquidityParams = {
54
+ coin_type_a: pool.coin_type_a,
55
+ coin_type_b: pool.coin_type_b,
56
+ pool_id: pool.id,
57
+ tick_lower: lower_tick.toString(),
58
+ tick_upper: upper_tick.toString(),
59
+ delta_liquidity: liquidity.toString(),
60
+ max_amount_a: coin_amount_limit_a.toString(),
61
+ max_amount_b: coin_amount_limit_b.toString(),
62
+ pos_id: position.pos_object_id,
63
+ rewarder_coin_types: [],
64
+ collect_fee: false,
65
+ }
66
+
67
+ const payload = await sdk.Position.createAddLiquidityPayload(add_liquidity_payload_params)
68
+
69
+ printTransaction(payload)
70
+ const send_key_pair = 'The key pair generated by your private key'
71
+ const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, payload, true)
72
+ ```
73
+
74
+ ### 2. Add liquidity with a fixed coin amount
75
+
76
+ Use `sdk.Position.createAddLiquidityFixTokenPayload()` method.
77
+
78
+ ### Function Parameters
79
+
80
+ - `pool_id`: The object id about which pool you want to operation
81
+ - `coin_type_a`: The coin type address about coinA
82
+ - `coin_type_b`: The coin type address about coinB
83
+ - `tick_lower`: Represents the index of the lower tick boundary
84
+ - `tick_upper`: Represents the index of the upper tick boundary
85
+ - `is_open`: true means if first add liquidity, so needs open one position
86
+ - `pos_id`: The object id about position
87
+ - `fix_amount_a`: true means fixed coinA amount, false means fixed coinB amount
88
+ - `slippage`: Price slippage point.
89
+ - `amount_a`: If fixed amount A, you must set amount_a, amount_b will be auto calculated by `ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts()`
90
+ - `amount_b`: If fixed amount B, you must set amount_b, amount_a will be auto calculated by `ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts()`
91
+ - `collect_fee`: If you already has one position, you can select collect fees while adding liquidity
92
+ - `rewarder_coin_types`: If these not empty, it will collect rewarder in this position, if you already open the position
93
+
94
+ ### Important Notes
95
+
96
+ - The tick index must be an integer multiple of tickSpacing. If the provided parameter is not a multiple of tickSpacing, the contract will throw an error.
97
+ - `-443636 < tick_lower_index < tick_upper_index < 443636`, 443636 is a constant, derived from the maximum range representable by the Q32.62 fixed-point number format.
98
+ - If you know price range, you can use `TickMath.priceToTickIndex()` to transform real price to tick index.
99
+ - You can just open one position near the current price of the pool, use `TickMath.getPrevInitializeTickIndex()` and `TickMath.getNextInitializeTickIndex()` to find the next initialized tick.
100
+ - If you want to add global liquidity, you can set:
101
+ - `tick_lower_index = -443636 + (443636 % tick_spacing)`
102
+ - `tick_upper_index = 443636 - (443636 % tick_spacing)`
103
+
104
+ ```typescript
105
+ const pool = await sdk.Pool.getPool(pool_id)
106
+ const position = await sdk.Position.getPositionById(pos_id)
107
+ const tick_lower_index = position.tick_lower_index
108
+ const tick_upper_index = position.tick_upper_index
109
+ const coin_amount = new BN(500)
110
+ const fix_amount_a = true
111
+ const slippage = 0.1
112
+ const cur_sqrt_price = new BN(pool.current_sqrt_price)
113
+
114
+ const liquidity_input = ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts(
115
+ tick_lower_index,
116
+ tick_upper_index,
117
+ coin_amount,
118
+ fix_amount_a,
119
+ true,
120
+ slippage,
121
+ cur_sqrt_price
122
+ )
123
+
124
+ const amount_a = fix_amount_a ? coin_amount.toNumber() : Number(liquidity_input.coin_amount_limit_a)
125
+ const amount_b = fix_amount_a ? Number(liquidity_input.coin_amount_limit_b) : coin_amount.toNumber()
126
+
127
+ const add_liquidity_payload_params: AddLiquidityFixTokenParams = {
128
+ coin_type_a: pool.coin_type_a,
129
+ coin_type_b: pool.coin_type_b,
130
+ pool_id: pool.id,
131
+ tick_lower: tick_lower_index.toString(),
132
+ tick_upper: tick_upper_index.toString(),
133
+ fix_amount_a,
134
+ amount_a,
135
+ amount_b,
136
+ slippage,
137
+ is_open: false,
138
+ pos_id: position.pos_object_id,
139
+ rewarder_coin_types: [],
140
+ collect_fee: true,
141
+ }
142
+ const add_liquidity_payload = await sdk.Position.createAddLiquidityFixTokenPayload(add_liquidity_payload_params)
143
+
144
+ const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, add_liquidity_payload, true)
145
+ ```
@@ -0,0 +1,57 @@
1
+ # Close Position
2
+
3
+ When you withdraw all the liquidity from your position, you can decide whether to close the position. Please note that when closing the position, you must also withdraw all the current position's liquidity, fees, and rewards.
4
+
5
+ ## 1. Close Position
6
+
7
+ Use `sdk.Position.closePositionPayload()` method.
8
+
9
+ ### Function Parameters
10
+
11
+ - `pool_id`: The object id about which pool you want to operation
12
+ - `pos_id`: The object id about which position you want to operation
13
+ - `coin_type_a`: The coin type address about coinA
14
+ - `coin_type_b`: The coin type address about coinB
15
+ - `min_amount_a`: The minimum amount of coin A that a user can acquire.
16
+ - `min_amount_b`: The minimum amount of coin B that a user can acquire.
17
+ - `rewarder_coin_types`: When closing the position, all pending rewards must be collected
18
+
19
+ ### Important Notes
20
+
21
+ - Because of pool price will change, the amount of coin A and coin B will change. So the min_amount_a and min_amount_a means no matter how the price moves, the amount quantity that I need to receive at least is typically obtained
22
+ by adding the amount potentially acquired through calculations to the slippage adjustment.
23
+
24
+ ### Example
25
+
26
+ ```typescript
27
+ const pool = await sdk.Pool.getPool(pool_id)
28
+ const position = await sdk.Position.getPositionById(pos_id)
29
+
30
+ const lower_tick = Number(position.tick_lower_index)
31
+ const upper_tick = Number(position.tick_upper_index)
32
+
33
+ const lower_sqrt_price = TickMath.tickIndexToSqrtPriceX64(lower_tick)
34
+ const upper_sqrt_price = TickMath.tickIndexToSqrtPriceX64(upper_tick)
35
+
36
+ const liquidity = new BN(position.liquidity)
37
+ const slippage_tolerance = new Percentage(new BN(5), new BN(100))
38
+ const cur_sqrt_price = new BN(pool.current_sqrt_price)
39
+
40
+ const coin_amounts = ClmmPoolUtil.getCoinAmountFromLiquidity(liquidity, cur_sqrt_price, lower_sqrt_price, upper_sqrt_price, false)
41
+ const { coin_amount_limit_a, coin_amount_limit_b } = adjustForCoinSlippage(coin_amounts, slippage_tolerance, false)
42
+
43
+ const reward_coin_types = pool.rewarder_infos.map((rewarder) => rewarder.coin_type)
44
+
45
+ const close_position_payload = await sdk.Position.closePositionPayload({
46
+ coin_type_a: pool.coin_type_a,
47
+ coin_type_b: pool.coin_type_b,
48
+ min_amount_a: coin_amount_limit_a.toString(),
49
+ min_amount_b: coin_amount_limit_b.toString(),
50
+ rewarder_coin_types: reward_coin_types,
51
+ pool_id: pool.id,
52
+ pos_id: position_nft_id,
53
+ collect_fee: true,
54
+ })
55
+ const send_key_pair = 'The key pair generated by your private key'
56
+ const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, close_position_payload, true)
57
+ ```
@@ -0,0 +1,37 @@
1
+ # Collect rewards
2
+
3
+ When you provide liquidity within a valid price range, when transactions occurring within this range, the rewards will be distributed every second based on the proportional share of effective liquidity from all positions within the current range. If you intend to harvest rewards separately, please follow the method below.
4
+
5
+ ## 1. Collect rewards
6
+
7
+ Use `sdk.Position.collectRewarderPayload()` method.
8
+
9
+ ### Function Parameters
10
+
11
+ - `pool_id`: The object id about which pool you want to operation
12
+ - `pos_id`: The object id about which position you want to operation
13
+ - `coin_type_a`: The coin type address about coinA
14
+ - `coin_type_b`: The coin type address about coinB
15
+ - `collect_fee`: you can select weather collect fees while Collect rewards.
16
+ - `rewarder_coin_types`: If these not empty, it will collect rewarders in this position, if you already open the position. You can even determine which types of rewards you want to harvest by specifying the coin types you pass.
17
+
18
+ ### Example
19
+
20
+ ```typescript
21
+ const pool = await sdk.Pool.getPool(pool_id)
22
+
23
+ const reward_coin_types = pool.rewarder_infos.map((rewarder) => rewarder.coin_type)
24
+
25
+ const collect_rewarder_params: CollectRewarderParams = {
26
+ pool_id: pool.id,
27
+ pos_id,
28
+ rewarder_coin_types: reward_coin_types,
29
+ coin_type_a: pool.coin_type_a,
30
+ coin_type_b: pool.coin_type_b,
31
+ collect_fee: true,
32
+ }
33
+
34
+ const collect_rewarder_payload = await sdk.Rewarder.collectRewarderPayload(collect_rewarder_params)
35
+ const send_key_pair = 'The key pair generated by your private key'
36
+ const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, collect_rewarder_payload, true)
37
+ ```
@@ -0,0 +1,228 @@
1
+ # Create CLMM Pool
2
+
3
+ Everyone can create Cetus CLMM pools directly.
4
+
5
+ ## 1. Create a CLMM Pool with Initial Liquidity
6
+
7
+ Use `sdk.Pool.createPoolTransactionPayload()` to create a pool.
8
+
9
+ ### Function Parameters
10
+
11
+ #### Required Parameters
12
+
13
+ - `tick_spacing`: Affects price precision. Different tick spacing values correspond to different fee rates:
14
+
15
+ | Tick Spacing | Fee Rate |
16
+ | ------------ | -------- |
17
+ | 2 | 0.0001 |
18
+ | 10 | 0.0005 |
19
+ | 20 | 0.001 |
20
+ | 60 | 0.0025 |
21
+ | 200 | 0.01 |
22
+ | 220 | 0.02 |
23
+
24
+ - `initialize_sqrt_price`: For computational convenience, we use fixed-point numbers to represent square root prices. Use `TickMath.priceToSqrtPriceX64()` to transform price to sqrtPrice.
25
+ - `coin_type_a`: The coin type address for coin A.
26
+ - `coin_type_b`: The coin type address for coin B.
27
+ - `amount_a`: The amount of coin A to add as liquidity.
28
+ - `amount_b`: The amount of coin B to add as liquidity.
29
+ - `fix_amount_a`: Boolean value - true means fixed coin A amount, false means fixed coin B amount.
30
+ - `tick_lower`: The index of the lower tick boundary.
31
+ - `tick_upper`: The index of the upper tick boundary.
32
+ - `metadata_a`: The coin metadata ID of coin A.
33
+ - `metadata_b`: The coin metadata ID of coin B.
34
+
35
+ #### Optional Parameters
36
+
37
+ - `uri`: The icon of the pool (can be null).
38
+
39
+ ### Determining Coin Type A and B
40
+
41
+ 1. Complete the Coin Type: Ensure the coin type is complete before comparing.
42
+ 2. Character-by-Character Comparison: Compare the characters of both coin type addresses.
43
+ 3. ASCII Value Comparison: When encountering differing characters, compare their ASCII values. The coin with the larger ASCII value becomes "coin A".
44
+
45
+ #### Examples:
46
+
47
+ 1. Example 1:
48
+
49
+ - coin_type_a: `0x6864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS`
50
+ - coin_type_b: `0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI`
51
+
52
+ 2. Example 2:
53
+ - coin_type_a: `0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC`
54
+ - coin_type_b: `0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN`
55
+
56
+ ### Important Notes
57
+
58
+ - The tick index must be an integer multiple of tickSpacing.
59
+ - Range: `-443636 < tick_lower_index < current_tick_index < tick_upper_index < 443636`
60
+ - Currently, creating a pool requires adding bidirectional liquidity.
61
+
62
+ ## Example Code
63
+
64
+ ```typescript
65
+ const sdk = CetusClmmSDK.createSDK({ env: 'mainnet' })
66
+ const signer = ... // set keypair
67
+ sdk.senderAddress = signer.getPublicKey().toSuiAddress() // set sdk.senderAddress
68
+
69
+ // Initialize sqrt_price
70
+ const initialize_sqrt_price = TickMath.priceToSqrtPriceX64(d(1.2),6,6).toString()
71
+ const tick_spacing = 2
72
+ const current_tick_index = TickMath.sqrtPriceX64ToTickIndex(new BN(initialize_sqrt_price))
73
+
74
+ // Build tick range
75
+ const tick_lower = TickMath.getPrevInitializeTickIndex(
76
+ new BN(current_tick_index).toNumber(),
77
+ new BN(tick_spacing).toNumber()
78
+ )
79
+ const tick_upper = TickMath.getNextInitializeTickIndex(
80
+ new BN(current_tick_index).toNumber(),
81
+ new BN(tick_spacing).toNumber()
82
+ )
83
+
84
+ // Input token amount
85
+ const fix_coin_amount = new BN(200)
86
+ const fix_amount_a = true // input token amount is token a
87
+ const slippage = 0.05 // 5% slippage
88
+ const cur_sqrt_price = new BN(initialize_sqrt_price)
89
+
90
+ // Estimate liquidity and token amount from one amounts
91
+ const res = ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts(
92
+ lower_tick,
93
+ upper_tick,
94
+ fix_coin_amount,
95
+ fix_amount_a,
96
+ true,
97
+ slippage,
98
+ cur_sqrt_price
99
+ )
100
+
101
+ // Estimate token a and token b amount
102
+ const amount_a = fix_amount_a ? fix_coin_amount.toNumber() : res.coin_amount_limit_a.toNumber()
103
+ const amount_b = fix_amount_a ? res.coin_amount_b.toNumber() : fix_coin_amount.toNumber()
104
+
105
+ const coin_type_a = '0x3cfe7b9f6106808a8178ebd2d5ae6656cd0ccec15d33e63fd857c180bde8da75::coin:CetusUSDT'
106
+ const coin_type_b = '0x3cfe7b9f6106808a8178ebd2d5ae6656cd0ccec15d33e63fd857c180bde8da75::coin::CetusUSDC'
107
+
108
+ const coin_metadata_a_id = await suiClient.fetchCoinMetadata({coinType: coin_type_a}).id
109
+ const coin_metadata_b_id = await suiClient.fetchCoinMetadata({coinType: coin_type_b}).id
110
+
111
+ // Build createPoolPayload
112
+ const create_pool_payload = sdk.Pool.createPoolPayload({
113
+ coin_type_a,
114
+ coin_type_b,
115
+ tick_spacing: tick_spacing,
116
+ initialize_sqrt_price: initialize_sqrt_price,
117
+ uri: '',
118
+ amount_a,
119
+ amount_b,
120
+ fix_amount_a,
121
+ tick_lower,
122
+ tick_upper,
123
+ metadata_a: coin_metadata_a_id,
124
+ metadata_b: coin_metadata_b_id,
125
+ })
126
+ const send_key_pair = 'The key pair generated by your private key'
127
+ const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, tx, true)
128
+ ```
129
+
130
+ ## 2. Create a CLMM Pool with Initial Liquidity by directly inputting the price range
131
+
132
+ Use `sdk.Pool.createPoolWithPricePayload()` to create a pool.
133
+
134
+ ### Function Parameters
135
+
136
+ #### Required Parameters
137
+
138
+ - `tick_spacing`: Affects price precision and fee rate (see table above)
139
+ - `current_price`: The initial price of the pool
140
+ - `coin_amount`: The amount of coins to add as liquidity
141
+ - `fix_amount_a`: Boolean value - true means fixed coin A amount, false means fixed coin B amount
142
+ - `add_mode_params`: Configuration for price range:
143
+ - For custom range: `{ is_full_range: false, min_price: string, max_price: string }`
144
+ - For full range: `{ is_full_range: true }`
145
+ - `coin_decimals_a`: Number of decimal places for coin A
146
+ - `coin_decimals_b`: Number of decimal places for coin B
147
+ - `price_base_coin`: Base coin for price calculation ('coin_a' or 'coin_b')
148
+ - `slippage`: Maximum acceptable slippage (e.g., 0.05 for 5%)
149
+
150
+ ### Two Ways to Create Pool
151
+
152
+ 1. **Create Pool with Position Return**
153
+ Use `sdk.Pool.createPoolWithPriceReturnPositionPayload()` to create a pool and get the position ID and remaining coins.
154
+
155
+ ```typescript
156
+ // Custom price range example
157
+ const tick_spacing = 220
158
+
159
+ const mode_params: CreatePoolCustomRangeParams = {
160
+ is_full_range: false,
161
+ min_price: '0.2',
162
+ max_price: '0.7',
163
+ }
164
+
165
+ const result = await sdk.Pool.calculateCreatePoolWithPrice({
166
+ tick_spacing,
167
+ current_price: '0.5',
168
+ coin_amount: '1000000',
169
+ fix_amount_a: true,
170
+ add_mode_params: mode_params,
171
+ coin_decimals_a: 6,
172
+ coin_decimals_b: 9,
173
+ price_base_coin: 'coin_a',
174
+ slippage: 0.05,
175
+ })
176
+
177
+ const { tx, pos_id, remain_coin_a, remain_coin_b, remain_coin_type_a, remain_coin_type_b } =
178
+ await sdk.Pool.createPoolWithPriceReturnPositionPayload({
179
+ tick_spacing,
180
+ calculate_result: result,
181
+ add_mode_params: mode_params,
182
+ coin_type_a,
183
+ coin_type_b,
184
+ })
185
+
186
+ // Handle remaining coins
187
+ buildTransferCoin(sdk, tx, remain_coin_a, remain_coin_type_a)
188
+ buildTransferCoin(sdk, tx, remain_coin_b, remain_coin_type_b)
189
+ tx.transferObjects([pos_id], sdk.getSenderAddress())
190
+ ```
191
+
192
+ 2. **Create Pool Directly**
193
+ Use `sdk.Pool.createPoolWithPricePayload()` for a simpler pool creation without position management.
194
+
195
+ ```typescript
196
+ // Full range example
197
+ const full_range_params: FullRangeParams = {
198
+ is_full_range: true,
199
+ }
200
+
201
+ const full_range_result = await sdk.Pool.calculateCreatePoolWithPrice({
202
+ tick_spacing,
203
+ current_price: '0.5',
204
+ coin_amount: '1000000',
205
+ fix_amount_a: true,
206
+ add_mode_params: full_range_params,
207
+ coin_decimals_a: 6,
208
+ coin_decimals_b: 9,
209
+ price_base_coin: 'coin_a',
210
+ slippage: 0.05,
211
+ })
212
+
213
+ const tx = await sdk.Pool.createPoolWithPricePayload({
214
+ tick_spacing,
215
+ calculate_result: full_range_result,
216
+ add_mode_params: full_range_params,
217
+ coin_type_a,
218
+ coin_type_b,
219
+ })
220
+ ```
221
+
222
+ ### Important Notes
223
+
224
+ - The price range must be valid and within acceptable bounds
225
+ - For custom ranges, ensure min_price < current_price < max_price
226
+ - The tick spacing determines the fee rate and price precision
227
+ - Slippage protection is important to prevent significant price impact
228
+ - Consider the decimal places of both coins when calculating amounts
@@ -0,0 +1,69 @@
1
+ # Contract Error Codes
2
+
3
+ the Cetus smart contract may return the following error codes:
4
+
5
+ | Module | Error Code | Description | Contract Methods |
6
+ | ------------------------ | ---------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
7
+ | cetus_clmm::pool | 0 | Amount is incorrect | flash_swap_internal,add_liquidity_fix_coin,repay_add_liquidity,repay_flash_swap,repay_flash_swap_with_partner |
8
+ | cetus_clmm::pool | 1 | Liquidity overflow | add_liquidity_internal,calculate_swap_result |
9
+ | cetus_clmm::pool | 3 | Liquidity is zero | add_liquidity,remove_liquidity,add_liquidity_internal |
10
+ | cetus_clmm::pool | 4 | Not enough liquidity | swap_in_pool |
11
+ | cetus_clmm::pool | 5 | Remainder amount underflow | check_remainer_amount_sub |
12
+ | cetus_clmm::pool | 6 | Swap amount in overflow | update_swap_result |
13
+ | cetus_clmm::pool | 7 | Swap amount out overflow | update_swap_result |
14
+ | cetus_clmm::pool | 8 | Fee amount overflow | update_swap_result |
15
+ | cetus_clmm::pool | 9 | Invalid fee rate | update_fee_rate |
16
+ | cetus_clmm::pool | 10 | Invalid fixed coin type | get_liquidity_from_amount |
17
+ | cetus_clmm::pool | 11 | Wrong sqrt price limit | flash_swap_internal |
18
+ | cetus_clmm::pool | 12 | Pool ID is error | repay_add_liquidity |
19
+ | cetus_clmm::pool | 13 | Pool is paused | |
20
+ | cetus_clmm::pool | 14 | Flash swap receipt not match | repay_flash_swap_with_partner, repay_flash_swap |
21
+ | cetus_clmm::pool | 16 | Invalid partner ref fee rate | swap_in_pool |
22
+ | cetus_clmm::pool | 17 | Reward does not exist | get_position_reward ,calculate_and_update_reward,collect_reward |
23
+ | cetus_clmm::pool | 18 | Amount out is zero | flash_swap_internal |
24
+ | cetus_clmm::pool | 19 | Pool position not match | collect_reward,add_liquidity,add_liquidity_fix_coin,remove_liquidity,close_position,collect_fee |
25
+ | cetus_clmm::position | 1 | Fee owned overflow | update_fee_internal |
26
+ | cetus_clmm::position | 2 | Reward owned overflow | update_rewards_internal |
27
+ | cetus_clmm::position | 3 | Points owned overflow | update_points_internal |
28
+ | cetus_clmm::position | 5 | Invalid position tick range | check_position_tick_range |
29
+ | cetus_clmm::position | 6 | Position does not exist | borrow_mut_position_info,fetch_positions,borrow_position_info |
30
+ | cetus_clmm::position | 7 | Position is not empty | close_position |
31
+ | cetus_clmm::position | 8 | Liquidity change overflow | increase_liquidity |
32
+ | cetus_clmm::position | 9 | Liquidity change underflow | decrease_liquidity |
33
+ | cetus_clmm::position | 10 | Invalid reward index | update_and_reset_rewards |
34
+ | cetus_clmm::rewarder | 1 | Reward slot is full | add_rewarder |
35
+ | cetus_clmm::rewarder | 2 | Reward already exists | add_rewarder |
36
+ | cetus_clmm::rewarder | 3 | Invalid time | settle |
37
+ | cetus_clmm::rewarder | 4 | Reward amount insufficient | update_emission |
38
+ | cetus_clmm::rewarder | 5 | Reward does not exist | borrow_mut_rewarder,borrow_rewarder |
39
+ | cetus_clmm::tick | 0 | Liquidity overflow | update_by_liquidity |
40
+ | cetus_clmm::tick | 1 | Liquidity underflow | update_by_liquidity,cross_by_swap |
41
+ | cetus_clmm::tick | 2 | Invalid tick | tick_score, |
42
+ | cetus_clmm::tick | 3 | Tick not found | decrease_liquidity, |
43
+ | cetus_clmm::pool_creator | 1 | Pool is permission | create_pool_v2 |
44
+ | cetus_clmm::pool_creator | 4 | Cap not match with pool key | create_pool_v2_with_creation_cap |
45
+ | cetus_clmm::pool_creator | 5 | Init sqrt price not between lower and upper | create_pool_v2 |
46
+ | cetus_clmm::partner | 1 | Partner already exists | create_partner |
47
+ | cetus_clmm::partner | 2 | Invalid time | create_partner,update_time_range |
48
+ | cetus_clmm::partner | 3 | Invalid partner ref fee rate | update_ref_fee_rate,create_partner |
49
+ | cetus_clmm::partner | 4 | Invalid partner cap | claim_ref_fee |
50
+ | cetus_clmm::partner | 5 | Invalid coin type | claim_ref_fee |
51
+ | cetus_clmm::partner | 6 | Invalid partner name | create_partner |
52
+ | cetus_clmm::factory | 1 | Pool already exists | create_pool_internal |
53
+ | cetus_clmm::factory | 2 | Invalid sqrt price | create_pool_internal |
54
+ | cetus_clmm::factory | 3 | Same coin type | new_pool_key,create_pool_internal |
55
+ | cetus_clmm::factory | 4 | Amount in above max limit | create_pool_v2_ |
56
+ | cetus_clmm::factory | 5 | Amount out below min limit | create_pool_v2_ |
57
+ | cetus_clmm::factory | 6 | Invalid coin type sequence | new_pool_key |
58
+ | cetus_clmm::factory | 7 | Quote coin type not in allowed pair config | register_permission_pair_internal |
59
+ | cetus_clmm::factory | 8 | Tick spacing not in allowed pair config | register_permission_pair_internal |
60
+ | cetus_clmm::factory | 9 | Pool key already registered | register_permission_pair_internal |
61
+ | cetus_clmm::factory | 10 | Pool key not registered | unregister_permission_pair_internal |
62
+ | cetus_clmm::factory | 11 | Cap already registered | mint_pool_creation_cap_by_admin,mint_pool_creation_cap |
63
+ | cetus_clmm::factory | 12 | Coin type not allowed | create_pool_v2_ |
64
+ | cetus_clmm::factory | 13 | Cap not match with coin type | unregister_permission_pair_internal,register_permission_pair_internal |
65
+ | cetus_clmm::factory | 14 | Coin already exists in list | add_denied_coin, add_allowed_list |
66
+ | cetus_clmm::factory | 15 | Coin not exists in list | remove_denied_list,remove_allowed_list |
67
+ | cetus_clmm::factory | 16 | Liquidity check failed | create_pool_v2_ |
68
+ | cetus_clmm::factory | 17 | Tick spacing not exists in fee tier | add_allowed_pair_config |
69
+
@@ -0,0 +1,92 @@
1
+ # Getting CLMM Pools
2
+
3
+ ## 1. Get All Pools
4
+
5
+ Use `sdk.Pool.getPoolsWithPage()` method to retrieve all pools.
6
+
7
+ ### Parameters
8
+
9
+ - `pagination_args`: Default to get all pool lists, supports pagination
10
+
11
+ ### Example
12
+
13
+ ```typescript
14
+ async function getAllPools() {
15
+ const pools = await sdk.Pool.getPoolsWithPage()
16
+ console.log(`pool length: ${pools.length}`)
17
+ }
18
+ ```
19
+
20
+ ## 2. Batch Get assign Pools
21
+
22
+ Use `sdk.Pool.getAssignPools()` method to retrieve specific pools.
23
+
24
+ ### Parameters
25
+
26
+ - `assign_pools`: An array of pool ID to get.
27
+
28
+ ### Example
29
+
30
+ ```typescript
31
+ const pools = await sdk.Pool.getAssignPools(['0x0...'])
32
+ console.log(pools)
33
+ ```
34
+
35
+ ## 3. Get Single Pool
36
+
37
+ Use `sdk.Pool.getPool()` method to retrieve a specific pool.
38
+
39
+ ### Parameters
40
+
41
+ - `pool_id`: Pool address
42
+ - `force_refresh`: Optional boolean to refresh cache
43
+
44
+ ### Example
45
+
46
+ ```typescript
47
+ const pool = await sdk.Pool.getPool('0x0...')
48
+ console.log({ pool })
49
+ ```
50
+
51
+ ## 4. Get Pool by Coin Types
52
+
53
+ Use `sdk.Pool.getPoolByCoins()` method to find pools by coin types.
54
+
55
+ ### Parameters
56
+
57
+ - `coins`: Array of coin types
58
+ - `fee_rate`: Optional fee rate number
59
+
60
+ ### Example
61
+
62
+ ```typescript
63
+ const coin_type_a = '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN'
64
+ const coin_type_b = '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN'
65
+
66
+ const pools = await sdk.Pool.getPoolByCoins([coin_type_a, coin_type_b])
67
+ ```
68
+
69
+ ## 5. Notes
70
+
71
+ Some common methods for pool
72
+
73
+ ### 1. Convert SqrtPrice to Price
74
+
75
+ Use `TickMath.sqrtPriceX64ToPrice()` method to convert a given sqrtPrice to a price.
76
+
77
+ ### Parameters
78
+
79
+ - `sqrt_price_x64`: The sqrtPrice value to convert.
80
+ - `decimals_a`: The number of decimals for coin A.
81
+ - `decimals_b`: The number of decimals for coin B.
82
+
83
+ ### Example
84
+
85
+ ```typescript
86
+ const sqrt_price_x64 = '18446744073709551616'
87
+ const decimals_a = 6
88
+ const decimals_b = 9
89
+
90
+ const price = TickMath.sqrtPriceX64ToPrice(new BN(sqrt_price_x64), decimals_a, decimals_b)
91
+ console.log('Price:', price.toString())
92
+ ```