@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.
- package/.turbo/turbo-build.log +11100 -0
- package/README.md +108 -0
- package/dist/index.d.mts +2251 -0
- package/dist/index.d.ts +2251 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +13 -0
- package/dist/index.mjs.map +1 -0
- package/docs/add_liquidity.md +145 -0
- package/docs/close_position.md +57 -0
- package/docs/collect_fees.md +37 -0
- package/docs/create_clmm_pool.md +228 -0
- package/docs/error_code.md +69 -0
- package/docs/get_clmm_pools.md +92 -0
- package/docs/get_positions.md +70 -0
- package/docs/get_reward.md +53 -0
- package/docs/get_ticks.md +39 -0
- package/docs/migrate_to_version_6.0.md +143 -0
- package/docs/open_position.md +224 -0
- package/docs/partner_swap.md +60 -0
- package/docs/pre_swap.md +136 -0
- package/docs/remove_liquidity.md +124 -0
- package/docs/swap.md +153 -0
- package/docs/utils.md +85 -0
- package/package.json +37 -0
- package/src/config/index.ts +2 -0
- package/src/config/mainnet.ts +41 -0
- package/src/config/testnet.ts +40 -0
- package/src/errors/errors.ts +93 -0
- package/src/errors/index.ts +1 -0
- package/src/index.ts +10 -0
- package/src/math/apr.ts +167 -0
- package/src/math/index.ts +1 -0
- package/src/modules/configModule.ts +540 -0
- package/src/modules/index.ts +5 -0
- package/src/modules/poolModule.ts +1066 -0
- package/src/modules/positionModule.ts +932 -0
- package/src/modules/rewarderModule.ts +430 -0
- package/src/modules/swapModule.ts +389 -0
- package/src/sdk.ts +131 -0
- package/src/types/clmm_type.ts +1002 -0
- package/src/types/clmmpool.ts +366 -0
- package/src/types/config_type.ts +241 -0
- package/src/types/index.ts +8 -0
- package/src/types/sui.ts +124 -0
- package/src/types/token_type.ts +189 -0
- package/src/utils/common.ts +426 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/positionUtils.ts +434 -0
- package/src/utils/swapUtils.ts +499 -0
- package/tests/add_liquidity.test.ts +121 -0
- package/tests/add_liquidity_fix_token.test.ts +182 -0
- package/tests/apr.test.ts +71 -0
- package/tests/cetus_config.test.ts +26 -0
- package/tests/collect_fees.test.ts +11 -0
- package/tests/pool.test.ts +267 -0
- package/tests/position.test.ts +145 -0
- package/tests/remove_liquidity.test.ts +119 -0
- package/tests/rewarder.test.ts +60 -0
- package/tests/sdk_config.test.ts +49 -0
- package/tests/swap.test.ts +254 -0
- package/tests/tsconfig.json +26 -0
- package/tsconfig.json +5 -0
- package/tsup.config.ts +10 -0
package/docs/pre_swap.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Pre Swap
|
|
2
|
+
|
|
3
|
+
Before performing an actual swap, you can do a pre-swap to get the swap result. Then you can set amount limit by swap result and slippage.
|
|
4
|
+
|
|
5
|
+
This text describes two primary methods for performing a swap function, each with distinct steps and calculation methods:
|
|
6
|
+
|
|
7
|
+
1. The first method involves initially obtaining tick data, followed by performing calculations locally
|
|
8
|
+
2. The second method involves conducting a simulated swap and then obtaining the resultant data through an event on Sui
|
|
9
|
+
|
|
10
|
+
There are three pre-calculation strategies for executing a swap:
|
|
11
|
+
|
|
12
|
+
1. Local Calculate
|
|
13
|
+
2. Simulate swap then get result
|
|
14
|
+
- Single pool swap result: use `sdk.Swap.preSwap()`
|
|
15
|
+
- Multi pool calculation: use `sdk.Swap.preSwapWithMultiPool()`
|
|
16
|
+
|
|
17
|
+
## Local Calculate Swap Result
|
|
18
|
+
|
|
19
|
+
This method requires getting ticks data and pool object first using `sdk.Swap.calculateRates` method.
|
|
20
|
+
|
|
21
|
+
### Function Parameters
|
|
22
|
+
|
|
23
|
+
- `params`: CalculateRatesParams object
|
|
24
|
+
- `decimals_a`: the decimal of coinA
|
|
25
|
+
- `decimals_b`: the decimal of coinB
|
|
26
|
+
- `a2b`: swap direction, true means swap from coinA to coinB, false means swap from coinB to CoinA
|
|
27
|
+
- `by_amount_in`: true means fixed the amount of input, false means fixed the amount of output
|
|
28
|
+
- `amount`: the amount of input (by_amount_in = true) or output (by_amount_in = false)
|
|
29
|
+
- `swap_ticks`: the array of TickData, get them by `sdk.Pool.fetchTicks()`
|
|
30
|
+
- `current_pool`: the pool object, get it by `sdk.Pool.getPool()`
|
|
31
|
+
|
|
32
|
+
### Example
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
const a2b = false
|
|
36
|
+
const pool = await sdk.Pool.getPool('0xc8d7a1503dc2f9f5b05449a87d8733593e2f0f3e7bffd90541252782e4d2ca20')
|
|
37
|
+
const by_amount_in = false
|
|
38
|
+
const amount = '80000000000000'
|
|
39
|
+
|
|
40
|
+
const swap_ticks = await sdk.Pool.fetchTicks({
|
|
41
|
+
pool_id: pool.id,
|
|
42
|
+
coin_type_a: pool.coin_type_a,
|
|
43
|
+
coin_type_b: pool.coin_type_b,
|
|
44
|
+
})
|
|
45
|
+
// or
|
|
46
|
+
// const swapTicks = await sdk.Pool.fetchTicksByRpc(pool.ticks_handle)
|
|
47
|
+
|
|
48
|
+
const res = sdk.Swap.calculateRates({
|
|
49
|
+
decimals_a: 6,
|
|
50
|
+
decimals_b: 6,
|
|
51
|
+
a2b,
|
|
52
|
+
by_amount_in,
|
|
53
|
+
amount: new BN(amount),
|
|
54
|
+
swap_ticks,
|
|
55
|
+
current_pool: pool,
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## PreSwap by Simulation Transaction
|
|
60
|
+
|
|
61
|
+
### preSwap
|
|
62
|
+
|
|
63
|
+
Use `sdk.Swap.preSwap` method.
|
|
64
|
+
|
|
65
|
+
#### Function Parameters
|
|
66
|
+
|
|
67
|
+
- `pool`: pool object, you can get it by `sdk.Pool.getPool()` method
|
|
68
|
+
- `current_sqrt_price`: pool's current_sqrt_price
|
|
69
|
+
- `coin_type_a`: the coin type address about coinA
|
|
70
|
+
- `coin_type_b`: the coin type address about coinB
|
|
71
|
+
- `decimals_a`: the decimal of coinA
|
|
72
|
+
- `decimals_b`: the decimal of coinB
|
|
73
|
+
- `a2b`: swap direction, true means swap from coinA to coinB, false means swap from coinB to CoinA
|
|
74
|
+
- `by_amount_in`: true means fixed the amount of input, false means fixed the amount of output
|
|
75
|
+
- `amount`: the amount of input (by_amount_in = true) or output (by_amount_in = false)
|
|
76
|
+
|
|
77
|
+
#### Example
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
const a2b = true
|
|
81
|
+
const by_amount_in = true
|
|
82
|
+
const amount = '10000000'
|
|
83
|
+
const slippage = Percentage.fromDecimal(d(0.1))
|
|
84
|
+
|
|
85
|
+
const pool = await sdk.Pool.getPool('0x6fd4915e6d8d3e2ba6d81787046eb948ae36fdfc75dad2e24f0d4aaa2417a416')
|
|
86
|
+
|
|
87
|
+
const res = await sdk.Swap.preSwap({
|
|
88
|
+
pool,
|
|
89
|
+
current_sqrt_price: : pool.current_sqrt_price,
|
|
90
|
+
coin_type_a: pool.coin_type_a,
|
|
91
|
+
coin_type_b: pool.coin_type_b,
|
|
92
|
+
decimals_a: 6,
|
|
93
|
+
decimals_b: 6,
|
|
94
|
+
a2b,
|
|
95
|
+
by_amount_in,
|
|
96
|
+
amount,
|
|
97
|
+
})
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### preSwapWithMultiPool
|
|
101
|
+
|
|
102
|
+
Use `sdk.Swap.preSwapWithMultiPool()` method.
|
|
103
|
+
|
|
104
|
+
#### Function Parameters
|
|
105
|
+
|
|
106
|
+
- `pool_ids`: An array of pool objects ID. All pools must have the same type
|
|
107
|
+
- `coin_type_a`: the coin type address about coinA
|
|
108
|
+
- `coin_type_b`: the coin type address about coinB
|
|
109
|
+
- `a2b`: swap direction, true means swap from coinA to coinB, false means swap from coinB to CoinA
|
|
110
|
+
- `by_amount_in`: true means fixed the amount of input, false means fixed the amount of output
|
|
111
|
+
- `amount`: the amount of input (by_amount_in = true) or output (by_amount_in = false)
|
|
112
|
+
|
|
113
|
+
#### Example
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const a2b = true
|
|
117
|
+
const pool_ids = [
|
|
118
|
+
'0x53d70570db4f4d8ebc20aa1b67dc6f5d061d318d371e5de50ff64525d7dd5bca',
|
|
119
|
+
'0x4038aea2341070550e9c1f723315624c539788d0ca9212dca7eb4b36147c0fcb',
|
|
120
|
+
'0x6fd4915e6d8d3e2ba6d81787046eb948ae36fdfc75dad2e24f0d4aaa2417a416',
|
|
121
|
+
]
|
|
122
|
+
const pool0 = await sdk.Pool.getPool(pool_ids[0])
|
|
123
|
+
const pool1 = await sdk.Pool.getPool(pool_ids[1])
|
|
124
|
+
const pool2 = await sdk.Pool.getPool(pool_ids[2])
|
|
125
|
+
const by_amount_in = true
|
|
126
|
+
const amount = '10000000'
|
|
127
|
+
|
|
128
|
+
const res_with_multi_pool = await sdk.Swap.preSwapWithMultiPool({
|
|
129
|
+
pool_ids: pool_ids,
|
|
130
|
+
coin_type_a: pool0.coin_type_a,
|
|
131
|
+
coin_type_b: pool0.coin_type_b,
|
|
132
|
+
a2b,
|
|
133
|
+
by_amount_in,
|
|
134
|
+
amount,
|
|
135
|
+
})
|
|
136
|
+
```
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Remove liquidity
|
|
2
|
+
|
|
3
|
+
When you want to adjust the liquidity of your position or withdraw liquidity from the position, you can use the following method.
|
|
4
|
+
|
|
5
|
+
When you withdraw liquidity, you also have the option to collect fees or rewards at the same time. Please refer to the parameter description below for more details.
|
|
6
|
+
|
|
7
|
+
There are two situations:
|
|
8
|
+
|
|
9
|
+
1. remove liquidity with a specified liquidity
|
|
10
|
+
2. remove liquidity with fixed coin amount.
|
|
11
|
+
|
|
12
|
+
## 1. Remove liquidity by inputting liquidity value
|
|
13
|
+
|
|
14
|
+
Use `sdk.Position.removeLiquidityPayload()` method.
|
|
15
|
+
|
|
16
|
+
### Function Parameters
|
|
17
|
+
|
|
18
|
+
- `pool_id`: The object id about which pool you want to operation
|
|
19
|
+
- `pos_id`: The object id about position.
|
|
20
|
+
- `coin_type_a`: The coin type address about coinA
|
|
21
|
+
- `coin_type_b`: The coin type address about coinB
|
|
22
|
+
- `min_amount_a`: The minimum amount of coin A that a user can acquire.
|
|
23
|
+
- `min_amount_b`: The minimum amount of coin B that a user can acquire.
|
|
24
|
+
- `delta_liquidity`: The quantity of liquidity.
|
|
25
|
+
- `collect_fee`: If you already has one position, you can select collect fees while adding liquidity.
|
|
26
|
+
- `rewarder_coin_types`: If these not empty, it will collect rewarder in this position, if you already open the position.
|
|
27
|
+
|
|
28
|
+
### Important Notes
|
|
29
|
+
|
|
30
|
+
- 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
|
|
31
|
+
by adding the amount potentially acquired through calculations to the slippage adjustment.
|
|
32
|
+
|
|
33
|
+
### Example
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
const pool = await sdk.Pool.getPool(pool_id)
|
|
37
|
+
const position = await sdk.Position.getPositionById(pos_id)
|
|
38
|
+
|
|
39
|
+
const lower_tick = Number(position.tick_lower_index)
|
|
40
|
+
const upper_tick = Number(position.tick_upper_index)
|
|
41
|
+
|
|
42
|
+
const lower_sqrt_price = TickMath.tickIndexToSqrtPriceX64(lower_tick)
|
|
43
|
+
const upper_sqrt_price = TickMath.tickIndexToSqrtPriceX64(upper_tick)
|
|
44
|
+
|
|
45
|
+
const liquidity = new BN(position.liquidity)
|
|
46
|
+
const slippage_tolerance = new Percentage(new BN(5), new BN(100))
|
|
47
|
+
const cur_sqrt_price = new BN(pool.current_sqrt_price)
|
|
48
|
+
|
|
49
|
+
const coin_amounts = ClmmPoolUtil.getCoinAmountFromLiquidity(liquidity, cur_sqrt_price, lower_sqrt_price, upper_sqrt_price, false)
|
|
50
|
+
const { coin_amount_limit_a, coin_amount_limit_b } = adjustForCoinSlippage(coin_amounts, slippage_tolerance, false)
|
|
51
|
+
|
|
52
|
+
const reward_coin_types = pool.rewarder_infos.map((rewarder) => rewarder.coin_type)
|
|
53
|
+
|
|
54
|
+
const remove_liquidity_params: RemoveLiquidityParams = {
|
|
55
|
+
coin_type_a: pool.coin_type_a,
|
|
56
|
+
coin_type_b: pool.coin_type_b,
|
|
57
|
+
delta_liquidity: liquidity.toString(),
|
|
58
|
+
min_amount_a: coin_amount_limit_a.toString(),
|
|
59
|
+
min_amount_b: coin_amount_limit_b.toString(),
|
|
60
|
+
pool_id: pool.id,
|
|
61
|
+
pos_id: position.pos_object_id,
|
|
62
|
+
rewarder_coin_types: reward_coin_types,
|
|
63
|
+
collect_fee: true,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const remove_liquidity_payload = await sdk.Position.removeLiquidityPayload(remove_liquidity_params)
|
|
67
|
+
const send_key_pair = 'The key pair generated by your private key'
|
|
68
|
+
const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, remove_liquidity_payload, true)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 2. Remove liquidity with a fixed coin amount
|
|
72
|
+
|
|
73
|
+
Use `sdk.Position.removeLiquidityPayload()` method.
|
|
74
|
+
|
|
75
|
+
### Function Parameters
|
|
76
|
+
|
|
77
|
+
- `pool_id`: The object id about which pool you want to operation
|
|
78
|
+
- `pos_id`: The object id about position.
|
|
79
|
+
- `coin_type_a`: The coin type address about coinA
|
|
80
|
+
- `coin_type_b`: The coin type address about coinB
|
|
81
|
+
- `min_amount_a`: The minimum amount of coin A that a user can acquire.
|
|
82
|
+
- `min_amount_b`: The minimum amount of coin B that a user can acquire.
|
|
83
|
+
- `delta_liquidity`: The quantity of liquidity.
|
|
84
|
+
- `collect_fee`: If you already has one position, you can select collect fees while adding liquidity.
|
|
85
|
+
- `rewarder_coin_types`: If these not empty, it will collect rewarder in this position, if you already open the position.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
const pool = await sdk.Pool.getPool(pool_id)
|
|
89
|
+
const position = await sdk.Position.getPositionById(pos_id)
|
|
90
|
+
const lower_tick = position.tick_lower_index
|
|
91
|
+
const upper_tick = position.tick_upper_index
|
|
92
|
+
const coin_amount = new BN(592)
|
|
93
|
+
const fix_amount_a = true
|
|
94
|
+
const slippage = 0.05
|
|
95
|
+
const cur_sqrt_price = new BN(pool.current_sqrt_price)
|
|
96
|
+
|
|
97
|
+
const liquidity_input = ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts(
|
|
98
|
+
lower_tick,
|
|
99
|
+
upper_tick,
|
|
100
|
+
coin_amount,
|
|
101
|
+
fix_amount_a,
|
|
102
|
+
false,
|
|
103
|
+
slippage,
|
|
104
|
+
cur_sqrt_price
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
const liquidity = liquidity_input.liquidity_amount.toString()
|
|
108
|
+
|
|
109
|
+
const remove_liquidity_params: RemoveLiquidityParams = {
|
|
110
|
+
coin_type_a: pool.coin_type_a,
|
|
111
|
+
coin_type_b: pool.coin_type_b,
|
|
112
|
+
delta_liquidity: liquidity,
|
|
113
|
+
min_amount_a: liquidity_input.coin_amount_limit_a,
|
|
114
|
+
min_amount_b: liquidity_input.coin_amount_limit_b,
|
|
115
|
+
pool_id: pool.id,
|
|
116
|
+
pos_id: position.pos_object_id,
|
|
117
|
+
rewarder_coin_types: [],
|
|
118
|
+
collect_fee: true,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const payload = await sdk.Position.removeLiquidityPayload(remove_liquidity_params)
|
|
122
|
+
|
|
123
|
+
const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, payload, true)
|
|
124
|
+
```
|
package/docs/swap.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Swap
|
|
2
|
+
|
|
3
|
+
Swaps typically occur in two steps:
|
|
4
|
+
|
|
5
|
+
1. The first step involves pre-calculating the potential result of the current transaction
|
|
6
|
+
2. The second step is to set the slippage based on the pre-calculated results, followed by executing the transaction
|
|
7
|
+
|
|
8
|
+
## Swap after preSwap
|
|
9
|
+
|
|
10
|
+
After pre-calculating, you can perform a swap. For a more detailed understanding of the pre-swap process and its intricacies, additional information is available [here](pre_swap.md).
|
|
11
|
+
|
|
12
|
+
### Function input parameters
|
|
13
|
+
|
|
14
|
+
Please refer to the original function for specific parameter types.
|
|
15
|
+
|
|
16
|
+
- `pool_id`: pool object id, you can get it by pre-calculating
|
|
17
|
+
- `coin_type_a`: the coin type address about coinA
|
|
18
|
+
- `coin_type_b`: the coin type address about coinB
|
|
19
|
+
- `a2b`: swap direction, true means swap from coinA to coinB, false means swap from coinB to CoinA
|
|
20
|
+
- `by_amount_in`: true means fixed the amount of input, false means fixed the amount of output
|
|
21
|
+
- `amount`: the amount of input (byAmountIn = true) or output (byAmountIn = false)
|
|
22
|
+
- `amount_limit`: the amount limit of coin what you get. There are two scenarios in amount limit:
|
|
23
|
+
- When `by_amount_in` equals true: amount limit means minimum number of outputs required to be obtained
|
|
24
|
+
- When `by_amount_in` equals false: it means maximum number of input coin
|
|
25
|
+
- `partner`: The partner address. If you do not have a partner, simply leave the partner field unset
|
|
26
|
+
|
|
27
|
+
### Important Notes
|
|
28
|
+
|
|
29
|
+
- This is the amount out of result after slippage adjustment. Use `adjustForSlippage` to calculate the limit of amount out
|
|
30
|
+
- If you set amount limit equal 0, when you trade during extremely volatile price fluctuations, you might end up with a very small trading outcome. The `amount_limit` will help prevent your assets from incurring losses
|
|
31
|
+
- You can get more details in these [Partner swap](partner_swap.md) parts
|
|
32
|
+
|
|
33
|
+
### Example
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
const a2b = true
|
|
37
|
+
// fix input token amount
|
|
38
|
+
const coin_amount = new BN(120000)
|
|
39
|
+
const by_amount_in = true
|
|
40
|
+
// slippage value
|
|
41
|
+
const slippage = Percentage.fromDecimal(d(5))
|
|
42
|
+
|
|
43
|
+
// Fetch pool data
|
|
44
|
+
const pool = await sdk.Pool.getPool(pool_id)
|
|
45
|
+
|
|
46
|
+
// Estimated amountIn amountOut fee
|
|
47
|
+
const res: any = await sdk.Swap.preSwap({
|
|
48
|
+
pool_id: pool.id,
|
|
49
|
+
current_sqrt_price: pool.current_sqrt_price,
|
|
50
|
+
coin_type_a: pool.coin_type_a,
|
|
51
|
+
coin_type_b: pool.coin_type_b,
|
|
52
|
+
decimals_a: 6, // coin a 's decimals
|
|
53
|
+
decimals_b: 8, // coin b 's decimals
|
|
54
|
+
a2b,
|
|
55
|
+
by_amount_in, // fix token a amount
|
|
56
|
+
amount,
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const partner = '0x8e0b7668a79592f70fbfb1ae0aebaf9e2019a7049783b9a4b6fe7c6ae038b528'
|
|
60
|
+
|
|
61
|
+
const to_amount = by_amount_in ? res.estimated_amount_out : res.estimated_amount_in
|
|
62
|
+
const amount_limit = adjustForSlippage(to_amount, slippage, !by_amount_in)
|
|
63
|
+
|
|
64
|
+
// build swap Payload
|
|
65
|
+
const swap_payload = sdk.Swap.createSwapPayload({
|
|
66
|
+
pool_id: pool.id,
|
|
67
|
+
coin_type_a: pool.coin_type_a,
|
|
68
|
+
coin_type_b: pool.coin_type_b,
|
|
69
|
+
a2b: a2b,
|
|
70
|
+
by_amount_in,
|
|
71
|
+
amount: res.amount.toString(),
|
|
72
|
+
amount_limit: amount_limit.toString(),
|
|
73
|
+
swap_partner: partner,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
const swap_txn = await sdk.fullClient.sendTransaction(signer, swap_payload)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Swap without transfer coins
|
|
80
|
+
|
|
81
|
+
This method supports returning two coins for user to build PTB.
|
|
82
|
+
|
|
83
|
+
### Function input parameters
|
|
84
|
+
|
|
85
|
+
Please refer to the original function for specific parameter types.
|
|
86
|
+
|
|
87
|
+
- `pool_id`: pool object id, you can get it by pre-calculating
|
|
88
|
+
- `coin_type_a`: the coin type address about coinA
|
|
89
|
+
- `coin_type_b`: the coin type address about coinB
|
|
90
|
+
- `a2b`: swap direction, true means swap from coinA to coinB, false means swap from coinB to CoinA
|
|
91
|
+
- `by_amount_in`: true means fixed the amount of input, false means fixed the amount of output
|
|
92
|
+
- `amount`: the amount of input (byAmountIn = true) or output (byAmountIn = false)
|
|
93
|
+
- `amount_limit`: the amount limit of coin what you get. There are two scenarios in amount limit:
|
|
94
|
+
- When `by_amount_in` equals true: amount limit means minimum number of outputs required to be obtained
|
|
95
|
+
- When `by_amount_in` equals false: it means maximum number of input coin
|
|
96
|
+
- `partner`: The partner address. If you do not have a partner, simply leave the partner field unset
|
|
97
|
+
|
|
98
|
+
### Important Notes
|
|
99
|
+
|
|
100
|
+
- This is the amount out of result after slippage adjustment. Use `adjustForSlippage` to calculate the limit of amount out
|
|
101
|
+
- If you set amount limit equal 0, when you trade during extremely volatile price fluctuations, you might end up with a very small trading outcome. The `amount_limit` will help prevent your assets from incurring losses
|
|
102
|
+
- You can get more details in these [Partner swap](#) parts
|
|
103
|
+
|
|
104
|
+
### Example
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// Whether the swap direction is token a to token b
|
|
108
|
+
const a2b = true
|
|
109
|
+
// fix input token amount
|
|
110
|
+
const amount = new BN(120000)
|
|
111
|
+
// input token amount is token a
|
|
112
|
+
const by_amount_in = true
|
|
113
|
+
// slippage value
|
|
114
|
+
const slippage = Percentage.fromDecimal(d(5))
|
|
115
|
+
|
|
116
|
+
// Fetch pool data
|
|
117
|
+
const pool = await sdk.Pool.getPool(pool_id)
|
|
118
|
+
|
|
119
|
+
// Estimated amountIn amountOut fee
|
|
120
|
+
const res: any = await sdk.Swap.preSwap({
|
|
121
|
+
pool_id: pool,
|
|
122
|
+
current_sqrt_price: pool.current_sqrt_price,
|
|
123
|
+
coin_type_a: pool.coin_type_a,
|
|
124
|
+
coin_type_b: pool.coin_type_b,
|
|
125
|
+
decimals_a: 6, // coin a 's decimals
|
|
126
|
+
decimals_b: 8, // coin b 's decimals
|
|
127
|
+
a2b,
|
|
128
|
+
by_amount_in,
|
|
129
|
+
amount,
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const partner = '0x8e0b7668a79592f70fbfb1ae0aebaf9e2019a7049783b9a4b6fe7c6ae038b528'
|
|
133
|
+
|
|
134
|
+
const to_amount = by_amount_in ? res.estimated_amount_out : res.estimated_amount_in
|
|
135
|
+
const amount_limit = adjustForSlippage(toAmount, slippage, !by_amount_in)
|
|
136
|
+
|
|
137
|
+
// build swap Tx
|
|
138
|
+
const swap_payload = sdk.Swap.createSwapWithoutTransferCoinsPayload({
|
|
139
|
+
pool_id: pool.id,
|
|
140
|
+
coin_type_a: pool.coin_type_a,
|
|
141
|
+
coin_type_b: pool.coin_type_b,
|
|
142
|
+
a2b: a2b,
|
|
143
|
+
by_amount_in,
|
|
144
|
+
amount: res.amount.toString(),
|
|
145
|
+
amount_limit: amount_limit.toString(),
|
|
146
|
+
swap_partner: partner,
|
|
147
|
+
})
|
|
148
|
+
const { tx, coin_ab_s } = swap_payload
|
|
149
|
+
// transfer coin a and coin b
|
|
150
|
+
tx.transferObjects(coins, tx.pure.address(recipient))
|
|
151
|
+
|
|
152
|
+
const transfer_txn = await sdk.fullClient.sendTransaction(signer, swap_payload)
|
|
153
|
+
```
|
package/docs/utils.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Utility Methods and Helper Functions
|
|
2
|
+
|
|
3
|
+
This document provides an overview of commonly used utility methods and helper functions in the Cetus SDK.
|
|
4
|
+
|
|
5
|
+
## Core Concepts
|
|
6
|
+
|
|
7
|
+
### Price, Tick Index, and Sqrt Price
|
|
8
|
+
|
|
9
|
+
| Concept | Definition | Features | Application |
|
|
10
|
+
| ---------- | ------------------------------------------ | -------------------------------------------------- | ----------------------------------------------------- |
|
|
11
|
+
| Price | Token exchange ratio (e.g., token1/token0) | Continuous value, updates in real-time | Directly determines trading rates |
|
|
12
|
+
| Tick Index | Discretized price interval index | Spacing determined by fee tiers | Manages liquidity distribution ranges |
|
|
13
|
+
| Sqrt Price | Square root of price | Stored as fixed-point numbers (e.g., sqrtPriceX64) | Simplifies on-chain calculations, improves efficiency |
|
|
14
|
+
|
|
15
|
+
#### Notes:
|
|
16
|
+
|
|
17
|
+
1. **Price**
|
|
18
|
+
|
|
19
|
+
- Represents the real-time ratio between two tokens (e.g., ETH/USDC)
|
|
20
|
+
|
|
21
|
+
2. **Tick Index**
|
|
22
|
+
|
|
23
|
+
- Derived from P = 1.0001^i, where i is the Tick Index
|
|
24
|
+
- Liquidity can only be provided at discrete Ticks (e.g., multiples of 10)
|
|
25
|
+
|
|
26
|
+
3. **Sqrt Price**
|
|
27
|
+
- Used for computational efficiency (avoids floating-point operations)
|
|
28
|
+
- In Uniswap V3, stored as sqrtPriceX64 (Q64 fixed-point format)
|
|
29
|
+
|
|
30
|
+
## 1.Tick index to price
|
|
31
|
+
|
|
32
|
+
when you want to open position, you don't know how to set your tick_lower and tick_upper.
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { TickMath } from '@cetusprotocol/common-sdk'
|
|
36
|
+
// decimalsA and decimalsB means the decimal of coinA and coinB
|
|
37
|
+
const price = TickMath.tickIndexToPrice(tick_index, decimals_a, decimals_b)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 2.Price to tick index
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { TickMath } from '@cetusprotocol/common-sdk'
|
|
44
|
+
// decimalsA and decimalsB means the decimal of coinA and coinB
|
|
45
|
+
const price = TickMath.priceToTickIndex(tick_index, decimals_a, decimals_b)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 3.Tick index to sqrt price x64
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { TickMath } from '@cetusprotocol/common-sdk'
|
|
52
|
+
const sqrt_price_x64 = TickMath.tickIndexToSqrtPriceX64(tick_index)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 4. Sqrt price x64 to tick index
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { TickMath } from '@cetusprotocol/common-sdk'
|
|
59
|
+
const tick_index = TickMath.sqrtPriceX64ToTickIndex(sqrt_price_x64)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 5. Price to sqrt price
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { TickMath } from '@cetusprotocol/common-sdk'
|
|
66
|
+
const sqrt_price_x64 = TickMath.priceToSqrtPriceX64(price, decimals_a, decimals_b)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 6. Sqrt price to price
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { TickMath } from '@cetusprotocol/common-sdk'
|
|
73
|
+
const price = TickMath.sqrtPriceX64ToPrice(sqrt_price_x64, decimals_a, decimals_b)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 7. Convert the tick index from i32 to u32
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { asUintN } from '@cetusprotocol/common-sdk'
|
|
80
|
+
const tick_lower_i32 = -100
|
|
81
|
+
const tick_lower_u32 = asUintN(BigInt(tick_lower_i32)).toString()
|
|
82
|
+
|
|
83
|
+
const tick_upper_i32 = 100
|
|
84
|
+
const tick_upper_u32 = asUintN(BigInt(tick_upper_i32)).toString()
|
|
85
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cetusprotocol/sui-clmm-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "SDK for cetus swap and liquidity",
|
|
5
|
+
"typings": "dist/index.d.ts",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "jest",
|
|
10
|
+
"lint": "eslint src/*.ts src/**/*.ts",
|
|
11
|
+
"lint:fix": "eslint src/*.ts src/**/*.ts --fix",
|
|
12
|
+
"build": "pnpm run build:tsup",
|
|
13
|
+
"build:tsup": "pnpm run build:clean && pnpm run _build:node",
|
|
14
|
+
"build:clean": "rm -rf dist",
|
|
15
|
+
"_build:browser": "tsup --platform browser --format iife --global-name cetusAptosSDK --minify",
|
|
16
|
+
"_build:node": "tsup --format cjs,esm --dts",
|
|
17
|
+
"build:doc": "npx typedoc",
|
|
18
|
+
"publish_batch:test": "npm publish --tag experimental",
|
|
19
|
+
"publish:test": "node ../../scripts/version.js clmm && npm publish --tag experimental"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": ""
|
|
24
|
+
},
|
|
25
|
+
"keywords": [],
|
|
26
|
+
"author": "test",
|
|
27
|
+
"license": "Apache-2.0",
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@cetusprotocol/common-sdk": "workspace:*",
|
|
30
|
+
"@cetusprotocol/test-utils": "workspace:*"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@cetusprotocol/common-sdk": ">=1.0.0",
|
|
34
|
+
"@mysten/bcs": "^1.5.0",
|
|
35
|
+
"@mysten/sui": "^1.24.0"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FullRpcUrlMainnet } from '@cetusprotocol/common-sdk'
|
|
2
|
+
import { CetusClmmSDK, SdkOptions } from '../sdk'
|
|
3
|
+
const SDKConfig = {
|
|
4
|
+
clmmConfig: {
|
|
5
|
+
pools_id: '0xf699e7f2276f5c9a75944b37a0c5b5d9ddfd2471bf6242483b03ab2887d198d0',
|
|
6
|
+
global_config_id: '0xdaa46292632c3c4d8f31f23ea0f9b36a28ff3677e9684980e4438403a67a3d8f',
|
|
7
|
+
global_vault_id: '0xce7bceef26d3ad1f6d9b6f13a953f053e6ed3ca77907516481ce99ae8e588f2b',
|
|
8
|
+
admin_cap_id: '0x89c1a321291d15ddae5a086c9abc533dff697fde3d89e0ca836c41af73e36a75',
|
|
9
|
+
},
|
|
10
|
+
cetusConfig: {
|
|
11
|
+
coin_list_id: '0x8cbc11d9e10140db3d230f50b4d30e9b721201c0083615441707ffec1ef77b23',
|
|
12
|
+
launchpad_pools_id: '0x1098fac992eab3a0ab7acf15bb654fc1cf29b5a6142c4ef1058e6c408dd15115',
|
|
13
|
+
clmm_pools_id: '0x15b6a27dd9ae03eb455aba03b39e29aad74abd3757b8e18c0755651b2ae5b71e',
|
|
14
|
+
admin_cap_id: '0x39d78781750e193ce35c45ff32c6c0c3f2941fa3ddaf8595c90c555589ddb113',
|
|
15
|
+
global_config_id: '0x0408fa4e4a4c03cc0de8f23d0c2bbfe8913d178713c9a271ed4080973fe42d8f',
|
|
16
|
+
coin_list_handle: '0x49136005e90e28c4695419ed4194cc240603f1ea8eb84e62275eaff088a71063',
|
|
17
|
+
launchpad_pools_handle: '0x5e194a8efcf653830daf85a85b52e3ae8f65dc39481d54b2382acda25068375c',
|
|
18
|
+
clmm_pools_handle: '0x37f60eb2d9d227949b95da8fea810db3c32d1e1fa8ed87434fc51664f87d83cb',
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// mainnet
|
|
23
|
+
export const clmmMainnet: SdkOptions = {
|
|
24
|
+
env: 'mainnet',
|
|
25
|
+
full_rpc_url: FullRpcUrlMainnet,
|
|
26
|
+
cetus_config: {
|
|
27
|
+
package_id: '0x95b8d278b876cae22206131fb9724f701c9444515813042f54f0a426c9a3bc2f',
|
|
28
|
+
published_at: '0x95b8d278b876cae22206131fb9724f701c9444515813042f54f0a426c9a3bc2f',
|
|
29
|
+
config: SDKConfig.cetusConfig,
|
|
30
|
+
},
|
|
31
|
+
clmm_pool: {
|
|
32
|
+
package_id: '0x1eabed72c53feb3805120a081dc15963c204dc8d091542592abaf7a35689b2fb',
|
|
33
|
+
published_at: '0xc6faf3703b0e8ba9ed06b7851134bbbe7565eb35ff823fd78432baa4cbeaa12e',
|
|
34
|
+
config: SDKConfig.clmmConfig,
|
|
35
|
+
},
|
|
36
|
+
integrate: {
|
|
37
|
+
package_id: '0x996c4d9480708fb8b92aa7acf819fb0497b5ec8e65ba06601cae2fb6db3312c3',
|
|
38
|
+
published_at: '0x2d8c2e0fc6dd25b0214b3fa747e0fd27fd54608142cd2e4f64c1cd350cc4add4',
|
|
39
|
+
},
|
|
40
|
+
stats_pools_url: 'https://api-sui.cetus.zone/v2/sui/stats_pools',
|
|
41
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { FullRpcUrlTestnet } from '@cetusprotocol/common-sdk'
|
|
2
|
+
import { CetusClmmSDK, SdkOptions } from '../sdk'
|
|
3
|
+
const SDKConfig = {
|
|
4
|
+
clmmConfig: {
|
|
5
|
+
pools_id: '0x50eb61dd5928cec5ea04711a2e9b72e5237e79e9fbcd2ce3d5469dc8708e0ee2',
|
|
6
|
+
global_config_id: '0x9774e359588ead122af1c7e7f64e14ade261cfeecdb5d0eb4a5b3b4c8ab8bd3e',
|
|
7
|
+
global_vault_id: '0xf78d2ee3c312f298882cb680695e5e8c81b1d441a646caccc058006c2851ddea',
|
|
8
|
+
admin_cap_id: '0xa456f86a53fc31e1243f065738ff1fc93f5a62cc080ff894a0fb3747556a799b',
|
|
9
|
+
},
|
|
10
|
+
cetusConfig: {
|
|
11
|
+
coin_list_id: '0x257eb2ba592a5480bba0a97d05338fab17cc3283f8df6998a0e12e4ab9b84478',
|
|
12
|
+
launchpad_pools_id: '0xdc3a7bd66a6dcff73c77c866e87d73826e446e9171f34e1c1b656377314f94da',
|
|
13
|
+
clmm_pools_id: '0x26c85500f5dd2983bf35123918a144de24e18936d0b234ef2b49fbb2d3d6307d',
|
|
14
|
+
admin_cap_id: '0x1a496f6c67668eb2c27c99e07e1d61754715c1acf86dac45020c886ac601edb8',
|
|
15
|
+
global_config_id: '0xe1f3db327e75f7ec30585fa52241edf66f7e359ef550b533f89aa1528dd1be52',
|
|
16
|
+
coin_list_handle: '0x3204350fc603609c91675e07b8f9ac0999b9607d83845086321fca7f469de235',
|
|
17
|
+
launchpad_pools_handle: '0xae67ff87c34aceea4d28107f9c6c62e297a111e9f8e70b9abbc2f4c9f5ec20fd',
|
|
18
|
+
clmm_pools_handle: '0xd28736923703342b4752f5ed8c2f2a5c0cb2336c30e1fed42b387234ce8408ec',
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const clmmTestnet: SdkOptions = {
|
|
23
|
+
env: 'testnet',
|
|
24
|
+
full_rpc_url: FullRpcUrlTestnet,
|
|
25
|
+
cetus_config: {
|
|
26
|
+
package_id: '0xf5ff7d5ba73b581bca6b4b9fa0049cd320360abd154b809f8700a8fd3cfaf7ca',
|
|
27
|
+
published_at: '0xf5ff7d5ba73b581bca6b4b9fa0049cd320360abd154b809f8700a8fd3cfaf7ca',
|
|
28
|
+
config: SDKConfig.cetusConfig,
|
|
29
|
+
},
|
|
30
|
+
clmm_pool: {
|
|
31
|
+
package_id: '0x0c7ae833c220aa73a3643a0d508afa4ac5d50d97312ea4584e35f9eb21b9df12',
|
|
32
|
+
published_at: '0x85e61285a10efc6602ab00df70a0c06357c384ef4c5633ecf73016df1500c704',
|
|
33
|
+
config: SDKConfig.clmmConfig,
|
|
34
|
+
},
|
|
35
|
+
integrate: {
|
|
36
|
+
package_id: '0x2918cf39850de6d5d94d8196dc878c8c722cd79db659318e00bff57fbb4e2ede',
|
|
37
|
+
published_at: '0x19dd42e05fa6c9988a60d30686ee3feb776672b5547e328d6dab16563da65293',
|
|
38
|
+
},
|
|
39
|
+
stats_pools_url: 'https://api-sui.devcetus.com/v2/sui/stats_pools',
|
|
40
|
+
}
|