@meteora-ag/dynamic-bonding-curve-sdk 1.2.2 → 1.2.4
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/dist/index.cjs +550 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +186 -52
- package/dist/index.d.ts +186 -52
- package/dist/index.js +601 -187
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/services/pool.ts
|
|
2
2
|
import {
|
|
3
3
|
PublicKey as PublicKey9,
|
|
4
|
-
Transaction as Transaction2
|
|
4
|
+
Transaction as Transaction2,
|
|
5
|
+
SYSVAR_INSTRUCTIONS_PUBKEY
|
|
5
6
|
} from "@solana/web3.js";
|
|
6
7
|
|
|
7
8
|
// src/types.ts
|
|
@@ -30,11 +31,12 @@ var GetFeeMode = /* @__PURE__ */ ((GetFeeMode2) => {
|
|
|
30
31
|
GetFeeMode2[GetFeeMode2["OutputToken"] = 1] = "OutputToken";
|
|
31
32
|
return GetFeeMode2;
|
|
32
33
|
})(GetFeeMode || {});
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
var BaseFeeMode = /* @__PURE__ */ ((BaseFeeMode3) => {
|
|
35
|
+
BaseFeeMode3[BaseFeeMode3["FeeSchedulerLinear"] = 0] = "FeeSchedulerLinear";
|
|
36
|
+
BaseFeeMode3[BaseFeeMode3["FeeSchedulerExponential"] = 1] = "FeeSchedulerExponential";
|
|
37
|
+
BaseFeeMode3[BaseFeeMode3["RateLimiter"] = 2] = "RateLimiter";
|
|
38
|
+
return BaseFeeMode3;
|
|
39
|
+
})(BaseFeeMode || {});
|
|
38
40
|
var MigrationFeeOption = /* @__PURE__ */ ((MigrationFeeOption2) => {
|
|
39
41
|
MigrationFeeOption2[MigrationFeeOption2["FixedBps25"] = 0] = "FixedBps25";
|
|
40
42
|
MigrationFeeOption2[MigrationFeeOption2["FixedBps30"] = 1] = "FixedBps30";
|
|
@@ -77,12 +79,17 @@ var MAX_SQRT_PRICE = new BN("79226673521066979257578248091");
|
|
|
77
79
|
var RESOLUTION = 64;
|
|
78
80
|
var ONE_Q64 = new BN(1).shln(RESOLUTION);
|
|
79
81
|
var FEE_DENOMINATOR = 1e9;
|
|
80
|
-
var
|
|
82
|
+
var MAX_FEE_BPS = 9900;
|
|
83
|
+
var MIN_FEE_BPS = 1;
|
|
84
|
+
var MIN_FEE_NUMERATOR = 1e5;
|
|
85
|
+
var MAX_FEE_NUMERATOR = 99e7;
|
|
81
86
|
var BASIS_POINT_MAX = 1e4;
|
|
82
87
|
var MAX_CURVE_POINT = 16;
|
|
83
88
|
var PARTNER_SURPLUS_SHARE = 80;
|
|
84
89
|
var SWAP_BUFFER_PERCENTAGE = 25;
|
|
85
90
|
var MAX_SWALLOW_PERCENTAGE = 20;
|
|
91
|
+
var MAX_RATE_LIMITER_DURATION_IN_SECONDS = 43200;
|
|
92
|
+
var MAX_RATE_LIMITER_DURATION_IN_SLOTS = 108e3;
|
|
86
93
|
var SLOT_DURATION = 400;
|
|
87
94
|
var TIMESTAMP_DURATION = 1e3;
|
|
88
95
|
var DYNAMIC_BONDING_CURVE_PROGRAM_ID = new PublicKey(
|
|
@@ -696,7 +703,7 @@ var getPercentageSupplyOnMigration = (initialMarketCap, migrationMarketCap, lock
|
|
|
696
703
|
var getMigrationQuoteAmount = (migrationMarketCap, percentageSupplyOnMigration) => {
|
|
697
704
|
return migrationMarketCap.mul(percentageSupplyOnMigration).div(new Decimal2(100));
|
|
698
705
|
};
|
|
699
|
-
function
|
|
706
|
+
function getFeeSchedulerParams(startingBaseFeeBps, endingBaseFeeBps, baseFeeMode, numberOfPeriod, totalDuration) {
|
|
700
707
|
if (startingBaseFeeBps == endingBaseFeeBps) {
|
|
701
708
|
if (numberOfPeriod != 0 || totalDuration != 0) {
|
|
702
709
|
throw new Error(
|
|
@@ -705,20 +712,18 @@ function getBaseFeeParams(startingBaseFeeBps, endingBaseFeeBps, feeSchedulerMode
|
|
|
705
712
|
}
|
|
706
713
|
return {
|
|
707
714
|
cliffFeeNumerator: bpsToFeeNumerator(startingBaseFeeBps),
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
715
|
+
firstFactor: 0,
|
|
716
|
+
secondFactor: new BN6(0),
|
|
717
|
+
thirdFactor: new BN6(0),
|
|
718
|
+
baseFeeMode: 0 /* FeeSchedulerLinear */
|
|
712
719
|
};
|
|
713
720
|
}
|
|
714
721
|
if (numberOfPeriod <= 0) {
|
|
715
722
|
throw new Error("Total periods must be greater than zero");
|
|
716
723
|
}
|
|
717
|
-
if (startingBaseFeeBps >
|
|
724
|
+
if (startingBaseFeeBps > MAX_FEE_BPS) {
|
|
718
725
|
throw new Error(
|
|
719
|
-
`startingBaseFeeBps (${startingBaseFeeBps} bps) exceeds maximum allowed value of ${
|
|
720
|
-
new BN6(MAX_FEE_NUMERATOR)
|
|
721
|
-
)} bps`
|
|
726
|
+
`startingBaseFeeBps (${startingBaseFeeBps} bps) exceeds maximum allowed value of ${MAX_FEE_BPS} bps`
|
|
722
727
|
);
|
|
723
728
|
}
|
|
724
729
|
if (endingBaseFeeBps > startingBaseFeeBps) {
|
|
@@ -735,7 +740,7 @@ function getBaseFeeParams(startingBaseFeeBps, endingBaseFeeBps, feeSchedulerMode
|
|
|
735
740
|
const minBaseFeeNumerator = bpsToFeeNumerator(endingBaseFeeBps);
|
|
736
741
|
const periodFrequency = new BN6(totalDuration / numberOfPeriod);
|
|
737
742
|
let reductionFactor;
|
|
738
|
-
if (
|
|
743
|
+
if (baseFeeMode == 0 /* FeeSchedulerLinear */) {
|
|
739
744
|
const totalReduction = maxBaseFeeNumerator.sub(minBaseFeeNumerator);
|
|
740
745
|
reductionFactor = totalReduction.divn(numberOfPeriod);
|
|
741
746
|
} else {
|
|
@@ -745,15 +750,15 @@ function getBaseFeeParams(startingBaseFeeBps, endingBaseFeeBps, feeSchedulerMode
|
|
|
745
750
|
}
|
|
746
751
|
return {
|
|
747
752
|
cliffFeeNumerator: maxBaseFeeNumerator,
|
|
748
|
-
numberOfPeriod,
|
|
749
|
-
periodFrequency,
|
|
750
|
-
reductionFactor,
|
|
751
|
-
|
|
753
|
+
firstFactor: numberOfPeriod,
|
|
754
|
+
secondFactor: periodFrequency,
|
|
755
|
+
thirdFactor: reductionFactor,
|
|
756
|
+
baseFeeMode
|
|
752
757
|
};
|
|
753
758
|
}
|
|
754
|
-
function
|
|
759
|
+
function calculateFeeSchedulerEndingBaseFeeBps(cliffFeeNumerator, numberOfPeriod, reductionFactor, baseFeeMode) {
|
|
755
760
|
let baseFeeNumerator;
|
|
756
|
-
if (
|
|
761
|
+
if (baseFeeMode == 0 /* FeeSchedulerLinear */) {
|
|
757
762
|
baseFeeNumerator = cliffFeeNumerator - numberOfPeriod * reductionFactor;
|
|
758
763
|
} else {
|
|
759
764
|
const decayRate = 1 - reductionFactor / BASIS_POINT_MAX;
|
|
@@ -761,6 +766,53 @@ function getMinBaseFeeBps(cliffFeeNumerator, numberOfPeriod, reductionFactor, fe
|
|
|
761
766
|
}
|
|
762
767
|
return Math.max(0, baseFeeNumerator / FEE_DENOMINATOR * BASIS_POINT_MAX);
|
|
763
768
|
}
|
|
769
|
+
function getRateLimiterParams(baseFeeBps, feeIncrementBps, referenceAmount, maxLimiterDuration, tokenQuoteDecimal, activationType) {
|
|
770
|
+
const cliffFeeNumerator = bpsToFeeNumerator(baseFeeBps);
|
|
771
|
+
const feeIncrementNumerator = bpsToFeeNumerator(feeIncrementBps);
|
|
772
|
+
if (baseFeeBps <= 0 || feeIncrementBps <= 0 || referenceAmount <= 0 || maxLimiterDuration <= 0) {
|
|
773
|
+
throw new Error("All rate limiter parameters must be greater than zero");
|
|
774
|
+
}
|
|
775
|
+
if (baseFeeBps > MAX_FEE_BPS) {
|
|
776
|
+
throw new Error(
|
|
777
|
+
`Base fee (${baseFeeBps} bps) exceeds maximum allowed value of ${MAX_FEE_BPS} bps`
|
|
778
|
+
);
|
|
779
|
+
}
|
|
780
|
+
if (feeIncrementBps > MAX_FEE_BPS) {
|
|
781
|
+
throw new Error(
|
|
782
|
+
`Fee increment (${feeIncrementBps} bps) exceeds maximum allowed value of ${MAX_FEE_BPS} bps`
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
if (feeIncrementNumerator.gte(new BN6(FEE_DENOMINATOR))) {
|
|
786
|
+
throw new Error(
|
|
787
|
+
"Fee increment numerator must be less than FEE_DENOMINATOR"
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
const deltaNumerator = new BN6(MAX_FEE_NUMERATOR).sub(cliffFeeNumerator);
|
|
791
|
+
const maxIndex = deltaNumerator.div(feeIncrementNumerator);
|
|
792
|
+
if (maxIndex.lt(new BN6(1))) {
|
|
793
|
+
throw new Error("Fee increment is too large for the given base fee");
|
|
794
|
+
}
|
|
795
|
+
if (cliffFeeNumerator.lt(new BN6(MIN_FEE_NUMERATOR)) || cliffFeeNumerator.gt(new BN6(MAX_FEE_NUMERATOR))) {
|
|
796
|
+
throw new Error("Base fee must be between 0.01% and 99%");
|
|
797
|
+
}
|
|
798
|
+
const maxDuration = activationType === 0 /* Slot */ ? MAX_RATE_LIMITER_DURATION_IN_SLOTS : MAX_RATE_LIMITER_DURATION_IN_SECONDS;
|
|
799
|
+
if (maxLimiterDuration > maxDuration) {
|
|
800
|
+
throw new Error(
|
|
801
|
+
`Max duration exceeds maximum allowed value of ${maxDuration}`
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
const referenceAmountInLamports = convertToLamports(
|
|
805
|
+
referenceAmount,
|
|
806
|
+
tokenQuoteDecimal
|
|
807
|
+
);
|
|
808
|
+
return {
|
|
809
|
+
cliffFeeNumerator,
|
|
810
|
+
firstFactor: feeIncrementBps,
|
|
811
|
+
secondFactor: new BN6(maxLimiterDuration),
|
|
812
|
+
thirdFactor: new BN6(referenceAmountInLamports),
|
|
813
|
+
baseFeeMode: 2 /* RateLimiter */
|
|
814
|
+
};
|
|
815
|
+
}
|
|
764
816
|
function getDynamicFeeParams(baseFeeBps, maxPriceChangeBps = MAX_PRICE_CHANGE_BPS_DEFAULT) {
|
|
765
817
|
if (maxPriceChangeBps > MAX_PRICE_CHANGE_BPS_DEFAULT) {
|
|
766
818
|
throw new Error(
|
|
@@ -881,6 +933,46 @@ var getTwoCurve = (migrationSqrtPrice, midSqrtPrice, initialSqrtPrice, swapAmoun
|
|
|
881
933
|
]
|
|
882
934
|
};
|
|
883
935
|
};
|
|
936
|
+
function checkRateLimiterApplied(baseFeeMode, swapBaseForQuote, currentPoint, activationPoint, maxLimiterDuration) {
|
|
937
|
+
return baseFeeMode === 2 /* RateLimiter */ && !swapBaseForQuote && currentPoint.gte(activationPoint) && currentPoint.lte(activationPoint.add(maxLimiterDuration));
|
|
938
|
+
}
|
|
939
|
+
function getBaseFeeParams(baseFeeParams, tokenQuoteDecimal, activationType) {
|
|
940
|
+
if (baseFeeParams.baseFeeMode === 2 /* RateLimiter */) {
|
|
941
|
+
if (!baseFeeParams.rateLimiterParam) {
|
|
942
|
+
throw new Error(
|
|
943
|
+
"Rate limiter parameters are required for RateLimiter mode"
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
const {
|
|
947
|
+
baseFeeBps,
|
|
948
|
+
feeIncrementBps,
|
|
949
|
+
referenceAmount,
|
|
950
|
+
maxLimiterDuration
|
|
951
|
+
} = baseFeeParams.rateLimiterParam;
|
|
952
|
+
return getRateLimiterParams(
|
|
953
|
+
baseFeeBps,
|
|
954
|
+
feeIncrementBps,
|
|
955
|
+
referenceAmount,
|
|
956
|
+
maxLimiterDuration,
|
|
957
|
+
tokenQuoteDecimal,
|
|
958
|
+
activationType
|
|
959
|
+
);
|
|
960
|
+
} else {
|
|
961
|
+
if (!baseFeeParams.feeSchedulerParam) {
|
|
962
|
+
throw new Error(
|
|
963
|
+
"Fee scheduler parameters are required for FeeScheduler mode"
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
const { startingFeeBps, endingFeeBps, numberOfPeriod, totalDuration } = baseFeeParams.feeSchedulerParam;
|
|
967
|
+
return getFeeSchedulerParams(
|
|
968
|
+
startingFeeBps,
|
|
969
|
+
endingFeeBps,
|
|
970
|
+
baseFeeParams.baseFeeMode,
|
|
971
|
+
numberOfPeriod,
|
|
972
|
+
totalDuration
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
884
976
|
|
|
885
977
|
// src/helpers/accounts.ts
|
|
886
978
|
import { PublicKey as PublicKey4 } from "@solana/web3.js";
|
|
@@ -1143,15 +1235,160 @@ function deriveBaseKeyForLocker(virtualPool) {
|
|
|
1143
1235
|
}
|
|
1144
1236
|
|
|
1145
1237
|
// src/helpers/validation.ts
|
|
1146
|
-
import
|
|
1238
|
+
import BN8 from "bn.js";
|
|
1147
1239
|
import { PublicKey as PublicKey5 } from "@solana/web3.js";
|
|
1148
1240
|
import Decimal3 from "decimal.js";
|
|
1149
|
-
|
|
1241
|
+
|
|
1242
|
+
// src/math/rateLimiter.ts
|
|
1243
|
+
import BN7 from "bn.js";
|
|
1244
|
+
function getMaxIndex(cliffFeeNumerator, feeIncrementBps) {
|
|
1245
|
+
const deltaNumerator = new BN7(MAX_FEE_NUMERATOR).sub(cliffFeeNumerator);
|
|
1246
|
+
const feeIncrementNumerator = mulDiv(
|
|
1247
|
+
new BN7(feeIncrementBps),
|
|
1248
|
+
new BN7(FEE_DENOMINATOR),
|
|
1249
|
+
new BN7(BASIS_POINT_MAX),
|
|
1250
|
+
1 /* Down */
|
|
1251
|
+
);
|
|
1252
|
+
return deltaNumerator.div(feeIncrementNumerator);
|
|
1253
|
+
}
|
|
1254
|
+
function getFeeNumeratorOnRateLimiter(cliffFeeNumerator, referenceAmount, feeIncrementBps, inputAmount) {
|
|
1255
|
+
if (inputAmount.lte(referenceAmount)) {
|
|
1256
|
+
return cliffFeeNumerator;
|
|
1257
|
+
}
|
|
1258
|
+
const c = new BN7(cliffFeeNumerator);
|
|
1259
|
+
const diff = inputAmount.sub(referenceAmount);
|
|
1260
|
+
const a = new BN7(diff.div(referenceAmount));
|
|
1261
|
+
const b = new BN7(diff.mod(referenceAmount));
|
|
1262
|
+
const maxIndex = new BN7(getMaxIndex(cliffFeeNumerator, feeIncrementBps));
|
|
1263
|
+
const i = mulDiv(
|
|
1264
|
+
new BN7(feeIncrementBps),
|
|
1265
|
+
new BN7(FEE_DENOMINATOR),
|
|
1266
|
+
new BN7(BASIS_POINT_MAX),
|
|
1267
|
+
1 /* Down */
|
|
1268
|
+
);
|
|
1269
|
+
const x0 = new BN7(referenceAmount);
|
|
1270
|
+
const one = new BN7(1);
|
|
1271
|
+
const two = new BN7(2);
|
|
1272
|
+
let tradingFeeNumerator;
|
|
1273
|
+
if (a.lt(maxIndex)) {
|
|
1274
|
+
let numerator1 = c.add(c.mul(a)).add(i.mul(a).mul(a.add(one)).div(two));
|
|
1275
|
+
let numerator2 = c.add(i.mul(a.add(one)));
|
|
1276
|
+
let firstFee = x0.mul(numerator1);
|
|
1277
|
+
let secondFee = b.mul(numerator2);
|
|
1278
|
+
tradingFeeNumerator = firstFee.add(secondFee);
|
|
1279
|
+
} else {
|
|
1280
|
+
let numerator1 = c.add(c.mul(maxIndex)).add(i.mul(maxIndex).mul(maxIndex.add(one)).div(two));
|
|
1281
|
+
let numerator2 = new BN7(MAX_FEE_NUMERATOR);
|
|
1282
|
+
let firstFee = x0.mul(numerator1);
|
|
1283
|
+
let d = a.sub(maxIndex);
|
|
1284
|
+
let leftAmount = d.mul(x0).add(b);
|
|
1285
|
+
let secondFee = leftAmount.mul(numerator2);
|
|
1286
|
+
tradingFeeNumerator = firstFee.add(secondFee);
|
|
1287
|
+
}
|
|
1288
|
+
const denominator = new BN7(FEE_DENOMINATOR);
|
|
1289
|
+
const tradingFee = tradingFeeNumerator.add(denominator).sub(one).div(denominator);
|
|
1290
|
+
const feeNumerator = mulDiv(
|
|
1291
|
+
tradingFee,
|
|
1292
|
+
new BN7(FEE_DENOMINATOR),
|
|
1293
|
+
inputAmount,
|
|
1294
|
+
0 /* Up */
|
|
1295
|
+
);
|
|
1296
|
+
return BN7.min(feeNumerator, new BN7(MAX_FEE_NUMERATOR));
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
// src/helpers/validation.ts
|
|
1300
|
+
function validatePoolFees(poolFees, collectFeeMode, activationType) {
|
|
1150
1301
|
if (!poolFees) return false;
|
|
1151
1302
|
if (poolFees.baseFee) {
|
|
1152
|
-
if (poolFees.baseFee.cliffFeeNumerator.lte(new
|
|
1303
|
+
if (poolFees.baseFee.cliffFeeNumerator.lte(new BN8(0))) {
|
|
1153
1304
|
return false;
|
|
1154
1305
|
}
|
|
1306
|
+
if (poolFees.baseFee.baseFeeMode === 0 /* FeeSchedulerLinear */ || poolFees.baseFee.baseFeeMode === 1 /* FeeSchedulerExponential */) {
|
|
1307
|
+
if (!validateFeeScheduler(poolFees.baseFee)) {
|
|
1308
|
+
return false;
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
if (poolFees.baseFee.baseFeeMode === 2 /* RateLimiter */) {
|
|
1312
|
+
if (!validateFeeRateLimiter(
|
|
1313
|
+
poolFees.baseFee,
|
|
1314
|
+
collectFeeMode,
|
|
1315
|
+
activationType
|
|
1316
|
+
)) {
|
|
1317
|
+
return false;
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
return true;
|
|
1322
|
+
}
|
|
1323
|
+
function validateFeeScheduler(feeScheduler) {
|
|
1324
|
+
if (!feeScheduler) return true;
|
|
1325
|
+
if (feeScheduler.firstFactor !== 0 || feeScheduler.secondFactor.gt(new BN8(0)) || feeScheduler.thirdFactor.gt(new BN8(0))) {
|
|
1326
|
+
if (feeScheduler.firstFactor === 0 || feeScheduler.secondFactor.eq(new BN8(0)) || feeScheduler.thirdFactor.eq(new BN8(0))) {
|
|
1327
|
+
return false;
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
if (feeScheduler.cliffFeeNumerator.lte(new BN8(0))) {
|
|
1331
|
+
return false;
|
|
1332
|
+
}
|
|
1333
|
+
if (feeScheduler.baseFeeMode !== 0 /* FeeSchedulerLinear */ && feeScheduler.baseFeeMode !== 1 /* FeeSchedulerExponential */) {
|
|
1334
|
+
return false;
|
|
1335
|
+
}
|
|
1336
|
+
if (feeScheduler.baseFeeMode === 0 /* FeeSchedulerLinear */) {
|
|
1337
|
+
const finalFee = feeScheduler.cliffFeeNumerator.sub(
|
|
1338
|
+
feeScheduler.secondFactor.mul(new BN8(feeScheduler.firstFactor))
|
|
1339
|
+
);
|
|
1340
|
+
if (finalFee.lt(new BN8(0))) {
|
|
1341
|
+
return false;
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
const minFeeNumerator = feeScheduler.cliffFeeNumerator.sub(
|
|
1345
|
+
feeScheduler.secondFactor.mul(new BN8(feeScheduler.firstFactor))
|
|
1346
|
+
);
|
|
1347
|
+
const maxFeeNumerator = feeScheduler.cliffFeeNumerator;
|
|
1348
|
+
if (minFeeNumerator.gte(new BN8(FEE_DENOMINATOR)) || maxFeeNumerator.gte(new BN8(FEE_DENOMINATOR))) {
|
|
1349
|
+
return false;
|
|
1350
|
+
}
|
|
1351
|
+
if (minFeeNumerator.lt(new BN8(MIN_FEE_NUMERATOR)) || maxFeeNumerator.gt(new BN8(MAX_FEE_NUMERATOR))) {
|
|
1352
|
+
return false;
|
|
1353
|
+
}
|
|
1354
|
+
return true;
|
|
1355
|
+
}
|
|
1356
|
+
function validateFeeRateLimiter(feeRateLimiter, collectFeeMode, activationType) {
|
|
1357
|
+
if (!feeRateLimiter) return true;
|
|
1358
|
+
if (collectFeeMode !== 0 /* OnlyQuote */) {
|
|
1359
|
+
return false;
|
|
1360
|
+
}
|
|
1361
|
+
if (!feeRateLimiter.firstFactor && !feeRateLimiter.secondFactor && !feeRateLimiter.thirdFactor) {
|
|
1362
|
+
return true;
|
|
1363
|
+
}
|
|
1364
|
+
if (!feeRateLimiter.firstFactor || !feeRateLimiter.secondFactor || !feeRateLimiter.thirdFactor) {
|
|
1365
|
+
return false;
|
|
1366
|
+
}
|
|
1367
|
+
const maxDuration = activationType === 0 /* Slot */ ? MAX_RATE_LIMITER_DURATION_IN_SLOTS : MAX_RATE_LIMITER_DURATION_IN_SECONDS;
|
|
1368
|
+
if (feeRateLimiter.secondFactor.gt(new BN8(maxDuration))) {
|
|
1369
|
+
return false;
|
|
1370
|
+
}
|
|
1371
|
+
const feeIncrementNumerator = bpsToFeeNumerator(feeRateLimiter.firstFactor);
|
|
1372
|
+
if (feeIncrementNumerator.gte(new BN8(FEE_DENOMINATOR))) {
|
|
1373
|
+
return false;
|
|
1374
|
+
}
|
|
1375
|
+
if (feeRateLimiter.cliffFeeNumerator.lt(new BN8(MIN_FEE_NUMERATOR)) || feeRateLimiter.cliffFeeNumerator.gt(new BN8(MAX_FEE_NUMERATOR))) {
|
|
1376
|
+
return false;
|
|
1377
|
+
}
|
|
1378
|
+
const minFeeNumerator = getFeeNumeratorOnRateLimiter(
|
|
1379
|
+
feeRateLimiter.cliffFeeNumerator,
|
|
1380
|
+
feeRateLimiter.thirdFactor,
|
|
1381
|
+
new BN8(feeRateLimiter.firstFactor),
|
|
1382
|
+
new BN8(0)
|
|
1383
|
+
);
|
|
1384
|
+
const maxFeeNumerator = getFeeNumeratorOnRateLimiter(
|
|
1385
|
+
feeRateLimiter.cliffFeeNumerator,
|
|
1386
|
+
feeRateLimiter.thirdFactor,
|
|
1387
|
+
new BN8(feeRateLimiter.firstFactor),
|
|
1388
|
+
new BN8(Number.MAX_SAFE_INTEGER)
|
|
1389
|
+
);
|
|
1390
|
+
if (minFeeNumerator.lt(new BN8(MIN_FEE_NUMERATOR)) || maxFeeNumerator.gt(new BN8(MAX_FEE_NUMERATOR))) {
|
|
1391
|
+
return false;
|
|
1155
1392
|
}
|
|
1156
1393
|
return true;
|
|
1157
1394
|
}
|
|
@@ -1192,7 +1429,7 @@ function validateCurve(curve, sqrtStartPrice) {
|
|
|
1192
1429
|
if (!curve || curve.length === 0 || curve.length > MAX_CURVE_POINT) {
|
|
1193
1430
|
return false;
|
|
1194
1431
|
}
|
|
1195
|
-
if (curve[0]?.sqrtPrice.lte(sqrtStartPrice) || curve[0]?.liquidity.lte(new
|
|
1432
|
+
if (curve[0]?.sqrtPrice.lte(sqrtStartPrice) || curve[0]?.liquidity.lte(new BN8(0)) || curve[0]?.sqrtPrice.gt(new BN8(MAX_SQRT_PRICE))) {
|
|
1196
1433
|
return false;
|
|
1197
1434
|
}
|
|
1198
1435
|
for (let i = 1; i < curve.length; i++) {
|
|
@@ -1201,11 +1438,11 @@ function validateCurve(curve, sqrtStartPrice) {
|
|
|
1201
1438
|
if (!currentPoint || !previousPoint) {
|
|
1202
1439
|
return false;
|
|
1203
1440
|
}
|
|
1204
|
-
if (currentPoint.sqrtPrice.lte(previousPoint.sqrtPrice) || currentPoint.liquidity.lte(new
|
|
1441
|
+
if (currentPoint.sqrtPrice.lte(previousPoint.sqrtPrice) || currentPoint.liquidity.lte(new BN8(0))) {
|
|
1205
1442
|
return false;
|
|
1206
1443
|
}
|
|
1207
1444
|
}
|
|
1208
|
-
return !curve[curve.length - 1]?.sqrtPrice.gt(new
|
|
1445
|
+
return !curve[curve.length - 1]?.sqrtPrice.gt(new BN8(MAX_SQRT_PRICE));
|
|
1209
1446
|
}
|
|
1210
1447
|
function validateTokenSupply(tokenSupply, leftoverReceiver, swapBaseAmount, migrationBaseAmount, lockedVesting, swapBaseAmountBuffer) {
|
|
1211
1448
|
if (!tokenSupply) return true;
|
|
@@ -1229,11 +1466,11 @@ function validateTokenSupply(tokenSupply, leftoverReceiver, swapBaseAmount, migr
|
|
|
1229
1466
|
lockedVesting
|
|
1230
1467
|
);
|
|
1231
1468
|
return !(minimumBaseSupplyWithoutBuffer.gt(
|
|
1232
|
-
new
|
|
1233
|
-
) || new
|
|
1234
|
-
new
|
|
1469
|
+
new BN8(tokenSupply.postMigrationTokenSupply)
|
|
1470
|
+
) || new BN8(tokenSupply.postMigrationTokenSupply).gt(
|
|
1471
|
+
new BN8(tokenSupply.preMigrationTokenSupply)
|
|
1235
1472
|
) || minimumBaseSupplyWithBuffer.gt(
|
|
1236
|
-
new
|
|
1473
|
+
new BN8(tokenSupply.preMigrationTokenSupply)
|
|
1237
1474
|
));
|
|
1238
1475
|
}
|
|
1239
1476
|
function validateTokenUpdateAuthorityOptions(option) {
|
|
@@ -1246,7 +1483,11 @@ function validateConfigParameters(configParam) {
|
|
|
1246
1483
|
if (!configParam.poolFees) {
|
|
1247
1484
|
throw new Error("Pool fees are required");
|
|
1248
1485
|
}
|
|
1249
|
-
if (!validatePoolFees(
|
|
1486
|
+
if (!validatePoolFees(
|
|
1487
|
+
configParam.poolFees,
|
|
1488
|
+
configParam.collectFeeMode,
|
|
1489
|
+
configParam.activationType
|
|
1490
|
+
)) {
|
|
1250
1491
|
throw new Error("Invalid pool fees");
|
|
1251
1492
|
}
|
|
1252
1493
|
if (!validateCollectFeeMode(configParam.collectFeeMode)) {
|
|
@@ -1284,10 +1525,10 @@ function validateConfigParameters(configParam) {
|
|
|
1284
1525
|
)) {
|
|
1285
1526
|
throw new Error("Sum of LP percentages must equal 100");
|
|
1286
1527
|
}
|
|
1287
|
-
if (configParam.migrationQuoteThreshold.lte(new
|
|
1528
|
+
if (configParam.migrationQuoteThreshold.lte(new BN8(0))) {
|
|
1288
1529
|
throw new Error("Migration quote threshold must be greater than 0");
|
|
1289
1530
|
}
|
|
1290
|
-
if (new
|
|
1531
|
+
if (new BN8(configParam.sqrtStartPrice).lt(new BN8(MIN_SQRT_PRICE)) || new BN8(configParam.sqrtStartPrice).gte(new BN8(MAX_SQRT_PRICE))) {
|
|
1291
1532
|
throw new Error("Invalid sqrt start price");
|
|
1292
1533
|
}
|
|
1293
1534
|
if (!validateCurve(configParam.curve, configParam.sqrtStartPrice)) {
|
|
@@ -1297,10 +1538,10 @@ function validateConfigParameters(configParam) {
|
|
|
1297
1538
|
try {
|
|
1298
1539
|
const totalAmount = configParam.lockedVesting.cliffUnlockAmount.add(
|
|
1299
1540
|
configParam.lockedVesting.amountPerPeriod.mul(
|
|
1300
|
-
new
|
|
1541
|
+
new BN8(configParam.lockedVesting.numberOfPeriod)
|
|
1301
1542
|
)
|
|
1302
1543
|
);
|
|
1303
|
-
if (configParam.lockedVesting.frequency.eq(new
|
|
1544
|
+
if (configParam.lockedVesting.frequency.eq(new BN8(0)) || totalAmount.eq(new BN8(0))) {
|
|
1304
1545
|
throw new Error("Invalid vesting parameters");
|
|
1305
1546
|
}
|
|
1306
1547
|
} catch (error) {
|
|
@@ -1361,7 +1602,7 @@ async function validateBalance(connection, owner, inputMint, amountIn, inputToke
|
|
|
1361
1602
|
} else {
|
|
1362
1603
|
try {
|
|
1363
1604
|
const tokenBalance = await connection.getTokenAccountBalance(inputTokenAccount);
|
|
1364
|
-
const balance = new
|
|
1605
|
+
const balance = new BN8(tokenBalance.value.amount);
|
|
1365
1606
|
if (balance.lt(amountIn)) {
|
|
1366
1607
|
throw new Error(
|
|
1367
1608
|
`Insufficient token balance. Required: ${amountIn.toString()}, Found: ${balance.toString()}`
|
|
@@ -1376,7 +1617,7 @@ async function validateBalance(connection, owner, inputMint, amountIn, inputToke
|
|
|
1376
1617
|
return true;
|
|
1377
1618
|
}
|
|
1378
1619
|
function validateSwapAmount(amountIn) {
|
|
1379
|
-
if (amountIn.lte(new
|
|
1620
|
+
if (amountIn.lte(new BN8(0))) {
|
|
1380
1621
|
throw new Error("Swap amount must be greater than 0");
|
|
1381
1622
|
}
|
|
1382
1623
|
return true;
|
|
@@ -1384,7 +1625,7 @@ function validateSwapAmount(amountIn) {
|
|
|
1384
1625
|
|
|
1385
1626
|
// src/helpers/buildCurve.ts
|
|
1386
1627
|
import Decimal4 from "decimal.js";
|
|
1387
|
-
import
|
|
1628
|
+
import BN9 from "bn.js";
|
|
1388
1629
|
function buildCurve(buildCurveParam) {
|
|
1389
1630
|
let {
|
|
1390
1631
|
totalTokenSupply,
|
|
@@ -1405,21 +1646,13 @@ function buildCurve(buildCurveParam) {
|
|
|
1405
1646
|
creatorTradingFeePercentage,
|
|
1406
1647
|
leftover,
|
|
1407
1648
|
tokenUpdateAuthority,
|
|
1408
|
-
migrationFee
|
|
1649
|
+
migrationFee,
|
|
1650
|
+
baseFeeParams
|
|
1409
1651
|
} = buildCurveParam;
|
|
1410
|
-
const
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
feeSchedulerMode,
|
|
1415
|
-
totalDuration
|
|
1416
|
-
} = buildCurveParam.feeSchedulerParam;
|
|
1417
|
-
const baseFeeParams = getBaseFeeParams(
|
|
1418
|
-
startingFeeBps,
|
|
1419
|
-
endingFeeBps,
|
|
1420
|
-
feeSchedulerMode,
|
|
1421
|
-
numberOfPeriod,
|
|
1422
|
-
totalDuration
|
|
1652
|
+
const baseFee = getBaseFeeParams(
|
|
1653
|
+
baseFeeParams,
|
|
1654
|
+
tokenQuoteDecimal,
|
|
1655
|
+
activationType
|
|
1423
1656
|
);
|
|
1424
1657
|
const {
|
|
1425
1658
|
totalLockedVestingAmount,
|
|
@@ -1436,7 +1669,7 @@ function buildCurve(buildCurveParam) {
|
|
|
1436
1669
|
cliffDurationFromMigrationTime,
|
|
1437
1670
|
tokenBaseDecimal
|
|
1438
1671
|
);
|
|
1439
|
-
const migrationBaseSupply = new
|
|
1672
|
+
const migrationBaseSupply = new BN9(totalTokenSupply).mul(new BN9(percentageSupplyOnMigration)).div(new BN9(100));
|
|
1440
1673
|
const totalSupply = convertToLamports(totalTokenSupply, tokenBaseDecimal);
|
|
1441
1674
|
const migrationQuoteAmount = getMigrationQuoteAmountFromMigrationQuoteThreshold(
|
|
1442
1675
|
new Decimal4(migrationQuoteThreshold),
|
|
@@ -1496,9 +1729,11 @@ function buildCurve(buildCurveParam) {
|
|
|
1496
1729
|
const instructionParams = {
|
|
1497
1730
|
poolFees: {
|
|
1498
1731
|
baseFee: {
|
|
1499
|
-
...
|
|
1732
|
+
...baseFee
|
|
1500
1733
|
},
|
|
1501
|
-
dynamicFee: dynamicFeeEnabled ? getDynamicFeeParams(
|
|
1734
|
+
dynamicFee: dynamicFeeEnabled ? getDynamicFeeParams(
|
|
1735
|
+
baseFeeParams.baseFeeMode === 2 /* RateLimiter */ ? baseFeeParams.rateLimiterParam.baseFeeBps : baseFeeParams.feeSchedulerParam.endingFeeBps
|
|
1736
|
+
) : null
|
|
1502
1737
|
},
|
|
1503
1738
|
activationType,
|
|
1504
1739
|
collectFeeMode,
|
|
@@ -1591,21 +1826,13 @@ function buildCurveWithTwoSegments(buildCurveWithTwoSegmentsParam) {
|
|
|
1591
1826
|
dynamicFeeEnabled,
|
|
1592
1827
|
migrationFeeOption,
|
|
1593
1828
|
migrationFee,
|
|
1594
|
-
tokenUpdateAuthority
|
|
1829
|
+
tokenUpdateAuthority,
|
|
1830
|
+
baseFeeParams
|
|
1595
1831
|
} = buildCurveWithTwoSegmentsParam;
|
|
1596
|
-
const
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
feeSchedulerMode,
|
|
1601
|
-
totalDuration
|
|
1602
|
-
} = buildCurveWithTwoSegmentsParam.feeSchedulerParam;
|
|
1603
|
-
const baseFeeParams = getBaseFeeParams(
|
|
1604
|
-
startingFeeBps,
|
|
1605
|
-
endingFeeBps,
|
|
1606
|
-
feeSchedulerMode,
|
|
1607
|
-
numberOfPeriod,
|
|
1608
|
-
totalDuration
|
|
1832
|
+
const baseFee = getBaseFeeParams(
|
|
1833
|
+
baseFeeParams,
|
|
1834
|
+
tokenQuoteDecimal,
|
|
1835
|
+
activationType
|
|
1609
1836
|
);
|
|
1610
1837
|
const {
|
|
1611
1838
|
totalLockedVestingAmount,
|
|
@@ -1622,7 +1849,7 @@ function buildCurveWithTwoSegments(buildCurveWithTwoSegmentsParam) {
|
|
|
1622
1849
|
cliffDurationFromMigrationTime,
|
|
1623
1850
|
tokenBaseDecimal
|
|
1624
1851
|
);
|
|
1625
|
-
let migrationBaseSupply = new
|
|
1852
|
+
let migrationBaseSupply = new BN9(totalTokenSupply).mul(new BN9(percentageSupplyOnMigration)).div(new BN9(100));
|
|
1626
1853
|
let totalSupply = convertToLamports(totalTokenSupply, tokenBaseDecimal);
|
|
1627
1854
|
let migrationQuoteAmount = getMigrationQuoteAmount(
|
|
1628
1855
|
new Decimal4(migrationMarketCap),
|
|
@@ -1661,19 +1888,19 @@ function buildCurveWithTwoSegments(buildCurveWithTwoSegmentsParam) {
|
|
|
1661
1888
|
tokenQuoteDecimal
|
|
1662
1889
|
);
|
|
1663
1890
|
let midSqrtPriceDecimal1 = new Decimal4(migrateSqrtPrice.toString()).mul(new Decimal4(initialSqrtPrice.toString())).sqrt();
|
|
1664
|
-
let midSqrtPrice1 = new
|
|
1891
|
+
let midSqrtPrice1 = new BN9(midSqrtPriceDecimal1.floor().toFixed());
|
|
1665
1892
|
let numerator1 = new Decimal4(initialSqrtPrice.toString());
|
|
1666
1893
|
let numerator2 = Decimal4.pow(migrateSqrtPrice.toString(), 3);
|
|
1667
1894
|
let product1 = numerator1.mul(numerator2);
|
|
1668
1895
|
let midSqrtPriceDecimal2 = Decimal4.pow(product1, 0.25);
|
|
1669
|
-
let midSqrtPrice2 = new
|
|
1896
|
+
let midSqrtPrice2 = new BN9(midSqrtPriceDecimal2.floor().toFixed());
|
|
1670
1897
|
let numerator3 = Decimal4.pow(initialSqrtPrice.toString(), 3);
|
|
1671
1898
|
let numerator4 = new Decimal4(migrateSqrtPrice.toString());
|
|
1672
1899
|
let product2 = numerator3.mul(numerator4);
|
|
1673
1900
|
let midSqrtPriceDecimal3 = Decimal4.pow(product2, 0.25);
|
|
1674
|
-
let midSqrtPrice3 = new
|
|
1901
|
+
let midSqrtPrice3 = new BN9(midSqrtPriceDecimal3.floor().toFixed());
|
|
1675
1902
|
let midPrices = [midSqrtPrice1, midSqrtPrice2, midSqrtPrice3];
|
|
1676
|
-
let sqrtStartPrice = new
|
|
1903
|
+
let sqrtStartPrice = new BN9(0);
|
|
1677
1904
|
let curve = [];
|
|
1678
1905
|
for (let i = 0; i < midPrices.length; i++) {
|
|
1679
1906
|
const result = getTwoCurve(
|
|
@@ -1707,9 +1934,11 @@ function buildCurveWithTwoSegments(buildCurveWithTwoSegmentsParam) {
|
|
|
1707
1934
|
const instructionParams = {
|
|
1708
1935
|
poolFees: {
|
|
1709
1936
|
baseFee: {
|
|
1710
|
-
...
|
|
1937
|
+
...baseFee
|
|
1711
1938
|
},
|
|
1712
|
-
dynamicFee: dynamicFeeEnabled ? getDynamicFeeParams(
|
|
1939
|
+
dynamicFee: dynamicFeeEnabled ? getDynamicFeeParams(
|
|
1940
|
+
baseFeeParams.baseFeeMode === 2 /* RateLimiter */ ? baseFeeParams.rateLimiterParam.baseFeeBps : baseFeeParams.feeSchedulerParam.endingFeeBps
|
|
1941
|
+
) : null
|
|
1713
1942
|
},
|
|
1714
1943
|
activationType,
|
|
1715
1944
|
collectFeeMode,
|
|
@@ -1758,21 +1987,13 @@ function buildCurveWithLiquidityWeights(buildCurveWithLiquidityWeightsParam) {
|
|
|
1758
1987
|
migrationMarketCap,
|
|
1759
1988
|
liquidityWeights,
|
|
1760
1989
|
migrationFee,
|
|
1761
|
-
tokenUpdateAuthority
|
|
1990
|
+
tokenUpdateAuthority,
|
|
1991
|
+
baseFeeParams
|
|
1762
1992
|
} = buildCurveWithLiquidityWeightsParam;
|
|
1763
|
-
const
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
feeSchedulerMode,
|
|
1768
|
-
totalDuration
|
|
1769
|
-
} = buildCurveWithLiquidityWeightsParam.feeSchedulerParam;
|
|
1770
|
-
const baseFeeParams = getBaseFeeParams(
|
|
1771
|
-
startingFeeBps,
|
|
1772
|
-
endingFeeBps,
|
|
1773
|
-
feeSchedulerMode,
|
|
1774
|
-
numberOfPeriod,
|
|
1775
|
-
totalDuration
|
|
1993
|
+
const baseFee = getBaseFeeParams(
|
|
1994
|
+
baseFeeParams,
|
|
1995
|
+
tokenQuoteDecimal,
|
|
1996
|
+
activationType
|
|
1776
1997
|
);
|
|
1777
1998
|
const {
|
|
1778
1999
|
totalLockedVestingAmount,
|
|
@@ -1873,9 +2094,11 @@ function buildCurveWithLiquidityWeights(buildCurveWithLiquidityWeightsParam) {
|
|
|
1873
2094
|
const instructionParams = {
|
|
1874
2095
|
poolFees: {
|
|
1875
2096
|
baseFee: {
|
|
1876
|
-
...
|
|
2097
|
+
...baseFee
|
|
1877
2098
|
},
|
|
1878
|
-
dynamicFee: dynamicFeeEnabled ? getDynamicFeeParams(
|
|
2099
|
+
dynamicFee: dynamicFeeEnabled ? getDynamicFeeParams(
|
|
2100
|
+
baseFeeParams.baseFeeMode === 2 /* RateLimiter */ ? baseFeeParams.rateLimiterParam.baseFeeBps : baseFeeParams.feeSchedulerParam.endingFeeBps
|
|
2101
|
+
) : null
|
|
1879
2102
|
},
|
|
1880
2103
|
activationType,
|
|
1881
2104
|
collectFeeMode,
|
|
@@ -5820,6 +6043,21 @@ var idl_default = {
|
|
|
5820
6043
|
code: 6040,
|
|
5821
6044
|
name: "MigrationFeeHasBeenWithdraw",
|
|
5822
6045
|
msg: "Migration fee has been withdraw"
|
|
6046
|
+
},
|
|
6047
|
+
{
|
|
6048
|
+
code: 6041,
|
|
6049
|
+
name: "InvalidBaseFeeMode",
|
|
6050
|
+
msg: "Invalid base fee mode"
|
|
6051
|
+
},
|
|
6052
|
+
{
|
|
6053
|
+
code: 6042,
|
|
6054
|
+
name: "InvalidFeeRateLimiter",
|
|
6055
|
+
msg: "Invalid fee rate limiter"
|
|
6056
|
+
},
|
|
6057
|
+
{
|
|
6058
|
+
code: 6043,
|
|
6059
|
+
name: "FailToValidateSingleSwapInstruction",
|
|
6060
|
+
msg: "Fail to validate single swap instruction in rate limiter"
|
|
5823
6061
|
}
|
|
5824
6062
|
],
|
|
5825
6063
|
types: [
|
|
@@ -5837,19 +6075,19 @@ var idl_default = {
|
|
|
5837
6075
|
type: "u64"
|
|
5838
6076
|
},
|
|
5839
6077
|
{
|
|
5840
|
-
name: "
|
|
6078
|
+
name: "second_factor",
|
|
5841
6079
|
type: "u64"
|
|
5842
6080
|
},
|
|
5843
6081
|
{
|
|
5844
|
-
name: "
|
|
6082
|
+
name: "third_factor",
|
|
5845
6083
|
type: "u64"
|
|
5846
6084
|
},
|
|
5847
6085
|
{
|
|
5848
|
-
name: "
|
|
6086
|
+
name: "first_factor",
|
|
5849
6087
|
type: "u16"
|
|
5850
6088
|
},
|
|
5851
6089
|
{
|
|
5852
|
-
name: "
|
|
6090
|
+
name: "base_fee_mode",
|
|
5853
6091
|
type: "u8"
|
|
5854
6092
|
},
|
|
5855
6093
|
{
|
|
@@ -5874,19 +6112,19 @@ var idl_default = {
|
|
|
5874
6112
|
type: "u64"
|
|
5875
6113
|
},
|
|
5876
6114
|
{
|
|
5877
|
-
name: "
|
|
6115
|
+
name: "first_factor",
|
|
5878
6116
|
type: "u16"
|
|
5879
6117
|
},
|
|
5880
6118
|
{
|
|
5881
|
-
name: "
|
|
6119
|
+
name: "second_factor",
|
|
5882
6120
|
type: "u64"
|
|
5883
6121
|
},
|
|
5884
6122
|
{
|
|
5885
|
-
name: "
|
|
6123
|
+
name: "third_factor",
|
|
5886
6124
|
type: "u64"
|
|
5887
6125
|
},
|
|
5888
6126
|
{
|
|
5889
|
-
name: "
|
|
6127
|
+
name: "base_fee_mode",
|
|
5890
6128
|
type: "u8"
|
|
5891
6129
|
}
|
|
5892
6130
|
]
|
|
@@ -20886,16 +21124,26 @@ import { NATIVE_MINT as NATIVE_MINT3, TOKEN_2022_PROGRAM_ID as TOKEN_2022_PROGRA
|
|
|
20886
21124
|
import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3 } from "@solana/spl-token";
|
|
20887
21125
|
|
|
20888
21126
|
// src/math/swapQuote.ts
|
|
20889
|
-
import
|
|
21127
|
+
import BN12 from "bn.js";
|
|
20890
21128
|
|
|
20891
21129
|
// src/math/feeMath.ts
|
|
20892
|
-
import
|
|
20893
|
-
|
|
21130
|
+
import BN11 from "bn.js";
|
|
21131
|
+
|
|
21132
|
+
// src/math/feeScheduler.ts
|
|
21133
|
+
import BN10 from "bn.js";
|
|
21134
|
+
function getFeeNumeratorOnLinearFeeScheduler(cliffFeeNumerator, reductionFactor, period) {
|
|
21135
|
+
const reduction = SafeMath.mul(new BN10(period), reductionFactor);
|
|
21136
|
+
if (reduction.gt(cliffFeeNumerator)) {
|
|
21137
|
+
return new BN10(0);
|
|
21138
|
+
}
|
|
21139
|
+
return SafeMath.sub(cliffFeeNumerator, reduction);
|
|
21140
|
+
}
|
|
21141
|
+
function getFeeNumeratorOnExponentialFeeScheduler(cliffFeeNumerator, reductionFactor, period) {
|
|
20894
21142
|
if (period === 0) {
|
|
20895
21143
|
return cliffFeeNumerator;
|
|
20896
21144
|
}
|
|
20897
21145
|
if (period === 1) {
|
|
20898
|
-
const basisPointMax2 = new
|
|
21146
|
+
const basisPointMax2 = new BN10(BASIS_POINT_MAX);
|
|
20899
21147
|
return mulDiv(
|
|
20900
21148
|
cliffFeeNumerator,
|
|
20901
21149
|
basisPointMax2.sub(reductionFactor),
|
|
@@ -20903,53 +21151,106 @@ function getFeeInPeriod(cliffFeeNumerator, reductionFactor, period) {
|
|
|
20903
21151
|
1 /* Down */
|
|
20904
21152
|
);
|
|
20905
21153
|
}
|
|
20906
|
-
const basisPointMax = new
|
|
20907
|
-
const ONE_Q642 = new
|
|
21154
|
+
const basisPointMax = new BN10(BASIS_POINT_MAX);
|
|
21155
|
+
const ONE_Q642 = new BN10(1).shln(64);
|
|
20908
21156
|
const reductionFactorScaled = SafeMath.div(
|
|
20909
21157
|
SafeMath.shl(reductionFactor, 64),
|
|
20910
21158
|
basisPointMax
|
|
20911
21159
|
);
|
|
20912
21160
|
let base = SafeMath.sub(ONE_Q642, reductionFactorScaled);
|
|
20913
|
-
const result = pow(base, new
|
|
21161
|
+
const result = pow(base, new BN10(period));
|
|
20914
21162
|
return SafeMath.div(SafeMath.mul(cliffFeeNumerator, result), ONE_Q642);
|
|
20915
21163
|
}
|
|
20916
|
-
|
|
20917
|
-
|
|
20918
|
-
|
|
20919
|
-
|
|
20920
|
-
|
|
20921
|
-
|
|
20922
|
-
|
|
20923
|
-
|
|
20924
|
-
const
|
|
20925
|
-
const
|
|
20926
|
-
|
|
20927
|
-
|
|
20928
|
-
|
|
21164
|
+
|
|
21165
|
+
// src/math/feeMath.ts
|
|
21166
|
+
function getBaseFeeNumerator(baseFee, tradeDirection, currentPoint, activationPoint, inputAmount) {
|
|
21167
|
+
const baseFeeMode = baseFee.baseFeeMode;
|
|
21168
|
+
if (baseFeeMode === 2 /* RateLimiter */) {
|
|
21169
|
+
const feeIncrementBps = baseFee.firstFactor;
|
|
21170
|
+
const maxLimiterDuration = baseFee.secondFactor;
|
|
21171
|
+
const referenceAmount = baseFee.thirdFactor;
|
|
21172
|
+
const isBaseToQuote = tradeDirection === 0 /* BaseToQuote */;
|
|
21173
|
+
const isRateLimiterApplied = checkRateLimiterApplied(
|
|
21174
|
+
baseFeeMode,
|
|
21175
|
+
isBaseToQuote,
|
|
21176
|
+
currentPoint,
|
|
21177
|
+
activationPoint,
|
|
21178
|
+
baseFee.secondFactor
|
|
20929
21179
|
);
|
|
20930
|
-
|
|
20931
|
-
|
|
20932
|
-
|
|
20933
|
-
const
|
|
20934
|
-
if (
|
|
20935
|
-
return
|
|
21180
|
+
if (currentPoint.lt(activationPoint)) {
|
|
21181
|
+
return baseFee.cliffFeeNumerator;
|
|
21182
|
+
}
|
|
21183
|
+
const lastEffectivePoint = activationPoint.add(maxLimiterDuration);
|
|
21184
|
+
if (currentPoint.gt(lastEffectivePoint)) {
|
|
21185
|
+
return baseFee.cliffFeeNumerator;
|
|
21186
|
+
}
|
|
21187
|
+
if (!inputAmount) {
|
|
21188
|
+
return baseFee.cliffFeeNumerator;
|
|
21189
|
+
}
|
|
21190
|
+
if (isRateLimiterApplied) {
|
|
21191
|
+
return getFeeNumeratorOnRateLimiter(
|
|
21192
|
+
baseFee.cliffFeeNumerator,
|
|
21193
|
+
referenceAmount,
|
|
21194
|
+
new BN11(feeIncrementBps),
|
|
21195
|
+
inputAmount
|
|
21196
|
+
);
|
|
21197
|
+
} else {
|
|
21198
|
+
return baseFee.cliffFeeNumerator;
|
|
20936
21199
|
}
|
|
20937
|
-
return SafeMath.sub(baseFee.cliffFeeNumerator, reduction);
|
|
20938
|
-
} else if (feeSchedulerMode === 1 /* Exponential */) {
|
|
20939
|
-
return getFeeInPeriod(
|
|
20940
|
-
baseFee.cliffFeeNumerator,
|
|
20941
|
-
baseFee.reductionFactor,
|
|
20942
|
-
period
|
|
20943
|
-
);
|
|
20944
21200
|
} else {
|
|
20945
|
-
|
|
21201
|
+
const numberOfPeriod = baseFee.firstFactor;
|
|
21202
|
+
const periodFrequency = baseFee.secondFactor;
|
|
21203
|
+
const reductionFactor = baseFee.thirdFactor;
|
|
21204
|
+
if (periodFrequency.isZero()) {
|
|
21205
|
+
return baseFee.cliffFeeNumerator;
|
|
21206
|
+
}
|
|
21207
|
+
let period;
|
|
21208
|
+
if (currentPoint.lt(activationPoint)) {
|
|
21209
|
+
period = numberOfPeriod;
|
|
21210
|
+
} else {
|
|
21211
|
+
const elapsedPoints = SafeMath.sub(currentPoint, activationPoint);
|
|
21212
|
+
const periodCount = SafeMath.div(elapsedPoints, periodFrequency);
|
|
21213
|
+
period = Math.min(parseInt(periodCount.toString()), numberOfPeriod);
|
|
21214
|
+
}
|
|
21215
|
+
if (baseFeeMode === 0 /* FeeSchedulerLinear */) {
|
|
21216
|
+
return getFeeNumeratorOnLinearFeeScheduler(
|
|
21217
|
+
baseFee.cliffFeeNumerator,
|
|
21218
|
+
reductionFactor,
|
|
21219
|
+
period
|
|
21220
|
+
);
|
|
21221
|
+
} else {
|
|
21222
|
+
return getFeeNumeratorOnExponentialFeeScheduler(
|
|
21223
|
+
baseFee.cliffFeeNumerator,
|
|
21224
|
+
reductionFactor,
|
|
21225
|
+
period
|
|
21226
|
+
);
|
|
21227
|
+
}
|
|
21228
|
+
}
|
|
21229
|
+
}
|
|
21230
|
+
function getVariableFee(dynamicFee, volatilityTracker) {
|
|
21231
|
+
if (dynamicFee.initialized === 0) {
|
|
21232
|
+
return new BN11(0);
|
|
21233
|
+
}
|
|
21234
|
+
if (volatilityTracker.volatilityAccumulator.isZero()) {
|
|
21235
|
+
return new BN11(0);
|
|
20946
21236
|
}
|
|
21237
|
+
const volatilityTimesBinStep = SafeMath.mul(
|
|
21238
|
+
volatilityTracker.volatilityAccumulator,
|
|
21239
|
+
new BN11(dynamicFee.binStep)
|
|
21240
|
+
);
|
|
21241
|
+
const squared = SafeMath.mul(volatilityTimesBinStep, volatilityTimesBinStep);
|
|
21242
|
+
const vFee = SafeMath.mul(squared, new BN11(dynamicFee.variableFeeControl));
|
|
21243
|
+
const scaleFactor = new BN11(1e11);
|
|
21244
|
+
const numerator = SafeMath.add(vFee, SafeMath.sub(scaleFactor, new BN11(1)));
|
|
21245
|
+
return SafeMath.div(numerator, scaleFactor);
|
|
20947
21246
|
}
|
|
20948
|
-
function getFeeOnAmount(amount, poolFees, isReferral, currentPoint, activationPoint, volatilityTracker) {
|
|
20949
|
-
const baseFeeNumerator =
|
|
21247
|
+
function getFeeOnAmount(amount, poolFees, isReferral, currentPoint, activationPoint, volatilityTracker, tradeDirection) {
|
|
21248
|
+
const baseFeeNumerator = getBaseFeeNumerator(
|
|
20950
21249
|
poolFees.baseFee,
|
|
21250
|
+
tradeDirection,
|
|
20951
21251
|
currentPoint,
|
|
20952
|
-
activationPoint
|
|
21252
|
+
activationPoint,
|
|
21253
|
+
poolFees.baseFee.baseFeeMode === 2 /* RateLimiter */ ? amount : void 0
|
|
20953
21254
|
);
|
|
20954
21255
|
let totalFeeNumerator = baseFeeNumerator;
|
|
20955
21256
|
if (poolFees.dynamicFee.initialized !== 0) {
|
|
@@ -20959,29 +21260,29 @@ function getFeeOnAmount(amount, poolFees, isReferral, currentPoint, activationPo
|
|
|
20959
21260
|
);
|
|
20960
21261
|
totalFeeNumerator = SafeMath.add(totalFeeNumerator, variableFee);
|
|
20961
21262
|
}
|
|
20962
|
-
if (totalFeeNumerator.gt(new
|
|
20963
|
-
totalFeeNumerator = new
|
|
21263
|
+
if (totalFeeNumerator.gt(new BN11(MAX_FEE_NUMERATOR))) {
|
|
21264
|
+
totalFeeNumerator = new BN11(MAX_FEE_NUMERATOR);
|
|
20964
21265
|
}
|
|
20965
21266
|
const tradingFee = mulDiv(
|
|
20966
21267
|
amount,
|
|
20967
21268
|
totalFeeNumerator,
|
|
20968
|
-
new
|
|
21269
|
+
new BN11(FEE_DENOMINATOR),
|
|
20969
21270
|
0 /* Up */
|
|
20970
21271
|
);
|
|
20971
21272
|
const amountAfterFee = SafeMath.sub(amount, tradingFee);
|
|
20972
21273
|
const protocolFee = mulDiv(
|
|
20973
21274
|
tradingFee,
|
|
20974
|
-
new
|
|
20975
|
-
new
|
|
21275
|
+
new BN11(poolFees.protocolFeePercent),
|
|
21276
|
+
new BN11(100),
|
|
20976
21277
|
1 /* Down */
|
|
20977
21278
|
);
|
|
20978
21279
|
const tradingFeeAfterProtocol = SafeMath.sub(tradingFee, protocolFee);
|
|
20979
|
-
let referralFee = new
|
|
21280
|
+
let referralFee = new BN11(0);
|
|
20980
21281
|
if (isReferral) {
|
|
20981
21282
|
referralFee = mulDiv(
|
|
20982
21283
|
protocolFee,
|
|
20983
|
-
new
|
|
20984
|
-
new
|
|
21284
|
+
new BN11(poolFees.referralFeePercent),
|
|
21285
|
+
new BN11(100),
|
|
20985
21286
|
1 /* Down */
|
|
20986
21287
|
);
|
|
20987
21288
|
}
|
|
@@ -20993,29 +21294,12 @@ function getFeeOnAmount(amount, poolFees, isReferral, currentPoint, activationPo
|
|
|
20993
21294
|
referralFee
|
|
20994
21295
|
};
|
|
20995
21296
|
}
|
|
20996
|
-
function getVariableFee(dynamicFee, volatilityTracker) {
|
|
20997
|
-
if (dynamicFee.initialized === 0) {
|
|
20998
|
-
return new BN9(0);
|
|
20999
|
-
}
|
|
21000
|
-
if (volatilityTracker.volatilityAccumulator.isZero()) {
|
|
21001
|
-
return new BN9(0);
|
|
21002
|
-
}
|
|
21003
|
-
const volatilityTimesBinStep = SafeMath.mul(
|
|
21004
|
-
volatilityTracker.volatilityAccumulator,
|
|
21005
|
-
new BN9(dynamicFee.binStep)
|
|
21006
|
-
);
|
|
21007
|
-
const squared = SafeMath.mul(volatilityTimesBinStep, volatilityTimesBinStep);
|
|
21008
|
-
const vFee = SafeMath.mul(squared, new BN9(dynamicFee.variableFeeControl));
|
|
21009
|
-
const scaleFactor = new BN9(1e11);
|
|
21010
|
-
const numerator = SafeMath.add(vFee, SafeMath.sub(scaleFactor, new BN9(1)));
|
|
21011
|
-
return SafeMath.div(numerator, scaleFactor);
|
|
21012
|
-
}
|
|
21013
21297
|
|
|
21014
21298
|
// src/math/swapQuote.ts
|
|
21015
21299
|
function getSwapResult(poolState, configState, amountIn, feeMode, tradeDirection, currentPoint) {
|
|
21016
|
-
let actualProtocolFee = new
|
|
21017
|
-
let actualTradingFee = new
|
|
21018
|
-
let actualReferralFee = new
|
|
21300
|
+
let actualProtocolFee = new BN12(0);
|
|
21301
|
+
let actualTradingFee = new BN12(0);
|
|
21302
|
+
let actualReferralFee = new BN12(0);
|
|
21019
21303
|
let actualAmountIn;
|
|
21020
21304
|
if (feeMode.feesOnInput) {
|
|
21021
21305
|
const feeResult = getFeeOnAmount(
|
|
@@ -21024,7 +21308,8 @@ function getSwapResult(poolState, configState, amountIn, feeMode, tradeDirection
|
|
|
21024
21308
|
feeMode.hasReferral,
|
|
21025
21309
|
currentPoint,
|
|
21026
21310
|
poolState.activationPoint,
|
|
21027
|
-
poolState.volatilityTracker
|
|
21311
|
+
poolState.volatilityTracker,
|
|
21312
|
+
tradeDirection
|
|
21028
21313
|
);
|
|
21029
21314
|
actualProtocolFee = feeResult.protocolFee;
|
|
21030
21315
|
actualTradingFee = feeResult.tradingFee;
|
|
@@ -21052,7 +21337,8 @@ function getSwapResult(poolState, configState, amountIn, feeMode, tradeDirection
|
|
|
21052
21337
|
feeMode.hasReferral,
|
|
21053
21338
|
currentPoint,
|
|
21054
21339
|
poolState.activationPoint,
|
|
21055
|
-
poolState.volatilityTracker
|
|
21340
|
+
poolState.volatilityTracker,
|
|
21341
|
+
tradeDirection
|
|
21056
21342
|
);
|
|
21057
21343
|
actualProtocolFee = feeResult.protocolFee;
|
|
21058
21344
|
actualTradingFee = feeResult.tradingFee;
|
|
@@ -21077,11 +21363,11 @@ function getSwapResult(poolState, configState, amountIn, feeMode, tradeDirection
|
|
|
21077
21363
|
function getSwapAmountFromBaseToQuote(configState, currentSqrtPrice, amountIn) {
|
|
21078
21364
|
if (amountIn.isZero()) {
|
|
21079
21365
|
return {
|
|
21080
|
-
outputAmount: new
|
|
21366
|
+
outputAmount: new BN12(0),
|
|
21081
21367
|
nextSqrtPrice: currentSqrtPrice
|
|
21082
21368
|
};
|
|
21083
21369
|
}
|
|
21084
|
-
let totalOutputAmount = new
|
|
21370
|
+
let totalOutputAmount = new BN12(0);
|
|
21085
21371
|
let sqrtPrice = currentSqrtPrice;
|
|
21086
21372
|
let amountLeft = amountIn;
|
|
21087
21373
|
for (let i = configState.curve.length - 1; i >= 0; i--) {
|
|
@@ -21115,7 +21401,7 @@ function getSwapAmountFromBaseToQuote(configState, currentSqrtPrice, amountIn) {
|
|
|
21115
21401
|
outputAmount
|
|
21116
21402
|
);
|
|
21117
21403
|
sqrtPrice = nextSqrtPrice;
|
|
21118
|
-
amountLeft = new
|
|
21404
|
+
amountLeft = new BN12(0);
|
|
21119
21405
|
break;
|
|
21120
21406
|
} else {
|
|
21121
21407
|
const nextSqrtPrice = configState.curve[i].sqrtPrice;
|
|
@@ -21158,11 +21444,11 @@ function getSwapAmountFromBaseToQuote(configState, currentSqrtPrice, amountIn) {
|
|
|
21158
21444
|
function getSwapAmountFromQuoteToBase(configState, currentSqrtPrice, amountIn) {
|
|
21159
21445
|
if (amountIn.isZero()) {
|
|
21160
21446
|
return {
|
|
21161
|
-
outputAmount: new
|
|
21447
|
+
outputAmount: new BN12(0),
|
|
21162
21448
|
nextSqrtPrice: currentSqrtPrice
|
|
21163
21449
|
};
|
|
21164
21450
|
}
|
|
21165
|
-
let totalOutputAmount = new
|
|
21451
|
+
let totalOutputAmount = new BN12(0);
|
|
21166
21452
|
let sqrtPrice = currentSqrtPrice;
|
|
21167
21453
|
let amountLeft = amountIn;
|
|
21168
21454
|
for (let i = 0; i < configState.curve.length; i++) {
|
|
@@ -21195,7 +21481,7 @@ function getSwapAmountFromQuoteToBase(configState, currentSqrtPrice, amountIn) {
|
|
|
21195
21481
|
outputAmount
|
|
21196
21482
|
);
|
|
21197
21483
|
sqrtPrice = nextSqrtPrice;
|
|
21198
|
-
amountLeft = new
|
|
21484
|
+
amountLeft = new BN12(0);
|
|
21199
21485
|
break;
|
|
21200
21486
|
} else {
|
|
21201
21487
|
const nextSqrtPrice = configState.curve[i].sqrtPrice;
|
|
@@ -21254,8 +21540,8 @@ async function swapQuote(virtualPool, config, swapBaseForQuote, amountIn, slippa
|
|
|
21254
21540
|
currentPoint
|
|
21255
21541
|
);
|
|
21256
21542
|
if (slippageBps > 0) {
|
|
21257
|
-
const slippageFactor = new
|
|
21258
|
-
const denominator = new
|
|
21543
|
+
const slippageFactor = new BN12(1e4 - slippageBps);
|
|
21544
|
+
const denominator = new BN12(1e4);
|
|
21259
21545
|
const minimumAmountOut = result.amountOut.mul(slippageFactor).div(denominator);
|
|
21260
21546
|
return {
|
|
21261
21547
|
...result,
|
|
@@ -21264,6 +21550,40 @@ async function swapQuote(virtualPool, config, swapBaseForQuote, amountIn, slippa
|
|
|
21264
21550
|
}
|
|
21265
21551
|
return result;
|
|
21266
21552
|
}
|
|
21553
|
+
function calculateQuoteExactInAmount(config, virtualPool, currentPoint) {
|
|
21554
|
+
if (virtualPool.quoteReserve.gte(config.migrationQuoteThreshold)) {
|
|
21555
|
+
return new BN12(0);
|
|
21556
|
+
}
|
|
21557
|
+
const amountInAfterFee = config.migrationQuoteThreshold.sub(
|
|
21558
|
+
virtualPool.quoteReserve
|
|
21559
|
+
);
|
|
21560
|
+
if (config.collectFeeMode === 0 /* OnlyQuote */) {
|
|
21561
|
+
const baseFeeNumerator = getBaseFeeNumerator(
|
|
21562
|
+
config.poolFees.baseFee,
|
|
21563
|
+
1 /* QuoteToBase */,
|
|
21564
|
+
currentPoint,
|
|
21565
|
+
virtualPool.activationPoint
|
|
21566
|
+
);
|
|
21567
|
+
let totalFeeNumerator = baseFeeNumerator;
|
|
21568
|
+
if (config.poolFees.dynamicFee.initialized !== 0) {
|
|
21569
|
+
const variableFee = getVariableFee(
|
|
21570
|
+
config.poolFees.dynamicFee,
|
|
21571
|
+
virtualPool.volatilityTracker
|
|
21572
|
+
);
|
|
21573
|
+
totalFeeNumerator = SafeMath.add(totalFeeNumerator, variableFee);
|
|
21574
|
+
}
|
|
21575
|
+
totalFeeNumerator = BN12.min(totalFeeNumerator, new BN12(MAX_FEE_NUMERATOR));
|
|
21576
|
+
const denominator = new BN12(FEE_DENOMINATOR).sub(totalFeeNumerator);
|
|
21577
|
+
return mulDiv(
|
|
21578
|
+
amountInAfterFee,
|
|
21579
|
+
new BN12(FEE_DENOMINATOR),
|
|
21580
|
+
denominator,
|
|
21581
|
+
0 /* Up */
|
|
21582
|
+
);
|
|
21583
|
+
} else {
|
|
21584
|
+
return amountInAfterFee;
|
|
21585
|
+
}
|
|
21586
|
+
}
|
|
21267
21587
|
|
|
21268
21588
|
// src/services/state.ts
|
|
21269
21589
|
import { PublicKey as PublicKey8 } from "@solana/web3.js";
|
|
@@ -21508,6 +21828,7 @@ var StateService = class extends DynamicBondingCurveProgram {
|
|
|
21508
21828
|
};
|
|
21509
21829
|
|
|
21510
21830
|
// src/services/pool.ts
|
|
21831
|
+
import BN13 from "bn.js";
|
|
21511
21832
|
var PoolService = class extends DynamicBondingCurveProgram {
|
|
21512
21833
|
constructor(connection, commitment) {
|
|
21513
21834
|
super(connection, commitment);
|
|
@@ -21682,6 +22003,22 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
21682
22003
|
const { baseMint, poolCreator } = createConfigAndPoolWithFirstBuyParam.createPoolParam;
|
|
21683
22004
|
const { buyAmount, minimumAmountOut, referralTokenAccount } = createConfigAndPoolWithFirstBuyParam.swapBuyParam;
|
|
21684
22005
|
validateSwapAmount(buyAmount);
|
|
22006
|
+
let currentPoint;
|
|
22007
|
+
if (createConfigAndPoolWithFirstBuyParam.activationType === 0 /* Slot */) {
|
|
22008
|
+
const currentSlot = await this.connection.getSlot();
|
|
22009
|
+
currentPoint = currentSlot;
|
|
22010
|
+
} else {
|
|
22011
|
+
const currentSlot = await this.connection.getSlot();
|
|
22012
|
+
const currentTime = await this.connection.getBlockTime(currentSlot);
|
|
22013
|
+
currentPoint = currentTime;
|
|
22014
|
+
}
|
|
22015
|
+
const isRateLimiterApplied = checkRateLimiterApplied(
|
|
22016
|
+
createConfigAndPoolWithFirstBuyParam.poolFees.baseFee.baseFeeMode,
|
|
22017
|
+
false,
|
|
22018
|
+
new BN13(0),
|
|
22019
|
+
new BN13(0),
|
|
22020
|
+
new BN13(0)
|
|
22021
|
+
);
|
|
21685
22022
|
const quoteTokenFlag = await getTokenType(this.connection, quoteMint);
|
|
21686
22023
|
const { inputMint, outputMint, inputTokenProgram, outputTokenProgram } = this.prepareSwapParams(
|
|
21687
22024
|
false,
|
|
@@ -21725,6 +22062,13 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
21725
22062
|
const unwrapIx = unwrapSOLInstruction(poolCreator, poolCreator);
|
|
21726
22063
|
unwrapIx && postInstructions.push(unwrapIx);
|
|
21727
22064
|
}
|
|
22065
|
+
const remainingAccounts = isRateLimiterApplied ? [
|
|
22066
|
+
{
|
|
22067
|
+
isSigner: false,
|
|
22068
|
+
isWritable: false,
|
|
22069
|
+
pubkey: SYSVAR_INSTRUCTIONS_PUBKEY
|
|
22070
|
+
}
|
|
22071
|
+
] : [];
|
|
21728
22072
|
return this.program.methods.swap({
|
|
21729
22073
|
amountIn: buyAmount,
|
|
21730
22074
|
minimumAmountOut
|
|
@@ -21742,7 +22086,7 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
21742
22086
|
payer: poolCreator,
|
|
21743
22087
|
tokenBaseProgram: outputTokenProgram,
|
|
21744
22088
|
tokenQuoteProgram: inputTokenProgram
|
|
21745
|
-
}).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
|
|
22089
|
+
}).remainingAccounts(remainingAccounts).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
|
|
21746
22090
|
}
|
|
21747
22091
|
/**
|
|
21748
22092
|
* Create a new pool
|
|
@@ -21915,6 +22259,22 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
21915
22259
|
tx = await this.initializeToken2022Pool(baseParams);
|
|
21916
22260
|
}
|
|
21917
22261
|
validateSwapAmount(buyAmount);
|
|
22262
|
+
let currentPoint;
|
|
22263
|
+
if (poolConfigState.activationType === 0 /* Slot */) {
|
|
22264
|
+
const currentSlot = await this.connection.getSlot();
|
|
22265
|
+
currentPoint = new BN13(currentSlot);
|
|
22266
|
+
} else {
|
|
22267
|
+
const currentSlot = await this.connection.getSlot();
|
|
22268
|
+
const currentTime = await this.connection.getBlockTime(currentSlot);
|
|
22269
|
+
currentPoint = new BN13(currentTime);
|
|
22270
|
+
}
|
|
22271
|
+
const isRateLimiterApplied = checkRateLimiterApplied(
|
|
22272
|
+
poolConfigState.poolFees.baseFee.baseFeeMode,
|
|
22273
|
+
false,
|
|
22274
|
+
new BN13(0),
|
|
22275
|
+
new BN13(0),
|
|
22276
|
+
new BN13(0)
|
|
22277
|
+
);
|
|
21918
22278
|
const { inputMint, outputMint, inputTokenProgram, outputTokenProgram } = this.prepareSwapParams(
|
|
21919
22279
|
false,
|
|
21920
22280
|
{ baseMint, poolType: tokenType },
|
|
@@ -21948,7 +22308,14 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
21948
22308
|
const unwrapIx = unwrapSOLInstruction(poolCreator, poolCreator);
|
|
21949
22309
|
unwrapIx && postInstructions.push(unwrapIx);
|
|
21950
22310
|
}
|
|
21951
|
-
const
|
|
22311
|
+
const remainingAccounts = isRateLimiterApplied ? [
|
|
22312
|
+
{
|
|
22313
|
+
isSigner: false,
|
|
22314
|
+
isWritable: false,
|
|
22315
|
+
pubkey: SYSVAR_INSTRUCTIONS_PUBKEY
|
|
22316
|
+
}
|
|
22317
|
+
] : [];
|
|
22318
|
+
const firstBuyTx = await this.program.methods.swap({
|
|
21952
22319
|
amountIn: buyAmount,
|
|
21953
22320
|
minimumAmountOut
|
|
21954
22321
|
}).accountsPartial({
|
|
@@ -21965,8 +22332,8 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
21965
22332
|
payer: poolCreator,
|
|
21966
22333
|
tokenBaseProgram: outputTokenProgram,
|
|
21967
22334
|
tokenQuoteProgram: inputTokenProgram
|
|
21968
|
-
}).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
|
|
21969
|
-
tx.add(...
|
|
22335
|
+
}).remainingAccounts(remainingAccounts).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
|
|
22336
|
+
tx.add(...firstBuyTx.instructions);
|
|
21970
22337
|
return tx;
|
|
21971
22338
|
}
|
|
21972
22339
|
/**
|
|
@@ -21983,6 +22350,22 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
21983
22350
|
const poolConfigState = await this.state.getPoolConfig(poolState.config);
|
|
21984
22351
|
const { amountIn, minimumAmountOut, swapBaseForQuote, owner } = swapParam;
|
|
21985
22352
|
validateSwapAmount(amountIn);
|
|
22353
|
+
let currentPoint;
|
|
22354
|
+
if (poolConfigState.activationType === 0 /* Slot */) {
|
|
22355
|
+
const currentSlot = await this.connection.getSlot();
|
|
22356
|
+
currentPoint = new BN13(currentSlot);
|
|
22357
|
+
} else {
|
|
22358
|
+
const currentSlot = await this.connection.getSlot();
|
|
22359
|
+
const currentTime = await this.connection.getBlockTime(currentSlot);
|
|
22360
|
+
currentPoint = new BN13(currentTime);
|
|
22361
|
+
}
|
|
22362
|
+
const isRateLimiterApplied = checkRateLimiterApplied(
|
|
22363
|
+
poolConfigState.poolFees.baseFee.baseFeeMode,
|
|
22364
|
+
swapBaseForQuote,
|
|
22365
|
+
currentPoint,
|
|
22366
|
+
poolState.activationPoint,
|
|
22367
|
+
poolConfigState.poolFees.baseFee.secondFactor
|
|
22368
|
+
);
|
|
21986
22369
|
const { inputMint, outputMint, inputTokenProgram, outputTokenProgram } = this.prepareSwapParams(swapBaseForQuote, poolState, poolConfigState);
|
|
21987
22370
|
const {
|
|
21988
22371
|
ataTokenA: inputTokenAccount,
|
|
@@ -22012,6 +22395,13 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
22012
22395
|
const unwrapIx = unwrapSOLInstruction(owner, owner);
|
|
22013
22396
|
unwrapIx && postInstructions.push(unwrapIx);
|
|
22014
22397
|
}
|
|
22398
|
+
const remainingAccounts = isRateLimiterApplied ? [
|
|
22399
|
+
{
|
|
22400
|
+
isSigner: false,
|
|
22401
|
+
isWritable: false,
|
|
22402
|
+
pubkey: SYSVAR_INSTRUCTIONS_PUBKEY
|
|
22403
|
+
}
|
|
22404
|
+
] : [];
|
|
22015
22405
|
return this.program.methods.swap({
|
|
22016
22406
|
amountIn,
|
|
22017
22407
|
minimumAmountOut
|
|
@@ -22029,7 +22419,7 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
22029
22419
|
payer: owner,
|
|
22030
22420
|
tokenBaseProgram: swapBaseForQuote ? inputTokenProgram : outputTokenProgram,
|
|
22031
22421
|
tokenQuoteProgram: swapBaseForQuote ? outputTokenProgram : inputTokenProgram
|
|
22032
|
-
}).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
|
|
22422
|
+
}).remainingAccounts(remainingAccounts).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
|
|
22033
22423
|
}
|
|
22034
22424
|
/**
|
|
22035
22425
|
* Calculate the amount out for a swap (quote)
|
|
@@ -22062,6 +22452,17 @@ var PoolService = class extends DynamicBondingCurveProgram {
|
|
|
22062
22452
|
currentPoint
|
|
22063
22453
|
);
|
|
22064
22454
|
}
|
|
22455
|
+
swapQuoteExactIn(swapQuoteExactInParam) {
|
|
22456
|
+
const { virtualPool, config, currentPoint } = swapQuoteExactInParam;
|
|
22457
|
+
const requiredQuoteAmount = calculateQuoteExactInAmount(
|
|
22458
|
+
config,
|
|
22459
|
+
virtualPool,
|
|
22460
|
+
currentPoint
|
|
22461
|
+
);
|
|
22462
|
+
return {
|
|
22463
|
+
exactAmountIn: requiredQuoteAmount
|
|
22464
|
+
};
|
|
22465
|
+
}
|
|
22065
22466
|
};
|
|
22066
22467
|
|
|
22067
22468
|
// src/services/migration.ts
|
|
@@ -23478,6 +23879,7 @@ export {
|
|
|
23478
23879
|
BASIS_POINT_MAX,
|
|
23479
23880
|
BIN_STEP_BPS_DEFAULT,
|
|
23480
23881
|
BIN_STEP_BPS_U128_DEFAULT,
|
|
23882
|
+
BaseFeeMode,
|
|
23481
23883
|
CollectFeeMode,
|
|
23482
23884
|
CreatorService,
|
|
23483
23885
|
DAMM_V1_MIGRATION_FEE_ADDRESS,
|
|
@@ -23491,15 +23893,19 @@ export {
|
|
|
23491
23893
|
DynamicBondingCurveClient,
|
|
23492
23894
|
DynamicBondingCurveProgram,
|
|
23493
23895
|
FEE_DENOMINATOR,
|
|
23494
|
-
FeeSchedulerMode,
|
|
23495
23896
|
GetFeeMode,
|
|
23496
23897
|
LOCKER_PROGRAM_ID,
|
|
23497
23898
|
MAX_CURVE_POINT,
|
|
23899
|
+
MAX_FEE_BPS,
|
|
23498
23900
|
MAX_FEE_NUMERATOR,
|
|
23499
23901
|
MAX_PRICE_CHANGE_BPS_DEFAULT,
|
|
23902
|
+
MAX_RATE_LIMITER_DURATION_IN_SECONDS,
|
|
23903
|
+
MAX_RATE_LIMITER_DURATION_IN_SLOTS,
|
|
23500
23904
|
MAX_SQRT_PRICE,
|
|
23501
23905
|
MAX_SWALLOW_PERCENTAGE,
|
|
23502
23906
|
METAPLEX_PROGRAM_ID,
|
|
23907
|
+
MIN_FEE_BPS,
|
|
23908
|
+
MIN_FEE_NUMERATOR,
|
|
23503
23909
|
MIN_SQRT_PRICE,
|
|
23504
23910
|
MigrationFeeOption,
|
|
23505
23911
|
MigrationOption,
|
|
@@ -23525,6 +23931,9 @@ export {
|
|
|
23525
23931
|
buildCurveWithLiquidityWeights,
|
|
23526
23932
|
buildCurveWithMarketCap,
|
|
23527
23933
|
buildCurveWithTwoSegments,
|
|
23934
|
+
calculateFeeSchedulerEndingBaseFeeBps,
|
|
23935
|
+
calculateQuoteExactInAmount,
|
|
23936
|
+
checkRateLimiterApplied,
|
|
23528
23937
|
cleanUpTokenAccountTx,
|
|
23529
23938
|
convertDecimalToBN,
|
|
23530
23939
|
convertToLamports,
|
|
@@ -23571,16 +23980,19 @@ export {
|
|
|
23571
23980
|
getAccountCreationTimestamp,
|
|
23572
23981
|
getAccountCreationTimestamps,
|
|
23573
23982
|
getAccountData,
|
|
23983
|
+
getBaseFeeNumerator,
|
|
23574
23984
|
getBaseFeeParams,
|
|
23575
23985
|
getBaseTokenForSwap,
|
|
23576
|
-
getCurrentBaseFeeNumerator,
|
|
23577
23986
|
getDeltaAmountBase,
|
|
23578
23987
|
getDeltaAmountBaseUnsigned,
|
|
23579
23988
|
getDeltaAmountQuoteUnsigned,
|
|
23580
23989
|
getDynamicFeeParams,
|
|
23581
|
-
getFeeInPeriod,
|
|
23582
23990
|
getFeeMode,
|
|
23991
|
+
getFeeNumeratorOnExponentialFeeScheduler,
|
|
23992
|
+
getFeeNumeratorOnLinearFeeScheduler,
|
|
23993
|
+
getFeeNumeratorOnRateLimiter,
|
|
23583
23994
|
getFeeOnAmount,
|
|
23995
|
+
getFeeSchedulerParams,
|
|
23584
23996
|
getFirstCurve,
|
|
23585
23997
|
getFirstKey,
|
|
23586
23998
|
getInitialLiquidityFromDeltaBase,
|
|
@@ -23593,13 +24005,13 @@ export {
|
|
|
23593
24005
|
getMigrationQuoteAmountFromMigrationQuoteThreshold,
|
|
23594
24006
|
getMigrationQuoteThresholdFromMigrationQuoteAmount,
|
|
23595
24007
|
getMigrationThresholdPrice,
|
|
23596
|
-
getMinBaseFeeBps,
|
|
23597
24008
|
getNextSqrtPriceFromAmountBaseRoundingUp,
|
|
23598
24009
|
getNextSqrtPriceFromAmountQuoteRoundingDown,
|
|
23599
24010
|
getNextSqrtPriceFromInput,
|
|
23600
24011
|
getOrCreateATAInstruction,
|
|
23601
24012
|
getPercentageSupplyOnMigration,
|
|
23602
24013
|
getPriceFromSqrtPrice,
|
|
24014
|
+
getRateLimiterParams,
|
|
23603
24015
|
getSecondKey,
|
|
23604
24016
|
getSqrtPriceFromMarketCap,
|
|
23605
24017
|
getSqrtPriceFromPrice,
|
|
@@ -23626,6 +24038,8 @@ export {
|
|
|
23626
24038
|
validateCollectFeeMode,
|
|
23627
24039
|
validateConfigParameters,
|
|
23628
24040
|
validateCurve,
|
|
24041
|
+
validateFeeRateLimiter,
|
|
24042
|
+
validateFeeScheduler,
|
|
23629
24043
|
validateLPPercentages,
|
|
23630
24044
|
validateMigrationAndTokenType,
|
|
23631
24045
|
validateMigrationFeeOption,
|