@hawksightco/hawk-sdk 1.3.237 → 1.3.239
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/src/classes/Transactions.d.ts +1 -63
- package/dist/src/classes/Transactions.d.ts.map +1 -1
- package/dist/src/classes/Transactions.js +9 -935
- package/dist/src/classes/TxGeneratorAutomations.d.ts +1 -60
- package/dist/src/classes/TxGeneratorAutomations.d.ts.map +1 -1
- package/dist/src/classes/TxGeneratorAutomations.js +0 -257
- package/dist/src/types.d.ts +0 -39
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1752,70 +1752,6 @@ class Transactions {
|
|
|
1752
1752
|
}
|
|
1753
1753
|
});
|
|
1754
1754
|
}
|
|
1755
|
-
/**
|
|
1756
|
-
*
|
|
1757
|
-
* @param connection The Solana web3 connection object for blockchain interactions.
|
|
1758
|
-
* @param params Parameters required for rebalance
|
|
1759
|
-
* @returns A ResponseWithStatus containing TransactionMetadataResponse.
|
|
1760
|
-
*/
|
|
1761
|
-
rebalanceAutomationIx(_a) {
|
|
1762
|
-
return __awaiter(this, arguments, void 0, function* ({ connection, params, }) {
|
|
1763
|
-
const program = yield meteora_1.MeteoraDLMM.program(connection);
|
|
1764
|
-
const position = yield program.account.positionV2.fetch(params.currentPosition);
|
|
1765
|
-
const dlmmPool = yield meteora_1.MeteoraDLMM.create(connection, position.lbPair, this.ix);
|
|
1766
|
-
const userPda = (0, functions_1.generateUserPda)(params.userWallet);
|
|
1767
|
-
// Step 1: Claim all fees/rewards, remove all liquidity and close current position
|
|
1768
|
-
const { userPositions } = yield dlmmPool.getPositionsByUserAndLbPair(userPda);
|
|
1769
|
-
const userPosition = userPositions.find(userPosition => userPosition.publicKey.equals(params.currentPosition));
|
|
1770
|
-
if (userPosition === undefined) {
|
|
1771
|
-
throw new Error(`Position: ${params.currentPosition} does not exist.`);
|
|
1772
|
-
}
|
|
1773
|
-
const binIdsToRemove = userPosition.positionData.positionBinData.map(bin => bin.binId);
|
|
1774
|
-
const removeLiquidityBuilder = yield dlmmPool.removeLiquidity(connection, params.userWallet, addresses_1.HS_AUTHORITY, {
|
|
1775
|
-
user: userPda,
|
|
1776
|
-
position: params.currentPosition,
|
|
1777
|
-
fromBinId: position.lowerBinId,
|
|
1778
|
-
toBinId: position.upperBinId,
|
|
1779
|
-
bps: new bn_js_1.default(10000),
|
|
1780
|
-
shouldClaimAndClose: true,
|
|
1781
|
-
}, hsToMeteora_1.meteoraToHawksightAutomationIxs);
|
|
1782
|
-
if (params.useAta) {
|
|
1783
|
-
removeLiquidityBuilder.replaceClaimFeeTokenToATA();
|
|
1784
|
-
removeLiquidityBuilder.replaceClaimRewardToATA();
|
|
1785
|
-
}
|
|
1786
|
-
else {
|
|
1787
|
-
removeLiquidityBuilder.replaceClaimFeeTokenToSTA();
|
|
1788
|
-
removeLiquidityBuilder.replaceClaimRewardToSTA();
|
|
1789
|
-
}
|
|
1790
|
-
// Re-deposit fees (TODO: How to re-deposit reward tokens that is not X or Y token?)
|
|
1791
|
-
const initPositionAndAddLiquidityBuilder = yield dlmmPool.initializePositionAndAddLiquidityByStrategy(connection, params.userWallet, addresses_1.HS_AUTHORITY, {
|
|
1792
|
-
positionPubKey: params.newPosition,
|
|
1793
|
-
user: userPda,
|
|
1794
|
-
totalXAmount: new bn_js_1.default(100000), // This is overriden on-chain, so value here do not matter
|
|
1795
|
-
totalYAmount: new bn_js_1.default(100000), // This is overriden on-chain, so value here do not matter
|
|
1796
|
-
strategy: {
|
|
1797
|
-
maxBinId: params.binRange.upperRange,
|
|
1798
|
-
minBinId: params.binRange.lowerRange,
|
|
1799
|
-
strategyType: types_3.StrategyTypeMap[params.distribution],
|
|
1800
|
-
},
|
|
1801
|
-
skipInputTokenCheck: true, // Rebalance should be independent of user wallet TA
|
|
1802
|
-
}, hsToMeteora_1.meteoraToHawksightAutomationIxs);
|
|
1803
|
-
const mainInstructions = [
|
|
1804
|
-
// Initialize required ATA
|
|
1805
|
-
...removeLiquidityBuilder.createAtaIxs,
|
|
1806
|
-
// Remove liquidity
|
|
1807
|
-
...removeLiquidityBuilder.mainIxs,
|
|
1808
|
-
// Re-deposit liquidity
|
|
1809
|
-
...initPositionAndAddLiquidityBuilder.mainIxs,
|
|
1810
|
-
];
|
|
1811
|
-
return (0, functions_1.createTransactionMeta)({
|
|
1812
|
-
payer: params.userWallet,
|
|
1813
|
-
description: 'Automation IX: Meteora Auto-rebalance instructions (Close position and deposit to new position)',
|
|
1814
|
-
addressLookupTableAddresses: addresses_1.GLOBAL_ALT,
|
|
1815
|
-
mainInstructions,
|
|
1816
|
-
});
|
|
1817
|
-
});
|
|
1818
|
-
}
|
|
1819
1755
|
/**
|
|
1820
1756
|
*
|
|
1821
1757
|
* @param connection The Solana web3 connection object for blockchain interactions.
|
|
@@ -1907,246 +1843,6 @@ class Transactions {
|
|
|
1907
1843
|
}
|
|
1908
1844
|
});
|
|
1909
1845
|
}
|
|
1910
|
-
/**
|
|
1911
|
-
* Rebalance a Meteora DLMM position with hybrid liquidity support.
|
|
1912
|
-
*
|
|
1913
|
-
* Supports two modes:
|
|
1914
|
-
* - Simple mode: Single distribution (same as rebalanceAutomationIx2)
|
|
1915
|
-
* - Hybrid mode: Multiple liquidity layers with per-side distribution control
|
|
1916
|
-
*
|
|
1917
|
-
* Simple mode (1 TX): Remove + close + init + deposit (same as Ixs2)
|
|
1918
|
-
* Hybrid mode (2 TXs):
|
|
1919
|
-
* TX1: Remove liquidity + claim fees/rewards + close position
|
|
1920
|
-
* TX2: Init new position + deposit layer 1 (static amounts) + deposit layer 2 (sweep remaining)
|
|
1921
|
-
*/
|
|
1922
|
-
rebalanceAutomationIx3(_a) {
|
|
1923
|
-
return __awaiter(this, arguments, void 0, function* ({ connection, params, }) {
|
|
1924
|
-
var _b, _c;
|
|
1925
|
-
try {
|
|
1926
|
-
// --- Validate and normalize layers ---
|
|
1927
|
-
let layers;
|
|
1928
|
-
if (params.distribution && !params.layers) {
|
|
1929
|
-
layers = [
|
|
1930
|
-
{
|
|
1931
|
-
distribution: params.distribution,
|
|
1932
|
-
percentageX: 100,
|
|
1933
|
-
percentageY: 100,
|
|
1934
|
-
},
|
|
1935
|
-
];
|
|
1936
|
-
}
|
|
1937
|
-
else if (params.layers && !params.distribution) {
|
|
1938
|
-
layers = params.layers;
|
|
1939
|
-
}
|
|
1940
|
-
else {
|
|
1941
|
-
throw new Error('Provide either distribution or layers, not both');
|
|
1942
|
-
}
|
|
1943
|
-
if (layers.length === 0 || layers.length > 3) {
|
|
1944
|
-
throw new Error('layers must have 1-3 entries');
|
|
1945
|
-
}
|
|
1946
|
-
const sumX = layers.reduce((s, l) => s + l.percentageX, 0);
|
|
1947
|
-
const sumY = layers.reduce((s, l) => s + l.percentageY, 0);
|
|
1948
|
-
if (sumX !== 100 || sumY !== 100) {
|
|
1949
|
-
throw new Error(`Layer percentages must sum to 100 per side (got X=${sumX}, Y=${sumY})`);
|
|
1950
|
-
}
|
|
1951
|
-
// --- Build labeled instructions ---
|
|
1952
|
-
const program = yield meteora_1.MeteoraDLMM.program(connection);
|
|
1953
|
-
const positionOnChain = yield program.account.positionV2.fetch(params.currentPosition);
|
|
1954
|
-
const lbPair = positionOnChain.lbPair;
|
|
1955
|
-
const dlmmPool = yield meteora_1.MeteoraDLMM.create(connection, lbPair, this.ix);
|
|
1956
|
-
const userPda = (0, functions_1.generateUserPda)(params.userWallet);
|
|
1957
|
-
// Get position data for amount estimates and bin range
|
|
1958
|
-
const { userPositions } = yield dlmmPool.getPositionsByUserAndLbPair(userPda);
|
|
1959
|
-
const userPosition = userPositions.find(p => p.publicKey.equals(params.currentPosition));
|
|
1960
|
-
if (!userPosition) {
|
|
1961
|
-
throw new Error(`Position: ${params.currentPosition} does not exist.`);
|
|
1962
|
-
}
|
|
1963
|
-
const currentLowerBinId = userPosition.positionData.lowerBinId;
|
|
1964
|
-
const currentUpperBinId = userPosition.positionData.upperBinId;
|
|
1965
|
-
const lbPairState = dlmmPool.dlmm.lbPair;
|
|
1966
|
-
const tokenXMint = lbPairState.tokenXMint;
|
|
1967
|
-
const tokenYMint = lbPairState.tokenYMint;
|
|
1968
|
-
const rewardInfos = lbPairState.rewardInfos;
|
|
1969
|
-
const tokenProgramMap = yield (0, functions_1.getTokenProgramMapForMints)(connection, [
|
|
1970
|
-
tokenXMint,
|
|
1971
|
-
tokenYMint,
|
|
1972
|
-
]);
|
|
1973
|
-
const tokenXProgram = tokenProgramMap[tokenXMint.toString()];
|
|
1974
|
-
const tokenYProgram = tokenProgramMap[tokenYMint.toString()];
|
|
1975
|
-
const remainingAccountsInfo = yield (0, functions_1.fetchRemainingAccountsInfo)(connection, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram);
|
|
1976
|
-
const pdaTokenTypeForClaimables = params.useAta
|
|
1977
|
-
? types_1.TokenType.ATA
|
|
1978
|
-
: types_1.TokenType.STA;
|
|
1979
|
-
// Estimate total X/Y from position data (liquidity + fees)
|
|
1980
|
-
const estimatedTotalX = new bn_js_1.default(userPosition.positionData.totalXAmount).add(userPosition.positionData.feeX);
|
|
1981
|
-
const estimatedTotalY = new bn_js_1.default(userPosition.positionData.totalYAmount).add(userPosition.positionData.feeY);
|
|
1982
|
-
const instructions = [];
|
|
1983
|
-
const labels = [];
|
|
1984
|
-
const removeLiquidityIx = yield this.ix.meteoraDlmm.removeLiquidityByRange2Automation({
|
|
1985
|
-
connection,
|
|
1986
|
-
userWallet: params.userWallet,
|
|
1987
|
-
lbPair,
|
|
1988
|
-
position: params.currentPosition,
|
|
1989
|
-
tokenXMint,
|
|
1990
|
-
tokenYMint,
|
|
1991
|
-
tokenXProgram,
|
|
1992
|
-
tokenYProgram,
|
|
1993
|
-
fromBinId: currentLowerBinId,
|
|
1994
|
-
toBinId: currentUpperBinId,
|
|
1995
|
-
bpsToRemove: 10000,
|
|
1996
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
1997
|
-
remainingAccountsInfo,
|
|
1998
|
-
});
|
|
1999
|
-
instructions.push(removeLiquidityIx);
|
|
2000
|
-
labels.push('remove');
|
|
2001
|
-
const claimFeeIx = yield this.ix.meteoraDlmm.claimFee2Automation(connection, {
|
|
2002
|
-
userWallet: params.userWallet,
|
|
2003
|
-
lbPair,
|
|
2004
|
-
position: params.currentPosition,
|
|
2005
|
-
tokenMintX: tokenXMint,
|
|
2006
|
-
tokenMintY: tokenYMint,
|
|
2007
|
-
tokenProgramX: tokenXProgram,
|
|
2008
|
-
tokenProgramY: tokenYProgram,
|
|
2009
|
-
lowerBinId: currentLowerBinId,
|
|
2010
|
-
upperBinId: currentUpperBinId,
|
|
2011
|
-
pdaTokenType: pdaTokenTypeForClaimables,
|
|
2012
|
-
remainingAccountsInfo,
|
|
2013
|
-
});
|
|
2014
|
-
instructions.push(claimFeeIx);
|
|
2015
|
-
labels.push('claim_fee');
|
|
2016
|
-
for (let rewardIndex = 0; rewardIndex < 2; rewardIndex++) {
|
|
2017
|
-
const rewardInfo = rewardInfos[rewardIndex];
|
|
2018
|
-
if (!rewardInfo || rewardInfo.mint.equals(web3.PublicKey.default))
|
|
2019
|
-
continue;
|
|
2020
|
-
const rewardTokenProgramMap = yield (0, functions_1.getTokenProgramMapForMints)(connection, [rewardInfo.mint]);
|
|
2021
|
-
const rewardTokenProgram = rewardTokenProgramMap[rewardInfo.mint.toString()];
|
|
2022
|
-
const rewardRemainingAccountsInfo = yield (0, functions_1.fetchRemainingAccountsInfoForReward)(connection, rewardInfo.mint, rewardTokenProgram);
|
|
2023
|
-
const claimRewardIx = yield this.ix.meteoraDlmm.claimReward2Automation(connection, {
|
|
2024
|
-
userWallet: params.userWallet,
|
|
2025
|
-
lbPair,
|
|
2026
|
-
position: params.currentPosition,
|
|
2027
|
-
rewardIndex,
|
|
2028
|
-
rewardMint: rewardInfo.mint,
|
|
2029
|
-
rewardVault: rewardInfo.vault,
|
|
2030
|
-
tokenProgram: rewardTokenProgram,
|
|
2031
|
-
lowerBinId: currentLowerBinId,
|
|
2032
|
-
upperBinId: currentUpperBinId,
|
|
2033
|
-
pdaTokenType: types_1.TokenType.STA,
|
|
2034
|
-
remainingAccountsInfo: rewardRemainingAccountsInfo,
|
|
2035
|
-
});
|
|
2036
|
-
instructions.push(claimRewardIx);
|
|
2037
|
-
labels.push('claim_reward');
|
|
2038
|
-
}
|
|
2039
|
-
const closePositionIx = yield this.ix.meteoraDlmm.closePosition2Automation({
|
|
2040
|
-
connection,
|
|
2041
|
-
userWallet: params.userWallet,
|
|
2042
|
-
position: params.currentPosition,
|
|
2043
|
-
lbPair,
|
|
2044
|
-
});
|
|
2045
|
-
instructions.push(closePositionIx);
|
|
2046
|
-
labels.push('close');
|
|
2047
|
-
// Find the last layer index that has non-zero percentage for X and Y
|
|
2048
|
-
let lastActiveXIndex = -1;
|
|
2049
|
-
let lastActiveYIndex = -1;
|
|
2050
|
-
for (let i = layers.length - 1; i >= 0; i--) {
|
|
2051
|
-
if (lastActiveXIndex === -1 && layers[i].percentageX > 0)
|
|
2052
|
-
lastActiveXIndex = i;
|
|
2053
|
-
if (lastActiveYIndex === -1 && layers[i].percentageY > 0)
|
|
2054
|
-
lastActiveYIndex = i;
|
|
2055
|
-
}
|
|
2056
|
-
// Helper to compute optional amounts for a layer
|
|
2057
|
-
const computeAmounts = (layer, i) => {
|
|
2058
|
-
let optionalTokenXAmount;
|
|
2059
|
-
let optionalTokenYAmount;
|
|
2060
|
-
if (layer.percentageX === 0) {
|
|
2061
|
-
optionalTokenXAmount = new bn_js_1.default(0);
|
|
2062
|
-
}
|
|
2063
|
-
else if (i === lastActiveXIndex) {
|
|
2064
|
-
optionalTokenXAmount = undefined; // sweep remaining
|
|
2065
|
-
}
|
|
2066
|
-
else {
|
|
2067
|
-
optionalTokenXAmount = estimatedTotalX
|
|
2068
|
-
.mul(new bn_js_1.default(layer.percentageX))
|
|
2069
|
-
.div(new bn_js_1.default(100));
|
|
2070
|
-
}
|
|
2071
|
-
if (layer.percentageY === 0) {
|
|
2072
|
-
optionalTokenYAmount = new bn_js_1.default(0);
|
|
2073
|
-
}
|
|
2074
|
-
else if (i === lastActiveYIndex) {
|
|
2075
|
-
optionalTokenYAmount = undefined; // sweep remaining
|
|
2076
|
-
}
|
|
2077
|
-
else {
|
|
2078
|
-
optionalTokenYAmount = estimatedTotalY
|
|
2079
|
-
.mul(new bn_js_1.default(layer.percentageY))
|
|
2080
|
-
.div(new bn_js_1.default(100));
|
|
2081
|
-
}
|
|
2082
|
-
return { optionalTokenXAmount, optionalTokenYAmount };
|
|
2083
|
-
};
|
|
2084
|
-
// Layer 0: init position + first deposit via relativeOpenAutomation
|
|
2085
|
-
const firstLayer = layers[0];
|
|
2086
|
-
const firstAmounts = computeAmounts(firstLayer, 0);
|
|
2087
|
-
const firstStrategyType = types_3.StrategyTypeMap[firstLayer.distribution];
|
|
2088
|
-
const initAndDepositIx = yield this.ix.meteoraDlmm.relativeOpenAutomation(connection, {
|
|
2089
|
-
userWallet: params.userWallet,
|
|
2090
|
-
lbPair,
|
|
2091
|
-
position: params.newPosition,
|
|
2092
|
-
relativeLowerBinId: params.relativeBinRange.lowerRange,
|
|
2093
|
-
relativeUpperBinId: params.relativeBinRange.upperRange,
|
|
2094
|
-
strategyType: firstStrategyType,
|
|
2095
|
-
checkRange: {
|
|
2096
|
-
minBinId: params.checkRange.lowerRange,
|
|
2097
|
-
maxBinId: params.checkRange.upperRange,
|
|
2098
|
-
},
|
|
2099
|
-
targetActiveBin: (_b = params.targetActiveBin) !== null && _b !== void 0 ? _b : undefined,
|
|
2100
|
-
userTokenXAmount: firstAmounts.optionalTokenXAmount,
|
|
2101
|
-
userTokenYAmount: firstAmounts.optionalTokenYAmount,
|
|
2102
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
2103
|
-
});
|
|
2104
|
-
instructions.push(initAndDepositIx);
|
|
2105
|
-
labels.push('init');
|
|
2106
|
-
// Layers 1+ : deposit-only via addLiquidityByStrategy2Automation
|
|
2107
|
-
const { binId: activeId } = yield dlmmPool.dlmm.getActiveBin();
|
|
2108
|
-
const effectiveActiveId = (_c = params.targetActiveBin) !== null && _c !== void 0 ? _c : activeId;
|
|
2109
|
-
const absLower = effectiveActiveId + params.relativeBinRange.lowerRange;
|
|
2110
|
-
const absUpper = effectiveActiveId + params.relativeBinRange.upperRange;
|
|
2111
|
-
for (let i = 1; i < layers.length; i++) {
|
|
2112
|
-
const layer = layers[i];
|
|
2113
|
-
const { optionalTokenXAmount, optionalTokenYAmount } = computeAmounts(layer, i);
|
|
2114
|
-
const strategyType = types_3.StrategyTypeMap[layer.distribution];
|
|
2115
|
-
const depositIx = yield this.ix.meteoraDlmm.addLiquidityByStrategy2Automation(connection, {
|
|
2116
|
-
userWallet: params.userWallet,
|
|
2117
|
-
lbPair,
|
|
2118
|
-
position: params.newPosition,
|
|
2119
|
-
tokenXMint,
|
|
2120
|
-
tokenYMint,
|
|
2121
|
-
tokenXProgram,
|
|
2122
|
-
tokenYProgram,
|
|
2123
|
-
activeId: effectiveActiveId,
|
|
2124
|
-
maxActiveBinSlippage: 0,
|
|
2125
|
-
strategyParametersMinBinId: absLower,
|
|
2126
|
-
strategyParametersMaxBinId: absUpper,
|
|
2127
|
-
strategyParametersStrategyType: strategyType,
|
|
2128
|
-
strategyParametersParameters: new Array(64).fill(0),
|
|
2129
|
-
userTokenXAmount: optionalTokenXAmount,
|
|
2130
|
-
userTokenYAmount: optionalTokenYAmount,
|
|
2131
|
-
remainingAccountsInfo,
|
|
2132
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
2133
|
-
});
|
|
2134
|
-
instructions.push(depositIx);
|
|
2135
|
-
labels.push('deposit');
|
|
2136
|
-
}
|
|
2137
|
-
return { instructions, labels };
|
|
2138
|
-
}
|
|
2139
|
-
catch (error) {
|
|
2140
|
-
console.error('=== REBALANCE AUTOMATION IX3 ERROR ===');
|
|
2141
|
-
console.error('Error type:', error instanceof Error ? error.constructor.name : typeof error);
|
|
2142
|
-
console.error('Error message:', error instanceof Error ? error.message : String(error));
|
|
2143
|
-
console.error('Error stack:', error instanceof Error ? error.stack : 'No stack trace');
|
|
2144
|
-
console.error('Full error object:', error);
|
|
2145
|
-
console.error('=== END ERROR LOG ===');
|
|
2146
|
-
throw error;
|
|
2147
|
-
}
|
|
2148
|
-
});
|
|
2149
|
-
}
|
|
2150
1846
|
rebalanceSmallPositionAutomation(_a) {
|
|
2151
1847
|
return __awaiter(this, arguments, void 0, function* ({ connection, params, }) {
|
|
2152
1848
|
// Current theoretical limit (149-bin)
|
|
@@ -2890,98 +2586,6 @@ class Transactions {
|
|
|
2890
2586
|
}
|
|
2891
2587
|
});
|
|
2892
2588
|
}
|
|
2893
|
-
/**
|
|
2894
|
-
* Generates a single rebalanceLiquidityAutomation instruction for reshaping a Meteora DLMM position.
|
|
2895
|
-
*
|
|
2896
|
-
* This is a low-level building block that creates ONE instruction to:
|
|
2897
|
-
* - Remove liquidity from specified bins (removeLiquidityParams)
|
|
2898
|
-
* - Add liquidity to new bins (addLiquidityParams)
|
|
2899
|
-
*
|
|
2900
|
-
* Unlike meteoraRebalanceLargePositionAutomation2 which handles full position reshaping
|
|
2901
|
-
* with chunking and multiple TXs, this function returns a single instruction that can
|
|
2902
|
-
* be composed into custom transaction flows.
|
|
2903
|
-
*
|
|
2904
|
-
* Features:
|
|
2905
|
-
* - Token2022 transfer hook support
|
|
2906
|
-
* - No fee/reward claiming (shouldClaimFee: false, shouldClaimReward: false)
|
|
2907
|
-
* - Uses ATA token accounts
|
|
2908
|
-
* - NoShrinkBoth shrink mode
|
|
2909
|
-
*
|
|
2910
|
-
* Note: Not part of test suite yet. For remove + add liquidity params, please fork
|
|
2911
|
-
* hawk-api/src/meteora/liquidityStrategy.ts to generate the parameters.
|
|
2912
|
-
*
|
|
2913
|
-
* @param connection Solana web3 connection
|
|
2914
|
-
* @param params Reshape parameters including position, bin ranges, and liquidity params
|
|
2915
|
-
* @returns LabeledInstructions with single 'rebalance_liquidity' instruction
|
|
2916
|
-
*/
|
|
2917
|
-
meteoraReshapePositionAutomation(_a) {
|
|
2918
|
-
return __awaiter(this, arguments, void 0, function* ({ connection, params, }) {
|
|
2919
|
-
var _b, _c;
|
|
2920
|
-
// Fetch pool data
|
|
2921
|
-
const dlmmPool = yield meteora_1.MeteoraDLMM.create(connection, params.lbPair, this.ix);
|
|
2922
|
-
const lbPairState = dlmmPool.dlmm.lbPair;
|
|
2923
|
-
const tokenXMint = lbPairState.tokenXMint;
|
|
2924
|
-
const tokenYMint = lbPairState.tokenYMint;
|
|
2925
|
-
const tokenProgramMap = yield (0, functions_1.getTokenProgramMapForMints)(connection, [
|
|
2926
|
-
tokenXMint,
|
|
2927
|
-
tokenYMint,
|
|
2928
|
-
]);
|
|
2929
|
-
const tokenXProgram = tokenProgramMap[tokenXMint.toString()];
|
|
2930
|
-
const tokenYProgram = tokenProgramMap[tokenYMint.toString()];
|
|
2931
|
-
// Fetch transfer hook accounts for token X and Y (Token2022 support)
|
|
2932
|
-
const baseRemainingAccountsInfo = yield (0, functions_1.fetchRemainingAccountsInfo)(connection, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram);
|
|
2933
|
-
// Build combined remainingAccountsInfo with transfer hooks for X, Y, and rewards
|
|
2934
|
-
// The slices describe: TransferHookX, TransferHookY, TransferHookMultiReward(index) for each reward
|
|
2935
|
-
// IMPORTANT: Always include all slices, even with length=0, so Meteora knows the account structure
|
|
2936
|
-
const combinedSlices = [];
|
|
2937
|
-
const combinedAccounts = [];
|
|
2938
|
-
// Always add TransferHookX and TransferHookY slices (even if length=0)
|
|
2939
|
-
const xSlice = baseRemainingAccountsInfo.slices.find(s => s.accountsType === types_1.RemainingAccountsType.TransferHookX);
|
|
2940
|
-
const ySlice = baseRemainingAccountsInfo.slices.find(s => s.accountsType === types_1.RemainingAccountsType.TransferHookY);
|
|
2941
|
-
combinedSlices.push({
|
|
2942
|
-
accountsType: types_1.RemainingAccountsType.TransferHookX,
|
|
2943
|
-
length: (_b = xSlice === null || xSlice === void 0 ? void 0 : xSlice.length) !== null && _b !== void 0 ? _b : 0,
|
|
2944
|
-
});
|
|
2945
|
-
combinedSlices.push({
|
|
2946
|
-
accountsType: types_1.RemainingAccountsType.TransferHookY,
|
|
2947
|
-
length: (_c = ySlice === null || ySlice === void 0 ? void 0 : ySlice.length) !== null && _c !== void 0 ? _c : 0,
|
|
2948
|
-
});
|
|
2949
|
-
// Add transfer hook accounts from base (for X and Y)
|
|
2950
|
-
combinedAccounts.push(...baseRemainingAccountsInfo.accounts);
|
|
2951
|
-
const remainingAccountsInfo = {
|
|
2952
|
-
slices: combinedSlices,
|
|
2953
|
-
accounts: combinedAccounts,
|
|
2954
|
-
};
|
|
2955
|
-
return {
|
|
2956
|
-
instructions: [
|
|
2957
|
-
yield this.ix.meteoraDlmm.rebalanceLiquidityAutomation({
|
|
2958
|
-
connection,
|
|
2959
|
-
userWallet: params.userWallet,
|
|
2960
|
-
position: params.position,
|
|
2961
|
-
lbPair: params.lbPair,
|
|
2962
|
-
tokenXMint,
|
|
2963
|
-
tokenYMint,
|
|
2964
|
-
tokenXProgram,
|
|
2965
|
-
tokenYProgram,
|
|
2966
|
-
activeId: params.activeId,
|
|
2967
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
2968
|
-
maxActiveBinSlippage: 0,
|
|
2969
|
-
shouldClaimFee: false,
|
|
2970
|
-
shouldClaimReward: false,
|
|
2971
|
-
minWithdrawXAmount: new bn_js_1.default(0),
|
|
2972
|
-
maxDepositXAmount: new bn_js_1.default(0),
|
|
2973
|
-
minWithdrawYAmount: new bn_js_1.default(0),
|
|
2974
|
-
maxDepositYAmount: new bn_js_1.default(0),
|
|
2975
|
-
removeLiquidityParams: params.removeLiquidityParams,
|
|
2976
|
-
addLiquidityParams: params.addLiquidityParams,
|
|
2977
|
-
shrinkMode: types_3.ShrinkMode.NoShrinkBoth,
|
|
2978
|
-
remainingAccountsInfo,
|
|
2979
|
-
}),
|
|
2980
|
-
],
|
|
2981
|
-
labels: ['rebalance_liquidity'],
|
|
2982
|
-
};
|
|
2983
|
-
});
|
|
2984
|
-
}
|
|
2985
2589
|
/**
|
|
2986
2590
|
* Compute claimable fees for a position directly from on-chain account data.
|
|
2987
2591
|
* Avoids expensive getPositionsByUserAndLbPair by parsing raw buffers.
|
|
@@ -6447,23 +6051,15 @@ class Transactions {
|
|
|
6447
6051
|
});
|
|
6448
6052
|
});
|
|
6449
6053
|
}
|
|
6450
|
-
|
|
6451
|
-
* Hybrid liquidity rebalance for automation: teardown old position and rebuild
|
|
6452
|
-
* with independent X/Y distributions per layer using rebalanceLiquidityAutomation.
|
|
6453
|
-
*
|
|
6454
|
-
* Supports all position sizes (≤70, 71-149, ≥150 bins).
|
|
6455
|
-
* All hybrid layers are passed as multiple addLiquidityParams entries in a single
|
|
6456
|
-
* rebalanceLiquidityAutomation call per chunk (rather than one call per layer).
|
|
6457
|
-
*/
|
|
6458
|
-
meteoraRebalanceHybridLiquidityAutomation(_a) {
|
|
6054
|
+
meteoraRebalanceHybridLiquidityV2Automation(_a) {
|
|
6459
6055
|
return __awaiter(this, arguments, void 0, function* ({ connection, params, }) {
|
|
6460
6056
|
var _b, _c;
|
|
6461
6057
|
try {
|
|
6462
6058
|
const MAX_INIT_WIDTH = 70;
|
|
6463
6059
|
const MAX_EXTEND_LENGTH = 91;
|
|
6464
|
-
const MAX_BINS_PER_WITHDRAW_CHUNK =
|
|
6465
|
-
const
|
|
6466
|
-
const CLASS = '
|
|
6060
|
+
const MAX_BINS_PER_WITHDRAW_CHUNK = 175;
|
|
6061
|
+
const CHUNKS_PER_TRANSACTION = 3;
|
|
6062
|
+
const CLASS = 'meteoraRebalanceHybridLiquidityV2Automation';
|
|
6467
6063
|
// --- Validate layers ---
|
|
6468
6064
|
const layers = params.layers;
|
|
6469
6065
|
if (layers.length === 0 || layers.length > 3) {
|
|
@@ -6474,14 +6070,13 @@ class Transactions {
|
|
|
6474
6070
|
if (sumX !== 100 || sumY !== 100) {
|
|
6475
6071
|
throw new Error(`Layer percentages must sum to 100 per side (got X=${sumX}, Y=${sumY})`);
|
|
6476
6072
|
}
|
|
6477
|
-
const { lbPair, lbPairState, dlmmPool, lowerBinId: currentLowerBinId, upperBinId: currentUpperBinId, estimatedTotalX, estimatedTotalY, activeId, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, withdrawFn,
|
|
6073
|
+
const { lbPair, lbPairState, dlmmPool, lowerBinId: currentLowerBinId, upperBinId: currentUpperBinId, estimatedTotalX, estimatedTotalY, activeId, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, withdrawFn, baseRemainingAccountsInfo, } = yield this.resolvePositionContext({
|
|
6478
6074
|
connection,
|
|
6479
6075
|
userWallet: params.userWallet,
|
|
6480
6076
|
position: params.currentPosition,
|
|
6481
6077
|
compound: params.compound,
|
|
6482
6078
|
targetActiveBin: params.targetActiveBin,
|
|
6483
6079
|
});
|
|
6484
|
-
// checkRange validation
|
|
6485
6080
|
if (activeId < params.checkRange.lowerRange ||
|
|
6486
6081
|
activeId > params.checkRange.upperRange) {
|
|
6487
6082
|
throw new Error(`Active bin ${activeId} outside checkRange [${params.checkRange.lowerRange}, ${params.checkRange.upperRange}]`);
|
|
@@ -6490,13 +6085,13 @@ class Transactions {
|
|
|
6490
6085
|
const newUpperBinId = activeId + params.relativeBinRange.upperRange;
|
|
6491
6086
|
const newWidth = newUpperBinId - newLowerBinId + 1;
|
|
6492
6087
|
const currentWidth = currentUpperBinId - currentLowerBinId + 1;
|
|
6493
|
-
const
|
|
6088
|
+
const maxBinsPerDepositChunk = newWidth <= 69 ? 69 : 45;
|
|
6089
|
+
const useLayeredDepositsForSmallPosition = newWidth <= 69 && layers.length > 1;
|
|
6494
6090
|
// =========================================================================
|
|
6495
6091
|
// PHASE 1: TEARDOWN (withdraw from old position + close)
|
|
6496
6092
|
// =========================================================================
|
|
6497
6093
|
const teardownTxGroups = [];
|
|
6498
6094
|
if (currentWidth <= MAX_BINS_PER_WITHDRAW_CHUNK) {
|
|
6499
|
-
// Small/medium: single withdraw TX
|
|
6500
6095
|
teardownTxGroups.push([
|
|
6501
6096
|
...(yield withdrawFn({
|
|
6502
6097
|
position: params.currentPosition,
|
|
@@ -6518,7 +6113,6 @@ class Transactions {
|
|
|
6518
6113
|
]);
|
|
6519
6114
|
}
|
|
6520
6115
|
else {
|
|
6521
|
-
// Large: chunked withdrawal
|
|
6522
6116
|
const withdrawChunks = (0, liquidityStrategy_1.chunkBinRange)(currentLowerBinId, currentUpperBinId, MAX_BINS_PER_WITHDRAW_CHUNK);
|
|
6523
6117
|
for (let i = 0; i < withdrawChunks.length; i++) {
|
|
6524
6118
|
const chunk = withdrawChunks[i];
|
|
@@ -6548,309 +6142,7 @@ class Transactions {
|
|
|
6548
6142
|
}
|
|
6549
6143
|
}
|
|
6550
6144
|
// =========================================================================
|
|
6551
|
-
// PHASE 2: REBUILD (init + extend + deposit with
|
|
6552
|
-
// =========================================================================
|
|
6553
|
-
const effectiveAmountX = (_b = params.amountXOverride) !== null && _b !== void 0 ? _b : estimatedTotalX;
|
|
6554
|
-
const effectiveAmountY = (_c = params.amountYOverride) !== null && _c !== void 0 ? _c : estimatedTotalY;
|
|
6555
|
-
const favorXInActiveId = effectiveAmountY.isZero() && !effectiveAmountX.isZero();
|
|
6556
|
-
const minDeltaId = newLowerBinId - activeId;
|
|
6557
|
-
const maxDeltaId = newUpperBinId - activeId;
|
|
6558
|
-
// Compute hybrid strategy for the full new range
|
|
6559
|
-
const strategyResults = (0, liquidityStrategy_1.distributionToHybridStrategy)({
|
|
6560
|
-
hybridDistribution: layers,
|
|
6561
|
-
amountX: effectiveAmountX,
|
|
6562
|
-
amountY: effectiveAmountY,
|
|
6563
|
-
minDeltaId: new bn_js_1.default(minDeltaId),
|
|
6564
|
-
maxDeltaId: new bn_js_1.default(maxDeltaId),
|
|
6565
|
-
binStep,
|
|
6566
|
-
activeId: new bn_js_1.default(activeId),
|
|
6567
|
-
});
|
|
6568
|
-
// Build init + extend instructions
|
|
6569
|
-
const initExtendIxs = [];
|
|
6570
|
-
const initWidth = Math.min(MAX_INIT_WIDTH, newWidth);
|
|
6571
|
-
initExtendIxs.push({
|
|
6572
|
-
label: 'initialize_position_relative',
|
|
6573
|
-
class: CLASS,
|
|
6574
|
-
instruction: yield this.ix.meteoraDlmm.initializePositionRelativeAutomation(connection, {
|
|
6575
|
-
userWallet: params.userWallet,
|
|
6576
|
-
lbPair,
|
|
6577
|
-
position: params.newPosition,
|
|
6578
|
-
relativeLowerBinId: params.relativeBinRange.lowerRange,
|
|
6579
|
-
width: initWidth,
|
|
6580
|
-
}),
|
|
6581
|
-
});
|
|
6582
|
-
let positionBinsAllocated = initWidth;
|
|
6583
|
-
while (positionBinsAllocated < newWidth) {
|
|
6584
|
-
const toAdd = Math.min(MAX_EXTEND_LENGTH, newWidth - positionBinsAllocated);
|
|
6585
|
-
initExtendIxs.push({
|
|
6586
|
-
label: 'increase_position_length',
|
|
6587
|
-
class: CLASS,
|
|
6588
|
-
instruction: yield this.ix.meteoraDlmm.increasePositionLengthAutomation({
|
|
6589
|
-
connection,
|
|
6590
|
-
userWallet: params.userWallet,
|
|
6591
|
-
lbPair,
|
|
6592
|
-
position: params.newPosition,
|
|
6593
|
-
lengthToAdd: toAdd,
|
|
6594
|
-
side: types_1.MeteoraPositionSide.Upper,
|
|
6595
|
-
}),
|
|
6596
|
-
});
|
|
6597
|
-
positionBinsAllocated += toAdd;
|
|
6598
|
-
}
|
|
6599
|
-
// Build deposit TX group(s)
|
|
6600
|
-
const rebuildTxGroups = [];
|
|
6601
|
-
if (newWidth <= MAX_BINS_PER_DEPOSIT_CHUNK) {
|
|
6602
|
-
// Small/medium: all layers in one rebalanceLiquidity call.
|
|
6603
|
-
// Split into two TXs when extension is needed (newWidth > MAX_INIT_WIDTH) to
|
|
6604
|
-
// avoid exceeding the TX size limit with init + extend + binArrayInits + deposit.
|
|
6605
|
-
//
|
|
6606
|
-
// Merge all layers into a single AddLiquidityParams entry by summing x0/y0/deltaX/deltaY.
|
|
6607
|
-
// Meteora's rebalanceLiquidity requires non-overlapping ranges across entries; since all
|
|
6608
|
-
// layers share the same full range, they must be merged into one. The formula is linear
|
|
6609
|
-
// so summing params is equivalent to summing per-bin amounts from each layer.
|
|
6610
|
-
const mergedLayer = strategyResults.reduce((acc, l) => ({
|
|
6611
|
-
x0: acc.x0.add(l.x0),
|
|
6612
|
-
y0: acc.y0.add(l.y0),
|
|
6613
|
-
deltaX: acc.deltaX.add(l.deltaX),
|
|
6614
|
-
deltaY: acc.deltaY.add(l.deltaY),
|
|
6615
|
-
}), {
|
|
6616
|
-
x0: new bn_js_1.default(0),
|
|
6617
|
-
y0: new bn_js_1.default(0),
|
|
6618
|
-
deltaX: new bn_js_1.default(0),
|
|
6619
|
-
deltaY: new bn_js_1.default(0),
|
|
6620
|
-
});
|
|
6621
|
-
const mergedP = (0, liquidityStrategy_1.buildBitFlagAndNegateStrategyParameters)(mergedLayer.x0, mergedLayer.y0, mergedLayer.deltaX, mergedLayer.deltaY);
|
|
6622
|
-
const allAddLiquidityParams = [
|
|
6623
|
-
{
|
|
6624
|
-
minDeltaId,
|
|
6625
|
-
maxDeltaId,
|
|
6626
|
-
x0: mergedP.x0,
|
|
6627
|
-
y0: mergedP.y0,
|
|
6628
|
-
deltaX: mergedP.deltaX,
|
|
6629
|
-
deltaY: mergedP.deltaY,
|
|
6630
|
-
bitFlag: mergedP.bitFlag,
|
|
6631
|
-
favorXInActiveId,
|
|
6632
|
-
},
|
|
6633
|
-
];
|
|
6634
|
-
const mergedBinsAmounts = (0, liquidityStrategy_1.toAmountIntoBins)(new bn_js_1.default(activeId), new bn_js_1.default(minDeltaId), new bn_js_1.default(maxDeltaId), mergedLayer.deltaX, mergedLayer.deltaY, mergedLayer.x0, mergedLayer.y0, binStep, favorXInActiveId);
|
|
6635
|
-
const totalMaxX = mergedBinsAmounts.reduce((s, b) => s.add(b.amountX), new bn_js_1.default(0));
|
|
6636
|
-
const totalMaxY = mergedBinsAmounts.reduce((s, b) => s.add(b.amountY), new bn_js_1.default(0));
|
|
6637
|
-
const binArrayInitIxs = yield this._initBinArraysForRange(connection, lbPair, dlmmPool, newLowerBinId, newUpperBinId);
|
|
6638
|
-
const binArrayInitIxsLabeled = binArrayInitIxs.map(ix => ({
|
|
6639
|
-
label: 'init_bin_array',
|
|
6640
|
-
class: CLASS,
|
|
6641
|
-
instruction: ix,
|
|
6642
|
-
}));
|
|
6643
|
-
const depositIx = yield depositFn({
|
|
6644
|
-
position: params.newPosition,
|
|
6645
|
-
shouldClaimFee: false,
|
|
6646
|
-
shouldClaimReward: false,
|
|
6647
|
-
maxDepositXAmount: totalMaxX,
|
|
6648
|
-
maxDepositYAmount: totalMaxY,
|
|
6649
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
6650
|
-
addLiquidityParams: allAddLiquidityParams,
|
|
6651
|
-
origin: CLASS,
|
|
6652
|
-
});
|
|
6653
|
-
if (newWidth <= MAX_INIT_WIDTH) {
|
|
6654
|
-
// ≤70 bins: no extension needed, everything fits in one TX
|
|
6655
|
-
rebuildTxGroups.push([
|
|
6656
|
-
...initExtendIxs,
|
|
6657
|
-
...binArrayInitIxsLabeled,
|
|
6658
|
-
depositIx,
|
|
6659
|
-
]);
|
|
6660
|
-
}
|
|
6661
|
-
else {
|
|
6662
|
-
// 71-149 bins: extension needed, split init+extend from deposit to stay within TX size limit
|
|
6663
|
-
rebuildTxGroups.push(initExtendIxs);
|
|
6664
|
-
rebuildTxGroups.push([...binArrayInitIxsLabeled, depositIx]);
|
|
6665
|
-
}
|
|
6666
|
-
}
|
|
6667
|
-
else {
|
|
6668
|
-
// Large: init+extend in first TX, then one TX per deposit chunk
|
|
6669
|
-
rebuildTxGroups.push(initExtendIxs);
|
|
6670
|
-
const depositChunks = (0, liquidityStrategy_1.chunkHybridDepositParameters)(strategyResults, new bn_js_1.default(minDeltaId), new bn_js_1.default(maxDeltaId), new bn_js_1.default(activeId), binStep, MAX_BINS_PER_DEPOSIT_CHUNK, favorXInActiveId);
|
|
6671
|
-
for (const chunk of depositChunks) {
|
|
6672
|
-
const chunkAddLiquidityParams = chunk.layers.map(layer => {
|
|
6673
|
-
const onChainParams = (0, liquidityStrategy_1.buildBitFlagAndNegateStrategyParameters)(layer.params.x0, layer.params.y0, layer.params.deltaX, layer.params.deltaY);
|
|
6674
|
-
return {
|
|
6675
|
-
minDeltaId: chunk.minDeltaId.toNumber(),
|
|
6676
|
-
maxDeltaId: chunk.maxDeltaId.toNumber(),
|
|
6677
|
-
x0: onChainParams.x0,
|
|
6678
|
-
y0: onChainParams.y0,
|
|
6679
|
-
deltaX: onChainParams.deltaX,
|
|
6680
|
-
deltaY: onChainParams.deltaY,
|
|
6681
|
-
bitFlag: onChainParams.bitFlag,
|
|
6682
|
-
favorXInActiveId,
|
|
6683
|
-
};
|
|
6684
|
-
});
|
|
6685
|
-
const chunkTotalMaxX = chunk.layers.reduce((s, layer) => s.add(layer.maxAmountX), new bn_js_1.default(0));
|
|
6686
|
-
const chunkTotalMaxY = chunk.layers.reduce((s, layer) => s.add(layer.maxAmountY), new bn_js_1.default(0));
|
|
6687
|
-
const binArrayInitIxs = yield this._initBinArraysForRange(connection, lbPair, dlmmPool, chunk.lowerBinId, chunk.upperBinId);
|
|
6688
|
-
rebuildTxGroups.push([
|
|
6689
|
-
...binArrayInitIxs.map(ix => ({
|
|
6690
|
-
label: 'init_bin_array',
|
|
6691
|
-
class: CLASS,
|
|
6692
|
-
instruction: ix,
|
|
6693
|
-
})),
|
|
6694
|
-
yield depositFn({
|
|
6695
|
-
position: params.newPosition,
|
|
6696
|
-
shouldClaimFee: false,
|
|
6697
|
-
shouldClaimReward: false,
|
|
6698
|
-
maxDepositXAmount: chunkTotalMaxX,
|
|
6699
|
-
maxDepositYAmount: chunkTotalMaxY,
|
|
6700
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
6701
|
-
addLiquidityParams: chunkAddLiquidityParams,
|
|
6702
|
-
origin: CLASS,
|
|
6703
|
-
}),
|
|
6704
|
-
]);
|
|
6705
|
-
}
|
|
6706
|
-
}
|
|
6707
|
-
// =========================================================================
|
|
6708
|
-
// PHASE 3: SWEEP REMAINING DUST
|
|
6709
|
-
// =========================================================================
|
|
6710
|
-
// After the main hybrid deposit, add one final deposit with undefined amounts
|
|
6711
|
-
// so the on-chain instruction reads the actual ATA balance and sweeps any dust.
|
|
6712
|
-
// Uses Spot distribution. Bin range follows the position's range (preserving
|
|
6713
|
-
// directional bias), clamped to 70 bins max (Meteora's single-call limit).
|
|
6714
|
-
const { sweepLower, sweepUpper } = this._calculateSweepBinRange(params.relativeBinRange.lowerRange, params.relativeBinRange.upperRange);
|
|
6715
|
-
const sweepIx = yield this.ix.meteoraDlmm.meteoraDlmmDepositRelativeAutomation({
|
|
6716
|
-
connection,
|
|
6717
|
-
userWallet: params.userWallet,
|
|
6718
|
-
lbPair,
|
|
6719
|
-
position: params.newPosition,
|
|
6720
|
-
tokenXMint,
|
|
6721
|
-
tokenYMint,
|
|
6722
|
-
tokenXProgram,
|
|
6723
|
-
tokenYProgram,
|
|
6724
|
-
activeId,
|
|
6725
|
-
relativeBinRange: { lowerRange: sweepLower, upperRange: sweepUpper },
|
|
6726
|
-
strategyType: 6, // SpotImBalanced — handles any X/Y ratio including single-sided
|
|
6727
|
-
optionalTokenXAmount: undefined, // sweep — use full ATA balance
|
|
6728
|
-
optionalTokenYAmount: undefined, // sweep — use full ATA balance
|
|
6729
|
-
checkRange: params.checkRange,
|
|
6730
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
6731
|
-
});
|
|
6732
|
-
rebuildTxGroups.push([
|
|
6733
|
-
{
|
|
6734
|
-
label: 'sweep_dust',
|
|
6735
|
-
class: CLASS,
|
|
6736
|
-
instruction: sweepIx,
|
|
6737
|
-
},
|
|
6738
|
-
]);
|
|
6739
|
-
// =========================================================================
|
|
6740
|
-
// Assemble final TX list
|
|
6741
|
-
// =========================================================================
|
|
6742
|
-
const allTxGroups = [...teardownTxGroups, ...rebuildTxGroups];
|
|
6743
|
-
const transactions = [];
|
|
6744
|
-
for (const txIxs of allTxGroups) {
|
|
6745
|
-
transactions.push(yield (0, functions_1.createTransactionMeta2)({
|
|
6746
|
-
payer: params.userWallet,
|
|
6747
|
-
addressLookupTableAddresses: addresses_1.GLOBAL_ALT,
|
|
6748
|
-
mainInstructions: txIxs,
|
|
6749
|
-
}));
|
|
6750
|
-
}
|
|
6751
|
-
return transactions;
|
|
6752
|
-
}
|
|
6753
|
-
catch (error) {
|
|
6754
|
-
console.error('=== REBALANCE HYBRID LIQUIDITY AUTOMATION ERROR ===');
|
|
6755
|
-
console.error('Error:', error instanceof Error ? error.message : String(error));
|
|
6756
|
-
console.error('Stack:', error instanceof Error ? error.stack : 'No stack trace');
|
|
6757
|
-
console.error('=== END ERROR LOG ===');
|
|
6758
|
-
throw error;
|
|
6759
|
-
}
|
|
6760
|
-
});
|
|
6761
|
-
}
|
|
6762
|
-
meteoraRebalanceHybridLiquidityV2Automation(_a) {
|
|
6763
|
-
return __awaiter(this, arguments, void 0, function* ({ connection, params, }) {
|
|
6764
|
-
var _b, _c;
|
|
6765
|
-
try {
|
|
6766
|
-
const MAX_INIT_WIDTH = 70;
|
|
6767
|
-
const MAX_EXTEND_LENGTH = 91;
|
|
6768
|
-
const MAX_BINS_PER_WITHDRAW_CHUNK = 175;
|
|
6769
|
-
const CHUNKS_PER_TRANSACTION = 3;
|
|
6770
|
-
const CLASS = 'meteoraRebalanceHybridLiquidityV2Automation';
|
|
6771
|
-
// --- Validate layers ---
|
|
6772
|
-
const layers = params.layers;
|
|
6773
|
-
if (layers.length === 0 || layers.length > 3) {
|
|
6774
|
-
throw new Error('layers must have 1-3 entries');
|
|
6775
|
-
}
|
|
6776
|
-
const sumX = layers.reduce((s, l) => s + l.x.percentage, 0);
|
|
6777
|
-
const sumY = layers.reduce((s, l) => s + l.y.percentage, 0);
|
|
6778
|
-
if (sumX !== 100 || sumY !== 100) {
|
|
6779
|
-
throw new Error(`Layer percentages must sum to 100 per side (got X=${sumX}, Y=${sumY})`);
|
|
6780
|
-
}
|
|
6781
|
-
const { lbPair, lbPairState, dlmmPool, lowerBinId: currentLowerBinId, upperBinId: currentUpperBinId, estimatedTotalX, estimatedTotalY, activeId, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, withdrawFn, baseRemainingAccountsInfo, } = yield this.resolvePositionContext({
|
|
6782
|
-
connection,
|
|
6783
|
-
userWallet: params.userWallet,
|
|
6784
|
-
position: params.currentPosition,
|
|
6785
|
-
compound: params.compound,
|
|
6786
|
-
targetActiveBin: params.targetActiveBin,
|
|
6787
|
-
});
|
|
6788
|
-
if (activeId < params.checkRange.lowerRange ||
|
|
6789
|
-
activeId > params.checkRange.upperRange) {
|
|
6790
|
-
throw new Error(`Active bin ${activeId} outside checkRange [${params.checkRange.lowerRange}, ${params.checkRange.upperRange}]`);
|
|
6791
|
-
}
|
|
6792
|
-
const newLowerBinId = activeId + params.relativeBinRange.lowerRange;
|
|
6793
|
-
const newUpperBinId = activeId + params.relativeBinRange.upperRange;
|
|
6794
|
-
const newWidth = newUpperBinId - newLowerBinId + 1;
|
|
6795
|
-
const currentWidth = currentUpperBinId - currentLowerBinId + 1;
|
|
6796
|
-
const maxBinsPerDepositChunk = newWidth === 69 ? 69 : 50;
|
|
6797
|
-
const useLayeredDepositsForSmallPosition = newWidth <= 69 && layers.length > 1;
|
|
6798
|
-
// =========================================================================
|
|
6799
|
-
// PHASE 1: TEARDOWN (withdraw from old position + close)
|
|
6800
|
-
// =========================================================================
|
|
6801
|
-
const teardownTxGroups = [];
|
|
6802
|
-
if (currentWidth <= MAX_BINS_PER_WITHDRAW_CHUNK) {
|
|
6803
|
-
teardownTxGroups.push([
|
|
6804
|
-
...(yield withdrawFn({
|
|
6805
|
-
position: params.currentPosition,
|
|
6806
|
-
minBinId: currentLowerBinId,
|
|
6807
|
-
maxBinId: currentUpperBinId,
|
|
6808
|
-
compound: params.compound,
|
|
6809
|
-
origin: CLASS,
|
|
6810
|
-
})),
|
|
6811
|
-
{
|
|
6812
|
-
label: 'close_position',
|
|
6813
|
-
class: CLASS,
|
|
6814
|
-
instruction: yield this.ix.meteoraDlmm.closePosition2Automation({
|
|
6815
|
-
connection,
|
|
6816
|
-
userWallet: params.userWallet,
|
|
6817
|
-
position: params.currentPosition,
|
|
6818
|
-
lbPair,
|
|
6819
|
-
}),
|
|
6820
|
-
},
|
|
6821
|
-
]);
|
|
6822
|
-
}
|
|
6823
|
-
else {
|
|
6824
|
-
const withdrawChunks = (0, liquidityStrategy_1.chunkBinRange)(currentLowerBinId, currentUpperBinId, MAX_BINS_PER_WITHDRAW_CHUNK);
|
|
6825
|
-
for (let i = 0; i < withdrawChunks.length; i++) {
|
|
6826
|
-
const chunk = withdrawChunks[i];
|
|
6827
|
-
const isLast = i === withdrawChunks.length - 1;
|
|
6828
|
-
const chunkIxs = [
|
|
6829
|
-
...(yield withdrawFn({
|
|
6830
|
-
position: params.currentPosition,
|
|
6831
|
-
minBinId: chunk.lowerBinId,
|
|
6832
|
-
maxBinId: chunk.upperBinId,
|
|
6833
|
-
compound: params.compound,
|
|
6834
|
-
origin: CLASS,
|
|
6835
|
-
})),
|
|
6836
|
-
];
|
|
6837
|
-
if (isLast) {
|
|
6838
|
-
chunkIxs.push({
|
|
6839
|
-
label: 'close_position',
|
|
6840
|
-
class: CLASS,
|
|
6841
|
-
instruction: yield this.ix.meteoraDlmm.closePosition2Automation({
|
|
6842
|
-
connection,
|
|
6843
|
-
userWallet: params.userWallet,
|
|
6844
|
-
position: params.currentPosition,
|
|
6845
|
-
lbPair,
|
|
6846
|
-
}),
|
|
6847
|
-
});
|
|
6848
|
-
}
|
|
6849
|
-
teardownTxGroups.push(chunkIxs);
|
|
6850
|
-
}
|
|
6851
|
-
}
|
|
6852
|
-
// =========================================================================
|
|
6853
|
-
// PHASE 2: REBUILD (init + extend + deposit with NEW add_liquidity_2 instruction)
|
|
6145
|
+
// PHASE 2: REBUILD (init + extend + deposit with NEW add_liquidity_2 instruction)
|
|
6854
6146
|
// =========================================================================
|
|
6855
6147
|
const effectiveAmountX = (_b = params.amountXOverride) !== null && _b !== void 0 ? _b : estimatedTotalX;
|
|
6856
6148
|
const effectiveAmountY = (_c = params.amountYOverride) !== null && _c !== void 0 ? _c : estimatedTotalY;
|
|
@@ -7062,224 +6354,6 @@ class Transactions {
|
|
|
7062
6354
|
}
|
|
7063
6355
|
});
|
|
7064
6356
|
}
|
|
7065
|
-
/**
|
|
7066
|
-
* Hybrid liquidity redeposit for automation: withdraw all liquidity from the same
|
|
7067
|
-
* position and re-deposit with independent X/Y distributions per layer.
|
|
7068
|
-
*
|
|
7069
|
-
* Unlike rebalance, the position is NOT closed or moved — the same bin range is reused.
|
|
7070
|
-
* Supports all position sizes (≤70, 71-149, ≥150 bins).
|
|
7071
|
-
*/
|
|
7072
|
-
meteoraRedepositHybridLiquidityAutomation(_a) {
|
|
7073
|
-
return __awaiter(this, arguments, void 0, function* ({ connection, params, }) {
|
|
7074
|
-
var _b, _c;
|
|
7075
|
-
try {
|
|
7076
|
-
const MAX_BINS_PER_WITHDRAW_CHUNK = 149;
|
|
7077
|
-
const MAX_BINS_PER_DEPOSIT_CHUNK = 149;
|
|
7078
|
-
const CLASS = 'meteoraRedepositHybridLiquidityAutomation';
|
|
7079
|
-
// --- Validate layers ---
|
|
7080
|
-
const layers = params.layers;
|
|
7081
|
-
if (layers.length === 0 || layers.length > 3) {
|
|
7082
|
-
throw new Error('layers must have 1-3 entries');
|
|
7083
|
-
}
|
|
7084
|
-
const sumX = layers.reduce((s, l) => s + l.x.percentage, 0);
|
|
7085
|
-
const sumY = layers.reduce((s, l) => s + l.y.percentage, 0);
|
|
7086
|
-
if (sumX !== 100 || sumY !== 100) {
|
|
7087
|
-
throw new Error(`Layer percentages must sum to 100 per side (got X=${sumX}, Y=${sumY})`);
|
|
7088
|
-
}
|
|
7089
|
-
const { lbPair, lbPairState, lowerBinId, upperBinId, estimatedTotalX, estimatedTotalY, activeId, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, withdrawFn, depositFn, } = yield this.resolvePositionContext({
|
|
7090
|
-
connection,
|
|
7091
|
-
userWallet: params.userWallet,
|
|
7092
|
-
position: params.position,
|
|
7093
|
-
compound: params.compound,
|
|
7094
|
-
targetActiveBin: undefined,
|
|
7095
|
-
skipClaim: true,
|
|
7096
|
-
});
|
|
7097
|
-
if (params.targetActiveBin !== undefined &&
|
|
7098
|
-
params.targetActiveBin !== activeId) {
|
|
7099
|
-
throw new Error(`targetActiveBin ${params.targetActiveBin} does not match live active bin ${activeId} for V2 redeposit`);
|
|
7100
|
-
}
|
|
7101
|
-
const positionWidth = upperBinId - lowerBinId + 1;
|
|
7102
|
-
const binStep = new bn_js_1.default(lbPairState.binStep);
|
|
7103
|
-
const effectiveAmountX = (_b = params.amountXOverride) !== null && _b !== void 0 ? _b : estimatedTotalX;
|
|
7104
|
-
const effectiveAmountY = (_c = params.amountYOverride) !== null && _c !== void 0 ? _c : estimatedTotalY;
|
|
7105
|
-
const favorXInActiveId = effectiveAmountY.isZero() && !effectiveAmountX.isZero();
|
|
7106
|
-
const minDeltaId = lowerBinId - activeId;
|
|
7107
|
-
const maxDeltaId = upperBinId - activeId;
|
|
7108
|
-
// =========================================================================
|
|
7109
|
-
// PHASE 1: WITHDRAW (no close — same position)
|
|
7110
|
-
// =========================================================================
|
|
7111
|
-
const withdrawTxGroups = [];
|
|
7112
|
-
if (positionWidth <= MAX_BINS_PER_WITHDRAW_CHUNK) {
|
|
7113
|
-
withdrawTxGroups.push([
|
|
7114
|
-
...(yield withdrawFn({
|
|
7115
|
-
position: params.position,
|
|
7116
|
-
minBinId: lowerBinId,
|
|
7117
|
-
maxBinId: upperBinId,
|
|
7118
|
-
compound: params.compound,
|
|
7119
|
-
origin: CLASS,
|
|
7120
|
-
})),
|
|
7121
|
-
]);
|
|
7122
|
-
}
|
|
7123
|
-
else {
|
|
7124
|
-
const withdrawChunks = (0, liquidityStrategy_1.chunkBinRange)(lowerBinId, upperBinId, MAX_BINS_PER_WITHDRAW_CHUNK);
|
|
7125
|
-
for (const chunk of withdrawChunks) {
|
|
7126
|
-
withdrawTxGroups.push([
|
|
7127
|
-
...(yield withdrawFn({
|
|
7128
|
-
position: params.position,
|
|
7129
|
-
minBinId: chunk.lowerBinId,
|
|
7130
|
-
maxBinId: chunk.upperBinId,
|
|
7131
|
-
compound: params.compound,
|
|
7132
|
-
origin: CLASS,
|
|
7133
|
-
})),
|
|
7134
|
-
]);
|
|
7135
|
-
}
|
|
7136
|
-
}
|
|
7137
|
-
// =========================================================================
|
|
7138
|
-
// PHASE 2: DEPOSIT (hybrid layers, no init/extend needed)
|
|
7139
|
-
// =========================================================================
|
|
7140
|
-
const strategyResults = (0, liquidityStrategy_1.distributionToHybridStrategy)({
|
|
7141
|
-
hybridDistribution: layers,
|
|
7142
|
-
amountX: effectiveAmountX,
|
|
7143
|
-
amountY: effectiveAmountY,
|
|
7144
|
-
minDeltaId: new bn_js_1.default(minDeltaId),
|
|
7145
|
-
maxDeltaId: new bn_js_1.default(maxDeltaId),
|
|
7146
|
-
binStep,
|
|
7147
|
-
activeId: new bn_js_1.default(activeId),
|
|
7148
|
-
});
|
|
7149
|
-
const depositTxGroups = [];
|
|
7150
|
-
if (positionWidth <= MAX_BINS_PER_DEPOSIT_CHUNK) {
|
|
7151
|
-
// Single deposit TX — all layers merged into one rebalanceLiquidity call.
|
|
7152
|
-
// Merge all layers into a single AddLiquidityParams entry by summing x0/y0/deltaX/deltaY.
|
|
7153
|
-
// Meteora's rebalanceLiquidity requires non-overlapping ranges across entries; since all
|
|
7154
|
-
// layers share the same full range, they must be merged into one. The formula is linear
|
|
7155
|
-
// so summing params is equivalent to summing per-bin amounts from each layer.
|
|
7156
|
-
const mergedLayer = strategyResults.reduce((acc, l) => ({
|
|
7157
|
-
x0: acc.x0.add(l.x0),
|
|
7158
|
-
y0: acc.y0.add(l.y0),
|
|
7159
|
-
deltaX: acc.deltaX.add(l.deltaX),
|
|
7160
|
-
deltaY: acc.deltaY.add(l.deltaY),
|
|
7161
|
-
}), {
|
|
7162
|
-
x0: new bn_js_1.default(0),
|
|
7163
|
-
y0: new bn_js_1.default(0),
|
|
7164
|
-
deltaX: new bn_js_1.default(0),
|
|
7165
|
-
deltaY: new bn_js_1.default(0),
|
|
7166
|
-
});
|
|
7167
|
-
const mergedP = (0, liquidityStrategy_1.buildBitFlagAndNegateStrategyParameters)(mergedLayer.x0, mergedLayer.y0, mergedLayer.deltaX, mergedLayer.deltaY);
|
|
7168
|
-
const allAddLiquidityParams = [
|
|
7169
|
-
{
|
|
7170
|
-
minDeltaId,
|
|
7171
|
-
maxDeltaId,
|
|
7172
|
-
x0: mergedP.x0,
|
|
7173
|
-
y0: mergedP.y0,
|
|
7174
|
-
deltaX: mergedP.deltaX,
|
|
7175
|
-
deltaY: mergedP.deltaY,
|
|
7176
|
-
bitFlag: mergedP.bitFlag,
|
|
7177
|
-
favorXInActiveId,
|
|
7178
|
-
},
|
|
7179
|
-
];
|
|
7180
|
-
const mergedBinsAmounts = (0, liquidityStrategy_1.toAmountIntoBins)(new bn_js_1.default(activeId), new bn_js_1.default(minDeltaId), new bn_js_1.default(maxDeltaId), mergedLayer.deltaX, mergedLayer.deltaY, mergedLayer.x0, mergedLayer.y0, binStep, favorXInActiveId);
|
|
7181
|
-
const totalMaxX = mergedBinsAmounts.reduce((s, b) => s.add(b.amountX), new bn_js_1.default(0));
|
|
7182
|
-
const totalMaxY = mergedBinsAmounts.reduce((s, b) => s.add(b.amountY), new bn_js_1.default(0));
|
|
7183
|
-
depositTxGroups.push([
|
|
7184
|
-
yield depositFn({
|
|
7185
|
-
position: params.position,
|
|
7186
|
-
shouldClaimFee: false,
|
|
7187
|
-
shouldClaimReward: false,
|
|
7188
|
-
maxDepositXAmount: totalMaxX,
|
|
7189
|
-
maxDepositYAmount: totalMaxY,
|
|
7190
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
7191
|
-
addLiquidityParams: allAddLiquidityParams,
|
|
7192
|
-
origin: CLASS,
|
|
7193
|
-
}),
|
|
7194
|
-
]);
|
|
7195
|
-
}
|
|
7196
|
-
else {
|
|
7197
|
-
// Chunked deposit — one TX per chunk, all layers per chunk
|
|
7198
|
-
const depositChunks = (0, liquidityStrategy_1.chunkHybridDepositParameters)(strategyResults, new bn_js_1.default(minDeltaId), new bn_js_1.default(maxDeltaId), new bn_js_1.default(activeId), binStep, MAX_BINS_PER_DEPOSIT_CHUNK, favorXInActiveId);
|
|
7199
|
-
for (const chunk of depositChunks) {
|
|
7200
|
-
const chunkAddLiquidityParams = chunk.layers.map(layer => {
|
|
7201
|
-
const onChainParams = (0, liquidityStrategy_1.buildBitFlagAndNegateStrategyParameters)(layer.params.x0, layer.params.y0, layer.params.deltaX, layer.params.deltaY);
|
|
7202
|
-
return {
|
|
7203
|
-
minDeltaId: chunk.minDeltaId.toNumber(),
|
|
7204
|
-
maxDeltaId: chunk.maxDeltaId.toNumber(),
|
|
7205
|
-
x0: onChainParams.x0,
|
|
7206
|
-
y0: onChainParams.y0,
|
|
7207
|
-
deltaX: onChainParams.deltaX,
|
|
7208
|
-
deltaY: onChainParams.deltaY,
|
|
7209
|
-
bitFlag: onChainParams.bitFlag,
|
|
7210
|
-
favorXInActiveId,
|
|
7211
|
-
};
|
|
7212
|
-
});
|
|
7213
|
-
const chunkTotalMaxX = chunk.layers.reduce((s, layer) => s.add(layer.maxAmountX), new bn_js_1.default(0));
|
|
7214
|
-
const chunkTotalMaxY = chunk.layers.reduce((s, layer) => s.add(layer.maxAmountY), new bn_js_1.default(0));
|
|
7215
|
-
depositTxGroups.push([
|
|
7216
|
-
yield depositFn({
|
|
7217
|
-
position: params.position,
|
|
7218
|
-
shouldClaimFee: false,
|
|
7219
|
-
shouldClaimReward: false,
|
|
7220
|
-
maxDepositXAmount: chunkTotalMaxX,
|
|
7221
|
-
maxDepositYAmount: chunkTotalMaxY,
|
|
7222
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
7223
|
-
addLiquidityParams: chunkAddLiquidityParams,
|
|
7224
|
-
origin: CLASS,
|
|
7225
|
-
}),
|
|
7226
|
-
]);
|
|
7227
|
-
}
|
|
7228
|
-
}
|
|
7229
|
-
// =========================================================================
|
|
7230
|
-
// PHASE 3: SWEEP REMAINING DUST
|
|
7231
|
-
// =========================================================================
|
|
7232
|
-
// After the main hybrid deposit, add one final deposit with undefined amounts
|
|
7233
|
-
// so the on-chain instruction reads the actual ATA balance and sweeps any dust.
|
|
7234
|
-
// Uses Spot distribution. Bin range follows the position's range (preserving
|
|
7235
|
-
// directional bias), clamped to 70 bins max (Meteora's single-call limit).
|
|
7236
|
-
const { sweepLower, sweepUpper } = this._calculateSweepBinRange(minDeltaId, maxDeltaId);
|
|
7237
|
-
const sweepIx = yield this.ix.meteoraDlmm.meteoraDlmmDepositRelativeAutomation({
|
|
7238
|
-
connection,
|
|
7239
|
-
userWallet: params.userWallet,
|
|
7240
|
-
lbPair,
|
|
7241
|
-
position: params.position,
|
|
7242
|
-
tokenXMint,
|
|
7243
|
-
tokenYMint,
|
|
7244
|
-
tokenXProgram,
|
|
7245
|
-
tokenYProgram,
|
|
7246
|
-
activeId,
|
|
7247
|
-
relativeBinRange: { lowerRange: sweepLower, upperRange: sweepUpper },
|
|
7248
|
-
strategyType: 6, // SpotImBalanced — handles any X/Y ratio including single-sided
|
|
7249
|
-
optionalTokenXAmount: undefined, // sweep — use full ATA balance
|
|
7250
|
-
optionalTokenYAmount: undefined, // sweep — use full ATA balance
|
|
7251
|
-
pdaTokenType: types_1.TokenType.ATA,
|
|
7252
|
-
});
|
|
7253
|
-
depositTxGroups.push([
|
|
7254
|
-
{
|
|
7255
|
-
label: 'sweep_dust',
|
|
7256
|
-
class: CLASS,
|
|
7257
|
-
instruction: sweepIx,
|
|
7258
|
-
},
|
|
7259
|
-
]);
|
|
7260
|
-
// =========================================================================
|
|
7261
|
-
// Assemble final TX list
|
|
7262
|
-
// =========================================================================
|
|
7263
|
-
const allTxGroups = [...withdrawTxGroups, ...depositTxGroups];
|
|
7264
|
-
const transactions = [];
|
|
7265
|
-
for (const txIxs of allTxGroups) {
|
|
7266
|
-
transactions.push(yield (0, functions_1.createTransactionMeta2)({
|
|
7267
|
-
payer: params.userWallet,
|
|
7268
|
-
addressLookupTableAddresses: addresses_1.GLOBAL_ALT,
|
|
7269
|
-
mainInstructions: txIxs,
|
|
7270
|
-
}));
|
|
7271
|
-
}
|
|
7272
|
-
return transactions;
|
|
7273
|
-
}
|
|
7274
|
-
catch (error) {
|
|
7275
|
-
console.error('=== REDEPOSIT HYBRID LIQUIDITY AUTOMATION ERROR ===');
|
|
7276
|
-
console.error('Error:', error instanceof Error ? error.message : String(error));
|
|
7277
|
-
console.error('Stack:', error instanceof Error ? error.stack : 'No stack trace');
|
|
7278
|
-
console.error('=== END ERROR LOG ===');
|
|
7279
|
-
throw error;
|
|
7280
|
-
}
|
|
7281
|
-
});
|
|
7282
|
-
}
|
|
7283
6357
|
meteoraRedepositHybridLiquidityV2Automation(_a) {
|
|
7284
6358
|
return __awaiter(this, arguments, void 0, function* ({ connection, params, }) {
|
|
7285
6359
|
var _b, _c;
|
|
@@ -7306,7 +6380,7 @@ class Transactions {
|
|
|
7306
6380
|
skipClaim: true,
|
|
7307
6381
|
});
|
|
7308
6382
|
const positionWidth = upperBinId - lowerBinId + 1;
|
|
7309
|
-
const maxBinsPerDepositChunk = positionWidth
|
|
6383
|
+
const maxBinsPerDepositChunk = positionWidth <= 69 ? 69 : 45;
|
|
7310
6384
|
const useLayeredDepositsForSmallPosition = positionWidth <= 69 && layers.length > 1;
|
|
7311
6385
|
const effectiveAmountX = (_b = params.amountXOverride) !== null && _b !== void 0 ? _b : estimatedTotalX;
|
|
7312
6386
|
const effectiveAmountY = (_c = params.amountYOverride) !== null && _c !== void 0 ? _c : estimatedTotalY;
|