@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,426 @@
|
|
|
1
|
+
import type { SuiObjectResponse, SuiTransactionBlockResponse } from '@mysten/sui/client'
|
|
2
|
+
import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions'
|
|
3
|
+
import BN from 'bn.js'
|
|
4
|
+
import {
|
|
5
|
+
asIntN,
|
|
6
|
+
buildNFT,
|
|
7
|
+
d,
|
|
8
|
+
DETAILS_KEYS,
|
|
9
|
+
extractStructTagFromType,
|
|
10
|
+
getMoveObjectType,
|
|
11
|
+
getObjectDeletedResponse,
|
|
12
|
+
getObjectFields,
|
|
13
|
+
getObjectId,
|
|
14
|
+
getObjectNotExistsResponse,
|
|
15
|
+
getObjectOwner,
|
|
16
|
+
MathUtil,
|
|
17
|
+
} from '@cetusprotocol/common-sdk'
|
|
18
|
+
import { handleMessageError, PoolErrorCode, PositionErrorCode } from '../errors/errors'
|
|
19
|
+
import { CetusClmmSDK } from '../sdk'
|
|
20
|
+
import type { Pool, PoolTransactionInfo, Position, PositionReward, PositionTransactionInfo, Rewarder } from '../types'
|
|
21
|
+
import { ClmmIntegrateUtilsModule, ClmmPositionStatus, poolFilterEvenTypes } from '../types'
|
|
22
|
+
import type { TickData } from '../types/clmmpool'
|
|
23
|
+
import type { NFT } from '../types/sui'
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Builds a pool name based on two coin types and tick spacing.
|
|
27
|
+
* @param {string} coin_type_a - The type of the first coin.
|
|
28
|
+
* @param {string} coin_type_b - The type of the second coin.
|
|
29
|
+
* @param {string} tick_spacing - The tick spacing of the pool.
|
|
30
|
+
* @returns {string} - The name of the pool.
|
|
31
|
+
*/
|
|
32
|
+
function buildPoolName(coin_type_a: string, coin_type_b: string, tick_spacing: string) {
|
|
33
|
+
const coinNameA = extractStructTagFromType(coin_type_a).name
|
|
34
|
+
const coinNameB = extractStructTagFromType(coin_type_b).name
|
|
35
|
+
return `${coinNameA}-${coinNameB}[${tick_spacing}]`
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Builds a Pool object based on a SuiObjectResponse.
|
|
40
|
+
* @param {SuiObjectResponse} objects - The SuiObjectResponse containing information about the pool.
|
|
41
|
+
* @returns {Pool} - The built Pool object.
|
|
42
|
+
*/
|
|
43
|
+
export function buildPool(objects: SuiObjectResponse): Pool {
|
|
44
|
+
const type = getMoveObjectType(objects) as string
|
|
45
|
+
const formatType = extractStructTagFromType(type)
|
|
46
|
+
const fields = getObjectFields(objects)
|
|
47
|
+
if (fields == null) {
|
|
48
|
+
handleMessageError(PoolErrorCode.InvalidPoolObject, `Pool id ${getObjectId(objects)} not exists.`, {
|
|
49
|
+
[DETAILS_KEYS.METHOD_NAME]: 'buildPool',
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const rewarders: Rewarder[] = []
|
|
54
|
+
fields.rewarder_manager.fields.rewarders.forEach((item: any) => {
|
|
55
|
+
const { emissions_per_second } = item.fields
|
|
56
|
+
const emissionSeconds = MathUtil.fromX64(new BN(emissions_per_second))
|
|
57
|
+
const emissionsEveryDay = Math.floor(emissionSeconds.toNumber() * 60 * 60 * 24)
|
|
58
|
+
|
|
59
|
+
rewarders.push({
|
|
60
|
+
emissions_per_second,
|
|
61
|
+
coin_type: extractStructTagFromType(item.fields.reward_coin.fields.name).source_address,
|
|
62
|
+
growth_global: item.fields.growth_global,
|
|
63
|
+
emissions_every_day: emissionsEveryDay,
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
const pool: Pool = {
|
|
68
|
+
id: getObjectId(objects),
|
|
69
|
+
pool_type: type,
|
|
70
|
+
coin_type_a: formatType.type_arguments[0],
|
|
71
|
+
coin_type_b: formatType.type_arguments[1],
|
|
72
|
+
coin_amount_a: fields.coin_a,
|
|
73
|
+
coin_amount_b: fields.coin_b,
|
|
74
|
+
current_sqrt_price: fields.current_sqrt_price,
|
|
75
|
+
current_tick_index: asIntN(BigInt(fields.current_tick_index.fields.bits)),
|
|
76
|
+
fee_growth_global_a: fields.fee_growth_global_a,
|
|
77
|
+
fee_growth_global_b: fields.fee_growth_global_b,
|
|
78
|
+
fee_protocol_coin_a: fields.fee_protocol_coin_a,
|
|
79
|
+
fee_protocol_coin_b: fields.fee_protocol_coin_b,
|
|
80
|
+
fee_rate: fields.fee_rate,
|
|
81
|
+
is_pause: fields.is_pause,
|
|
82
|
+
liquidity: fields.liquidity,
|
|
83
|
+
position_manager: {
|
|
84
|
+
positions_handle: fields.position_manager.fields.positions.fields.id.id,
|
|
85
|
+
size: fields.position_manager.fields.positions.fields.size,
|
|
86
|
+
},
|
|
87
|
+
rewarder_infos: rewarders,
|
|
88
|
+
rewarder_last_updated_time: fields.rewarder_manager.fields.last_updated_time,
|
|
89
|
+
tick_spacing: fields.tick_spacing,
|
|
90
|
+
ticks_handle: fields.tick_manager.fields.ticks.fields.id.id,
|
|
91
|
+
uri: fields.url,
|
|
92
|
+
index: Number(fields.index),
|
|
93
|
+
name: '',
|
|
94
|
+
}
|
|
95
|
+
pool.name = buildPoolName(pool.coin_type_a, pool.coin_type_b, pool.tick_spacing)
|
|
96
|
+
return pool
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Builds a Position object based on a SuiObjectResponse.
|
|
100
|
+
* @param {SuiObjectResponse} object - The SuiObjectResponse containing information about the position.
|
|
101
|
+
* @returns {Position} - The built Position object.
|
|
102
|
+
*/
|
|
103
|
+
export function buildPosition(object: SuiObjectResponse): Position {
|
|
104
|
+
if (object.error != null || object.data?.content?.dataType !== 'moveObject') {
|
|
105
|
+
handleMessageError(PositionErrorCode.InvalidPositionObject, `Position not exists. Get Position error:${object.error}`, {
|
|
106
|
+
[DETAILS_KEYS.METHOD_NAME]: 'buildPosition',
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let nft: NFT = {
|
|
111
|
+
creator: '',
|
|
112
|
+
description: '',
|
|
113
|
+
image_url: '',
|
|
114
|
+
link: '',
|
|
115
|
+
name: '',
|
|
116
|
+
project_url: '',
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let position = {
|
|
120
|
+
...nft,
|
|
121
|
+
pos_object_id: '',
|
|
122
|
+
owner: '',
|
|
123
|
+
type: '',
|
|
124
|
+
coin_type_a: '',
|
|
125
|
+
coin_type_b: '',
|
|
126
|
+
liquidity: '',
|
|
127
|
+
tick_lower_index: 0,
|
|
128
|
+
tick_upper_index: 0,
|
|
129
|
+
index: 0,
|
|
130
|
+
pool: '',
|
|
131
|
+
reward_amount_owned_0: '0',
|
|
132
|
+
reward_amount_owned_1: '0',
|
|
133
|
+
reward_amount_owned_2: '0',
|
|
134
|
+
reward_growth_inside_0: '0',
|
|
135
|
+
reward_growth_inside_1: '0',
|
|
136
|
+
reward_growth_inside_2: '0',
|
|
137
|
+
fee_growth_inside_a: '0',
|
|
138
|
+
fee_owned_a: '0',
|
|
139
|
+
fee_growth_inside_b: '0',
|
|
140
|
+
fee_owned_b: '0',
|
|
141
|
+
position_status: ClmmPositionStatus.Exists,
|
|
142
|
+
}
|
|
143
|
+
let fields = getObjectFields(object)
|
|
144
|
+
if (fields) {
|
|
145
|
+
const type = getMoveObjectType(object) as string
|
|
146
|
+
const ownerWarp = getObjectOwner(object) as {
|
|
147
|
+
AddressOwner: string
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if ('nft' in fields) {
|
|
151
|
+
fields = fields.nft.fields
|
|
152
|
+
nft.description = fields.description as string
|
|
153
|
+
nft.name = fields.name
|
|
154
|
+
nft.link = fields.url
|
|
155
|
+
} else {
|
|
156
|
+
nft = buildNFT(object)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
position = {
|
|
160
|
+
...nft,
|
|
161
|
+
pos_object_id: fields.id.id,
|
|
162
|
+
owner: ownerWarp.AddressOwner,
|
|
163
|
+
type,
|
|
164
|
+
liquidity: fields.liquidity,
|
|
165
|
+
coin_type_a: fields.coin_type_a.fields.name,
|
|
166
|
+
coin_type_b: fields.coin_type_b.fields.name,
|
|
167
|
+
tick_lower_index: asIntN(BigInt(fields.tick_lower_index.fields.bits)),
|
|
168
|
+
tick_upper_index: asIntN(BigInt(fields.tick_upper_index.fields.bits)),
|
|
169
|
+
index: fields.index,
|
|
170
|
+
pool: fields.pool,
|
|
171
|
+
reward_amount_owned_0: '0',
|
|
172
|
+
reward_amount_owned_1: '0',
|
|
173
|
+
reward_amount_owned_2: '0',
|
|
174
|
+
reward_growth_inside_0: '0',
|
|
175
|
+
reward_growth_inside_1: '0',
|
|
176
|
+
reward_growth_inside_2: '0',
|
|
177
|
+
fee_growth_inside_a: '0',
|
|
178
|
+
fee_owned_a: '0',
|
|
179
|
+
fee_growth_inside_b: '0',
|
|
180
|
+
fee_owned_b: '0',
|
|
181
|
+
position_status: ClmmPositionStatus.Exists,
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const deletedResponse = getObjectDeletedResponse(object)
|
|
186
|
+
if (deletedResponse) {
|
|
187
|
+
position.pos_object_id = deletedResponse.objectId
|
|
188
|
+
position.position_status = ClmmPositionStatus.Deleted
|
|
189
|
+
}
|
|
190
|
+
const objectNotExistsResponse = getObjectNotExistsResponse(object)
|
|
191
|
+
if (objectNotExistsResponse) {
|
|
192
|
+
position.pos_object_id = objectNotExistsResponse
|
|
193
|
+
position.position_status = ClmmPositionStatus.NotExists
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return position
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Builds a PositionReward object based on a response containing information about the reward.
|
|
201
|
+
* @param {any} fields - The response containing information about the reward.
|
|
202
|
+
* @returns {PositionReward} - The built PositionReward object.
|
|
203
|
+
*/
|
|
204
|
+
export function buildPositionReward(fields: any): PositionReward {
|
|
205
|
+
const rewarders = {
|
|
206
|
+
reward_amount_owned_0: '0',
|
|
207
|
+
reward_amount_owned_1: '0',
|
|
208
|
+
reward_amount_owned_2: '0',
|
|
209
|
+
reward_growth_inside_0: '0',
|
|
210
|
+
reward_growth_inside_1: '0',
|
|
211
|
+
reward_growth_inside_2: '0',
|
|
212
|
+
}
|
|
213
|
+
fields = 'fields' in fields ? fields.fields : fields
|
|
214
|
+
|
|
215
|
+
fields.rewards.forEach((item: any, index: number) => {
|
|
216
|
+
const { amount_owned, growth_inside } = 'fields' in item ? item.fields : item
|
|
217
|
+
if (index === 0) {
|
|
218
|
+
rewarders.reward_amount_owned_0 = amount_owned
|
|
219
|
+
rewarders.reward_growth_inside_0 = growth_inside
|
|
220
|
+
} else if (index === 1) {
|
|
221
|
+
rewarders.reward_amount_owned_1 = amount_owned
|
|
222
|
+
rewarders.reward_growth_inside_1 = growth_inside
|
|
223
|
+
} else if (index === 2) {
|
|
224
|
+
rewarders.reward_amount_owned_2 = amount_owned
|
|
225
|
+
rewarders.reward_growth_inside_2 = growth_inside
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
const tick_lower_index = 'fields' in fields.tick_lower_index ? fields.tick_lower_index.fields.bits : fields.tick_lower_index.bits
|
|
230
|
+
const tick_upper_index = 'fields' in fields.tick_upper_index ? fields.tick_upper_index.fields.bits : fields.tick_upper_index.bits
|
|
231
|
+
|
|
232
|
+
const position: PositionReward = {
|
|
233
|
+
liquidity: fields.liquidity,
|
|
234
|
+
tick_lower_index: asIntN(BigInt(tick_lower_index)),
|
|
235
|
+
tick_upper_index: asIntN(BigInt(tick_upper_index)),
|
|
236
|
+
...rewarders,
|
|
237
|
+
fee_growth_inside_a: fields.fee_growth_inside_a,
|
|
238
|
+
fee_owned_a: fields.fee_owned_a,
|
|
239
|
+
fee_growth_inside_b: fields.fee_growth_inside_b,
|
|
240
|
+
fee_owned_b: fields.fee_owned_b,
|
|
241
|
+
pos_object_id: fields.position_id,
|
|
242
|
+
}
|
|
243
|
+
return position
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Builds a TickData object based on a response containing information about tick data.
|
|
248
|
+
* It must check if the response contains the required fields.
|
|
249
|
+
* @param {SuiObjectResponse} objects - The response containing information about tick data.
|
|
250
|
+
* @returns {TickData} - The built TickData object.
|
|
251
|
+
*/
|
|
252
|
+
export function buildTickData(objects: SuiObjectResponse): TickData {
|
|
253
|
+
if (objects.error != null || objects.data?.content?.dataType !== 'moveObject') {
|
|
254
|
+
handleMessageError(PoolErrorCode.InvalidTickObject, `Tick not exists. Get tick data error:${objects.error}`, {
|
|
255
|
+
[DETAILS_KEYS.METHOD_NAME]: 'buildTickData',
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const fields = getObjectFields(objects)
|
|
260
|
+
|
|
261
|
+
const valueItem = fields.value.fields.value.fields
|
|
262
|
+
const position: TickData = {
|
|
263
|
+
object_id: getObjectId(objects),
|
|
264
|
+
index: asIntN(BigInt(valueItem.index.fields.bits)),
|
|
265
|
+
sqrt_price: new BN(valueItem.sqrt_price),
|
|
266
|
+
liquidity_net: new BN(valueItem.liquidity_net.fields.bits),
|
|
267
|
+
liquidity_gross: new BN(valueItem.liquidity_gross),
|
|
268
|
+
fee_growth_outside_a: new BN(valueItem.fee_growth_outside_a),
|
|
269
|
+
fee_growth_outside_b: new BN(valueItem.fee_growth_outside_b),
|
|
270
|
+
rewarders_growth_outside: valueItem.rewards_growth_outside,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return position
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Builds a TickData object based on a given event's fields.
|
|
278
|
+
* @param {any} fields - The fields of an event.
|
|
279
|
+
* @returns {TickData} - The built TickData object.
|
|
280
|
+
* @throws {Error} If any required field is missing.
|
|
281
|
+
*/
|
|
282
|
+
export function buildTickDataByEvent(fields: any): TickData {
|
|
283
|
+
if (
|
|
284
|
+
!fields ||
|
|
285
|
+
!fields.index ||
|
|
286
|
+
!fields.sqrt_price ||
|
|
287
|
+
!fields.liquidity_net ||
|
|
288
|
+
!fields.liquidity_gross ||
|
|
289
|
+
!fields.fee_growth_outside_a ||
|
|
290
|
+
!fields.fee_growth_outside_b
|
|
291
|
+
) {
|
|
292
|
+
handleMessageError(PoolErrorCode.InvalidTickFields, `Invalid tick fields.`, {
|
|
293
|
+
[DETAILS_KEYS.METHOD_NAME]: 'buildTickDataByEvent',
|
|
294
|
+
})
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// It's assumed that asIntN is a function that converts a BigInt to an integer.
|
|
298
|
+
const index = asIntN(BigInt(fields.index.bits))
|
|
299
|
+
const sqrt_price = new BN(fields.sqrt_price)
|
|
300
|
+
const liquidity_net = new BN(fields.liquidity_net.bits)
|
|
301
|
+
const liquidity_gross = new BN(fields.liquidity_gross)
|
|
302
|
+
const fee_growth_outside_a = new BN(fields.fee_growth_outside_a)
|
|
303
|
+
const fee_growth_outside_b = new BN(fields.fee_growth_outside_b)
|
|
304
|
+
const rewarders_growth_outside = fields.rewards_growth_outside || []
|
|
305
|
+
|
|
306
|
+
const tick: TickData = {
|
|
307
|
+
object_id: '',
|
|
308
|
+
index,
|
|
309
|
+
sqrt_price,
|
|
310
|
+
liquidity_net,
|
|
311
|
+
liquidity_gross,
|
|
312
|
+
fee_growth_outside_a,
|
|
313
|
+
fee_growth_outside_b,
|
|
314
|
+
rewarders_growth_outside,
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return tick
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function buildClmmPositionName(pool_index: number, position_index: number): string {
|
|
321
|
+
return `Cetus LP | Pool${pool_index}-${position_index}`
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export function buildPositionTransactionInfo(data: SuiTransactionBlockResponse, txIndex: number, filterIds: string[]) {
|
|
325
|
+
const list: PositionTransactionInfo[] = []
|
|
326
|
+
const { timestampMs, events } = data
|
|
327
|
+
|
|
328
|
+
const filterEvenTypes = [
|
|
329
|
+
'AddLiquidityEvent',
|
|
330
|
+
'RemoveLiquidityEvent',
|
|
331
|
+
'CollectFeeEvent',
|
|
332
|
+
'CollectRewardEvent',
|
|
333
|
+
'CollectRewardV2Event',
|
|
334
|
+
'HarvestEvent',
|
|
335
|
+
]
|
|
336
|
+
|
|
337
|
+
events?.forEach((event, index) => {
|
|
338
|
+
const type = extractStructTagFromType(event.type).name
|
|
339
|
+
if (filterEvenTypes.includes(type)) {
|
|
340
|
+
const info: PositionTransactionInfo = {
|
|
341
|
+
tx_digest: event.id.txDigest,
|
|
342
|
+
package_id: event.packageId,
|
|
343
|
+
transaction_module: event.transactionModule,
|
|
344
|
+
sender: event.sender,
|
|
345
|
+
type: event.type,
|
|
346
|
+
timestamp_ms: timestampMs || '0',
|
|
347
|
+
parsed_json: event.parsedJson,
|
|
348
|
+
index: `${txIndex}_${index}`,
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
switch (type) {
|
|
352
|
+
case 'CollectFeeEvent':
|
|
353
|
+
if (filterIds.includes(info.parsed_json.position) && (d(info.parsed_json.amount_a).gt(0) || d(info.parsed_json.amount_b).gt(0))) {
|
|
354
|
+
list.push(info)
|
|
355
|
+
}
|
|
356
|
+
break
|
|
357
|
+
case 'RemoveLiquidityEvent':
|
|
358
|
+
case 'AddLiquidityEvent':
|
|
359
|
+
if (d(info.parsed_json.amount_a).gt(0) || d(info.parsed_json.amount_b).gt(0)) {
|
|
360
|
+
list.push(info)
|
|
361
|
+
}
|
|
362
|
+
break
|
|
363
|
+
case 'CollectRewardEvent':
|
|
364
|
+
case 'HarvestEvent':
|
|
365
|
+
case 'CollectRewardV2Event':
|
|
366
|
+
if (
|
|
367
|
+
(filterIds.includes(info.parsed_json.position) || filterIds.includes(info.parsed_json.wrapped_position_id)) &&
|
|
368
|
+
d(info.parsed_json.amount).gt(0)
|
|
369
|
+
) {
|
|
370
|
+
list.push(info)
|
|
371
|
+
}
|
|
372
|
+
break
|
|
373
|
+
|
|
374
|
+
default:
|
|
375
|
+
break
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
return list
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export function buildPoolTransactionInfo(data: SuiTransactionBlockResponse, txIndex: number, package_id: string, pool_id: string) {
|
|
384
|
+
const list: PoolTransactionInfo[] = []
|
|
385
|
+
const { timestampMs, events } = data
|
|
386
|
+
|
|
387
|
+
events?.forEach((event: any, index) => {
|
|
388
|
+
const { name: type, address: package_address } = extractStructTagFromType(event.type)
|
|
389
|
+
if (poolFilterEvenTypes.includes(type) && package_address === package_id && pool_id === event.parsedJson.pool) {
|
|
390
|
+
const info: PoolTransactionInfo = {
|
|
391
|
+
tx: event.id.txDigest,
|
|
392
|
+
sender: event.sender,
|
|
393
|
+
type: event.type,
|
|
394
|
+
block_time: timestampMs || '0',
|
|
395
|
+
index: `${txIndex}_${index}`,
|
|
396
|
+
parsed_json: event.parsedJson,
|
|
397
|
+
}
|
|
398
|
+
list.push(info)
|
|
399
|
+
}
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
return list
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export function buildTransferCoinToSender(sdk: CetusClmmSDK, tx: Transaction, coin: TransactionObjectArgument, coinType: string) {
|
|
406
|
+
tx.moveCall({
|
|
407
|
+
target: `${sdk.sdkOptions.integrate.published_at}::${ClmmIntegrateUtilsModule}::transfer_coin_to_sender`,
|
|
408
|
+
typeArguments: [coinType],
|
|
409
|
+
arguments: [coin],
|
|
410
|
+
})
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// If recipient not set, transfer objects move call will use ctx sender
|
|
414
|
+
export function buildTransferCoin(
|
|
415
|
+
sdk: CetusClmmSDK,
|
|
416
|
+
tx: Transaction,
|
|
417
|
+
coin: TransactionObjectArgument,
|
|
418
|
+
coinType: string,
|
|
419
|
+
recipient?: string
|
|
420
|
+
) {
|
|
421
|
+
if (recipient != null) {
|
|
422
|
+
tx.transferObjects([coin], tx.pure.address(recipient))
|
|
423
|
+
} else {
|
|
424
|
+
buildTransferCoinToSender(sdk, tx, coin, coinType)
|
|
425
|
+
}
|
|
426
|
+
}
|