@cetusprotocol/dlmm-sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/.turbo/turbo-build.log +10423 -0
  2. package/README.md +646 -0
  3. package/dist/index.d.mts +1015 -0
  4. package/dist/index.d.ts +1015 -0
  5. package/dist/index.js +13 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/index.mjs +13 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/package.json +35 -0
  10. package/src/config/index.ts +2 -0
  11. package/src/config/mainnet.ts +25 -0
  12. package/src/config/testnet.ts +30 -0
  13. package/src/errors/errors.ts +40 -0
  14. package/src/index.ts +8 -0
  15. package/src/modules/configModule.ts +184 -0
  16. package/src/modules/index.ts +1 -0
  17. package/src/modules/partnerModule.ts +302 -0
  18. package/src/modules/poolModule.ts +578 -0
  19. package/src/modules/positionModule.ts +888 -0
  20. package/src/modules/rewardModule.ts +175 -0
  21. package/src/modules/swapModule.ts +129 -0
  22. package/src/sdk.ts +88 -0
  23. package/src/types/constants.ts +23 -0
  24. package/src/types/dlmm.ts +445 -0
  25. package/src/types/index.ts +2 -0
  26. package/src/utils/binUtils.ts +552 -0
  27. package/src/utils/feeUtils.ts +92 -0
  28. package/src/utils/index.ts +5 -0
  29. package/src/utils/parseData.ts +519 -0
  30. package/src/utils/strategyUtils.ts +121 -0
  31. package/src/utils/weightUtils.ts +510 -0
  32. package/tests/add_liquidity_bidask.test.ts +180 -0
  33. package/tests/add_liquidity_curve.test.ts +244 -0
  34. package/tests/add_liquidity_spot.test.ts +262 -0
  35. package/tests/bin.test.ts +80 -0
  36. package/tests/config.test.ts +51 -0
  37. package/tests/partner.test.ts +74 -0
  38. package/tests/pool.test.ts +174 -0
  39. package/tests/position.test.ts +76 -0
  40. package/tests/remove_liquidity.test.ts +137 -0
  41. package/tests/swap.test.ts +96 -0
  42. package/tests/tsconfig.json +26 -0
  43. package/tsconfig.json +5 -0
  44. package/tsup.config.ts +9 -0
