@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
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { BaseError } from '@cetusprotocol/common-sdk'
|
|
2
|
+
|
|
3
|
+
export enum SwapErrorCode {
|
|
4
|
+
InvalidSqrtPriceLimitDirection = `InvalidSqrtPriceLimitDirection`,
|
|
5
|
+
ZeroTradableAmount = `ZeroTradableAmount`,
|
|
6
|
+
AmountOutBelowMinimum = `AmountOutBelowMinimum`,
|
|
7
|
+
AmountInAboveMaximum = `AmountInAboveMaximum`,
|
|
8
|
+
NextTickNotFound = `NextTickNotFound`,
|
|
9
|
+
TickArraySequenceInvalid = `TickArraySequenceInvalid`,
|
|
10
|
+
TickArrayCrossingAboveMax = `TickArrayCrossingAboveMax`,
|
|
11
|
+
TickArrayIndexNotInitialized = `TickArrayIndexNotInitialized`,
|
|
12
|
+
ParamsLengthNotEqual = `ParamsLengthNotEqual`,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export enum PositionErrorCode {
|
|
16
|
+
InvalidTickEvent = `InvalidTickEvent`,
|
|
17
|
+
InvalidPositionObject = `InvalidPositionObject`,
|
|
18
|
+
InvalidPositionRewardObject = `InvalidPositionRewardObject`,
|
|
19
|
+
InvalidParams = `InvalidParams`,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export enum PoolErrorCode {
|
|
23
|
+
InvalidCoinTypeSequence = `InvalidCoinTypeSequence`,
|
|
24
|
+
InvalidTickIndex = `InvalidTickIndex`,
|
|
25
|
+
InvalidPoolObject = `InvalidPoolObject`,
|
|
26
|
+
InvalidTickObjectId = `InvalidTickObjectId`,
|
|
27
|
+
InvalidTickObject = `InvalidTickObject`,
|
|
28
|
+
InvalidTickFields = `InvalidTickFields`,
|
|
29
|
+
PoolsNotFound = `PoolsNotFound`,
|
|
30
|
+
StatsPoolsUrlNotSet = `StatsPoolsUrlNotSet`,
|
|
31
|
+
FetchError = `FetchError`,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export enum PartnerErrorCode {
|
|
35
|
+
NotFoundPartnerObject = `NotFoundPartnerObject`,
|
|
36
|
+
InvalidPartnerRefFeeFields = `InvalidPartnerRefFeeFields`,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export enum ConfigErrorCode {
|
|
40
|
+
InvalidConfig = `InvalidConfig`,
|
|
41
|
+
InvalidConfigHandle = `InvalidConfigHandle`,
|
|
42
|
+
InvalidSimulateAccount = `InvalidSimulateAccount`,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export enum UtilsErrorCode {
|
|
46
|
+
InvalidSendAddress = `InvalidSendAddress`,
|
|
47
|
+
InvalidRecipientAddress = `InvalidRecipientAddress`,
|
|
48
|
+
InvalidRecipientAndAmountLength = `InvalidRecipientAndAmountLength`,
|
|
49
|
+
InsufficientBalance = `InsufficientBalance`,
|
|
50
|
+
InvalidTarget = `InvalidTarget`,
|
|
51
|
+
InvalidTransactionBuilder = `InvalidTransactionBuilder`,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export enum RouterErrorCode {
|
|
55
|
+
InvalidCoin = `InvalidCoin`,
|
|
56
|
+
NotFoundPath = `NotFoundPath`,
|
|
57
|
+
NoDowngradeNeedParams = `NoDowngradeNeedParams`,
|
|
58
|
+
InvalidSwapCountUrl = `InvalidSwapCountUrl`,
|
|
59
|
+
InvalidTransactionBuilder = `InvalidTransactionBuilder`,
|
|
60
|
+
InvalidServerResponse = `InvalidServerResponse`,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export enum TypesErrorCode {
|
|
64
|
+
InvalidType = `InvalidType`,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type ClmmErrorCode =
|
|
68
|
+
| SwapErrorCode
|
|
69
|
+
| PoolErrorCode
|
|
70
|
+
| PositionErrorCode
|
|
71
|
+
| PartnerErrorCode
|
|
72
|
+
| ConfigErrorCode
|
|
73
|
+
| UtilsErrorCode
|
|
74
|
+
| RouterErrorCode
|
|
75
|
+
| TypesErrorCode
|
|
76
|
+
|
|
77
|
+
export class ClmmError extends BaseError {
|
|
78
|
+
constructor(message: string, errorCode?: ClmmErrorCode, details?: Record<string, any>) {
|
|
79
|
+
super(message, errorCode || 'UnknownError', details)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static isVaultsErrorCode(e: any, code: ClmmErrorCode): boolean {
|
|
83
|
+
return this.isErrorCode<ClmmError>(e, code)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const handleError = (code: ClmmErrorCode, error: Error, details?: Record<string, any>) => {
|
|
88
|
+
throw new ClmmError(error.message, code, details)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const handleMessageError = (code: ClmmErrorCode, message: string, details?: Record<string, any>) => {
|
|
92
|
+
throw new ClmmError(message, code, details)
|
|
93
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './errors'
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CetusClmmSDK, SdkOptions } from './sdk'
|
|
2
|
+
|
|
3
|
+
export * from './utils'
|
|
4
|
+
export * from './math'
|
|
5
|
+
export * from './types'
|
|
6
|
+
export * from './modules'
|
|
7
|
+
export * from './config'
|
|
8
|
+
export * from './errors'
|
|
9
|
+
export { CetusClmmSDK, SdkOptions }
|
|
10
|
+
export default CetusClmmSDK
|
package/src/math/apr.ts
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import BN from 'bn.js'
|
|
2
|
+
import { MathUtil, TickMath } from '@cetusprotocol/common-sdk'
|
|
3
|
+
import Decimal from 'decimal.js'
|
|
4
|
+
|
|
5
|
+
const D365 = new BN(365)
|
|
6
|
+
const H24 = new BN(24)
|
|
7
|
+
const S3600 = new BN(3600)
|
|
8
|
+
const B05 = new BN(0.5)
|
|
9
|
+
|
|
10
|
+
export function estPoolAPR(pre_block_reward: BN, reward_price: BN, total_trading_fee: BN, total_liquidity_value: BN): BN {
|
|
11
|
+
const annualRate = D365.mul(H24).mul(S3600).mul(B05)
|
|
12
|
+
|
|
13
|
+
const APR = annualRate.mul(pre_block_reward.mul(reward_price).add(total_trading_fee).div(total_liquidity_value))
|
|
14
|
+
|
|
15
|
+
return APR
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function calculatePoolValidTVL(
|
|
19
|
+
amount_a: BN,
|
|
20
|
+
amount_b: BN,
|
|
21
|
+
decimals_a: number,
|
|
22
|
+
decimals_b: number,
|
|
23
|
+
coin_a_price: Decimal,
|
|
24
|
+
coin_b_price: Decimal
|
|
25
|
+
): Decimal {
|
|
26
|
+
const poolValidAmountA = new Decimal(amount_a.toString()).div(new Decimal(10 ** decimals_a))
|
|
27
|
+
const poolValidAmountB = new Decimal(amount_b.toString()).div(new Decimal(10 ** decimals_b))
|
|
28
|
+
|
|
29
|
+
const TVL = poolValidAmountA.mul(coin_a_price).add(poolValidAmountB.mul(coin_b_price))
|
|
30
|
+
|
|
31
|
+
return TVL
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type estPosAPRResult = {
|
|
35
|
+
fee_apr: Decimal
|
|
36
|
+
pos_rewarder_0_apr: Decimal
|
|
37
|
+
pos_rewarder_1_apr: Decimal
|
|
38
|
+
pos_rewarder_2_apr: Decimal
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function estPositionAPRWithDeltaMethod(
|
|
42
|
+
current_tick_index: number,
|
|
43
|
+
lower_tick_index: number,
|
|
44
|
+
upper_tick_index: number,
|
|
45
|
+
current_sqrt_price_x64: BN,
|
|
46
|
+
pool_liquidity: BN,
|
|
47
|
+
decimals_a: number,
|
|
48
|
+
decimals_b: number,
|
|
49
|
+
decimals_rewarder_0: number,
|
|
50
|
+
decimals_rewarder_1: number,
|
|
51
|
+
decimals_rewarder_2: number,
|
|
52
|
+
fee_rate: number,
|
|
53
|
+
amount_a_str: string,
|
|
54
|
+
amount_b_str: string,
|
|
55
|
+
pool_amount_a: BN,
|
|
56
|
+
pool_amount_b: BN,
|
|
57
|
+
swap_volume_str: string,
|
|
58
|
+
pool_rewarders_0_str: string,
|
|
59
|
+
pool_rewarders_1_str: string,
|
|
60
|
+
pool_rewarders_2_str: string,
|
|
61
|
+
coin_a_price_str: string,
|
|
62
|
+
coin_b_price_str: string,
|
|
63
|
+
rewarder_0_price_str: string,
|
|
64
|
+
rewarder_1_price_str: string,
|
|
65
|
+
rewarder_2_price_str: string
|
|
66
|
+
): estPosAPRResult {
|
|
67
|
+
const amount_a = new Decimal(amount_a_str)
|
|
68
|
+
const amount_b = new Decimal(amount_b_str)
|
|
69
|
+
const swap_volume = new Decimal(swap_volume_str)
|
|
70
|
+
const pool_rewarders_0 = new Decimal(pool_rewarders_0_str)
|
|
71
|
+
const pool_rewarders_1 = new Decimal(pool_rewarders_1_str)
|
|
72
|
+
const pool_rewarders_2 = new Decimal(pool_rewarders_2_str)
|
|
73
|
+
const coin_a_price = new Decimal(coin_a_price_str)
|
|
74
|
+
const coin_b_price = new Decimal(coin_b_price_str)
|
|
75
|
+
const rewarder_0_price = new Decimal(rewarder_0_price_str)
|
|
76
|
+
const rewarder_1_price = new Decimal(rewarder_1_price_str)
|
|
77
|
+
const rewarder_2_price = new Decimal(rewarder_2_price_str)
|
|
78
|
+
|
|
79
|
+
const lower_sqrt_price_x64 = TickMath.tickIndexToSqrtPriceX64(lower_tick_index)
|
|
80
|
+
const upper_sqrt_price_x64 = TickMath.tickIndexToSqrtPriceX64(upper_tick_index)
|
|
81
|
+
const lower_sqrt_price_d = MathUtil.toX64Decimal(MathUtil.fromX64(lower_sqrt_price_x64)).round()
|
|
82
|
+
const upper_sqrt_price_d = MathUtil.toX64Decimal(MathUtil.fromX64(upper_sqrt_price_x64)).round()
|
|
83
|
+
const current_sqrt_price_d = MathUtil.toX64Decimal(MathUtil.fromX64(current_sqrt_price_x64)).round()
|
|
84
|
+
let delta_liquidity
|
|
85
|
+
const liquidity_amount_0 = amount_a
|
|
86
|
+
.mul(new Decimal(10 ** decimals_a))
|
|
87
|
+
.mul(upper_sqrt_price_d.mul(lower_sqrt_price_d))
|
|
88
|
+
.div(upper_sqrt_price_d.sub(lower_sqrt_price_d))
|
|
89
|
+
.round()
|
|
90
|
+
const liquidity_amount_1 = amount_b
|
|
91
|
+
.mul(new Decimal(10 ** decimals_b))
|
|
92
|
+
.div(upper_sqrt_price_d.sub(lower_sqrt_price_d))
|
|
93
|
+
.round()
|
|
94
|
+
if (current_tick_index < lower_tick_index) {
|
|
95
|
+
delta_liquidity = liquidity_amount_0
|
|
96
|
+
} else if (current_tick_index > upper_tick_index) {
|
|
97
|
+
delta_liquidity = liquidity_amount_1
|
|
98
|
+
} else {
|
|
99
|
+
delta_liquidity = Decimal.min(liquidity_amount_0, liquidity_amount_1)
|
|
100
|
+
}
|
|
101
|
+
const delta_y = delta_liquidity.mul(current_sqrt_price_d.sub(lower_sqrt_price_d))
|
|
102
|
+
const delta_x = delta_liquidity.mul(upper_sqrt_price_d.sub(current_sqrt_price_d)).div(current_sqrt_price_d.mul(upper_sqrt_price_d))
|
|
103
|
+
const pos_valid_tvl = delta_x
|
|
104
|
+
.div(new Decimal(10 ** decimals_a))
|
|
105
|
+
.mul(coin_a_price)
|
|
106
|
+
.add(delta_y.div(new Decimal(10 ** decimals_b).mul(coin_b_price)))
|
|
107
|
+
const pool_valid_tvl = calculatePoolValidTVL(pool_amount_a, pool_amount_b, decimals_a, decimals_b, coin_a_price, coin_b_price)
|
|
108
|
+
const pos_valid_rate = pos_valid_tvl.div(pool_valid_tvl)
|
|
109
|
+
|
|
110
|
+
const fee_apr = delta_liquidity.eq(new Decimal(0))
|
|
111
|
+
? new Decimal(0)
|
|
112
|
+
: new Decimal(fee_rate / 10000)
|
|
113
|
+
.mul(swap_volume)
|
|
114
|
+
.mul(
|
|
115
|
+
new Decimal(delta_liquidity.toString()).div(new Decimal(pool_liquidity.toString()).add(new Decimal(delta_liquidity.toString())))
|
|
116
|
+
)
|
|
117
|
+
.div(pos_valid_tvl)
|
|
118
|
+
|
|
119
|
+
const apr_coe = pos_valid_rate.eq(new Decimal(0)) ? new Decimal(0) : pos_valid_rate.mul(new Decimal(36500 / 7)).div(pos_valid_tvl)
|
|
120
|
+
const pos_rewarder_0_apr = pool_rewarders_0
|
|
121
|
+
.div(new Decimal(10 ** decimals_rewarder_0))
|
|
122
|
+
.mul(rewarder_0_price)
|
|
123
|
+
.mul(apr_coe)
|
|
124
|
+
const pos_rewarder_1_apr = pool_rewarders_1
|
|
125
|
+
.div(new Decimal(10 ** decimals_rewarder_1))
|
|
126
|
+
.mul(rewarder_1_price)
|
|
127
|
+
.mul(apr_coe)
|
|
128
|
+
const pos_rewarder_2_apr = pool_rewarders_2
|
|
129
|
+
.div(new Decimal(10 ** decimals_rewarder_2))
|
|
130
|
+
.mul(rewarder_2_price)
|
|
131
|
+
.mul(apr_coe)
|
|
132
|
+
return {
|
|
133
|
+
fee_apr,
|
|
134
|
+
pos_rewarder_0_apr,
|
|
135
|
+
pos_rewarder_1_apr,
|
|
136
|
+
pos_rewarder_2_apr,
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function estPositionAPRWithMultiMethod(
|
|
141
|
+
lower_user_price: number,
|
|
142
|
+
upper_user_price: number,
|
|
143
|
+
lower_hist_price: number,
|
|
144
|
+
upper_hist_price: number
|
|
145
|
+
): Decimal {
|
|
146
|
+
const retro_lower = Math.max(lower_user_price, lower_hist_price)
|
|
147
|
+
const retro_upper = Math.min(upper_user_price, upper_hist_price)
|
|
148
|
+
const retro_range = retro_upper - retro_lower
|
|
149
|
+
const user_range = upper_user_price - lower_user_price
|
|
150
|
+
const hist_range = upper_hist_price - lower_hist_price
|
|
151
|
+
const user_range_d = new Decimal(user_range.toString())
|
|
152
|
+
const hist_range_d = new Decimal(hist_range.toString())
|
|
153
|
+
const retro_range_d = new Decimal(retro_range.toString())
|
|
154
|
+
|
|
155
|
+
let m = new Decimal('0')
|
|
156
|
+
if (retro_range < 0) {
|
|
157
|
+
m = new Decimal('0')
|
|
158
|
+
} else if (user_range === retro_range) {
|
|
159
|
+
m = hist_range_d.div(retro_range_d)
|
|
160
|
+
} else if (hist_range === retro_range) {
|
|
161
|
+
m = retro_range_d.div(user_range_d)
|
|
162
|
+
} else {
|
|
163
|
+
m = retro_range_d.mul(retro_range_d).div(hist_range_d).div(user_range_d)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return m
|
|
167
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './apr'
|