@xitadel-fi/sdk 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -0
- package/dist/sdk/src/constants.d.ts +11 -0
- package/dist/sdk/src/constants.js +15 -0
- package/dist/sdk/src/index.d.ts +3 -0
- package/dist/sdk/src/index.js +12 -0
- package/dist/sdk/src/meteora.d.ts +1229 -0
- package/dist/sdk/src/meteora.js +1231 -0
- package/dist/sdk/src/program.d.ts +433 -0
- package/dist/sdk/src/program.js +825 -0
- package/dist/sdk/src/utils.d.ts +17 -0
- package/dist/sdk/src/utils.js +75 -0
- package/dist/target/idl/xitadel.json +4978 -0
- package/dist/target/types/xitadel.d.ts +4984 -0
- package/dist/target/types/xitadel.js +2 -0
- package/package.json +52 -0
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.XitadelProgram = exports.SEEDS = void 0;
|
|
7
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
8
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
9
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
10
|
+
const web3_js_2 = require("@solana/web3.js");
|
|
11
|
+
const xitadel_json_1 = __importDefault(require("../../target/idl/xitadel.json"));
|
|
12
|
+
const utils_1 = require("./utils");
|
|
13
|
+
const constants_1 = require("./constants");
|
|
14
|
+
exports.SEEDS = {
|
|
15
|
+
LTT_CONFIG: Buffer.from('ltt_config'),
|
|
16
|
+
LTT_MINT: Buffer.from('ltt_mint'),
|
|
17
|
+
ORACLE_PRICE_FEED: Buffer.from('oracle_price_feed'),
|
|
18
|
+
METADATA: Buffer.from('metadata'),
|
|
19
|
+
FUNDING_RECORD: Buffer.from('funding_record'),
|
|
20
|
+
COLLATERAL_STATE: Buffer.from('collateral_state'),
|
|
21
|
+
COLLATERAL_VAULT: Buffer.from('collateral_vault'),
|
|
22
|
+
};
|
|
23
|
+
class XitadelProgram {
|
|
24
|
+
constructor(provider, address) {
|
|
25
|
+
const idl = Object.assign(xitadel_json_1.default, {});
|
|
26
|
+
if (address) {
|
|
27
|
+
idl.address = address;
|
|
28
|
+
}
|
|
29
|
+
this.program = new anchor_1.Program(idl, provider);
|
|
30
|
+
// if (process.env.NODE_ENV === 'development') {
|
|
31
|
+
// const workspace = require('@coral-xyz/anchor').workspace;
|
|
32
|
+
// this.program = workspace.Xitadel as Program<Xitadel>;
|
|
33
|
+
// } else {
|
|
34
|
+
// }
|
|
35
|
+
}
|
|
36
|
+
getProgramId() {
|
|
37
|
+
return this.program.programId;
|
|
38
|
+
}
|
|
39
|
+
getConfigPda() {
|
|
40
|
+
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('config')], this.program.programId)[0];
|
|
41
|
+
}
|
|
42
|
+
async getConfig() {
|
|
43
|
+
return this.program.account.config.fetch(this.getConfigPda());
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Initialize the Xitadel program configuration
|
|
47
|
+
* @param manager The manager's public key (can be different from payer)
|
|
48
|
+
* @param payer Optional payer public key (defaults to manager if not provided)
|
|
49
|
+
* @returns Transaction instruction for initializing the program configuration
|
|
50
|
+
*/
|
|
51
|
+
async initConfig(manager, payer) {
|
|
52
|
+
const [configPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('config')], this.program.programId);
|
|
53
|
+
const payerKey = payer || manager;
|
|
54
|
+
return this.program.methods
|
|
55
|
+
.initConfig()
|
|
56
|
+
.accountsPartial({
|
|
57
|
+
payer: payerKey,
|
|
58
|
+
manager,
|
|
59
|
+
config: configPda,
|
|
60
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
61
|
+
})
|
|
62
|
+
.instruction();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Helper method to get LTT configuration PDA
|
|
66
|
+
* @param lttId The LTT ID (Pubkey)
|
|
67
|
+
* @returns LTT configuration PDA
|
|
68
|
+
*/
|
|
69
|
+
getLTTConfigPda(lttId) {
|
|
70
|
+
return web3_js_1.PublicKey.findProgramAddressSync([exports.SEEDS.LTT_CONFIG, lttId.toBuffer()], this.program.programId)[0];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get LTT configuration data
|
|
74
|
+
* @param lttId The LTT ID (Pubkey)
|
|
75
|
+
* @returns LTT configuration data
|
|
76
|
+
*/
|
|
77
|
+
async getLttConfig(lttId) {
|
|
78
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
79
|
+
return this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Helper method to get LP authority PDA
|
|
83
|
+
* @returns LP authority PDA
|
|
84
|
+
*/
|
|
85
|
+
getLpAuthority() {
|
|
86
|
+
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('lp_authority')], this.program.programId)[0];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Helper method to get metadata PDA
|
|
90
|
+
* @param lttMintPda The LTT mint PDA
|
|
91
|
+
* @returns Metadata PDA
|
|
92
|
+
*/
|
|
93
|
+
getMetadataPda(lttMintPda) {
|
|
94
|
+
return web3_js_1.PublicKey.findProgramAddressSync([exports.SEEDS.METADATA, constants_1.METADATA_PROGRAM_ID.toBuffer(), lttMintPda.toBuffer()], constants_1.METADATA_PROGRAM_ID)[0];
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Helper method to get funding record PDA
|
|
98
|
+
* @param lttId The LTT ID
|
|
99
|
+
* @param investor The investor's public key
|
|
100
|
+
* @returns Funding record PDA
|
|
101
|
+
*/
|
|
102
|
+
getFundingRecordPda(lttConfig, investor) {
|
|
103
|
+
return web3_js_1.PublicKey.findProgramAddressSync([exports.SEEDS.FUNDING_RECORD, lttConfig.toBuffer(), investor.toBuffer()], this.program.programId)[0];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Helper method to get collateral state PDA
|
|
107
|
+
* @param lttId The LTT ID
|
|
108
|
+
* @returns Collateral state PDA
|
|
109
|
+
*/
|
|
110
|
+
getCollateralStatePda(lttId) {
|
|
111
|
+
return web3_js_1.PublicKey.findProgramAddressSync([exports.SEEDS.COLLATERAL_STATE, lttId.toBuffer()], this.program.programId)[0];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Register a new LTT
|
|
115
|
+
* @param manager The manager's public key
|
|
116
|
+
* @param params The LTT registration parameters
|
|
117
|
+
* @param fundingTokenMint The funding token mint account
|
|
118
|
+
* @param collateralTokenMint The collateral token mint account
|
|
119
|
+
* @returns Transaction instruction for registering the LTT
|
|
120
|
+
*/
|
|
121
|
+
async registerLTT(manager, fundingTokenMint, collateralTokenMint, params) {
|
|
122
|
+
const config = this.getConfigPda();
|
|
123
|
+
const lttConfigPda = this.getLTTConfigPda(params.lttId);
|
|
124
|
+
const metadataPda = this.getMetadataPda(params.lttId);
|
|
125
|
+
return this.program.methods
|
|
126
|
+
.registerLtt(params)
|
|
127
|
+
.accountsPartial({
|
|
128
|
+
manager: manager,
|
|
129
|
+
config: config,
|
|
130
|
+
lttConfiguration: lttConfigPda,
|
|
131
|
+
lttTokenMint: params.lttId,
|
|
132
|
+
fundingTokenMint: fundingTokenMint,
|
|
133
|
+
collateralTokenMint: collateralTokenMint,
|
|
134
|
+
metadataAccount: metadataPda,
|
|
135
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
136
|
+
tokenMetadataProgram: constants_1.METADATA_PROGRAM_ID,
|
|
137
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
138
|
+
})
|
|
139
|
+
.instruction();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Fund an LTT
|
|
143
|
+
* @param lttId The LTT ID to fund
|
|
144
|
+
* @param investor The investor's public key
|
|
145
|
+
* @param amount The amount to fund
|
|
146
|
+
* @returns Transaction instruction for funding the LTT
|
|
147
|
+
*/
|
|
148
|
+
async fundLTT(lttId, investor, fundingAmount) {
|
|
149
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
150
|
+
const fundingRecordPda = this.getFundingRecordPda(lttConfigPda, investor);
|
|
151
|
+
const lttConfig = await this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
152
|
+
const fundingTokenMint = lttConfig.fundingTokenMint;
|
|
153
|
+
const fundingVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(fundingTokenMint, lttConfigPda, true);
|
|
154
|
+
const investorStablecoinAta = (0, spl_token_1.getAssociatedTokenAddressSync)(fundingTokenMint, investor, true);
|
|
155
|
+
const investorLTTAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttId, investor, true);
|
|
156
|
+
const instructions = [];
|
|
157
|
+
let ataInfo = null;
|
|
158
|
+
try {
|
|
159
|
+
ataInfo = await this.program.provider.connection.getAccountInfo(investorLTTAta);
|
|
160
|
+
}
|
|
161
|
+
catch (error) { }
|
|
162
|
+
if (ataInfo == null) {
|
|
163
|
+
const createInvestorLTTAtaIx = (0, spl_token_1.createAssociatedTokenAccountInstruction)(investor, investorLTTAta, investor, lttId);
|
|
164
|
+
instructions.push(createInvestorLTTAtaIx);
|
|
165
|
+
}
|
|
166
|
+
instructions.push(await this.program.methods
|
|
167
|
+
.fundLtt(fundingAmount)
|
|
168
|
+
.accountsPartial({
|
|
169
|
+
investor,
|
|
170
|
+
lttConfiguration: lttConfigPda,
|
|
171
|
+
fundingVaultAta,
|
|
172
|
+
investorFundingAta: investorStablecoinAta,
|
|
173
|
+
investorLttAta: investorLTTAta,
|
|
174
|
+
fundingTokenMint,
|
|
175
|
+
lttTokenMint: lttId,
|
|
176
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
177
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
178
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
179
|
+
})
|
|
180
|
+
.instruction());
|
|
181
|
+
return instructions;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Activate liquidation for an LTT
|
|
185
|
+
* @param lttId The LTT ID
|
|
186
|
+
* @param keeperBot The keeper bot's public key
|
|
187
|
+
* @returns Transaction instruction for activating liquidation
|
|
188
|
+
*/
|
|
189
|
+
async activateLiquidation(lttId, keeperBot, pricefeed, chainLinkProgram, signedReport, verifierAccounts) {
|
|
190
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
191
|
+
const lttConfig = await this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
192
|
+
const collateralVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true);
|
|
193
|
+
return this.program.methods
|
|
194
|
+
.activateLiquidation(Buffer.from(signedReport))
|
|
195
|
+
.accountsPartial({
|
|
196
|
+
lttConfiguration: lttConfigPda,
|
|
197
|
+
priceFeed: pricefeed,
|
|
198
|
+
signer: keeperBot,
|
|
199
|
+
collateralVaultAta,
|
|
200
|
+
collateralTokenMint: lttConfig.collateralTokenMint,
|
|
201
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
202
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
203
|
+
stableTokenMint: lttConfig.fundingTokenMint,
|
|
204
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
205
|
+
chainlinkProgram: chainLinkProgram,
|
|
206
|
+
verifierAccount: verifierAccounts.verifier,
|
|
207
|
+
accessController: verifierAccounts.accessController,
|
|
208
|
+
configAccount: verifierAccounts.config,
|
|
209
|
+
})
|
|
210
|
+
.instruction();
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Execute liquidation for an LTT
|
|
214
|
+
* @param lttId The LTT ID
|
|
215
|
+
* @param keeperBot The keeper bot's public key
|
|
216
|
+
* @param priceFeed Switchboard price feed
|
|
217
|
+
* @returns Transaction instruction for executing liquidation
|
|
218
|
+
*/
|
|
219
|
+
async executeLiquidation(lttId, keeperBot, priceFeed, chainLinkProgram, signedReport, verifierAccounts) {
|
|
220
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
221
|
+
const lttConfig = await this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
222
|
+
const collateralVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true);
|
|
223
|
+
return this.program.methods
|
|
224
|
+
.executeLiquidation(Buffer.from(signedReport))
|
|
225
|
+
.accountsPartial({
|
|
226
|
+
priceFeed,
|
|
227
|
+
lttConfiguration: lttConfigPda,
|
|
228
|
+
signer: keeperBot,
|
|
229
|
+
collateralVaultAta,
|
|
230
|
+
lttTokenMint: lttId,
|
|
231
|
+
collateralTokenMint: lttConfig.collateralTokenMint,
|
|
232
|
+
stableTokenMint: lttConfig.fundingTokenMint,
|
|
233
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
234
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
235
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
236
|
+
chainlinkProgram: chainLinkProgram,
|
|
237
|
+
verifierAccount: verifierAccounts.verifier,
|
|
238
|
+
accessController: verifierAccounts.accessController,
|
|
239
|
+
configAccount: verifierAccounts.config,
|
|
240
|
+
})
|
|
241
|
+
.instruction();
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Withdraw collateral from an LTT
|
|
245
|
+
* @param lttId The LTT ID
|
|
246
|
+
* @param withdrawer The withdrawer's public key
|
|
247
|
+
* @param amount The amount to withdraw
|
|
248
|
+
* @returns Transaction instruction for withdrawing collateral
|
|
249
|
+
*/
|
|
250
|
+
async withdrawCollateral(lttId, withdrawer, amount, chainLinkProgram, priceFeed, signedReport, verifierAccounts) {
|
|
251
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
252
|
+
const lttConfig = await this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
253
|
+
const instructions = [];
|
|
254
|
+
const collateralVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true);
|
|
255
|
+
const withdrawerCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, withdrawer, true);
|
|
256
|
+
const ataInfo = await this.program.provider.connection.getAccountInfo(withdrawerCollateralAta);
|
|
257
|
+
const needsCreate = ataInfo == null;
|
|
258
|
+
if (needsCreate) {
|
|
259
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(withdrawer, withdrawerCollateralAta, withdrawer, lttConfig.collateralTokenMint));
|
|
260
|
+
}
|
|
261
|
+
instructions.push(await this.program.methods
|
|
262
|
+
.withdrawCollateral(amount, Buffer.from(signedReport))
|
|
263
|
+
.accountsPartial({
|
|
264
|
+
lttConfiguration: lttConfigPda,
|
|
265
|
+
issuer: withdrawer,
|
|
266
|
+
collateralVaultAta,
|
|
267
|
+
stableTokenMint: lttConfig.fundingTokenMint,
|
|
268
|
+
issuerCollateralAta: withdrawerCollateralAta,
|
|
269
|
+
collateralTokenMint: lttConfig.collateralTokenMint,
|
|
270
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
271
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
272
|
+
chainlinkProgram: chainLinkProgram,
|
|
273
|
+
priceFeed,
|
|
274
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
275
|
+
verifierAccount: verifierAccounts.verifier,
|
|
276
|
+
accessController: verifierAccounts.accessController,
|
|
277
|
+
configAccount: verifierAccounts.config,
|
|
278
|
+
})
|
|
279
|
+
.instruction());
|
|
280
|
+
return instructions;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Withdraw USDC from an LTT
|
|
284
|
+
* @param lttId The LTT ID
|
|
285
|
+
* @param withdrawer The withdrawer's public key
|
|
286
|
+
* @param amount The amount to withdraw
|
|
287
|
+
* @returns Transaction instruction for withdrawing USDC
|
|
288
|
+
*/
|
|
289
|
+
async withdrawUsdc(lttId, withdrawer, amount) {
|
|
290
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
291
|
+
const lttConfig = await this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
292
|
+
const fundingVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, lttConfigPda, true);
|
|
293
|
+
const withdrawerFundingAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, withdrawer, true);
|
|
294
|
+
return this.program.methods
|
|
295
|
+
.withdrawUsdc(amount)
|
|
296
|
+
.accountsPartial({
|
|
297
|
+
lttConfiguration: lttConfigPda,
|
|
298
|
+
issuer: withdrawer,
|
|
299
|
+
fundingVaultAta,
|
|
300
|
+
issuerFundingAta: withdrawerFundingAta,
|
|
301
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
302
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
303
|
+
fundingTokenMint: lttConfig.fundingTokenMint,
|
|
304
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
305
|
+
})
|
|
306
|
+
.instruction();
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Fetch LTT configuration
|
|
310
|
+
* @param lttId The LTT ID
|
|
311
|
+
* @returns LTT configuration
|
|
312
|
+
*/
|
|
313
|
+
async fetchLTTConfiguration(lttId) {
|
|
314
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
315
|
+
return this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Redeem LTT tokens
|
|
319
|
+
* @param lttId The LTT ID
|
|
320
|
+
* @param investor The investor's public key
|
|
321
|
+
* @param amount The amount to redeem
|
|
322
|
+
* @returns Transaction instruction for redeeming LTT tokens
|
|
323
|
+
*/
|
|
324
|
+
async redeemLTT(lttId, investor, amount) {
|
|
325
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
326
|
+
const lttConfig = await this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
327
|
+
// Get all required token accounts
|
|
328
|
+
const fundingVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, lttConfigPda, true);
|
|
329
|
+
const investorFundingAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, investor, true);
|
|
330
|
+
const investorLttAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttId, investor, true);
|
|
331
|
+
const interestVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true);
|
|
332
|
+
const investorInterestAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, investor, true);
|
|
333
|
+
const collateralVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true);
|
|
334
|
+
const investorCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, investor, true);
|
|
335
|
+
const instructions = [];
|
|
336
|
+
// Check if investor's collateral token account exists
|
|
337
|
+
let investorCollateralAtaInfo = null;
|
|
338
|
+
try {
|
|
339
|
+
investorCollateralAtaInfo = await this.program.provider.connection.getAccountInfo(investorCollateralAta);
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
// Account doesn't exist, will create it
|
|
343
|
+
}
|
|
344
|
+
if (investorCollateralAtaInfo == null) {
|
|
345
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(investor, investorCollateralAta, investor, lttConfig.collateralTokenMint));
|
|
346
|
+
}
|
|
347
|
+
instructions.push(await this.program.methods
|
|
348
|
+
.redeem(amount)
|
|
349
|
+
.accountsPartial({
|
|
350
|
+
investor: investor,
|
|
351
|
+
lttConfiguration: lttConfigPda,
|
|
352
|
+
fundingVaultAta,
|
|
353
|
+
investorFundingAta,
|
|
354
|
+
investorLttAta,
|
|
355
|
+
interestVaultAta,
|
|
356
|
+
investorInterestAta,
|
|
357
|
+
collateralVaultAta,
|
|
358
|
+
investorCollateralAta,
|
|
359
|
+
fundingTokenMint: lttConfig.fundingTokenMint,
|
|
360
|
+
lttTokenMint: lttId,
|
|
361
|
+
collateralTokenMint: lttConfig.collateralTokenMint,
|
|
362
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
363
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
364
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
365
|
+
})
|
|
366
|
+
.instruction());
|
|
367
|
+
return instructions;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Update LTT status
|
|
371
|
+
* @param lttId The LTT ID
|
|
372
|
+
* @returns Transaction instruction for updating LTT status
|
|
373
|
+
*/
|
|
374
|
+
async updateLTTStatus(lttId) {
|
|
375
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
376
|
+
const lttConfig = await this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
377
|
+
const fundingVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, lttConfigPda, true);
|
|
378
|
+
const collateralVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true);
|
|
379
|
+
return this.program.methods
|
|
380
|
+
.updateLttStatus()
|
|
381
|
+
.accountsPartial({
|
|
382
|
+
lttConfiguration: lttConfigPda,
|
|
383
|
+
fundingVaultAta,
|
|
384
|
+
collateralVaultAta,
|
|
385
|
+
fundingTokenMint: lttConfig.fundingTokenMint,
|
|
386
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
387
|
+
})
|
|
388
|
+
.instruction();
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Deactivate an LTT
|
|
392
|
+
* @param signer
|
|
393
|
+
* @param lttId The LTT ID
|
|
394
|
+
* @param positionNftMint The position NFT mint
|
|
395
|
+
* @param cpAmmProgramId The CP AMM program ID
|
|
396
|
+
* @returns Transaction instructions for deactivating the LTT
|
|
397
|
+
*/
|
|
398
|
+
async deactivateLTT(signer, lttId, positionNftMint, cpAmmProgramId) {
|
|
399
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
400
|
+
const lttConfig = await this.getLttConfig(lttId);
|
|
401
|
+
const lpAuthority = this.getLpAuthority();
|
|
402
|
+
const harvestVault = this.getHarvestVaultPda(lttId);
|
|
403
|
+
const instructions = [];
|
|
404
|
+
// Check if harvest vault position NFT ATA exists, create if not
|
|
405
|
+
const harvestVaultPositionNftAta = (0, spl_token_1.getAssociatedTokenAddressSync)(positionNftMint, harvestVault, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
406
|
+
let harvestVaultPositionNftAtaInfo = null;
|
|
407
|
+
try {
|
|
408
|
+
harvestVaultPositionNftAtaInfo = await this.program.provider.connection.getAccountInfo(harvestVaultPositionNftAta);
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
// Account doesn't exist, will create it
|
|
412
|
+
}
|
|
413
|
+
if (harvestVaultPositionNftAtaInfo == null) {
|
|
414
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(signer, harvestVaultPositionNftAta, harvestVault, positionNftMint, spl_token_1.TOKEN_2022_PROGRAM_ID));
|
|
415
|
+
}
|
|
416
|
+
// Check if harvest vault funding ATA exists, create if not
|
|
417
|
+
const harvestVaultFundingAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, harvestVault, true);
|
|
418
|
+
let harvestVaultFundingAtaInfo = null;
|
|
419
|
+
try {
|
|
420
|
+
harvestVaultFundingAtaInfo = await this.program.provider.connection.getAccountInfo(harvestVaultFundingAta);
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
// Account doesn't exist, will create it
|
|
424
|
+
}
|
|
425
|
+
if (harvestVaultFundingAtaInfo == null) {
|
|
426
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(signer, harvestVaultFundingAta, harvestVault, lttConfig.fundingTokenMint));
|
|
427
|
+
}
|
|
428
|
+
// Check if harvest vault collateral ATA exists, create if not
|
|
429
|
+
const harvestVaultCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, harvestVault, true);
|
|
430
|
+
let harvestVaultCollateralAtaInfo = null;
|
|
431
|
+
try {
|
|
432
|
+
harvestVaultCollateralAtaInfo = await this.program.provider.connection.getAccountInfo(harvestVaultCollateralAta);
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
// Account doesn't exist, will create it
|
|
436
|
+
}
|
|
437
|
+
if (harvestVaultCollateralAtaInfo == null) {
|
|
438
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(signer, harvestVaultCollateralAta, harvestVault, lttConfig.collateralTokenMint));
|
|
439
|
+
}
|
|
440
|
+
// Use Token-2022 ATA for position NFT account owned by lpAuthority
|
|
441
|
+
const [positionNftAccount] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POSITION_NFT_ACCOUNT_SEED, positionNftMint.toBuffer()], cpAmmProgramId);
|
|
442
|
+
let positionNftAccountInfo = null;
|
|
443
|
+
try {
|
|
444
|
+
positionNftAccountInfo = await this.program.provider.connection.getAccountInfo(positionNftAccount);
|
|
445
|
+
}
|
|
446
|
+
catch (error) {
|
|
447
|
+
// Account doesn't exist, will create it
|
|
448
|
+
}
|
|
449
|
+
if (positionNftAccountInfo == null) {
|
|
450
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(signer, positionNftAccount, lpAuthority, positionNftMint, spl_token_1.TOKEN_2022_PROGRAM_ID));
|
|
451
|
+
}
|
|
452
|
+
console.log('harvestVaultPositionNftAta', harvestVaultPositionNftAta.toBase58());
|
|
453
|
+
console.log('harvestVaultFundingAta', harvestVaultFundingAta.toBase58());
|
|
454
|
+
console.log('harvestVaultCollateralAta', harvestVaultCollateralAta.toBase58());
|
|
455
|
+
console.log('positionNftAccount', positionNftAccount.toBase58());
|
|
456
|
+
// Add the main deactivate instruction
|
|
457
|
+
instructions.push(await this.program.methods
|
|
458
|
+
.deactivateLtt()
|
|
459
|
+
.accountsPartial({
|
|
460
|
+
signer: signer,
|
|
461
|
+
lttConfiguration: lttConfigPda,
|
|
462
|
+
lpAuthority: lpAuthority,
|
|
463
|
+
harvestVault,
|
|
464
|
+
fundingVaultAta: (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, lttConfigPda, true),
|
|
465
|
+
collateralVaultAta: (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true),
|
|
466
|
+
positionNftMint,
|
|
467
|
+
positionNftAccount: positionNftAccount,
|
|
468
|
+
harvestVaultPositionNftAta,
|
|
469
|
+
harvestVaultFundingAta,
|
|
470
|
+
harvestVaultCollateralAta,
|
|
471
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
472
|
+
token2022Program: spl_token_1.TOKEN_2022_PROGRAM_ID,
|
|
473
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
474
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
475
|
+
})
|
|
476
|
+
.instruction());
|
|
477
|
+
return instructions;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Activate an LTT
|
|
481
|
+
* @param signer The signer's public key
|
|
482
|
+
* @param positionNftMintKeypair
|
|
483
|
+
* @param ammConfig
|
|
484
|
+
* @param params The LP creation parameters
|
|
485
|
+
* @returns Transaction instructions for creating LP
|
|
486
|
+
*/
|
|
487
|
+
async activateLtt(signer, positionNftMintKeypair, positionNftMintKeypairB, ammConfig, ammConfigB, params) {
|
|
488
|
+
const lpAuthority = this.getLpAuthority();
|
|
489
|
+
const lttConfigPda = this.getLTTConfigPda(params.lttId);
|
|
490
|
+
const lttTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(params.lttId, lpAuthority, true);
|
|
491
|
+
// console.log("lpAuthority", lpAuthority.toBase58());
|
|
492
|
+
const instructions = [];
|
|
493
|
+
// Create stable coin token account if it doesn't exist
|
|
494
|
+
const stableCoinVaultTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(params.stableCoinMint, lpAuthority, true);
|
|
495
|
+
const fundingVaultTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(params.stableCoinMint, lttConfigPda, true);
|
|
496
|
+
let stableCoinTokenAccountInfo = null;
|
|
497
|
+
try {
|
|
498
|
+
stableCoinTokenAccountInfo = await this.program.provider.connection.getAccountInfo(stableCoinVaultTokenAccount);
|
|
499
|
+
}
|
|
500
|
+
catch (error) {
|
|
501
|
+
// Account doesn't exist, will create it
|
|
502
|
+
}
|
|
503
|
+
if (stableCoinTokenAccountInfo == null) {
|
|
504
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(signer, stableCoinVaultTokenAccount, lpAuthority, params.stableCoinMint));
|
|
505
|
+
}
|
|
506
|
+
const pool = (0, utils_1.derivePoolKey)(ammConfig, params.lttId, params.stableCoinMint, params.cpAmmProgramId);
|
|
507
|
+
const poolb = (0, utils_1.derivePoolKey)(ammConfigB, params.lttId, params.stableCoinMint, params.cpAmmProgramId);
|
|
508
|
+
const [lpMint] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('lp_mint'), pool.toBuffer()], params.cpAmmProgramId);
|
|
509
|
+
let lttVaultAta, stableVaultAta, lttVaultAtaB, stableVaultAtaB;
|
|
510
|
+
[lttVaultAta, stableVaultAta, lttVaultAtaB, stableVaultAtaB] = [
|
|
511
|
+
(0, utils_1.getVaultPda)(params.lttId, params.cpAmmProgramId, pool),
|
|
512
|
+
(0, utils_1.getVaultPda)(params.stableCoinMint, params.cpAmmProgramId, pool),
|
|
513
|
+
(0, utils_1.getVaultPda)(params.lttId, params.cpAmmProgramId, poolb),
|
|
514
|
+
(0, utils_1.getVaultPda)(params.stableCoinMint, params.cpAmmProgramId, poolb),
|
|
515
|
+
];
|
|
516
|
+
let lttTokenAccountInfo = null;
|
|
517
|
+
try {
|
|
518
|
+
lttTokenAccountInfo = await this.program.provider.connection.getAccountInfo(lttTokenAccount);
|
|
519
|
+
}
|
|
520
|
+
catch (error) {
|
|
521
|
+
// Account doesn't exist, will create it
|
|
522
|
+
}
|
|
523
|
+
if (lttTokenAccountInfo == null) {
|
|
524
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(signer, lttTokenAccount, lpAuthority, params.lttId));
|
|
525
|
+
}
|
|
526
|
+
// Initialize payer LTT token account
|
|
527
|
+
const payerLttTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(params.lttId, lpAuthority, true);
|
|
528
|
+
// Initialize payer stablecoin token account
|
|
529
|
+
const payerStableCoinTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(params.stableCoinMint, lpAuthority, true);
|
|
530
|
+
let payerStableCoinTokenAccountInfo = null;
|
|
531
|
+
try {
|
|
532
|
+
payerStableCoinTokenAccountInfo = await this.program.provider.connection.getAccountInfo(payerStableCoinTokenAccount);
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
// Account doesn't exist, will create it
|
|
536
|
+
}
|
|
537
|
+
if (payerStableCoinTokenAccountInfo == null) {
|
|
538
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(signer, payerStableCoinTokenAccount, lpAuthority, params.stableCoinMint));
|
|
539
|
+
}
|
|
540
|
+
// Generate position NFT mint and account
|
|
541
|
+
const [positionNftAccount] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('position_nft_account'), positionNftMintKeypair.publicKey.toBuffer()], params.cpAmmProgramId);
|
|
542
|
+
const [positionNftAccountB] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('position_nft_account'), positionNftMintKeypairB.publicKey.toBuffer()], params.cpAmmProgramId);
|
|
543
|
+
// Get position PDA
|
|
544
|
+
const [position] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('position'), positionNftMintKeypair.publicKey.toBuffer()], params.cpAmmProgramId);
|
|
545
|
+
const [positionB] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('position'), positionNftMintKeypairB.publicKey.toBuffer()], params.cpAmmProgramId);
|
|
546
|
+
const [poolAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('pool_authority')], params.cpAmmProgramId);
|
|
547
|
+
const [eventAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('__event_authority')], params.cpAmmProgramId);
|
|
548
|
+
const collateralVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(params.collateralTokenMint, lttConfigPda, true);
|
|
549
|
+
instructions.push(await this.program.methods
|
|
550
|
+
.activateLtt()
|
|
551
|
+
.accountsPartial({
|
|
552
|
+
signer: signer,
|
|
553
|
+
lttConfiguration: lttConfigPda,
|
|
554
|
+
lpAuthority,
|
|
555
|
+
poolAuthority: poolAuthority,
|
|
556
|
+
pool,
|
|
557
|
+
poolb,
|
|
558
|
+
lpMint,
|
|
559
|
+
poolConfig: ammConfig,
|
|
560
|
+
poolConfigB: ammConfigB,
|
|
561
|
+
lttMint: params.lttId,
|
|
562
|
+
stableCoinMint: params.stableCoinMint,
|
|
563
|
+
fundingVaultAccount: fundingVaultTokenAccount,
|
|
564
|
+
lttVaultAta: lttVaultAta,
|
|
565
|
+
stableCoinVaultAta: stableVaultAta,
|
|
566
|
+
lttVaultAtaB,
|
|
567
|
+
stableCoinVaultAtaB: stableVaultAtaB,
|
|
568
|
+
payerLttTokenAccount: payerLttTokenAccount,
|
|
569
|
+
payerStableCoinTokenAccount: payerStableCoinTokenAccount,
|
|
570
|
+
positionNftMint: positionNftMintKeypair.publicKey,
|
|
571
|
+
positionNftMintB: positionNftMintKeypairB.publicKey,
|
|
572
|
+
positionNftAccount: positionNftAccount,
|
|
573
|
+
positionNftAccountB,
|
|
574
|
+
position: position,
|
|
575
|
+
positionB,
|
|
576
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
577
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
578
|
+
collateralAta: collateralVaultAta,
|
|
579
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
580
|
+
tokenBProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
581
|
+
token2022Program: spl_token_1.TOKEN_2022_PROGRAM_ID,
|
|
582
|
+
eventAuthority: eventAuthority,
|
|
583
|
+
cpAmmProgram: params.cpAmmProgramId,
|
|
584
|
+
rent: web3_js_1.SYSVAR_RENT_PUBKEY,
|
|
585
|
+
})
|
|
586
|
+
.instruction());
|
|
587
|
+
return instructions;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Maturate an LTT
|
|
591
|
+
* @param signer
|
|
592
|
+
* @param lttId The LTT ID
|
|
593
|
+
* @param positionNftMint The position NFT mint
|
|
594
|
+
* @param ammConfig The AMM config
|
|
595
|
+
* @param cpAmmProgramId The CP AMM program ID
|
|
596
|
+
* @param params The maturate parameters
|
|
597
|
+
* @returns Transaction instruction for maturing the LTT
|
|
598
|
+
*/
|
|
599
|
+
async maturateLtt(signer, lttId, positionNftMint, positionNftMintB, ammConfig, ammConfigB, cpAmmProgramId) {
|
|
600
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
601
|
+
const lttConfig = await this.getLttConfig(lttId);
|
|
602
|
+
const lpAuthority = this.getLpAuthority();
|
|
603
|
+
// Derive pool key
|
|
604
|
+
const pool = (0, utils_1.derivePoolKey)(ammConfig, lttId, lttConfig.fundingTokenMint, cpAmmProgramId);
|
|
605
|
+
const poolB = (0, utils_1.derivePoolKey)(ammConfigB, lttId, lttConfig.fundingTokenMint, cpAmmProgramId);
|
|
606
|
+
// Derive position PDA
|
|
607
|
+
const [position] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POSITION_SEED, positionNftMint.toBuffer()], cpAmmProgramId);
|
|
608
|
+
const [positionB] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POSITION_SEED, positionNftMintB.toBuffer()], cpAmmProgramId);
|
|
609
|
+
// Derive pool authority
|
|
610
|
+
const [poolAuthority] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POOL_AUTHORITY_SEED], cpAmmProgramId);
|
|
611
|
+
// Derive event authority
|
|
612
|
+
const [eventAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('__event_authority')], cpAmmProgramId);
|
|
613
|
+
// Derive vault addresses
|
|
614
|
+
const [lttVault, stableVault] = [
|
|
615
|
+
(0, utils_1.getVaultPda)(lttId, cpAmmProgramId, pool),
|
|
616
|
+
(0, utils_1.getVaultPda)(lttConfig.fundingTokenMint, cpAmmProgramId, pool),
|
|
617
|
+
];
|
|
618
|
+
const [lttVaultB, stableVaultB] = [
|
|
619
|
+
(0, utils_1.getVaultPda)(lttId, cpAmmProgramId, poolB),
|
|
620
|
+
(0, utils_1.getVaultPda)(lttConfig.fundingTokenMint, cpAmmProgramId, poolB),
|
|
621
|
+
];
|
|
622
|
+
// Get LP authority token accounts
|
|
623
|
+
const lttTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(lttId, lpAuthority, true);
|
|
624
|
+
const stableCoinTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, lpAuthority, true);
|
|
625
|
+
// Derive position NFT account
|
|
626
|
+
const [positionNftAccount] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POSITION_NFT_ACCOUNT_SEED, positionNftMint.toBuffer()], cpAmmProgramId);
|
|
627
|
+
const [positionNftAccountB] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POSITION_NFT_ACCOUNT_SEED, positionNftMintB.toBuffer()], cpAmmProgramId);
|
|
628
|
+
const collateralVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true);
|
|
629
|
+
const fundingVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, lttConfigPda, true);
|
|
630
|
+
const maturateIx = await this.program.methods
|
|
631
|
+
.maturate()
|
|
632
|
+
.accountsPartial({
|
|
633
|
+
signer,
|
|
634
|
+
lpAuthority,
|
|
635
|
+
lttConfiguration: lttConfigPda,
|
|
636
|
+
poolAuthority,
|
|
637
|
+
pool,
|
|
638
|
+
position,
|
|
639
|
+
poolB,
|
|
640
|
+
positionB,
|
|
641
|
+
fundingVaultAta,
|
|
642
|
+
collateralVaultAta,
|
|
643
|
+
tokenAAccount: lttTokenAccount,
|
|
644
|
+
tokenBAccount: stableCoinTokenAccount,
|
|
645
|
+
tokenAVault: lttVault,
|
|
646
|
+
tokenBVault: stableVault,
|
|
647
|
+
tokenAVaultB: lttVaultB,
|
|
648
|
+
tokenBVaultB: stableVaultB,
|
|
649
|
+
tokenAMint: lttId,
|
|
650
|
+
tokenBMint: lttConfig.fundingTokenMint,
|
|
651
|
+
positionNftMint,
|
|
652
|
+
positionNftAccount,
|
|
653
|
+
positionNftMintB,
|
|
654
|
+
positionNftAccountB,
|
|
655
|
+
tokenAProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
656
|
+
tokenBProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
657
|
+
eventAuthority,
|
|
658
|
+
cpAmmProgram: cpAmmProgramId,
|
|
659
|
+
})
|
|
660
|
+
.instruction();
|
|
661
|
+
return maturateIx;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Stop liquidation
|
|
665
|
+
* @param lttId The LTT ID
|
|
666
|
+
* @param signer The signer's public key
|
|
667
|
+
* @returns Transaction instruction for stopping liquidation
|
|
668
|
+
*/
|
|
669
|
+
async stopLiquidation(lttId, signer, priceFeed, chainlinkProgram, signedReport, verifierAccounts) {
|
|
670
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
671
|
+
const lttConfig = await this.program.account.lttConfiguration.fetch(lttConfigPda);
|
|
672
|
+
const collateralVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true);
|
|
673
|
+
return this.program.methods
|
|
674
|
+
.stopLiquidation(Buffer.from(signedReport))
|
|
675
|
+
.accountsPartial({
|
|
676
|
+
lttConfiguration: lttConfigPda,
|
|
677
|
+
signer: signer,
|
|
678
|
+
priceFeed,
|
|
679
|
+
chainlinkProgram,
|
|
680
|
+
collateralVaultAta,
|
|
681
|
+
collateralTokenMint: lttConfig.collateralTokenMint,
|
|
682
|
+
stableTokenMint: lttConfig.fundingTokenMint,
|
|
683
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
684
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
685
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
686
|
+
verifierAccount: verifierAccounts.verifier,
|
|
687
|
+
accessController: verifierAccounts.accessController,
|
|
688
|
+
configAccount: verifierAccounts.config,
|
|
689
|
+
})
|
|
690
|
+
.instruction();
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Harvest funds or NFTs from the LTT harvest vault.
|
|
694
|
+
* @param lttId The LTT ID
|
|
695
|
+
* @param manager The manager's keypair or public key
|
|
696
|
+
* @param positionNftMint The position NFT mint
|
|
697
|
+
* @returns A transaction instruction to perform the harvest
|
|
698
|
+
*/
|
|
699
|
+
async harvestLTT(lttId, manager, positionNftMint) {
|
|
700
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
701
|
+
const harvestVault = this.getHarvestVaultPda(lttId);
|
|
702
|
+
const configPda = this.getConfigPda();
|
|
703
|
+
const lttConfig = await this.getLttConfig(lttId);
|
|
704
|
+
// Derive all ATAs
|
|
705
|
+
const harvestVaultPositionNftAta = (0, spl_token_1.getAssociatedTokenAddressSync)(positionNftMint, harvestVault, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
706
|
+
const managerPositionNftAta = (0, spl_token_1.getAssociatedTokenAddressSync)(positionNftMint, manager, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
|
|
707
|
+
const harvestVaultFundingAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, harvestVault, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
708
|
+
const harvestVaultCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, harvestVault, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
709
|
+
const managerFundingAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, manager, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
710
|
+
const managerCollateralAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, manager, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
711
|
+
const fundingVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, lttConfigPda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
712
|
+
const collateralVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.collateralTokenMint, lttConfigPda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
713
|
+
const interestVaultAta = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, lttConfigPda, true, spl_token_1.TOKEN_PROGRAM_ID);
|
|
714
|
+
const instructions = [];
|
|
715
|
+
// Create missing ATAs if needed
|
|
716
|
+
const connection = this.program.provider.connection;
|
|
717
|
+
const harvestVaultPositionNftAtaInfo = await connection.getAccountInfo(harvestVaultPositionNftAta);
|
|
718
|
+
if (!harvestVaultPositionNftAtaInfo) {
|
|
719
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(manager, harvestVaultPositionNftAta, harvestVault, positionNftMint, spl_token_1.TOKEN_2022_PROGRAM_ID));
|
|
720
|
+
}
|
|
721
|
+
const managerPositionNftAtaInfo = await connection.getAccountInfo(managerPositionNftAta);
|
|
722
|
+
if (!managerPositionNftAtaInfo) {
|
|
723
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(manager, managerPositionNftAta, manager, positionNftMint, spl_token_1.TOKEN_2022_PROGRAM_ID));
|
|
724
|
+
}
|
|
725
|
+
const harvestVaultFundingAtaInfo = await connection.getAccountInfo(harvestVaultFundingAta);
|
|
726
|
+
if (!harvestVaultFundingAtaInfo) {
|
|
727
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(manager, harvestVaultFundingAta, harvestVault, lttConfig.fundingTokenMint, spl_token_1.TOKEN_PROGRAM_ID));
|
|
728
|
+
}
|
|
729
|
+
const harvestVaultCollateralAtaInfo = await connection.getAccountInfo(harvestVaultCollateralAta);
|
|
730
|
+
if (!harvestVaultCollateralAtaInfo) {
|
|
731
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(manager, harvestVaultCollateralAta, harvestVault, lttConfig.collateralTokenMint, spl_token_1.TOKEN_PROGRAM_ID));
|
|
732
|
+
}
|
|
733
|
+
const managerCollateralAtaInfo = await connection.getAccountInfo(managerCollateralAta);
|
|
734
|
+
if (!managerCollateralAtaInfo) {
|
|
735
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(manager, managerCollateralAta, manager, lttConfig.collateralTokenMint, spl_token_1.TOKEN_PROGRAM_ID));
|
|
736
|
+
}
|
|
737
|
+
// Add the harvest instruction
|
|
738
|
+
const harvestIx = await this.program.methods
|
|
739
|
+
.harvest()
|
|
740
|
+
.accountsPartial({
|
|
741
|
+
lttConfiguration: lttConfigPda,
|
|
742
|
+
config: configPda,
|
|
743
|
+
manager,
|
|
744
|
+
harvestVault,
|
|
745
|
+
positionNftMint,
|
|
746
|
+
harvestVaultPositionNftAta,
|
|
747
|
+
managerPositionNftAta,
|
|
748
|
+
harvestVaultFundingAta,
|
|
749
|
+
managerFundingAta,
|
|
750
|
+
managerCollateralAta,
|
|
751
|
+
fundingVaultAta,
|
|
752
|
+
harvestVaultCollateralAta,
|
|
753
|
+
interestVaultAta,
|
|
754
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
755
|
+
token2022Program: spl_token_1.TOKEN_2022_PROGRAM_ID,
|
|
756
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
757
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
758
|
+
})
|
|
759
|
+
.instruction();
|
|
760
|
+
instructions.push(harvestIx);
|
|
761
|
+
return instructions;
|
|
762
|
+
}
|
|
763
|
+
getHarvestVaultPda(lttId) {
|
|
764
|
+
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('harvest_vault'), lttId.toBuffer()], this.program.programId)[0];
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Claim LP fees for an active LTT
|
|
768
|
+
* @param signer The signer's public key
|
|
769
|
+
* @param lttId The LTT ID
|
|
770
|
+
* @param positionNftMint The position NFT mint
|
|
771
|
+
* @param ammConfig The AMM config
|
|
772
|
+
* @param cpAmmProgramId The CP AMM program ID
|
|
773
|
+
* @returns Transaction instruction for claiming fees
|
|
774
|
+
*/
|
|
775
|
+
async claimFees(signer, lttId, positionNftMint, ammConfig, cpAmmProgramId, receiver) {
|
|
776
|
+
const lttConfigPda = this.getLTTConfigPda(lttId);
|
|
777
|
+
const configPda = this.getConfigPda();
|
|
778
|
+
const lttConfig = await this.getLttConfig(lttId);
|
|
779
|
+
const lpAuthority = this.getLpAuthority();
|
|
780
|
+
// Derive pool key
|
|
781
|
+
const pool = (0, utils_1.derivePoolKey)(ammConfig, lttId, lttConfig.fundingTokenMint, cpAmmProgramId);
|
|
782
|
+
// Derive position PDA
|
|
783
|
+
const [position] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POSITION_SEED, positionNftMint.toBuffer()], cpAmmProgramId);
|
|
784
|
+
// Derive pool authority
|
|
785
|
+
const [poolAuthority] = web3_js_1.PublicKey.findProgramAddressSync([constants_1.POOL_AUTHORITY_SEED], cpAmmProgramId);
|
|
786
|
+
// Derive event authority
|
|
787
|
+
const [eventAuthority] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('__event_authority')], cpAmmProgramId);
|
|
788
|
+
// Derive vault addresses
|
|
789
|
+
const [lttVault, stableVault] = [
|
|
790
|
+
(0, utils_1.getVaultPda)(lttId, cpAmmProgramId, pool),
|
|
791
|
+
(0, utils_1.getVaultPda)(lttConfig.fundingTokenMint, cpAmmProgramId, pool),
|
|
792
|
+
];
|
|
793
|
+
// Get receiver's token accounts for receiving fees
|
|
794
|
+
const receiverTokenAAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(lttId, receiver, true);
|
|
795
|
+
const receiverTokenBAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(lttConfig.fundingTokenMint, receiver, true);
|
|
796
|
+
// Get position NFT account
|
|
797
|
+
const [positionNftAccount] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('position_nft_account'), positionNftMint.toBuffer()], cpAmmProgramId);
|
|
798
|
+
return await this.program.methods
|
|
799
|
+
.claimFees()
|
|
800
|
+
.accountsPartial({
|
|
801
|
+
signer,
|
|
802
|
+
lpAuthority,
|
|
803
|
+
config: configPda,
|
|
804
|
+
lttConfiguration: lttConfigPda,
|
|
805
|
+
pool,
|
|
806
|
+
position,
|
|
807
|
+
poolAuthority,
|
|
808
|
+
lttMint: lttId,
|
|
809
|
+
stableCoinMint: lttConfig.fundingTokenMint,
|
|
810
|
+
lttVaultAta: lttVault,
|
|
811
|
+
stableCoinVaultAta: stableVault,
|
|
812
|
+
receiverTokenAAccount: receiverTokenAAccount,
|
|
813
|
+
receiverTokenBAccount: receiverTokenBAccount,
|
|
814
|
+
positionNftAccount,
|
|
815
|
+
eventAuthority,
|
|
816
|
+
tokenAProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
817
|
+
tokenBProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
818
|
+
associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
819
|
+
cpAmmProgram: cpAmmProgramId,
|
|
820
|
+
systemProgram: web3_js_2.SystemProgram.programId,
|
|
821
|
+
})
|
|
822
|
+
.instruction();
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
exports.XitadelProgram = XitadelProgram;
|