@hawksightco/hawk-sdk 1.3.265 → 1.3.267
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/addresses.d.ts +37 -0
- package/dist/addresses.d.ts.map +1 -0
- package/dist/addresses.js +84 -0
- package/dist/anchor.d.ts +22 -0
- package/dist/anchor.d.ts.map +1 -0
- package/dist/anchor.js +121 -0
- package/dist/classes/AltStorage.d.ts +29 -0
- package/dist/classes/AltStorage.d.ts.map +1 -0
- package/dist/classes/AltStorage.js +58 -0
- package/dist/classes/Atomicity.d.ts +34 -0
- package/dist/classes/Atomicity.d.ts.map +1 -0
- package/dist/classes/Atomicity.js +110 -0
- package/dist/classes/Client.d.ts +35 -0
- package/dist/classes/Client.d.ts.map +1 -0
- package/dist/classes/Client.js +66 -0
- package/dist/classes/CombineTransactions.d.ts +11 -0
- package/dist/classes/CombineTransactions.d.ts.map +1 -0
- package/dist/classes/CombineTransactions.js +58 -0
- package/dist/classes/CreateTxMetadata.d.ts +100 -0
- package/dist/classes/CreateTxMetadata.d.ts.map +1 -0
- package/dist/classes/CreateTxMetadata.js +415 -0
- package/dist/classes/General.d.ts +87 -0
- package/dist/classes/General.d.ts.map +1 -0
- package/dist/classes/General.js +176 -0
- package/dist/classes/GeneralUtility.d.ts +79 -0
- package/dist/classes/GeneralUtility.d.ts.map +1 -0
- package/dist/classes/GeneralUtility.js +121 -0
- package/dist/classes/HawkAPI.d.ts +122 -0
- package/dist/classes/HawkAPI.d.ts.map +1 -0
- package/dist/classes/HawkAPI.js +169 -0
- package/dist/classes/Health.d.ts +29 -0
- package/dist/classes/Health.d.ts.map +1 -0
- package/dist/classes/Health.js +48 -0
- package/dist/classes/JupiterAlts.d.ts +37 -0
- package/dist/classes/JupiterAlts.d.ts.map +1 -0
- package/dist/classes/JupiterAlts.js +114 -0
- package/dist/classes/JupiterSwap.d.ts +21 -0
- package/dist/classes/JupiterSwap.d.ts.map +1 -0
- package/dist/classes/JupiterSwap.js +40 -0
- package/dist/classes/Logging.d.ts +13 -0
- package/dist/classes/Logging.d.ts.map +1 -0
- package/dist/classes/Logging.js +50 -0
- package/dist/classes/MultiTransaction.d.ts +75 -0
- package/dist/classes/MultiTransaction.d.ts.map +1 -0
- package/dist/classes/MultiTransaction.js +296 -0
- package/dist/classes/RaydiumSDK.d.ts +67 -0
- package/dist/classes/RaydiumSDK.d.ts.map +1 -0
- package/dist/classes/RaydiumSDK.js +206 -0
- package/dist/classes/Search.d.ts +100 -0
- package/dist/classes/Search.d.ts.map +1 -0
- package/dist/classes/Search.js +216 -0
- package/dist/classes/SimpleIxGenerator.d.ts +57 -0
- package/dist/classes/SimpleIxGenerator.d.ts.map +1 -0
- package/dist/classes/SimpleIxGenerator.js +62 -0
- package/dist/classes/SimplePdaGenerator.d.ts +28 -0
- package/dist/classes/SimplePdaGenerator.d.ts.map +1 -0
- package/dist/classes/SimplePdaGenerator.js +33 -0
- package/dist/classes/Transaction.d.ts +229 -0
- package/dist/classes/Transaction.d.ts.map +1 -0
- package/dist/classes/Transaction.js +643 -0
- package/dist/classes/Transaction2.d.ts +107 -0
- package/dist/classes/Transaction2.d.ts.map +1 -0
- package/dist/classes/Transaction2.js +249 -0
- package/dist/classes/Transaction3.d.ts +165 -0
- package/dist/classes/Transaction3.d.ts.map +1 -0
- package/dist/classes/Transaction3.js +416 -0
- package/dist/classes/TransactionBatchExecute.d.ts +163 -0
- package/dist/classes/TransactionBatchExecute.d.ts.map +1 -0
- package/dist/classes/TransactionBatchExecute.js +466 -0
- package/dist/classes/TransactionBatchExecute2.d.ts +99 -0
- package/dist/classes/TransactionBatchExecute2.d.ts.map +1 -0
- package/dist/classes/TransactionBatchExecute2.js +357 -0
- package/dist/classes/Transactions.d.ts +586 -0
- package/dist/classes/Transactions.d.ts.map +1 -0
- package/dist/classes/Transactions.js +7667 -0
- package/dist/classes/TxGenerator.d.ts +350 -0
- package/dist/classes/TxGenerator.d.ts.map +1 -0
- package/dist/classes/TxGenerator.js +1957 -0
- package/dist/classes/TxGeneratorAutomations.d.ts +186 -0
- package/dist/classes/TxGeneratorAutomations.d.ts.map +1 -0
- package/dist/classes/TxGeneratorAutomations.js +897 -0
- package/dist/classes/Util.d.ts +87 -0
- package/dist/classes/Util.d.ts.map +1 -0
- package/dist/classes/Util.js +148 -0
- package/dist/classes/account-cache/AccountCache.d.ts +54 -0
- package/dist/classes/account-cache/AccountCache.d.ts.map +1 -0
- package/dist/classes/account-cache/AccountCache.js +143 -0
- package/dist/classes/account-cache/MintCache.d.ts +33 -0
- package/dist/classes/account-cache/MintCache.d.ts.map +1 -0
- package/dist/classes/account-cache/MintCache.js +47 -0
- package/dist/classes/account-cache/TokenCache.d.ts +33 -0
- package/dist/classes/account-cache/TokenCache.d.ts.map +1 -0
- package/dist/classes/account-cache/TokenCache.js +47 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +96 -0
- package/dist/functions.d.ts +514 -0
- package/dist/functions.d.ts.map +1 -0
- package/dist/functions.js +1636 -0
- package/dist/hawksight.d.ts +53 -0
- package/dist/hawksight.d.ts.map +1 -0
- package/dist/hawksight.js +328 -0
- package/dist/hsToMeteora.d.ts +31 -0
- package/dist/hsToMeteora.d.ts.map +1 -0
- package/dist/hsToMeteora.js +3175 -0
- package/dist/idl/iyf-extension-idl.d.ts +14583 -0
- package/dist/idl/iyf-extension-idl.d.ts.map +1 -0
- package/dist/idl/iyf-extension-idl.js +14578 -0
- package/dist/idl/iyf-extension-wrapper.d.ts +112 -0
- package/dist/idl/iyf-extension-wrapper.d.ts.map +1 -0
- package/dist/idl/iyf-extension-wrapper.js +2 -0
- package/dist/idl/iyf-main-idl.d.ts +12078 -0
- package/dist/idl/iyf-main-idl.d.ts.map +1 -0
- package/dist/idl/iyf-main-idl.js +12073 -0
- package/dist/idl/iyf-main-wrapper.d.ts +112 -0
- package/dist/idl/iyf-main-wrapper.d.ts.map +1 -0
- package/dist/idl/iyf-main-wrapper.js +2 -0
- package/dist/idl/jupiter-idl.d.ts +3063 -0
- package/dist/idl/jupiter-idl.d.ts.map +1 -0
- package/dist/idl/jupiter-idl.js +3061 -0
- package/dist/idl/meteora-idl.d.ts +7371 -0
- package/dist/idl/meteora-idl.d.ts.map +1 -0
- package/dist/idl/meteora-idl.js +7372 -0
- package/dist/idl/orca-idl.d.ts +3833 -0
- package/dist/idl/orca-idl.d.ts.map +1 -0
- package/dist/idl/orca-idl.js +3834 -0
- package/dist/idl/raydium-idl.d.ts +3054 -0
- package/dist/idl/raydium-idl.d.ts.map +1 -0
- package/dist/idl/raydium-idl.js +3055 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/ixGenerator/IyfExtensionIxGenerator.d.ts +126 -0
- package/dist/ixGenerator/IyfExtensionIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/IyfExtensionIxGenerator.js +467 -0
- package/dist/ixGenerator/IyfMainIxGenerator.d.ts +330 -0
- package/dist/ixGenerator/IyfMainIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/IyfMainIxGenerator.js +1239 -0
- package/dist/ixGenerator/MeteoraDlmmIxGenerator.d.ts +685 -0
- package/dist/ixGenerator/MeteoraDlmmIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/MeteoraDlmmIxGenerator.js +3008 -0
- package/dist/ixGenerator/OrcaIxGenerator.d.ts +119 -0
- package/dist/ixGenerator/OrcaIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/OrcaIxGenerator.js +438 -0
- package/dist/ixGenerator/RaydiumIxGenerator.d.ts +99 -0
- package/dist/ixGenerator/RaydiumIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/RaydiumIxGenerator.js +558 -0
- package/dist/ixGenerator/UtilIxGenerator.d.ts +20 -0
- package/dist/ixGenerator/UtilIxGenerator.d.ts.map +1 -0
- package/dist/ixGenerator/UtilIxGenerator.js +25 -0
- package/dist/meteora/index.d.ts +2 -0
- package/dist/meteora/index.d.ts.map +1 -0
- package/dist/meteora/index.js +17 -0
- package/dist/meteora/liquidityStrategy.d.ts +408 -0
- package/dist/meteora/liquidityStrategy.d.ts.map +1 -0
- package/dist/meteora/liquidityStrategy.js +1325 -0
- package/dist/meteora.d.ts +669 -0
- package/dist/meteora.d.ts.map +1 -0
- package/dist/meteora.js +1932 -0
- package/dist/orca.d.ts +57 -0
- package/dist/orca.d.ts.map +1 -0
- package/dist/orca.js +123 -0
- package/dist/pdaGenerator/HawksightPdaGenerator.d.ts +29 -0
- package/dist/pdaGenerator/HawksightPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/HawksightPdaGenerator.js +75 -0
- package/dist/pdaGenerator/MeteoraPdaGenerator.d.ts +76 -0
- package/dist/pdaGenerator/MeteoraPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/MeteoraPdaGenerator.js +166 -0
- package/dist/pdaGenerator/OrcaPdaGenerator.d.ts +23 -0
- package/dist/pdaGenerator/OrcaPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/OrcaPdaGenerator.js +68 -0
- package/dist/pdaGenerator/RaydiumPdaGenerator.d.ts +49 -0
- package/dist/pdaGenerator/RaydiumPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/RaydiumPdaGenerator.js +114 -0
- package/dist/pdaGenerator/UtilPdaGenerator.d.ts +8 -0
- package/dist/pdaGenerator/UtilPdaGenerator.d.ts.map +1 -0
- package/dist/pdaGenerator/UtilPdaGenerator.js +51 -0
- package/dist/types.d.ts +1104 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +95 -0
- package/package.json +6 -5
|
@@ -0,0 +1,3008 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.MeteoraDlmmIxGenerator = exports.StrategyType = void 0;
|
|
49
|
+
exports.mapOldStrategyTypeToNew = mapOldStrategyTypeToNew;
|
|
50
|
+
exports.buildBaseClosePosition2AutomationIx = buildBaseClosePosition2AutomationIx;
|
|
51
|
+
const web3 = __importStar(require("@solana/web3.js"));
|
|
52
|
+
const anchor_1 = require("../anchor");
|
|
53
|
+
const functions_1 = require("../functions");
|
|
54
|
+
const addresses_1 = require("../addresses");
|
|
55
|
+
const meteora_1 = require("../meteora");
|
|
56
|
+
const dlmm_1 = __importDefault(require("@meteora-ag/dlmm"));
|
|
57
|
+
const types_1 = require("../types");
|
|
58
|
+
const bn_js_1 = __importDefault(require("bn.js"));
|
|
59
|
+
const AccountCache_1 = require("../classes/account-cache/AccountCache");
|
|
60
|
+
const MintCache_1 = require("../classes/account-cache/MintCache");
|
|
61
|
+
const util = __importStar(require("../functions"));
|
|
62
|
+
/**
|
|
63
|
+
* Meteora event authority
|
|
64
|
+
*/
|
|
65
|
+
const METEORA_EVENT_AUTHORITY = new web3.PublicKey('D1ZN9Wj1fRSUQfCjhvnu1hqDMT7hzjzBBpi12nVniYD6');
|
|
66
|
+
/**
|
|
67
|
+
* Meteora Program ID
|
|
68
|
+
*/
|
|
69
|
+
const METEORA_DLMM_PROGRAM = new web3.PublicKey('LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo');
|
|
70
|
+
var StrategyType;
|
|
71
|
+
(function (StrategyType) {
|
|
72
|
+
StrategyType[StrategyType["Spot"] = 0] = "Spot";
|
|
73
|
+
StrategyType[StrategyType["Curve"] = 1] = "Curve";
|
|
74
|
+
StrategyType[StrategyType["BidAsk"] = 2] = "BidAsk";
|
|
75
|
+
})(StrategyType || (exports.StrategyType = StrategyType = {}));
|
|
76
|
+
// Backwards-compatible mapping from old StrategyType to new StrategyType
|
|
77
|
+
function mapOldStrategyTypeToNew(oldStrategyType) {
|
|
78
|
+
// Handle the old enum values (0-8) and map them to the new simplified enum
|
|
79
|
+
switch (oldStrategyType) {
|
|
80
|
+
case 0: // SpotOneSide
|
|
81
|
+
case 3: // SpotBalanced
|
|
82
|
+
case 6: // SpotImBalanced
|
|
83
|
+
return StrategyType.Spot;
|
|
84
|
+
case 1: // CurveOneSide
|
|
85
|
+
case 4: // CurveBalanced
|
|
86
|
+
case 7: // CurveImBalanced
|
|
87
|
+
return StrategyType.Curve;
|
|
88
|
+
case 2: // BidAskOneSide
|
|
89
|
+
case 5: // BidAskBalanced
|
|
90
|
+
case 8: // BidAskImBalanced
|
|
91
|
+
return StrategyType.BidAsk;
|
|
92
|
+
default:
|
|
93
|
+
// Default fallback
|
|
94
|
+
return StrategyType.Spot;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function buildBaseClosePosition2AutomationIx({ userPda, hawksightAuthority, authority, position, lbPair, fuelAccount, isHawkRefund, }) {
|
|
98
|
+
return new web3.TransactionInstruction({
|
|
99
|
+
data: Buffer.concat([
|
|
100
|
+
Buffer.from(util.sighash('meteora_dlmm_base_close_position_automation', undefined, true)),
|
|
101
|
+
Buffer.from([isHawkRefund ? 1 : 0]),
|
|
102
|
+
]),
|
|
103
|
+
keys: [
|
|
104
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
105
|
+
{ pubkey: hawksightAuthority, isSigner: true, isWritable: true },
|
|
106
|
+
{ pubkey: authority, isSigner: false, isWritable: true },
|
|
107
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
108
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
109
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: false },
|
|
110
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
111
|
+
{ pubkey: fuelAccount, isSigner: false, isWritable: true },
|
|
112
|
+
],
|
|
113
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Meteora related instructions executed via iyf extension or iyf main
|
|
118
|
+
*/
|
|
119
|
+
class MeteoraDlmmIxGenerator {
|
|
120
|
+
constructor(ix, pda) {
|
|
121
|
+
this.ix = ix;
|
|
122
|
+
this.pda = pda;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Initialize a Meteora DLMM position via IYF Main's meteora dynamic CPI.
|
|
126
|
+
*
|
|
127
|
+
* This is the raw Meteora initializePosition instruction invoked through IYF Main.
|
|
128
|
+
*
|
|
129
|
+
* @param connection - Solana connection
|
|
130
|
+
* @param params - Initialize position parameters (Meteora-aligned: lowerBinId, width)
|
|
131
|
+
* @returns TransactionInstruction for initializing the position
|
|
132
|
+
*/
|
|
133
|
+
initializePosition(_a) {
|
|
134
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, position, lowerBinId, width, }) {
|
|
135
|
+
// Initialize anchor
|
|
136
|
+
anchor_1.Anchor.initialize(connection);
|
|
137
|
+
// Generate user PDA
|
|
138
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
139
|
+
// Build instruction data: sighash + lowerBinId (i32) + width (i32)
|
|
140
|
+
const lowerBinIdBuffer = Buffer.alloc(4);
|
|
141
|
+
lowerBinIdBuffer.writeInt32LE(lowerBinId, 0);
|
|
142
|
+
const widthBuffer = Buffer.alloc(4);
|
|
143
|
+
widthBuffer.writeInt32LE(width, 0);
|
|
144
|
+
// Build raw Meteora instruction (accounts only - no hawksight wrapper accounts)
|
|
145
|
+
// meteoraDynamicCpi will prepend userPda and authority
|
|
146
|
+
const meteoraIx = new web3.TransactionInstruction({
|
|
147
|
+
data: Buffer.concat([
|
|
148
|
+
Buffer.from(util.sighash('initialize_position')),
|
|
149
|
+
lowerBinIdBuffer,
|
|
150
|
+
widthBuffer,
|
|
151
|
+
]),
|
|
152
|
+
keys: [
|
|
153
|
+
{ pubkey: userWallet, isSigner: false, isWritable: true }, // payer (Mutable, Signer - signed by IYF Main)
|
|
154
|
+
{ pubkey: position, isSigner: true, isWritable: true }, // position (Mutable, Signer)
|
|
155
|
+
{ pubkey: lbPair, isSigner: false, isWritable: false }, // lbPair
|
|
156
|
+
{ pubkey: userPda, isSigner: false, isWritable: false }, // owner (Signer - signed by IYF Main)
|
|
157
|
+
{
|
|
158
|
+
pubkey: web3.SystemProgram.programId,
|
|
159
|
+
isSigner: false,
|
|
160
|
+
isWritable: false,
|
|
161
|
+
}, // systemProgram
|
|
162
|
+
{ pubkey: web3.SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // rent
|
|
163
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: false }, // eventAuthority (PDA)
|
|
164
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false }, // program
|
|
165
|
+
],
|
|
166
|
+
programId: METEORA_DLMM_PROGRAM,
|
|
167
|
+
});
|
|
168
|
+
return yield this.ix.iyfMain.meteoraDynamicCpi({
|
|
169
|
+
connection,
|
|
170
|
+
userWallet,
|
|
171
|
+
meteoraIx,
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
initializePositionAutomation(connection_1, _a) {
|
|
176
|
+
return __awaiter(this, arguments, void 0, function* (connection, { userWallet, lbPair, position, lowerBinId, upperBinId, }) {
|
|
177
|
+
// Initialize anchor
|
|
178
|
+
anchor_1.Anchor.initialize(connection);
|
|
179
|
+
// Generate user pda
|
|
180
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
181
|
+
// Generate instruction
|
|
182
|
+
const width = upperBinId - lowerBinId + 1;
|
|
183
|
+
// @ts-ignore
|
|
184
|
+
const iyfExtensionIx = yield anchor_1.Anchor.instance()
|
|
185
|
+
.iyfExtension.methods.meteoraDlmmInitializePositionAutomation(lowerBinId, width)
|
|
186
|
+
.accounts({
|
|
187
|
+
farm: addresses_1.USDC_FARM,
|
|
188
|
+
userPda,
|
|
189
|
+
authority: userWallet,
|
|
190
|
+
iyfProgram: addresses_1.IYF_MAIN,
|
|
191
|
+
hawksightAuthority: addresses_1.HS_AUTHORITY,
|
|
192
|
+
position,
|
|
193
|
+
lbPair,
|
|
194
|
+
systemProgram: web3.SystemProgram.programId,
|
|
195
|
+
rent: web3.SYSVAR_RENT_PUBKEY,
|
|
196
|
+
eventAuthority: METEORA_EVENT_AUTHORITY,
|
|
197
|
+
meteoraDlmmProgram: METEORA_DLMM_PROGRAM,
|
|
198
|
+
})
|
|
199
|
+
.instruction();
|
|
200
|
+
// Set position to writable
|
|
201
|
+
iyfExtensionIx.keys = iyfExtensionIx.keys.map(meta => {
|
|
202
|
+
if (meta.pubkey === position) {
|
|
203
|
+
meta.isWritable = true;
|
|
204
|
+
}
|
|
205
|
+
return meta;
|
|
206
|
+
});
|
|
207
|
+
return this.ix.iyfMain.iyfExtensionExecute(connection, {
|
|
208
|
+
userWallet,
|
|
209
|
+
iyfExtensionIx,
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
initializePositionRelativeAutomation(connection_1, _a) {
|
|
214
|
+
return __awaiter(this, arguments, void 0, function* (connection, { userWallet, lbPair, position, relativeLowerBinId, width, useFuelAccount, }) {
|
|
215
|
+
// Initialize anchor
|
|
216
|
+
anchor_1.Anchor.initialize(connection);
|
|
217
|
+
// Width > 70 is invalid (will error on-chain)
|
|
218
|
+
if (width > 70) {
|
|
219
|
+
throw new Error('Width exceeds maximum allowed 70 bins');
|
|
220
|
+
}
|
|
221
|
+
// Generate user pda
|
|
222
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
223
|
+
// Generate instruction
|
|
224
|
+
return this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
225
|
+
userPda,
|
|
226
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
227
|
+
ix: new web3.TransactionInstruction({
|
|
228
|
+
data: Buffer.concat([
|
|
229
|
+
Buffer.from(util.sighash('meteora_dlmm_initialize_position_relative_automation')),
|
|
230
|
+
new bn_js_1.default(relativeLowerBinId).toTwos(16).toArrayLike(Buffer, 'le', 2),
|
|
231
|
+
Buffer.from([width]),
|
|
232
|
+
]),
|
|
233
|
+
keys: [
|
|
234
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
235
|
+
{ pubkey: addresses_1.HS_AUTHORITY, isSigner: true, isWritable: false },
|
|
236
|
+
{ pubkey: position, isSigner: true, isWritable: true },
|
|
237
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
238
|
+
{
|
|
239
|
+
pubkey: web3.SystemProgram.programId,
|
|
240
|
+
isSigner: false,
|
|
241
|
+
isWritable: false,
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
pubkey: web3.SYSVAR_RENT_PUBKEY,
|
|
245
|
+
isSigner: false,
|
|
246
|
+
isWritable: false,
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
pubkey: METEORA_EVENT_AUTHORITY,
|
|
250
|
+
isSigner: false,
|
|
251
|
+
isWritable: true,
|
|
252
|
+
},
|
|
253
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: true },
|
|
254
|
+
...(useFuelAccount
|
|
255
|
+
? [
|
|
256
|
+
{
|
|
257
|
+
pubkey: (0, functions_1.generateFuelAccount)(userWallet),
|
|
258
|
+
isSigner: false,
|
|
259
|
+
isWritable: true,
|
|
260
|
+
},
|
|
261
|
+
]
|
|
262
|
+
: []),
|
|
263
|
+
],
|
|
264
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
265
|
+
}),
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Add liquidity to an existing Meteora DLMM position using strategy parameters.
|
|
271
|
+
* This is the automation version that uses V2 execution (meteora_dlmm_deposit_2_automation).
|
|
272
|
+
*
|
|
273
|
+
* Key differences from depositAutomation:
|
|
274
|
+
* - Uses iyfExtensionExecuteV2 with Anchor-based instruction building
|
|
275
|
+
* - Supports remainingAccountsInfo for Token2022 transfer hooks
|
|
276
|
+
* - Authority is HS_AUTHORITY (automation wallet)
|
|
277
|
+
* - Does not require binArrayLower/binArrayUpper (bin arrays are auto-derived or created separately)
|
|
278
|
+
*
|
|
279
|
+
* @param connection - Solana connection
|
|
280
|
+
* @param params - AddLiquidityByStrategy2AutomationParams parameters
|
|
281
|
+
* @returns TransactionInstruction for adding liquidity
|
|
282
|
+
*/
|
|
283
|
+
meteoraDlmmDepositRelativeAutomation(_a) {
|
|
284
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, position, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, activeId, relativeBinRange, strategyType, optionalTokenXAmount, optionalTokenYAmount, checkRange, remainingAccountsInfo, pdaTokenType, positionIsSigner = false, }) {
|
|
285
|
+
var _b, _c, _d, _e;
|
|
286
|
+
// Initialize anchor
|
|
287
|
+
anchor_1.Anchor.initialize(connection);
|
|
288
|
+
// Derive reserves from the ACTUAL lbPair (not the one passed in, which may be incorrect)
|
|
289
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenXMint, lbPair);
|
|
290
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenYMint, lbPair);
|
|
291
|
+
// Derive bin array bitmap extension from actual lb_pair and check if it exists
|
|
292
|
+
const derivedBinArrayBitmapExtension = this.pda.meteora.deriveBinArrayBitmapExtension(lbPair);
|
|
293
|
+
const binArrayBitmapExtensionInfo = yield connection.getAccountInfo(derivedBinArrayBitmapExtension);
|
|
294
|
+
const actualBinArrayBitmapExtension = binArrayBitmapExtensionInfo
|
|
295
|
+
? derivedBinArrayBitmapExtension
|
|
296
|
+
: METEORA_DLMM_PROGRAM;
|
|
297
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
298
|
+
// Determine user token accounts based on pdaTokenType
|
|
299
|
+
let userTokenX;
|
|
300
|
+
let userTokenY;
|
|
301
|
+
if (pdaTokenType === types_1.TokenType.LTA) {
|
|
302
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
303
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
304
|
+
}
|
|
305
|
+
else if (pdaTokenType === types_1.TokenType.STA) {
|
|
306
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenXMint);
|
|
307
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenYMint);
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
// Default: ATA
|
|
311
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, tokenXProgram);
|
|
312
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, tokenYProgram);
|
|
313
|
+
}
|
|
314
|
+
// Serialize RemainingAccountsInfo as Vec<u8> (Borsh format)
|
|
315
|
+
// This is passed directly to the on-chain instruction which forwards it to Meteora
|
|
316
|
+
// For SPL tokens (non-Token2022), we still need to provide the slices structure with length=0
|
|
317
|
+
// This matches what Meteora SDK's getPotentialToken2022IxDataAndAccounts returns
|
|
318
|
+
// AccountsType enum: 0=TransferHookX, 1=TransferHookY, 2=TransferHookReward
|
|
319
|
+
const defaultSlices = [
|
|
320
|
+
{ accountsType: 0, length: 0 }, // TransferHookX with 0 accounts
|
|
321
|
+
{ accountsType: 1, length: 0 }, // TransferHookY with 0 accounts
|
|
322
|
+
];
|
|
323
|
+
const remainingAccountsInfoSerialized = this.serializeRemainingAccountsInfo({
|
|
324
|
+
slices: (_b = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.slices) !== null && _b !== void 0 ? _b : defaultSlices,
|
|
325
|
+
});
|
|
326
|
+
const lowerBinId = activeId + relativeBinRange.lowerRange;
|
|
327
|
+
const upperBinId = activeId + relativeBinRange.upperRange;
|
|
328
|
+
// Derive bin arrays needed for the deposit range using the lbPair from position
|
|
329
|
+
const binArrays = meteora_1.MeteoraFunctions.findMeteoraTickArrays(lbPair, lowerBinId, upperBinId);
|
|
330
|
+
const binArrayAccounts = binArrays.map(binArray => ({
|
|
331
|
+
pubkey: binArray,
|
|
332
|
+
isSigner: false,
|
|
333
|
+
isWritable: true,
|
|
334
|
+
}));
|
|
335
|
+
// Build remaining accounts: Token2022 transfer hook accounts first (described by remainingAccountsInfo),
|
|
336
|
+
// then bin arrays (not described - Meteora expects them at the end after transfer hooks)
|
|
337
|
+
const remainingAccounts = [
|
|
338
|
+
...((_c = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.accounts) !== null && _c !== void 0 ? _c : []),
|
|
339
|
+
...binArrayAccounts,
|
|
340
|
+
];
|
|
341
|
+
const remainingAccountsInfoLength = Buffer.alloc(4);
|
|
342
|
+
remainingAccountsInfoLength.writeUInt32LE(remainingAccountsInfoSerialized.length, 0);
|
|
343
|
+
const relativeLowerRange = Buffer.alloc(2);
|
|
344
|
+
relativeLowerRange.writeInt16LE(relativeBinRange.lowerRange, 0);
|
|
345
|
+
const relativeUpperRange = Buffer.alloc(2);
|
|
346
|
+
relativeUpperRange.writeInt16LE(relativeBinRange.upperRange, 0);
|
|
347
|
+
const checkLowerRange = Buffer.alloc(4);
|
|
348
|
+
checkLowerRange.writeInt32LE((_d = checkRange === null || checkRange === void 0 ? void 0 : checkRange.lowerRange) !== null && _d !== void 0 ? _d : 0, 0);
|
|
349
|
+
const checkUpperRange = Buffer.alloc(4);
|
|
350
|
+
checkUpperRange.writeInt32LE((_e = checkRange === null || checkRange === void 0 ? void 0 : checkRange.upperRange) !== null && _e !== void 0 ? _e : 0, 0);
|
|
351
|
+
const optionalTokenXAmountBuffer = optionalTokenXAmount
|
|
352
|
+
? Buffer.concat([
|
|
353
|
+
Buffer.from([1]),
|
|
354
|
+
Buffer.from(optionalTokenXAmount.toArrayLike(Buffer, 'le', 8)),
|
|
355
|
+
])
|
|
356
|
+
: Buffer.from([0]);
|
|
357
|
+
const optionalTokenYAmountBuffer = optionalTokenYAmount
|
|
358
|
+
? Buffer.concat([
|
|
359
|
+
Buffer.from([1]),
|
|
360
|
+
Buffer.from(optionalTokenYAmount.toArrayLike(Buffer, 'le', 8)),
|
|
361
|
+
])
|
|
362
|
+
: Buffer.from([0]);
|
|
363
|
+
const remainingAccountsInfoSerializedWithLength = Buffer.concat([
|
|
364
|
+
remainingAccountsInfoLength,
|
|
365
|
+
remainingAccountsInfoSerialized,
|
|
366
|
+
]);
|
|
367
|
+
// Use Anchor to serialize the instruction (ensures proper Borsh serialization)
|
|
368
|
+
// @ts-ignore
|
|
369
|
+
const depositIx = new web3.TransactionInstruction({
|
|
370
|
+
data: Buffer.concat([
|
|
371
|
+
Buffer.from(util.sighash('meteora_dlmm_deposit_relative_automation')),
|
|
372
|
+
relativeLowerRange,
|
|
373
|
+
relativeUpperRange,
|
|
374
|
+
Buffer.from([strategyType]),
|
|
375
|
+
optionalTokenXAmountBuffer,
|
|
376
|
+
optionalTokenYAmountBuffer,
|
|
377
|
+
Buffer.from(!!checkRange
|
|
378
|
+
? Buffer.concat([
|
|
379
|
+
Buffer.from([1]),
|
|
380
|
+
checkLowerRange,
|
|
381
|
+
checkUpperRange,
|
|
382
|
+
])
|
|
383
|
+
: Buffer.from([0])),
|
|
384
|
+
remainingAccountsInfoSerializedWithLength,
|
|
385
|
+
]),
|
|
386
|
+
keys: [
|
|
387
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
388
|
+
{ pubkey: addresses_1.HS_AUTHORITY, isSigner: true, isWritable: false },
|
|
389
|
+
{ pubkey: position, isSigner: positionIsSigner, isWritable: true },
|
|
390
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
391
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true },
|
|
392
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true },
|
|
393
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true },
|
|
394
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true },
|
|
395
|
+
{ pubkey: tokenXMint, isSigner: false, isWritable: false },
|
|
396
|
+
{ pubkey: tokenYMint, isSigner: false, isWritable: false },
|
|
397
|
+
{ pubkey: tokenXProgram, isSigner: false, isWritable: false },
|
|
398
|
+
{ pubkey: tokenYProgram, isSigner: false, isWritable: false },
|
|
399
|
+
{
|
|
400
|
+
pubkey: actualBinArrayBitmapExtension,
|
|
401
|
+
isSigner: false,
|
|
402
|
+
isWritable: true,
|
|
403
|
+
},
|
|
404
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: true },
|
|
405
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: true },
|
|
406
|
+
...remainingAccounts,
|
|
407
|
+
],
|
|
408
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
409
|
+
});
|
|
410
|
+
return this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
411
|
+
userPda,
|
|
412
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
413
|
+
ix: depositIx,
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
redepositAutomation(connection_1, _a) {
|
|
418
|
+
return __awaiter(this, arguments, void 0, function* (connection, { userWallet, lbPair, position, relativeLowerBinId, relativeUpperBinId, strategyType, checkRange, }) {
|
|
419
|
+
// Initialize anchor
|
|
420
|
+
anchor_1.Anchor.initialize(connection);
|
|
421
|
+
// Meteora utility function
|
|
422
|
+
const fn = new meteora_1.MeteoraFunctions(this.ix);
|
|
423
|
+
// Generate user pda
|
|
424
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
425
|
+
// Get meteora pool
|
|
426
|
+
const lbPairInfo = yield anchor_1.Anchor.instance().meteoraProgram.account.lbPair.fetch(lbPair);
|
|
427
|
+
const tokenXMint = lbPairInfo.tokenXMint;
|
|
428
|
+
const tokenYMint = lbPairInfo.tokenYMint;
|
|
429
|
+
const reserveX = lbPairInfo.reserveX;
|
|
430
|
+
const reserveY = lbPairInfo.reserveY;
|
|
431
|
+
const userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint);
|
|
432
|
+
const userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint);
|
|
433
|
+
const activeBinId = lbPairInfo.activeId;
|
|
434
|
+
const MAX_BIN_ARRAY_SIZE = new bn_js_1.default(anchor_1.Anchor.instance().meteoraProgram.idl.constants[1].value);
|
|
435
|
+
// Get min and max bin id values from checkRange threshold
|
|
436
|
+
const { minBinId, maxBinId } = checkRange;
|
|
437
|
+
let _checkRange = [minBinId, maxBinId];
|
|
438
|
+
// Note: relative lower & upper bins can be positive or negative
|
|
439
|
+
const expectedMinBinId = activeBinId + relativeLowerBinId;
|
|
440
|
+
const expectedMaxBinId = activeBinId + relativeUpperBinId;
|
|
441
|
+
if (expectedMaxBinId < expectedMinBinId) {
|
|
442
|
+
throw new Error('Invalid bin range');
|
|
443
|
+
}
|
|
444
|
+
// get min and max bin +- 3
|
|
445
|
+
// this is to ensure that we allow for some buffer
|
|
446
|
+
let lowerTickArrays = meteora_1.MeteoraFunctions.findMeteoraTickArrays(lbPair, expectedMinBinId - 3, expectedMinBinId + 3);
|
|
447
|
+
let upperTickArrays = meteora_1.MeteoraFunctions.findMeteoraTickArrays(lbPair, expectedMaxBinId - 3, expectedMaxBinId + 3);
|
|
448
|
+
// Merge and remove duplicates
|
|
449
|
+
// it will handle overlapping tick arrays
|
|
450
|
+
// if lower is 1 2 3 4 5 6 7 and upper is 3 4 5 6 7 8 9
|
|
451
|
+
// we want to merge it to 1 2 3 4 5 6 7 8 9
|
|
452
|
+
const tickArrays = [
|
|
453
|
+
...new Set([...lowerTickArrays, ...upperTickArrays]),
|
|
454
|
+
];
|
|
455
|
+
// comment out for reference
|
|
456
|
+
// const lowerBinArrayIndex = fn.binIdToBinArrayIndex(MAX_BIN_ARRAY_SIZE, new BN(activeBinId - relativeLowerBinId));
|
|
457
|
+
// const binArrayLower = fn.deriveBinArray(lbPair, lowerBinArrayIndex);
|
|
458
|
+
// const binArrayUpper = fn.deriveBinArray(lbPair, lowerBinArrayIndex.add(new BN(1)));
|
|
459
|
+
// comment out for reference
|
|
460
|
+
// let _checkRange: null | [number, number];
|
|
461
|
+
// if (!!checkRange) {
|
|
462
|
+
// const { minBinId, maxBinId } = checkRange;
|
|
463
|
+
// _checkRange = [minBinId, maxBinId];
|
|
464
|
+
// } else {
|
|
465
|
+
// _checkRange = null;
|
|
466
|
+
// }
|
|
467
|
+
// Generate instruction
|
|
468
|
+
return this.ix.iyfMain.iyfExtensionExecute(connection, {
|
|
469
|
+
userWallet,
|
|
470
|
+
// @ts-ignore
|
|
471
|
+
iyfExtensionIx: yield anchor_1.Anchor.instance()
|
|
472
|
+
.iyfExtension.methods.meteoraDlmmRedepositAutomation(relativeLowerBinId, relativeUpperBinId, mapOldStrategyTypeToNew(strategyType), _checkRange)
|
|
473
|
+
.accounts({
|
|
474
|
+
farm: addresses_1.USDC_FARM,
|
|
475
|
+
userPda,
|
|
476
|
+
authority: userWallet,
|
|
477
|
+
iyfProgram: addresses_1.IYF_MAIN,
|
|
478
|
+
hawksightAuthority: addresses_1.HS_AUTHORITY,
|
|
479
|
+
position,
|
|
480
|
+
lbPair,
|
|
481
|
+
userTokenX,
|
|
482
|
+
userTokenY,
|
|
483
|
+
reserveX,
|
|
484
|
+
reserveY,
|
|
485
|
+
tokenXMint,
|
|
486
|
+
tokenYMint,
|
|
487
|
+
// binArrayLower,
|
|
488
|
+
// binArrayUpper,
|
|
489
|
+
systemProgram: web3.SystemProgram.programId,
|
|
490
|
+
tokenProgram: addresses_1.TOKEN_PROGRAM_ID,
|
|
491
|
+
rent: web3.SYSVAR_RENT_PUBKEY,
|
|
492
|
+
eventAuthority: METEORA_EVENT_AUTHORITY,
|
|
493
|
+
meteoraDlmmProgram: METEORA_DLMM_PROGRAM,
|
|
494
|
+
})
|
|
495
|
+
.remainingAccounts(tickArrays.map((pubkey) => {
|
|
496
|
+
return { pubkey, isSigner: false, isWritable: true };
|
|
497
|
+
}))
|
|
498
|
+
.instruction(),
|
|
499
|
+
});
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
redepositAutomation2(connection_1, _a) {
|
|
503
|
+
return __awaiter(this, arguments, void 0, function* (connection, { userWallet, lbPair, position, relativeLowerBinId, relativeUpperBinId, strategyType, checkRange, targetActiveBin, }) {
|
|
504
|
+
try {
|
|
505
|
+
console.log('=== REDEPOSIT AUTOMATION 2 START ===');
|
|
506
|
+
console.log('Parameters:', {
|
|
507
|
+
userWallet: userWallet.toString(),
|
|
508
|
+
lbPair: lbPair.toString(),
|
|
509
|
+
position: position.toString(),
|
|
510
|
+
relativeLowerBinId,
|
|
511
|
+
relativeUpperBinId,
|
|
512
|
+
strategyType,
|
|
513
|
+
checkRange,
|
|
514
|
+
});
|
|
515
|
+
// Initialize anchor
|
|
516
|
+
anchor_1.Anchor.initialize(connection);
|
|
517
|
+
// Meteora utility function
|
|
518
|
+
// const fn = new MeteoraFunctions(this.ix);
|
|
519
|
+
// Generate user pda
|
|
520
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
521
|
+
console.log('User PDA generated:', userPda.toString());
|
|
522
|
+
// Get meteora pool
|
|
523
|
+
console.log('Fetching LB pair info...');
|
|
524
|
+
const lbPairInfo = yield anchor_1.Anchor.instance().meteoraProgram.account.lbPair.fetch(lbPair);
|
|
525
|
+
const tokenXMint = lbPairInfo.tokenXMint;
|
|
526
|
+
const tokenYMint = lbPairInfo.tokenYMint;
|
|
527
|
+
const mintAInfo = AccountCache_1.AccountCache.get(tokenXMint);
|
|
528
|
+
const mintBInfo = AccountCache_1.AccountCache.get(tokenYMint);
|
|
529
|
+
const tokenProgramA = mintAInfo === null || mintAInfo === void 0 ? void 0 : mintAInfo.info.owner;
|
|
530
|
+
const tokenProgramB = mintBInfo === null || mintBInfo === void 0 ? void 0 : mintBInfo.info.owner;
|
|
531
|
+
const reserveX = lbPairInfo.reserveX;
|
|
532
|
+
const reserveY = lbPairInfo.reserveY;
|
|
533
|
+
const userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, mintAInfo === null || mintAInfo === void 0 ? void 0 : mintAInfo.info.owner);
|
|
534
|
+
const userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, mintBInfo === null || mintBInfo === void 0 ? void 0 : mintBInfo.info.owner);
|
|
535
|
+
let activeBinId = lbPairInfo.activeId;
|
|
536
|
+
if (!!targetActiveBin) {
|
|
537
|
+
activeBinId = targetActiveBin;
|
|
538
|
+
}
|
|
539
|
+
console.log('LB pair info:', {
|
|
540
|
+
tokenXMint: tokenXMint.toString(),
|
|
541
|
+
tokenYMint: tokenYMint.toString(),
|
|
542
|
+
activeBinId: activeBinId.toString(),
|
|
543
|
+
});
|
|
544
|
+
// const MAX_BIN_ARRAY_SIZE = new BN(Anchor.instance().meteoraProgram.idl.constants[1].value);
|
|
545
|
+
// Get min and max bin id values from checkRange threshold
|
|
546
|
+
const { minBinId, maxBinId } = checkRange;
|
|
547
|
+
let _checkRange = [minBinId, maxBinId];
|
|
548
|
+
// Note: relative lower & upper bins can be positive or negative
|
|
549
|
+
const expectedMinBinId = activeBinId + relativeLowerBinId;
|
|
550
|
+
const expectedMaxBinId = activeBinId + relativeUpperBinId;
|
|
551
|
+
console.log('Bin calculations:', {
|
|
552
|
+
activeBinId: activeBinId.toString(),
|
|
553
|
+
relativeLowerBinId,
|
|
554
|
+
relativeUpperBinId,
|
|
555
|
+
expectedMinBinId,
|
|
556
|
+
expectedMaxBinId,
|
|
557
|
+
});
|
|
558
|
+
if (expectedMaxBinId < expectedMinBinId) {
|
|
559
|
+
throw new Error('Invalid bin range');
|
|
560
|
+
}
|
|
561
|
+
// get min and max bin +- 3
|
|
562
|
+
// this is to ensure that we allow for some buffer
|
|
563
|
+
// let lowerTickArrays = fn.findMeteoraTickArrays(lbPair, expectedMinBinId - 3, expectedMinBinId + 3);
|
|
564
|
+
// let upperTickArrays = fn.findMeteoraTickArrays(lbPair, expectedMaxBinId - 3, expectedMaxBinId + 3);
|
|
565
|
+
// Merge and remove duplicates
|
|
566
|
+
// it will handle overlapping tick arrays
|
|
567
|
+
// if lower is 1 2 3 4 5 6 7 and upper is 3 4 5 6 7 8 9
|
|
568
|
+
// we want to merge it to 1 2 3 4 5 6 7 8 9
|
|
569
|
+
// const tickArrays: web3.PublicKey[] = [...new Set([...lowerTickArrays, ...upperTickArrays])];
|
|
570
|
+
// comment out for reference
|
|
571
|
+
// const lowerBinArrayIndex = fn.binIdToBinArrayIndex(MAX_BIN_ARRAY_SIZE, new BN(activeBinId - relativeLowerBinId));
|
|
572
|
+
// const binArrayLower = fn.deriveBinArray(lbPair, lowerBinArrayIndex);
|
|
573
|
+
// const binArrayUpper = fn.deriveBinArray(lbPair, lowerBinArrayIndex.add(new BN(1)));
|
|
574
|
+
// comment out for reference
|
|
575
|
+
// let _checkRange: null | [number, number];
|
|
576
|
+
// if (!!checkRange) {
|
|
577
|
+
// const { minBinId, maxBinId } = checkRange;
|
|
578
|
+
// _checkRange = [minBinId, maxBinId];
|
|
579
|
+
// } else {
|
|
580
|
+
// _checkRange = null;
|
|
581
|
+
// }
|
|
582
|
+
console.log('Creating DLMM instance...');
|
|
583
|
+
let DLMM = yield this.dlmm(connection, lbPair);
|
|
584
|
+
console.log('Calling addLiquidityByStrategy...');
|
|
585
|
+
const addLiquidityByStrategyTx = yield DLMM.dlmm.initializePositionAndAddLiquidityByStrategy({
|
|
586
|
+
positionPubKey: position,
|
|
587
|
+
totalXAmount: new bn_js_1.default(0),
|
|
588
|
+
totalYAmount: new bn_js_1.default(0),
|
|
589
|
+
strategy: {
|
|
590
|
+
minBinId: expectedMinBinId,
|
|
591
|
+
maxBinId: expectedMaxBinId,
|
|
592
|
+
strategyType: mapOldStrategyTypeToNew(strategyType),
|
|
593
|
+
},
|
|
594
|
+
user: userWallet,
|
|
595
|
+
});
|
|
596
|
+
console.log('addLiquidityByStrategy completed, instruction count:', addLiquidityByStrategyTx.instructions.length);
|
|
597
|
+
// const addLiquidityByStrategyIxs = addLiquidityByStrategyTx.instructions.filter((ix) => ix.programId.equals(METEORA_DLMM_PROGRAM))
|
|
598
|
+
console.log('Filtering instructions for add_liquidity_by_strategy2...');
|
|
599
|
+
const addLiquidityByStrategyIx = addLiquidityByStrategyTx.instructions.filter(ix => {
|
|
600
|
+
return (ix.programId.equals(METEORA_DLMM_PROGRAM) &&
|
|
601
|
+
ix.data
|
|
602
|
+
.subarray(0, 8)
|
|
603
|
+
.equals(Buffer.from([3, 221, 149, 218, 111, 141, 118, 213])));
|
|
604
|
+
})[0];
|
|
605
|
+
const binArrayBitmapExtension = addLiquidityByStrategyIx.keys[2].pubkey;
|
|
606
|
+
if (!addLiquidityByStrategyIx) {
|
|
607
|
+
throw new Error('add_liquidity_by_strategy2 instruction not found in transaction');
|
|
608
|
+
}
|
|
609
|
+
console.log('Found add_liquidity_by_strategy2 instruction');
|
|
610
|
+
// Log the instruction structure for debugging
|
|
611
|
+
console.log('Instruction keys count:', addLiquidityByStrategyIx.keys.length);
|
|
612
|
+
console.log('Instruction data length:', addLiquidityByStrategyIx.data.length);
|
|
613
|
+
// Find the correct slice point for remaining accounts
|
|
614
|
+
// The remaining accounts typically start after the main accounts (usually around index 10-15)
|
|
615
|
+
const remainingAccountStartIndex = Math.min(14, addLiquidityByStrategyIx.keys.length);
|
|
616
|
+
const remainingAccountMeta = addLiquidityByStrategyIx.keys.slice(remainingAccountStartIndex);
|
|
617
|
+
const strategyParametersStrategyType = addLiquidityByStrategyIx.data[32];
|
|
618
|
+
// const strategyParametersParameters: number[] = new Array(64).fill(0);
|
|
619
|
+
// index 97 onwards are remaining accounts info
|
|
620
|
+
const remainingAccountsInfo = addLiquidityByStrategyIx.data.subarray(97);
|
|
621
|
+
console.log('Remaining accounts start index:', remainingAccountStartIndex);
|
|
622
|
+
console.log('Remaining accounts count:', remainingAccountMeta.length);
|
|
623
|
+
console.log('Remaining accounts info length:', remainingAccountsInfo.length);
|
|
624
|
+
// // Generate IX via extension contract
|
|
625
|
+
// const data = this.ix.data.subarray(8);
|
|
626
|
+
// const activeId = data.subarray(16, 20).readInt32LE();
|
|
627
|
+
// const maxActiveBinSlippage = data.subarray(20, 24).readInt32LE();
|
|
628
|
+
// const strategyParametersMinBinId = data.subarray(24, 28).readInt32LE();
|
|
629
|
+
// const strategyParametersMaxBinId = data.subarray(28, 32).readInt32LE();
|
|
630
|
+
// const strategyParametersStrategyType = data[32];
|
|
631
|
+
// const strategyParametersParameters = Array.from(data.subarray(33, 97));
|
|
632
|
+
// const remainingAccountsInfo = this.ix.data.subarray(97);
|
|
633
|
+
console.log('old strategy type', strategyType);
|
|
634
|
+
console.log('new strategy type', mapOldStrategyTypeToNew(strategyType));
|
|
635
|
+
console.log('strategyParametersStrategyType', strategyParametersStrategyType);
|
|
636
|
+
// Log the first few keys to understand the structure
|
|
637
|
+
console.log('First 5 instruction keys:', addLiquidityByStrategyIx.keys.slice(0, 5).map((key, i) => ({
|
|
638
|
+
index: i,
|
|
639
|
+
pubkey: key.pubkey.toString(),
|
|
640
|
+
isSigner: key.isSigner,
|
|
641
|
+
isWritable: key.isWritable,
|
|
642
|
+
})));
|
|
643
|
+
console.log('Creating extension instruction...');
|
|
644
|
+
// @ts-ignore
|
|
645
|
+
const extensionIx = yield anchor_1.Anchor.instance()
|
|
646
|
+
.iyfExtension.methods.meteoraDlmmRedepositAutomation2(relativeLowerBinId, relativeUpperBinId, strategyType, _checkRange,
|
|
647
|
+
// strategyParametersParameters,
|
|
648
|
+
remainingAccountsInfo)
|
|
649
|
+
.accounts({
|
|
650
|
+
userPda,
|
|
651
|
+
hawksightAuthority: addresses_1.HS_AUTHORITY,
|
|
652
|
+
position,
|
|
653
|
+
lbPair,
|
|
654
|
+
userTokenX,
|
|
655
|
+
userTokenY,
|
|
656
|
+
reserveX,
|
|
657
|
+
reserveY,
|
|
658
|
+
tokenXMint,
|
|
659
|
+
tokenYMint,
|
|
660
|
+
systemProgram: web3.SystemProgram.programId,
|
|
661
|
+
tokenXProgram: tokenProgramA,
|
|
662
|
+
tokenYProgram: tokenProgramB,
|
|
663
|
+
rent: web3.SYSVAR_RENT_PUBKEY,
|
|
664
|
+
eventAuthority: METEORA_EVENT_AUTHORITY,
|
|
665
|
+
meteoraDlmmProgram: METEORA_DLMM_PROGRAM,
|
|
666
|
+
binArrayBitmapExtension,
|
|
667
|
+
})
|
|
668
|
+
.remainingAccounts(remainingAccountMeta.length > 0 ? remainingAccountMeta : [])
|
|
669
|
+
.instruction();
|
|
670
|
+
// Patch binArrayBitmapExtension writable flag: writable only when it's a real PDA, not the program ID placeholder
|
|
671
|
+
const bitmapKey = extensionIx.keys.find(k => k.pubkey.equals(binArrayBitmapExtension));
|
|
672
|
+
if (bitmapKey) {
|
|
673
|
+
bitmapKey.isWritable =
|
|
674
|
+
!binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM);
|
|
675
|
+
}
|
|
676
|
+
console.log('Extension instruction created:', {
|
|
677
|
+
keysCount: extensionIx.keys.length,
|
|
678
|
+
dataLength: extensionIx.data.length,
|
|
679
|
+
programId: extensionIx.programId.toString(),
|
|
680
|
+
});
|
|
681
|
+
// Generate instruction
|
|
682
|
+
console.log('Calling iyfExtensionExecuteV2 with:', {
|
|
683
|
+
authority: userWallet.toString(),
|
|
684
|
+
extensionIxKeysCount: extensionIx.keys.length,
|
|
685
|
+
extensionIxProgramId: extensionIx.programId.toString(),
|
|
686
|
+
});
|
|
687
|
+
const sighash = util.sighash('meteora_dlmm_redeposit_automation_2');
|
|
688
|
+
extensionIx.data.set(sighash, 0);
|
|
689
|
+
const ix = yield this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
690
|
+
userPda,
|
|
691
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
692
|
+
ix: extensionIx,
|
|
693
|
+
});
|
|
694
|
+
console.log('ix data length:', ix.data.length);
|
|
695
|
+
return ix;
|
|
696
|
+
console.log('=== REDEPOSIT AUTOMATION 2 SUCCESS ===');
|
|
697
|
+
}
|
|
698
|
+
catch (error) {
|
|
699
|
+
console.error('=== REDEPOSIT AUTOMATION 2 ERROR ===');
|
|
700
|
+
console.error('Error type:', error instanceof Error ? error.constructor.name : typeof error);
|
|
701
|
+
console.error('Error message:', error instanceof Error ? error.message : String(error));
|
|
702
|
+
console.error('Error stack:', error instanceof Error ? error.stack : 'No stack trace');
|
|
703
|
+
console.error('Full error object:', error);
|
|
704
|
+
console.error('=== END REDEPOSIT ERROR LOG ===');
|
|
705
|
+
throw error;
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
relativeOpenAutomation(connection_1, _a) {
|
|
710
|
+
return __awaiter(this, arguments, void 0, function* (connection, { userWallet, lbPair, position, relativeLowerBinId, relativeUpperBinId, strategyType, checkRange, targetActiveBin, userTokenXAmount, userTokenYAmount, useFuelAccount, pdaTokenType, }) {
|
|
711
|
+
try {
|
|
712
|
+
// Initialize anchor
|
|
713
|
+
anchor_1.Anchor.initialize(connection);
|
|
714
|
+
// Generate user pda
|
|
715
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
716
|
+
// Get meteora pool
|
|
717
|
+
const lbPairInfo = yield anchor_1.Anchor.instance().meteoraProgram.account.lbPair.fetch(lbPair);
|
|
718
|
+
const tokenXMint = lbPairInfo.tokenXMint;
|
|
719
|
+
const tokenYMint = lbPairInfo.tokenYMint;
|
|
720
|
+
// Fetch and cache mint accounts so AccountCache.get() returns the token programs
|
|
721
|
+
yield MintCache_1.MintCache.instance(connection)
|
|
722
|
+
.getBatchedMultipleAccountsInfo([tokenXMint, tokenYMint])
|
|
723
|
+
.waitForResult();
|
|
724
|
+
const mintAInfo = AccountCache_1.AccountCache.get(tokenXMint);
|
|
725
|
+
const mintBInfo = AccountCache_1.AccountCache.get(tokenYMint);
|
|
726
|
+
const tokenProgramA = mintAInfo === null || mintAInfo === void 0 ? void 0 : mintAInfo.info.owner;
|
|
727
|
+
const tokenProgramB = mintBInfo === null || mintBInfo === void 0 ? void 0 : mintBInfo.info.owner;
|
|
728
|
+
const reserveX = lbPairInfo.reserveX;
|
|
729
|
+
const reserveY = lbPairInfo.reserveY;
|
|
730
|
+
// Generate user token accounts based on pdaTokenType
|
|
731
|
+
let userTokenX;
|
|
732
|
+
let userTokenY;
|
|
733
|
+
if (pdaTokenType === types_1.TokenType.STA) {
|
|
734
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenXMint);
|
|
735
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenYMint);
|
|
736
|
+
}
|
|
737
|
+
else if (pdaTokenType === types_1.TokenType.LTA) {
|
|
738
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
739
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
740
|
+
}
|
|
741
|
+
else {
|
|
742
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, tokenProgramA);
|
|
743
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, tokenProgramB);
|
|
744
|
+
}
|
|
745
|
+
let activeBinId = lbPairInfo.activeId;
|
|
746
|
+
if (!!targetActiveBin) {
|
|
747
|
+
activeBinId = targetActiveBin;
|
|
748
|
+
}
|
|
749
|
+
// Get min and max bin id values from checkRange threshold
|
|
750
|
+
const { minBinId, maxBinId } = checkRange;
|
|
751
|
+
let _checkRange = [minBinId, maxBinId];
|
|
752
|
+
// Note: relative lower & upper bins can be positive or negative
|
|
753
|
+
const expectedMinBinId = activeBinId + relativeLowerBinId;
|
|
754
|
+
const expectedMaxBinId = activeBinId + relativeUpperBinId;
|
|
755
|
+
if (expectedMaxBinId < expectedMinBinId) {
|
|
756
|
+
throw new Error('Invalid bin range');
|
|
757
|
+
}
|
|
758
|
+
let DLMM = yield this.dlmm(connection, lbPair);
|
|
759
|
+
const addLiquidityByStrategyTx = yield DLMM.dlmm.initializePositionAndAddLiquidityByStrategy({
|
|
760
|
+
positionPubKey: position,
|
|
761
|
+
totalXAmount: new bn_js_1.default(0),
|
|
762
|
+
totalYAmount: new bn_js_1.default(0),
|
|
763
|
+
strategy: {
|
|
764
|
+
minBinId: expectedMinBinId,
|
|
765
|
+
maxBinId: expectedMaxBinId,
|
|
766
|
+
strategyType: mapOldStrategyTypeToNew(strategyType),
|
|
767
|
+
},
|
|
768
|
+
user: userWallet,
|
|
769
|
+
});
|
|
770
|
+
const addLiquidityByStrategyIx = addLiquidityByStrategyTx.instructions.filter(ix => {
|
|
771
|
+
return (ix.programId.equals(METEORA_DLMM_PROGRAM) &&
|
|
772
|
+
ix.data
|
|
773
|
+
.subarray(0, 8)
|
|
774
|
+
.equals(Buffer.from([3, 221, 149, 218, 111, 141, 118, 213])));
|
|
775
|
+
})[0];
|
|
776
|
+
const binArrayBitmapExtension = addLiquidityByStrategyIx.keys[2].pubkey;
|
|
777
|
+
if (!addLiquidityByStrategyIx) {
|
|
778
|
+
throw new Error('add_liquidity_by_strategy2 instruction not found in transaction');
|
|
779
|
+
}
|
|
780
|
+
const remainingAccountStartIndex = Math.min(14, addLiquidityByStrategyIx.keys.length);
|
|
781
|
+
const remainingAccountMeta = addLiquidityByStrategyIx.keys.slice(remainingAccountStartIndex);
|
|
782
|
+
const remainingAccountsInfo = addLiquidityByStrategyIx.data.subarray(97);
|
|
783
|
+
const fuelAccount = useFuelAccount
|
|
784
|
+
? (0, functions_1.generateFuelAccount)(userWallet)
|
|
785
|
+
: web3.SystemProgram.programId;
|
|
786
|
+
// @ts-ignore
|
|
787
|
+
const extensionIx = yield anchor_1.Anchor.instance()
|
|
788
|
+
.iyfExtension.methods.meteoraDlmmRelativeOpenAutomation(relativeLowerBinId, relativeUpperBinId, strategyType, userTokenXAmount !== null && userTokenXAmount !== void 0 ? userTokenXAmount : null, userTokenYAmount !== null && userTokenYAmount !== void 0 ? userTokenYAmount : null, _checkRange, remainingAccountsInfo)
|
|
789
|
+
.accounts({
|
|
790
|
+
userPda,
|
|
791
|
+
hawksightAuthority: addresses_1.HS_AUTHORITY,
|
|
792
|
+
position,
|
|
793
|
+
lbPair,
|
|
794
|
+
userTokenX,
|
|
795
|
+
userTokenY,
|
|
796
|
+
reserveX,
|
|
797
|
+
reserveY,
|
|
798
|
+
tokenXMint,
|
|
799
|
+
tokenYMint,
|
|
800
|
+
systemProgram: web3.SystemProgram.programId,
|
|
801
|
+
tokenXProgram: tokenProgramA,
|
|
802
|
+
tokenYProgram: tokenProgramB,
|
|
803
|
+
rent: web3.SYSVAR_RENT_PUBKEY,
|
|
804
|
+
eventAuthority: METEORA_EVENT_AUTHORITY,
|
|
805
|
+
meteoraDlmmProgram: METEORA_DLMM_PROGRAM,
|
|
806
|
+
binArrayBitmapExtension,
|
|
807
|
+
fuelAccount,
|
|
808
|
+
})
|
|
809
|
+
.remainingAccounts(remainingAccountMeta.length > 0 ? remainingAccountMeta : [])
|
|
810
|
+
.instruction();
|
|
811
|
+
// Patch binArrayBitmapExtension writable flag: writable only when it's a real PDA, not the program ID placeholder
|
|
812
|
+
const bitmapKey = extensionIx.keys.find(k => k.pubkey.equals(binArrayBitmapExtension));
|
|
813
|
+
if (bitmapKey) {
|
|
814
|
+
bitmapKey.isWritable =
|
|
815
|
+
!binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM);
|
|
816
|
+
}
|
|
817
|
+
// Set the correct sighash for the new instruction
|
|
818
|
+
const sighash = util.sighash('meteora_dlmm_relative_open_automation');
|
|
819
|
+
extensionIx.data.set(sighash, 0);
|
|
820
|
+
const ix = yield this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
821
|
+
userPda,
|
|
822
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
823
|
+
ix: extensionIx,
|
|
824
|
+
});
|
|
825
|
+
return ix;
|
|
826
|
+
}
|
|
827
|
+
catch (error) {
|
|
828
|
+
console.error('=== RELATIVE OPEN AUTOMATION ERROR ===');
|
|
829
|
+
console.error('Error message:', error instanceof Error ? error.message : String(error));
|
|
830
|
+
throw error;
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
claimFee(connection, params) {
|
|
835
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
836
|
+
// Initialize anchor
|
|
837
|
+
anchor_1.Anchor.initialize(connection);
|
|
838
|
+
return new web3.TransactionInstruction({
|
|
839
|
+
data: Buffer.from([]),
|
|
840
|
+
keys: [],
|
|
841
|
+
programId: web3.SystemProgram.programId,
|
|
842
|
+
});
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
claimFee2(connection_1, _a) {
|
|
846
|
+
return __awaiter(this, arguments, void 0, function* (connection, { userWallet, lbPair, position, tokenMintX, tokenMintY, tokenProgramX, tokenProgramY, lowerBinId, upperBinId, }) {
|
|
847
|
+
// Initialize anchor
|
|
848
|
+
anchor_1.Anchor.initialize(connection);
|
|
849
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
850
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenMintX, lbPair);
|
|
851
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenMintY, lbPair);
|
|
852
|
+
const userTokenX = (0, functions_1.generateAta)(userPda, tokenMintX, tokenProgramX);
|
|
853
|
+
const userTokenY = (0, functions_1.generateAta)(userPda, tokenMintY, tokenProgramY);
|
|
854
|
+
const ownerFeeX = (0, functions_1.generateAta)(addresses_1.SITE_FEE_OWNER, tokenMintX, tokenProgramX);
|
|
855
|
+
const ownerFeeY = (0, functions_1.generateAta)(addresses_1.SITE_FEE_OWNER, tokenMintY, tokenProgramY);
|
|
856
|
+
const binArrays = this.pda.meteora.deriveBinArrays(lbPair, lowerBinId, upperBinId);
|
|
857
|
+
const sighash = util.sighash('meteora_dlmm_claim_fee_2');
|
|
858
|
+
const minBinId = Buffer.alloc(4);
|
|
859
|
+
const maxBinId = Buffer.alloc(4);
|
|
860
|
+
const remainingAccountsInfo = Buffer.from(new Uint8Array([0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
|
|
861
|
+
minBinId.writeInt32LE(lowerBinId, 0);
|
|
862
|
+
maxBinId.writeInt32LE(upperBinId, 0);
|
|
863
|
+
return yield this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
864
|
+
userPda,
|
|
865
|
+
authority: userWallet,
|
|
866
|
+
ix: new web3.TransactionInstruction({
|
|
867
|
+
data: Buffer.concat([
|
|
868
|
+
new Uint8Array(sighash),
|
|
869
|
+
new Uint8Array(minBinId),
|
|
870
|
+
new Uint8Array(maxBinId),
|
|
871
|
+
new Uint8Array(remainingAccountsInfo),
|
|
872
|
+
]),
|
|
873
|
+
keys: [
|
|
874
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
875
|
+
{ pubkey: userWallet, isSigner: true, isWritable: false },
|
|
876
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
877
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
878
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
879
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true },
|
|
880
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true },
|
|
881
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true },
|
|
882
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true },
|
|
883
|
+
{ pubkey: tokenMintX, isSigner: false, isWritable: false },
|
|
884
|
+
{ pubkey: tokenMintY, isSigner: false, isWritable: false },
|
|
885
|
+
{ pubkey: tokenProgramX, isSigner: false, isWritable: false },
|
|
886
|
+
{ pubkey: tokenProgramY, isSigner: false, isWritable: false },
|
|
887
|
+
{ pubkey: addresses_1.MEMO_PROGRAM, isSigner: false, isWritable: false },
|
|
888
|
+
{
|
|
889
|
+
pubkey: METEORA_EVENT_AUTHORITY,
|
|
890
|
+
isSigner: false,
|
|
891
|
+
isWritable: false,
|
|
892
|
+
},
|
|
893
|
+
{ pubkey: ownerFeeX, isSigner: false, isWritable: true },
|
|
894
|
+
{ pubkey: ownerFeeY, isSigner: false, isWritable: true },
|
|
895
|
+
...binArrays.map(binArray => ({
|
|
896
|
+
pubkey: binArray,
|
|
897
|
+
isSigner: false,
|
|
898
|
+
isWritable: true,
|
|
899
|
+
})),
|
|
900
|
+
],
|
|
901
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
902
|
+
}),
|
|
903
|
+
});
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
claimReward(connection, params) {
|
|
907
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
908
|
+
// Initialize anchor
|
|
909
|
+
anchor_1.Anchor.initialize(connection);
|
|
910
|
+
return new web3.TransactionInstruction({
|
|
911
|
+
data: Buffer.from([]),
|
|
912
|
+
keys: [],
|
|
913
|
+
programId: web3.SystemProgram.programId,
|
|
914
|
+
});
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
claimReward2(connection_1, _a) {
|
|
918
|
+
return __awaiter(this, arguments, void 0, function* (connection, { userWallet, lbPair, position, rewardIndex, rewardMint, rewardVault, tokenProgram, lowerBinId, upperBinId, }) {
|
|
919
|
+
// Initialize anchor
|
|
920
|
+
anchor_1.Anchor.initialize(connection);
|
|
921
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
922
|
+
const userTokenAccount = (0, functions_1.generateAta)(userPda, rewardMint);
|
|
923
|
+
const ownerFee = (0, functions_1.generateAta)(addresses_1.SITE_FEE_OWNER, rewardMint, tokenProgram);
|
|
924
|
+
const binArrays = this.pda.meteora.deriveBinArrays(lbPair, lowerBinId, upperBinId);
|
|
925
|
+
const sighash = util.sighash('meteora_dlmm_claim_reward_2');
|
|
926
|
+
const minBinId = Buffer.alloc(4);
|
|
927
|
+
const maxBinId = Buffer.alloc(4);
|
|
928
|
+
const remainingAccountsInfo = Buffer.from(new Uint8Array([
|
|
929
|
+
0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
|
|
930
|
+
]));
|
|
931
|
+
minBinId.writeInt32LE(lowerBinId, 0);
|
|
932
|
+
maxBinId.writeInt32LE(upperBinId, 0);
|
|
933
|
+
return yield this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
934
|
+
userPda,
|
|
935
|
+
authority: userWallet,
|
|
936
|
+
ix: new web3.TransactionInstruction({
|
|
937
|
+
data: Buffer.concat([
|
|
938
|
+
new Uint8Array(sighash),
|
|
939
|
+
new Uint8Array([rewardIndex]),
|
|
940
|
+
new Uint8Array(minBinId),
|
|
941
|
+
new Uint8Array(maxBinId),
|
|
942
|
+
new Uint8Array(remainingAccountsInfo),
|
|
943
|
+
]),
|
|
944
|
+
keys: [
|
|
945
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
946
|
+
{ pubkey: userWallet, isSigner: true, isWritable: false },
|
|
947
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
948
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
949
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
950
|
+
{ pubkey: rewardVault, isSigner: false, isWritable: true },
|
|
951
|
+
{ pubkey: rewardMint, isSigner: false, isWritable: true },
|
|
952
|
+
{ pubkey: userTokenAccount, isSigner: false, isWritable: true },
|
|
953
|
+
{ pubkey: tokenProgram, isSigner: false, isWritable: true },
|
|
954
|
+
{ pubkey: addresses_1.MEMO_PROGRAM, isSigner: false, isWritable: false },
|
|
955
|
+
{
|
|
956
|
+
pubkey: METEORA_EVENT_AUTHORITY,
|
|
957
|
+
isSigner: false,
|
|
958
|
+
isWritable: false,
|
|
959
|
+
},
|
|
960
|
+
{ pubkey: ownerFee, isSigner: false, isWritable: true },
|
|
961
|
+
...binArrays.map(binArray => ({
|
|
962
|
+
pubkey: binArray,
|
|
963
|
+
isSigner: false,
|
|
964
|
+
isWritable: true,
|
|
965
|
+
})),
|
|
966
|
+
],
|
|
967
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
968
|
+
}),
|
|
969
|
+
});
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Claim fees from a Meteora DLMM position via IYF Extension for automation.
|
|
974
|
+
*
|
|
975
|
+
* This is the automation version that uses HS_AUTHORITY as the signer.
|
|
976
|
+
*
|
|
977
|
+
* @param connection - Solana connection
|
|
978
|
+
* @param params - ClaimFee2AutomationParams parameters
|
|
979
|
+
* @returns TransactionInstruction for the claim_fee2 automation operation
|
|
980
|
+
*/
|
|
981
|
+
claimFee2Automation(connection_1, _a) {
|
|
982
|
+
return __awaiter(this, arguments, void 0, function* (connection, { userWallet, lbPair, position, tokenMintX, tokenMintY, tokenProgramX, tokenProgramY, lowerBinId, upperBinId, pdaTokenType, remainingAccountsInfo, }) {
|
|
983
|
+
var _b, _c;
|
|
984
|
+
// Initialize anchor
|
|
985
|
+
anchor_1.Anchor.initialize(connection);
|
|
986
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
987
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenMintX, lbPair);
|
|
988
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenMintY, lbPair);
|
|
989
|
+
// Generate user token accounts based on pdaTokenType
|
|
990
|
+
let userTokenX;
|
|
991
|
+
let userTokenY;
|
|
992
|
+
if (pdaTokenType === types_1.TokenType.LTA) {
|
|
993
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenMintX);
|
|
994
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenMintY);
|
|
995
|
+
}
|
|
996
|
+
else if (pdaTokenType === types_1.TokenType.STA) {
|
|
997
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenMintX);
|
|
998
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenMintY);
|
|
999
|
+
}
|
|
1000
|
+
else {
|
|
1001
|
+
// Default: ATA
|
|
1002
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenMintX, tokenProgramX);
|
|
1003
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenMintY, tokenProgramY);
|
|
1004
|
+
}
|
|
1005
|
+
const ownerFeeX = (0, functions_1.generateAta)(addresses_1.SITE_FEE_OWNER, tokenMintX, tokenProgramX);
|
|
1006
|
+
const ownerFeeY = (0, functions_1.generateAta)(addresses_1.SITE_FEE_OWNER, tokenMintY, tokenProgramY);
|
|
1007
|
+
const binArrays = this.pda.meteora.deriveBinArrays(lbPair, lowerBinId, upperBinId);
|
|
1008
|
+
const sighash = util.sighash('meteora_dlmm_claim_fee_2_automation');
|
|
1009
|
+
const minBinId = Buffer.alloc(4);
|
|
1010
|
+
const maxBinId = Buffer.alloc(4);
|
|
1011
|
+
minBinId.writeInt32LE(lowerBinId, 0);
|
|
1012
|
+
maxBinId.writeInt32LE(upperBinId, 0);
|
|
1013
|
+
// Serialize RemainingAccountsInfo with Vec<u8> length prefix for Anchor
|
|
1014
|
+
const remainingAccountsInfoContent = this.serializeRemainingAccountsInfo({
|
|
1015
|
+
slices: (_b = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.slices) !== null && _b !== void 0 ? _b : [],
|
|
1016
|
+
});
|
|
1017
|
+
// For Anchor Vec<u8> parameter, we need to prepend the length as u32 LE
|
|
1018
|
+
const remainingAccountsInfoVec = Buffer.alloc(4 + remainingAccountsInfoContent.length);
|
|
1019
|
+
remainingAccountsInfoVec.writeUInt32LE(remainingAccountsInfoContent.length, 0);
|
|
1020
|
+
remainingAccountsInfoContent.copy(remainingAccountsInfoVec, 4);
|
|
1021
|
+
return yield this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
1022
|
+
userPda,
|
|
1023
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
1024
|
+
ix: new web3.TransactionInstruction({
|
|
1025
|
+
data: Buffer.concat([
|
|
1026
|
+
new Uint8Array(sighash),
|
|
1027
|
+
new Uint8Array(minBinId),
|
|
1028
|
+
new Uint8Array(maxBinId),
|
|
1029
|
+
new Uint8Array(remainingAccountsInfoVec),
|
|
1030
|
+
]),
|
|
1031
|
+
keys: [
|
|
1032
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
1033
|
+
{ pubkey: addresses_1.HS_AUTHORITY, isSigner: true, isWritable: false },
|
|
1034
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
1035
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
1036
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true },
|
|
1037
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true },
|
|
1038
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true },
|
|
1039
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true },
|
|
1040
|
+
{ pubkey: tokenMintX, isSigner: false, isWritable: false },
|
|
1041
|
+
{ pubkey: tokenMintY, isSigner: false, isWritable: false },
|
|
1042
|
+
{ pubkey: tokenProgramX, isSigner: false, isWritable: false },
|
|
1043
|
+
{ pubkey: tokenProgramY, isSigner: false, isWritable: false },
|
|
1044
|
+
{ pubkey: addresses_1.MEMO_PROGRAM, isSigner: false, isWritable: false },
|
|
1045
|
+
{
|
|
1046
|
+
pubkey: METEORA_EVENT_AUTHORITY,
|
|
1047
|
+
isSigner: false,
|
|
1048
|
+
isWritable: false,
|
|
1049
|
+
},
|
|
1050
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
1051
|
+
{ pubkey: ownerFeeX, isSigner: false, isWritable: true },
|
|
1052
|
+
{ pubkey: ownerFeeY, isSigner: false, isWritable: true },
|
|
1053
|
+
...binArrays.map(binArray => ({
|
|
1054
|
+
pubkey: binArray,
|
|
1055
|
+
isSigner: false,
|
|
1056
|
+
isWritable: true,
|
|
1057
|
+
})),
|
|
1058
|
+
// Transfer hook accounts (if any)
|
|
1059
|
+
...((_c = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.accounts) !== null && _c !== void 0 ? _c : []),
|
|
1060
|
+
],
|
|
1061
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
1062
|
+
}),
|
|
1063
|
+
});
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Claim rewards from a Meteora DLMM position via IYF Extension for automation.
|
|
1068
|
+
*
|
|
1069
|
+
* This is the automation version that uses HS_AUTHORITY as the signer.
|
|
1070
|
+
*
|
|
1071
|
+
* @param connection - Solana connection
|
|
1072
|
+
* @param params - ClaimReward2AutomationParams parameters
|
|
1073
|
+
* @returns TransactionInstruction for the claim_reward2 automation operation
|
|
1074
|
+
*/
|
|
1075
|
+
claimReward2Automation(connection_1, _a) {
|
|
1076
|
+
return __awaiter(this, arguments, void 0, function* (connection, { userWallet, lbPair, position, rewardIndex, rewardMint, rewardVault, tokenProgram, lowerBinId, upperBinId, pdaTokenType, remainingAccountsInfo, }) {
|
|
1077
|
+
var _b, _c;
|
|
1078
|
+
// Initialize anchor
|
|
1079
|
+
anchor_1.Anchor.initialize(connection);
|
|
1080
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
1081
|
+
// Generate user token account based on pdaTokenType
|
|
1082
|
+
let userTokenAccount;
|
|
1083
|
+
if (pdaTokenType === types_1.TokenType.LTA) {
|
|
1084
|
+
userTokenAccount = (0, functions_1.generateLimitToken)(userPda, rewardMint);
|
|
1085
|
+
}
|
|
1086
|
+
else if (pdaTokenType === types_1.TokenType.STA) {
|
|
1087
|
+
userTokenAccount = (0, functions_1.generateUserPdaStorageAccount)(userPda, rewardMint);
|
|
1088
|
+
}
|
|
1089
|
+
else {
|
|
1090
|
+
// Default: ATA
|
|
1091
|
+
userTokenAccount = (0, functions_1.generateAta)(userPda, rewardMint, tokenProgram);
|
|
1092
|
+
}
|
|
1093
|
+
const ownerFee = (0, functions_1.generateAta)(addresses_1.SITE_FEE_OWNER, rewardMint, tokenProgram);
|
|
1094
|
+
const binArrays = this.pda.meteora.deriveBinArrays(lbPair, lowerBinId, upperBinId);
|
|
1095
|
+
const sighash = util.sighash('meteora_dlmm_claim_reward_2_automation');
|
|
1096
|
+
const minBinId = Buffer.alloc(4);
|
|
1097
|
+
const maxBinId = Buffer.alloc(4);
|
|
1098
|
+
minBinId.writeInt32LE(lowerBinId, 0);
|
|
1099
|
+
maxBinId.writeInt32LE(upperBinId, 0);
|
|
1100
|
+
// Serialize RemainingAccountsInfo with Vec<u8> length prefix for Anchor
|
|
1101
|
+
const remainingAccountsInfoContent = this.serializeRemainingAccountsInfo({
|
|
1102
|
+
slices: (_b = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.slices) !== null && _b !== void 0 ? _b : [],
|
|
1103
|
+
});
|
|
1104
|
+
// For Anchor Vec<u8> parameter, we need to prepend the length as u32 LE
|
|
1105
|
+
const remainingAccountsInfoVec = Buffer.alloc(4 + remainingAccountsInfoContent.length);
|
|
1106
|
+
remainingAccountsInfoVec.writeUInt32LE(remainingAccountsInfoContent.length, 0);
|
|
1107
|
+
remainingAccountsInfoContent.copy(remainingAccountsInfoVec, 4);
|
|
1108
|
+
// Serialize rewardIndex as u64 (8 bytes, little endian)
|
|
1109
|
+
const rewardIndexBuffer = Buffer.alloc(8);
|
|
1110
|
+
rewardIndexBuffer.writeBigUInt64LE(BigInt(rewardIndex), 0);
|
|
1111
|
+
return yield this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
1112
|
+
userPda,
|
|
1113
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
1114
|
+
ix: new web3.TransactionInstruction({
|
|
1115
|
+
data: Buffer.concat([
|
|
1116
|
+
new Uint8Array(sighash),
|
|
1117
|
+
new Uint8Array(rewardIndexBuffer),
|
|
1118
|
+
new Uint8Array(minBinId),
|
|
1119
|
+
new Uint8Array(maxBinId),
|
|
1120
|
+
new Uint8Array(remainingAccountsInfoVec),
|
|
1121
|
+
]),
|
|
1122
|
+
keys: [
|
|
1123
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
1124
|
+
{ pubkey: addresses_1.HS_AUTHORITY, isSigner: true, isWritable: false },
|
|
1125
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
1126
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
1127
|
+
{ pubkey: rewardVault, isSigner: false, isWritable: true },
|
|
1128
|
+
{ pubkey: rewardMint, isSigner: false, isWritable: true },
|
|
1129
|
+
{ pubkey: userTokenAccount, isSigner: false, isWritable: true },
|
|
1130
|
+
{ pubkey: tokenProgram, isSigner: false, isWritable: true },
|
|
1131
|
+
{ pubkey: addresses_1.MEMO_PROGRAM, isSigner: false, isWritable: false },
|
|
1132
|
+
{
|
|
1133
|
+
pubkey: METEORA_EVENT_AUTHORITY,
|
|
1134
|
+
isSigner: false,
|
|
1135
|
+
isWritable: false,
|
|
1136
|
+
},
|
|
1137
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
1138
|
+
{ pubkey: ownerFee, isSigner: false, isWritable: true },
|
|
1139
|
+
...binArrays.map(binArray => ({
|
|
1140
|
+
pubkey: binArray,
|
|
1141
|
+
isSigner: false,
|
|
1142
|
+
isWritable: true,
|
|
1143
|
+
})),
|
|
1144
|
+
// Transfer hook accounts (if any)
|
|
1145
|
+
...((_c = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.accounts) !== null && _c !== void 0 ? _c : []),
|
|
1146
|
+
],
|
|
1147
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
1148
|
+
}),
|
|
1149
|
+
});
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
depositAutomation(connection, params) {
|
|
1153
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1154
|
+
// Initialize anchor
|
|
1155
|
+
anchor_1.Anchor.initialize(connection);
|
|
1156
|
+
const userPda = (0, functions_1.generateUserPda)(params.userWallet);
|
|
1157
|
+
let userTokenX;
|
|
1158
|
+
let userTokenY;
|
|
1159
|
+
if (params.tokenType === types_1.TokenType.LTA) {
|
|
1160
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, params.tokenXMint);
|
|
1161
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, params.tokenYMint);
|
|
1162
|
+
}
|
|
1163
|
+
else if (params.tokenType === types_1.TokenType.STA) {
|
|
1164
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, params.tokenXMint);
|
|
1165
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, params.tokenYMint);
|
|
1166
|
+
}
|
|
1167
|
+
else {
|
|
1168
|
+
userTokenX = (0, functions_1.generateAta)(userPda, params.tokenXMint);
|
|
1169
|
+
userTokenY = (0, functions_1.generateAta)(userPda, params.tokenYMint);
|
|
1170
|
+
}
|
|
1171
|
+
// @ts-ignore
|
|
1172
|
+
const ix = yield anchor_1.Anchor.instance()
|
|
1173
|
+
.iyfExtension.methods.meteoraDlmmDepositAutomation(params.activeId, params.maxActiveBinSlippage, params.strategyParametersMinBinId, params.strategyParametersMaxBinId, params.strategyParametersStrategyType, params.strategyParametersParameters)
|
|
1174
|
+
.accounts({
|
|
1175
|
+
farm: addresses_1.USDC_FARM,
|
|
1176
|
+
userPda,
|
|
1177
|
+
authority: params.userWallet,
|
|
1178
|
+
iyfProgram: addresses_1.IYF_MAIN,
|
|
1179
|
+
hawksightAuthority: addresses_1.HS_AUTHORITY,
|
|
1180
|
+
position: params.position,
|
|
1181
|
+
lbPair: params.lbPair,
|
|
1182
|
+
binArrayBitmapExtension: params.binArrayBitmapExtension,
|
|
1183
|
+
userTokenX,
|
|
1184
|
+
userTokenY,
|
|
1185
|
+
reserveX: params.reserveX,
|
|
1186
|
+
reserveY: params.reserveY,
|
|
1187
|
+
tokenXMint: params.tokenXMint,
|
|
1188
|
+
tokenYMint: params.tokenYMint,
|
|
1189
|
+
binArrayLower: params.binArrayLower,
|
|
1190
|
+
binArrayUpper: params.binArrayUpper,
|
|
1191
|
+
tokenXProgram: params.tokenXProgram,
|
|
1192
|
+
tokenYProgram: params.tokenYProgram,
|
|
1193
|
+
eventAuthority: METEORA_EVENT_AUTHORITY,
|
|
1194
|
+
meteoraDlmmProgram: METEORA_DLMM_PROGRAM,
|
|
1195
|
+
})
|
|
1196
|
+
.instruction();
|
|
1197
|
+
// Patch binArrayBitmapExtension writable flag: writable only when it's a real PDA, not the program ID placeholder
|
|
1198
|
+
const bitmapKey = ix.keys.find(k => k.pubkey.equals(params.binArrayBitmapExtension));
|
|
1199
|
+
if (bitmapKey) {
|
|
1200
|
+
bitmapKey.isWritable =
|
|
1201
|
+
!params.binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM);
|
|
1202
|
+
}
|
|
1203
|
+
return yield this.ix.iyfMain.iyfExtensionExecute(connection, {
|
|
1204
|
+
userWallet: params.userWallet,
|
|
1205
|
+
iyfExtensionIx: ix,
|
|
1206
|
+
});
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
depositWithAmountAutomation(connection, params) {
|
|
1210
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1211
|
+
// Initialize anchor
|
|
1212
|
+
anchor_1.Anchor.initialize(connection);
|
|
1213
|
+
const userPda = (0, functions_1.generateUserPda)(params.userWallet);
|
|
1214
|
+
let userTokenX;
|
|
1215
|
+
let userTokenY;
|
|
1216
|
+
if (params.tokenType === types_1.TokenType.LTA) {
|
|
1217
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, params.tokenXMint);
|
|
1218
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, params.tokenYMint);
|
|
1219
|
+
}
|
|
1220
|
+
else if (params.tokenType === types_1.TokenType.STA) {
|
|
1221
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, params.tokenXMint);
|
|
1222
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, params.tokenYMint);
|
|
1223
|
+
}
|
|
1224
|
+
else {
|
|
1225
|
+
userTokenX = (0, functions_1.generateAta)(userPda, params.tokenXMint);
|
|
1226
|
+
userTokenY = (0, functions_1.generateAta)(userPda, params.tokenYMint);
|
|
1227
|
+
}
|
|
1228
|
+
// @ts-ignore
|
|
1229
|
+
const ix = yield anchor_1.Anchor.instance()
|
|
1230
|
+
.iyfExtension.methods.meteoraDlmmDepositWithAmountAutomation(params.activeId, params.maxActiveBinSlippage, params.strategyParametersMinBinId, params.strategyParametersMaxBinId, params.strategyParametersStrategyType, params.strategyParametersParameters, params.userTokenXAmount, params.userTokenYAmount)
|
|
1231
|
+
.accounts({
|
|
1232
|
+
farm: addresses_1.USDC_FARM,
|
|
1233
|
+
userPda,
|
|
1234
|
+
authority: params.userWallet,
|
|
1235
|
+
iyfProgram: addresses_1.IYF_MAIN,
|
|
1236
|
+
hawksightAuthority: addresses_1.HS_AUTHORITY,
|
|
1237
|
+
position: params.position,
|
|
1238
|
+
lbPair: params.lbPair,
|
|
1239
|
+
binArrayBitmapExtension: params.binArrayBitmapExtension,
|
|
1240
|
+
userTokenX,
|
|
1241
|
+
userTokenY,
|
|
1242
|
+
reserveX: params.reserveX,
|
|
1243
|
+
reserveY: params.reserveY,
|
|
1244
|
+
tokenXMint: params.tokenXMint,
|
|
1245
|
+
tokenYMint: params.tokenYMint,
|
|
1246
|
+
binArrayLower: params.binArrayLower,
|
|
1247
|
+
binArrayUpper: params.binArrayUpper,
|
|
1248
|
+
tokenXProgram: params.tokenXProgram,
|
|
1249
|
+
tokenYProgram: params.tokenYProgram,
|
|
1250
|
+
eventAuthority: METEORA_EVENT_AUTHORITY,
|
|
1251
|
+
meteoraDlmmProgram: METEORA_DLMM_PROGRAM,
|
|
1252
|
+
})
|
|
1253
|
+
.instruction();
|
|
1254
|
+
// Patch binArrayBitmapExtension writable flag: writable only when it's a real PDA, not the program ID placeholder
|
|
1255
|
+
const bitmapKey = ix.keys.find(k => k.pubkey.equals(params.binArrayBitmapExtension));
|
|
1256
|
+
if (bitmapKey) {
|
|
1257
|
+
bitmapKey.isWritable =
|
|
1258
|
+
!params.binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM);
|
|
1259
|
+
}
|
|
1260
|
+
return yield this.ix.iyfMain.iyfExtensionExecute(connection, {
|
|
1261
|
+
userWallet: params.userWallet,
|
|
1262
|
+
iyfExtensionIx: ix,
|
|
1263
|
+
});
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
/**
|
|
1267
|
+
* Add liquidity to an existing Meteora DLMM position using strategy parameters.
|
|
1268
|
+
* This is the automation version that uses V2 execution (meteora_dlmm_deposit_2_automation).
|
|
1269
|
+
*
|
|
1270
|
+
* Key differences from depositAutomation:
|
|
1271
|
+
* - Uses iyfExtensionExecuteV2 with Anchor-based instruction building
|
|
1272
|
+
* - Supports remainingAccountsInfo for Token2022 transfer hooks
|
|
1273
|
+
* - Authority is HS_AUTHORITY (automation wallet)
|
|
1274
|
+
* - Does not require binArrayLower/binArrayUpper (bin arrays are auto-derived or created separately)
|
|
1275
|
+
*
|
|
1276
|
+
* @param connection - Solana connection
|
|
1277
|
+
* @param params - AddLiquidityByStrategy2AutomationParams parameters
|
|
1278
|
+
* @returns TransactionInstruction for adding liquidity
|
|
1279
|
+
*/
|
|
1280
|
+
addLiquidityByStrategy2Automation(connection, params) {
|
|
1281
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1282
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1283
|
+
// Initialize anchor
|
|
1284
|
+
anchor_1.Anchor.initialize(connection);
|
|
1285
|
+
// Derive reserves from the ACTUAL lbPair (not the one passed in, which may be incorrect)
|
|
1286
|
+
const actualReserveX = this.pda.meteora.deriveReserve(params.tokenXMint, params.lbPair);
|
|
1287
|
+
const actualReserveY = this.pda.meteora.deriveReserve(params.tokenYMint, params.lbPair);
|
|
1288
|
+
const userPda = (0, functions_1.generateUserPda)(params.userWallet);
|
|
1289
|
+
// Determine user token accounts based on pdaTokenType
|
|
1290
|
+
let userTokenX;
|
|
1291
|
+
let userTokenY;
|
|
1292
|
+
if (params.pdaTokenType === types_1.TokenType.LTA) {
|
|
1293
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, params.tokenXMint);
|
|
1294
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, params.tokenYMint);
|
|
1295
|
+
}
|
|
1296
|
+
else if (params.pdaTokenType === types_1.TokenType.STA) {
|
|
1297
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, params.tokenXMint);
|
|
1298
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, params.tokenYMint);
|
|
1299
|
+
}
|
|
1300
|
+
else {
|
|
1301
|
+
// Default: ATA
|
|
1302
|
+
userTokenX = (0, functions_1.generateAta)(userPda, params.tokenXMint, params.tokenXProgram);
|
|
1303
|
+
userTokenY = (0, functions_1.generateAta)(userPda, params.tokenYMint, params.tokenYProgram);
|
|
1304
|
+
}
|
|
1305
|
+
// Derive bin array bitmap extension
|
|
1306
|
+
const lowerBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(params.strategyParametersMinBinId));
|
|
1307
|
+
const upperBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(params.strategyParametersMaxBinId));
|
|
1308
|
+
const binArrayBitmapExtension = this.isOverflowDefaultBinArrayBitmap(lowerBinArrayIndex) ||
|
|
1309
|
+
this.isOverflowDefaultBinArrayBitmap(upperBinArrayIndex)
|
|
1310
|
+
? this.pda.meteora.deriveBinArrayBitmapExtension(params.lbPair)
|
|
1311
|
+
: METEORA_DLMM_PROGRAM;
|
|
1312
|
+
// Serialize RemainingAccountsInfo as Vec<u8> (Borsh format)
|
|
1313
|
+
// This is passed directly to the on-chain instruction which forwards it to Meteora
|
|
1314
|
+
// For SPL tokens (non-Token2022), we still need to provide the slices structure with length=0
|
|
1315
|
+
// This matches what Meteora SDK's getPotentialToken2022IxDataAndAccounts returns
|
|
1316
|
+
// AccountsType enum: 0=TransferHookX, 1=TransferHookY, 2=TransferHookReward
|
|
1317
|
+
const defaultSlices = [
|
|
1318
|
+
{ accountsType: 0, length: 0 }, // TransferHookX with 0 accounts
|
|
1319
|
+
{ accountsType: 1, length: 0 }, // TransferHookY with 0 accounts
|
|
1320
|
+
];
|
|
1321
|
+
const remainingAccountsInfoSerialized = this.serializeRemainingAccountsInfo({
|
|
1322
|
+
slices: (_b = (_a = params.remainingAccountsInfo) === null || _a === void 0 ? void 0 : _a.slices) !== null && _b !== void 0 ? _b : defaultSlices,
|
|
1323
|
+
});
|
|
1324
|
+
// Use strategy parameters directly as absolute bin IDs
|
|
1325
|
+
// strategyParametersMinBinId and strategyParametersMaxBinId are ABSOLUTE bin IDs, not deltas from activeId
|
|
1326
|
+
const lowerBinId = params.strategyParametersMinBinId;
|
|
1327
|
+
const upperBinId = params.strategyParametersMaxBinId;
|
|
1328
|
+
// Derive bin arrays needed for the deposit range using the lbPair from position
|
|
1329
|
+
const binArrays = meteora_1.MeteoraFunctions.findMeteoraTickArrays(params.lbPair, lowerBinId, upperBinId);
|
|
1330
|
+
const binArrayAccounts = binArrays.map(binArray => ({
|
|
1331
|
+
pubkey: binArray,
|
|
1332
|
+
isSigner: false,
|
|
1333
|
+
isWritable: true,
|
|
1334
|
+
}));
|
|
1335
|
+
// Build remaining accounts: Token2022 transfer hook accounts first (described by remainingAccountsInfo),
|
|
1336
|
+
// then bin arrays (not described - Meteora expects them at the end after transfer hooks)
|
|
1337
|
+
const remainingAccounts = [
|
|
1338
|
+
...((_d = (_c = params.remainingAccountsInfo) === null || _c === void 0 ? void 0 : _c.accounts) !== null && _d !== void 0 ? _d : []),
|
|
1339
|
+
...binArrayAccounts,
|
|
1340
|
+
];
|
|
1341
|
+
// Use Anchor to serialize the instruction (ensures proper Borsh serialization)
|
|
1342
|
+
// @ts-ignore
|
|
1343
|
+
const depositIx = yield anchor_1.Anchor.instance()
|
|
1344
|
+
.iyfExtension.methods.meteoraDlmmDeposit2Automation((_e = params.userTokenXAmount) !== null && _e !== void 0 ? _e : null, // Option<u64>
|
|
1345
|
+
(_f = params.userTokenYAmount) !== null && _f !== void 0 ? _f : null, // Option<u64>
|
|
1346
|
+
params.activeId, params.maxActiveBinSlippage, params.strategyParametersMinBinId, params.strategyParametersMaxBinId, params.strategyParametersStrategyType, params.strategyParametersParameters, Buffer.from(remainingAccountsInfoSerialized))
|
|
1347
|
+
.accounts({
|
|
1348
|
+
userPda,
|
|
1349
|
+
hawksightAuthority: addresses_1.HS_AUTHORITY,
|
|
1350
|
+
position: params.position,
|
|
1351
|
+
lbPair: params.lbPair,
|
|
1352
|
+
binArrayBitmapExtension,
|
|
1353
|
+
userTokenX,
|
|
1354
|
+
userTokenY,
|
|
1355
|
+
reserveX: actualReserveX,
|
|
1356
|
+
reserveY: actualReserveY,
|
|
1357
|
+
tokenXMint: params.tokenXMint,
|
|
1358
|
+
tokenYMint: params.tokenYMint,
|
|
1359
|
+
tokenXProgram: params.tokenXProgram,
|
|
1360
|
+
tokenYProgram: params.tokenYProgram,
|
|
1361
|
+
eventAuthority: METEORA_EVENT_AUTHORITY,
|
|
1362
|
+
meteoraDlmmProgram: METEORA_DLMM_PROGRAM,
|
|
1363
|
+
memoProgram: addresses_1.MEMO_PROGRAM,
|
|
1364
|
+
})
|
|
1365
|
+
.remainingAccounts(remainingAccounts)
|
|
1366
|
+
.instruction();
|
|
1367
|
+
// Patch binArrayBitmapExtension writable flag: writable only when it's a real PDA, not the program ID placeholder
|
|
1368
|
+
const bitmapKey = depositIx.keys.find(k => k.pubkey.equals(binArrayBitmapExtension));
|
|
1369
|
+
if (bitmapKey) {
|
|
1370
|
+
bitmapKey.isWritable =
|
|
1371
|
+
!binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM);
|
|
1372
|
+
}
|
|
1373
|
+
// Override sighash: Anchor's TypeScript client generates a different sighash than what
|
|
1374
|
+
// the on-chain program expects. We need to manually set the correct sighash.
|
|
1375
|
+
const sighash = util.sighash('meteora_dlmm_deposit_2_automation');
|
|
1376
|
+
depositIx.data.set(sighash, 0);
|
|
1377
|
+
// Generate instruction via IYF Main ExecuteV2
|
|
1378
|
+
// @ts-ignore
|
|
1379
|
+
const ix = yield anchor_1.Anchor.instance()
|
|
1380
|
+
.iyfMain.methods.iyfExtensionExecuteV2(depositIx.data)
|
|
1381
|
+
.accounts({
|
|
1382
|
+
userPda,
|
|
1383
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
1384
|
+
iyfExtensionProgram: addresses_1.IYF_EXTENSION,
|
|
1385
|
+
})
|
|
1386
|
+
.remainingAccounts(depositIx.keys.slice(2))
|
|
1387
|
+
.instruction();
|
|
1388
|
+
return ix;
|
|
1389
|
+
});
|
|
1390
|
+
}
|
|
1391
|
+
oneSideDeposit(connection, params) {
|
|
1392
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1393
|
+
// Initialize anchor
|
|
1394
|
+
anchor_1.Anchor.initialize(connection);
|
|
1395
|
+
return new web3.TransactionInstruction({
|
|
1396
|
+
data: Buffer.from([]),
|
|
1397
|
+
keys: [],
|
|
1398
|
+
programId: web3.SystemProgram.programId,
|
|
1399
|
+
});
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
withdrawAutomation(connection, params) {
|
|
1403
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1404
|
+
// Initialize anchor
|
|
1405
|
+
anchor_1.Anchor.initialize(connection);
|
|
1406
|
+
return new web3.TransactionInstruction({
|
|
1407
|
+
data: Buffer.from([]),
|
|
1408
|
+
keys: [],
|
|
1409
|
+
programId: web3.SystemProgram.programId,
|
|
1410
|
+
});
|
|
1411
|
+
});
|
|
1412
|
+
}
|
|
1413
|
+
closePositionAutomation(connection, params) {
|
|
1414
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1415
|
+
// Initialize anchor
|
|
1416
|
+
anchor_1.Anchor.initialize(connection);
|
|
1417
|
+
return new web3.TransactionInstruction({
|
|
1418
|
+
data: Buffer.from([]),
|
|
1419
|
+
keys: [],
|
|
1420
|
+
programId: web3.SystemProgram.programId,
|
|
1421
|
+
});
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Close an empty Meteora DLMM position via IYF Extension for automation.
|
|
1426
|
+
*
|
|
1427
|
+
* This is the automation version that uses HS_AUTHORITY as the signer.
|
|
1428
|
+
*
|
|
1429
|
+
* @param params - ClosePositionIfEmptyAutomationParams parameters
|
|
1430
|
+
* @returns TransactionInstruction for the close_position_if_empty automation operation
|
|
1431
|
+
*/
|
|
1432
|
+
closePosition2Automation(_a) {
|
|
1433
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, position, lbPair, useFuelAccount, }) {
|
|
1434
|
+
// Initialize Anchor
|
|
1435
|
+
anchor_1.Anchor.initialize(connection);
|
|
1436
|
+
// Generate user PDA
|
|
1437
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
1438
|
+
// Optional fuel account - use userPda as placeholder if not using fuel account
|
|
1439
|
+
// (userPda is already writable, while System Program cannot be writable)
|
|
1440
|
+
const fuelAccount = useFuelAccount
|
|
1441
|
+
? (0, functions_1.generateFuelAccount)(userWallet)
|
|
1442
|
+
: userPda;
|
|
1443
|
+
// Generate instruction via IYF Extension
|
|
1444
|
+
return this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
1445
|
+
userPda,
|
|
1446
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
1447
|
+
ix: new web3.TransactionInstruction({
|
|
1448
|
+
data: Buffer.from(util.sighash('meteora_dlmm_close_position_automation_v2', undefined, true)),
|
|
1449
|
+
keys: [
|
|
1450
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
1451
|
+
{ pubkey: addresses_1.HS_AUTHORITY, isSigner: true, isWritable: true },
|
|
1452
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
1453
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
1454
|
+
{
|
|
1455
|
+
pubkey: METEORA_EVENT_AUTHORITY,
|
|
1456
|
+
isSigner: false,
|
|
1457
|
+
isWritable: false,
|
|
1458
|
+
},
|
|
1459
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
1460
|
+
{ pubkey: fuelAccount, isSigner: false, isWritable: true },
|
|
1461
|
+
],
|
|
1462
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
1463
|
+
}),
|
|
1464
|
+
});
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
baseClosePosition2Automation(_a) {
|
|
1468
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, position, lbPair, useFuelAccount, isHawkRefund = false, }) {
|
|
1469
|
+
anchor_1.Anchor.initialize(connection);
|
|
1470
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
1471
|
+
const fuelAccount = useFuelAccount
|
|
1472
|
+
? (0, functions_1.generateFuelAccount)(userWallet)
|
|
1473
|
+
: userPda;
|
|
1474
|
+
return this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
1475
|
+
userPda,
|
|
1476
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
1477
|
+
ix: buildBaseClosePosition2AutomationIx({
|
|
1478
|
+
userPda,
|
|
1479
|
+
hawksightAuthority: addresses_1.HS_AUTHORITY,
|
|
1480
|
+
authority: userWallet,
|
|
1481
|
+
position,
|
|
1482
|
+
lbPair,
|
|
1483
|
+
fuelAccount,
|
|
1484
|
+
isHawkRefund,
|
|
1485
|
+
}),
|
|
1486
|
+
});
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
limitCloseAutomation(connection, params) {
|
|
1490
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1491
|
+
// Initialize anchor
|
|
1492
|
+
anchor_1.Anchor.initialize(connection);
|
|
1493
|
+
return new web3.TransactionInstruction({
|
|
1494
|
+
data: Buffer.from([]),
|
|
1495
|
+
keys: [],
|
|
1496
|
+
programId: web3.SystemProgram.programId,
|
|
1497
|
+
});
|
|
1498
|
+
});
|
|
1499
|
+
}
|
|
1500
|
+
/**
|
|
1501
|
+
* Meteora IDL
|
|
1502
|
+
*
|
|
1503
|
+
* @param connection
|
|
1504
|
+
* @returns
|
|
1505
|
+
*/
|
|
1506
|
+
meteora(connection) {
|
|
1507
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1508
|
+
return yield meteora_1.MeteoraDLMM.program(connection);
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* Meteora IDL
|
|
1513
|
+
*
|
|
1514
|
+
* @param connection
|
|
1515
|
+
* @returns
|
|
1516
|
+
*/
|
|
1517
|
+
dlmm(connection, poolAddress) {
|
|
1518
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1519
|
+
console.log('dlmm method called with:', {
|
|
1520
|
+
connection: connection ? 'valid' : 'undefined',
|
|
1521
|
+
poolAddress: poolAddress.toString(),
|
|
1522
|
+
ix: this.ix ? 'valid' : 'undefined',
|
|
1523
|
+
});
|
|
1524
|
+
if (!connection) {
|
|
1525
|
+
throw new Error('Connection is undefined in dlmm method');
|
|
1526
|
+
}
|
|
1527
|
+
if (!this.ix) {
|
|
1528
|
+
throw new Error('this.ix is undefined in dlmm method');
|
|
1529
|
+
}
|
|
1530
|
+
return yield meteora_1.MeteoraDLMM.create(connection, poolAddress, this.ix);
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1533
|
+
limitOrderCloseV2(_a) {
|
|
1534
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, position, lbPair, tokenXMint, tokenYMint, reserveX, reserveY, tokenXProgram, tokenYProgram, useFuelAccount, param, minBinId, maxBinId, binArrays, }) {
|
|
1535
|
+
// Initialize Anchor
|
|
1536
|
+
anchor_1.Anchor.initialize(connection);
|
|
1537
|
+
// Generate user PDA
|
|
1538
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
1539
|
+
// Generate limit tokens
|
|
1540
|
+
const limitTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
1541
|
+
const limitTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
1542
|
+
// Generate authority token accounts
|
|
1543
|
+
const authorityTokenX = (0, functions_1.generateAta)(userWallet, tokenXMint, tokenXProgram);
|
|
1544
|
+
const authorityTokenY = (0, functions_1.generateAta)(userWallet, tokenYMint, tokenYProgram);
|
|
1545
|
+
// Generate fee accounts
|
|
1546
|
+
const { ownerFeeX, ownerFeeY } = (0, functions_1.generateHawksightFeeAccounts)(tokenXMint, tokenYMint, tokenXProgram, tokenYProgram);
|
|
1547
|
+
// Create instruction
|
|
1548
|
+
// @ts-ignore
|
|
1549
|
+
const limitOrderCloseV2Ix = yield anchor_1.Anchor.instance()
|
|
1550
|
+
.iyfExtension.methods.limitOrderClose2(param, minBinId, maxBinId)
|
|
1551
|
+
.accounts({
|
|
1552
|
+
userPda,
|
|
1553
|
+
hawksightAuthority: addresses_1.HS_AUTHORITY,
|
|
1554
|
+
authority: userWallet,
|
|
1555
|
+
position,
|
|
1556
|
+
lbPair,
|
|
1557
|
+
binArrayBitmapExtension: METEORA_DLMM_PROGRAM,
|
|
1558
|
+
limitTokenX,
|
|
1559
|
+
limitTokenY,
|
|
1560
|
+
authorityTokenX,
|
|
1561
|
+
authorityTokenY,
|
|
1562
|
+
systemProgram: web3.SystemProgram.programId,
|
|
1563
|
+
reserveX,
|
|
1564
|
+
reserveY,
|
|
1565
|
+
tokenXMint,
|
|
1566
|
+
tokenYMint,
|
|
1567
|
+
tokenXProgram,
|
|
1568
|
+
tokenYProgram,
|
|
1569
|
+
rent: web3.SYSVAR_RENT_PUBKEY,
|
|
1570
|
+
eventAuthority: METEORA_EVENT_AUTHORITY,
|
|
1571
|
+
memoProgram: addresses_1.MEMO_PROGRAM,
|
|
1572
|
+
meteoraDlmmProgram: METEORA_DLMM_PROGRAM,
|
|
1573
|
+
ownerFeeX,
|
|
1574
|
+
ownerFeeY,
|
|
1575
|
+
fuelAccount: useFuelAccount
|
|
1576
|
+
? (0, functions_1.generateFuelAccount)(userWallet)
|
|
1577
|
+
: web3.SystemProgram.programId,
|
|
1578
|
+
})
|
|
1579
|
+
.remainingAccounts(binArrays.map(pubkey => ({
|
|
1580
|
+
pubkey,
|
|
1581
|
+
isSigner: false,
|
|
1582
|
+
isWritable: true,
|
|
1583
|
+
})))
|
|
1584
|
+
.instruction();
|
|
1585
|
+
const sighash = util.sighash('limit_order_close_2', undefined, true);
|
|
1586
|
+
limitOrderCloseV2Ix.data.set(sighash, 0);
|
|
1587
|
+
// Return the instruction directly (no wrapper needed for Meteora IX Generator)
|
|
1588
|
+
return limitOrderCloseV2Ix;
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
meteoraDlmmLimitCloseAutomationV2(_a) {
|
|
1592
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, position, lbPair, tokenXMint, tokenYMint, reserveX, reserveY, tokenXProgram, tokenYProgram, pdaTokenType, param, minBinId, maxBinId, isHawkRefund, useFuelAccount, binArrays, }) {
|
|
1593
|
+
// Initialize Anchor
|
|
1594
|
+
anchor_1.Anchor.initialize(connection);
|
|
1595
|
+
const authority = userWallet;
|
|
1596
|
+
const hawksightAuthority = addresses_1.HS_AUTHORITY;
|
|
1597
|
+
// Generate user PDA
|
|
1598
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet, addresses_1.USDC_FARM);
|
|
1599
|
+
// Generate user token accounts based on pdaTokenType
|
|
1600
|
+
let userTokenX;
|
|
1601
|
+
let userTokenY;
|
|
1602
|
+
if (pdaTokenType === types_1.TokenType.STA) {
|
|
1603
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenXMint);
|
|
1604
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenYMint);
|
|
1605
|
+
}
|
|
1606
|
+
else if (pdaTokenType === types_1.TokenType.LTA) {
|
|
1607
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
1608
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
1609
|
+
}
|
|
1610
|
+
else {
|
|
1611
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, tokenXProgram);
|
|
1612
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, tokenYProgram);
|
|
1613
|
+
}
|
|
1614
|
+
// Generate fee accounts
|
|
1615
|
+
const { ownerFeeX, ownerFeeY } = (0, functions_1.generateHawksightFeeAccounts)(tokenXMint, tokenYMint, tokenXProgram, tokenYProgram);
|
|
1616
|
+
// Create instruction
|
|
1617
|
+
// @ts-ignore
|
|
1618
|
+
const meteoraDlmmLimitCloseAutomationV2Ix = yield anchor_1.Anchor.instance()
|
|
1619
|
+
.iyfExtension.methods.meteoraDlmmLimitCloseAutomationV2(param, minBinId, maxBinId, isHawkRefund)
|
|
1620
|
+
.accounts({
|
|
1621
|
+
userPda,
|
|
1622
|
+
hawksightAuthority,
|
|
1623
|
+
authority,
|
|
1624
|
+
position,
|
|
1625
|
+
lbPair,
|
|
1626
|
+
binArrayBitmapExtension: METEORA_DLMM_PROGRAM,
|
|
1627
|
+
userTokenX,
|
|
1628
|
+
userTokenY,
|
|
1629
|
+
reserveX,
|
|
1630
|
+
reserveY,
|
|
1631
|
+
tokenXMint,
|
|
1632
|
+
tokenYMint,
|
|
1633
|
+
tokenXProgram,
|
|
1634
|
+
tokenYProgram,
|
|
1635
|
+
eventAuthority: METEORA_EVENT_AUTHORITY,
|
|
1636
|
+
memoProgram: addresses_1.MEMO_PROGRAM,
|
|
1637
|
+
meteoraDlmmProgram: METEORA_DLMM_PROGRAM,
|
|
1638
|
+
ownerFeeX,
|
|
1639
|
+
ownerFeeY,
|
|
1640
|
+
fuelAccount: useFuelAccount
|
|
1641
|
+
? (0, functions_1.generateFuelAccount)(userWallet)
|
|
1642
|
+
: web3.SystemProgram.programId,
|
|
1643
|
+
})
|
|
1644
|
+
.remainingAccounts(binArrays.map(pubkey => ({
|
|
1645
|
+
pubkey,
|
|
1646
|
+
isSigner: false,
|
|
1647
|
+
isWritable: true,
|
|
1648
|
+
})))
|
|
1649
|
+
.instruction();
|
|
1650
|
+
// Return the instruction directly (no wrapper needed for Meteora IX Generator)
|
|
1651
|
+
return meteoraDlmmLimitCloseAutomationV2Ix;
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1654
|
+
/**
|
|
1655
|
+
* Generates raw meteora instruction that initializes a meteora pool
|
|
1656
|
+
*
|
|
1657
|
+
* @param param0
|
|
1658
|
+
* @returns
|
|
1659
|
+
*/
|
|
1660
|
+
initializeLbPair2Raw(_a) {
|
|
1661
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, funder, tokenMintX, tokenMintY, tokenProgramX, tokenProgramY, presetParameter, activeId, }) {
|
|
1662
|
+
// Initialize anchor
|
|
1663
|
+
anchor_1.Anchor.initialize(connection);
|
|
1664
|
+
const tokenX = tokenMintX;
|
|
1665
|
+
const tokenY = tokenMintY;
|
|
1666
|
+
const lbPair = this.pda.meteora.deriveLbPairWithPresetParamWithIndexKey(presetParameter, tokenX, tokenY);
|
|
1667
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenX, lbPair);
|
|
1668
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenY, lbPair);
|
|
1669
|
+
const oracle = this.pda.meteora.deriveOracle(lbPair);
|
|
1670
|
+
const activeBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(activeId));
|
|
1671
|
+
const binArrayBitmapExtension = this.isOverflowDefaultBinArrayBitmap(activeBinArrayIndex)
|
|
1672
|
+
? this.pda.meteora.deriveBinArrayBitmapExtension(lbPair)
|
|
1673
|
+
: METEORA_DLMM_PROGRAM;
|
|
1674
|
+
return new web3.TransactionInstruction({
|
|
1675
|
+
data: Buffer.concat([
|
|
1676
|
+
Buffer.from(util.sighash('initialize_lb_pair_2')),
|
|
1677
|
+
Buffer.from([activeId]),
|
|
1678
|
+
Buffer.from(Array(96).fill(0)),
|
|
1679
|
+
]),
|
|
1680
|
+
keys: [
|
|
1681
|
+
{ pubkey: funder, isSigner: true, isWritable: true },
|
|
1682
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
1683
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true },
|
|
1684
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true },
|
|
1685
|
+
{
|
|
1686
|
+
pubkey: binArrayBitmapExtension,
|
|
1687
|
+
isSigner: false,
|
|
1688
|
+
isWritable: !binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM),
|
|
1689
|
+
},
|
|
1690
|
+
{ pubkey: tokenMintX, isSigner: false, isWritable: false },
|
|
1691
|
+
{ pubkey: tokenMintY, isSigner: false, isWritable: false },
|
|
1692
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
1693
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
1694
|
+
{ pubkey: tokenProgramX, isSigner: false, isWritable: false },
|
|
1695
|
+
{ pubkey: tokenProgramY, isSigner: false, isWritable: false },
|
|
1696
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
1697
|
+
],
|
|
1698
|
+
programId: METEORA_DLMM_PROGRAM,
|
|
1699
|
+
});
|
|
1700
|
+
});
|
|
1701
|
+
}
|
|
1702
|
+
isOverflowDefaultBinArrayBitmap(binArrayIndex) {
|
|
1703
|
+
const [minBinArrayIndex, maxBinArrayIndex] = this.internalBitmapRange();
|
|
1704
|
+
return (binArrayIndex.gt(maxBinArrayIndex) || binArrayIndex.lt(minBinArrayIndex));
|
|
1705
|
+
}
|
|
1706
|
+
internalBitmapRange() {
|
|
1707
|
+
const lowerBinArrayIndex = new bn_js_1.default(512).neg();
|
|
1708
|
+
const upperBinArrayIndex = new bn_js_1.default(512).sub(new bn_js_1.default(1));
|
|
1709
|
+
return [lowerBinArrayIndex, upperBinArrayIndex];
|
|
1710
|
+
}
|
|
1711
|
+
binIdToBinArrayIndex(binId) {
|
|
1712
|
+
const { div: idx, mod } = binId.divmod(new bn_js_1.default(70));
|
|
1713
|
+
return binId.isNeg() && !mod.isZero() ? idx.sub(new bn_js_1.default(1)) : idx;
|
|
1714
|
+
}
|
|
1715
|
+
meteoraDlmmCreatePoolAndPosition(_a) {
|
|
1716
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, position, presetParameter, tokenMintX, tokenMintY, tokenProgramX, tokenProgramY, activeId, lowerBinId, upperBinId, strategyType, binStep, baseFactor, baseFeePowerFactor, }) {
|
|
1717
|
+
// Initialize anchor
|
|
1718
|
+
anchor_1.Anchor.initialize(connection);
|
|
1719
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
1720
|
+
const userTokenX = (0, functions_1.generateAta)(userPda, tokenMintX, tokenProgramX);
|
|
1721
|
+
const userTokenY = (0, functions_1.generateAta)(userPda, tokenMintY, tokenProgramY);
|
|
1722
|
+
// Try to get existing LB pair first
|
|
1723
|
+
let lbPair;
|
|
1724
|
+
try {
|
|
1725
|
+
lbPair = yield dlmm_1.default.getPairPubkeyIfExists(connection, tokenMintX, tokenMintY, binStep, baseFactor, baseFeePowerFactor);
|
|
1726
|
+
}
|
|
1727
|
+
catch (error) {
|
|
1728
|
+
// If getPairPubkeyIfExists fails, set lbPair to null to trigger fallback
|
|
1729
|
+
lbPair = null;
|
|
1730
|
+
}
|
|
1731
|
+
// If no existing pair found or error occurred, derive it with preset parameters
|
|
1732
|
+
if (!lbPair) {
|
|
1733
|
+
lbPair = this.pda.meteora.deriveLbPairWithPresetParamWithIndexKey(presetParameter, tokenMintX, tokenMintY);
|
|
1734
|
+
}
|
|
1735
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenMintX, lbPair);
|
|
1736
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenMintY, lbPair);
|
|
1737
|
+
const oracle = this.pda.meteora.deriveOracle(lbPair);
|
|
1738
|
+
const hawkfiPayer = this.pda.hawksight.generateHawkfiPayer();
|
|
1739
|
+
return new web3.TransactionInstruction({
|
|
1740
|
+
data: Buffer.concat([
|
|
1741
|
+
Buffer.from(util.sighash('meteora_dlmm_create_pool_and_position')),
|
|
1742
|
+
new bn_js_1.default(activeId).toTwos(32).toArrayLike(Buffer, 'le', 4),
|
|
1743
|
+
new bn_js_1.default(lowerBinId).toTwos(32).toArrayLike(Buffer, 'le', 4),
|
|
1744
|
+
new bn_js_1.default(upperBinId).toTwos(32).toArrayLike(Buffer, 'le', 4),
|
|
1745
|
+
Buffer.from([strategyType]),
|
|
1746
|
+
]),
|
|
1747
|
+
keys: [
|
|
1748
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
1749
|
+
{ pubkey: userWallet, isSigner: true, isWritable: true },
|
|
1750
|
+
{ pubkey: hawkfiPayer, isSigner: false, isWritable: true },
|
|
1751
|
+
{ pubkey: position, isSigner: true, isWritable: true },
|
|
1752
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
1753
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true },
|
|
1754
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true },
|
|
1755
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true },
|
|
1756
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true },
|
|
1757
|
+
{ pubkey: oracle, isSigner: false, isWritable: true },
|
|
1758
|
+
{ pubkey: presetParameter, isSigner: false, isWritable: false },
|
|
1759
|
+
{ pubkey: tokenMintX, isSigner: false, isWritable: false },
|
|
1760
|
+
{ pubkey: tokenMintY, isSigner: false, isWritable: false },
|
|
1761
|
+
{ pubkey: tokenProgramX, isSigner: false, isWritable: false },
|
|
1762
|
+
{ pubkey: tokenProgramY, isSigner: false, isWritable: false },
|
|
1763
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: false },
|
|
1764
|
+
{ pubkey: web3.SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
|
|
1765
|
+
{
|
|
1766
|
+
pubkey: web3.SystemProgram.programId,
|
|
1767
|
+
isSigner: false,
|
|
1768
|
+
isWritable: false,
|
|
1769
|
+
},
|
|
1770
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
1771
|
+
...(() => {
|
|
1772
|
+
const binArrays = meteora_1.MeteoraFunctions.findMeteoraTickArrays(lbPair, lowerBinId, upperBinId);
|
|
1773
|
+
return binArrays.map(pubkey => ({
|
|
1774
|
+
pubkey,
|
|
1775
|
+
isSigner: false,
|
|
1776
|
+
isWritable: true,
|
|
1777
|
+
}));
|
|
1778
|
+
})(),
|
|
1779
|
+
],
|
|
1780
|
+
programId: addresses_1.IYF_MAIN,
|
|
1781
|
+
});
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
meteoraDlmmInitializeBinArray(_a) {
|
|
1785
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, lowerBinId, upperBinId, }) {
|
|
1786
|
+
// Initialize anchor
|
|
1787
|
+
anchor_1.Anchor.initialize(connection);
|
|
1788
|
+
// Generate user PDA
|
|
1789
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
1790
|
+
// Generate hawkfi payer
|
|
1791
|
+
const hawkfiPayer = this.pda.hawksight.generateHawkfiPayer();
|
|
1792
|
+
return new web3.TransactionInstruction({
|
|
1793
|
+
data: Buffer.concat([
|
|
1794
|
+
Buffer.from(util.sighash('meteora_dlmm_init_bin_arrays')),
|
|
1795
|
+
new bn_js_1.default(lowerBinId).toTwos(32).toArrayLike(Buffer, 'le', 4),
|
|
1796
|
+
new bn_js_1.default(upperBinId).toTwos(32).toArrayLike(Buffer, 'le', 4),
|
|
1797
|
+
]),
|
|
1798
|
+
keys: [
|
|
1799
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
1800
|
+
{ pubkey: userWallet, isSigner: true, isWritable: true },
|
|
1801
|
+
{ pubkey: hawkfiPayer, isSigner: false, isWritable: true },
|
|
1802
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
1803
|
+
{
|
|
1804
|
+
pubkey: web3.SystemProgram.programId,
|
|
1805
|
+
isSigner: false,
|
|
1806
|
+
isWritable: false,
|
|
1807
|
+
},
|
|
1808
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
1809
|
+
...(() => {
|
|
1810
|
+
const binArrays = meteora_1.MeteoraFunctions.findMeteoraTickArrays(lbPair, lowerBinId, upperBinId);
|
|
1811
|
+
return binArrays.map(pubkey => ({
|
|
1812
|
+
pubkey,
|
|
1813
|
+
isSigner: false,
|
|
1814
|
+
isWritable: true,
|
|
1815
|
+
}));
|
|
1816
|
+
})(),
|
|
1817
|
+
],
|
|
1818
|
+
programId: addresses_1.IYF_MAIN,
|
|
1819
|
+
});
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
/**
|
|
1823
|
+
* Initialize bin arrays for Meteora DLMM pool, invoked through meteora dlmm program
|
|
1824
|
+
* which means initialization is paid by the user.
|
|
1825
|
+
*
|
|
1826
|
+
* @param connection - Solana connection
|
|
1827
|
+
* @param userWallet - User wallet public key
|
|
1828
|
+
* @param lbPair - LB pair public key
|
|
1829
|
+
* @param lowerBinId - Lower bin ID
|
|
1830
|
+
* @param upperBinId - Upper bin ID
|
|
1831
|
+
* @returns
|
|
1832
|
+
*/
|
|
1833
|
+
meteoraDlmmInitializeBinArrayDefault(_a) {
|
|
1834
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, lowerBinId, upperBinId, }) {
|
|
1835
|
+
// Initialize anchor
|
|
1836
|
+
anchor_1.Anchor.initialize(connection);
|
|
1837
|
+
const funder = userWallet;
|
|
1838
|
+
const systemProgram = web3.SystemProgram.programId;
|
|
1839
|
+
const tickIndices = meteora_1.MeteoraFunctions.findMeteoraTickArrayIndices(lowerBinId, upperBinId);
|
|
1840
|
+
const upperTickIndex = tickIndices[tickIndices.length - 1].add(new bn_js_1.default(1));
|
|
1841
|
+
const binArrays = meteora_1.MeteoraFunctions.findMeteoraTickArrays(lbPair, lowerBinId, upperBinId);
|
|
1842
|
+
const ixs = binArrays.map((binArray, i) => {
|
|
1843
|
+
const index = tickIndices[i] !== undefined ? tickIndices[i] : upperTickIndex;
|
|
1844
|
+
return new web3.TransactionInstruction({
|
|
1845
|
+
data: Buffer.concat([
|
|
1846
|
+
Buffer.from(util.sighash('initialize_bin_array')),
|
|
1847
|
+
new bn_js_1.default(index).toTwos(64).toArrayLike(Buffer, 'le', 8),
|
|
1848
|
+
]),
|
|
1849
|
+
keys: [
|
|
1850
|
+
{ pubkey: lbPair, isSigner: false, isWritable: false },
|
|
1851
|
+
{ pubkey: binArray, isSigner: false, isWritable: true },
|
|
1852
|
+
{ pubkey: funder, isSigner: true, isWritable: true },
|
|
1853
|
+
{ pubkey: systemProgram, isSigner: false, isWritable: true },
|
|
1854
|
+
],
|
|
1855
|
+
programId: METEORA_DLMM_PROGRAM,
|
|
1856
|
+
});
|
|
1857
|
+
});
|
|
1858
|
+
return ixs;
|
|
1859
|
+
});
|
|
1860
|
+
}
|
|
1861
|
+
syncWithMarketPrice(_a) {
|
|
1862
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, lbPair, marketPrice, owner, skipCanSyncCheck = false, }) {
|
|
1863
|
+
var _b;
|
|
1864
|
+
// Initialize anchor
|
|
1865
|
+
anchor_1.Anchor.initialize(connection);
|
|
1866
|
+
// Create DLMM instance
|
|
1867
|
+
const dlmmInstance = yield this.dlmm(connection, lbPair);
|
|
1868
|
+
// Get active bin
|
|
1869
|
+
const activeBin = yield dlmmInstance.dlmm.getActiveBin();
|
|
1870
|
+
// Check if sync is possible
|
|
1871
|
+
if (!skipCanSyncCheck) {
|
|
1872
|
+
const canSync = dlmmInstance.dlmm.canSyncWithMarketPrice(marketPrice, activeBin.binId);
|
|
1873
|
+
if (!canSync) {
|
|
1874
|
+
return { canSync: false, instruction: null };
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
// Get sync transaction
|
|
1878
|
+
const tx = yield dlmmInstance.dlmm.syncWithMarketPrice(marketPrice, owner);
|
|
1879
|
+
// Extract the goToABin instruction (raw Meteora instruction)
|
|
1880
|
+
const instruction = (_b = tx.instructions.find(ix => ix.programId.equals(METEORA_DLMM_PROGRAM))) !== null && _b !== void 0 ? _b : null;
|
|
1881
|
+
return { canSync: true, instruction };
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
/**
|
|
1885
|
+
* Increase the length of a Meteora DLMM position via IYF Main's meteora dynamic CPI.
|
|
1886
|
+
*
|
|
1887
|
+
* This instruction can only extend for up to 10kb in size, thus this instruction needs to be called
|
|
1888
|
+
* multiple times.
|
|
1889
|
+
*
|
|
1890
|
+
* This is the raw Meteora initializePosition instruction invoked through IYF Main.
|
|
1891
|
+
*
|
|
1892
|
+
* @param connection - Solana connection
|
|
1893
|
+
* @param params - Increase position length parameters
|
|
1894
|
+
* @returns TransactionInstruction for initializing the position
|
|
1895
|
+
*/
|
|
1896
|
+
increasePositionLength(_a) {
|
|
1897
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, position, lengthToAdd, side, }) {
|
|
1898
|
+
// Initialize anchor
|
|
1899
|
+
anchor_1.Anchor.initialize(connection);
|
|
1900
|
+
// Generate user PDA
|
|
1901
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
1902
|
+
// Build instruction data: sighash + lengthToAdd (u16) + side (u8)
|
|
1903
|
+
const lengthToAddBuffer = Buffer.alloc(2);
|
|
1904
|
+
lengthToAddBuffer.writeUInt16LE(lengthToAdd, 0);
|
|
1905
|
+
const sideBuffer = Buffer.alloc(1);
|
|
1906
|
+
sideBuffer.writeUInt8(side, 0);
|
|
1907
|
+
// Build raw Meteora instruction (accounts only - no hawksight wrapper accounts)
|
|
1908
|
+
// meteoraDynamicCpi will prepend userPda and authority
|
|
1909
|
+
const meteoraIx = new web3.TransactionInstruction({
|
|
1910
|
+
data: Buffer.concat([
|
|
1911
|
+
Buffer.from(util.sighash('increase_position_length')),
|
|
1912
|
+
lengthToAddBuffer,
|
|
1913
|
+
sideBuffer,
|
|
1914
|
+
]),
|
|
1915
|
+
keys: [
|
|
1916
|
+
{ pubkey: userWallet, isSigner: false, isWritable: true }, // funder (Mutable, Signer - signed by IYF Main)
|
|
1917
|
+
{ pubkey: lbPair, isSigner: false, isWritable: false }, // lbPair
|
|
1918
|
+
{ pubkey: position, isSigner: true, isWritable: true }, // position (Mutable, Signer)
|
|
1919
|
+
{ pubkey: userPda, isSigner: false, isWritable: false }, // owner (Signer - signed by IYF Main)
|
|
1920
|
+
{
|
|
1921
|
+
pubkey: web3.SystemProgram.programId,
|
|
1922
|
+
isSigner: false,
|
|
1923
|
+
isWritable: false,
|
|
1924
|
+
}, // systemProgram (required for realloc)
|
|
1925
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: false }, // eventAuthority (PDA)
|
|
1926
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false }, // Meteora DLMM program
|
|
1927
|
+
],
|
|
1928
|
+
programId: METEORA_DLMM_PROGRAM,
|
|
1929
|
+
});
|
|
1930
|
+
return yield this.ix.iyfMain.meteoraDynamicCpi({
|
|
1931
|
+
connection,
|
|
1932
|
+
userWallet,
|
|
1933
|
+
meteoraIx,
|
|
1934
|
+
});
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
increasePositionLengthAutomation(_a) {
|
|
1938
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, position, lengthToAdd, side, useFuelAccount, }) {
|
|
1939
|
+
// Initialize anchor
|
|
1940
|
+
anchor_1.Anchor.initialize(connection);
|
|
1941
|
+
// Generate user PDA
|
|
1942
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
1943
|
+
// Build instruction data: sighash + lengthToAdd (u16) + side (u8)
|
|
1944
|
+
const lengthToAddBuffer = Buffer.alloc(2);
|
|
1945
|
+
lengthToAddBuffer.writeUInt16LE(lengthToAdd, 0);
|
|
1946
|
+
const sideBuffer = Buffer.alloc(1);
|
|
1947
|
+
sideBuffer.writeUInt8(side, 0);
|
|
1948
|
+
const fuelAccount = useFuelAccount
|
|
1949
|
+
? (0, functions_1.generateFuelAccount)(userWallet)
|
|
1950
|
+
: web3.SystemProgram.programId;
|
|
1951
|
+
// Generate instruction
|
|
1952
|
+
return this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
1953
|
+
userPda,
|
|
1954
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
1955
|
+
ix: new web3.TransactionInstruction({
|
|
1956
|
+
data: Buffer.concat([
|
|
1957
|
+
Buffer.from(util.sighash('meteora_dlmm_increase_position_length_automation')),
|
|
1958
|
+
lengthToAddBuffer,
|
|
1959
|
+
sideBuffer,
|
|
1960
|
+
]),
|
|
1961
|
+
keys: [
|
|
1962
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
1963
|
+
{ pubkey: addresses_1.HS_AUTHORITY, isSigner: true, isWritable: true },
|
|
1964
|
+
{ pubkey: lbPair, isSigner: false, isWritable: false },
|
|
1965
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
1966
|
+
{
|
|
1967
|
+
pubkey: METEORA_EVENT_AUTHORITY,
|
|
1968
|
+
isSigner: false,
|
|
1969
|
+
isWritable: false,
|
|
1970
|
+
},
|
|
1971
|
+
{
|
|
1972
|
+
pubkey: web3.SystemProgram.programId,
|
|
1973
|
+
isSigner: false,
|
|
1974
|
+
isWritable: false,
|
|
1975
|
+
},
|
|
1976
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
1977
|
+
{
|
|
1978
|
+
pubkey: fuelAccount,
|
|
1979
|
+
isSigner: false,
|
|
1980
|
+
isWritable: useFuelAccount !== null && useFuelAccount !== void 0 ? useFuelAccount : false,
|
|
1981
|
+
},
|
|
1982
|
+
],
|
|
1983
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
1984
|
+
}),
|
|
1985
|
+
});
|
|
1986
|
+
});
|
|
1987
|
+
}
|
|
1988
|
+
/**
|
|
1989
|
+
* Create a Meteora DLMM rebalance_liquidity instruction via IYF Main's meteora dynamic CPI.
|
|
1990
|
+
*
|
|
1991
|
+
* The rebalance_liquidity instruction allows for complex liquidity management including:
|
|
1992
|
+
* - Removing liquidity from specific bin ranges
|
|
1993
|
+
* - Adding liquidity to new bin ranges
|
|
1994
|
+
* - Claiming fees and rewards
|
|
1995
|
+
* - All in a single atomic transaction
|
|
1996
|
+
*
|
|
1997
|
+
* @param params - RebalanceLiquidityIxParams containing all necessary accounts and parameters
|
|
1998
|
+
* @returns TransactionInstruction for the rebalance_liquidity operation
|
|
1999
|
+
*/
|
|
2000
|
+
rebalanceLiquidity(_a) {
|
|
2001
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, position, lbPair, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, activeId, pdaTokenType, maxActiveBinSlippage, shouldClaimFee, shouldClaimReward, minWithdrawXAmount, maxDepositXAmount, minWithdrawYAmount, maxDepositYAmount, removeLiquidityParams, addLiquidityParams, shrinkMode, }) {
|
|
2002
|
+
// Initialize Anchor
|
|
2003
|
+
anchor_1.Anchor.initialize(connection);
|
|
2004
|
+
// Generate user PDA
|
|
2005
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
2006
|
+
// Generate user token accounts based on pdaTokenType
|
|
2007
|
+
let userTokenX;
|
|
2008
|
+
let userTokenY;
|
|
2009
|
+
if (pdaTokenType === types_1.TokenType.LTA) {
|
|
2010
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
2011
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
2012
|
+
}
|
|
2013
|
+
else if (pdaTokenType === types_1.TokenType.STA) {
|
|
2014
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenXMint);
|
|
2015
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenYMint);
|
|
2016
|
+
}
|
|
2017
|
+
else {
|
|
2018
|
+
// Default: ATA
|
|
2019
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, tokenXProgram);
|
|
2020
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, tokenYProgram);
|
|
2021
|
+
}
|
|
2022
|
+
// Derive bin array bitmap extension
|
|
2023
|
+
const lowerBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(activeId + addLiquidityParams[0].minDeltaId));
|
|
2024
|
+
const upperBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(activeId + addLiquidityParams[0].maxDeltaId));
|
|
2025
|
+
const binArrayBitmapExtension = this.isOverflowDefaultBinArrayBitmap(lowerBinArrayIndex) ||
|
|
2026
|
+
this.isOverflowDefaultBinArrayBitmap(upperBinArrayIndex)
|
|
2027
|
+
? this.pda.meteora.deriveBinArrayBitmapExtension(lbPair)
|
|
2028
|
+
: METEORA_DLMM_PROGRAM;
|
|
2029
|
+
// Derive reserves
|
|
2030
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenXMint, lbPair);
|
|
2031
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenYMint, lbPair);
|
|
2032
|
+
// Derive bin arrays based on activeId, minDeltaId, and maxDeltaId
|
|
2033
|
+
const lowerBinId = activeId + addLiquidityParams[0].minDeltaId;
|
|
2034
|
+
const upperBinId = activeId + addLiquidityParams[0].maxDeltaId;
|
|
2035
|
+
const binArrays = this.pda.meteora.deriveBinArrays(lbPair, lowerBinId, upperBinId);
|
|
2036
|
+
// Serialize RebalanceLiquidityParams
|
|
2037
|
+
const rebalanceParamsData = this.serializeRebalanceLiquidityParams({
|
|
2038
|
+
activeId,
|
|
2039
|
+
maxActiveBinSlippage,
|
|
2040
|
+
shouldClaimFee,
|
|
2041
|
+
shouldClaimReward,
|
|
2042
|
+
minWithdrawXAmount,
|
|
2043
|
+
maxDepositXAmount,
|
|
2044
|
+
minWithdrawYAmount,
|
|
2045
|
+
maxDepositYAmount,
|
|
2046
|
+
shrinkMode,
|
|
2047
|
+
removeLiquidityParams,
|
|
2048
|
+
addLiquidityParams,
|
|
2049
|
+
});
|
|
2050
|
+
// Serialize RemainingAccountsInfo (default empty for now - no transfer hooks)
|
|
2051
|
+
const remainingAccountsInfo = this.serializeRemainingAccountsInfo({
|
|
2052
|
+
slices: [],
|
|
2053
|
+
});
|
|
2054
|
+
// Build instruction data: sighash + RebalanceLiquidityParams + RemainingAccountsInfo
|
|
2055
|
+
const instructionData = Buffer.concat([
|
|
2056
|
+
Buffer.from(util.sighash('rebalance_liquidity')),
|
|
2057
|
+
rebalanceParamsData,
|
|
2058
|
+
remainingAccountsInfo,
|
|
2059
|
+
]);
|
|
2060
|
+
// Build raw Meteora instruction
|
|
2061
|
+
const meteoraIx = new web3.TransactionInstruction({
|
|
2062
|
+
data: instructionData,
|
|
2063
|
+
keys: [
|
|
2064
|
+
{ pubkey: position, isSigner: false, isWritable: true }, // position (Mutable)
|
|
2065
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true }, // lbPair (Mutable)
|
|
2066
|
+
{
|
|
2067
|
+
pubkey: binArrayBitmapExtension,
|
|
2068
|
+
isSigner: false,
|
|
2069
|
+
isWritable: !binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM),
|
|
2070
|
+
}, // binArrayBitmapExtension
|
|
2071
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true }, // userTokenX (Mutable)
|
|
2072
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true }, // userTokenY (Mutable)
|
|
2073
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true }, // reserveX (Mutable)
|
|
2074
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true }, // reserveY (Mutable)
|
|
2075
|
+
{ pubkey: tokenXMint, isSigner: false, isWritable: false }, // tokenXMint
|
|
2076
|
+
{ pubkey: tokenYMint, isSigner: false, isWritable: false }, // tokenYMint
|
|
2077
|
+
{ pubkey: userPda, isSigner: false, isWritable: false }, // sender (Signer - signed by IYF Main)
|
|
2078
|
+
{ pubkey: userWallet, isSigner: false, isWritable: true }, // rentReceiver (Mutable)
|
|
2079
|
+
{ pubkey: tokenXProgram, isSigner: false, isWritable: false }, // tokenXProgram
|
|
2080
|
+
{ pubkey: tokenYProgram, isSigner: false, isWritable: false }, // tokenYProgram
|
|
2081
|
+
{ pubkey: addresses_1.MEMO_PROGRAM, isSigner: false, isWritable: false }, // memoProgram
|
|
2082
|
+
{
|
|
2083
|
+
pubkey: web3.SystemProgram.programId,
|
|
2084
|
+
isSigner: false,
|
|
2085
|
+
isWritable: false,
|
|
2086
|
+
}, // systemProgram
|
|
2087
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: false }, // eventAuthority
|
|
2088
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false }, // program
|
|
2089
|
+
// Bin arrays as remaining accounts
|
|
2090
|
+
...binArrays.map(pubkey => ({
|
|
2091
|
+
pubkey,
|
|
2092
|
+
isSigner: false,
|
|
2093
|
+
isWritable: true,
|
|
2094
|
+
})),
|
|
2095
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false }, // program
|
|
2096
|
+
],
|
|
2097
|
+
programId: METEORA_DLMM_PROGRAM,
|
|
2098
|
+
});
|
|
2099
|
+
return yield this.ix.iyfMain.meteoraDynamicCpi({
|
|
2100
|
+
connection,
|
|
2101
|
+
userWallet,
|
|
2102
|
+
meteoraIx,
|
|
2103
|
+
});
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
/**
|
|
2107
|
+
* Serialize RebalanceLiquidityParams to match Rust struct layout
|
|
2108
|
+
*/
|
|
2109
|
+
serializeRebalanceLiquidityParams(params) {
|
|
2110
|
+
var _a;
|
|
2111
|
+
const buffers = [];
|
|
2112
|
+
// activeId (i32)
|
|
2113
|
+
const activeIdBuf = Buffer.alloc(4);
|
|
2114
|
+
activeIdBuf.writeInt32LE(params.activeId, 0);
|
|
2115
|
+
buffers.push(activeIdBuf);
|
|
2116
|
+
// maxActiveBinSlippage (u16)
|
|
2117
|
+
const slippageBuf = Buffer.alloc(2);
|
|
2118
|
+
slippageBuf.writeUInt16LE(params.maxActiveBinSlippage, 0);
|
|
2119
|
+
buffers.push(slippageBuf);
|
|
2120
|
+
// shouldClaimFee (bool as u8)
|
|
2121
|
+
buffers.push(Buffer.from([params.shouldClaimFee ? 1 : 0]));
|
|
2122
|
+
// shouldClaimReward (bool as u8)
|
|
2123
|
+
buffers.push(Buffer.from([params.shouldClaimReward ? 1 : 0]));
|
|
2124
|
+
// minWithdrawXAmount (u64)
|
|
2125
|
+
buffers.push(params.minWithdrawXAmount.toArrayLike(Buffer, 'le', 8));
|
|
2126
|
+
// maxDepositXAmount (u64)
|
|
2127
|
+
buffers.push(params.maxDepositXAmount.toArrayLike(Buffer, 'le', 8));
|
|
2128
|
+
// minWithdrawYAmount (u64)
|
|
2129
|
+
buffers.push(params.minWithdrawYAmount.toArrayLike(Buffer, 'le', 8));
|
|
2130
|
+
// maxDepositYAmount (u64)
|
|
2131
|
+
buffers.push(params.maxDepositYAmount.toArrayLike(Buffer, 'le', 8));
|
|
2132
|
+
// shrink_mode (u8) + padding [u8; 31]
|
|
2133
|
+
const paddingBuf = Buffer.alloc(32, 0);
|
|
2134
|
+
paddingBuf[0] = (_a = params.shrinkMode) !== null && _a !== void 0 ? _a : types_1.ShrinkMode.NoShrinkBoth;
|
|
2135
|
+
buffers.push(paddingBuf);
|
|
2136
|
+
// removeLiquidityParams Vec (length as u32, then each RemoveLiquidityParams)
|
|
2137
|
+
const removeLenBuf = Buffer.alloc(4);
|
|
2138
|
+
removeLenBuf.writeUInt32LE(params.removeLiquidityParams.length, 0);
|
|
2139
|
+
buffers.push(removeLenBuf);
|
|
2140
|
+
for (const removeParam of params.removeLiquidityParams) {
|
|
2141
|
+
// minBinId: Option<i32>
|
|
2142
|
+
if (removeParam.minBinId !== undefined) {
|
|
2143
|
+
buffers.push(Buffer.from([1])); // Some
|
|
2144
|
+
const minBinIdBuf = Buffer.alloc(4);
|
|
2145
|
+
minBinIdBuf.writeInt32LE(removeParam.minBinId, 0);
|
|
2146
|
+
buffers.push(minBinIdBuf);
|
|
2147
|
+
}
|
|
2148
|
+
else {
|
|
2149
|
+
buffers.push(Buffer.from([0])); // None
|
|
2150
|
+
}
|
|
2151
|
+
// maxBinId: Option<i32>
|
|
2152
|
+
if (removeParam.maxBinId !== undefined) {
|
|
2153
|
+
buffers.push(Buffer.from([1])); // Some
|
|
2154
|
+
const maxBinIdBuf = Buffer.alloc(4);
|
|
2155
|
+
maxBinIdBuf.writeInt32LE(removeParam.maxBinId, 0);
|
|
2156
|
+
buffers.push(maxBinIdBuf);
|
|
2157
|
+
}
|
|
2158
|
+
else {
|
|
2159
|
+
buffers.push(Buffer.from([0])); // None
|
|
2160
|
+
}
|
|
2161
|
+
// bps (u16)
|
|
2162
|
+
const bpsBuf = Buffer.alloc(2);
|
|
2163
|
+
bpsBuf.writeUInt16LE(removeParam.bps, 0);
|
|
2164
|
+
buffers.push(bpsBuf);
|
|
2165
|
+
// padding [u8; 16]
|
|
2166
|
+
buffers.push(Buffer.alloc(16, 0));
|
|
2167
|
+
}
|
|
2168
|
+
// addLiquidityParams Vec (length as u32, then each AddLiquidityParams)
|
|
2169
|
+
const addLenBuf = Buffer.alloc(4);
|
|
2170
|
+
addLenBuf.writeUInt32LE(params.addLiquidityParams.length, 0);
|
|
2171
|
+
buffers.push(addLenBuf);
|
|
2172
|
+
for (const addParam of params.addLiquidityParams) {
|
|
2173
|
+
// minDeltaId (i32)
|
|
2174
|
+
const minDeltaIdBuf = Buffer.alloc(4);
|
|
2175
|
+
minDeltaIdBuf.writeInt32LE(addParam.minDeltaId, 0);
|
|
2176
|
+
buffers.push(minDeltaIdBuf);
|
|
2177
|
+
// maxDeltaId (i32)
|
|
2178
|
+
const maxDeltaIdBuf = Buffer.alloc(4);
|
|
2179
|
+
maxDeltaIdBuf.writeInt32LE(addParam.maxDeltaId, 0);
|
|
2180
|
+
buffers.push(maxDeltaIdBuf);
|
|
2181
|
+
// x0 (u64)
|
|
2182
|
+
buffers.push(addParam.x0.toArrayLike(Buffer, 'le', 8));
|
|
2183
|
+
// y0 (u64)
|
|
2184
|
+
buffers.push(addParam.y0.toArrayLike(Buffer, 'le', 8));
|
|
2185
|
+
// deltaX (u64)
|
|
2186
|
+
buffers.push(addParam.deltaX.toArrayLike(Buffer, 'le', 8));
|
|
2187
|
+
// deltaY (u64)
|
|
2188
|
+
buffers.push(addParam.deltaY.toArrayLike(Buffer, 'le', 8));
|
|
2189
|
+
// bitFlag (u8)
|
|
2190
|
+
buffers.push(Buffer.from([addParam.bitFlag]));
|
|
2191
|
+
// favorXInActiveId (bool as u8)
|
|
2192
|
+
buffers.push(Buffer.from([addParam.favorXInActiveId ? 1 : 0]));
|
|
2193
|
+
// padding [u8; 16]
|
|
2194
|
+
buffers.push(Buffer.alloc(16, 0));
|
|
2195
|
+
}
|
|
2196
|
+
return Buffer.concat(buffers);
|
|
2197
|
+
}
|
|
2198
|
+
/**
|
|
2199
|
+
* Serialize RemainingAccountsInfo to match Rust struct layout
|
|
2200
|
+
*
|
|
2201
|
+
* The format is a Borsh Vec of AccountsTypeSlice:
|
|
2202
|
+
* - [slices_count: u32] - number of slices
|
|
2203
|
+
* - For each slice: [accountsType: u8 (or u8+u8 for TransferHookMultiReward)][length: u8]
|
|
2204
|
+
*
|
|
2205
|
+
* This is passed directly to Anchor methods which wrap it in another Vec<u8>.
|
|
2206
|
+
*/
|
|
2207
|
+
serializeRemainingAccountsInfo(info) {
|
|
2208
|
+
const buffers = [];
|
|
2209
|
+
// Vec length (u32) - number of slices
|
|
2210
|
+
const lenBuf = Buffer.alloc(4);
|
|
2211
|
+
lenBuf.writeUInt32LE(info.slices.length, 0);
|
|
2212
|
+
buffers.push(lenBuf);
|
|
2213
|
+
// Serialize each slice
|
|
2214
|
+
for (const slice of info.slices) {
|
|
2215
|
+
// AccountsType enum (varies in size)
|
|
2216
|
+
if (slice.accountsType === 3 && slice.multiRewardIndex !== undefined) {
|
|
2217
|
+
// TransferHookMultiReward(u8)
|
|
2218
|
+
buffers.push(Buffer.from([3, slice.multiRewardIndex]));
|
|
2219
|
+
}
|
|
2220
|
+
else {
|
|
2221
|
+
buffers.push(Buffer.from([slice.accountsType]));
|
|
2222
|
+
}
|
|
2223
|
+
// length (u8)
|
|
2224
|
+
buffers.push(Buffer.from([slice.length]));
|
|
2225
|
+
}
|
|
2226
|
+
return Buffer.concat(buffers);
|
|
2227
|
+
}
|
|
2228
|
+
/**
|
|
2229
|
+
* Remove liquidity from a bin range in a Meteora DLMM position via IYF Main's meteora dynamic CPI.
|
|
2230
|
+
*
|
|
2231
|
+
* This instruction withdraws liquidity from the specified bin range.
|
|
2232
|
+
* The bin arrays for the range are automatically derived and included as remaining accounts.
|
|
2233
|
+
*
|
|
2234
|
+
* @param params - RemoveLiquidityByRange2 parameters
|
|
2235
|
+
* @returns TransactionInstruction for the remove_liquidity_by_range2 operation
|
|
2236
|
+
*/
|
|
2237
|
+
removeLiquidityByRange2(_a) {
|
|
2238
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, position, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, fromBinId, toBinId, bpsToRemove, pdaTokenType, remainingAccountsInfo: remainingAccountsInfoParam, }) {
|
|
2239
|
+
var _b, _c;
|
|
2240
|
+
// Initialize Anchor
|
|
2241
|
+
anchor_1.Anchor.initialize(connection);
|
|
2242
|
+
// Generate user PDA
|
|
2243
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
2244
|
+
// Generate user token accounts based on pdaTokenType
|
|
2245
|
+
let userTokenX;
|
|
2246
|
+
let userTokenY;
|
|
2247
|
+
if (pdaTokenType === types_1.TokenType.LTA) {
|
|
2248
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
2249
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
2250
|
+
}
|
|
2251
|
+
else if (pdaTokenType === types_1.TokenType.STA) {
|
|
2252
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenXMint);
|
|
2253
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenYMint);
|
|
2254
|
+
}
|
|
2255
|
+
else {
|
|
2256
|
+
// Default: ATA
|
|
2257
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, tokenXProgram);
|
|
2258
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, tokenYProgram);
|
|
2259
|
+
}
|
|
2260
|
+
// Derive bin array bitmap extension
|
|
2261
|
+
const lowerBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(fromBinId));
|
|
2262
|
+
const upperBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(toBinId));
|
|
2263
|
+
const binArrayBitmapExtension = this.isOverflowDefaultBinArrayBitmap(lowerBinArrayIndex) ||
|
|
2264
|
+
this.isOverflowDefaultBinArrayBitmap(upperBinArrayIndex)
|
|
2265
|
+
? this.pda.meteora.deriveBinArrayBitmapExtension(lbPair)
|
|
2266
|
+
: METEORA_DLMM_PROGRAM;
|
|
2267
|
+
// Derive reserves
|
|
2268
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenXMint, lbPair);
|
|
2269
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenYMint, lbPair);
|
|
2270
|
+
// Derive bin arrays for the range
|
|
2271
|
+
const binArrays = this.pda.meteora.deriveBinArrays(lbPair, fromBinId, toBinId);
|
|
2272
|
+
// Build instruction data: sighash + fromBinId(i32) + toBinId(i32) + bpsToRemove(u16) + remainingAccountsInfo
|
|
2273
|
+
const fromBinIdBuffer = Buffer.alloc(4);
|
|
2274
|
+
fromBinIdBuffer.writeInt32LE(fromBinId, 0);
|
|
2275
|
+
const toBinIdBuffer = Buffer.alloc(4);
|
|
2276
|
+
toBinIdBuffer.writeInt32LE(toBinId, 0);
|
|
2277
|
+
const bpsToRemoveBuffer = Buffer.alloc(2);
|
|
2278
|
+
bpsToRemoveBuffer.writeUInt16LE(bpsToRemove, 0);
|
|
2279
|
+
// Serialize RemainingAccountsInfo
|
|
2280
|
+
// Use provided remainingAccountsInfo or default to empty slices (no transfer hooks)
|
|
2281
|
+
// Note: Bin arrays are passed as regular remaining accounts, NOT in slices
|
|
2282
|
+
const remainingAccountsInfoSerialized = this.serializeRemainingAccountsInfo({
|
|
2283
|
+
slices: (_b = remainingAccountsInfoParam === null || remainingAccountsInfoParam === void 0 ? void 0 : remainingAccountsInfoParam.slices) !== null && _b !== void 0 ? _b : [],
|
|
2284
|
+
});
|
|
2285
|
+
const instructionData = Buffer.concat([
|
|
2286
|
+
Buffer.from(util.sighash('remove_liquidity_by_range2', undefined, true)),
|
|
2287
|
+
fromBinIdBuffer,
|
|
2288
|
+
toBinIdBuffer,
|
|
2289
|
+
bpsToRemoveBuffer,
|
|
2290
|
+
remainingAccountsInfoSerialized,
|
|
2291
|
+
]);
|
|
2292
|
+
// Build raw Meteora instruction
|
|
2293
|
+
// Account order from IDL: position, lbPair, binArrayBitmapExtension, userTokenX, userTokenY,
|
|
2294
|
+
// reserveX, reserveY, tokenXMint, tokenYMint, sender, tokenXProgram, tokenYProgram,
|
|
2295
|
+
// memoProgram, eventAuthority, program + bin arrays as remaining accounts + transfer hook accounts
|
|
2296
|
+
const meteoraIx = new web3.TransactionInstruction({
|
|
2297
|
+
data: instructionData,
|
|
2298
|
+
keys: [
|
|
2299
|
+
{ pubkey: position, isSigner: false, isWritable: true }, // position (Mutable)
|
|
2300
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true }, // lbPair (Mutable)
|
|
2301
|
+
{
|
|
2302
|
+
pubkey: binArrayBitmapExtension,
|
|
2303
|
+
isSigner: false,
|
|
2304
|
+
isWritable: !binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM),
|
|
2305
|
+
}, // binArrayBitmapExtension (optional, writable when real PDA)
|
|
2306
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true }, // userTokenX (Mutable)
|
|
2307
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true }, // userTokenY (Mutable)
|
|
2308
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true }, // reserveX (Mutable)
|
|
2309
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true }, // reserveY (Mutable)
|
|
2310
|
+
{ pubkey: tokenXMint, isSigner: false, isWritable: false }, // tokenXMint
|
|
2311
|
+
{ pubkey: tokenYMint, isSigner: false, isWritable: false }, // tokenYMint
|
|
2312
|
+
{ pubkey: userPda, isSigner: false, isWritable: false }, // sender (Signer - signed by IYF Main)
|
|
2313
|
+
{ pubkey: tokenXProgram, isSigner: false, isWritable: false }, // tokenXProgram
|
|
2314
|
+
{ pubkey: tokenYProgram, isSigner: false, isWritable: false }, // tokenYProgram
|
|
2315
|
+
{ pubkey: addresses_1.MEMO_PROGRAM, isSigner: false, isWritable: false }, // memoProgram
|
|
2316
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: false }, // eventAuthority
|
|
2317
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false }, // program
|
|
2318
|
+
// Bin arrays as remaining accounts
|
|
2319
|
+
...binArrays.map(pubkey => ({
|
|
2320
|
+
pubkey,
|
|
2321
|
+
isSigner: false,
|
|
2322
|
+
isWritable: true,
|
|
2323
|
+
})),
|
|
2324
|
+
// Transfer hook accounts (if any) - order must match slices order
|
|
2325
|
+
...((_c = remainingAccountsInfoParam === null || remainingAccountsInfoParam === void 0 ? void 0 : remainingAccountsInfoParam.accounts) !== null && _c !== void 0 ? _c : []),
|
|
2326
|
+
],
|
|
2327
|
+
programId: METEORA_DLMM_PROGRAM,
|
|
2328
|
+
});
|
|
2329
|
+
return yield this.ix.iyfMain.meteoraDynamicCpi({
|
|
2330
|
+
connection,
|
|
2331
|
+
userWallet,
|
|
2332
|
+
meteoraIx,
|
|
2333
|
+
});
|
|
2334
|
+
});
|
|
2335
|
+
}
|
|
2336
|
+
/**
|
|
2337
|
+
* Close an empty Meteora DLMM position via IYF Main's meteora dynamic CPI.
|
|
2338
|
+
*
|
|
2339
|
+
* This instruction closes a position and returns the rent to the user.
|
|
2340
|
+
* The position must be empty (no liquidity) for this to succeed.
|
|
2341
|
+
*
|
|
2342
|
+
* @param params - ClosePosition2 parameters
|
|
2343
|
+
* @returns TransactionInstruction for the close_position2 operation
|
|
2344
|
+
*/
|
|
2345
|
+
closePosition2(_a) {
|
|
2346
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, position, }) {
|
|
2347
|
+
// Initialize Anchor
|
|
2348
|
+
anchor_1.Anchor.initialize(connection);
|
|
2349
|
+
// Generate user PDA
|
|
2350
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
2351
|
+
// Build instruction data: sighash only (no args)
|
|
2352
|
+
const instructionData = Buffer.from(util.sighash('close_position2', undefined, true));
|
|
2353
|
+
// Build raw Meteora instruction
|
|
2354
|
+
// Account order from IDL: position, sender, rentReceiver, eventAuthority, program
|
|
2355
|
+
const meteoraIx = new web3.TransactionInstruction({
|
|
2356
|
+
data: instructionData,
|
|
2357
|
+
keys: [
|
|
2358
|
+
{ pubkey: position, isSigner: false, isWritable: true }, // position (Mutable)
|
|
2359
|
+
{ pubkey: userPda, isSigner: false, isWritable: false }, // sender (Signer - signed by IYF Main)
|
|
2360
|
+
{ pubkey: userWallet, isSigner: false, isWritable: true }, // rentReceiver (Mutable)
|
|
2361
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: false }, // eventAuthority
|
|
2362
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false }, // program
|
|
2363
|
+
],
|
|
2364
|
+
programId: METEORA_DLMM_PROGRAM,
|
|
2365
|
+
});
|
|
2366
|
+
return yield this.ix.iyfMain.meteoraDynamicCpi({
|
|
2367
|
+
connection,
|
|
2368
|
+
userWallet,
|
|
2369
|
+
meteoraIx,
|
|
2370
|
+
});
|
|
2371
|
+
});
|
|
2372
|
+
}
|
|
2373
|
+
/**
|
|
2374
|
+
* Close a Meteora DLMM position only if it is empty via IYF Main's meteora dynamic CPI.
|
|
2375
|
+
*
|
|
2376
|
+
* This instruction is similar to closePosition2 but will fail silently if the position
|
|
2377
|
+
* still has liquidity. This is useful for safely attempting to close a position without
|
|
2378
|
+
* knowing its current state.
|
|
2379
|
+
*
|
|
2380
|
+
* @param params - ClosePositionIfEmpty parameters
|
|
2381
|
+
* @returns TransactionInstruction for the close_position_if_empty operation
|
|
2382
|
+
*/
|
|
2383
|
+
closePositionIfEmpty(_a) {
|
|
2384
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, position, }) {
|
|
2385
|
+
// Initialize Anchor
|
|
2386
|
+
anchor_1.Anchor.initialize(connection);
|
|
2387
|
+
// Generate user PDA
|
|
2388
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
2389
|
+
// Build instruction data: sighash only (no args)
|
|
2390
|
+
const instructionData = Buffer.from(util.sighash('close_position_if_empty'));
|
|
2391
|
+
// Build raw Meteora instruction
|
|
2392
|
+
// Account order from IDL: position, sender, rentReceiver, eventAuthority, program
|
|
2393
|
+
const meteoraIx = new web3.TransactionInstruction({
|
|
2394
|
+
data: instructionData,
|
|
2395
|
+
keys: [
|
|
2396
|
+
{ pubkey: position, isSigner: false, isWritable: true }, // position (Mutable)
|
|
2397
|
+
{ pubkey: userPda, isSigner: false, isWritable: false }, // sender (Signer - signed by IYF Main)
|
|
2398
|
+
{ pubkey: userWallet, isSigner: false, isWritable: true }, // rentReceiver (Mutable)
|
|
2399
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: false }, // eventAuthority
|
|
2400
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false }, // program
|
|
2401
|
+
],
|
|
2402
|
+
programId: METEORA_DLMM_PROGRAM,
|
|
2403
|
+
});
|
|
2404
|
+
return yield this.ix.iyfMain.meteoraDynamicCpi({
|
|
2405
|
+
connection,
|
|
2406
|
+
userWallet,
|
|
2407
|
+
meteoraIx,
|
|
2408
|
+
});
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
/**
|
|
2412
|
+
* Rebalance liquidity in a Meteora DLMM position via IYF Extension for automation.
|
|
2413
|
+
*
|
|
2414
|
+
* This is the automation version that uses HS_AUTHORITY as the signer.
|
|
2415
|
+
* Wraps via iyfExtensionExecuteV2 instead of meteoraDynamicCpi.
|
|
2416
|
+
*
|
|
2417
|
+
* @param params - RebalanceLiquidityIxParams containing all necessary accounts and parameters
|
|
2418
|
+
* @returns TransactionInstruction for the rebalance_liquidity automation operation
|
|
2419
|
+
*/
|
|
2420
|
+
rebalanceLiquidityAutomation(_a) {
|
|
2421
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, position, lbPair, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, activeId, pdaTokenType, maxActiveBinSlippage, shouldClaimFee, shouldClaimReward, minWithdrawXAmount, maxDepositXAmount, minWithdrawYAmount, maxDepositYAmount, removeLiquidityParams, addLiquidityParams, shrinkMode, rewardInfos, remainingAccountsInfo, }) {
|
|
2422
|
+
var _b, _c;
|
|
2423
|
+
// Initialize Anchor
|
|
2424
|
+
anchor_1.Anchor.initialize(connection);
|
|
2425
|
+
// Generate user PDA
|
|
2426
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
2427
|
+
// Generate user token accounts based on pdaTokenType
|
|
2428
|
+
let userTokenX;
|
|
2429
|
+
let userTokenY;
|
|
2430
|
+
if (pdaTokenType === types_1.TokenType.LTA) {
|
|
2431
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
2432
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
2433
|
+
}
|
|
2434
|
+
else if (pdaTokenType === types_1.TokenType.STA) {
|
|
2435
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenXMint);
|
|
2436
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenYMint);
|
|
2437
|
+
}
|
|
2438
|
+
else {
|
|
2439
|
+
// Default: ATA
|
|
2440
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, tokenXProgram);
|
|
2441
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, tokenYProgram);
|
|
2442
|
+
}
|
|
2443
|
+
// Collect all bin IDs from both remove and add params
|
|
2444
|
+
const allBinIds = [];
|
|
2445
|
+
for (const p of removeLiquidityParams) {
|
|
2446
|
+
if (p.minBinId !== undefined && p.maxBinId !== undefined) {
|
|
2447
|
+
allBinIds.push(p.minBinId, p.maxBinId);
|
|
2448
|
+
}
|
|
2449
|
+
else {
|
|
2450
|
+
if (p.minBinId === undefined) {
|
|
2451
|
+
throw new Error(`rebalanceLiquidityAutomation: removeLiquidityParams.minBinid is not optional.`);
|
|
2452
|
+
}
|
|
2453
|
+
else {
|
|
2454
|
+
throw new Error(`rebalanceLiquidityAutomation: removeLiquidityParams.maxBinId is not optional.`);
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
for (const p of addLiquidityParams) {
|
|
2459
|
+
allBinIds.push(activeId + p.minDeltaId, activeId + p.maxDeltaId);
|
|
2460
|
+
}
|
|
2461
|
+
if (allBinIds.length === 0) {
|
|
2462
|
+
throw new Error('rebalanceLiquidityAutomation: both removeLiquidityParams and addLiquidityParams are empty');
|
|
2463
|
+
}
|
|
2464
|
+
const minBinId = Math.min(...allBinIds);
|
|
2465
|
+
const maxBinId = Math.max(...allBinIds);
|
|
2466
|
+
// Derive bin array bitmap extension
|
|
2467
|
+
const lowerBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(minBinId));
|
|
2468
|
+
const upperBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(maxBinId));
|
|
2469
|
+
const binArrayBitmapExtension = this.isOverflowDefaultBinArrayBitmap(lowerBinArrayIndex) ||
|
|
2470
|
+
this.isOverflowDefaultBinArrayBitmap(upperBinArrayIndex)
|
|
2471
|
+
? this.pda.meteora.deriveBinArrayBitmapExtension(lbPair)
|
|
2472
|
+
: METEORA_DLMM_PROGRAM;
|
|
2473
|
+
// Derive reserves
|
|
2474
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenXMint, lbPair);
|
|
2475
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenYMint, lbPair);
|
|
2476
|
+
let binArrays;
|
|
2477
|
+
const lowerBinId = minBinId;
|
|
2478
|
+
const upperBinId = maxBinId;
|
|
2479
|
+
binArrays = this.pda.meteora.deriveBinArrays(lbPair, lowerBinId, upperBinId);
|
|
2480
|
+
// Build reward remaining accounts if shouldClaimReward and rewardInfos provided
|
|
2481
|
+
const rewardRemainingAccounts = [];
|
|
2482
|
+
if (shouldClaimReward && rewardInfos && rewardInfos.length > 0) {
|
|
2483
|
+
console.log(`[rebalanceLiquidityAutomation] Building reward accounts for ${rewardInfos.length} reward(s)`);
|
|
2484
|
+
for (const reward of rewardInfos) {
|
|
2485
|
+
// User reward token account (ATA or STA based on pdaTokenType)
|
|
2486
|
+
let userRewardToken = (0, functions_1.generateUserPdaStorageAccount)(userPda, reward.rewardMint);
|
|
2487
|
+
console.log(`[rebalanceLiquidityAutomation] Reward: vault=${reward.rewardVault.toString()}, userToken=${userRewardToken.toString()}, mint=${reward.rewardMint.toString()}, program=${reward.rewardTokenProgram.toString()}`);
|
|
2488
|
+
// Add reward accounts in order: vault, userToken, mint, tokenProgram
|
|
2489
|
+
rewardRemainingAccounts.push({ pubkey: reward.rewardVault, isSigner: false, isWritable: true }, { pubkey: userRewardToken, isSigner: false, isWritable: true }, { pubkey: reward.rewardMint, isSigner: false, isWritable: false }, {
|
|
2490
|
+
pubkey: reward.rewardTokenProgram,
|
|
2491
|
+
isSigner: false,
|
|
2492
|
+
isWritable: false,
|
|
2493
|
+
});
|
|
2494
|
+
}
|
|
2495
|
+
console.log(`[rebalanceLiquidityAutomation] Total reward remaining accounts: ${rewardRemainingAccounts.length}`);
|
|
2496
|
+
}
|
|
2497
|
+
else if (shouldClaimReward) {
|
|
2498
|
+
console.log(`[rebalanceLiquidityAutomation] shouldClaimReward=true but no rewardInfos provided!`);
|
|
2499
|
+
}
|
|
2500
|
+
// Serialize RebalanceLiquidityParams
|
|
2501
|
+
const rebalanceParamsData = this.serializeRebalanceLiquidityParams({
|
|
2502
|
+
activeId,
|
|
2503
|
+
maxActiveBinSlippage,
|
|
2504
|
+
shouldClaimFee,
|
|
2505
|
+
shouldClaimReward,
|
|
2506
|
+
minWithdrawXAmount,
|
|
2507
|
+
maxDepositXAmount,
|
|
2508
|
+
minWithdrawYAmount,
|
|
2509
|
+
maxDepositYAmount,
|
|
2510
|
+
shrinkMode,
|
|
2511
|
+
removeLiquidityParams,
|
|
2512
|
+
addLiquidityParams,
|
|
2513
|
+
});
|
|
2514
|
+
// Serialize RemainingAccountsInfo from passed parameter or use empty slices
|
|
2515
|
+
const serializedRemainingAccountsInfo = this.serializeRemainingAccountsInfo({
|
|
2516
|
+
slices: (_b = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.slices) !== null && _b !== void 0 ? _b : [],
|
|
2517
|
+
});
|
|
2518
|
+
// Build instruction data: sighash + RebalanceLiquidityParams + RemainingAccountsInfo
|
|
2519
|
+
// The handler takes two typed Anchor args (not Vec<u8>), so no length prefix needed.
|
|
2520
|
+
const instructionData = Buffer.concat([
|
|
2521
|
+
Buffer.from(util.sighash('meteora_dlmm_rebalance_liquidity_automation')),
|
|
2522
|
+
rebalanceParamsData,
|
|
2523
|
+
serializedRemainingAccountsInfo,
|
|
2524
|
+
]);
|
|
2525
|
+
// Generate instruction via IYF Extension
|
|
2526
|
+
return this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
2527
|
+
userPda,
|
|
2528
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
2529
|
+
ix: new web3.TransactionInstruction({
|
|
2530
|
+
data: instructionData,
|
|
2531
|
+
keys: [
|
|
2532
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
2533
|
+
{ pubkey: addresses_1.HS_AUTHORITY, isSigner: true, isWritable: true },
|
|
2534
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
2535
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
2536
|
+
{
|
|
2537
|
+
pubkey: binArrayBitmapExtension,
|
|
2538
|
+
isSigner: false,
|
|
2539
|
+
isWritable: !binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM),
|
|
2540
|
+
},
|
|
2541
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true },
|
|
2542
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true },
|
|
2543
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true },
|
|
2544
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true },
|
|
2545
|
+
{ pubkey: tokenXMint, isSigner: false, isWritable: false },
|
|
2546
|
+
{ pubkey: tokenYMint, isSigner: false, isWritable: false },
|
|
2547
|
+
{ pubkey: tokenXProgram, isSigner: false, isWritable: false },
|
|
2548
|
+
{ pubkey: tokenYProgram, isSigner: false, isWritable: false },
|
|
2549
|
+
{ pubkey: addresses_1.MEMO_PROGRAM, isSigner: false, isWritable: false },
|
|
2550
|
+
{
|
|
2551
|
+
pubkey: web3.SystemProgram.programId,
|
|
2552
|
+
isSigner: false,
|
|
2553
|
+
isWritable: false,
|
|
2554
|
+
},
|
|
2555
|
+
{
|
|
2556
|
+
pubkey: METEORA_EVENT_AUTHORITY,
|
|
2557
|
+
isSigner: false,
|
|
2558
|
+
isWritable: false,
|
|
2559
|
+
},
|
|
2560
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
2561
|
+
// Transfer hook accounts (from fetchRemainingAccountsInfo)
|
|
2562
|
+
...((_c = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.accounts) !== null && _c !== void 0 ? _c : []),
|
|
2563
|
+
// Bin arrays as remaining accounts
|
|
2564
|
+
...binArrays.map(pubkey => ({
|
|
2565
|
+
pubkey,
|
|
2566
|
+
isSigner: false,
|
|
2567
|
+
isWritable: true,
|
|
2568
|
+
})),
|
|
2569
|
+
// Boundary account
|
|
2570
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
2571
|
+
// Reward accounts after boundary account
|
|
2572
|
+
...rewardRemainingAccounts,
|
|
2573
|
+
],
|
|
2574
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
2575
|
+
}),
|
|
2576
|
+
});
|
|
2577
|
+
});
|
|
2578
|
+
}
|
|
2579
|
+
/**
|
|
2580
|
+
* Remove liquidity from a bin range in a Meteora DLMM position via IYF Extension for automation.
|
|
2581
|
+
*
|
|
2582
|
+
* This is the automation version that uses HS_AUTHORITY as the signer.
|
|
2583
|
+
* Supports larger bin ranges (not limited to 70-bin chunks).
|
|
2584
|
+
*
|
|
2585
|
+
* @param params - RemoveLiquidityByRange2AutomationParams parameters
|
|
2586
|
+
* @returns TransactionInstruction for the remove_liquidity_by_range2 automation operation
|
|
2587
|
+
*/
|
|
2588
|
+
removeLiquidityByRange2Automation(_a) {
|
|
2589
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, position, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, fromBinId, toBinId, bpsToRemove, pdaTokenType, remainingAccountsInfo, }) {
|
|
2590
|
+
var _b, _c;
|
|
2591
|
+
// Initialize Anchor
|
|
2592
|
+
anchor_1.Anchor.initialize(connection);
|
|
2593
|
+
// Generate user PDA
|
|
2594
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
2595
|
+
// Generate user token accounts based on pdaTokenType
|
|
2596
|
+
let userTokenX;
|
|
2597
|
+
let userTokenY;
|
|
2598
|
+
if (pdaTokenType === types_1.TokenType.LTA) {
|
|
2599
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
2600
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
2601
|
+
}
|
|
2602
|
+
else if (pdaTokenType === types_1.TokenType.STA) {
|
|
2603
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenXMint);
|
|
2604
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenYMint);
|
|
2605
|
+
}
|
|
2606
|
+
else {
|
|
2607
|
+
// Default: ATA
|
|
2608
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, tokenXProgram);
|
|
2609
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, tokenYProgram);
|
|
2610
|
+
}
|
|
2611
|
+
// Derive bin array bitmap extension
|
|
2612
|
+
const lowerBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(fromBinId));
|
|
2613
|
+
const upperBinArrayIndex = this.binIdToBinArrayIndex(new bn_js_1.default(toBinId));
|
|
2614
|
+
const binArrayBitmapExtension = this.isOverflowDefaultBinArrayBitmap(lowerBinArrayIndex) ||
|
|
2615
|
+
this.isOverflowDefaultBinArrayBitmap(upperBinArrayIndex)
|
|
2616
|
+
? this.pda.meteora.deriveBinArrayBitmapExtension(lbPair)
|
|
2617
|
+
: METEORA_DLMM_PROGRAM;
|
|
2618
|
+
// Derive reserves
|
|
2619
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenXMint, lbPair);
|
|
2620
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenYMint, lbPair);
|
|
2621
|
+
// Derive bin arrays for the range
|
|
2622
|
+
const binArrays = this.pda.meteora.deriveBinArrays(lbPair, fromBinId, toBinId);
|
|
2623
|
+
// Build instruction data: fromBinId(i32) + toBinId(i32) + bpsToRemove(u16) + remainingAccountsInfo
|
|
2624
|
+
const fromBinIdBuffer = Buffer.alloc(4);
|
|
2625
|
+
fromBinIdBuffer.writeInt32LE(fromBinId, 0);
|
|
2626
|
+
const toBinIdBuffer = Buffer.alloc(4);
|
|
2627
|
+
toBinIdBuffer.writeInt32LE(toBinId, 0);
|
|
2628
|
+
const bpsToRemoveBuffer = Buffer.alloc(2);
|
|
2629
|
+
bpsToRemoveBuffer.writeUInt16LE(bpsToRemove, 0);
|
|
2630
|
+
// Serialize RemainingAccountsInfo
|
|
2631
|
+
const remainingAccountsInfoSerialized = this.serializeRemainingAccountsInfo({
|
|
2632
|
+
slices: (_b = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.slices) !== null && _b !== void 0 ? _b : [],
|
|
2633
|
+
});
|
|
2634
|
+
const instructionData = Buffer.concat([
|
|
2635
|
+
fromBinIdBuffer,
|
|
2636
|
+
toBinIdBuffer,
|
|
2637
|
+
bpsToRemoveBuffer,
|
|
2638
|
+
remainingAccountsInfoSerialized,
|
|
2639
|
+
]);
|
|
2640
|
+
// For Anchor Vec<u8> parameter, we need to prepend the length as u32 LE
|
|
2641
|
+
const instructionDataVec = Buffer.alloc(4 + instructionData.length);
|
|
2642
|
+
instructionDataVec.writeUInt32LE(instructionData.length, 0);
|
|
2643
|
+
instructionData.copy(instructionDataVec, 4);
|
|
2644
|
+
// Generate instruction via IYF Extension
|
|
2645
|
+
return this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
2646
|
+
userPda,
|
|
2647
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
2648
|
+
ix: new web3.TransactionInstruction({
|
|
2649
|
+
data: Buffer.concat([
|
|
2650
|
+
Buffer.from(util.sighash('meteora_dlmm_withdraw_2_automation')),
|
|
2651
|
+
instructionDataVec,
|
|
2652
|
+
]),
|
|
2653
|
+
keys: [
|
|
2654
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
2655
|
+
{ pubkey: addresses_1.HS_AUTHORITY, isSigner: true, isWritable: true },
|
|
2656
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
2657
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
2658
|
+
{
|
|
2659
|
+
pubkey: binArrayBitmapExtension,
|
|
2660
|
+
isSigner: false,
|
|
2661
|
+
isWritable: !binArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM),
|
|
2662
|
+
},
|
|
2663
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true },
|
|
2664
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true },
|
|
2665
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true },
|
|
2666
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true },
|
|
2667
|
+
{ pubkey: tokenXMint, isSigner: false, isWritable: false },
|
|
2668
|
+
{ pubkey: tokenYMint, isSigner: false, isWritable: false },
|
|
2669
|
+
{ pubkey: tokenXProgram, isSigner: false, isWritable: false },
|
|
2670
|
+
{ pubkey: tokenYProgram, isSigner: false, isWritable: false },
|
|
2671
|
+
{
|
|
2672
|
+
pubkey: METEORA_EVENT_AUTHORITY,
|
|
2673
|
+
isSigner: false,
|
|
2674
|
+
isWritable: false,
|
|
2675
|
+
},
|
|
2676
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: false },
|
|
2677
|
+
{ pubkey: addresses_1.MEMO_PROGRAM, isSigner: false, isWritable: false },
|
|
2678
|
+
// Bin arrays as remaining accounts
|
|
2679
|
+
...binArrays.map(pubkey => ({
|
|
2680
|
+
pubkey,
|
|
2681
|
+
isSigner: false,
|
|
2682
|
+
isWritable: true,
|
|
2683
|
+
})),
|
|
2684
|
+
// Transfer hook accounts (if any)
|
|
2685
|
+
...((_c = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.accounts) !== null && _c !== void 0 ? _c : []),
|
|
2686
|
+
],
|
|
2687
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
2688
|
+
}),
|
|
2689
|
+
});
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
addLiquidity2Automation(_a) {
|
|
2693
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, position, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, layers, checkRange, userTokenXAmount, userTokenYAmount, chunkLowerOffset, chunkUpperOffset, remainingAccountsInfo, pdaTokenType, lowerBinId, upperBinId, }) {
|
|
2694
|
+
var _b, _c;
|
|
2695
|
+
anchor_1.Anchor.initialize(connection);
|
|
2696
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenXMint, lbPair);
|
|
2697
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenYMint, lbPair);
|
|
2698
|
+
const derivedBinArrayBitmapExtension = this.pda.meteora.deriveBinArrayBitmapExtension(lbPair);
|
|
2699
|
+
const binArrayBitmapExtensionInfo = yield connection.getAccountInfo(derivedBinArrayBitmapExtension);
|
|
2700
|
+
const actualBinArrayBitmapExtension = binArrayBitmapExtensionInfo
|
|
2701
|
+
? derivedBinArrayBitmapExtension
|
|
2702
|
+
: METEORA_DLMM_PROGRAM;
|
|
2703
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
2704
|
+
let userTokenX;
|
|
2705
|
+
let userTokenY;
|
|
2706
|
+
if (pdaTokenType === types_1.TokenType.LTA) {
|
|
2707
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
2708
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
2709
|
+
}
|
|
2710
|
+
else if (pdaTokenType === types_1.TokenType.STA) {
|
|
2711
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenXMint);
|
|
2712
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenYMint);
|
|
2713
|
+
}
|
|
2714
|
+
else {
|
|
2715
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, tokenXProgram);
|
|
2716
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, tokenYProgram);
|
|
2717
|
+
}
|
|
2718
|
+
// --- Serialize instruction data ---
|
|
2719
|
+
const sighash = Buffer.from(util.sighash('meteora_dlmm_add_liquidity_2_automation'));
|
|
2720
|
+
layers.forEach((layer, index) => {
|
|
2721
|
+
const validateByteField = (fieldName, value, maxValue) => {
|
|
2722
|
+
if (!Number.isInteger(value) || value < 0 || value > maxValue) {
|
|
2723
|
+
throw new Error(`layers[${index}].${fieldName} must be an integer between 0 and ${maxValue}`);
|
|
2724
|
+
}
|
|
2725
|
+
};
|
|
2726
|
+
validateByteField('strategyTypeX', layer.strategyTypeX, 255);
|
|
2727
|
+
validateByteField('strategyTypeY', layer.strategyTypeY, 255);
|
|
2728
|
+
validateByteField('percentageX', layer.percentageX, 100);
|
|
2729
|
+
validateByteField('percentageY', layer.percentageY, 100);
|
|
2730
|
+
});
|
|
2731
|
+
// Vec<HybridLayer>: u32 length + 4 u8s per layer
|
|
2732
|
+
const layersLenBuf = Buffer.alloc(4);
|
|
2733
|
+
layersLenBuf.writeUInt32LE(layers.length, 0);
|
|
2734
|
+
const layersBuf = Buffer.concat([
|
|
2735
|
+
layersLenBuf,
|
|
2736
|
+
...layers.map(l => Buffer.from([
|
|
2737
|
+
l.strategyTypeX,
|
|
2738
|
+
l.strategyTypeY,
|
|
2739
|
+
l.percentageX,
|
|
2740
|
+
l.percentageY,
|
|
2741
|
+
])),
|
|
2742
|
+
]);
|
|
2743
|
+
// Option<[i32; 2]> check_range
|
|
2744
|
+
const checkRangeBuf = checkRange
|
|
2745
|
+
? (() => {
|
|
2746
|
+
const buf = Buffer.alloc(9);
|
|
2747
|
+
buf.writeUInt8(1, 0);
|
|
2748
|
+
buf.writeInt32LE(checkRange.lowerRange, 1);
|
|
2749
|
+
buf.writeInt32LE(checkRange.upperRange, 5);
|
|
2750
|
+
return buf;
|
|
2751
|
+
})()
|
|
2752
|
+
: Buffer.from([0]);
|
|
2753
|
+
// Option<u64> user_token_x_amount
|
|
2754
|
+
const xAmountBuf = userTokenXAmount
|
|
2755
|
+
? Buffer.concat([
|
|
2756
|
+
Buffer.from([1]),
|
|
2757
|
+
Buffer.from(userTokenXAmount.toArrayLike(Buffer, 'le', 8)),
|
|
2758
|
+
])
|
|
2759
|
+
: Buffer.from([0]);
|
|
2760
|
+
// Option<u64> user_token_y_amount
|
|
2761
|
+
const yAmountBuf = userTokenYAmount
|
|
2762
|
+
? Buffer.concat([
|
|
2763
|
+
Buffer.from([1]),
|
|
2764
|
+
Buffer.from(userTokenYAmount.toArrayLike(Buffer, 'le', 8)),
|
|
2765
|
+
])
|
|
2766
|
+
: Buffer.from([0]);
|
|
2767
|
+
// Option<i32> chunk_lower_offset
|
|
2768
|
+
const chunkLowerBuf = chunkLowerOffset !== undefined
|
|
2769
|
+
? (() => {
|
|
2770
|
+
const b = Buffer.alloc(5);
|
|
2771
|
+
b.writeUInt8(1, 0);
|
|
2772
|
+
b.writeInt32LE(chunkLowerOffset, 1);
|
|
2773
|
+
return b;
|
|
2774
|
+
})()
|
|
2775
|
+
: Buffer.from([0]);
|
|
2776
|
+
// Option<i32> chunk_upper_offset
|
|
2777
|
+
const chunkUpperBuf = chunkUpperOffset !== undefined
|
|
2778
|
+
? (() => {
|
|
2779
|
+
const b = Buffer.alloc(5);
|
|
2780
|
+
b.writeUInt8(1, 0);
|
|
2781
|
+
b.writeInt32LE(chunkUpperOffset, 1);
|
|
2782
|
+
return b;
|
|
2783
|
+
})()
|
|
2784
|
+
: Buffer.from([0]);
|
|
2785
|
+
// Vec<u8> remaining_accounts_info — needs u32 Vec length prefix (like depositRelativeAutomation)
|
|
2786
|
+
const defaultSlices = [
|
|
2787
|
+
{ accountsType: 0, length: 0 },
|
|
2788
|
+
{ accountsType: 1, length: 0 },
|
|
2789
|
+
];
|
|
2790
|
+
const remainingAccountsInfoSerialized = this.serializeRemainingAccountsInfo({
|
|
2791
|
+
slices: (_b = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.slices) !== null && _b !== void 0 ? _b : defaultSlices,
|
|
2792
|
+
});
|
|
2793
|
+
const raiLenBuf = Buffer.alloc(4);
|
|
2794
|
+
raiLenBuf.writeUInt32LE(remainingAccountsInfoSerialized.length, 0);
|
|
2795
|
+
const remainingAccountsInfoWithLength = Buffer.concat([
|
|
2796
|
+
raiLenBuf,
|
|
2797
|
+
remainingAccountsInfoSerialized,
|
|
2798
|
+
]);
|
|
2799
|
+
// --- Bin arrays ---
|
|
2800
|
+
const binArrays = meteora_1.MeteoraFunctions.findMeteoraTickArrays(lbPair, lowerBinId, upperBinId);
|
|
2801
|
+
const binArrayAccounts = binArrays.map(binArray => ({
|
|
2802
|
+
pubkey: binArray,
|
|
2803
|
+
isSigner: false,
|
|
2804
|
+
isWritable: true,
|
|
2805
|
+
}));
|
|
2806
|
+
const transferHookAccounts = (_c = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.accounts) !== null && _c !== void 0 ? _c : [];
|
|
2807
|
+
// --- Assemble instruction ---
|
|
2808
|
+
// Account order matches contract MeteoraDlmmAddLiquidity2Automation (meteora.rs:3699)
|
|
2809
|
+
// Same order as meteoraDlmmDepositRelativeAutomation (line 809)
|
|
2810
|
+
const ix = new web3.TransactionInstruction({
|
|
2811
|
+
data: Buffer.concat([
|
|
2812
|
+
sighash,
|
|
2813
|
+
layersBuf,
|
|
2814
|
+
checkRangeBuf,
|
|
2815
|
+
xAmountBuf,
|
|
2816
|
+
yAmountBuf,
|
|
2817
|
+
chunkLowerBuf,
|
|
2818
|
+
chunkUpperBuf,
|
|
2819
|
+
remainingAccountsInfoWithLength,
|
|
2820
|
+
]),
|
|
2821
|
+
keys: [
|
|
2822
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
2823
|
+
{ pubkey: addresses_1.HS_AUTHORITY, isSigner: true, isWritable: true },
|
|
2824
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
2825
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
2826
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true },
|
|
2827
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true },
|
|
2828
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true },
|
|
2829
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true },
|
|
2830
|
+
{ pubkey: tokenXMint, isSigner: false, isWritable: false },
|
|
2831
|
+
{ pubkey: tokenYMint, isSigner: false, isWritable: false },
|
|
2832
|
+
{ pubkey: tokenXProgram, isSigner: false, isWritable: false },
|
|
2833
|
+
{ pubkey: tokenYProgram, isSigner: false, isWritable: false },
|
|
2834
|
+
{
|
|
2835
|
+
pubkey: actualBinArrayBitmapExtension,
|
|
2836
|
+
isSigner: false,
|
|
2837
|
+
isWritable: !actualBinArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM),
|
|
2838
|
+
},
|
|
2839
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: true },
|
|
2840
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: true },
|
|
2841
|
+
...transferHookAccounts,
|
|
2842
|
+
...binArrayAccounts,
|
|
2843
|
+
],
|
|
2844
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
2845
|
+
});
|
|
2846
|
+
return this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
2847
|
+
userPda,
|
|
2848
|
+
authority: addresses_1.HS_AUTHORITY,
|
|
2849
|
+
ix,
|
|
2850
|
+
});
|
|
2851
|
+
});
|
|
2852
|
+
}
|
|
2853
|
+
/**
|
|
2854
|
+
* FE-callable mirror of addLiquidity2Automation.
|
|
2855
|
+
* Same hybrid-layer add-liquidity flow, but signed by the user's wallet
|
|
2856
|
+
* instead of HS_AUTHORITY (sighash: meteora_dlmm_add_liquidity_2).
|
|
2857
|
+
*/
|
|
2858
|
+
addLiquidity2(_a) {
|
|
2859
|
+
return __awaiter(this, arguments, void 0, function* ({ connection, userWallet, lbPair, position, tokenXMint, tokenYMint, tokenXProgram, tokenYProgram, layers, checkRange, userTokenXAmount, userTokenYAmount, chunkLowerOffset, chunkUpperOffset, remainingAccountsInfo, pdaTokenType, lowerBinId, upperBinId, }) {
|
|
2860
|
+
var _b, _c;
|
|
2861
|
+
anchor_1.Anchor.initialize(connection);
|
|
2862
|
+
const reserveX = this.pda.meteora.deriveReserve(tokenXMint, lbPair);
|
|
2863
|
+
const reserveY = this.pda.meteora.deriveReserve(tokenYMint, lbPair);
|
|
2864
|
+
const derivedBinArrayBitmapExtension = this.pda.meteora.deriveBinArrayBitmapExtension(lbPair);
|
|
2865
|
+
const binArrayBitmapExtensionInfo = yield connection.getAccountInfo(derivedBinArrayBitmapExtension);
|
|
2866
|
+
const actualBinArrayBitmapExtension = binArrayBitmapExtensionInfo
|
|
2867
|
+
? derivedBinArrayBitmapExtension
|
|
2868
|
+
: METEORA_DLMM_PROGRAM;
|
|
2869
|
+
const userPda = (0, functions_1.generateUserPda)(userWallet);
|
|
2870
|
+
let userTokenX;
|
|
2871
|
+
let userTokenY;
|
|
2872
|
+
if (pdaTokenType === types_1.TokenType.LTA) {
|
|
2873
|
+
userTokenX = (0, functions_1.generateLimitToken)(userPda, tokenXMint);
|
|
2874
|
+
userTokenY = (0, functions_1.generateLimitToken)(userPda, tokenYMint);
|
|
2875
|
+
}
|
|
2876
|
+
else if (pdaTokenType === types_1.TokenType.STA) {
|
|
2877
|
+
userTokenX = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenXMint);
|
|
2878
|
+
userTokenY = (0, functions_1.generateUserPdaStorageAccount)(userPda, tokenYMint);
|
|
2879
|
+
}
|
|
2880
|
+
else {
|
|
2881
|
+
userTokenX = (0, functions_1.generateAta)(userPda, tokenXMint, tokenXProgram);
|
|
2882
|
+
userTokenY = (0, functions_1.generateAta)(userPda, tokenYMint, tokenYProgram);
|
|
2883
|
+
}
|
|
2884
|
+
const sighash = Buffer.from(util.sighash('meteora_dlmm_add_liquidity_2'));
|
|
2885
|
+
layers.forEach((layer, index) => {
|
|
2886
|
+
const validateByteField = (fieldName, value, maxValue) => {
|
|
2887
|
+
if (!Number.isInteger(value) || value < 0 || value > maxValue) {
|
|
2888
|
+
throw new Error(`layers[${index}].${fieldName} must be an integer between 0 and ${maxValue}`);
|
|
2889
|
+
}
|
|
2890
|
+
};
|
|
2891
|
+
validateByteField('strategyTypeX', layer.strategyTypeX, 255);
|
|
2892
|
+
validateByteField('strategyTypeY', layer.strategyTypeY, 255);
|
|
2893
|
+
validateByteField('percentageX', layer.percentageX, 100);
|
|
2894
|
+
validateByteField('percentageY', layer.percentageY, 100);
|
|
2895
|
+
});
|
|
2896
|
+
const layersLenBuf = Buffer.alloc(4);
|
|
2897
|
+
layersLenBuf.writeUInt32LE(layers.length, 0);
|
|
2898
|
+
const layersBuf = Buffer.concat([
|
|
2899
|
+
layersLenBuf,
|
|
2900
|
+
...layers.map(l => Buffer.from([
|
|
2901
|
+
l.strategyTypeX,
|
|
2902
|
+
l.strategyTypeY,
|
|
2903
|
+
l.percentageX,
|
|
2904
|
+
l.percentageY,
|
|
2905
|
+
])),
|
|
2906
|
+
]);
|
|
2907
|
+
const checkRangeBuf = checkRange
|
|
2908
|
+
? (() => {
|
|
2909
|
+
const buf = Buffer.alloc(9);
|
|
2910
|
+
buf.writeUInt8(1, 0);
|
|
2911
|
+
buf.writeInt32LE(checkRange.lowerRange, 1);
|
|
2912
|
+
buf.writeInt32LE(checkRange.upperRange, 5);
|
|
2913
|
+
return buf;
|
|
2914
|
+
})()
|
|
2915
|
+
: Buffer.from([0]);
|
|
2916
|
+
const xAmountBuf = userTokenXAmount
|
|
2917
|
+
? Buffer.concat([
|
|
2918
|
+
Buffer.from([1]),
|
|
2919
|
+
Buffer.from(userTokenXAmount.toArrayLike(Buffer, 'le', 8)),
|
|
2920
|
+
])
|
|
2921
|
+
: Buffer.from([0]);
|
|
2922
|
+
const yAmountBuf = userTokenYAmount
|
|
2923
|
+
? Buffer.concat([
|
|
2924
|
+
Buffer.from([1]),
|
|
2925
|
+
Buffer.from(userTokenYAmount.toArrayLike(Buffer, 'le', 8)),
|
|
2926
|
+
])
|
|
2927
|
+
: Buffer.from([0]);
|
|
2928
|
+
const chunkLowerBuf = chunkLowerOffset !== undefined
|
|
2929
|
+
? (() => {
|
|
2930
|
+
const b = Buffer.alloc(5);
|
|
2931
|
+
b.writeUInt8(1, 0);
|
|
2932
|
+
b.writeInt32LE(chunkLowerOffset, 1);
|
|
2933
|
+
return b;
|
|
2934
|
+
})()
|
|
2935
|
+
: Buffer.from([0]);
|
|
2936
|
+
const chunkUpperBuf = chunkUpperOffset !== undefined
|
|
2937
|
+
? (() => {
|
|
2938
|
+
const b = Buffer.alloc(5);
|
|
2939
|
+
b.writeUInt8(1, 0);
|
|
2940
|
+
b.writeInt32LE(chunkUpperOffset, 1);
|
|
2941
|
+
return b;
|
|
2942
|
+
})()
|
|
2943
|
+
: Buffer.from([0]);
|
|
2944
|
+
const defaultSlices = [
|
|
2945
|
+
{ accountsType: 0, length: 0 },
|
|
2946
|
+
{ accountsType: 1, length: 0 },
|
|
2947
|
+
];
|
|
2948
|
+
const remainingAccountsInfoSerialized = this.serializeRemainingAccountsInfo({
|
|
2949
|
+
slices: (_b = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.slices) !== null && _b !== void 0 ? _b : defaultSlices,
|
|
2950
|
+
});
|
|
2951
|
+
const raiLenBuf = Buffer.alloc(4);
|
|
2952
|
+
raiLenBuf.writeUInt32LE(remainingAccountsInfoSerialized.length, 0);
|
|
2953
|
+
const remainingAccountsInfoWithLength = Buffer.concat([
|
|
2954
|
+
raiLenBuf,
|
|
2955
|
+
remainingAccountsInfoSerialized,
|
|
2956
|
+
]);
|
|
2957
|
+
const binArrays = meteora_1.MeteoraFunctions.findMeteoraTickArrays(lbPair, lowerBinId, upperBinId);
|
|
2958
|
+
const binArrayAccounts = binArrays.map(binArray => ({
|
|
2959
|
+
pubkey: binArray,
|
|
2960
|
+
isSigner: false,
|
|
2961
|
+
isWritable: true,
|
|
2962
|
+
}));
|
|
2963
|
+
const transferHookAccounts = (_c = remainingAccountsInfo === null || remainingAccountsInfo === void 0 ? void 0 : remainingAccountsInfo.accounts) !== null && _c !== void 0 ? _c : [];
|
|
2964
|
+
const ix = new web3.TransactionInstruction({
|
|
2965
|
+
data: Buffer.concat([
|
|
2966
|
+
sighash,
|
|
2967
|
+
layersBuf,
|
|
2968
|
+
checkRangeBuf,
|
|
2969
|
+
xAmountBuf,
|
|
2970
|
+
yAmountBuf,
|
|
2971
|
+
chunkLowerBuf,
|
|
2972
|
+
chunkUpperBuf,
|
|
2973
|
+
remainingAccountsInfoWithLength,
|
|
2974
|
+
]),
|
|
2975
|
+
keys: [
|
|
2976
|
+
{ pubkey: userPda, isSigner: false, isWritable: false },
|
|
2977
|
+
{ pubkey: userWallet, isSigner: true, isWritable: true },
|
|
2978
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
2979
|
+
{ pubkey: lbPair, isSigner: false, isWritable: true },
|
|
2980
|
+
{ pubkey: userTokenX, isSigner: false, isWritable: true },
|
|
2981
|
+
{ pubkey: userTokenY, isSigner: false, isWritable: true },
|
|
2982
|
+
{ pubkey: reserveX, isSigner: false, isWritable: true },
|
|
2983
|
+
{ pubkey: reserveY, isSigner: false, isWritable: true },
|
|
2984
|
+
{ pubkey: tokenXMint, isSigner: false, isWritable: false },
|
|
2985
|
+
{ pubkey: tokenYMint, isSigner: false, isWritable: false },
|
|
2986
|
+
{ pubkey: tokenXProgram, isSigner: false, isWritable: false },
|
|
2987
|
+
{ pubkey: tokenYProgram, isSigner: false, isWritable: false },
|
|
2988
|
+
{
|
|
2989
|
+
pubkey: actualBinArrayBitmapExtension,
|
|
2990
|
+
isSigner: false,
|
|
2991
|
+
isWritable: !actualBinArrayBitmapExtension.equals(METEORA_DLMM_PROGRAM),
|
|
2992
|
+
},
|
|
2993
|
+
{ pubkey: METEORA_EVENT_AUTHORITY, isSigner: false, isWritable: true },
|
|
2994
|
+
{ pubkey: METEORA_DLMM_PROGRAM, isSigner: false, isWritable: true },
|
|
2995
|
+
...transferHookAccounts,
|
|
2996
|
+
...binArrayAccounts,
|
|
2997
|
+
],
|
|
2998
|
+
programId: addresses_1.IYF_EXTENSION,
|
|
2999
|
+
});
|
|
3000
|
+
return this.ix.iyfMain.iyfExtensionExecuteV2(connection, {
|
|
3001
|
+
userPda,
|
|
3002
|
+
authority: userWallet,
|
|
3003
|
+
ix,
|
|
3004
|
+
});
|
|
3005
|
+
});
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
exports.MeteoraDlmmIxGenerator = MeteoraDlmmIxGenerator;
|