@meteora-ag/dlmm 1.9.12 → 1.9.14
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 +26 -24
- package/dist/index.d.ts +51 -1
- package/dist/index.js +736 -488
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +739 -491
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -12
package/dist/index.mjs
CHANGED
|
@@ -10448,7 +10448,7 @@ var LimitOrderStatus = /* @__PURE__ */ ((LimitOrderStatus2) => {
|
|
|
10448
10448
|
})(LimitOrderStatus || {});
|
|
10449
10449
|
|
|
10450
10450
|
// src/dlmm/helpers/binArray.ts
|
|
10451
|
-
import { BN as
|
|
10451
|
+
import { BN as BN10 } from "@coral-xyz/anchor";
|
|
10452
10452
|
import { PublicKey as PublicKey5 } from "@solana/web3.js";
|
|
10453
10453
|
|
|
10454
10454
|
// src/dlmm/helpers/derive.ts
|
|
@@ -11811,137 +11811,422 @@ function generateBinAmount(amount, binStep, binId, tokenXDecimal, tokenYDecimal,
|
|
|
11811
11811
|
return new BN7(c1.sub(c0).floor().toString());
|
|
11812
11812
|
}
|
|
11813
11813
|
|
|
11814
|
-
// src/dlmm/helpers/
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
const
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11814
|
+
// src/dlmm/helpers/positions/index.ts
|
|
11815
|
+
import BN9 from "bn.js";
|
|
11816
|
+
|
|
11817
|
+
// src/dlmm/helpers/positions/wrapper.ts
|
|
11818
|
+
import BN8 from "bn.js";
|
|
11819
|
+
function combineBaseAndExtendedPositionBinData(base, extended) {
|
|
11820
|
+
const combinedLiquidityShares = base.liquidityShares;
|
|
11821
|
+
const combinedRewardInfos = base.rewardInfos;
|
|
11822
|
+
const combinedFeeInfos = base.feeInfos;
|
|
11823
|
+
for (const binData of extended) {
|
|
11824
|
+
combinedLiquidityShares.push(binData.liquidityShare);
|
|
11825
|
+
combinedRewardInfos.push(binData.rewardInfo);
|
|
11826
|
+
combinedFeeInfos.push(binData.feeInfo);
|
|
11827
|
+
}
|
|
11828
|
+
return {
|
|
11829
|
+
liquidityShares: combinedLiquidityShares,
|
|
11830
|
+
rewardInfos: combinedRewardInfos,
|
|
11831
|
+
feeInfos: combinedFeeInfos
|
|
11832
|
+
};
|
|
11827
11833
|
}
|
|
11828
|
-
function
|
|
11829
|
-
|
|
11830
|
-
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11834
|
+
function wrapPosition(program, key, account) {
|
|
11835
|
+
const disc = account.data.subarray(0, 8);
|
|
11836
|
+
if (disc.equals(Buffer.from(getAccountDiscriminator("positionV2")))) {
|
|
11837
|
+
const state = decodeAccount(
|
|
11838
|
+
program,
|
|
11839
|
+
"positionV2",
|
|
11840
|
+
account.data
|
|
11841
|
+
);
|
|
11842
|
+
const extended = decodeExtendedPosition(
|
|
11843
|
+
state,
|
|
11844
|
+
program,
|
|
11845
|
+
account.data.subarray(8 + POSITION_MIN_SIZE)
|
|
11846
|
+
);
|
|
11847
|
+
const combinedPositionBinData = combineBaseAndExtendedPositionBinData(
|
|
11848
|
+
state,
|
|
11849
|
+
extended
|
|
11850
|
+
);
|
|
11851
|
+
return new PositionV2Wrapper(key, state, extended, combinedPositionBinData);
|
|
11834
11852
|
} else {
|
|
11835
|
-
|
|
11836
|
-
bits: 512,
|
|
11837
|
-
bytes: 512 / 8
|
|
11838
|
-
};
|
|
11853
|
+
throw new Error("Unknown position account");
|
|
11839
11854
|
}
|
|
11840
11855
|
}
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11856
|
+
var PositionV2Wrapper = class {
|
|
11857
|
+
constructor(positionAddress, inner, extended, combinedPositionBinData) {
|
|
11858
|
+
this.positionAddress = positionAddress;
|
|
11859
|
+
this.inner = inner;
|
|
11860
|
+
this.extended = extended;
|
|
11861
|
+
this.combinedPositionBinData = combinedPositionBinData;
|
|
11845
11862
|
}
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
return highestIndex - i;
|
|
11849
|
-
}
|
|
11863
|
+
address() {
|
|
11864
|
+
return this.positionAddress;
|
|
11850
11865
|
}
|
|
11851
|
-
|
|
11852
|
-
|
|
11853
|
-
function leastSignificantBit(number, bitLength) {
|
|
11854
|
-
if (number.isZero()) {
|
|
11855
|
-
return null;
|
|
11866
|
+
totalClaimedRewards() {
|
|
11867
|
+
return this.inner.totalClaimedRewards;
|
|
11856
11868
|
}
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11869
|
+
feeOwner() {
|
|
11870
|
+
return this.inner.feeOwner;
|
|
11871
|
+
}
|
|
11872
|
+
lockReleasePoint() {
|
|
11873
|
+
return this.inner.lockReleasePoint;
|
|
11874
|
+
}
|
|
11875
|
+
operator() {
|
|
11876
|
+
return this.inner.operator;
|
|
11877
|
+
}
|
|
11878
|
+
totalClaimedFeeYAmount() {
|
|
11879
|
+
return this.inner.totalClaimedFeeYAmount;
|
|
11880
|
+
}
|
|
11881
|
+
totalClaimedFeeXAmount() {
|
|
11882
|
+
return this.inner.totalClaimedFeeXAmount;
|
|
11883
|
+
}
|
|
11884
|
+
lbPair() {
|
|
11885
|
+
return this.inner.lbPair;
|
|
11886
|
+
}
|
|
11887
|
+
lowerBinId() {
|
|
11888
|
+
return new BN8(this.inner.lowerBinId);
|
|
11889
|
+
}
|
|
11890
|
+
upperBinId() {
|
|
11891
|
+
return new BN8(this.inner.upperBinId);
|
|
11892
|
+
}
|
|
11893
|
+
liquidityShares() {
|
|
11894
|
+
return this.combinedPositionBinData.liquidityShares;
|
|
11895
|
+
}
|
|
11896
|
+
rewardInfos() {
|
|
11897
|
+
return this.combinedPositionBinData.rewardInfos;
|
|
11898
|
+
}
|
|
11899
|
+
feeInfos() {
|
|
11900
|
+
return this.combinedPositionBinData.feeInfos;
|
|
11901
|
+
}
|
|
11902
|
+
lastUpdatedAt() {
|
|
11903
|
+
return this.inner.lastUpdatedAt;
|
|
11904
|
+
}
|
|
11905
|
+
getBinArrayIndexesCoverage() {
|
|
11906
|
+
const isExtended = this.extended.length > 0;
|
|
11907
|
+
if (isExtended) {
|
|
11908
|
+
return getBinArrayIndexesCoverage(this.lowerBinId(), this.upperBinId());
|
|
11909
|
+
} else {
|
|
11910
|
+
const lowerBinArrayIndex = binIdToBinArrayIndex(this.lowerBinId());
|
|
11911
|
+
const upperBinArrayIndex = lowerBinArrayIndex.add(new BN8(1));
|
|
11912
|
+
return [lowerBinArrayIndex, upperBinArrayIndex];
|
|
11860
11913
|
}
|
|
11861
11914
|
}
|
|
11862
|
-
|
|
11915
|
+
getBinArrayKeysCoverage(programId) {
|
|
11916
|
+
return this.getBinArrayIndexesCoverage().map(
|
|
11917
|
+
(index) => deriveBinArray(this.lbPair(), index, programId)[0]
|
|
11918
|
+
);
|
|
11919
|
+
}
|
|
11920
|
+
version() {
|
|
11921
|
+
return 1 /* V2 */;
|
|
11922
|
+
}
|
|
11923
|
+
owner() {
|
|
11924
|
+
return this.inner.owner;
|
|
11925
|
+
}
|
|
11926
|
+
width() {
|
|
11927
|
+
return this.upperBinId().sub(this.lowerBinId()).add(new BN8(1));
|
|
11928
|
+
}
|
|
11929
|
+
};
|
|
11930
|
+
|
|
11931
|
+
// src/dlmm/helpers/positions/index.ts
|
|
11932
|
+
function getBinArrayIndexesCoverage(lowerBinId, upperBinId) {
|
|
11933
|
+
const lowerBinArrayIndex = binIdToBinArrayIndex(lowerBinId);
|
|
11934
|
+
const upperBinArrayIndex = binIdToBinArrayIndex(upperBinId);
|
|
11935
|
+
const binArrayIndexes = [];
|
|
11936
|
+
for (let i = lowerBinArrayIndex.toNumber(); i <= upperBinArrayIndex.toNumber(); i++) {
|
|
11937
|
+
binArrayIndexes.push(new BN9(i));
|
|
11938
|
+
}
|
|
11939
|
+
return binArrayIndexes;
|
|
11863
11940
|
}
|
|
11864
|
-
function
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
BIN_ARRAY_BITMAP_SIZE.mul(
|
|
11870
|
-
EXTENSION_BINARRAY_BITMAP_SIZE.add(new BN8(1))
|
|
11871
|
-
).sub(new BN8(1))
|
|
11872
|
-
];
|
|
11941
|
+
function getBinArrayKeysCoverage(lowerBinId, upperBinId, lbPair, programId) {
|
|
11942
|
+
const binArrayIndexes = getBinArrayIndexesCoverage(lowerBinId, upperBinId);
|
|
11943
|
+
return binArrayIndexes.map((index) => {
|
|
11944
|
+
return deriveBinArray(lbPair, index, programId)[0];
|
|
11945
|
+
});
|
|
11873
11946
|
}
|
|
11874
|
-
function
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
for (let i = startIndex; i <= endIndex; i++) {
|
|
11883
|
-
const binArrayOffset = getBinArrayOffset(new BN8(i)).toNumber();
|
|
11884
|
-
const bitmapOffset = getBitmapOffset(new BN8(i)).toNumber();
|
|
11885
|
-
const bitmapChunks = i > 0 ? binArrayBitmapExtension.positiveBinArrayBitmap[bitmapOffset] : binArrayBitmapExtension.negativeBinArrayBitmap[bitmapOffset];
|
|
11886
|
-
const bitmap = buildBitmapFromU64Arrays(bitmapChunks, 1 /* U512 */);
|
|
11887
|
-
if (bitmap.testn(binArrayOffset)) {
|
|
11888
|
-
return i;
|
|
11889
|
-
}
|
|
11890
|
-
}
|
|
11891
|
-
} else {
|
|
11892
|
-
for (let i = startIndex; i >= endIndex; i--) {
|
|
11893
|
-
const binArrayOffset = getBinArrayOffset(new BN8(i)).toNumber();
|
|
11894
|
-
const bitmapOffset = getBitmapOffset(new BN8(i)).toNumber();
|
|
11895
|
-
const bitmapChunks = i > 0 ? binArrayBitmapExtension.positiveBinArrayBitmap[bitmapOffset] : binArrayBitmapExtension.negativeBinArrayBitmap[bitmapOffset];
|
|
11896
|
-
const bitmap = buildBitmapFromU64Arrays(bitmapChunks, 1 /* U512 */);
|
|
11897
|
-
if (bitmap.testn(binArrayOffset)) {
|
|
11898
|
-
return i;
|
|
11899
|
-
}
|
|
11947
|
+
function getBinArrayAccountMetasCoverage(lowerBinId, upperBinId, lbPair, programId) {
|
|
11948
|
+
return getBinArrayKeysCoverage(lowerBinId, upperBinId, lbPair, programId).map(
|
|
11949
|
+
(key) => {
|
|
11950
|
+
return {
|
|
11951
|
+
pubkey: key,
|
|
11952
|
+
isSigner: false,
|
|
11953
|
+
isWritable: true
|
|
11954
|
+
};
|
|
11900
11955
|
}
|
|
11901
|
-
|
|
11902
|
-
return null;
|
|
11903
|
-
}
|
|
11904
|
-
function isOverflowDefaultBinArrayBitmap(binArrayIndex) {
|
|
11905
|
-
const [minBinArrayIndex, maxBinArrayIndex] = internalBitmapRange();
|
|
11906
|
-
return binArrayIndex.gt(maxBinArrayIndex) || binArrayIndex.lt(minBinArrayIndex);
|
|
11956
|
+
);
|
|
11907
11957
|
}
|
|
11908
|
-
function
|
|
11909
|
-
|
|
11910
|
-
[
|
|
11911
|
-
programId
|
|
11958
|
+
function getPositionLowerUpperBinIdWithLiquidity(position) {
|
|
11959
|
+
const binWithLiquidity = position.positionBinData.filter(
|
|
11960
|
+
(b) => !new BN9(b.binLiquidity).isZero() || !new BN9(b.positionFeeXAmount.toString()).isZero() || !new BN9(b.positionFeeYAmount.toString()).isZero() || !new BN9(b.positionRewardAmount[0].toString()).isZero() || !new BN9(b.positionRewardAmount[1].toString()).isZero()
|
|
11912
11961
|
);
|
|
11962
|
+
return binWithLiquidity.length > 0 ? {
|
|
11963
|
+
lowerBinId: new BN9(binWithLiquidity[0].binId),
|
|
11964
|
+
upperBinId: new BN9(binWithLiquidity[binWithLiquidity.length - 1].binId)
|
|
11965
|
+
} : null;
|
|
11913
11966
|
}
|
|
11914
|
-
function
|
|
11915
|
-
|
|
11916
|
-
return binId.isNeg() && !mod.isZero() ? idx.sub(new BN8(1)) : idx;
|
|
11967
|
+
function isPositionNoFee(position) {
|
|
11968
|
+
return position.feeX.isZero() && position.feeY.isZero();
|
|
11917
11969
|
}
|
|
11918
|
-
function
|
|
11919
|
-
|
|
11920
|
-
const upperBinId = lowerBinId.add(MAX_BIN_ARRAY_SIZE).sub(new BN8(1));
|
|
11921
|
-
return [lowerBinId, upperBinId];
|
|
11970
|
+
function isPositionNoReward(position) {
|
|
11971
|
+
return position.rewardOne.isZero() && position.rewardTwo.isZero();
|
|
11922
11972
|
}
|
|
11923
|
-
function
|
|
11924
|
-
const
|
|
11925
|
-
|
|
11973
|
+
function chunkBinRangeIntoExtendedPositions(minBinId, maxBinId) {
|
|
11974
|
+
const chunkedBinRange = [];
|
|
11975
|
+
for (let currentMinBinId = minBinId; currentMinBinId <= maxBinId; currentMinBinId += POSITION_MAX_LENGTH.toNumber()) {
|
|
11976
|
+
const currentMaxBinId = Math.min(
|
|
11977
|
+
currentMinBinId + POSITION_MAX_LENGTH.toNumber() - 1,
|
|
11978
|
+
maxBinId
|
|
11979
|
+
);
|
|
11980
|
+
chunkedBinRange.push({
|
|
11981
|
+
lowerBinId: currentMinBinId,
|
|
11982
|
+
upperBinId: currentMaxBinId
|
|
11983
|
+
});
|
|
11984
|
+
}
|
|
11985
|
+
return chunkedBinRange;
|
|
11926
11986
|
}
|
|
11927
|
-
function
|
|
11928
|
-
const
|
|
11929
|
-
let
|
|
11930
|
-
|
|
11931
|
-
|
|
11932
|
-
|
|
11933
|
-
|
|
11934
|
-
|
|
11987
|
+
function chunkBinRange(minBinId, maxBinId, binPerChunk) {
|
|
11988
|
+
const chunkedBinRange = [];
|
|
11989
|
+
let startBinId = minBinId;
|
|
11990
|
+
binPerChunk = binPerChunk ?? DEFAULT_BIN_PER_POSITION.toNumber();
|
|
11991
|
+
while (startBinId <= maxBinId) {
|
|
11992
|
+
const endBinId = Math.min(startBinId + binPerChunk - 1, maxBinId);
|
|
11993
|
+
chunkedBinRange.push({
|
|
11994
|
+
lowerBinId: startBinId,
|
|
11995
|
+
upperBinId: endBinId
|
|
11996
|
+
});
|
|
11997
|
+
startBinId += binPerChunk;
|
|
11935
11998
|
}
|
|
11936
|
-
return
|
|
11999
|
+
return chunkedBinRange;
|
|
11937
12000
|
}
|
|
11938
|
-
function
|
|
11939
|
-
const
|
|
11940
|
-
let
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
12001
|
+
function chunkPositionBinRange(position, minBinId, maxBinId) {
|
|
12002
|
+
const chunkedFeesAndRewards = [];
|
|
12003
|
+
let totalAmountX = new BN9(0);
|
|
12004
|
+
let totalAmountY = new BN9(0);
|
|
12005
|
+
let totalFeeXAmount = new BN9(0);
|
|
12006
|
+
let totalFeeYAmount = new BN9(0);
|
|
12007
|
+
let totalRewardAmounts = [new BN9(0), new BN9(0)];
|
|
12008
|
+
let count = 0;
|
|
12009
|
+
for (let i = 0; i < position.positionData.positionBinData.length; i++) {
|
|
12010
|
+
const positionBinData = position.positionData.positionBinData[i];
|
|
12011
|
+
if (positionBinData.binId >= minBinId && positionBinData.binId <= maxBinId) {
|
|
12012
|
+
totalFeeXAmount = totalFeeXAmount.add(
|
|
12013
|
+
new BN9(positionBinData.positionFeeXAmount)
|
|
12014
|
+
);
|
|
12015
|
+
totalFeeYAmount = totalFeeYAmount.add(
|
|
12016
|
+
new BN9(positionBinData.positionFeeYAmount)
|
|
12017
|
+
);
|
|
12018
|
+
totalAmountX = totalAmountX.add(new BN9(positionBinData.positionXAmount));
|
|
12019
|
+
totalAmountY = totalAmountY.add(new BN9(positionBinData.positionYAmount));
|
|
12020
|
+
for (const [
|
|
12021
|
+
index,
|
|
12022
|
+
reward
|
|
12023
|
+
] of positionBinData.positionRewardAmount.entries()) {
|
|
12024
|
+
totalRewardAmounts[index] = totalRewardAmounts[index].add(
|
|
12025
|
+
new BN9(reward)
|
|
12026
|
+
);
|
|
12027
|
+
}
|
|
12028
|
+
count++;
|
|
12029
|
+
}
|
|
12030
|
+
if (count === DEFAULT_BIN_PER_POSITION.toNumber() || positionBinData.binId == maxBinId) {
|
|
12031
|
+
chunkedFeesAndRewards.push({
|
|
12032
|
+
minBinId: positionBinData.binId - count + 1,
|
|
12033
|
+
maxBinId: positionBinData.binId,
|
|
12034
|
+
feeXAmount: totalFeeXAmount,
|
|
12035
|
+
feeYAmount: totalFeeYAmount,
|
|
12036
|
+
rewardAmounts: totalRewardAmounts,
|
|
12037
|
+
amountX: totalAmountX,
|
|
12038
|
+
amountY: totalAmountY
|
|
12039
|
+
});
|
|
12040
|
+
totalFeeXAmount = new BN9(0);
|
|
12041
|
+
totalFeeYAmount = new BN9(0);
|
|
12042
|
+
totalAmountX = new BN9(0);
|
|
12043
|
+
totalAmountY = new BN9(0);
|
|
12044
|
+
totalRewardAmounts = [new BN9(0), new BN9(0)];
|
|
12045
|
+
count = 0;
|
|
12046
|
+
}
|
|
12047
|
+
}
|
|
12048
|
+
return chunkedFeesAndRewards;
|
|
12049
|
+
}
|
|
12050
|
+
function calculatePositionSize(binCount) {
|
|
12051
|
+
const extraBinCount = binCount.gt(DEFAULT_BIN_PER_POSITION) ? binCount.sub(DEFAULT_BIN_PER_POSITION) : new BN9(0);
|
|
12052
|
+
return new BN9(POSITION_MIN_SIZE).add(
|
|
12053
|
+
extraBinCount.mul(new BN9(POSITION_BIN_DATA_SIZE))
|
|
12054
|
+
);
|
|
12055
|
+
}
|
|
12056
|
+
function getPositionRentExemption(connection, binCount) {
|
|
12057
|
+
const size = calculatePositionSize(binCount);
|
|
12058
|
+
return connection.getMinimumBalanceForRentExemption(size.toNumber());
|
|
12059
|
+
}
|
|
12060
|
+
async function getPositionExpandRentExemption(currentMinBinId, currentMaxBinId, connection, binCountToExpand) {
|
|
12061
|
+
const currentPositionWidth = currentMaxBinId.sub(currentMinBinId).addn(1);
|
|
12062
|
+
const positionWidthAfterExpand = currentPositionWidth.add(binCountToExpand);
|
|
12063
|
+
if (positionWidthAfterExpand.lte(DEFAULT_BIN_PER_POSITION)) {
|
|
12064
|
+
return 0;
|
|
12065
|
+
} else {
|
|
12066
|
+
const binCountInExpandedBytes = positionWidthAfterExpand.sub(
|
|
12067
|
+
DEFAULT_BIN_PER_POSITION
|
|
12068
|
+
);
|
|
12069
|
+
const expandSize = binCountInExpandedBytes.toNumber() * POSITION_BIN_DATA_SIZE;
|
|
12070
|
+
const [minimumLamports, rentExemptionLamports] = await Promise.all([
|
|
12071
|
+
connection.getMinimumBalanceForRentExemption(0),
|
|
12072
|
+
connection.getMinimumBalanceForRentExemption(expandSize)
|
|
12073
|
+
]);
|
|
12074
|
+
return rentExemptionLamports - minimumLamports;
|
|
12075
|
+
}
|
|
12076
|
+
}
|
|
12077
|
+
function getExtendedPositionBinCount(minBinId, maxBinId) {
|
|
12078
|
+
const width = maxBinId.sub(minBinId).addn(1);
|
|
12079
|
+
const extended = width.sub(DEFAULT_BIN_PER_POSITION);
|
|
12080
|
+
return extended.lte(new BN9(0)) ? new BN9(0) : extended;
|
|
12081
|
+
}
|
|
12082
|
+
function decodeExtendedPosition(base, program, bytes) {
|
|
12083
|
+
const width = base.upperBinId - base.lowerBinId + 1;
|
|
12084
|
+
const extendedWidth = width - DEFAULT_BIN_PER_POSITION.toNumber();
|
|
12085
|
+
const extendedPosition = [];
|
|
12086
|
+
for (let i = 0; i < extendedWidth; i++) {
|
|
12087
|
+
const offset = i * POSITION_BIN_DATA_SIZE;
|
|
12088
|
+
const data = bytes.subarray(offset, offset + POSITION_BIN_DATA_SIZE);
|
|
12089
|
+
const decodedPositionBinData = program.coder.types.decode(
|
|
12090
|
+
// TODO: Find a type safe way
|
|
12091
|
+
"positionBinData",
|
|
12092
|
+
data
|
|
12093
|
+
);
|
|
12094
|
+
extendedPosition.push(decodedPositionBinData);
|
|
12095
|
+
}
|
|
12096
|
+
return extendedPosition;
|
|
12097
|
+
}
|
|
12098
|
+
|
|
12099
|
+
// src/dlmm/helpers/binArray.ts
|
|
12100
|
+
function internalBitmapRange() {
|
|
12101
|
+
const lowerBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.neg();
|
|
12102
|
+
const upperBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.sub(new BN10(1));
|
|
12103
|
+
return [lowerBinArrayIndex, upperBinArrayIndex];
|
|
12104
|
+
}
|
|
12105
|
+
function buildBitmapFromU64Arrays(u64Arrays, type) {
|
|
12106
|
+
const buffer = Buffer.concat(
|
|
12107
|
+
u64Arrays.map((b) => {
|
|
12108
|
+
return b.toArrayLike(Buffer, "le", 8);
|
|
12109
|
+
})
|
|
12110
|
+
);
|
|
12111
|
+
return new BN10(buffer, "le");
|
|
12112
|
+
}
|
|
12113
|
+
function bitmapTypeDetail(type) {
|
|
12114
|
+
if (type == 0 /* U1024 */) {
|
|
12115
|
+
return {
|
|
12116
|
+
bits: 1024,
|
|
12117
|
+
bytes: 1024 / 8
|
|
12118
|
+
};
|
|
12119
|
+
} else {
|
|
12120
|
+
return {
|
|
12121
|
+
bits: 512,
|
|
12122
|
+
bytes: 512 / 8
|
|
12123
|
+
};
|
|
12124
|
+
}
|
|
12125
|
+
}
|
|
12126
|
+
function mostSignificantBit(number, bitLength) {
|
|
12127
|
+
const highestIndex = bitLength - 1;
|
|
12128
|
+
if (number.isZero()) {
|
|
12129
|
+
return null;
|
|
12130
|
+
}
|
|
12131
|
+
for (let i = highestIndex; i >= 0; i--) {
|
|
12132
|
+
if (number.testn(i)) {
|
|
12133
|
+
return highestIndex - i;
|
|
12134
|
+
}
|
|
12135
|
+
}
|
|
12136
|
+
return null;
|
|
12137
|
+
}
|
|
12138
|
+
function leastSignificantBit(number, bitLength) {
|
|
12139
|
+
if (number.isZero()) {
|
|
12140
|
+
return null;
|
|
12141
|
+
}
|
|
12142
|
+
for (let i = 0; i < bitLength; i++) {
|
|
12143
|
+
if (number.testn(i)) {
|
|
12144
|
+
return i;
|
|
12145
|
+
}
|
|
12146
|
+
}
|
|
12147
|
+
return null;
|
|
12148
|
+
}
|
|
12149
|
+
function extensionBitmapRange() {
|
|
12150
|
+
return [
|
|
12151
|
+
BIN_ARRAY_BITMAP_SIZE.neg().mul(
|
|
12152
|
+
EXTENSION_BINARRAY_BITMAP_SIZE.add(new BN10(1))
|
|
12153
|
+
),
|
|
12154
|
+
BIN_ARRAY_BITMAP_SIZE.mul(
|
|
12155
|
+
EXTENSION_BINARRAY_BITMAP_SIZE.add(new BN10(1))
|
|
12156
|
+
).sub(new BN10(1))
|
|
12157
|
+
];
|
|
12158
|
+
}
|
|
12159
|
+
function findSetBit(startIndex, endIndex, binArrayBitmapExtension) {
|
|
12160
|
+
const getBinArrayOffset = (binArrayIndex) => {
|
|
12161
|
+
return binArrayIndex.gt(new BN10(0)) ? binArrayIndex.mod(BIN_ARRAY_BITMAP_SIZE) : binArrayIndex.add(new BN10(1)).neg().mod(BIN_ARRAY_BITMAP_SIZE);
|
|
12162
|
+
};
|
|
12163
|
+
const getBitmapOffset = (binArrayIndex) => {
|
|
12164
|
+
return binArrayIndex.gt(new BN10(0)) ? binArrayIndex.div(BIN_ARRAY_BITMAP_SIZE).sub(new BN10(1)) : binArrayIndex.add(new BN10(1)).neg().div(BIN_ARRAY_BITMAP_SIZE).sub(new BN10(1));
|
|
12165
|
+
};
|
|
12166
|
+
if (startIndex <= endIndex) {
|
|
12167
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
12168
|
+
const binArrayOffset = getBinArrayOffset(new BN10(i)).toNumber();
|
|
12169
|
+
const bitmapOffset = getBitmapOffset(new BN10(i)).toNumber();
|
|
12170
|
+
const bitmapChunks = i > 0 ? binArrayBitmapExtension.positiveBinArrayBitmap[bitmapOffset] : binArrayBitmapExtension.negativeBinArrayBitmap[bitmapOffset];
|
|
12171
|
+
const bitmap = buildBitmapFromU64Arrays(bitmapChunks, 1 /* U512 */);
|
|
12172
|
+
if (bitmap.testn(binArrayOffset)) {
|
|
12173
|
+
return i;
|
|
12174
|
+
}
|
|
12175
|
+
}
|
|
12176
|
+
} else {
|
|
12177
|
+
for (let i = startIndex; i >= endIndex; i--) {
|
|
12178
|
+
const binArrayOffset = getBinArrayOffset(new BN10(i)).toNumber();
|
|
12179
|
+
const bitmapOffset = getBitmapOffset(new BN10(i)).toNumber();
|
|
12180
|
+
const bitmapChunks = i > 0 ? binArrayBitmapExtension.positiveBinArrayBitmap[bitmapOffset] : binArrayBitmapExtension.negativeBinArrayBitmap[bitmapOffset];
|
|
12181
|
+
const bitmap = buildBitmapFromU64Arrays(bitmapChunks, 1 /* U512 */);
|
|
12182
|
+
if (bitmap.testn(binArrayOffset)) {
|
|
12183
|
+
return i;
|
|
12184
|
+
}
|
|
12185
|
+
}
|
|
12186
|
+
}
|
|
12187
|
+
return null;
|
|
12188
|
+
}
|
|
12189
|
+
function isOverflowDefaultBinArrayBitmap(binArrayIndex) {
|
|
12190
|
+
const [minBinArrayIndex, maxBinArrayIndex] = internalBitmapRange();
|
|
12191
|
+
return binArrayIndex.gt(maxBinArrayIndex) || binArrayIndex.lt(minBinArrayIndex);
|
|
12192
|
+
}
|
|
12193
|
+
function deriveBinArrayBitmapExtension(lbPair, programId) {
|
|
12194
|
+
return PublicKey5.findProgramAddressSync(
|
|
12195
|
+
[Buffer.from("bitmap"), lbPair.toBytes()],
|
|
12196
|
+
programId
|
|
12197
|
+
);
|
|
12198
|
+
}
|
|
12199
|
+
function binIdToBinArrayIndex(binId) {
|
|
12200
|
+
const { div: idx, mod } = binId.divmod(MAX_BIN_ARRAY_SIZE);
|
|
12201
|
+
return binId.isNeg() && !mod.isZero() ? idx.sub(new BN10(1)) : idx;
|
|
12202
|
+
}
|
|
12203
|
+
function getBinArrayLowerUpperBinId(binArrayIndex) {
|
|
12204
|
+
const lowerBinId = binArrayIndex.mul(MAX_BIN_ARRAY_SIZE);
|
|
12205
|
+
const upperBinId = lowerBinId.add(MAX_BIN_ARRAY_SIZE).sub(new BN10(1));
|
|
12206
|
+
return [lowerBinId, upperBinId];
|
|
12207
|
+
}
|
|
12208
|
+
function isBinIdWithinBinArray(activeId, binArrayIndex) {
|
|
12209
|
+
const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(binArrayIndex);
|
|
12210
|
+
return activeId.gte(lowerBinId) && activeId.lte(upperBinId);
|
|
12211
|
+
}
|
|
12212
|
+
function getBinFromBinArray(binId, binArray) {
|
|
12213
|
+
const [lowerBinId, upperBinId] = getBinArrayLowerUpperBinId(binArray.index);
|
|
12214
|
+
let index = 0;
|
|
12215
|
+
if (binId > 0) {
|
|
12216
|
+
index = binId - lowerBinId.toNumber();
|
|
12217
|
+
} else {
|
|
12218
|
+
const delta = upperBinId.toNumber() - binId;
|
|
12219
|
+
index = MAX_BIN_ARRAY_SIZE.toNumber() - delta - 1;
|
|
12220
|
+
}
|
|
12221
|
+
return binArray.bins[index];
|
|
12222
|
+
}
|
|
12223
|
+
function findNextBinArrayIndexWithLiquidity(swapForY, activeId, lbPairState, binArrayBitmapExtension) {
|
|
12224
|
+
const [lowerBinArrayIndex, upperBinArrayIndex] = internalBitmapRange();
|
|
12225
|
+
let startBinArrayIndex = binIdToBinArrayIndex(activeId);
|
|
12226
|
+
while (true) {
|
|
12227
|
+
if (isOverflowDefaultBinArrayBitmap(startBinArrayIndex)) {
|
|
12228
|
+
if (binArrayBitmapExtension === null) {
|
|
12229
|
+
return null;
|
|
11945
12230
|
}
|
|
11946
12231
|
const [minBinArrayIndex, maxBinArrayIndex] = extensionBitmapRange();
|
|
11947
12232
|
if (startBinArrayIndex.isNeg()) {
|
|
@@ -11952,18 +12237,18 @@ function findNextBinArrayIndexWithLiquidity(swapForY, activeId, lbPairState, bin
|
|
|
11952
12237
|
binArrayBitmapExtension
|
|
11953
12238
|
);
|
|
11954
12239
|
if (binArrayIndex !== null) {
|
|
11955
|
-
return new
|
|
12240
|
+
return new BN10(binArrayIndex);
|
|
11956
12241
|
} else {
|
|
11957
12242
|
return null;
|
|
11958
12243
|
}
|
|
11959
12244
|
} else {
|
|
11960
12245
|
const binArrayIndex = findSetBit(
|
|
11961
12246
|
startBinArrayIndex.toNumber(),
|
|
11962
|
-
BIN_ARRAY_BITMAP_SIZE.neg().sub(new
|
|
12247
|
+
BIN_ARRAY_BITMAP_SIZE.neg().sub(new BN10(1)).toNumber(),
|
|
11963
12248
|
binArrayBitmapExtension
|
|
11964
12249
|
);
|
|
11965
12250
|
if (binArrayIndex !== null) {
|
|
11966
|
-
return new
|
|
12251
|
+
return new BN10(binArrayIndex);
|
|
11967
12252
|
} else {
|
|
11968
12253
|
startBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.neg();
|
|
11969
12254
|
}
|
|
@@ -11976,9 +12261,9 @@ function findNextBinArrayIndexWithLiquidity(swapForY, activeId, lbPairState, bin
|
|
|
11976
12261
|
binArrayBitmapExtension
|
|
11977
12262
|
);
|
|
11978
12263
|
if (binArrayIndex !== null) {
|
|
11979
|
-
return new
|
|
12264
|
+
return new BN10(binArrayIndex);
|
|
11980
12265
|
} else {
|
|
11981
|
-
startBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.sub(new
|
|
12266
|
+
startBinArrayIndex = BIN_ARRAY_BITMAP_SIZE.sub(new BN10(1));
|
|
11982
12267
|
}
|
|
11983
12268
|
} else {
|
|
11984
12269
|
const binArrayIndex = findSetBit(
|
|
@@ -11987,7 +12272,7 @@ function findNextBinArrayIndexWithLiquidity(swapForY, activeId, lbPairState, bin
|
|
|
11987
12272
|
binArrayBitmapExtension
|
|
11988
12273
|
);
|
|
11989
12274
|
if (binArrayIndex !== null) {
|
|
11990
|
-
return new
|
|
12275
|
+
return new BN10(binArrayIndex);
|
|
11991
12276
|
} else {
|
|
11992
12277
|
return null;
|
|
11993
12278
|
}
|
|
@@ -12002,22 +12287,22 @@ function findNextBinArrayIndexWithLiquidity(swapForY, activeId, lbPairState, bin
|
|
|
12002
12287
|
bitmapType
|
|
12003
12288
|
);
|
|
12004
12289
|
if (swapForY) {
|
|
12005
|
-
const upperBitRange = new
|
|
12290
|
+
const upperBitRange = new BN10(bitmapDetail.bits - 1).sub(offset);
|
|
12006
12291
|
const croppedBitmap = bitmap.shln(upperBitRange.toNumber());
|
|
12007
12292
|
const msb = mostSignificantBit(croppedBitmap, bitmapDetail.bits);
|
|
12008
12293
|
if (msb !== null) {
|
|
12009
|
-
return startBinArrayIndex.sub(new
|
|
12294
|
+
return startBinArrayIndex.sub(new BN10(msb));
|
|
12010
12295
|
} else {
|
|
12011
|
-
startBinArrayIndex = lowerBinArrayIndex.sub(new
|
|
12296
|
+
startBinArrayIndex = lowerBinArrayIndex.sub(new BN10(1));
|
|
12012
12297
|
}
|
|
12013
12298
|
} else {
|
|
12014
12299
|
const lowerBitRange = offset;
|
|
12015
12300
|
const croppedBitmap = bitmap.shrn(lowerBitRange.toNumber());
|
|
12016
12301
|
const lsb = leastSignificantBit(croppedBitmap, bitmapDetail.bits);
|
|
12017
12302
|
if (lsb !== null) {
|
|
12018
|
-
return startBinArrayIndex.add(new
|
|
12303
|
+
return startBinArrayIndex.add(new BN10(lsb));
|
|
12019
12304
|
} else {
|
|
12020
|
-
startBinArrayIndex = upperBinArrayIndex.add(new
|
|
12305
|
+
startBinArrayIndex = upperBinArrayIndex.add(new BN10(1));
|
|
12021
12306
|
}
|
|
12022
12307
|
}
|
|
12023
12308
|
}
|
|
@@ -12046,9 +12331,9 @@ function getBinArraysRequiredByPositionRange(pair, fromBinId, toBinId, programId
|
|
|
12046
12331
|
const positionCount = getPositionCount(minBinId, maxBinId);
|
|
12047
12332
|
const binArrays = /* @__PURE__ */ new Map();
|
|
12048
12333
|
for (let i = 0; i < positionCount.toNumber(); i++) {
|
|
12049
|
-
const lowerBinId = minBinId.add(DEFAULT_BIN_PER_POSITION.mul(new
|
|
12334
|
+
const lowerBinId = minBinId.add(DEFAULT_BIN_PER_POSITION.mul(new BN10(i)));
|
|
12050
12335
|
const lowerBinArrayIndex = binIdToBinArrayIndex(lowerBinId);
|
|
12051
|
-
const upperBinArrayIndex = lowerBinArrayIndex.add(new
|
|
12336
|
+
const upperBinArrayIndex = lowerBinArrayIndex.add(new BN10(1));
|
|
12052
12337
|
const [lowerBinArray] = deriveBinArray(pair, lowerBinArrayIndex, programId);
|
|
12053
12338
|
const [upperBinArray] = deriveBinArray(pair, upperBinArrayIndex, programId);
|
|
12054
12339
|
binArrays.set(lowerBinArray.toBase58(), lowerBinArrayIndex);
|
|
@@ -12059,6 +12344,17 @@ function getBinArraysRequiredByPositionRange(pair, fromBinId, toBinId, programId
|
|
|
12059
12344
|
index
|
|
12060
12345
|
}));
|
|
12061
12346
|
}
|
|
12347
|
+
function getBinArraysRequiredByPositionRange2(pair, fromBinId, toBinId, programId) {
|
|
12348
|
+
const [minBinId, maxBinId] = fromBinId.lt(toBinId) ? [fromBinId, toBinId] : [toBinId, fromBinId];
|
|
12349
|
+
const binArrayIndexes = getBinArrayIndexesCoverage(minBinId, maxBinId);
|
|
12350
|
+
return Array.from(binArrayIndexes, (index) => {
|
|
12351
|
+
const [binArrayPubkey] = deriveBinArray(pair, index, programId);
|
|
12352
|
+
return {
|
|
12353
|
+
key: binArrayPubkey,
|
|
12354
|
+
index
|
|
12355
|
+
};
|
|
12356
|
+
});
|
|
12357
|
+
}
|
|
12062
12358
|
function* enumerateBins(binsById, lowerBinId, upperBinId, binStep, baseTokenDecimal, quoteTokenDecimal, version, lbPair) {
|
|
12063
12359
|
for (let currentBinId = lowerBinId; currentBinId <= upperBinId; currentBinId++) {
|
|
12064
12360
|
const bin = binsById.get(currentBinId);
|
|
@@ -12108,7 +12404,7 @@ function decodeRewardPerTokenStored(bin) {
|
|
|
12108
12404
|
"le",
|
|
12109
12405
|
8
|
|
12110
12406
|
);
|
|
12111
|
-
const rewardPerTokenStored0 = new
|
|
12407
|
+
const rewardPerTokenStored0 = new BN10(
|
|
12112
12408
|
Buffer.concat([rewardPerTokenStored0Buf0, rewardPerTokenStored0Buf1]),
|
|
12113
12409
|
"le"
|
|
12114
12410
|
);
|
|
@@ -12122,381 +12418,96 @@ function decodeRewardPerTokenStored(bin) {
|
|
|
12122
12418
|
"le",
|
|
12123
12419
|
8
|
|
12124
12420
|
);
|
|
12125
|
-
const rewardPerTokenStored1 = new
|
|
12421
|
+
const rewardPerTokenStored1 = new BN10(
|
|
12126
12422
|
Buffer.concat([rewardPerTokenStored1Buf0, rewardPerTokenStored1Buf1]),
|
|
12127
12423
|
"le"
|
|
12128
|
-
);
|
|
12129
|
-
return [rewardPerTokenStored0, rewardPerTokenStored1];
|
|
12130
|
-
}
|
|
12131
|
-
function getBinArrayInfoForNonContiguousBinIds(binIds, programId, lbPair) {
|
|
12132
|
-
let binArrayBitmapExtension = programId;
|
|
12133
|
-
const binArrayIndexes = /* @__PURE__ */ new Set();
|
|
12134
|
-
for (const binId of binIds) {
|
|
12135
|
-
const binArrayIndex = binIdToBinArrayIndex(new BN8(binId));
|
|
12136
|
-
if (isOverflowDefaultBinArrayBitmap(binArrayIndex) && binArrayBitmapExtension.equals(programId)) {
|
|
12137
|
-
binArrayBitmapExtension = deriveBinArrayBitmapExtension(
|
|
12138
|
-
lbPair,
|
|
12139
|
-
programId
|
|
12140
|
-
)[0];
|
|
12141
|
-
}
|
|
12142
|
-
binArrayIndexes.add(binArrayIndex.toNumber());
|
|
12143
|
-
}
|
|
12144
|
-
const binArrayPubkeys = [...binArrayIndexes].map(
|
|
12145
|
-
(idx) => deriveBinArray(lbPair, new BN8(idx), programId)[0]
|
|
12146
|
-
);
|
|
12147
|
-
const binArrayAccountMetas = binArrayPubkeys.map((pubkey) => {
|
|
12148
|
-
return {
|
|
12149
|
-
pubkey,
|
|
12150
|
-
isSigner: false,
|
|
12151
|
-
isWritable: true
|
|
12152
|
-
};
|
|
12153
|
-
});
|
|
12154
|
-
return {
|
|
12155
|
-
binArrayAccountMetas,
|
|
12156
|
-
binArrayBitmapExtension,
|
|
12157
|
-
binArrayIndexes: [...binArrayIndexes].map((idx) => new BN8(idx))
|
|
12158
|
-
};
|
|
12159
|
-
}
|
|
12160
|
-
|
|
12161
|
-
// src/dlmm/helpers/computeUnit.ts
|
|
12162
|
-
import {
|
|
12163
|
-
ComputeBudgetProgram,
|
|
12164
|
-
PublicKey as PublicKey6,
|
|
12165
|
-
TransactionMessage,
|
|
12166
|
-
VersionedTransaction
|
|
12167
|
-
} from "@solana/web3.js";
|
|
12168
|
-
var DEFAULT_ADD_LIQUIDITY_CU = 1e6;
|
|
12169
|
-
var DEFAULT_EXTEND_POSITION_HIGH_CU = 1e6;
|
|
12170
|
-
var DEFAULT_EXTEND_POSITION_LOW_CU = 3e4;
|
|
12171
|
-
var DEFAULT_INIT_POSITION_CU = 3e4;
|
|
12172
|
-
var DEFAULT_INIT_BIN_ARRAY_CU = 35e4;
|
|
12173
|
-
var MIN_CU_BUFFER = 5e4;
|
|
12174
|
-
var MAX_CU_BUFFER = 2e5;
|
|
12175
|
-
var MAX_CU = 14e5;
|
|
12176
|
-
var getDefaultExtendPositionCU = (side) => {
|
|
12177
|
-
switch (side) {
|
|
12178
|
-
case 0 /* Lower */:
|
|
12179
|
-
return DEFAULT_EXTEND_POSITION_HIGH_CU;
|
|
12180
|
-
case 1 /* Upper */:
|
|
12181
|
-
return DEFAULT_EXTEND_POSITION_LOW_CU;
|
|
12182
|
-
}
|
|
12183
|
-
};
|
|
12184
|
-
var getSimulationComputeUnits = async (connection, instructions, payer, lookupTables, commitment = "confirmed") => {
|
|
12185
|
-
const testInstructions = [
|
|
12186
|
-
// Set an arbitrarily high number in simulation
|
|
12187
|
-
// so we can be sure the transaction will succeed
|
|
12188
|
-
// and get the real compute units used
|
|
12189
|
-
ComputeBudgetProgram.setComputeUnitLimit({ units: 14e5 }),
|
|
12190
|
-
...instructions
|
|
12191
|
-
];
|
|
12192
|
-
const testTransaction = new VersionedTransaction(
|
|
12193
|
-
new TransactionMessage({
|
|
12194
|
-
instructions: testInstructions,
|
|
12195
|
-
payerKey: payer,
|
|
12196
|
-
// RecentBlockhash can by any public key during simulation
|
|
12197
|
-
// since 'replaceRecentBlockhash' is set to 'true' below
|
|
12198
|
-
recentBlockhash: PublicKey6.default.toString()
|
|
12199
|
-
}).compileToV0Message(lookupTables)
|
|
12200
|
-
);
|
|
12201
|
-
const rpcResponse = await connection.simulateTransaction(testTransaction, {
|
|
12202
|
-
replaceRecentBlockhash: true,
|
|
12203
|
-
sigVerify: false,
|
|
12204
|
-
commitment
|
|
12205
|
-
});
|
|
12206
|
-
if (rpcResponse?.value?.err) {
|
|
12207
|
-
const logs = rpcResponse.value.logs?.join("\n \u2022 ") || "No logs available";
|
|
12208
|
-
throw new Error(
|
|
12209
|
-
`Transaction simulation failed:
|
|
12210
|
-
\u2022${logs}` + JSON.stringify(rpcResponse?.value?.err)
|
|
12211
|
-
);
|
|
12212
|
-
}
|
|
12213
|
-
return rpcResponse.value.unitsConsumed || null;
|
|
12214
|
-
};
|
|
12215
|
-
|
|
12216
|
-
// src/dlmm/helpers/positions/index.ts
|
|
12217
|
-
import BN10 from "bn.js";
|
|
12218
|
-
|
|
12219
|
-
// src/dlmm/helpers/positions/wrapper.ts
|
|
12220
|
-
import BN9 from "bn.js";
|
|
12221
|
-
function combineBaseAndExtendedPositionBinData(base, extended) {
|
|
12222
|
-
const combinedLiquidityShares = base.liquidityShares;
|
|
12223
|
-
const combinedRewardInfos = base.rewardInfos;
|
|
12224
|
-
const combinedFeeInfos = base.feeInfos;
|
|
12225
|
-
for (const binData of extended) {
|
|
12226
|
-
combinedLiquidityShares.push(binData.liquidityShare);
|
|
12227
|
-
combinedRewardInfos.push(binData.rewardInfo);
|
|
12228
|
-
combinedFeeInfos.push(binData.feeInfo);
|
|
12229
|
-
}
|
|
12230
|
-
return {
|
|
12231
|
-
liquidityShares: combinedLiquidityShares,
|
|
12232
|
-
rewardInfos: combinedRewardInfos,
|
|
12233
|
-
feeInfos: combinedFeeInfos
|
|
12234
|
-
};
|
|
12235
|
-
}
|
|
12236
|
-
function wrapPosition(program, key, account) {
|
|
12237
|
-
const disc = account.data.subarray(0, 8);
|
|
12238
|
-
if (disc.equals(Buffer.from(getAccountDiscriminator("positionV2")))) {
|
|
12239
|
-
const state = decodeAccount(
|
|
12240
|
-
program,
|
|
12241
|
-
"positionV2",
|
|
12242
|
-
account.data
|
|
12243
|
-
);
|
|
12244
|
-
const extended = decodeExtendedPosition(
|
|
12245
|
-
state,
|
|
12246
|
-
program,
|
|
12247
|
-
account.data.subarray(8 + POSITION_MIN_SIZE)
|
|
12248
|
-
);
|
|
12249
|
-
const combinedPositionBinData = combineBaseAndExtendedPositionBinData(
|
|
12250
|
-
state,
|
|
12251
|
-
extended
|
|
12252
|
-
);
|
|
12253
|
-
return new PositionV2Wrapper(key, state, extended, combinedPositionBinData);
|
|
12254
|
-
} else {
|
|
12255
|
-
throw new Error("Unknown position account");
|
|
12256
|
-
}
|
|
12257
|
-
}
|
|
12258
|
-
var PositionV2Wrapper = class {
|
|
12259
|
-
constructor(positionAddress, inner, extended, combinedPositionBinData) {
|
|
12260
|
-
this.positionAddress = positionAddress;
|
|
12261
|
-
this.inner = inner;
|
|
12262
|
-
this.extended = extended;
|
|
12263
|
-
this.combinedPositionBinData = combinedPositionBinData;
|
|
12264
|
-
}
|
|
12265
|
-
address() {
|
|
12266
|
-
return this.positionAddress;
|
|
12267
|
-
}
|
|
12268
|
-
totalClaimedRewards() {
|
|
12269
|
-
return this.inner.totalClaimedRewards;
|
|
12270
|
-
}
|
|
12271
|
-
feeOwner() {
|
|
12272
|
-
return this.inner.feeOwner;
|
|
12273
|
-
}
|
|
12274
|
-
lockReleasePoint() {
|
|
12275
|
-
return this.inner.lockReleasePoint;
|
|
12276
|
-
}
|
|
12277
|
-
operator() {
|
|
12278
|
-
return this.inner.operator;
|
|
12279
|
-
}
|
|
12280
|
-
totalClaimedFeeYAmount() {
|
|
12281
|
-
return this.inner.totalClaimedFeeYAmount;
|
|
12282
|
-
}
|
|
12283
|
-
totalClaimedFeeXAmount() {
|
|
12284
|
-
return this.inner.totalClaimedFeeXAmount;
|
|
12285
|
-
}
|
|
12286
|
-
lbPair() {
|
|
12287
|
-
return this.inner.lbPair;
|
|
12288
|
-
}
|
|
12289
|
-
lowerBinId() {
|
|
12290
|
-
return new BN9(this.inner.lowerBinId);
|
|
12291
|
-
}
|
|
12292
|
-
upperBinId() {
|
|
12293
|
-
return new BN9(this.inner.upperBinId);
|
|
12294
|
-
}
|
|
12295
|
-
liquidityShares() {
|
|
12296
|
-
return this.combinedPositionBinData.liquidityShares;
|
|
12297
|
-
}
|
|
12298
|
-
rewardInfos() {
|
|
12299
|
-
return this.combinedPositionBinData.rewardInfos;
|
|
12300
|
-
}
|
|
12301
|
-
feeInfos() {
|
|
12302
|
-
return this.combinedPositionBinData.feeInfos;
|
|
12303
|
-
}
|
|
12304
|
-
lastUpdatedAt() {
|
|
12305
|
-
return this.inner.lastUpdatedAt;
|
|
12306
|
-
}
|
|
12307
|
-
getBinArrayIndexesCoverage() {
|
|
12308
|
-
const isExtended = this.extended.length > 0;
|
|
12309
|
-
if (isExtended) {
|
|
12310
|
-
return getBinArrayIndexesCoverage(this.lowerBinId(), this.upperBinId());
|
|
12311
|
-
} else {
|
|
12312
|
-
const lowerBinArrayIndex = binIdToBinArrayIndex(this.lowerBinId());
|
|
12313
|
-
const upperBinArrayIndex = lowerBinArrayIndex.add(new BN9(1));
|
|
12314
|
-
return [lowerBinArrayIndex, upperBinArrayIndex];
|
|
12315
|
-
}
|
|
12316
|
-
}
|
|
12317
|
-
getBinArrayKeysCoverage(programId) {
|
|
12318
|
-
return this.getBinArrayIndexesCoverage().map(
|
|
12319
|
-
(index) => deriveBinArray(this.lbPair(), index, programId)[0]
|
|
12320
|
-
);
|
|
12321
|
-
}
|
|
12322
|
-
version() {
|
|
12323
|
-
return 1 /* V2 */;
|
|
12324
|
-
}
|
|
12325
|
-
owner() {
|
|
12326
|
-
return this.inner.owner;
|
|
12327
|
-
}
|
|
12328
|
-
width() {
|
|
12329
|
-
return this.upperBinId().sub(this.lowerBinId()).add(new BN9(1));
|
|
12330
|
-
}
|
|
12331
|
-
};
|
|
12332
|
-
|
|
12333
|
-
// src/dlmm/helpers/positions/index.ts
|
|
12334
|
-
function getBinArrayIndexesCoverage(lowerBinId, upperBinId) {
|
|
12335
|
-
const lowerBinArrayIndex = binIdToBinArrayIndex(lowerBinId);
|
|
12336
|
-
const upperBinArrayIndex = binIdToBinArrayIndex(upperBinId);
|
|
12337
|
-
const binArrayIndexes = [];
|
|
12338
|
-
for (let i = lowerBinArrayIndex.toNumber(); i <= upperBinArrayIndex.toNumber(); i++) {
|
|
12339
|
-
binArrayIndexes.push(new BN10(i));
|
|
12340
|
-
}
|
|
12341
|
-
return binArrayIndexes;
|
|
12342
|
-
}
|
|
12343
|
-
function getBinArrayKeysCoverage(lowerBinId, upperBinId, lbPair, programId) {
|
|
12344
|
-
const binArrayIndexes = getBinArrayIndexesCoverage(lowerBinId, upperBinId);
|
|
12345
|
-
return binArrayIndexes.map((index) => {
|
|
12346
|
-
return deriveBinArray(lbPair, index, programId)[0];
|
|
12347
|
-
});
|
|
12348
|
-
}
|
|
12349
|
-
function getBinArrayAccountMetasCoverage(lowerBinId, upperBinId, lbPair, programId) {
|
|
12350
|
-
return getBinArrayKeysCoverage(lowerBinId, upperBinId, lbPair, programId).map(
|
|
12351
|
-
(key) => {
|
|
12352
|
-
return {
|
|
12353
|
-
pubkey: key,
|
|
12354
|
-
isSigner: false,
|
|
12355
|
-
isWritable: true
|
|
12356
|
-
};
|
|
12357
|
-
}
|
|
12358
|
-
);
|
|
12359
|
-
}
|
|
12360
|
-
function getPositionLowerUpperBinIdWithLiquidity(position) {
|
|
12361
|
-
const binWithLiquidity = position.positionBinData.filter(
|
|
12362
|
-
(b) => !new BN10(b.binLiquidity).isZero() || !new BN10(b.positionFeeXAmount.toString()).isZero() || !new BN10(b.positionFeeYAmount.toString()).isZero() || !new BN10(b.positionRewardAmount[0].toString()).isZero() || !new BN10(b.positionRewardAmount[1].toString()).isZero()
|
|
12363
|
-
);
|
|
12364
|
-
return binWithLiquidity.length > 0 ? {
|
|
12365
|
-
lowerBinId: new BN10(binWithLiquidity[0].binId),
|
|
12366
|
-
upperBinId: new BN10(binWithLiquidity[binWithLiquidity.length - 1].binId)
|
|
12367
|
-
} : null;
|
|
12368
|
-
}
|
|
12369
|
-
function isPositionNoFee(position) {
|
|
12370
|
-
return position.feeX.isZero() && position.feeY.isZero();
|
|
12371
|
-
}
|
|
12372
|
-
function isPositionNoReward(position) {
|
|
12373
|
-
return position.rewardOne.isZero() && position.rewardTwo.isZero();
|
|
12374
|
-
}
|
|
12375
|
-
function chunkBinRangeIntoExtendedPositions(minBinId, maxBinId) {
|
|
12376
|
-
const chunkedBinRange = [];
|
|
12377
|
-
for (let currentMinBinId = minBinId; currentMinBinId <= maxBinId; currentMinBinId += POSITION_MAX_LENGTH.toNumber()) {
|
|
12378
|
-
const currentMaxBinId = Math.min(
|
|
12379
|
-
currentMinBinId + POSITION_MAX_LENGTH.toNumber() - 1,
|
|
12380
|
-
maxBinId
|
|
12381
|
-
);
|
|
12382
|
-
chunkedBinRange.push({
|
|
12383
|
-
lowerBinId: currentMinBinId,
|
|
12384
|
-
upperBinId: currentMaxBinId
|
|
12385
|
-
});
|
|
12386
|
-
}
|
|
12387
|
-
return chunkedBinRange;
|
|
12388
|
-
}
|
|
12389
|
-
function chunkBinRange(minBinId, maxBinId, binPerChunk) {
|
|
12390
|
-
const chunkedBinRange = [];
|
|
12391
|
-
let startBinId = minBinId;
|
|
12392
|
-
binPerChunk = binPerChunk ?? DEFAULT_BIN_PER_POSITION.toNumber();
|
|
12393
|
-
while (startBinId <= maxBinId) {
|
|
12394
|
-
const endBinId = Math.min(startBinId + binPerChunk - 1, maxBinId);
|
|
12395
|
-
chunkedBinRange.push({
|
|
12396
|
-
lowerBinId: startBinId,
|
|
12397
|
-
upperBinId: endBinId
|
|
12398
|
-
});
|
|
12399
|
-
startBinId += binPerChunk;
|
|
12400
|
-
}
|
|
12401
|
-
return chunkedBinRange;
|
|
12424
|
+
);
|
|
12425
|
+
return [rewardPerTokenStored0, rewardPerTokenStored1];
|
|
12402
12426
|
}
|
|
12403
|
-
function
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
if (positionBinData.binId >= minBinId && positionBinData.binId <= maxBinId) {
|
|
12414
|
-
totalFeeXAmount = totalFeeXAmount.add(
|
|
12415
|
-
new BN10(positionBinData.positionFeeXAmount)
|
|
12416
|
-
);
|
|
12417
|
-
totalFeeYAmount = totalFeeYAmount.add(
|
|
12418
|
-
new BN10(positionBinData.positionFeeYAmount)
|
|
12419
|
-
);
|
|
12420
|
-
totalAmountX = totalAmountX.add(new BN10(positionBinData.positionXAmount));
|
|
12421
|
-
totalAmountY = totalAmountY.add(new BN10(positionBinData.positionYAmount));
|
|
12422
|
-
for (const [
|
|
12423
|
-
index,
|
|
12424
|
-
reward
|
|
12425
|
-
] of positionBinData.positionRewardAmount.entries()) {
|
|
12426
|
-
totalRewardAmounts[index] = totalRewardAmounts[index].add(
|
|
12427
|
-
new BN10(reward)
|
|
12428
|
-
);
|
|
12429
|
-
}
|
|
12430
|
-
count++;
|
|
12431
|
-
}
|
|
12432
|
-
if (count === DEFAULT_BIN_PER_POSITION.toNumber() || positionBinData.binId == maxBinId) {
|
|
12433
|
-
chunkedFeesAndRewards.push({
|
|
12434
|
-
minBinId: positionBinData.binId - count + 1,
|
|
12435
|
-
maxBinId: positionBinData.binId,
|
|
12436
|
-
feeXAmount: totalFeeXAmount,
|
|
12437
|
-
feeYAmount: totalFeeYAmount,
|
|
12438
|
-
rewardAmounts: totalRewardAmounts,
|
|
12439
|
-
amountX: totalAmountX,
|
|
12440
|
-
amountY: totalAmountY
|
|
12441
|
-
});
|
|
12442
|
-
totalFeeXAmount = new BN10(0);
|
|
12443
|
-
totalFeeYAmount = new BN10(0);
|
|
12444
|
-
totalAmountX = new BN10(0);
|
|
12445
|
-
totalAmountY = new BN10(0);
|
|
12446
|
-
totalRewardAmounts = [new BN10(0), new BN10(0)];
|
|
12447
|
-
count = 0;
|
|
12427
|
+
function getBinArrayInfoForNonContiguousBinIds(binIds, programId, lbPair) {
|
|
12428
|
+
let binArrayBitmapExtension = programId;
|
|
12429
|
+
const binArrayIndexes = /* @__PURE__ */ new Set();
|
|
12430
|
+
for (const binId of binIds) {
|
|
12431
|
+
const binArrayIndex = binIdToBinArrayIndex(new BN10(binId));
|
|
12432
|
+
if (isOverflowDefaultBinArrayBitmap(binArrayIndex) && binArrayBitmapExtension.equals(programId)) {
|
|
12433
|
+
binArrayBitmapExtension = deriveBinArrayBitmapExtension(
|
|
12434
|
+
lbPair,
|
|
12435
|
+
programId
|
|
12436
|
+
)[0];
|
|
12448
12437
|
}
|
|
12438
|
+
binArrayIndexes.add(binArrayIndex.toNumber());
|
|
12449
12439
|
}
|
|
12450
|
-
|
|
12451
|
-
|
|
12452
|
-
function calculatePositionSize(binCount) {
|
|
12453
|
-
const extraBinCount = binCount.gt(DEFAULT_BIN_PER_POSITION) ? binCount.sub(DEFAULT_BIN_PER_POSITION) : new BN10(0);
|
|
12454
|
-
return new BN10(POSITION_MIN_SIZE).add(
|
|
12455
|
-
extraBinCount.mul(new BN10(POSITION_BIN_DATA_SIZE))
|
|
12440
|
+
const binArrayPubkeys = [...binArrayIndexes].map(
|
|
12441
|
+
(idx) => deriveBinArray(lbPair, new BN10(idx), programId)[0]
|
|
12456
12442
|
);
|
|
12443
|
+
const binArrayAccountMetas = binArrayPubkeys.map((pubkey) => {
|
|
12444
|
+
return {
|
|
12445
|
+
pubkey,
|
|
12446
|
+
isSigner: false,
|
|
12447
|
+
isWritable: true
|
|
12448
|
+
};
|
|
12449
|
+
});
|
|
12450
|
+
return {
|
|
12451
|
+
binArrayAccountMetas,
|
|
12452
|
+
binArrayBitmapExtension,
|
|
12453
|
+
binArrayIndexes: [...binArrayIndexes].map((idx) => new BN10(idx))
|
|
12454
|
+
};
|
|
12457
12455
|
}
|
|
12458
|
-
|
|
12459
|
-
|
|
12460
|
-
|
|
12461
|
-
|
|
12462
|
-
|
|
12463
|
-
|
|
12464
|
-
|
|
12465
|
-
|
|
12466
|
-
|
|
12467
|
-
|
|
12468
|
-
|
|
12469
|
-
|
|
12470
|
-
|
|
12471
|
-
|
|
12472
|
-
|
|
12473
|
-
|
|
12474
|
-
|
|
12475
|
-
|
|
12476
|
-
|
|
12456
|
+
|
|
12457
|
+
// src/dlmm/helpers/computeUnit.ts
|
|
12458
|
+
import {
|
|
12459
|
+
ComputeBudgetProgram,
|
|
12460
|
+
PublicKey as PublicKey6,
|
|
12461
|
+
TransactionMessage,
|
|
12462
|
+
VersionedTransaction
|
|
12463
|
+
} from "@solana/web3.js";
|
|
12464
|
+
var DEFAULT_ADD_LIQUIDITY_CU = 1e6;
|
|
12465
|
+
var DEFAULT_EXTEND_POSITION_HIGH_CU = 1e6;
|
|
12466
|
+
var DEFAULT_EXTEND_POSITION_LOW_CU = 3e4;
|
|
12467
|
+
var DEFAULT_INIT_POSITION_CU = 3e4;
|
|
12468
|
+
var DEFAULT_INIT_BIN_ARRAY_CU = 35e4;
|
|
12469
|
+
var MIN_CU_BUFFER = 5e4;
|
|
12470
|
+
var MAX_CU_BUFFER = 2e5;
|
|
12471
|
+
var MAX_CU = 14e5;
|
|
12472
|
+
var getDefaultExtendPositionCU = (side) => {
|
|
12473
|
+
switch (side) {
|
|
12474
|
+
case 0 /* Lower */:
|
|
12475
|
+
return DEFAULT_EXTEND_POSITION_HIGH_CU;
|
|
12476
|
+
case 1 /* Upper */:
|
|
12477
|
+
return DEFAULT_EXTEND_POSITION_LOW_CU;
|
|
12477
12478
|
}
|
|
12478
|
-
}
|
|
12479
|
-
|
|
12480
|
-
const
|
|
12481
|
-
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
const
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
//
|
|
12493
|
-
|
|
12494
|
-
|
|
12479
|
+
};
|
|
12480
|
+
var getSimulationComputeUnits = async (connection, instructions, payer, lookupTables, commitment = "confirmed") => {
|
|
12481
|
+
const testInstructions = [
|
|
12482
|
+
// Set an arbitrarily high number in simulation
|
|
12483
|
+
// so we can be sure the transaction will succeed
|
|
12484
|
+
// and get the real compute units used
|
|
12485
|
+
ComputeBudgetProgram.setComputeUnitLimit({ units: 14e5 }),
|
|
12486
|
+
...instructions
|
|
12487
|
+
];
|
|
12488
|
+
const testTransaction = new VersionedTransaction(
|
|
12489
|
+
new TransactionMessage({
|
|
12490
|
+
instructions: testInstructions,
|
|
12491
|
+
payerKey: payer,
|
|
12492
|
+
// RecentBlockhash can by any public key during simulation
|
|
12493
|
+
// since 'replaceRecentBlockhash' is set to 'true' below
|
|
12494
|
+
recentBlockhash: PublicKey6.default.toString()
|
|
12495
|
+
}).compileToV0Message(lookupTables)
|
|
12496
|
+
);
|
|
12497
|
+
const rpcResponse = await connection.simulateTransaction(testTransaction, {
|
|
12498
|
+
replaceRecentBlockhash: true,
|
|
12499
|
+
sigVerify: false,
|
|
12500
|
+
commitment
|
|
12501
|
+
});
|
|
12502
|
+
if (rpcResponse?.value?.err) {
|
|
12503
|
+
const logs = rpcResponse.value.logs?.join("\n \u2022 ") || "No logs available";
|
|
12504
|
+
throw new Error(
|
|
12505
|
+
`Transaction simulation failed:
|
|
12506
|
+
\u2022${logs}` + JSON.stringify(rpcResponse?.value?.err)
|
|
12495
12507
|
);
|
|
12496
|
-
extendedPosition.push(decodedPositionBinData);
|
|
12497
12508
|
}
|
|
12498
|
-
return
|
|
12499
|
-
}
|
|
12509
|
+
return rpcResponse.value.unitsConsumed || null;
|
|
12510
|
+
};
|
|
12500
12511
|
|
|
12501
12512
|
// src/dlmm/helpers/rebalance/rebalancePosition.ts
|
|
12502
12513
|
import { SYSVAR_CLOCK_PUBKEY } from "@solana/web3.js";
|
|
@@ -16748,6 +16759,242 @@ var DLMM = class {
|
|
|
16748
16759
|
}
|
|
16749
16760
|
return positionsMap;
|
|
16750
16761
|
}
|
|
16762
|
+
/**
|
|
16763
|
+
* The function `getPositionsByUserAndTokenAddress` retrieves all of a user's positions across every
|
|
16764
|
+
* DLMM pool that includes the given token mint as either the X or Y token.
|
|
16765
|
+
* @param {Connection} connection - The `connection` parameter is an instance of the `Connection`
|
|
16766
|
+
* class, which represents the connection to the Solana blockchain.
|
|
16767
|
+
* @param {PublicKey} userPubKey - The user's wallet public key.
|
|
16768
|
+
* @param {PublicKey} tokenMint - The token mint used to filter pools. Only positions in pools whose
|
|
16769
|
+
* `tokenXMint` or `tokenYMint` matches this mint are returned.
|
|
16770
|
+
* @param {Opt} [opt] - An optional object that contains additional options for the function.
|
|
16771
|
+
* @param {GetPositionsOpt} [getPositionsOpt] - Optional settings for chunked position fetching
|
|
16772
|
+
* @returns The function `getPositionsByUserAndTokenAddress` returns a `Promise` that resolves to a
|
|
16773
|
+
* `Map` object. The `Map` object contains key-value pairs, where the key is a string representing the
|
|
16774
|
+
* LB Pair account, and the value is an object of PositionInfo. Only pools containing `tokenMint` are
|
|
16775
|
+
* included.
|
|
16776
|
+
*/
|
|
16777
|
+
static async getPositionsByUserAndTokenAddress(connection, userPubKey, tokenMint, opt, getPositionsOpt) {
|
|
16778
|
+
const allPositions = await DLMM.getAllLbPairPositionsByUser(
|
|
16779
|
+
connection,
|
|
16780
|
+
userPubKey,
|
|
16781
|
+
opt,
|
|
16782
|
+
getPositionsOpt
|
|
16783
|
+
);
|
|
16784
|
+
const targetMint = tokenMint.toBase58();
|
|
16785
|
+
const filteredPositions = /* @__PURE__ */ new Map();
|
|
16786
|
+
for (const [lbPairKey, positionInfo] of allPositions) {
|
|
16787
|
+
const tokenXMint = positionInfo.lbPair.tokenXMint.toBase58();
|
|
16788
|
+
const tokenYMint = positionInfo.lbPair.tokenYMint.toBase58();
|
|
16789
|
+
if (tokenXMint === targetMint || tokenYMint === targetMint) {
|
|
16790
|
+
filteredPositions.set(lbPairKey, positionInfo);
|
|
16791
|
+
}
|
|
16792
|
+
}
|
|
16793
|
+
return filteredPositions;
|
|
16794
|
+
}
|
|
16795
|
+
/**
|
|
16796
|
+
* The function `getLimitOrdersByUserAndTokenAddress` retrieves all of a user's limit orders across
|
|
16797
|
+
* every DLMM pool that includes the given token mint as either the X or Y token.
|
|
16798
|
+
* @param {Connection} connection - The `connection` parameter is an instance of the `Connection`
|
|
16799
|
+
* class, which represents the connection to the Solana blockchain.
|
|
16800
|
+
* @param {PublicKey} userPubKey - The user's wallet public key.
|
|
16801
|
+
* @param {PublicKey} tokenMint - The token mint used to filter pools. Only limit orders in pools
|
|
16802
|
+
* whose `tokenXMint` or `tokenYMint` matches this mint are returned.
|
|
16803
|
+
* @param {Opt} [opt] - An optional object that contains additional options for the function.
|
|
16804
|
+
* @returns The function `getLimitOrdersByUserAndTokenAddress` returns a `Promise` that resolves to a
|
|
16805
|
+
* `Map` object keyed by LB Pair account (base58), where each value is a `LimitOrderInfo` containing
|
|
16806
|
+
* the LB pair state, token reserves, and the parsed limit orders for that pool.
|
|
16807
|
+
*/
|
|
16808
|
+
static async getLimitOrdersByUserAndTokenAddress(connection, userPubKey, tokenMint, opt) {
|
|
16809
|
+
const program = createProgram(connection, opt);
|
|
16810
|
+
const limitOrderAccounts = await chunkedGetProgramAccounts(
|
|
16811
|
+
program.provider.connection,
|
|
16812
|
+
program.programId,
|
|
16813
|
+
[limitOrderFilter(), limitOrderOwnerFilter(userPubKey)]
|
|
16814
|
+
);
|
|
16815
|
+
const limitOrderWrappers = limitOrderAccounts.map(
|
|
16816
|
+
({ pubkey, account }) => wrapLimitOrder(program, pubkey, account)
|
|
16817
|
+
);
|
|
16818
|
+
if (limitOrderWrappers.length === 0) {
|
|
16819
|
+
return /* @__PURE__ */ new Map();
|
|
16820
|
+
}
|
|
16821
|
+
const lbPairKeys = Array.from(
|
|
16822
|
+
new Set(limitOrderWrappers.map((lo) => lo.lbPair().toBase58()))
|
|
16823
|
+
).map((key) => new PublicKey10(key));
|
|
16824
|
+
const lbPairAccInfos = await chunkedGetMultipleAccountInfos(
|
|
16825
|
+
connection,
|
|
16826
|
+
lbPairKeys
|
|
16827
|
+
);
|
|
16828
|
+
const lbPairMap = /* @__PURE__ */ new Map();
|
|
16829
|
+
lbPairKeys.forEach((lbPairPubkey, i) => {
|
|
16830
|
+
const accInfo = lbPairAccInfos[i];
|
|
16831
|
+
if (!accInfo) {
|
|
16832
|
+
throw new Error(`LB Pair account ${lbPairPubkey.toBase58()} not found`);
|
|
16833
|
+
}
|
|
16834
|
+
lbPairMap.set(
|
|
16835
|
+
lbPairPubkey.toBase58(),
|
|
16836
|
+
decodeAccount(program, "lbPair", accInfo.data)
|
|
16837
|
+
);
|
|
16838
|
+
});
|
|
16839
|
+
const targetMint = tokenMint.toBase58();
|
|
16840
|
+
const matchingLbPairKeys = lbPairKeys.filter((lbPairPubkey) => {
|
|
16841
|
+
const lbPairState = lbPairMap.get(lbPairPubkey.toBase58());
|
|
16842
|
+
return lbPairState.tokenXMint.toBase58() === targetMint || lbPairState.tokenYMint.toBase58() === targetMint;
|
|
16843
|
+
});
|
|
16844
|
+
if (matchingLbPairKeys.length === 0) {
|
|
16845
|
+
return /* @__PURE__ */ new Map();
|
|
16846
|
+
}
|
|
16847
|
+
const matchingLbPairSet = new Set(
|
|
16848
|
+
matchingLbPairKeys.map((key) => key.toBase58())
|
|
16849
|
+
);
|
|
16850
|
+
const matchingLimitOrders = limitOrderWrappers.filter(
|
|
16851
|
+
(lo) => matchingLbPairSet.has(lo.lbPair().toBase58())
|
|
16852
|
+
);
|
|
16853
|
+
const reserveAndMintKeys = matchingLbPairKeys.map((lbPairPubkey) => {
|
|
16854
|
+
const { reserveX, reserveY, tokenXMint, tokenYMint } = lbPairMap.get(
|
|
16855
|
+
lbPairPubkey.toBase58()
|
|
16856
|
+
);
|
|
16857
|
+
return [reserveX, reserveY, tokenXMint, tokenYMint];
|
|
16858
|
+
}).flat();
|
|
16859
|
+
const binArrayPubkeySet = /* @__PURE__ */ new Set();
|
|
16860
|
+
matchingLimitOrders.forEach((lo) => {
|
|
16861
|
+
lo.getBinArrayKeysCoverage(program.programId).forEach((key) => {
|
|
16862
|
+
binArrayPubkeySet.add(key.toBase58());
|
|
16863
|
+
});
|
|
16864
|
+
});
|
|
16865
|
+
const binArrayKeys = Array.from(binArrayPubkeySet).map(
|
|
16866
|
+
(key) => new PublicKey10(key)
|
|
16867
|
+
);
|
|
16868
|
+
const [clockAccInfo, ...rest] = await chunkedGetMultipleAccountInfos(
|
|
16869
|
+
connection,
|
|
16870
|
+
[SYSVAR_CLOCK_PUBKEY2, ...binArrayKeys, ...reserveAndMintKeys]
|
|
16871
|
+
);
|
|
16872
|
+
const binArraysAccInfo = rest.slice(0, binArrayKeys.length);
|
|
16873
|
+
const reserveAndMintAccInfo = rest.slice(binArrayKeys.length);
|
|
16874
|
+
const clock = ClockLayout.decode(clockAccInfo.data);
|
|
16875
|
+
const binArrayMap = /* @__PURE__ */ new Map();
|
|
16876
|
+
binArrayKeys.forEach((binArrayPubkey, i) => {
|
|
16877
|
+
const accInfo = binArraysAccInfo[i];
|
|
16878
|
+
if (accInfo) {
|
|
16879
|
+
binArrayMap.set(
|
|
16880
|
+
binArrayPubkey.toBase58(),
|
|
16881
|
+
decodeAccount(program, "binArray", accInfo.data)
|
|
16882
|
+
);
|
|
16883
|
+
}
|
|
16884
|
+
});
|
|
16885
|
+
const seenMints = /* @__PURE__ */ new Set();
|
|
16886
|
+
const mintsWithAccount = matchingLbPairKeys.flatMap((lbPairPubkey, idx) => {
|
|
16887
|
+
const { tokenXMint, tokenYMint } = lbPairMap.get(
|
|
16888
|
+
lbPairPubkey.toBase58()
|
|
16889
|
+
);
|
|
16890
|
+
const index = idx * 4;
|
|
16891
|
+
return [
|
|
16892
|
+
{
|
|
16893
|
+
mintAddress: tokenXMint,
|
|
16894
|
+
mintAccountInfo: reserveAndMintAccInfo[index + 2]
|
|
16895
|
+
},
|
|
16896
|
+
{
|
|
16897
|
+
mintAddress: tokenYMint,
|
|
16898
|
+
mintAccountInfo: reserveAndMintAccInfo[index + 3]
|
|
16899
|
+
}
|
|
16900
|
+
];
|
|
16901
|
+
}).filter(({ mintAddress, mintAccountInfo }) => {
|
|
16902
|
+
if (!mintAccountInfo || seenMints.has(mintAddress.toBase58())) {
|
|
16903
|
+
return false;
|
|
16904
|
+
}
|
|
16905
|
+
seenMints.add(mintAddress.toBase58());
|
|
16906
|
+
return true;
|
|
16907
|
+
});
|
|
16908
|
+
const mintHookAccountsMap = await getMultipleMintsExtraAccountMetasForTransferHook(
|
|
16909
|
+
connection,
|
|
16910
|
+
mintsWithAccount
|
|
16911
|
+
);
|
|
16912
|
+
const lbPairTokenMap = /* @__PURE__ */ new Map();
|
|
16913
|
+
matchingLbPairKeys.forEach((lbPairPubkey, idx) => {
|
|
16914
|
+
const index = idx * 4;
|
|
16915
|
+
const reserveXAccount = reserveAndMintAccInfo[index];
|
|
16916
|
+
const reserveYAccount = reserveAndMintAccInfo[index + 1];
|
|
16917
|
+
const mintXAccount = reserveAndMintAccInfo[index + 2];
|
|
16918
|
+
const mintYAccount = reserveAndMintAccInfo[index + 3];
|
|
16919
|
+
if (!reserveXAccount || !reserveYAccount) {
|
|
16920
|
+
throw new Error(
|
|
16921
|
+
`Reserve account for LB Pair ${lbPairPubkey.toBase58()} not found`
|
|
16922
|
+
);
|
|
16923
|
+
}
|
|
16924
|
+
if (!mintXAccount || !mintYAccount) {
|
|
16925
|
+
throw new Error(
|
|
16926
|
+
`Mint account for LB Pair ${lbPairPubkey.toBase58()} not found`
|
|
16927
|
+
);
|
|
16928
|
+
}
|
|
16929
|
+
const lbPairState = lbPairMap.get(lbPairPubkey.toBase58());
|
|
16930
|
+
const reserveAccX = AccountLayout.decode(reserveXAccount.data);
|
|
16931
|
+
const reserveAccY = AccountLayout.decode(reserveYAccount.data);
|
|
16932
|
+
const mintX = unpackMint2(
|
|
16933
|
+
reserveAccX.mint,
|
|
16934
|
+
mintXAccount,
|
|
16935
|
+
mintXAccount.owner
|
|
16936
|
+
);
|
|
16937
|
+
const mintY = unpackMint2(
|
|
16938
|
+
reserveAccY.mint,
|
|
16939
|
+
mintYAccount,
|
|
16940
|
+
mintYAccount.owner
|
|
16941
|
+
);
|
|
16942
|
+
const { tokenXProgram, tokenYProgram } = getTokenProgramId(lbPairState);
|
|
16943
|
+
const tokenX = {
|
|
16944
|
+
publicKey: lbPairState.tokenXMint,
|
|
16945
|
+
reserve: lbPairState.reserveX,
|
|
16946
|
+
amount: reserveAccX.amount,
|
|
16947
|
+
mint: mintX,
|
|
16948
|
+
owner: tokenXProgram,
|
|
16949
|
+
transferHookAccountMetas: mintHookAccountsMap.get(lbPairState.tokenXMint.toBase58()) ?? []
|
|
16950
|
+
};
|
|
16951
|
+
const tokenY = {
|
|
16952
|
+
publicKey: lbPairState.tokenYMint,
|
|
16953
|
+
reserve: lbPairState.reserveY,
|
|
16954
|
+
amount: reserveAccY.amount,
|
|
16955
|
+
mint: mintY,
|
|
16956
|
+
owner: tokenYProgram,
|
|
16957
|
+
transferHookAccountMetas: mintHookAccountsMap.get(lbPairState.tokenYMint.toBase58()) ?? []
|
|
16958
|
+
};
|
|
16959
|
+
lbPairTokenMap.set(lbPairPubkey.toBase58(), {
|
|
16960
|
+
tokenX,
|
|
16961
|
+
tokenY,
|
|
16962
|
+
mintX,
|
|
16963
|
+
mintY
|
|
16964
|
+
});
|
|
16965
|
+
});
|
|
16966
|
+
const limitOrdersMap = /* @__PURE__ */ new Map();
|
|
16967
|
+
for (const lo of matchingLimitOrders) {
|
|
16968
|
+
const lbPairKey = lo.lbPair().toBase58();
|
|
16969
|
+
const lbPairState = lbPairMap.get(lbPairKey);
|
|
16970
|
+
const { tokenX, tokenY, mintX, mintY } = lbPairTokenMap.get(lbPairKey);
|
|
16971
|
+
const parsedLo = lo.parseInfo(
|
|
16972
|
+
program.programId,
|
|
16973
|
+
lbPairState,
|
|
16974
|
+
mintX,
|
|
16975
|
+
mintY,
|
|
16976
|
+
clock,
|
|
16977
|
+
binArrayMap
|
|
16978
|
+
);
|
|
16979
|
+
const entry = {
|
|
16980
|
+
publicKey: lo.address(),
|
|
16981
|
+
limitOrderData: parsedLo
|
|
16982
|
+
};
|
|
16983
|
+
const existing = limitOrdersMap.get(lbPairKey);
|
|
16984
|
+
if (existing) {
|
|
16985
|
+
existing.limitOrders.push(entry);
|
|
16986
|
+
} else {
|
|
16987
|
+
limitOrdersMap.set(lbPairKey, {
|
|
16988
|
+
publicKey: lo.lbPair(),
|
|
16989
|
+
lbPair: lbPairState,
|
|
16990
|
+
tokenX,
|
|
16991
|
+
tokenY,
|
|
16992
|
+
limitOrders: [entry]
|
|
16993
|
+
});
|
|
16994
|
+
}
|
|
16995
|
+
}
|
|
16996
|
+
return limitOrdersMap;
|
|
16997
|
+
}
|
|
16751
16998
|
static getPricePerLamport(tokenXDecimal, tokenYDecimal, price) {
|
|
16752
16999
|
return new Decimal11(price).mul(new Decimal11(10 ** (tokenYDecimal - tokenXDecimal))).toString();
|
|
16753
17000
|
}
|
|
@@ -23018,6 +23265,7 @@ export {
|
|
|
23018
23265
|
getBinArrayKeysCoverage,
|
|
23019
23266
|
getBinArrayLowerUpperBinId,
|
|
23020
23267
|
getBinArraysRequiredByPositionRange,
|
|
23268
|
+
getBinArraysRequiredByPositionRange2,
|
|
23021
23269
|
getBinCount,
|
|
23022
23270
|
getBinFromBinArray,
|
|
23023
23271
|
getBinIdIndexInBinArray,
|