@meteora-ag/dynamic-bonding-curve-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/README.md +53 -0
- package/dist/index.cjs +14641 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5024 -0
- package/dist/index.d.ts +5024 -0
- package/dist/index.js +14641 -0
- package/dist/index.js.map +1 -0
- package/docs.md +317 -0
- package/eslint.config.mjs +4 -0
- package/package.json +46 -0
- package/src/client.ts +1848 -0
- package/src/common.ts +275 -0
- package/src/constants.ts +42 -0
- package/src/derive.ts +488 -0
- package/src/design.ts +394 -0
- package/src/idl/damm-v1/idl.json +4615 -0
- package/src/idl/damm-v1/idl.ts +1158 -0
- package/src/idl/damm-v2/idl.json +6322 -0
- package/src/idl/damm-v2/idl.ts +5224 -0
- package/src/idl/dynamic-bonding-curve/idl.json +5351 -0
- package/src/idl/dynamic-bonding-curve/idl.ts +4428 -0
- package/src/idl/dynamic-vault/idl.json +1723 -0
- package/src/idl/dynamic-vault/idl.ts +295 -0
- package/src/index.ts +7 -0
- package/src/math/curve.ts +230 -0
- package/src/math/feeMath.ts +286 -0
- package/src/math/safeMath.ts +88 -0
- package/src/math/swapQuote.ts +464 -0
- package/src/math/utilsMath.ts +154 -0
- package/src/types.ts +465 -0
- package/src/utils.ts +252 -0
- package/tests/math/curveMath.test.ts +79 -0
- package/tests/math/feeMath.test.ts +22 -0
- package/tests/math/feeMode.test.ts +97 -0
- package/tests/math/pool.test.ts +46 -0
- package/tests/math/swapQuote.test.ts +248 -0
- package/tests/utils/defaults.ts +90 -0
- package/tests/utils/test-helpers.ts +110 -0
- package/tsconfig.json +10 -0
package/src/design.ts
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import Decimal from 'decimal.js'
|
|
2
|
+
import BN from 'bn.js'
|
|
3
|
+
import {
|
|
4
|
+
FeeSchedulerMode,
|
|
5
|
+
type ConfigParameters,
|
|
6
|
+
type DesignConstantProductCurveWithLockVestingParam,
|
|
7
|
+
type DesignConstantProductCurveWithoutLockVestingParam,
|
|
8
|
+
type DesignCurveParam,
|
|
9
|
+
type DesignCurveResponse,
|
|
10
|
+
} from './types'
|
|
11
|
+
import { MAX_SQRT_PRICE } from './constants'
|
|
12
|
+
import {
|
|
13
|
+
getLiquidityBuffer,
|
|
14
|
+
getBaseTokenForMigration,
|
|
15
|
+
getBaseTokenForSwap,
|
|
16
|
+
getPriceFromSqrtPrice,
|
|
17
|
+
getSqrtPriceFromPrice,
|
|
18
|
+
} from './common'
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Design the curve for the Constant Product curve with lock vesting
|
|
22
|
+
* @param designConstantProductCurveWithLockVestingParam - The parameters for the curve
|
|
23
|
+
* @returns The instruction parameters
|
|
24
|
+
*/
|
|
25
|
+
export function designConstantProductCurveWithLockVesting(
|
|
26
|
+
designConstantProductCurveWithLockVestingParam: DesignConstantProductCurveWithLockVestingParam
|
|
27
|
+
): ConfigParameters {
|
|
28
|
+
const {
|
|
29
|
+
totalTokenSupply,
|
|
30
|
+
percentageSupplyOnMigration,
|
|
31
|
+
lockVestingParams,
|
|
32
|
+
startPrice,
|
|
33
|
+
migrationPrice,
|
|
34
|
+
tokenBaseDecimal,
|
|
35
|
+
tokenQuoteDecimal,
|
|
36
|
+
baseFeeBps,
|
|
37
|
+
dynamicFeeEnabled,
|
|
38
|
+
activationType,
|
|
39
|
+
collectFeeMode,
|
|
40
|
+
migrationOption,
|
|
41
|
+
migrationFeeOption,
|
|
42
|
+
tokenType,
|
|
43
|
+
partnerLpPercentage,
|
|
44
|
+
creatorLpPercentage,
|
|
45
|
+
partnerLockedLpPercentage,
|
|
46
|
+
creatorLockedLpPercentage,
|
|
47
|
+
} = designConstantProductCurveWithLockVestingParam
|
|
48
|
+
|
|
49
|
+
const totalSupply = new BN(totalTokenSupply).mul(
|
|
50
|
+
new BN(10).pow(new BN(tokenBaseDecimal))
|
|
51
|
+
)
|
|
52
|
+
const baseDecimalFactor = new Decimal(10 ** tokenBaseDecimal)
|
|
53
|
+
const quoteDecimalFactor = new Decimal(10 ** tokenQuoteDecimal)
|
|
54
|
+
const preMigrationTokenSupply = totalSupply
|
|
55
|
+
const postMigrationTokenSupply = totalSupply
|
|
56
|
+
const migrationSupply = totalSupply
|
|
57
|
+
.mul(new BN(percentageSupplyOnMigration))
|
|
58
|
+
.div(new BN(100))
|
|
59
|
+
|
|
60
|
+
let lockedVestingAmount = totalSupply
|
|
61
|
+
.mul(new BN(lockVestingParams.percentageSupplyVesting))
|
|
62
|
+
.div(new BN(100))
|
|
63
|
+
|
|
64
|
+
const amountPerPeriod =
|
|
65
|
+
lockVestingParams.numberOfPeriod == 0
|
|
66
|
+
? new BN(0)
|
|
67
|
+
: lockedVestingAmount.div(new BN(lockVestingParams.numberOfPeriod))
|
|
68
|
+
lockedVestingAmount = amountPerPeriod.mul(
|
|
69
|
+
new BN(lockVestingParams.numberOfPeriod)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
const sqrtStartPrice = getSqrtPriceFromPrice(
|
|
73
|
+
startPrice.toString(),
|
|
74
|
+
tokenBaseDecimal,
|
|
75
|
+
tokenQuoteDecimal
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
const migrationSqrtPrice = getSqrtPriceFromPrice(
|
|
79
|
+
migrationPrice.toString(),
|
|
80
|
+
tokenBaseDecimal,
|
|
81
|
+
tokenQuoteDecimal
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
const priceDelta = migrationSqrtPrice.sub(sqrtStartPrice)
|
|
85
|
+
|
|
86
|
+
const migrationQuoteThresholdFloat = migrationPrice
|
|
87
|
+
.mul(new Decimal(migrationSupply.toString()))
|
|
88
|
+
.mul(quoteDecimalFactor)
|
|
89
|
+
.div(baseDecimalFactor)
|
|
90
|
+
.floor()
|
|
91
|
+
|
|
92
|
+
const migrationQuoteThreshold = new BN(
|
|
93
|
+
migrationQuoteThresholdFloat.toString()
|
|
94
|
+
)
|
|
95
|
+
const liquidity = migrationQuoteThreshold.shln(128).div(priceDelta)
|
|
96
|
+
const curves = [
|
|
97
|
+
{
|
|
98
|
+
sqrtPrice: migrationSqrtPrice,
|
|
99
|
+
liquidity,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
sqrtPrice: MAX_SQRT_PRICE,
|
|
103
|
+
liquidity: getLiquidityBuffer(
|
|
104
|
+
liquidity,
|
|
105
|
+
migrationSqrtPrice,
|
|
106
|
+
MAX_SQRT_PRICE
|
|
107
|
+
),
|
|
108
|
+
},
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
// reverse to get amount on swap
|
|
112
|
+
const maxSwapAmount = getBaseTokenForSwap(
|
|
113
|
+
sqrtStartPrice,
|
|
114
|
+
MAX_SQRT_PRICE,
|
|
115
|
+
curves
|
|
116
|
+
)
|
|
117
|
+
const migrationAmount = getBaseTokenForMigration(
|
|
118
|
+
migrationSqrtPrice,
|
|
119
|
+
migrationQuoteThreshold
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
const cliffUnlockAmount =
|
|
123
|
+
lockVestingParams.cliffUnlockEnabled == false
|
|
124
|
+
? new BN(0)
|
|
125
|
+
: totalSupply
|
|
126
|
+
.sub(maxSwapAmount)
|
|
127
|
+
.sub(lockedVestingAmount)
|
|
128
|
+
.sub(migrationAmount)
|
|
129
|
+
|
|
130
|
+
const config: ConfigParameters = {
|
|
131
|
+
poolFees: {
|
|
132
|
+
baseFee: {
|
|
133
|
+
cliffFeeNumerator: new BN((baseFeeBps * 100000).toString()),
|
|
134
|
+
numberOfPeriod: 0,
|
|
135
|
+
reductionFactor: new BN('0'),
|
|
136
|
+
periodFrequency: new BN('0'),
|
|
137
|
+
feeSchedulerMode: FeeSchedulerMode.Linear,
|
|
138
|
+
},
|
|
139
|
+
dynamicFee: dynamicFeeEnabled
|
|
140
|
+
? {
|
|
141
|
+
binStep: 1,
|
|
142
|
+
binStepU128: new BN('1844674407370955'),
|
|
143
|
+
filterPeriod: 10,
|
|
144
|
+
decayPeriod: 120,
|
|
145
|
+
reductionFactor: 5000,
|
|
146
|
+
variableFeeControl: 2000000,
|
|
147
|
+
maxVolatilityAccumulator: 100000,
|
|
148
|
+
}
|
|
149
|
+
: null,
|
|
150
|
+
},
|
|
151
|
+
activationType: activationType,
|
|
152
|
+
collectFeeMode: collectFeeMode,
|
|
153
|
+
migrationOption: migrationOption,
|
|
154
|
+
tokenType: tokenType,
|
|
155
|
+
tokenDecimal: tokenBaseDecimal,
|
|
156
|
+
migrationQuoteThreshold: new BN(migrationQuoteThreshold.toString()),
|
|
157
|
+
partnerLpPercentage: partnerLpPercentage,
|
|
158
|
+
creatorLpPercentage: creatorLpPercentage,
|
|
159
|
+
partnerLockedLpPercentage: partnerLockedLpPercentage,
|
|
160
|
+
creatorLockedLpPercentage: creatorLockedLpPercentage,
|
|
161
|
+
sqrtStartPrice: new BN(sqrtStartPrice.toString()),
|
|
162
|
+
lockedVesting: {
|
|
163
|
+
amountPerPeriod: new BN(amountPerPeriod.toString()),
|
|
164
|
+
cliffDurationFromMigrationTime: new BN('0'),
|
|
165
|
+
frequency: new BN(lockVestingParams.frequency.toString()),
|
|
166
|
+
numberOfPeriod: new BN(lockVestingParams.numberOfPeriod.toString()),
|
|
167
|
+
cliffUnlockAmount: new BN(cliffUnlockAmount.toString()),
|
|
168
|
+
},
|
|
169
|
+
migrationFeeOption: migrationFeeOption,
|
|
170
|
+
tokenSupply: {
|
|
171
|
+
preMigrationTokenSupply: new BN(preMigrationTokenSupply.toString()),
|
|
172
|
+
postMigrationTokenSupply: new BN(
|
|
173
|
+
postMigrationTokenSupply.toString()
|
|
174
|
+
),
|
|
175
|
+
},
|
|
176
|
+
padding: [
|
|
177
|
+
new BN(0),
|
|
178
|
+
new BN(0),
|
|
179
|
+
new BN(0),
|
|
180
|
+
new BN(0),
|
|
181
|
+
new BN(0),
|
|
182
|
+
new BN(0),
|
|
183
|
+
new BN(0),
|
|
184
|
+
],
|
|
185
|
+
curve: curves.map((point) => ({
|
|
186
|
+
sqrtPrice: new BN(point.sqrtPrice.toString()),
|
|
187
|
+
liquidity: new BN(point.liquidity.toString()),
|
|
188
|
+
})),
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return config
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Design the curve for the Constant Product curve without lock vesting
|
|
196
|
+
* @param designConstantProductCurveWithoutLockVestingParam - The parameters for the curve
|
|
197
|
+
* @returns The instruction parameters
|
|
198
|
+
*/
|
|
199
|
+
export function designConstantProductCurveWithoutLockVesting(
|
|
200
|
+
designConstantProductCurveWithoutLockVestingParam: DesignConstantProductCurveWithoutLockVestingParam
|
|
201
|
+
): ConfigParameters {
|
|
202
|
+
const {
|
|
203
|
+
totalTokenSupply,
|
|
204
|
+
percentageSupplyOnMigration,
|
|
205
|
+
startPrice,
|
|
206
|
+
tokenBaseDecimal,
|
|
207
|
+
tokenQuoteDecimal,
|
|
208
|
+
baseFeeBps,
|
|
209
|
+
dynamicFeeEnabled,
|
|
210
|
+
activationType,
|
|
211
|
+
collectFeeMode,
|
|
212
|
+
migrationOption,
|
|
213
|
+
migrationFeeOption,
|
|
214
|
+
tokenType,
|
|
215
|
+
partnerLpPercentage,
|
|
216
|
+
creatorLpPercentage,
|
|
217
|
+
partnerLockedLpPercentage,
|
|
218
|
+
creatorLockedLpPercentage,
|
|
219
|
+
} = designConstantProductCurveWithoutLockVestingParam
|
|
220
|
+
|
|
221
|
+
const totalSupply = new BN(totalTokenSupply).mul(
|
|
222
|
+
new BN(10).pow(new BN(tokenBaseDecimal))
|
|
223
|
+
)
|
|
224
|
+
const baseDecimalFactor = new Decimal(10 ** tokenBaseDecimal)
|
|
225
|
+
const quoteDecimalFactor = new Decimal(10 ** tokenQuoteDecimal)
|
|
226
|
+
const preMigrationTokenSupply = totalSupply
|
|
227
|
+
const postMigrationTokenSupply = totalSupply
|
|
228
|
+
const migrationSupply = totalSupply
|
|
229
|
+
.mul(new BN(percentageSupplyOnMigration))
|
|
230
|
+
.div(new BN(100))
|
|
231
|
+
const swapSupply = totalSupply.sub(migrationSupply)
|
|
232
|
+
|
|
233
|
+
const sqrtStartPrice = getSqrtPriceFromPrice(
|
|
234
|
+
startPrice.toString(),
|
|
235
|
+
tokenBaseDecimal,
|
|
236
|
+
tokenQuoteDecimal
|
|
237
|
+
)
|
|
238
|
+
let migrationSqrtPrice = sqrtStartPrice.mul(swapSupply).div(migrationSupply)
|
|
239
|
+
migrationSqrtPrice = migrationSqrtPrice.sub(new BN(1))
|
|
240
|
+
const priceDelta = migrationSqrtPrice.sub(sqrtStartPrice)
|
|
241
|
+
|
|
242
|
+
const migrationPrice = getPriceFromSqrtPrice(
|
|
243
|
+
migrationSqrtPrice,
|
|
244
|
+
tokenBaseDecimal,
|
|
245
|
+
tokenQuoteDecimal
|
|
246
|
+
)
|
|
247
|
+
const migrationQuoteThresholdFloat = migrationPrice
|
|
248
|
+
.mul(new Decimal(migrationSupply.toString()))
|
|
249
|
+
.mul(quoteDecimalFactor)
|
|
250
|
+
.div(baseDecimalFactor)
|
|
251
|
+
.floor()
|
|
252
|
+
|
|
253
|
+
const migrationQuoteThreshold = new BN(
|
|
254
|
+
migrationQuoteThresholdFloat.toString()
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
const liquidity = migrationQuoteThreshold.shln(128).div(priceDelta)
|
|
258
|
+
const curves = [
|
|
259
|
+
{
|
|
260
|
+
sqrtPrice: migrationSqrtPrice,
|
|
261
|
+
liquidity,
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
sqrtPrice: MAX_SQRT_PRICE,
|
|
265
|
+
liquidity: getLiquidityBuffer(
|
|
266
|
+
liquidity,
|
|
267
|
+
migrationSqrtPrice,
|
|
268
|
+
MAX_SQRT_PRICE
|
|
269
|
+
),
|
|
270
|
+
},
|
|
271
|
+
]
|
|
272
|
+
|
|
273
|
+
const config: ConfigParameters = {
|
|
274
|
+
poolFees: {
|
|
275
|
+
baseFee: {
|
|
276
|
+
cliffFeeNumerator: new BN((baseFeeBps * 100000).toString()),
|
|
277
|
+
numberOfPeriod: 0,
|
|
278
|
+
reductionFactor: new BN('0'),
|
|
279
|
+
periodFrequency: new BN('0'),
|
|
280
|
+
feeSchedulerMode: FeeSchedulerMode.Linear,
|
|
281
|
+
},
|
|
282
|
+
dynamicFee: dynamicFeeEnabled
|
|
283
|
+
? {
|
|
284
|
+
binStep: 1,
|
|
285
|
+
binStepU128: new BN('1844674407370955'),
|
|
286
|
+
filterPeriod: 10,
|
|
287
|
+
decayPeriod: 120,
|
|
288
|
+
reductionFactor: 5000,
|
|
289
|
+
variableFeeControl: 2000000,
|
|
290
|
+
maxVolatilityAccumulator: 100000,
|
|
291
|
+
}
|
|
292
|
+
: null,
|
|
293
|
+
},
|
|
294
|
+
activationType: activationType,
|
|
295
|
+
collectFeeMode: collectFeeMode,
|
|
296
|
+
migrationOption: migrationOption,
|
|
297
|
+
tokenType: tokenType,
|
|
298
|
+
tokenDecimal: tokenBaseDecimal,
|
|
299
|
+
migrationQuoteThreshold: new BN(migrationQuoteThreshold.toString()),
|
|
300
|
+
partnerLpPercentage: partnerLpPercentage,
|
|
301
|
+
creatorLpPercentage: creatorLpPercentage,
|
|
302
|
+
partnerLockedLpPercentage: partnerLockedLpPercentage,
|
|
303
|
+
creatorLockedLpPercentage: creatorLockedLpPercentage,
|
|
304
|
+
sqrtStartPrice: new BN(sqrtStartPrice.toString()),
|
|
305
|
+
lockedVesting: {
|
|
306
|
+
amountPerPeriod: new BN('0'),
|
|
307
|
+
cliffDurationFromMigrationTime: new BN('0'),
|
|
308
|
+
frequency: new BN('0'),
|
|
309
|
+
numberOfPeriod: new BN('0'),
|
|
310
|
+
cliffUnlockAmount: new BN('0'),
|
|
311
|
+
},
|
|
312
|
+
migrationFeeOption: migrationFeeOption,
|
|
313
|
+
tokenSupply: {
|
|
314
|
+
preMigrationTokenSupply: new BN(preMigrationTokenSupply.toString()),
|
|
315
|
+
postMigrationTokenSupply: new BN(
|
|
316
|
+
postMigrationTokenSupply.toString()
|
|
317
|
+
),
|
|
318
|
+
},
|
|
319
|
+
padding: [
|
|
320
|
+
new BN(0),
|
|
321
|
+
new BN(0),
|
|
322
|
+
new BN(0),
|
|
323
|
+
new BN(0),
|
|
324
|
+
new BN(0),
|
|
325
|
+
new BN(0),
|
|
326
|
+
new BN(0),
|
|
327
|
+
],
|
|
328
|
+
curve: curves.map((point) => ({
|
|
329
|
+
sqrtPrice: new BN(point.sqrtPrice.toString()),
|
|
330
|
+
liquidity: new BN(point.liquidity.toString()),
|
|
331
|
+
})),
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return config
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Design a Constant Product curve
|
|
339
|
+
* @param params - The parameters for the curve
|
|
340
|
+
* @returns The instruction parameters
|
|
341
|
+
*/
|
|
342
|
+
export async function designCurve(
|
|
343
|
+
params: DesignCurveParam
|
|
344
|
+
): Promise<DesignCurveResponse> {
|
|
345
|
+
const {
|
|
346
|
+
tokenDecimal,
|
|
347
|
+
migrationQuoteThreshold,
|
|
348
|
+
tokenBaseSupply,
|
|
349
|
+
migrationBasePercent,
|
|
350
|
+
} = params
|
|
351
|
+
|
|
352
|
+
const Q64 = new BN(2).pow(new BN(64))
|
|
353
|
+
const Q128 = Q64.mul(Q64)
|
|
354
|
+
const Q64_DEC = new Decimal(Q64.toString())
|
|
355
|
+
|
|
356
|
+
// Scale the base supply by the migration percent and token decimals
|
|
357
|
+
// baseSupplyDecimal: e.g. 1e9
|
|
358
|
+
// migrationBaseSupplyDecimal = 1e9 * 0.15 * 10^9 = 1.5e17
|
|
359
|
+
const baseSupplyDecimal = new Decimal(tokenBaseSupply.toString())
|
|
360
|
+
const migrationBaseSupplyDecimal = baseSupplyDecimal
|
|
361
|
+
.mul(migrationBasePercent / 100)
|
|
362
|
+
.mul(new Decimal(10).pow(tokenDecimal))
|
|
363
|
+
|
|
364
|
+
// quoteThresholdDecimal: e.g. 80 * 10^9
|
|
365
|
+
const quoteThresholdDecimal = new Decimal(
|
|
366
|
+
migrationQuoteThreshold.toString()
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
// Compute Pmax = ceil( sqrt(quote/base) * 2^64 )
|
|
370
|
+
const priceDecimal = quoteThresholdDecimal.div(migrationBaseSupplyDecimal)
|
|
371
|
+
const sqrtPriceDecimal = priceDecimal.sqrt()
|
|
372
|
+
const PmaxDEC = sqrtPriceDecimal.mul(Q64_DEC).ceil()
|
|
373
|
+
const PmaxBN = new BN(PmaxDEC.toFixed(0), 10)
|
|
374
|
+
|
|
375
|
+
// Pmin = floor((2^128 / 10_000_000) / Pmax)
|
|
376
|
+
const ratioBN = Q128.div(new BN(10_000_000))
|
|
377
|
+
const PminBN = ratioBN.div(PmaxBN)
|
|
378
|
+
|
|
379
|
+
// sqrt_start_price in Q64 is exactly Pmin
|
|
380
|
+
const sqrtStartPrice = PminBN
|
|
381
|
+
|
|
382
|
+
// liquidity = floor( quote * 2^128 / (Pmax – Pmin) )
|
|
383
|
+
const liquidity = migrationQuoteThreshold.mul(Q128).div(PmaxBN.sub(PminBN))
|
|
384
|
+
|
|
385
|
+
return {
|
|
386
|
+
sqrtStartPrice,
|
|
387
|
+
curve: [
|
|
388
|
+
{
|
|
389
|
+
sqrtPrice: MAX_SQRT_PRICE,
|
|
390
|
+
liquidity,
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
}
|
|
394
|
+
}
|