@@ -0,0 +1,519 @@
1
+ import {
2
+ asIntN,
3
+ d,
4
+ DETAILS_KEYS,
5
+ extractStructTagFromType,
6
+ fixCoinType,
7
+ getObjectFields,
8
+ getObjectType,
9
+ MathUtil,
10
+ } from '@cetusprotocol/common-sdk'
11
+ import { DevInspectResults, SuiEvent, SuiObjectResponse, SuiTransactionBlockResponse } from '@mysten/sui/client'
12
+ import BN from 'bn.js'
13
+ import Decimal from 'decimal.js'
14
+ import { DlmmErrorCode, handleError, DlmmError } from '../errors/errors'
15
+ import {
16
+ BinAmount,
17
+ BinLiquidityInfo,
18
+ BinManager,
19
+ BinSwap,
20
+ DlmmBasePool,
21
+ DlmmPool,
22
+ DlmmPosition,
23
+ Partner,
24
+ PoolTransactionInfo,
25
+ PositionFee,
26
+ PositionManager,
27
+ PositionReward,
28
+ PreSwapQuote,
29
+ Reward,
30
+ RewardInfo,
31
+ RewardManager,
32
+ RewardPeriodEmission,
33
+ RewardPeriodEmissionFormat,
34
+ StrategyType,
35
+ VariableParameters,
36
+ } from '../types/dlmm'
37
+ import { BinUtils } from './binUtils'
38
+ import { BASIS_POINT } from '../types/constants'
39
+ import { bcs } from '@mysten/sui/bcs'
40
+
41
+ /**
42
+ * Parse the DLMM base pool data
43
+ * @param data - The DLMM base pool data
44
+ * @returns The DLMM base pool
45
+ */
46
+ export function parseDlmmBasePool(data: SuiEvent): DlmmBasePool {
47
+ try {
48
+ const fields = data.parsedJson as any
49
+ const pool: DlmmBasePool = {
50
+ id: fields.pool_id,
51
+ bin_step: Number(fields.bin_step),
52
+ coin_type_a: fixCoinType(fields.coin_type_a, false),
53
+ coin_type_b: fixCoinType(fields.coin_type_b, false),
54
+ }
55
+
56
+ return pool
57
+ } catch (error) {
58
+ return handleError(DlmmErrorCode.ParseError, error as Error, {
59
+ [DETAILS_KEYS.METHOD_NAME]: 'parseDlmmBasePool',
60
+ [DETAILS_KEYS.REQUEST_PARAMS]: data,
61
+ })
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Parse the DLMM pool data
67
+ * @param data - The DLMM pool data
68
+ * @returns The DLMM pool
69
+ */
70
+ export function parseDlmmPool(data: SuiObjectResponse): DlmmPool {
71
+ try {
72
+ const fields = getObjectFields(data)
73
+ const type = getObjectType(data) as string
74
+ const formatType = extractStructTagFromType(type)
75
+
76
+ const bin_manager: BinManager = {
77
+ bin_step: fields.bin_manager.fields.bin_step,
78
+ bin_manager_handle: fields.bin_manager.fields.bins.fields.id.id,
79
+ size: fields.bin_manager.fields.bins.fields.size,
80
+ }
81
+
82
+ const position_manager: PositionManager = {
83
+ bin_step: fields.position_manager.fields.bin_step,
84
+ position_index: fields.position_manager.fields.position_index,
85
+ position_handle: fields.position_manager.fields.positions.fields.id.id,
86
+ size: fields.position_manager.fields.positions.fields.size,
87
+ }
88
+
89
+ const reward_manager_fields = fields.reward_manager.fields
90
+
91
+ const rewards = reward_manager_fields.rewards.map((reward: any) => {
92
+ const current_reward_rate = reward.fields.current_emission_rate
93
+ const emissions_per_second = MathUtil.fromX64(new BN(current_reward_rate))
94
+ const emissions_per_day = Math.floor(emissions_per_second.toNumber() * 60 * 60 * 24).toString()
95
+
96
+ const info: Reward = {
97
+ reward_coin: fixCoinType(reward.fields.reward_coin.fields.name, false),
98
+ emissions_per_second: emissions_per_second.toString(),
99
+ emissions_per_day,
100
+ period_emission_rates: {
101
+ id: reward.fields.period_emission_rates.fields.id.id,
102
+ size: reward.fields.period_emission_rates.fields.size,
103
+ },
104
+ }
105
+ return info
106
+ })
107
+ const reward_manager: RewardManager = {
108
+ is_public: reward_manager_fields.is_public,
109
+ emergency_reward_pause: reward_manager_fields.emergency_reward_pause,
110
+ vault: {
111
+ id: reward_manager_fields.vault.fields.id.id,
112
+ size: reward_manager_fields.vault.fields.size,
113
+ },
114
+ rewards,
115
+ last_updated_time: reward_manager_fields.last_updated_time,
116
+ }
117
+
118
+ const variable_parameters: VariableParameters = {
119
+ volatility_accumulator: fields.v_parameters.fields.volatility_accumulator,
120
+ volatility_reference: fields.v_parameters.fields.volatility_reference,
121
+ index_reference: asIntN(BigInt(fields.v_parameters.fields.index_reference.fields.bits)),
122
+ last_update_timestamp: fields.v_parameters.fields.last_update_timestamp,
123
+ bin_step_config: fields.v_parameters.fields.bin_step_config.fields,
124
+ }
125
+
126
+ const pool: DlmmPool = {
127
+ id: fields.id.id,
128
+ bin_step: Number(fields.bin_step),
129
+ coin_type_a: fixCoinType(formatType.type_arguments[0], false),
130
+ coin_type_b: fixCoinType(formatType.type_arguments[1], false),
131
+ pool_type: type,
132
+ index: Number(fields.index),
133
+ bin_manager,
134
+ variable_parameters,
135
+ active_id: asIntN(BigInt(fields.active_id.fields.bits)),
136
+ permissions: fields.permissions.fields,
137
+ balance_a: fields.balance_a,
138
+ balance_b: fields.balance_b,
139
+ base_fee_rate: fields.base_fee_rate,
140
+ protocol_fee_a: fields.protocol_fee_a,
141
+ protocol_fee_b: fields.protocol_fee_b,
142
+ url: fields.url,
143
+ reward_manager,
144
+ position_manager,
145
+ }
146
+ pool.bin_step = pool.bin_manager.bin_step
147
+ return pool
148
+ } catch (error) {
149
+ console.log('🚀 ~ parseDlmmPool ~ error:', error)
150
+ return handleError(DlmmErrorCode.ParseError, error as Error, {
151
+ [DETAILS_KEYS.METHOD_NAME]: 'parseDlmmPool',
152
+ [DETAILS_KEYS.REQUEST_PARAMS]: data,
153
+ })
154
+ }
155
+ }
156
+
157
+ export function parsePartner(data: SuiObjectResponse): Partner {
158
+ const fields = getObjectFields(data)
159
+ const type = getObjectType(data) as string
160
+ const formatType = extractStructTagFromType(type)
161
+
162
+ const partner: Partner = {
163
+ id: fields.id.id,
164
+ name: fields.name,
165
+ ref_fee_rate: d(fields.ref_fee_rate).div(BASIS_POINT).toNumber(),
166
+ start_time: Number(fields.start_time),
167
+ end_time: Number(fields.end_time),
168
+ balances: {
169
+ id: fields.balances.fields.id.id,
170
+ size: fields.balances.fields.size,
171
+ },
172
+ type: formatType.full_address,
173
+ }
174
+
175
+ return partner
176
+ }
177
+
178
+ export function parseDlmmPosition(data: SuiObjectResponse): DlmmPosition {
179
+ try {
180
+ const fields = getObjectFields(data)
181
+ const position: DlmmPosition = {
182
+ uri: fields.uri,
183
+ index: fields.index,
184
+ id: fields.id.id,
185
+ name: fields.name,
186
+ pool_id: fields.pool_id,
187
+ lower_bin_id: asIntN(BigInt(fields.lower_bin_id.fields.bits)),
188
+ upper_bin_id: asIntN(BigInt(fields.upper_bin_id.fields.bits)),
189
+ liquidity_shares: fields.liquidity_shares,
190
+ description: fields.description,
191
+ coin_type_a: fixCoinType(fields.coin_type_a, false),
192
+ coin_type_b: fixCoinType(fields.coin_type_b, false),
193
+ }
194
+
195
+ return position
196
+ } catch (error) {
197
+ console.log('🚀 ~ parseDlmmPosition ~ error:', error)
198
+ return handleError(DlmmErrorCode.ParseError, error as Error, {
199
+ [DETAILS_KEYS.METHOD_NAME]: 'parseDlmmPosition',
200
+ [DETAILS_KEYS.REQUEST_PARAMS]: data,
201
+ })
202
+ }
203
+ }
204
+
205
+ export function parseLiquidityShares(
206
+ liquidity_shares: string[],
207
+ bin_step: number,
208
+ lower_bin_id: number,
209
+ active_bin: BinAmount
210
+ ): BinLiquidityInfo {
211
+ const bins = liquidity_shares.map((liquidity, index) => {
212
+ const bin_id = lower_bin_id + index
213
+ const price_per_lamport = BinUtils.getPricePerLamportFromBinId(bin_id, bin_step)
214
+ if (bin_id === active_bin.bin_id) {
215
+ const { amount_a, amount_b } = BinUtils.calculateOutByShare(active_bin, liquidity)
216
+ return {
217
+ bin_id,
218
+ amount_a,
219
+ amount_b,
220
+ liquidity,
221
+ price_per_lamport,
222
+ }
223
+ }
224
+
225
+ if (bin_id < active_bin.bin_id) {
226
+ const amount_b = BinUtils.getAmountBFromLiquidity(liquidity)
227
+ return {
228
+ bin_id,
229
+ amount_a: '0',
230
+ amount_b,
231
+ liquidity,
232
+ price_per_lamport,
233
+ }
234
+ }
235
+
236
+ const q_price = BinUtils.getQPriceFromId(bin_id, bin_step)
237
+ const amount_a = BinUtils.getAmountAFromLiquidity(liquidity, q_price)
238
+ return {
239
+ bin_id,
240
+ amount_a,
241
+ amount_b: '0',
242
+ liquidity,
243
+ price_per_lamport,
244
+ }
245
+ })
246
+
247
+ const amount_a = bins
248
+ .reduce((acc, bin) => {
249
+ return acc.add(new Decimal(bin.amount_a))
250
+ }, new Decimal(0))
251
+ .toFixed(0)
252
+
253
+ const amount_b = bins
254
+ .reduce((acc, bin) => {
255
+ return acc.add(new Decimal(bin.amount_b))
256
+ }, new Decimal(0))
257
+ .toFixed(0)
258
+
259
+ return {
260
+ bins,
261
+ amount_a,
262
+ amount_b,
263
+ }
264
+ }
265
+
266
+ export function parseBinInfoList(res: DevInspectResults): BinAmount[] {
267
+ try {
268
+ const bcsCoinAmount = bcs.struct('BinAmount', {
269
+ id: bcs.struct('I32', {
270
+ bits: bcs.u32(),
271
+ }),
272
+ amount_a: bcs.u64(),
273
+ amount_b: bcs.u64(),
274
+ price: bcs.u128(),
275
+ liquidity_supply: bcs.u128(),
276
+ rewards_growth_global: bcs.vector(bcs.u128()),
277
+ fee_a_growth_global: bcs.u128(),
278
+ fee_b_growth_global: bcs.u128(),
279
+ })
280
+
281
+ const bin_amounts = bcs.vector(bcsCoinAmount).parse(Uint8Array.from(res.results![0].returnValues![0][0]))
282
+
283
+ return bin_amounts.map((bin_amount) => {
284
+ const bin_id = asIntN(BigInt(bin_amount.id.bits))
285
+ return {
286
+ bin_id,
287
+ amount_a: bin_amount.amount_a,
288
+ amount_b: bin_amount.amount_b,
289
+ liquidity: bin_amount.liquidity_supply,
290
+ price_per_lamport: BinUtils.getPricePerLamportFromQPrice(bin_amount.price),
291
+ }
292
+ })
293
+ } catch (error) {
294
+ console.log('🚀 ~ parseBinInfo ~ error:', error)
295
+ return []
296
+ }
297
+ }
298
+
299
+ export function parseBinInfo(fields: any): BinAmount {
300
+ try {
301
+ const bin_id = asIntN(BigInt(fields.id.fields.bits))
302
+ const bin_amount: BinAmount = {
303
+ bin_id,
304
+ amount_a: fields.amount_a,
305
+ amount_b: fields.amount_b,
306
+ liquidity: fields.liquidity_supply,
307
+ price_per_lamport: BinUtils.getPricePerLamportFromQPrice(fields.price),
308
+ }
309
+
310
+ return bin_amount
311
+ } catch (error) {
312
+ console.log('🚀 ~ parseBinInfo ~ error:', error)
313
+ return handleError(DlmmErrorCode.ParseError, error as Error, {
314
+ [DETAILS_KEYS.METHOD_NAME]: 'parseBinInfo',
315
+ [DETAILS_KEYS.REQUEST_PARAMS]: {
316
+ fields,
317
+ },
318
+ })
319
+ }
320
+ }
321
+
322
+ export function parsedDlmmPosFeeData(simulate_res: DevInspectResults) {
323
+ const feeData: Record<string, PositionFee> = {}
324
+ const feeValueData: any[] = simulate_res.events?.filter((item: any) => {
325
+ return item.type.includes('pool::CollectFeeEvent')
326
+ })
327
+
328
+ for (let i = 0; i < feeValueData.length; i += 1) {
329
+ const { parsedJson } = feeValueData[i]
330
+ const posObj = {
331
+ position_id: parsedJson.position,
332
+ fee_owned_a: parsedJson.fee_a,
333
+ fee_owned_b: parsedJson.fee_b,
334
+ }
335
+ feeData[parsedJson.position] = posObj
336
+ }
337
+
338
+ return feeData
339
+ }
340
+
341
+ export function parsedDlmmPosRewardData(simulate_res: DevInspectResults) {
342
+ const rewarderData: Record<string, PositionReward> = {}
343
+ const rewarderValueData: any[] = simulate_res.events?.filter((item: any) => {
344
+ return item.type.includes('pool::CollectRewardEvent')
345
+ })
346
+
347
+ for (let i = 0; i < rewarderValueData.length; i += 1) {
348
+ const { parsedJson } = rewarderValueData[i]
349
+ const position_id = parsedJson.position
350
+ const reward_coin = parsedJson.reward
351
+ const reward_amount = parsedJson.amount
352
+ const rewardInfo: RewardInfo = {
353
+ coin_type: fixCoinType(reward_coin.name, false),
354
+ reward_owned: reward_amount,
355
+ }
356
+ let rewarder = rewarderData[position_id]
357
+ if (rewarder) {
358
+ rewarder.rewards.push(rewardInfo)
359
+ } else {
360
+ rewarder = {
361
+ position_id,
362
+ rewards: [rewardInfo],
363
+ }
364
+ }
365
+ rewarderData[position_id] = rewarder
366
+ }
367
+
368
+ return rewarderData
369
+ }
370
+
371
+ export function parsedSwapQuoteData(simulate_res: DevInspectResults, a2b: boolean): PreSwapQuote | undefined {
372
+ const rewarderValueData: any[] = simulate_res.events?.filter((item: any) => {
373
+ return item.type.includes('pool::SwapEvent')
374
+ })
375
+
376
+ for (let i = 0; i < rewarderValueData.length; i += 1) {
377
+ const { parsedJson } = rewarderValueData[i]
378
+ const { partner, pool, amount_in, amount_out, fee, ref_fee, bin_swaps, from, target } = parsedJson
379
+ const bin_swaps_info: BinSwap[] = bin_swaps.map((bin_swap: any) => {
380
+ return {
381
+ bin_id: bin_swap.bin_id.bits,
382
+ in_amount: bin_swap.amount_in,
383
+ out_amount: bin_swap.amount_out,
384
+ fee: bin_swap.fee,
385
+ var_fee_rate: bin_swap.var_fee_rate,
386
+ }
387
+ })
388
+ const info: PreSwapQuote = {
389
+ pool_id: pool,
390
+ a2b,
391
+ in_amount: amount_in,
392
+ out_amount: amount_out,
393
+ ref_fee_amount: ref_fee,
394
+ fee_amount: fee,
395
+ bin_swaps: bin_swaps_info,
396
+ partner,
397
+ from_coin_type: fixCoinType(from.name, false),
398
+ to_coin_type: fixCoinType(target.name, false),
399
+ }
400
+
401
+ return info
402
+ }
403
+ return undefined
404
+ }
405
+
406
+ export function parseStrategyType(strategy_type: StrategyType): number {
407
+ switch (strategy_type) {
408
+ case StrategyType.Spot:
409
+ return 0
410
+ case StrategyType.Curve:
411
+ return 1
412
+ case StrategyType.BidAsk:
413
+ return 2
414
+ }
415
+ }
416
+ export const poolFilterEvenTypes = ['RemoveLiquidityEvent', 'SwapEvent', 'AddLiquidityEvent', 'ClosePositionEvent']
417
+ export function parsePoolTransactionInfo(data: SuiTransactionBlockResponse, txIndex: number, package_id: string, pool_id: string) {
418
+ const list: PoolTransactionInfo[] = []
419
+ const { timestampMs, events } = data
420
+
421
+ events?.forEach((event: any, index) => {
422
+ const { name: type, address: package_address } = extractStructTagFromType(event.type)
423
+ if (poolFilterEvenTypes.includes(type) && package_address === package_id && pool_id === event.parsedJson.pool) {
424
+ const info: PoolTransactionInfo = {
425
+ tx: event.id.txDigest,
426
+ sender: event.sender,
427
+ type: event.type,
428
+ block_time: timestampMs || '0',
429
+ index: `${txIndex}_${index}`,
430
+ parsed_json: event.parsedJson,
431
+ }
432
+ list.push(info)
433
+ }
434
+ })
435
+
436
+ return list
437
+ }
438
+
439
+ export function generateRewardSchedule(baseTime: number, maxIntervals: number, timeInterval: number): number[] {
440
+ const result: number[] = []
441
+
442
+ let intervals = 0 // Start from 0 to include base time if needed
443
+ const baseDateTime = new Date(baseTime * 1000).getTime() // Convert seconds to milliseconds
444
+ const nowTime = new Date().getTime()
445
+ while (true) {
446
+ const rewardTime = baseDateTime + intervals * timeInterval
447
+
448
+ if (rewardTime >= nowTime) {
449
+ result.push(rewardTime)
450
+ }
451
+
452
+ if (intervals >= maxIntervals) {
453
+ break
454
+ }
455
+
456
+ intervals += 1
457
+ }
458
+
459
+ return result
460
+ }
461
+
462
+ export function parseRewardPeriodEmission(
463
+ periodEmissionList: RewardPeriodEmission[],
464
+ startTimeInSeconds: number,
465
+ endTimeInSeconds: number,
466
+ durationSeconds: number
467
+ ) {
468
+ const result: RewardPeriodEmissionFormat[] = []
469
+ for (let time = startTimeInSeconds; time <= endTimeInSeconds; time += durationSeconds) {
470
+ const findRewardPeriodEmission = periodEmissionList.findLast((period) => d(time).gte(period.time))
471
+ if (findRewardPeriodEmission) {
472
+ result.push({
473
+ time: time.toString(),
474
+ emissions_per_second: findRewardPeriodEmission.emissions_per_second,
475
+ emissions_per_day: findRewardPeriodEmission.emissions_per_day,
476
+ visualized_time: new Date(time * 1000).toLocaleString(),
477
+ })
478
+ } else {
479
+ result.push({
480
+ emissions_per_day: '0',
481
+ time: time.toString(),
482
+ emissions_per_second: '0',
483
+ visualized_time: new Date(time * 1000).toLocaleString(),
484
+ })
485
+ }
486
+ }
487
+ return result
488
+ }
489
+
490
+ export function parseCurrentRewardPeriodEmission(periodEmissionList: RewardPeriodEmission[]): RewardPeriodEmission | undefined {
491
+ if (periodEmissionList.length === 0) {
492
+ return undefined
493
+ }
494
+ const currentTime = new Date().getTime() / 1000
495
+ const findRewardPeriodEmission = periodEmissionList.findLast((period) => d(currentTime).gte(period.time))
496
+ if (findRewardPeriodEmission) {
497
+ return findRewardPeriodEmission
498
+ }
499
+ return periodEmissionList[periodEmissionList.length - 1]
500
+ }
501
+
502
+ export function safeMulAmount(amount: Decimal, rate: Decimal): Decimal {
503
+ const result = amount.mul(rate)
504
+ if (result.gt(0) && result.lt(1)) {
505
+ throw new DlmmError(`Multiplication ${result} is less than 1`, DlmmErrorCode.AmountTooSmall)
506
+ }
507
+ return result.floor()
508
+ }
509
+
510
+ export function getRouterModule(strategy_type: StrategyType) {
511
+ switch (strategy_type) {
512
+ case StrategyType.Spot:
513
+ return 'spot'
514
+ case StrategyType.Curve:
515
+ return 'curve'
516
+ case StrategyType.BidAsk:
517
+ return 'bid_ask'
518
+ }
519
+ }
@@ -0,0 +1,121 @@
1
+ import { d } from '@cetusprotocol/common-sdk'
2
+ import { BinAmount, BinLiquidityInfo, StrategyType } from '../types/dlmm'
3
+ import { WeightUtils } from './weightUtils'
4
+
5
+ export class StrategyUtils {
6
+ /**
7
+ * Given a strategy type and amounts of X and Y, returns the distribution of liquidity.
8
+ * @param active_id The bin id of the active bin.
9
+ * @param bin_step The step size of each bin.
10
+ * @param min_bin_id The min bin id.
11
+ * @param max_bin_id The max bin id.
12
+ * @param amount_a The amount of X token to deposit.
13
+ * @param amount_b The amount of Y token to deposit.
14
+ * @param amount_a_in_active_bin The amount of X token in the active bin.
15
+ * @param amount_b_in_active_bin The amount of Y token in the active bin.
16
+ * @param strategy_type The strategy type.
17
+ * @returns The distribution of liquidity.
18
+ */
19
+ static toAmountsBothSideByStrategy(
20
+ active_id: number,
21
+ bin_step: number,
22
+ min_bin_id: number,
23
+ max_bin_id: number,
24
+ amount_a: string,
25
+ amount_b: string,
26
+ amount_a_in_active_bin: string,
27
+ amount_b_in_active_bin: string,
28
+ strategy_type: StrategyType
29
+ ): BinLiquidityInfo {
30
+ switch (strategy_type) {
31
+ case StrategyType.Spot: {
32
+ let weights = WeightUtils.toWeightSpotBalanced(min_bin_id, max_bin_id)
33
+ return WeightUtils.toAmountBothSide(
34
+ active_id,
35
+ bin_step,
36
+ amount_a,
37
+ amount_b,
38
+ amount_a_in_active_bin,
39
+ amount_b_in_active_bin,
40
+ weights
41
+ )
42
+ }
43
+ case StrategyType.Curve: {
44
+ let weights = WeightUtils.toWeightCurve(min_bin_id, max_bin_id, active_id)
45
+ return WeightUtils.toAmountBothSide(
46
+ active_id,
47
+ bin_step,
48
+ amount_a,
49
+ amount_b,
50
+ amount_a_in_active_bin,
51
+ amount_b_in_active_bin,
52
+ weights
53
+ )
54
+ }
55
+ case StrategyType.BidAsk: {
56
+ let weights = WeightUtils.toWeightBidAsk(min_bin_id, max_bin_id, active_id)
57
+ return WeightUtils.toAmountBothSide(
58
+ active_id,
59
+ bin_step,
60
+ amount_a,
61
+ amount_b,
62
+ amount_a_in_active_bin,
63
+ amount_b_in_active_bin,
64
+ weights
65
+ )
66
+ }
67
+ }
68
+ }
69
+
70
+ // only apply for
71
+ static autoFillCoinByStrategy(
72
+ active_id: number,
73
+ bin_step: number,
74
+ amount: string,
75
+ fix_amount_a: boolean,
76
+ amount_a_in_active_bin: string,
77
+ amount_b_in_active_bin: string,
78
+ min_bin_id: number,
79
+ max_bin_id: number,
80
+ strategy_type: StrategyType
81
+ ): BinLiquidityInfo {
82
+ switch (strategy_type) {
83
+ case StrategyType.Spot: {
84
+ let weights = WeightUtils.toWeightSpotBalanced(min_bin_id, max_bin_id)
85
+ return WeightUtils.autoFillCoinByWeight(
86
+ active_id,
87
+ bin_step,
88
+ amount,
89
+ fix_amount_a,
90
+ amount_a_in_active_bin,
91
+ amount_b_in_active_bin,
92
+ weights
93
+ )
94
+ }
95
+ case StrategyType.Curve: {
96
+ let weights = WeightUtils.toWeightCurve(min_bin_id, max_bin_id, active_id)
97
+ return WeightUtils.autoFillCoinByWeight(
98
+ active_id,
99
+ bin_step,
100
+ amount,
101
+ fix_amount_a,
102
+ amount_a_in_active_bin,
103
+ amount_b_in_active_bin,
104
+ weights
105
+ )
106
+ }
107
+ case StrategyType.BidAsk: {
108
+ let weights = WeightUtils.toWeightBidAsk(min_bin_id, max_bin_id, active_id)
109
+ return WeightUtils.autoFillCoinByWeight(
110
+ active_id,
111
+ bin_step,
112
+ amount,
113
+ fix_amount_a,
114
+ amount_a_in_active_bin,
115
+ amount_b_in_active_bin,
116
+ weights
117
+ )
118
+ }
119
+ }
120
+ }
121
+ }