@velocity-exchange/vaults-sdk 0.0.1 → 0.0.2
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/lib/accountSubscribers/index.d.ts +3 -0
- package/lib/accountSubscribers/index.d.ts.map +1 -0
- package/lib/accountSubscribers/index.js +18 -0
- package/lib/accountSubscribers/pollingVaultDepositorSubscriber.d.ts +8 -0
- package/lib/accountSubscribers/pollingVaultDepositorSubscriber.d.ts.map +1 -0
- package/lib/accountSubscribers/pollingVaultDepositorSubscriber.js +46 -0
- package/lib/accountSubscribers/pollingVaultSubscriber.d.ts +8 -0
- package/lib/accountSubscribers/pollingVaultSubscriber.d.ts.map +1 -0
- package/lib/accountSubscribers/pollingVaultSubscriber.js +46 -0
- package/lib/accountSubscribers/pollingVaultsProgramAccountSubscriber.d.ts +28 -0
- package/lib/accountSubscribers/pollingVaultsProgramAccountSubscriber.d.ts.map +1 -0
- package/lib/accountSubscribers/pollingVaultsProgramAccountSubscriber.js +71 -0
- package/lib/accounts/index.d.ts +3 -0
- package/lib/accounts/index.d.ts.map +1 -0
- package/lib/accounts/index.js +18 -0
- package/lib/accounts/vaultAccount.d.ts +27 -0
- package/lib/accounts/vaultAccount.d.ts.map +1 -0
- package/lib/accounts/vaultAccount.js +174 -0
- package/lib/accounts/vaultDepositorAccount.d.ts +18 -0
- package/lib/accounts/vaultDepositorAccount.d.ts.map +1 -0
- package/lib/accounts/vaultDepositorAccount.js +47 -0
- package/lib/accounts/vaultsProgramAccount.d.ts +13 -0
- package/lib/accounts/vaultsProgramAccount.d.ts.map +1 -0
- package/lib/accounts/vaultsProgramAccount.js +25 -0
- package/lib/addresses.d.ts +10 -0
- package/lib/addresses.d.ts.map +1 -0
- package/lib/addresses.js +87 -0
- package/lib/constants/index.d.ts +8 -0
- package/lib/constants/index.d.ts.map +1 -0
- package/lib/constants/index.js +12 -0
- package/lib/idl/drift_vaults.json +5698 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +27 -0
- package/lib/math/index.d.ts +3 -0
- package/lib/math/index.d.ts.map +1 -0
- package/lib/math/index.js +18 -0
- package/lib/math/vault.d.ts +17 -0
- package/lib/math/vault.d.ts.map +1 -0
- package/lib/math/vault.js +56 -0
- package/lib/math/vaultDepositor.d.ts +24 -0
- package/lib/math/vaultDepositor.d.ts.map +1 -0
- package/lib/math/vaultDepositor.js +49 -0
- package/lib/name.d.ts +4 -0
- package/lib/name.d.ts.map +1 -0
- package/lib/name.js +19 -0
- package/lib/parsers/index.d.ts +2 -0
- package/lib/parsers/index.d.ts.map +1 -0
- package/lib/parsers/index.js +17 -0
- package/lib/parsers/logParser.d.ts +15 -0
- package/lib/parsers/logParser.d.ts.map +1 -0
- package/lib/parsers/logParser.js +21 -0
- package/lib/types/drift_vaults.d.ts +6212 -0
- package/lib/types/drift_vaults.d.ts.map +1 -0
- package/lib/types/drift_vaults.js +2 -0
- package/lib/types/types.d.ts +283 -0
- package/lib/types/types.d.ts.map +1 -0
- package/lib/types/types.js +48 -0
- package/lib/utils.d.ts +10 -0
- package/lib/utils.d.ts.map +1 -0
- package/lib/utils.js +69 -0
- package/lib/vaultClient.d.ts +446 -0
- package/lib/vaultClient.d.ts.map +1 -0
- package/lib/vaultClient.js +1914 -0
- package/package.json +1 -1
- package/velocity-exchange-vaults-sdk-0.0.1.tgz +0 -0
|
@@ -0,0 +1,1914 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VaultClient = void 0;
|
|
4
|
+
const sdk_1 = require("@velocity-exchange/sdk");
|
|
5
|
+
const addresses_1 = require("./addresses");
|
|
6
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
7
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
8
|
+
const types_1 = require("./types/types");
|
|
9
|
+
const bytes_1 = require("@coral-xyz/anchor/dist/cjs/utils/bytes");
|
|
10
|
+
const math_1 = require("./math");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
|
+
const constants_1 = require("./constants");
|
|
13
|
+
class VaultClient {
|
|
14
|
+
constructor({ driftClient, program, metaplex,
|
|
15
|
+
// @deprecated, no longer used
|
|
16
|
+
cliMode, userMapConfig, }) {
|
|
17
|
+
this.driftClient = driftClient;
|
|
18
|
+
this.metaplex = metaplex;
|
|
19
|
+
this.program = program;
|
|
20
|
+
this.cliMode = !!cliMode;
|
|
21
|
+
if (!userMapConfig) {
|
|
22
|
+
this.vaultUsers = new sdk_1.UserMap({
|
|
23
|
+
driftClient: driftClient,
|
|
24
|
+
subscriptionConfig: {
|
|
25
|
+
type: 'polling',
|
|
26
|
+
frequency: 1000,
|
|
27
|
+
commitment: 'processed',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
this.vaultUsers = new sdk_1.UserMap(userMapConfig);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
getRemainingAccountsForUser(userAccounts, writableSpotMarketIndexes, vaultAccount, _userStats, skipVaultProtocol = false, _skipFuelOverflow = false, skipFeeUpdate = false) {
|
|
36
|
+
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
37
|
+
userAccounts,
|
|
38
|
+
writableSpotMarketIndexes,
|
|
39
|
+
});
|
|
40
|
+
const hasVaultProtocol = vaultAccount.vaultProtocol === true;
|
|
41
|
+
const hasFeeUpdate = (0, types_1.hasPendingFeeUpdate)(vaultAccount.feeUpdateStatus);
|
|
42
|
+
if (hasFeeUpdate && !skipFeeUpdate) {
|
|
43
|
+
const feeUpdate = (0, addresses_1.getFeeUpdateAddressSync)(this.program.programId, vaultAccount.pubkey);
|
|
44
|
+
remainingAccounts.push({
|
|
45
|
+
pubkey: feeUpdate,
|
|
46
|
+
isSigner: false,
|
|
47
|
+
isWritable: true,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (hasVaultProtocol && !skipVaultProtocol) {
|
|
51
|
+
const vaultProtocol = this.getVaultProtocolAddress(vaultAccount.pubkey);
|
|
52
|
+
remainingAccounts.push({
|
|
53
|
+
pubkey: vaultProtocol,
|
|
54
|
+
isSigner: false,
|
|
55
|
+
isWritable: true,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return remainingAccounts;
|
|
59
|
+
}
|
|
60
|
+
async checkIfAccountExists(account) {
|
|
61
|
+
try {
|
|
62
|
+
const accountInfo = await this.driftClient.connection.getAccountInfo(account);
|
|
63
|
+
return accountInfo != null;
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
// Doesn't already exist
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Unsubscribes from the vault users map. Call this to clean up any dangling promises.
|
|
72
|
+
*/
|
|
73
|
+
async unsubscribe() {
|
|
74
|
+
if (this.vaultUsers) {
|
|
75
|
+
await this.vaultUsers.unsubscribe();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async getVault(vault) {
|
|
79
|
+
return await this.program.account.vault.fetch(vault);
|
|
80
|
+
}
|
|
81
|
+
async getFeeUpdate(feeUpdate) {
|
|
82
|
+
return await this.program.account.feeUpdate.fetch(feeUpdate);
|
|
83
|
+
}
|
|
84
|
+
async getVaultAndSlot(vault) {
|
|
85
|
+
const vaultAndSlot = await this.program.account.vault.fetchAndContext(vault);
|
|
86
|
+
return {
|
|
87
|
+
vault: vaultAndSlot.data,
|
|
88
|
+
slot: vaultAndSlot.context.slot,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async getVaultDepositor(vaultDepositor) {
|
|
92
|
+
return await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
93
|
+
}
|
|
94
|
+
async getVaultDepositorAndSlot(vaultDepositor) {
|
|
95
|
+
const vaultDepositorAndSlot = await this.program.account.vaultDepositor.fetchAndContext(vaultDepositor);
|
|
96
|
+
return {
|
|
97
|
+
vaultDepositor: vaultDepositorAndSlot.data,
|
|
98
|
+
slot: vaultDepositorAndSlot.context.slot,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
getVaultProtocolAddress(vault) {
|
|
102
|
+
return (0, addresses_1.getVaultProtocolAddressSync)(this.program.programId, vault);
|
|
103
|
+
}
|
|
104
|
+
async getVaultProtocol(vaultProtocol) {
|
|
105
|
+
return await this.program.account.vaultProtocol.fetch(vaultProtocol);
|
|
106
|
+
}
|
|
107
|
+
async getVaultProtocolAndSlot(vaultProtocol) {
|
|
108
|
+
const vaultProtocolAndSlot = await this.program.account.vaultProtocol.fetchAndContext(vaultProtocol);
|
|
109
|
+
return {
|
|
110
|
+
vaultProtocol: vaultProtocolAndSlot.data,
|
|
111
|
+
slot: vaultProtocolAndSlot.context.slot,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async getAllVaultDepositorsWithNoWithdrawRequest(vault) {
|
|
115
|
+
const filters = [
|
|
116
|
+
{
|
|
117
|
+
// discriminator = VaultDepositor
|
|
118
|
+
memcmp: {
|
|
119
|
+
offset: 0,
|
|
120
|
+
bytes: bytes_1.bs58.encode(this.program.coder.accounts.accountDiscriminator('vaultDepositor')),
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
// vault = vault
|
|
125
|
+
memcmp: {
|
|
126
|
+
offset: 8,
|
|
127
|
+
bytes: vault.toBase58(),
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
// last_withdraw_request.shares (u128) = 0
|
|
132
|
+
memcmp: {
|
|
133
|
+
offset: 112,
|
|
134
|
+
bytes: bytes_1.bs58.encode(new Uint8Array(16).fill(0)),
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
// @ts-ignore
|
|
139
|
+
return (await this.program.account.vaultDepositor.all(filters));
|
|
140
|
+
}
|
|
141
|
+
async getAllVaultDepositors(vault) {
|
|
142
|
+
const filters = [
|
|
143
|
+
{
|
|
144
|
+
// discriminator = VaultDepositor
|
|
145
|
+
memcmp: {
|
|
146
|
+
offset: 0,
|
|
147
|
+
bytes: bytes_1.bs58.encode(this.program.coder.accounts.accountDiscriminator('vaultDepositor')),
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
];
|
|
151
|
+
if (vault) {
|
|
152
|
+
filters.push({
|
|
153
|
+
// vault = vault
|
|
154
|
+
memcmp: {
|
|
155
|
+
offset: 8,
|
|
156
|
+
bytes: vault.toBase58(),
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
// @ts-ignore
|
|
161
|
+
return (await this.program.account.vaultDepositor.all(filters));
|
|
162
|
+
}
|
|
163
|
+
async getAllVaultDepositorsForAuthority(authority) {
|
|
164
|
+
const filters = [
|
|
165
|
+
{
|
|
166
|
+
// discriminator = VaultDepositor
|
|
167
|
+
memcmp: {
|
|
168
|
+
offset: 0,
|
|
169
|
+
bytes: bytes_1.bs58.encode(this.program.coder.accounts.accountDiscriminator('vaultDepositor')),
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
filters.push({
|
|
174
|
+
// authority = authority
|
|
175
|
+
memcmp: {
|
|
176
|
+
offset: 8 + 32 + 32,
|
|
177
|
+
bytes: authority.toBase58(),
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
// @ts-ignore
|
|
181
|
+
return (await this.program.account.vaultDepositor.all(filters));
|
|
182
|
+
}
|
|
183
|
+
async getSubscribedVaultUser(vaultDriftUserAccountPubKey) {
|
|
184
|
+
return this.vaultUsers.mustGet(vaultDriftUserAccountPubKey.toBase58(), {
|
|
185
|
+
type: 'websocket',
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
/// useful for syncing state during tests.
|
|
189
|
+
async syncVaultUsers() {
|
|
190
|
+
for (const user of this.vaultUsers.values()) {
|
|
191
|
+
await user.fetchAccounts();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
*
|
|
196
|
+
* @param vault pubkey
|
|
197
|
+
* @param factorUnrealizedPNL add unrealized pnl to net balance
|
|
198
|
+
* @returns vault equity, in USDC
|
|
199
|
+
*/
|
|
200
|
+
async calculateVaultEquity(params) {
|
|
201
|
+
try {
|
|
202
|
+
// defaults to true if undefined
|
|
203
|
+
let factorUnrealizedPNL = true;
|
|
204
|
+
if (params.factorUnrealizedPNL !== undefined) {
|
|
205
|
+
factorUnrealizedPNL = params.factorUnrealizedPNL;
|
|
206
|
+
}
|
|
207
|
+
let includeManagerBorrowedValue = true;
|
|
208
|
+
if (params.includeManagerBorrowedValue !== undefined) {
|
|
209
|
+
includeManagerBorrowedValue = params.includeManagerBorrowedValue;
|
|
210
|
+
}
|
|
211
|
+
let vaultAccount;
|
|
212
|
+
if (params.address !== undefined) {
|
|
213
|
+
// @ts-ignore
|
|
214
|
+
vaultAccount = await this.program.account.vault.fetch(params.address);
|
|
215
|
+
}
|
|
216
|
+
else if (params.vault !== undefined) {
|
|
217
|
+
vaultAccount = params.vault;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
throw new Error('Must supply address or vault');
|
|
221
|
+
}
|
|
222
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
223
|
+
let netSpotValue = user.getNetSpotMarketValue();
|
|
224
|
+
if (factorUnrealizedPNL) {
|
|
225
|
+
const unrealizedPnl = user.getUnrealizedPNL(true, undefined, undefined);
|
|
226
|
+
netSpotValue = netSpotValue.add(unrealizedPnl);
|
|
227
|
+
}
|
|
228
|
+
if (includeManagerBorrowedValue) {
|
|
229
|
+
netSpotValue = netSpotValue.add(vaultAccount.managerBorrowedValue);
|
|
230
|
+
}
|
|
231
|
+
return netSpotValue;
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
console.error('VaultClient ~ err:', err);
|
|
235
|
+
return sdk_1.ZERO;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
async calculateVaultAllTimeNotionalPnl(params) {
|
|
239
|
+
try {
|
|
240
|
+
let vaultAccount;
|
|
241
|
+
if (params.address !== undefined) {
|
|
242
|
+
// @ts-ignore
|
|
243
|
+
vaultAccount = await this.program.account.vault.fetch(params.address);
|
|
244
|
+
}
|
|
245
|
+
else if (params.vault !== undefined) {
|
|
246
|
+
vaultAccount = params.vault;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
throw new Error('Must supply address or vault');
|
|
250
|
+
}
|
|
251
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
252
|
+
const allTimeTotalPnl = user.getTotalAllTimePnl();
|
|
253
|
+
return allTimeTotalPnl;
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
console.error('VaultClient ~ err:', err);
|
|
257
|
+
return sdk_1.ZERO;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
*
|
|
262
|
+
* @param vault pubkey
|
|
263
|
+
* @param factorUnrealizedPNL add unrealized pnl to existing equity
|
|
264
|
+
* @returns total vault equity, in spot deposit asset
|
|
265
|
+
*/
|
|
266
|
+
async calculateVaultEquityInDepositAsset(params) {
|
|
267
|
+
let vaultAccount;
|
|
268
|
+
if (params.address !== undefined) {
|
|
269
|
+
vaultAccount = await this.program.account.vault.fetch(params.address);
|
|
270
|
+
}
|
|
271
|
+
else if (params.vault !== undefined) {
|
|
272
|
+
vaultAccount = params.vault;
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
throw new Error('Must supply address or vault');
|
|
276
|
+
}
|
|
277
|
+
const vaultEquity = await this.calculateVaultEquity({
|
|
278
|
+
vault: vaultAccount,
|
|
279
|
+
factorUnrealizedPNL: params.factorUnrealizedPNL,
|
|
280
|
+
});
|
|
281
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
282
|
+
const spotOracle = this.driftClient.getOracleDataForSpotMarket(vaultAccount.spotMarketIndex);
|
|
283
|
+
const spotPrecision = sdk_1.TEN.pow(new sdk_1.BN(spotMarket.decimals));
|
|
284
|
+
return vaultEquity.mul(spotPrecision).div(spotOracle.price);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* @param params
|
|
288
|
+
* @returns vault depositor equity, in spot market value (which is usually USDC)
|
|
289
|
+
*/
|
|
290
|
+
async calculateWithdrawableVaultDepositorEquity(params) {
|
|
291
|
+
let vaultAccount;
|
|
292
|
+
if (params.vaultAddress !== undefined) {
|
|
293
|
+
vaultAccount = await this.program.account.vault.fetch(params.vaultAddress);
|
|
294
|
+
}
|
|
295
|
+
else if (params.vault !== undefined) {
|
|
296
|
+
vaultAccount = params.vault;
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
throw new Error('Must supply vaultAddress or vault');
|
|
300
|
+
}
|
|
301
|
+
let vaultDepositorAccount;
|
|
302
|
+
if (params.vaultDepositorAddress !== undefined) {
|
|
303
|
+
vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(params.vaultDepositorAddress);
|
|
304
|
+
}
|
|
305
|
+
else if (params.vaultDepositor !== undefined) {
|
|
306
|
+
vaultDepositorAccount = params.vaultDepositor;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
throw new Error('Must supply vaultDepositorAddress or vaultDepositor');
|
|
310
|
+
}
|
|
311
|
+
const vaultEquity = await this.calculateVaultEquity({
|
|
312
|
+
vault: vaultAccount,
|
|
313
|
+
factorUnrealizedPNL: false,
|
|
314
|
+
});
|
|
315
|
+
return (0, math_1.calculateRealizedVaultDepositorEquity)(vaultDepositorAccount, vaultEquity, vaultAccount);
|
|
316
|
+
}
|
|
317
|
+
async calculateWithdrawableVaultDepositorEquityInDepositAsset(params) {
|
|
318
|
+
let vaultAccount;
|
|
319
|
+
if (params.vaultAddress !== undefined) {
|
|
320
|
+
vaultAccount = await this.program.account.vault.fetch(params.vaultAddress);
|
|
321
|
+
}
|
|
322
|
+
else if (params.vault !== undefined) {
|
|
323
|
+
vaultAccount = params.vault;
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
throw new Error('Must supply vaultAddress or vault');
|
|
327
|
+
}
|
|
328
|
+
let vaultDepositorAccount;
|
|
329
|
+
if (params.vaultDepositorAddress !== undefined) {
|
|
330
|
+
vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(params.vaultDepositorAddress);
|
|
331
|
+
}
|
|
332
|
+
else if (params.vaultDepositor !== undefined) {
|
|
333
|
+
vaultDepositorAccount = params.vaultDepositor;
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
throw new Error('Must supply vaultDepositorAddress or vaultDepositor');
|
|
337
|
+
}
|
|
338
|
+
let vaultProtocol = undefined;
|
|
339
|
+
if (vaultAccount.vaultProtocol) {
|
|
340
|
+
vaultProtocol = await this.program.account.vaultProtocol.fetch(this.getVaultProtocolAddress(vaultAccount.pubkey));
|
|
341
|
+
}
|
|
342
|
+
const vaultEquity = await this.calculateVaultEquity({
|
|
343
|
+
vault: vaultAccount,
|
|
344
|
+
factorUnrealizedPNL: false,
|
|
345
|
+
});
|
|
346
|
+
const vdEquity = (0, math_1.calculateRealizedVaultDepositorEquity)(vaultDepositorAccount, vaultEquity, vaultAccount, vaultProtocol);
|
|
347
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
348
|
+
const spotOracle = this.driftClient.getOracleDataForSpotMarket(vaultAccount.spotMarketIndex);
|
|
349
|
+
const spotPrecision = sdk_1.TEN.pow(new sdk_1.BN(spotMarket.decimals));
|
|
350
|
+
return vdEquity.mul(spotPrecision).div(spotOracle.price);
|
|
351
|
+
}
|
|
352
|
+
async calculateVaultProtocolEquity(params) {
|
|
353
|
+
const vaultAccount = await this.program.account.vault.fetch(params.vault);
|
|
354
|
+
const vaultTotalEquity = await this.calculateVaultEquity({
|
|
355
|
+
vault: vaultAccount,
|
|
356
|
+
});
|
|
357
|
+
const vaultProtocol = this.getVaultProtocolAddress(params.vault);
|
|
358
|
+
const vpAccount = await this.program.account.vaultProtocol.fetch(vaultProtocol);
|
|
359
|
+
return (0, sdk_1.unstakeSharesToAmount)(vpAccount.protocolProfitAndFeeShares, vaultAccount.totalShares, vaultTotalEquity);
|
|
360
|
+
}
|
|
361
|
+
async initializeVault(params, uiTxParams) {
|
|
362
|
+
const ix = await this.getInitializeVaultIx(params);
|
|
363
|
+
return await this.createAndSendTxn([ix], uiTxParams);
|
|
364
|
+
}
|
|
365
|
+
async getInitializeVaultIx(params) {
|
|
366
|
+
var _a, _b, _c, _d;
|
|
367
|
+
const { vaultProtocol: vaultProtocolParams, ...vaultParams } = params;
|
|
368
|
+
const vault = (0, addresses_1.getVaultAddressSync)(this.program.programId, params.name);
|
|
369
|
+
const tokenAccount = (0, addresses_1.getTokenVaultAddressSync)(this.program.programId, vault);
|
|
370
|
+
const driftState = await this.driftClient.getStatePublicKey();
|
|
371
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(params.spotMarketIndex);
|
|
372
|
+
if (!spotMarket) {
|
|
373
|
+
throw new Error(`Spot market ${params.spotMarketIndex} not found on driftClient`);
|
|
374
|
+
}
|
|
375
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
376
|
+
const userKey = (0, sdk_1.getUserAccountPublicKeySync)(this.driftClient.program.programId, vault);
|
|
377
|
+
const accounts = {
|
|
378
|
+
driftSpotMarket: spotMarket.pubkey,
|
|
379
|
+
driftSpotMarketMint: spotMarket.mint,
|
|
380
|
+
driftUserStats: userStatsKey,
|
|
381
|
+
driftUser: userKey,
|
|
382
|
+
driftState,
|
|
383
|
+
vault,
|
|
384
|
+
tokenAccount,
|
|
385
|
+
driftProgram: this.driftClient.program.programId,
|
|
386
|
+
};
|
|
387
|
+
if (vaultProtocolParams) {
|
|
388
|
+
const _params = {
|
|
389
|
+
...vaultParams,
|
|
390
|
+
vaultProtocol: vaultProtocolParams,
|
|
391
|
+
};
|
|
392
|
+
const uiAuthority = this.driftClient.wallet.publicKey;
|
|
393
|
+
const initializeVaultWithProtocolIx = await this.program.methods
|
|
394
|
+
.initializeVaultWithProtocol(_params)
|
|
395
|
+
.accounts({
|
|
396
|
+
...accounts,
|
|
397
|
+
payer: (_a = params.manager) !== null && _a !== void 0 ? _a : uiAuthority,
|
|
398
|
+
manager: (_b = params.manager) !== null && _b !== void 0 ? _b : uiAuthority,
|
|
399
|
+
})
|
|
400
|
+
.instruction();
|
|
401
|
+
return initializeVaultWithProtocolIx;
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
const _params = vaultParams;
|
|
405
|
+
const uiAuthority = this.driftClient.wallet.publicKey;
|
|
406
|
+
const initializeVaultIx = await this.program.methods
|
|
407
|
+
.initializeVault(_params)
|
|
408
|
+
.accounts({
|
|
409
|
+
...accounts,
|
|
410
|
+
payer: (_c = params.manager) !== null && _c !== void 0 ? _c : uiAuthority,
|
|
411
|
+
manager: (_d = params.manager) !== null && _d !== void 0 ? _d : uiAuthority,
|
|
412
|
+
})
|
|
413
|
+
.instruction();
|
|
414
|
+
return initializeVaultIx;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Updates the delegate address for a vault. The delegate address will be allowed to trade
|
|
419
|
+
* on behalf of the vault.
|
|
420
|
+
* @param vault vault address to update
|
|
421
|
+
* @param delegate delegate address to update to
|
|
422
|
+
* @returns
|
|
423
|
+
*/
|
|
424
|
+
async updateDelegate(vault, delegate, uiTxParams) {
|
|
425
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
426
|
+
const updateDelegateIx = await this.getUpdateDelegateIx(vault, delegate, vaultAccount.user, vaultAccount.manager);
|
|
427
|
+
return await this.createAndSendTxn([updateDelegateIx], uiTxParams);
|
|
428
|
+
}
|
|
429
|
+
async getUpdateDelegateIx(vault, delegate, vaultDriftUser, vaultManager) {
|
|
430
|
+
const accounts = {
|
|
431
|
+
vault: vault,
|
|
432
|
+
driftUser: vaultDriftUser,
|
|
433
|
+
driftProgram: this.driftClient.program.programId,
|
|
434
|
+
};
|
|
435
|
+
return await this.program.methods
|
|
436
|
+
.updateDelegate(delegate)
|
|
437
|
+
.accounts({ ...accounts, manager: vaultManager })
|
|
438
|
+
.instruction();
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Updates the vault margin trading status.
|
|
442
|
+
* @param vault vault address to update
|
|
443
|
+
* @param enabled whether to enable margin trading
|
|
444
|
+
* @returns
|
|
445
|
+
*/
|
|
446
|
+
async updateMarginTradingEnabled(vault, enabled, uiTxParams) {
|
|
447
|
+
const updateMarginTradingEnabledIx = await this.getUpdateMarginTradingEnabledIx(vault, enabled);
|
|
448
|
+
return await this.createAndSendTxn([updateMarginTradingEnabledIx], uiTxParams);
|
|
449
|
+
}
|
|
450
|
+
async getUpdateMarginTradingEnabledIx(vault, enabled) {
|
|
451
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
452
|
+
const accounts = {
|
|
453
|
+
vault: vault,
|
|
454
|
+
driftUser: vaultAccount.user,
|
|
455
|
+
driftProgram: this.driftClient.program.programId,
|
|
456
|
+
};
|
|
457
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
458
|
+
const remainingAccounts = [];
|
|
459
|
+
try {
|
|
460
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
461
|
+
const driftProgram = this.driftClient.program;
|
|
462
|
+
const userStats = (await driftProgram.account.userStats.fetch(userStatsKey));
|
|
463
|
+
remainingAccounts.push(...this.getRemainingAccountsForUser([user.getUserAccount()], [], vaultAccount, userStats));
|
|
464
|
+
}
|
|
465
|
+
catch (err) {
|
|
466
|
+
console.error('failed to get remaining accounts', err);
|
|
467
|
+
// do nothing
|
|
468
|
+
}
|
|
469
|
+
return await this.program.methods
|
|
470
|
+
.updateMarginTradingEnabled(enabled)
|
|
471
|
+
.accounts({ ...accounts, manager: vaultAccount.manager })
|
|
472
|
+
.remainingAccounts(remainingAccounts)
|
|
473
|
+
.instruction();
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Updates the vault's pool id (for isolated pools).
|
|
477
|
+
* @param vault vault address to update
|
|
478
|
+
* @param poolId pool id to update to
|
|
479
|
+
* @returns
|
|
480
|
+
*/
|
|
481
|
+
async updateUserPoolId(vault, poolId, uiTxParams) {
|
|
482
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
483
|
+
const updatePoolIdIx = await this.getUpdatePoolIdIx(vault, poolId, vaultAccount);
|
|
484
|
+
return await this.createAndSendTxn([updatePoolIdIx], uiTxParams);
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Gets the instruction to update the pool id for a vault.
|
|
488
|
+
* @param vault vault address to update
|
|
489
|
+
* @param vaultAccount vault account data (optional, will be fetched if not provided)
|
|
490
|
+
* @param poolId pool id to update to
|
|
491
|
+
* @returns instruction to update pool id
|
|
492
|
+
*/
|
|
493
|
+
async getUpdatePoolIdIx(vault, poolId, vaultAccount) {
|
|
494
|
+
if (!vaultAccount) {
|
|
495
|
+
vaultAccount = await this.program.account.vault.fetch(vault);
|
|
496
|
+
}
|
|
497
|
+
const accounts = {
|
|
498
|
+
vault: vault,
|
|
499
|
+
driftUser: vaultAccount.user,
|
|
500
|
+
driftProgram: this.driftClient.program.programId,
|
|
501
|
+
};
|
|
502
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
503
|
+
const remainingAccounts = [];
|
|
504
|
+
try {
|
|
505
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
506
|
+
const driftProgram = this.driftClient.program;
|
|
507
|
+
const userStats = (await driftProgram.account.userStats.fetch(userStatsKey));
|
|
508
|
+
remainingAccounts.push(...this.getRemainingAccountsForUser([user.getUserAccount()], [], vaultAccount, userStats));
|
|
509
|
+
}
|
|
510
|
+
catch (err) {
|
|
511
|
+
console.error('failed to get remaining accounts', err);
|
|
512
|
+
// do nothing
|
|
513
|
+
}
|
|
514
|
+
return await this.program.methods
|
|
515
|
+
.updateUserPoolId(poolId)
|
|
516
|
+
.accounts({ ...accounts, manager: vaultAccount.manager })
|
|
517
|
+
.remainingAccounts(remainingAccounts)
|
|
518
|
+
.instruction();
|
|
519
|
+
}
|
|
520
|
+
async handleWSolMovement(amount, driftSpotMarket, userTokenAccount) {
|
|
521
|
+
const isSolDeposit = driftSpotMarket.mint.equals(sdk_1.WRAPPED_SOL_MINT);
|
|
522
|
+
const preIxs = [];
|
|
523
|
+
const postIxs = [];
|
|
524
|
+
if (isSolDeposit) {
|
|
525
|
+
const { ixs: createWSolAccountIxs, pubkey } = await this.driftClient.getWrappedSolAccountCreationIxs(amount, true);
|
|
526
|
+
userTokenAccount = pubkey;
|
|
527
|
+
preIxs.push(...createWSolAccountIxs);
|
|
528
|
+
postIxs.push((0, spl_token_1.createCloseAccountInstruction)(userTokenAccount, this.driftClient.wallet.publicKey, this.driftClient.wallet.publicKey, []));
|
|
529
|
+
}
|
|
530
|
+
return { userTokenAccount, preIxs, postIxs };
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
*
|
|
534
|
+
* @param vault vault address to deposit to
|
|
535
|
+
* @param amount amount to deposit
|
|
536
|
+
* @returns
|
|
537
|
+
*/
|
|
538
|
+
async managerDeposit(vault, amount, uiTxParams, managerTokenAccount) {
|
|
539
|
+
const managerDepositIxs = await this.getManagerDepositIx(vault, amount, managerTokenAccount);
|
|
540
|
+
return await this.createAndSendTxn(managerDepositIxs, uiTxParams);
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
*
|
|
544
|
+
* @param vault vault address to deposit to
|
|
545
|
+
* @param amount amount to deposit
|
|
546
|
+
* @returns
|
|
547
|
+
*/
|
|
548
|
+
async getManagerDepositIx(vault, amount, managerTokenAccount) {
|
|
549
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
550
|
+
const driftSpotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
551
|
+
if (!driftSpotMarket) {
|
|
552
|
+
throw new Error(`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`);
|
|
553
|
+
}
|
|
554
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
555
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
556
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
557
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, true, true);
|
|
558
|
+
const accounts = {
|
|
559
|
+
vault,
|
|
560
|
+
vaultTokenAccount: vaultAccount.tokenAccount,
|
|
561
|
+
driftUser: await (0, sdk_1.getUserAccountPublicKey)(this.driftClient.program.programId, vault),
|
|
562
|
+
driftUserStats: (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault),
|
|
563
|
+
driftProgram: this.driftClient.program.programId,
|
|
564
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
565
|
+
driftSpotMarketVault: driftSpotMarket.vault,
|
|
566
|
+
userTokenAccount: managerTokenAccount !== null && managerTokenAccount !== void 0 ? managerTokenAccount : (0, spl_token_1.getAssociatedTokenAddressSync)(driftSpotMarket.mint, vaultAccount.manager, true),
|
|
567
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
568
|
+
};
|
|
569
|
+
const { userTokenAccount, preIxs, postIxs } = await this.handleWSolMovement(amount, driftSpotMarket, accounts.userTokenAccount);
|
|
570
|
+
const managerDepositIx = await this.program.methods
|
|
571
|
+
.managerDeposit(amount)
|
|
572
|
+
.accounts({
|
|
573
|
+
...accounts,
|
|
574
|
+
userTokenAccount,
|
|
575
|
+
manager: vaultAccount.manager,
|
|
576
|
+
})
|
|
577
|
+
.remainingAccounts(remainingAccounts)
|
|
578
|
+
.instruction();
|
|
579
|
+
return [...preIxs, managerDepositIx, ...postIxs];
|
|
580
|
+
}
|
|
581
|
+
async managerRequestWithdraw(vault, amount, withdrawUnit, uiTxParams) {
|
|
582
|
+
const requestWithdrawIx = await this.getManagerRequestWithdrawIx(vault, amount, withdrawUnit);
|
|
583
|
+
return await this.createAndSendTxn([requestWithdrawIx], uiTxParams);
|
|
584
|
+
}
|
|
585
|
+
async getManagerRequestWithdrawIx(vault, amount, withdrawUnit) {
|
|
586
|
+
this.program.idl.types;
|
|
587
|
+
// @ts-ignore
|
|
588
|
+
const vaultAccount = (await this.program.account.vault.fetch(vault));
|
|
589
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
590
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
591
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
592
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, true, true);
|
|
593
|
+
const accounts = {
|
|
594
|
+
vault,
|
|
595
|
+
driftUser: vaultAccount.user,
|
|
596
|
+
driftUserStats: userStatsKey,
|
|
597
|
+
};
|
|
598
|
+
return this.program.instruction.managerRequestWithdraw(
|
|
599
|
+
// @ts-ignore
|
|
600
|
+
amount, withdrawUnit, {
|
|
601
|
+
accounts: {
|
|
602
|
+
manager: vaultAccount.manager,
|
|
603
|
+
...accounts,
|
|
604
|
+
},
|
|
605
|
+
remainingAccounts,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
async managerCancelWithdrawRequest(vault, uiTxParams) {
|
|
609
|
+
const ix = await this.getManagerCancelWithdrawRequestIx(vault);
|
|
610
|
+
return await this.createAndSendTxn([ix], uiTxParams);
|
|
611
|
+
}
|
|
612
|
+
async getManagerCancelWithdrawRequestIx(vault) {
|
|
613
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
614
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
615
|
+
const accounts = {
|
|
616
|
+
manager: vaultAccount.manager,
|
|
617
|
+
vault,
|
|
618
|
+
driftUser: vaultAccount.user,
|
|
619
|
+
driftUserStats: userStatsKey,
|
|
620
|
+
};
|
|
621
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
622
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
623
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [], vaultAccount, userStats, false, true, true);
|
|
624
|
+
return this.program.instruction.mangerCancelWithdrawRequest({
|
|
625
|
+
accounts,
|
|
626
|
+
remainingAccounts,
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
async managerWithdraw(vault, uiTxParams) {
|
|
630
|
+
const ixs = await this.getManagerWithdrawIx(vault);
|
|
631
|
+
return this.createAndSendTxn(ixs, uiTxParams);
|
|
632
|
+
}
|
|
633
|
+
async getManagerWithdrawIx(vault) {
|
|
634
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
635
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
636
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
637
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
638
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, false, false);
|
|
639
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
640
|
+
if (!spotMarket) {
|
|
641
|
+
throw new Error(`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`);
|
|
642
|
+
}
|
|
643
|
+
const isSolMarket = spotMarket.mint.equals(sdk_1.WRAPPED_SOL_MINT);
|
|
644
|
+
let userAta = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, vaultAccount.manager, true);
|
|
645
|
+
const preIxs = [];
|
|
646
|
+
const postIxs = [];
|
|
647
|
+
if (isSolMarket) {
|
|
648
|
+
const { ixs, pubkey } = await this.driftClient.getWrappedSolAccountCreationIxs(sdk_1.ZERO, false);
|
|
649
|
+
userAta = pubkey;
|
|
650
|
+
preIxs.push(...ixs);
|
|
651
|
+
postIxs.push((0, spl_token_1.createSyncNativeInstruction)(userAta));
|
|
652
|
+
postIxs.push((0, spl_token_1.createCloseAccountInstruction)(userAta, vaultAccount.manager, vaultAccount.manager, []));
|
|
653
|
+
}
|
|
654
|
+
else {
|
|
655
|
+
const userAtaExists = await this.driftClient.connection.getAccountInfo(userAta);
|
|
656
|
+
if (userAtaExists === null) {
|
|
657
|
+
preIxs.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(vaultAccount.manager, userAta, vaultAccount.manager, spotMarket.mint));
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
const withdrawIx = await this.program.instruction.managerWithdraw({
|
|
661
|
+
accounts: {
|
|
662
|
+
vault,
|
|
663
|
+
manager: vaultAccount.manager,
|
|
664
|
+
vaultTokenAccount: vaultAccount.tokenAccount,
|
|
665
|
+
driftUser: await (0, sdk_1.getUserAccountPublicKey)(this.driftClient.program.programId, vault),
|
|
666
|
+
driftProgram: this.driftClient.program.programId,
|
|
667
|
+
driftUserStats: (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault),
|
|
668
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
669
|
+
driftSpotMarketVault: spotMarket.vault,
|
|
670
|
+
userTokenAccount: userAta,
|
|
671
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
672
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
673
|
+
},
|
|
674
|
+
remainingAccounts,
|
|
675
|
+
});
|
|
676
|
+
return [...preIxs, withdrawIx, ...postIxs];
|
|
677
|
+
}
|
|
678
|
+
async managerBorrow(vault, borrowSpotMarketIndex, borrowAmount, managerTokenAccount, txParams) {
|
|
679
|
+
const ixs = await this.getManagerBorrowIx(vault, borrowSpotMarketIndex, borrowAmount, managerTokenAccount);
|
|
680
|
+
return await this.createAndSendTxn(ixs, txParams);
|
|
681
|
+
}
|
|
682
|
+
async getManagerBorrowIx(vault, borrowSpotMarketIndex, borrowAmount, managerTokenAccount) {
|
|
683
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
684
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(borrowSpotMarketIndex);
|
|
685
|
+
if (!spotMarket) {
|
|
686
|
+
throw new Error(`Spot market ${borrowSpotMarketIndex} not found on driftClient`);
|
|
687
|
+
}
|
|
688
|
+
if (!managerTokenAccount) {
|
|
689
|
+
managerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, this.driftClient.wallet.publicKey, true);
|
|
690
|
+
}
|
|
691
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
692
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
693
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
694
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [borrowSpotMarketIndex, vaultAccount.spotMarketIndex], vaultAccount, userStats, false, false, false);
|
|
695
|
+
const preIxs = [];
|
|
696
|
+
const postIxs = [];
|
|
697
|
+
const managerTokenAccountExists = await this.driftClient.connection.getAccountInfo(managerTokenAccount);
|
|
698
|
+
if (managerTokenAccountExists === null) {
|
|
699
|
+
preIxs.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(vaultAccount.manager, managerTokenAccount, vaultAccount.manager, spotMarket.mint));
|
|
700
|
+
}
|
|
701
|
+
const vaultBorrowTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, vault, true);
|
|
702
|
+
const vaultBorrowTokenAccountExists = await this.driftClient.connection.getAccountInfo(vaultBorrowTokenAccount);
|
|
703
|
+
if (vaultBorrowTokenAccountExists === null) {
|
|
704
|
+
preIxs.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(this.driftClient.wallet.publicKey, vaultBorrowTokenAccount, vault, spotMarket.mint));
|
|
705
|
+
}
|
|
706
|
+
if (spotMarket.mint.equals(sdk_1.WRAPPED_SOL_MINT)) {
|
|
707
|
+
postIxs.push((0, spl_token_1.createCloseAccountInstruction)(managerTokenAccount, vaultAccount.manager, vaultAccount.manager, []));
|
|
708
|
+
}
|
|
709
|
+
return [
|
|
710
|
+
...preIxs,
|
|
711
|
+
await this.program.methods
|
|
712
|
+
.managerBorrow(borrowSpotMarketIndex, borrowAmount)
|
|
713
|
+
.accounts({
|
|
714
|
+
vault,
|
|
715
|
+
vaultTokenAccount: vaultBorrowTokenAccount,
|
|
716
|
+
manager: vaultAccount.manager,
|
|
717
|
+
driftUserStats: userStatsKey,
|
|
718
|
+
driftUser: vaultAccount.user,
|
|
719
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
720
|
+
driftSpotMarketVault: spotMarket.vault,
|
|
721
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
722
|
+
userTokenAccount: managerTokenAccount,
|
|
723
|
+
})
|
|
724
|
+
.remainingAccounts(remainingAccounts)
|
|
725
|
+
.instruction(),
|
|
726
|
+
...postIxs,
|
|
727
|
+
];
|
|
728
|
+
}
|
|
729
|
+
async managerRepay(vault, repaySpotMarketIndex, repayAmount, repayValue, managerTokenAccount, uiTxParams) {
|
|
730
|
+
const ixs = await this.getManagerRepayIxs(vault, repaySpotMarketIndex, repayAmount, repayValue, managerTokenAccount);
|
|
731
|
+
return this.createAndSendTxn(ixs, uiTxParams);
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Get the instructions for the manager repay transaction
|
|
735
|
+
* @param vault - The vault to repay
|
|
736
|
+
* @param repaySpotMarketIndex - The spot market index to repay
|
|
737
|
+
* @param repayAmount - The amount to repay
|
|
738
|
+
* @param repayValue - The value of the repay
|
|
739
|
+
* @param managerTokenAccount - The manager token account to use, if depositing SOL, leave undefined to automatically wrap the SOL
|
|
740
|
+
* @returns The instructions for the manager repay transaction
|
|
741
|
+
*/
|
|
742
|
+
async getManagerRepayIxs(vault, repaySpotMarketIndex, repayAmount, repayValue, managerTokenAccount) {
|
|
743
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
744
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(repaySpotMarketIndex);
|
|
745
|
+
if (!spotMarket) {
|
|
746
|
+
throw new Error(`Spot market ${repaySpotMarketIndex} not found on driftClient`);
|
|
747
|
+
}
|
|
748
|
+
const isSolMarket = spotMarket.mint.equals(sdk_1.WRAPPED_SOL_MINT);
|
|
749
|
+
const preIxs = [];
|
|
750
|
+
const postIxs = [];
|
|
751
|
+
let createdWsolAccount = false;
|
|
752
|
+
if (!managerTokenAccount) {
|
|
753
|
+
if (isSolMarket) {
|
|
754
|
+
// create wSOL
|
|
755
|
+
const { ixs, pubkey } = await this.driftClient.getWrappedSolAccountCreationIxs(repayAmount, true);
|
|
756
|
+
preIxs.push(...ixs);
|
|
757
|
+
managerTokenAccount = pubkey;
|
|
758
|
+
createdWsolAccount = true;
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
managerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, vaultAccount.manager, true);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
const vaultRepayTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, vault, true);
|
|
765
|
+
const vaultRepayTokenAccountExists = await this.driftClient.connection.getAccountInfo(vaultRepayTokenAccount);
|
|
766
|
+
if (vaultRepayTokenAccountExists === null) {
|
|
767
|
+
preIxs.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(this.driftClient.wallet.publicKey, vaultRepayTokenAccount, vault, spotMarket.mint));
|
|
768
|
+
}
|
|
769
|
+
if (createdWsolAccount) {
|
|
770
|
+
postIxs.push((0, spl_token_1.createCloseAccountInstruction)(managerTokenAccount, vaultAccount.manager, vaultAccount.manager, []));
|
|
771
|
+
}
|
|
772
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
773
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
774
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
775
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [repaySpotMarketIndex, vaultAccount.spotMarketIndex], vaultAccount, userStats, false, false, false);
|
|
776
|
+
return [
|
|
777
|
+
...preIxs,
|
|
778
|
+
await this.program.methods
|
|
779
|
+
.managerRepay(repaySpotMarketIndex, repayAmount, repayValue)
|
|
780
|
+
.accounts({
|
|
781
|
+
vault,
|
|
782
|
+
vaultTokenAccount: vaultRepayTokenAccount,
|
|
783
|
+
manager: vaultAccount.manager,
|
|
784
|
+
driftUserStats: userStatsKey,
|
|
785
|
+
driftUser: vaultAccount.user,
|
|
786
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
787
|
+
driftSpotMarketVault: spotMarket.vault,
|
|
788
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
789
|
+
userTokenAccount: managerTokenAccount,
|
|
790
|
+
})
|
|
791
|
+
.remainingAccounts(remainingAccounts)
|
|
792
|
+
.instruction(),
|
|
793
|
+
...postIxs,
|
|
794
|
+
];
|
|
795
|
+
}
|
|
796
|
+
async managerUpdateBorrow(vault, newBorrowValue, txParams) {
|
|
797
|
+
const ix = await this.getManagerUpdateBorrowIx(vault, newBorrowValue);
|
|
798
|
+
return await this.createAndSendTxn([ix], txParams);
|
|
799
|
+
}
|
|
800
|
+
async getManagerUpdateBorrowIx(vault, newBorrowValue) {
|
|
801
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
802
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
803
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
804
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
805
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [], vaultAccount, userStats, false, false, false);
|
|
806
|
+
return this.program.instruction.managerUpdateBorrow(newBorrowValue, {
|
|
807
|
+
accounts: {
|
|
808
|
+
vault,
|
|
809
|
+
manager: vaultAccount.manager,
|
|
810
|
+
driftUserStats: userStatsKey,
|
|
811
|
+
driftUser: vaultAccount.user,
|
|
812
|
+
},
|
|
813
|
+
remainingAccounts,
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
async managerUpdateVault(vault, params, uiTxParams) {
|
|
817
|
+
const ix = await this.getManagerUpdateVaultIx(vault, params);
|
|
818
|
+
return this.createAndSendTxn([ix], uiTxParams);
|
|
819
|
+
}
|
|
820
|
+
async getManagerUpdateVaultIx(vault, params) {
|
|
821
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
822
|
+
return this.program.instruction.updateVault(params, {
|
|
823
|
+
accounts: {
|
|
824
|
+
vault,
|
|
825
|
+
manager: vaultAccount.manager,
|
|
826
|
+
},
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
async managerUpdateVaultManager(vault, manager, uiTxParams) {
|
|
830
|
+
const ix = await this.getManagerUpdateVaultManagerIx(vault, manager);
|
|
831
|
+
return this.createAndSendTxn([ix], uiTxParams);
|
|
832
|
+
}
|
|
833
|
+
async getManagerUpdateVaultManagerIx(vault, manager) {
|
|
834
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
835
|
+
return this.program.instruction.updateVaultManager(manager, {
|
|
836
|
+
accounts: {
|
|
837
|
+
vault,
|
|
838
|
+
manager: vaultAccount.manager,
|
|
839
|
+
},
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
async applyProfitShare(vault, vaultDepositor, uiTxParams) {
|
|
843
|
+
const ix = await this.getApplyProfitShareIx(vault, vaultDepositor);
|
|
844
|
+
return this.createAndSendTxn([ix], uiTxParams);
|
|
845
|
+
}
|
|
846
|
+
async getApplyProfitShareIx(vault, vaultDepositor) {
|
|
847
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
848
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
849
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
850
|
+
if (!spotMarket) {
|
|
851
|
+
throw new Error(`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`);
|
|
852
|
+
}
|
|
853
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
854
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
855
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, false, false);
|
|
856
|
+
const accounts = {
|
|
857
|
+
vault,
|
|
858
|
+
vaultDepositor,
|
|
859
|
+
manager: vaultAccount.manager,
|
|
860
|
+
driftUserStats: (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault),
|
|
861
|
+
driftUser: await (0, sdk_1.getUserAccountPublicKey)(this.driftClient.program.programId, vault),
|
|
862
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
863
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
864
|
+
driftProgram: this.driftClient.program.programId,
|
|
865
|
+
};
|
|
866
|
+
return this.program.instruction.applyProfitShare({
|
|
867
|
+
accounts: {
|
|
868
|
+
...accounts,
|
|
869
|
+
},
|
|
870
|
+
remainingAccounts,
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
async getApplyRebaseTokenizedDepositorIx(vault, tokenizedVaultDepositor) {
|
|
874
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
875
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
876
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
877
|
+
if (!spotMarket) {
|
|
878
|
+
throw new Error(`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`);
|
|
879
|
+
}
|
|
880
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
881
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
882
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, true, true);
|
|
883
|
+
const accounts = {
|
|
884
|
+
vault,
|
|
885
|
+
tokenizedVaultDepositor,
|
|
886
|
+
driftUser: await (0, sdk_1.getUserAccountPublicKey)(this.driftClient.program.programId, vault),
|
|
887
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
888
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
889
|
+
driftProgram: this.driftClient.program.programId,
|
|
890
|
+
};
|
|
891
|
+
return this.program.instruction.applyRebaseTokenizedDepositor({
|
|
892
|
+
accounts: {
|
|
893
|
+
...accounts,
|
|
894
|
+
},
|
|
895
|
+
remainingAccounts,
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
async applyRebase(vault, vaultDepositor) {
|
|
899
|
+
return await this.createAndSendTxn([
|
|
900
|
+
await this.getApplyRebaseIx(vault, vaultDepositor),
|
|
901
|
+
]);
|
|
902
|
+
}
|
|
903
|
+
async getApplyRebaseIx(vault, vaultDepositor) {
|
|
904
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
905
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
906
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
907
|
+
if (!spotMarket) {
|
|
908
|
+
throw new Error(`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`);
|
|
909
|
+
}
|
|
910
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
911
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
912
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, true, true);
|
|
913
|
+
const accounts = {
|
|
914
|
+
vault,
|
|
915
|
+
vaultDepositor,
|
|
916
|
+
driftUser: await (0, sdk_1.getUserAccountPublicKey)(this.driftClient.program.programId, vault),
|
|
917
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
918
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
919
|
+
driftProgram: this.driftClient.program.programId,
|
|
920
|
+
};
|
|
921
|
+
return this.program.instruction.applyRebase({
|
|
922
|
+
accounts: {
|
|
923
|
+
...accounts,
|
|
924
|
+
},
|
|
925
|
+
remainingAccounts,
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
async applyRebaseTokenizedDepositor(vault, tokenizedVaultDepositor) {
|
|
929
|
+
return await this.createAndSendTxn([
|
|
930
|
+
await this.getApplyRebaseTokenizedDepositorIx(vault, tokenizedVaultDepositor),
|
|
931
|
+
]);
|
|
932
|
+
}
|
|
933
|
+
createInitVaultDepositorIx(vault, authority, payer) {
|
|
934
|
+
const vaultDepositor = (0, addresses_1.getVaultDepositorAddressSync)(this.program.programId, vault, authority || this.driftClient.wallet.publicKey);
|
|
935
|
+
const accounts = {
|
|
936
|
+
vaultDepositor,
|
|
937
|
+
vault,
|
|
938
|
+
authority: authority || this.driftClient.wallet.publicKey,
|
|
939
|
+
};
|
|
940
|
+
const initIx = this.program.instruction.initializeVaultDepositor({
|
|
941
|
+
accounts: {
|
|
942
|
+
...accounts,
|
|
943
|
+
payer: payer || authority || this.driftClient.wallet.publicKey,
|
|
944
|
+
rent: web3_js_1.SYSVAR_RENT_PUBKEY,
|
|
945
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
946
|
+
},
|
|
947
|
+
});
|
|
948
|
+
return initIx;
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Initializes the vault depositor account. This account is used to deposit funds into a vault.
|
|
952
|
+
* @param vault the vault address to deposit into
|
|
953
|
+
* @param authority the authority allowed to make deposits into the vault
|
|
954
|
+
* @returns
|
|
955
|
+
*/
|
|
956
|
+
async initializeVaultDepositor(vault, authority, payer, uiTxParams) {
|
|
957
|
+
const initIx = this.createInitVaultDepositorIx(vault, authority, payer);
|
|
958
|
+
return await this.createAndSendTxn([initIx], uiTxParams);
|
|
959
|
+
}
|
|
960
|
+
async initializeTokenizedVaultDepositor(params, uiTxParams) {
|
|
961
|
+
var _a;
|
|
962
|
+
if (!this.metaplex) {
|
|
963
|
+
throw new Error('Metaplex instance is required when constructing VaultClient to initialize a tokenized vault depositor');
|
|
964
|
+
}
|
|
965
|
+
let spotMarketDecimals = 6;
|
|
966
|
+
let sharesBase = 0;
|
|
967
|
+
if (params.decimals === undefined || params.sharesBase === undefined) {
|
|
968
|
+
const vault = await this.program.account.vault.fetch(params.vault);
|
|
969
|
+
const spotMarketAccount = this.driftClient.getSpotMarketAccount(vault.spotMarketIndex);
|
|
970
|
+
if (!spotMarketAccount) {
|
|
971
|
+
throw new Error(`DriftClient failed to load vault's spot market (marketIndex: ${vault.spotMarketIndex})`);
|
|
972
|
+
}
|
|
973
|
+
spotMarketDecimals = spotMarketAccount.decimals;
|
|
974
|
+
sharesBase = vault.sharesBase;
|
|
975
|
+
}
|
|
976
|
+
const mintAddress = (0, addresses_1.getTokenizedVaultMintAddressSync)(this.program.programId, params.vault, sharesBase);
|
|
977
|
+
const vaultAccount = await this.program.account.vault.fetch(params.vault);
|
|
978
|
+
const accounts = {
|
|
979
|
+
vault: params.vault,
|
|
980
|
+
vaultDepositor: (0, addresses_1.getTokenizedVaultAddressSync)(this.program.programId, params.vault, sharesBase),
|
|
981
|
+
mintAccount: mintAddress,
|
|
982
|
+
metadataAccount: this.metaplex.nfts().pdas().metadata({
|
|
983
|
+
mint: mintAddress,
|
|
984
|
+
}),
|
|
985
|
+
tokenMetadataProgram: this.metaplex.programs().getTokenMetadata().address,
|
|
986
|
+
payer: vaultAccount.manager,
|
|
987
|
+
};
|
|
988
|
+
const vaultTokenAta = (0, spl_token_1.getAssociatedTokenAddressSync)(mintAddress, params.vault, true);
|
|
989
|
+
const createAtaIx = (0, spl_token_1.createAssociatedTokenAccountInstruction)(vaultAccount.manager, vaultTokenAta, params.vault, mintAddress);
|
|
990
|
+
return await this.createAndSendTxn([
|
|
991
|
+
await this.program.methods
|
|
992
|
+
.initializeTokenizedVaultDepositor({
|
|
993
|
+
...params,
|
|
994
|
+
decimals: (_a = params.decimals) !== null && _a !== void 0 ? _a : spotMarketDecimals,
|
|
995
|
+
})
|
|
996
|
+
.accounts(accounts)
|
|
997
|
+
.instruction(),
|
|
998
|
+
createAtaIx,
|
|
999
|
+
], uiTxParams);
|
|
1000
|
+
}
|
|
1001
|
+
async createTokenizeSharesIx(vaultDepositor, amount, unit, mint) {
|
|
1002
|
+
const vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1003
|
+
const vaultAccount = await this.program.account.vault.fetch(vaultDepositorAccount.vault);
|
|
1004
|
+
mint =
|
|
1005
|
+
mint !== null && mint !== void 0 ? mint : (0, addresses_1.getTokenizedVaultMintAddressSync)(this.program.programId, vaultDepositorAccount.vault, vaultAccount.sharesBase);
|
|
1006
|
+
const userAta = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, this.driftClient.wallet.publicKey, true);
|
|
1007
|
+
const ixs = [];
|
|
1008
|
+
const userAtaExists = await this.driftClient.connection.getAccountInfo(userAta);
|
|
1009
|
+
if (userAtaExists === null) {
|
|
1010
|
+
ixs.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(this.driftClient.wallet.publicKey, userAta, this.driftClient.wallet.publicKey, mint));
|
|
1011
|
+
}
|
|
1012
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1013
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vaultDepositorAccount.vault);
|
|
1014
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1015
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, true, true);
|
|
1016
|
+
ixs.push(await this.program.methods
|
|
1017
|
+
// anchor idl bug: https://github.com/coral-xyz/anchor/issues/2914
|
|
1018
|
+
// @ts-ignore args tuple vs anchor 0.32 IDL recursion limit
|
|
1019
|
+
.tokenizeShares(amount, unit)
|
|
1020
|
+
// `mint` is auto-resolved from IDL seeds, but anchor 1.0's IDL
|
|
1021
|
+
// generator can't encode `vault.shares_base.to_string().as_bytes()`
|
|
1022
|
+
// and emits broken seeds. Pass it explicitly to override.
|
|
1023
|
+
.accountsPartial({
|
|
1024
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1025
|
+
vault: vaultDepositorAccount.vault,
|
|
1026
|
+
tokenizedVaultDepositor: (0, addresses_1.getTokenizedVaultAddressSync)(this.program.programId, vaultDepositorAccount.vault, vaultAccount.sharesBase),
|
|
1027
|
+
mint,
|
|
1028
|
+
userTokenAccount: userAta,
|
|
1029
|
+
driftUser: vaultAccount.user,
|
|
1030
|
+
})
|
|
1031
|
+
.remainingAccounts(remainingAccounts)
|
|
1032
|
+
.instruction());
|
|
1033
|
+
return ixs;
|
|
1034
|
+
}
|
|
1035
|
+
async tokenizeShares(vaultDepositor, amount, unit, mint, txParams) {
|
|
1036
|
+
const ixs = await this.createTokenizeSharesIx(vaultDepositor, amount, unit, mint);
|
|
1037
|
+
return await this.createAndSendTxn(ixs, txParams);
|
|
1038
|
+
}
|
|
1039
|
+
async createTransferVaultDepositorSharesIx(fromVaultDepositor, toVaultDepositor, amount, withdrawUnit) {
|
|
1040
|
+
const vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(fromVaultDepositor);
|
|
1041
|
+
const vaultAccount = await this.program.account.vault.fetch(vaultDepositorAccount.vault);
|
|
1042
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1043
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vaultDepositorAccount.vault);
|
|
1044
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1045
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, true, true);
|
|
1046
|
+
const ixs = [];
|
|
1047
|
+
ixs.push(await this.program.methods
|
|
1048
|
+
// @ts-ignore args tuple vs anchor 0.32 IDL recursion limit
|
|
1049
|
+
.transferVaultDepositorShares(amount, withdrawUnit)
|
|
1050
|
+
.accounts({
|
|
1051
|
+
vault: vaultDepositorAccount.vault,
|
|
1052
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1053
|
+
toVaultDepositor,
|
|
1054
|
+
driftUser: vaultAccount.user,
|
|
1055
|
+
})
|
|
1056
|
+
.remainingAccounts(remainingAccounts)
|
|
1057
|
+
.instruction());
|
|
1058
|
+
return ixs;
|
|
1059
|
+
}
|
|
1060
|
+
async transferVaultDepositorShares(fromVaultDepositor, toVaultDepositor, amount, withdrawUnit, txParams) {
|
|
1061
|
+
const ixs = await this.createTransferVaultDepositorSharesIx(fromVaultDepositor, toVaultDepositor, amount, withdrawUnit);
|
|
1062
|
+
return await this.createAndSendTxn(ixs, txParams);
|
|
1063
|
+
}
|
|
1064
|
+
async createRedeemTokensIx(vaultDepositor, tokensToBurn, sharesBase) {
|
|
1065
|
+
const vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1066
|
+
const vaultAccount = await this.program.account.vault.fetch(vaultDepositorAccount.vault);
|
|
1067
|
+
const mint = (0, addresses_1.getTokenizedVaultMintAddressSync)(this.program.programId, vaultDepositorAccount.vault, sharesBase !== null && sharesBase !== void 0 ? sharesBase : vaultAccount.sharesBase);
|
|
1068
|
+
const userAta = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, this.driftClient.wallet.publicKey, true);
|
|
1069
|
+
const vaultTokenAta = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, vaultDepositorAccount.vault, true);
|
|
1070
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1071
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vaultDepositorAccount.vault);
|
|
1072
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1073
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, true, true);
|
|
1074
|
+
return await this.program.methods
|
|
1075
|
+
.redeemTokens(tokensToBurn)
|
|
1076
|
+
.accounts({
|
|
1077
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1078
|
+
vault: vaultDepositorAccount.vault,
|
|
1079
|
+
tokenizedVaultDepositor: (0, addresses_1.getTokenizedVaultAddressSync)(this.program.programId, vaultDepositorAccount.vault, sharesBase !== null && sharesBase !== void 0 ? sharesBase : vaultAccount.sharesBase),
|
|
1080
|
+
mint,
|
|
1081
|
+
userTokenAccount: userAta,
|
|
1082
|
+
vaultTokenAccount: vaultTokenAta,
|
|
1083
|
+
driftUser: vaultAccount.user,
|
|
1084
|
+
})
|
|
1085
|
+
.remainingAccounts(remainingAccounts)
|
|
1086
|
+
.instruction();
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1089
|
+
* Redeems tokens from the vault.
|
|
1090
|
+
* @param vaultDepositor
|
|
1091
|
+
* @param tokensToBurn
|
|
1092
|
+
* @param mint optionally provide a mint, or infer the mint from the current vault share base
|
|
1093
|
+
* @param txParams
|
|
1094
|
+
* @returns
|
|
1095
|
+
*/
|
|
1096
|
+
async redeemTokens(vaultDepositor, tokensToBurn, sharesBase, txParams) {
|
|
1097
|
+
const ix = await this.createRedeemTokensIx(vaultDepositor, tokensToBurn, sharesBase);
|
|
1098
|
+
return await this.createAndSendTxn([ix], txParams);
|
|
1099
|
+
}
|
|
1100
|
+
async prepDepositTx(vaultDepositor, amount, initVaultDepositor, depositTokenAccount) {
|
|
1101
|
+
let vaultPubKey;
|
|
1102
|
+
if (initVaultDepositor) {
|
|
1103
|
+
vaultPubKey = initVaultDepositor.vault;
|
|
1104
|
+
}
|
|
1105
|
+
else {
|
|
1106
|
+
const vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1107
|
+
vaultPubKey = vaultDepositorAccount.vault;
|
|
1108
|
+
}
|
|
1109
|
+
const vaultAccount = await this.program.account.vault.fetch(vaultPubKey);
|
|
1110
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1111
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vaultPubKey);
|
|
1112
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1113
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, false, false);
|
|
1114
|
+
const driftStateKey = await this.driftClient.getStatePublicKey();
|
|
1115
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
1116
|
+
if (!spotMarket) {
|
|
1117
|
+
throw new Error(`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`);
|
|
1118
|
+
}
|
|
1119
|
+
const nonWSolUserTokenAccount = depositTokenAccount !== null && depositTokenAccount !== void 0 ? depositTokenAccount : (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, this.driftClient.wallet.publicKey, true);
|
|
1120
|
+
const { userTokenAccount, preIxs, postIxs } = await this.handleWSolMovement(amount, spotMarket, nonWSolUserTokenAccount);
|
|
1121
|
+
const accounts = {
|
|
1122
|
+
vault: vaultPubKey,
|
|
1123
|
+
vaultDepositor,
|
|
1124
|
+
vaultTokenAccount: vaultAccount.tokenAccount,
|
|
1125
|
+
driftUserStats: userStatsKey,
|
|
1126
|
+
driftUser: vaultAccount.user,
|
|
1127
|
+
driftState: driftStateKey,
|
|
1128
|
+
driftSpotMarketVault: spotMarket.vault,
|
|
1129
|
+
userTokenAccount: userTokenAccount,
|
|
1130
|
+
driftProgram: this.driftClient.program.programId,
|
|
1131
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
1132
|
+
};
|
|
1133
|
+
return {
|
|
1134
|
+
vaultAccount,
|
|
1135
|
+
accounts,
|
|
1136
|
+
remainingAccounts,
|
|
1137
|
+
preIxs,
|
|
1138
|
+
postIxs,
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Creates a transaction to deposit funds into the specified vault.
|
|
1143
|
+
* Uses the associated token account of the vault depositor authority and spot market mint,
|
|
1144
|
+
* and assumes it exists before calling this function.
|
|
1145
|
+
* @param vaultDepositor
|
|
1146
|
+
* @param amount
|
|
1147
|
+
* @param initVaultDepositor If true, will initialize the vault depositor account
|
|
1148
|
+
* @returns transaction
|
|
1149
|
+
*/
|
|
1150
|
+
async createDepositTx(vaultDepositor, amount, initVaultDepositor, txParams, userTokenAccount) {
|
|
1151
|
+
const { vaultAccount, accounts, remainingAccounts, preIxs, postIxs } = await this.prepDepositTx(vaultDepositor, amount, initVaultDepositor, userTokenAccount);
|
|
1152
|
+
const ixs = [];
|
|
1153
|
+
if (initVaultDepositor) {
|
|
1154
|
+
ixs.push(this.createInitVaultDepositorIx(vaultAccount.pubkey, initVaultDepositor.authority));
|
|
1155
|
+
}
|
|
1156
|
+
const depositIx = await this.program.methods
|
|
1157
|
+
.deposit(amount)
|
|
1158
|
+
.accounts({
|
|
1159
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1160
|
+
...accounts,
|
|
1161
|
+
})
|
|
1162
|
+
.remainingAccounts(remainingAccounts)
|
|
1163
|
+
.instruction();
|
|
1164
|
+
ixs.push(...preIxs);
|
|
1165
|
+
ixs.push(depositIx);
|
|
1166
|
+
ixs.push(...postIxs);
|
|
1167
|
+
if ((txParams === null || txParams === void 0 ? void 0 : txParams.noLut) ? txParams.noLut : false) {
|
|
1168
|
+
return await this.createTxnNoLut(ixs, txParams);
|
|
1169
|
+
}
|
|
1170
|
+
else {
|
|
1171
|
+
return await this.createTxn(ixs, txParams);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Depositor funds into the specified vault.
|
|
1176
|
+
* @param vaultDepositor
|
|
1177
|
+
* @param amount
|
|
1178
|
+
* @param initVaultDepositor If true, will initialize the vault depositor account
|
|
1179
|
+
* @param txParams
|
|
1180
|
+
* @returns
|
|
1181
|
+
*/
|
|
1182
|
+
async deposit(vaultDepositor, amount, initVaultDepositor, txParams, userTokenAccount) {
|
|
1183
|
+
const depositTxn = await this.createDepositTx(vaultDepositor, amount, initVaultDepositor, txParams, userTokenAccount);
|
|
1184
|
+
return this.sendTxn(depositTxn, txParams === null || txParams === void 0 ? void 0 : txParams.simulateTransaction);
|
|
1185
|
+
}
|
|
1186
|
+
async requestWithdraw(vaultDepositor, amount, withdrawUnit, txParams) {
|
|
1187
|
+
const ixs = await this.getRequestWithdrawIx(vaultDepositor, amount, withdrawUnit, txParams === null || txParams === void 0 ? void 0 : txParams.oracleFeedsToCrank);
|
|
1188
|
+
return await this.createAndSendTxn(ixs, txParams);
|
|
1189
|
+
}
|
|
1190
|
+
async getRequestWithdrawIx(vaultDepositor, amount, withdrawUnit, oracleFeedsToCrank) {
|
|
1191
|
+
const vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1192
|
+
const vaultAccount = await this.program.account.vault.fetch(vaultDepositorAccount.vault);
|
|
1193
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1194
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vaultDepositorAccount.vault);
|
|
1195
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1196
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, false, false);
|
|
1197
|
+
const accounts = {
|
|
1198
|
+
vault: vaultDepositorAccount.vault,
|
|
1199
|
+
vaultDepositor,
|
|
1200
|
+
driftUser: vaultAccount.user,
|
|
1201
|
+
driftUserStats: userStatsKey,
|
|
1202
|
+
};
|
|
1203
|
+
const oracleFeedsToCrankIxs = await this.getOracleFeedsToCrankIxs(oracleFeedsToCrank);
|
|
1204
|
+
const requestWithdrawIx = this.program.instruction.requestWithdraw(
|
|
1205
|
+
// @ts-ignore
|
|
1206
|
+
amount, withdrawUnit, {
|
|
1207
|
+
accounts: {
|
|
1208
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1209
|
+
...accounts,
|
|
1210
|
+
},
|
|
1211
|
+
remainingAccounts,
|
|
1212
|
+
});
|
|
1213
|
+
return [...oracleFeedsToCrankIxs, requestWithdrawIx];
|
|
1214
|
+
}
|
|
1215
|
+
async withdraw(vaultDepositor, txParams) {
|
|
1216
|
+
const ixs = await this.getWithdrawIx(vaultDepositor, txParams === null || txParams === void 0 ? void 0 : txParams.oracleFeedsToCrank);
|
|
1217
|
+
return await this.createAndSendTxn(ixs, {
|
|
1218
|
+
cuLimit: 850000, // overestimating to be safe
|
|
1219
|
+
...txParams,
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
async getWithdrawIx(vaultDepositor, oracleFeedsToCrank) {
|
|
1223
|
+
const vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1224
|
+
const vaultAccount = await this.program.account.vault.fetch(vaultDepositorAccount.vault);
|
|
1225
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1226
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vaultDepositorAccount.vault);
|
|
1227
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1228
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, false, false);
|
|
1229
|
+
const driftStateKey = await this.driftClient.getStatePublicKey();
|
|
1230
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
1231
|
+
if (!spotMarket) {
|
|
1232
|
+
throw new Error(`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`);
|
|
1233
|
+
}
|
|
1234
|
+
const isSolMarket = spotMarket.mint.equals(sdk_1.WRAPPED_SOL_MINT);
|
|
1235
|
+
// let createAtaIx: TransactionInstruction | undefined = undefined;
|
|
1236
|
+
let userAta = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, this.driftClient.wallet.publicKey, true);
|
|
1237
|
+
const preIxs = [];
|
|
1238
|
+
const postIxs = [];
|
|
1239
|
+
if (isSolMarket) {
|
|
1240
|
+
const { ixs, pubkey } = await this.driftClient.getWrappedSolAccountCreationIxs(sdk_1.ZERO, false);
|
|
1241
|
+
userAta = pubkey;
|
|
1242
|
+
preIxs.push(...ixs);
|
|
1243
|
+
postIxs.push((0, spl_token_1.createSyncNativeInstruction)(userAta));
|
|
1244
|
+
postIxs.push((0, spl_token_1.createCloseAccountInstruction)(userAta, this.driftClient.wallet.publicKey, this.driftClient.wallet.publicKey, []));
|
|
1245
|
+
}
|
|
1246
|
+
else {
|
|
1247
|
+
const userAtaExists = await this.driftClient.connection.getAccountInfo(userAta);
|
|
1248
|
+
if (userAtaExists === null) {
|
|
1249
|
+
preIxs.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(this.driftClient.wallet.publicKey, userAta, this.driftClient.wallet.publicKey, spotMarket.mint));
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
const accounts = {
|
|
1253
|
+
vault: vaultDepositorAccount.vault,
|
|
1254
|
+
vaultDepositor,
|
|
1255
|
+
vaultTokenAccount: vaultAccount.tokenAccount,
|
|
1256
|
+
driftUserStats: userStatsKey,
|
|
1257
|
+
driftUser: vaultAccount.user,
|
|
1258
|
+
driftState: driftStateKey,
|
|
1259
|
+
driftSpotMarketVault: spotMarket.vault,
|
|
1260
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
1261
|
+
userTokenAccount: userAta,
|
|
1262
|
+
driftProgram: this.driftClient.program.programId,
|
|
1263
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
1264
|
+
};
|
|
1265
|
+
const oracleFeedsToCrankIxs = await this.getOracleFeedsToCrankIxs(oracleFeedsToCrank);
|
|
1266
|
+
const ixs = [
|
|
1267
|
+
...oracleFeedsToCrankIxs,
|
|
1268
|
+
...preIxs,
|
|
1269
|
+
await this.program.methods
|
|
1270
|
+
.withdraw()
|
|
1271
|
+
.accounts({
|
|
1272
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1273
|
+
...accounts,
|
|
1274
|
+
})
|
|
1275
|
+
.remainingAccounts(remainingAccounts)
|
|
1276
|
+
.instruction(),
|
|
1277
|
+
...postIxs,
|
|
1278
|
+
];
|
|
1279
|
+
return ixs;
|
|
1280
|
+
}
|
|
1281
|
+
async forceWithdraw(vaultDepositor, txParams) {
|
|
1282
|
+
const ix = await this.getForceWithdrawIx(vaultDepositor);
|
|
1283
|
+
return await this.createAndSendTxn(ix, txParams);
|
|
1284
|
+
}
|
|
1285
|
+
async getForceWithdrawIx(vaultDepositor) {
|
|
1286
|
+
const vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1287
|
+
const vaultAccount = await this.program.account.vault.fetch(vaultDepositorAccount.vault);
|
|
1288
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1289
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vaultDepositorAccount.vault);
|
|
1290
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1291
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, false, false);
|
|
1292
|
+
if (vaultAccount.vaultProtocol) {
|
|
1293
|
+
const vaultProtocol = this.getVaultProtocolAddress(vaultDepositorAccount.vault);
|
|
1294
|
+
remainingAccounts.push({
|
|
1295
|
+
pubkey: vaultProtocol,
|
|
1296
|
+
isSigner: false,
|
|
1297
|
+
isWritable: true,
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
const driftStateKey = await this.driftClient.getStatePublicKey();
|
|
1301
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
1302
|
+
if (!spotMarket) {
|
|
1303
|
+
throw new Error(`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`);
|
|
1304
|
+
}
|
|
1305
|
+
const [userTokenAccount, createAtaIx] = await (0, utils_1.getOrCreateATAInstruction)(spotMarket.mint, vaultDepositorAccount.authority, this.driftClient.connection, true, this.driftClient.wallet.publicKey);
|
|
1306
|
+
if (createAtaIx) {
|
|
1307
|
+
console.log(`Creating ATA for ${vaultDepositorAccount.authority.toBase58()} to ${userTokenAccount.toBase58()}`);
|
|
1308
|
+
}
|
|
1309
|
+
const accounts = {
|
|
1310
|
+
manager: vaultAccount.manager,
|
|
1311
|
+
vault: vaultDepositorAccount.vault,
|
|
1312
|
+
vaultDepositor,
|
|
1313
|
+
vaultTokenAccount: vaultAccount.tokenAccount,
|
|
1314
|
+
driftUserStats: userStatsKey,
|
|
1315
|
+
driftUser: vaultAccount.user,
|
|
1316
|
+
driftState: driftStateKey,
|
|
1317
|
+
driftSpotMarketVault: spotMarket.vault,
|
|
1318
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
1319
|
+
userTokenAccount,
|
|
1320
|
+
driftProgram: this.driftClient.program.programId,
|
|
1321
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
1322
|
+
};
|
|
1323
|
+
const ixs = [];
|
|
1324
|
+
if (createAtaIx) {
|
|
1325
|
+
ixs.push(createAtaIx);
|
|
1326
|
+
}
|
|
1327
|
+
ixs.push(await this.program.methods
|
|
1328
|
+
.forceWithdraw()
|
|
1329
|
+
.accounts(accounts)
|
|
1330
|
+
.remainingAccounts(remainingAccounts)
|
|
1331
|
+
.instruction());
|
|
1332
|
+
return ixs;
|
|
1333
|
+
}
|
|
1334
|
+
async cancelRequestWithdraw(vaultDepositor, txParams) {
|
|
1335
|
+
const ixs = await this.getCancelRequestWithdrawIx(vaultDepositor, txParams === null || txParams === void 0 ? void 0 : txParams.oracleFeedsToCrank);
|
|
1336
|
+
return await this.createAndSendTxn(ixs, txParams);
|
|
1337
|
+
}
|
|
1338
|
+
async getCancelRequestWithdrawIx(vaultDepositor, oracleFeedsToCrank) {
|
|
1339
|
+
const vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1340
|
+
const vaultAccount = await this.program.account.vault.fetch(vaultDepositorAccount.vault);
|
|
1341
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vaultDepositorAccount.vault);
|
|
1342
|
+
const accounts = {
|
|
1343
|
+
vault: vaultDepositorAccount.vault,
|
|
1344
|
+
vaultDepositor,
|
|
1345
|
+
driftUserStats: userStatsKey,
|
|
1346
|
+
driftUser: vaultAccount.user,
|
|
1347
|
+
};
|
|
1348
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1349
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1350
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, false, false);
|
|
1351
|
+
if (this.cliMode) {
|
|
1352
|
+
return [
|
|
1353
|
+
await this.program.methods
|
|
1354
|
+
.cancelRequestWithdraw()
|
|
1355
|
+
.accounts(accounts)
|
|
1356
|
+
.remainingAccounts(remainingAccounts)
|
|
1357
|
+
.instruction(),
|
|
1358
|
+
];
|
|
1359
|
+
}
|
|
1360
|
+
else {
|
|
1361
|
+
const oracleFeedsToCrankIxs = await this.getOracleFeedsToCrankIxs(oracleFeedsToCrank);
|
|
1362
|
+
const cancelRequestWithdrawIx = this.program.instruction.cancelRequestWithdraw({
|
|
1363
|
+
accounts: {
|
|
1364
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1365
|
+
...accounts,
|
|
1366
|
+
},
|
|
1367
|
+
remainingAccounts,
|
|
1368
|
+
});
|
|
1369
|
+
return [...oracleFeedsToCrankIxs, cancelRequestWithdrawIx];
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* Liquidates (become delegate for) a vault.
|
|
1374
|
+
* @param
|
|
1375
|
+
* @param
|
|
1376
|
+
* @returns
|
|
1377
|
+
*/
|
|
1378
|
+
async liquidate(vaultDepositor, txParams) {
|
|
1379
|
+
const ix = await this.getLiquidateIx(vaultDepositor);
|
|
1380
|
+
return await this.createAndSendTxn([ix], txParams);
|
|
1381
|
+
}
|
|
1382
|
+
async getLiquidateIx(vaultDepositor) {
|
|
1383
|
+
if (!this.driftClient.wallet.publicKey.equals(constants_1.VAULT_ADMIN_KEY)) {
|
|
1384
|
+
throw new Error('Only vault admin can liquidate');
|
|
1385
|
+
}
|
|
1386
|
+
const vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1387
|
+
const vault = vaultDepositorAccount.vault;
|
|
1388
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1389
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1390
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
1391
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1392
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [vaultAccount.spotMarketIndex], vaultAccount, userStats, false, true, true);
|
|
1393
|
+
const driftStateKey = await this.driftClient.getStatePublicKey();
|
|
1394
|
+
const accounts = {
|
|
1395
|
+
vault,
|
|
1396
|
+
vaultDepositor,
|
|
1397
|
+
vaultTokenAccount: vaultAccount.tokenAccount,
|
|
1398
|
+
driftUserStats: userStatsKey,
|
|
1399
|
+
driftUser: vaultAccount.user,
|
|
1400
|
+
driftState: driftStateKey,
|
|
1401
|
+
driftProgram: this.driftClient.program.programId,
|
|
1402
|
+
authority: vaultDepositorAccount.authority,
|
|
1403
|
+
};
|
|
1404
|
+
if (this.cliMode) {
|
|
1405
|
+
return await this.program.methods
|
|
1406
|
+
.liquidate()
|
|
1407
|
+
.accounts(accounts)
|
|
1408
|
+
.remainingAccounts(remainingAccounts)
|
|
1409
|
+
.instruction();
|
|
1410
|
+
}
|
|
1411
|
+
else {
|
|
1412
|
+
return this.program.instruction.liquidate({
|
|
1413
|
+
accounts: {
|
|
1414
|
+
...accounts,
|
|
1415
|
+
admin: this.driftClient.wallet.publicKey,
|
|
1416
|
+
},
|
|
1417
|
+
remainingAccounts,
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
async createTxn(vaultIxs, txParams) {
|
|
1422
|
+
var _a, _b;
|
|
1423
|
+
const ixs = [
|
|
1424
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
1425
|
+
units: (_a = txParams === null || txParams === void 0 ? void 0 : txParams.cuLimit) !== null && _a !== void 0 ? _a : 400000,
|
|
1426
|
+
}),
|
|
1427
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
1428
|
+
microLamports: (txParams === null || txParams === void 0 ? void 0 : txParams.cuPriceMicroLamports) === undefined
|
|
1429
|
+
? 50000
|
|
1430
|
+
: txParams.cuPriceMicroLamports,
|
|
1431
|
+
}),
|
|
1432
|
+
...vaultIxs,
|
|
1433
|
+
];
|
|
1434
|
+
return (await this.driftClient.txHandler.buildTransaction({
|
|
1435
|
+
connection: this.driftClient.connection,
|
|
1436
|
+
instructions: ixs,
|
|
1437
|
+
lookupTables: (_b = txParams === null || txParams === void 0 ? void 0 : txParams.lookupTables) !== null && _b !== void 0 ? _b : [],
|
|
1438
|
+
preFlightCommitment: 'confirmed',
|
|
1439
|
+
forceVersionedTransaction: true,
|
|
1440
|
+
txVersion: 0,
|
|
1441
|
+
fetchAllMarketLookupTableAccounts: this.driftClient.fetchAllLookupTableAccounts.bind(this.driftClient),
|
|
1442
|
+
}));
|
|
1443
|
+
}
|
|
1444
|
+
async createTxnNoLut(vaultIxs, txParams) {
|
|
1445
|
+
var _a;
|
|
1446
|
+
const ixs = [
|
|
1447
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
1448
|
+
units: (_a = txParams === null || txParams === void 0 ? void 0 : txParams.cuLimit) !== null && _a !== void 0 ? _a : 400000,
|
|
1449
|
+
}),
|
|
1450
|
+
web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
1451
|
+
microLamports: (txParams === null || txParams === void 0 ? void 0 : txParams.cuPriceMicroLamports) === undefined
|
|
1452
|
+
? 50000
|
|
1453
|
+
: txParams.cuPriceMicroLamports,
|
|
1454
|
+
}),
|
|
1455
|
+
...vaultIxs,
|
|
1456
|
+
];
|
|
1457
|
+
const recentBlockhash = await this.driftClient.connection.getLatestBlockhash();
|
|
1458
|
+
return this.driftClient.txHandler.generateVersionedTransaction(recentBlockhash, ixs, [], this.driftClient.wallet);
|
|
1459
|
+
}
|
|
1460
|
+
async sendTxn(transaction, simulateTransaction) {
|
|
1461
|
+
var _a;
|
|
1462
|
+
let txSig = bytes_1.bs58.encode(transaction.signatures[0]);
|
|
1463
|
+
if (simulateTransaction) {
|
|
1464
|
+
try {
|
|
1465
|
+
const resp = await this.driftClient.connection.simulateTransaction(transaction, {
|
|
1466
|
+
sigVerify: false,
|
|
1467
|
+
commitment: this.driftClient.connection.commitment,
|
|
1468
|
+
});
|
|
1469
|
+
console.log(`Simulated transaction:\n${JSON.stringify(resp, null, 2)}`);
|
|
1470
|
+
}
|
|
1471
|
+
catch (e) {
|
|
1472
|
+
const err = e;
|
|
1473
|
+
console.error(`Error simulating transaction: ${err.message}\n:${(_a = err.stack) !== null && _a !== void 0 ? _a : ''}`);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
else {
|
|
1477
|
+
const resp = await this.driftClient.sendTransaction(transaction, [], this.driftClient.opts);
|
|
1478
|
+
if (resp.txSig !== txSig) {
|
|
1479
|
+
txSig = resp.txSig;
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
return txSig;
|
|
1483
|
+
}
|
|
1484
|
+
/**
|
|
1485
|
+
* Used for UI wallet adapters compatibility
|
|
1486
|
+
*/
|
|
1487
|
+
async createAndSendTxn(vaultIxs, txParams) {
|
|
1488
|
+
let tx;
|
|
1489
|
+
if ((txParams === null || txParams === void 0 ? void 0 : txParams.noLut) ? txParams.noLut : false) {
|
|
1490
|
+
tx = await this.createTxnNoLut(vaultIxs, txParams);
|
|
1491
|
+
// @ts-ignore
|
|
1492
|
+
tx.sign([this.driftClient.wallet.payer]);
|
|
1493
|
+
}
|
|
1494
|
+
else {
|
|
1495
|
+
tx = await this.createTxn(vaultIxs, txParams);
|
|
1496
|
+
}
|
|
1497
|
+
const txSig = await this.sendTxn(tx, txParams === null || txParams === void 0 ? void 0 : txParams.simulateTransaction);
|
|
1498
|
+
return txSig;
|
|
1499
|
+
}
|
|
1500
|
+
/**
|
|
1501
|
+
* Initializes an insurance fund stake for the vault.
|
|
1502
|
+
* @param vault vault address to update
|
|
1503
|
+
* @param spotMarketIndex spot market index of the insurance fund stake
|
|
1504
|
+
* @returns
|
|
1505
|
+
*/
|
|
1506
|
+
async initializeInsuranceFundStake(vault, spotMarketIndex, txParams) {
|
|
1507
|
+
const ixs = await this.getInitializeInsuranceFundStakeIx(vault, spotMarketIndex);
|
|
1508
|
+
return await this.createAndSendTxn([ixs], txParams);
|
|
1509
|
+
}
|
|
1510
|
+
async getInitializeInsuranceFundStakeIx(vault, spotMarketIndex) {
|
|
1511
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1512
|
+
const _ifStakeAccountPublicKey = (0, sdk_1.getInsuranceFundStakeAccountPublicKey)(this.driftClient.program.programId, vault, spotMarketIndex);
|
|
1513
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex);
|
|
1514
|
+
if (!spotMarket) {
|
|
1515
|
+
throw new Error(`Spot market ${spotMarketIndex} not found on driftClient`);
|
|
1516
|
+
}
|
|
1517
|
+
const _ifVaultTokenAccount = (0, addresses_1.getInsuranceFundTokenVaultAddressSync)(this.program.programId, vault, spotMarketIndex);
|
|
1518
|
+
return await this.program.methods
|
|
1519
|
+
.initializeInsuranceFundStake(spotMarketIndex)
|
|
1520
|
+
.accounts({
|
|
1521
|
+
vault: vault,
|
|
1522
|
+
driftSpotMarketMint: spotMarket.mint,
|
|
1523
|
+
driftUserStats: vaultAccount.userStats,
|
|
1524
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
1525
|
+
})
|
|
1526
|
+
.instruction();
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* Adds an amount to an insurance fund stake for the vault.
|
|
1530
|
+
* @param vault vault address to update
|
|
1531
|
+
* @param spotMarketIndex spot market index of the insurance fund stake
|
|
1532
|
+
* @param amount amount to add to the insurance fund stake, in spotMarketIndex precision
|
|
1533
|
+
* @returns
|
|
1534
|
+
*/
|
|
1535
|
+
async addToInsuranceFundStake(vault, spotMarketIndex, amount, managerTokenAccount, txParams) {
|
|
1536
|
+
const ixs = await this.getAddToInsuranceFundStakeIx(vault, spotMarketIndex, amount, managerTokenAccount);
|
|
1537
|
+
return await this.createAndSendTxn([ixs], txParams);
|
|
1538
|
+
}
|
|
1539
|
+
async getAddToInsuranceFundStakeIx(vault, spotMarketIndex, amount, managerTokenAccount) {
|
|
1540
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1541
|
+
if (!vaultAccount.manager.equals(this.driftClient.wallet.publicKey)) {
|
|
1542
|
+
throw new Error(`Only the manager of the vault can add to the insurance fund stake.`);
|
|
1543
|
+
}
|
|
1544
|
+
const _ifStakeAccountPublicKey = (0, sdk_1.getInsuranceFundStakeAccountPublicKey)(this.driftClient.program.programId, vault, spotMarketIndex);
|
|
1545
|
+
const _ifVaultPublicKey = await (0, sdk_1.getInsuranceFundVaultPublicKey)(this.driftClient.program.programId, spotMarketIndex);
|
|
1546
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex);
|
|
1547
|
+
if (!spotMarket) {
|
|
1548
|
+
throw new Error(`Spot market ${spotMarketIndex} not found on driftClient`);
|
|
1549
|
+
}
|
|
1550
|
+
if (!managerTokenAccount) {
|
|
1551
|
+
managerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, vaultAccount.manager, true);
|
|
1552
|
+
}
|
|
1553
|
+
const _ifVaultTokenAccount = (0, addresses_1.getInsuranceFundTokenVaultAddressSync)(this.program.programId, vault, spotMarketIndex);
|
|
1554
|
+
return await this.program.methods
|
|
1555
|
+
.addInsuranceFundStake(spotMarketIndex, amount)
|
|
1556
|
+
.accounts({
|
|
1557
|
+
vault: vault,
|
|
1558
|
+
managerTokenAccount,
|
|
1559
|
+
driftUserStats: vaultAccount.userStats,
|
|
1560
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
1561
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
1562
|
+
})
|
|
1563
|
+
.instruction();
|
|
1564
|
+
}
|
|
1565
|
+
async requestRemoveInsuranceFundStake(vault, spotMarketIndex, amount, txParams) {
|
|
1566
|
+
const ix = await this.getRequestRemoveInsuranceFundStakeIx(vault, spotMarketIndex, amount);
|
|
1567
|
+
return await this.createAndSendTxn([ix], txParams);
|
|
1568
|
+
}
|
|
1569
|
+
async getRequestRemoveInsuranceFundStakeIx(vault, spotMarketIndex, amount) {
|
|
1570
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1571
|
+
const _ifStakeAccountPublicKey = (0, sdk_1.getInsuranceFundStakeAccountPublicKey)(this.driftClient.program.programId, vault, spotMarketIndex);
|
|
1572
|
+
const _ifVaultPublicKey = await (0, sdk_1.getInsuranceFundVaultPublicKey)(this.driftClient.program.programId, spotMarketIndex);
|
|
1573
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex);
|
|
1574
|
+
if (!spotMarket) {
|
|
1575
|
+
throw new Error(`Spot market ${spotMarketIndex} not found on driftClient`);
|
|
1576
|
+
}
|
|
1577
|
+
return await this.program.methods
|
|
1578
|
+
.requestRemoveInsuranceFundStake(spotMarketIndex, amount)
|
|
1579
|
+
.accounts({
|
|
1580
|
+
vault,
|
|
1581
|
+
manager: vaultAccount.manager,
|
|
1582
|
+
driftUserStats: vaultAccount.userStats,
|
|
1583
|
+
})
|
|
1584
|
+
.instruction();
|
|
1585
|
+
}
|
|
1586
|
+
async cancelRequestRemoveInsuranceFundStake(vault, spotMarketIndex, txParams) {
|
|
1587
|
+
const ix = await this.getCancelRequestRemoveInsuranceFundStakeIx(vault, spotMarketIndex);
|
|
1588
|
+
return await this.createAndSendTxn([ix], txParams);
|
|
1589
|
+
}
|
|
1590
|
+
async getCancelRequestRemoveInsuranceFundStakeIx(vault, spotMarketIndex) {
|
|
1591
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1592
|
+
const _ifStakeAccountPublicKey = (0, sdk_1.getInsuranceFundStakeAccountPublicKey)(this.driftClient.program.programId, vault, spotMarketIndex);
|
|
1593
|
+
const _ifVaultPublicKey = await (0, sdk_1.getInsuranceFundVaultPublicKey)(this.driftClient.program.programId, spotMarketIndex);
|
|
1594
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex);
|
|
1595
|
+
if (!spotMarket) {
|
|
1596
|
+
throw new Error(`Spot market ${spotMarketIndex} not found on driftClient`);
|
|
1597
|
+
}
|
|
1598
|
+
return await this.program.methods
|
|
1599
|
+
.cancelRequestRemoveInsuranceFundStake(spotMarketIndex)
|
|
1600
|
+
.accounts({
|
|
1601
|
+
vault: vault,
|
|
1602
|
+
manager: vaultAccount.manager,
|
|
1603
|
+
driftUserStats: vaultAccount.userStats,
|
|
1604
|
+
})
|
|
1605
|
+
.instruction();
|
|
1606
|
+
}
|
|
1607
|
+
async removeInsuranceFundStake(vault, spotMarketIndex, managerTokenAccount, txParams) {
|
|
1608
|
+
const ixs = await this.getRemoveInsuranceFundStakeIx(vault, spotMarketIndex, managerTokenAccount);
|
|
1609
|
+
return await this.createAndSendTxn([ixs], txParams);
|
|
1610
|
+
}
|
|
1611
|
+
async getRemoveInsuranceFundStakeIx(vault, spotMarketIndex, managerTokenAccount) {
|
|
1612
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1613
|
+
const _ifStakeAccountPublicKey = (0, sdk_1.getInsuranceFundStakeAccountPublicKey)(this.driftClient.program.programId, vault, spotMarketIndex);
|
|
1614
|
+
const _ifVaultPublicKey = await (0, sdk_1.getInsuranceFundVaultPublicKey)(this.driftClient.program.programId, spotMarketIndex);
|
|
1615
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex);
|
|
1616
|
+
if (!spotMarket) {
|
|
1617
|
+
throw new Error(`Spot market ${spotMarketIndex} not found on driftClient`);
|
|
1618
|
+
}
|
|
1619
|
+
if (!managerTokenAccount) {
|
|
1620
|
+
managerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, vaultAccount.manager, true);
|
|
1621
|
+
}
|
|
1622
|
+
const _ifVaultTokenAccount = (0, addresses_1.getInsuranceFundTokenVaultAddressSync)(this.program.programId, vault, spotMarketIndex);
|
|
1623
|
+
return await this.program.methods
|
|
1624
|
+
.removeInsuranceFundStake(spotMarketIndex)
|
|
1625
|
+
.accounts({
|
|
1626
|
+
vault: vault,
|
|
1627
|
+
managerTokenAccount,
|
|
1628
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
1629
|
+
driftUserStats: vaultAccount.userStats,
|
|
1630
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
1631
|
+
})
|
|
1632
|
+
.instruction();
|
|
1633
|
+
}
|
|
1634
|
+
async protocolRequestWithdraw(vault, amount, withdrawUnit, txParams) {
|
|
1635
|
+
const ix = await this.getProtocolRequestWithdrawIx(vault, amount, withdrawUnit);
|
|
1636
|
+
return await this.createAndSendTxn([ix], txParams);
|
|
1637
|
+
}
|
|
1638
|
+
async getProtocolRequestWithdrawIx(vault, amount, withdrawUnit) {
|
|
1639
|
+
// @ts-ignore
|
|
1640
|
+
const vaultAccount = (await this.program.account.vault.fetch(vault));
|
|
1641
|
+
const vp = this.getVaultProtocolAddress(vault);
|
|
1642
|
+
const vpAccount = (await this.program.account.vaultProtocol.fetch(vp));
|
|
1643
|
+
if (!this.driftClient.wallet.publicKey.equals(vpAccount.protocol)) {
|
|
1644
|
+
throw new Error(`Only the protocol of the vault can request a withdraw.`);
|
|
1645
|
+
}
|
|
1646
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1647
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
1648
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1649
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [], vaultAccount, userStats, false, true, true);
|
|
1650
|
+
const accounts = {
|
|
1651
|
+
vault,
|
|
1652
|
+
driftUserStats: userStatsKey,
|
|
1653
|
+
driftUser: vaultAccount.user,
|
|
1654
|
+
};
|
|
1655
|
+
if (this.cliMode) {
|
|
1656
|
+
return await this.program.methods
|
|
1657
|
+
// @ts-ignore, 0.29.0 anchor issues..
|
|
1658
|
+
.managerRequestWithdraw(amount, withdrawUnit)
|
|
1659
|
+
.accounts(accounts)
|
|
1660
|
+
.remainingAccounts(remainingAccounts)
|
|
1661
|
+
.instruction();
|
|
1662
|
+
}
|
|
1663
|
+
else {
|
|
1664
|
+
const requestWithdrawIx = this.program.instruction.managerRequestWithdraw(
|
|
1665
|
+
// @ts-ignore
|
|
1666
|
+
amount, withdrawUnit, {
|
|
1667
|
+
accounts: {
|
|
1668
|
+
manager: vaultAccount.manager,
|
|
1669
|
+
...accounts,
|
|
1670
|
+
},
|
|
1671
|
+
remainingAccounts,
|
|
1672
|
+
});
|
|
1673
|
+
return requestWithdrawIx;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
async protocolCancelWithdrawRequest(vault, txParams) {
|
|
1677
|
+
const ixs = await this.getProtocolCancelWithdrawRequestIx(vault);
|
|
1678
|
+
return await this.createAndSendTxn(ixs, txParams);
|
|
1679
|
+
}
|
|
1680
|
+
async getProtocolCancelWithdrawRequestIx(vault) {
|
|
1681
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1682
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
1683
|
+
const accounts = {
|
|
1684
|
+
manager: vaultAccount.manager,
|
|
1685
|
+
vault,
|
|
1686
|
+
driftUserStats: userStatsKey,
|
|
1687
|
+
driftUser: vaultAccount.user,
|
|
1688
|
+
};
|
|
1689
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1690
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1691
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [], vaultAccount, userStats, false, true, true);
|
|
1692
|
+
if (this.cliMode) {
|
|
1693
|
+
return [
|
|
1694
|
+
await this.program.methods
|
|
1695
|
+
.mangerCancelWithdrawRequest()
|
|
1696
|
+
.accounts(accounts)
|
|
1697
|
+
.remainingAccounts(remainingAccounts)
|
|
1698
|
+
.instruction(),
|
|
1699
|
+
];
|
|
1700
|
+
}
|
|
1701
|
+
else {
|
|
1702
|
+
const cancelRequestWithdrawIx = this.program.instruction.mangerCancelWithdrawRequest({
|
|
1703
|
+
accounts: {
|
|
1704
|
+
...accounts,
|
|
1705
|
+
manager: vaultAccount.manager,
|
|
1706
|
+
},
|
|
1707
|
+
remainingAccounts,
|
|
1708
|
+
});
|
|
1709
|
+
return [cancelRequestWithdrawIx];
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
async protocolWithdraw(vault, txParams) {
|
|
1713
|
+
const ixs = await this.getProtocolWithdrawIx(vault);
|
|
1714
|
+
return await this.createAndSendTxn(ixs, txParams);
|
|
1715
|
+
}
|
|
1716
|
+
async getProtocolWithdrawIx(vault) {
|
|
1717
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1718
|
+
if (!this.driftClient.wallet.publicKey.equals(vaultAccount.manager)) {
|
|
1719
|
+
throw new Error(`Only the manager of the vault can request a withdraw.`);
|
|
1720
|
+
}
|
|
1721
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1722
|
+
const userStatsKey = (0, sdk_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, vault);
|
|
1723
|
+
const userStats = (await this.driftClient.program.account.userStats.fetch(userStatsKey));
|
|
1724
|
+
const remainingAccounts = this.getRemainingAccountsForUser([user.getUserAccount()], [], vaultAccount, userStats, false, true, true);
|
|
1725
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
1726
|
+
if (!spotMarket) {
|
|
1727
|
+
throw new Error(`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`);
|
|
1728
|
+
}
|
|
1729
|
+
const ix = this.program.instruction.managerWithdraw({
|
|
1730
|
+
accounts: {
|
|
1731
|
+
vault,
|
|
1732
|
+
manager: vaultAccount.manager,
|
|
1733
|
+
vaultTokenAccount: vaultAccount.tokenAccount,
|
|
1734
|
+
driftUser: await (0, sdk_1.getUserAccountPublicKey)(this.driftClient.program.programId, vault),
|
|
1735
|
+
driftProgram: this.driftClient.program.programId,
|
|
1736
|
+
driftUserStats: userStatsKey,
|
|
1737
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
1738
|
+
driftSpotMarketVault: spotMarket.vault,
|
|
1739
|
+
userTokenAccount: (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarket.mint, this.driftClient.wallet.publicKey),
|
|
1740
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
1741
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
1742
|
+
},
|
|
1743
|
+
remainingAccounts,
|
|
1744
|
+
});
|
|
1745
|
+
return [ix];
|
|
1746
|
+
}
|
|
1747
|
+
async getPythLazerOracleCrankIxs(oracleFeedsToCrank = [], pythLazerMsgHexGetter) {
|
|
1748
|
+
try {
|
|
1749
|
+
const isPythLazerOracle = (oracleSource) => {
|
|
1750
|
+
const pythLazerStr = JSON.stringify(sdk_1.OracleSource.PYTH_LAZER);
|
|
1751
|
+
const pythLazer1kStr = JSON.stringify(sdk_1.OracleSource.PYTH_LAZER_1K);
|
|
1752
|
+
const pythLazer1mStr = JSON.stringify(sdk_1.OracleSource.PYTH_LAZER_1M);
|
|
1753
|
+
const pythLazerStableCoinStr = JSON.stringify(sdk_1.OracleSource.PYTH_LAZER_STABLE_COIN);
|
|
1754
|
+
const targetOracleSourceStr = JSON.stringify(oracleSource);
|
|
1755
|
+
return (targetOracleSourceStr === pythLazerStr ||
|
|
1756
|
+
targetOracleSourceStr === pythLazer1kStr ||
|
|
1757
|
+
targetOracleSourceStr === pythLazer1mStr ||
|
|
1758
|
+
targetOracleSourceStr === pythLazerStableCoinStr);
|
|
1759
|
+
};
|
|
1760
|
+
const pythLazerOracles = oracleFeedsToCrank.filter((config) => isPythLazerOracle(config.oracleSource));
|
|
1761
|
+
if (pythLazerOracles.length === 0) {
|
|
1762
|
+
return [];
|
|
1763
|
+
}
|
|
1764
|
+
if (!pythLazerMsgHexGetter) {
|
|
1765
|
+
console.error('pythLazerMsgHexGetter is required to crank pyth lazer oracles');
|
|
1766
|
+
return [];
|
|
1767
|
+
}
|
|
1768
|
+
const pythLazerFeedIds = pythLazerOracles
|
|
1769
|
+
.map((config) => config.pythLazerId)
|
|
1770
|
+
.filter(Boolean);
|
|
1771
|
+
const pythLazerMsgHex = await pythLazerMsgHexGetter(pythLazerFeedIds);
|
|
1772
|
+
const oracleUpdateIxs = await this.driftClient.getPostPythLazerOracleUpdateIxs(pythLazerFeedIds, pythLazerMsgHex, undefined, 3);
|
|
1773
|
+
return oracleUpdateIxs;
|
|
1774
|
+
}
|
|
1775
|
+
catch (err) {
|
|
1776
|
+
console.error('Error cranking pyth lazer oracles', err);
|
|
1777
|
+
return [];
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
async getOracleFeedsToCrankIxs(oracleFeedsToCrank) {
|
|
1781
|
+
if (!(oracleFeedsToCrank === null || oracleFeedsToCrank === void 0 ? void 0 : oracleFeedsToCrank.feedsToCrank)) {
|
|
1782
|
+
return [];
|
|
1783
|
+
}
|
|
1784
|
+
return await this.getPythLazerOracleCrankIxs(oracleFeedsToCrank.feedsToCrank, oracleFeedsToCrank.pythLazerMsgHexGetter);
|
|
1785
|
+
}
|
|
1786
|
+
async updateVaultProtocol(vault, params, txParams) {
|
|
1787
|
+
const ix = await this.getUpdateVaultProtocolIx(vault, params);
|
|
1788
|
+
return await this.createAndSendTxn([ix], txParams);
|
|
1789
|
+
}
|
|
1790
|
+
async getUpdateVaultProtocolIx(vault, params) {
|
|
1791
|
+
return this.program.methods
|
|
1792
|
+
.updateVaultProtocol(params)
|
|
1793
|
+
.accounts({
|
|
1794
|
+
vault,
|
|
1795
|
+
vaultProtocol: this.getVaultProtocolAddress(vault),
|
|
1796
|
+
})
|
|
1797
|
+
.instruction();
|
|
1798
|
+
}
|
|
1799
|
+
async adminInitFeeUpdate(vault, uiTxParams) {
|
|
1800
|
+
const ix = await this.getAdminInitFeeUpdateIx(vault);
|
|
1801
|
+
return await this.createAndSendTxn([ix], uiTxParams);
|
|
1802
|
+
}
|
|
1803
|
+
async getAdminInitFeeUpdateIx(vault) {
|
|
1804
|
+
const feeUpdate = (0, addresses_1.getFeeUpdateAddressSync)(this.program.programId, vault);
|
|
1805
|
+
return this.program.instruction.adminInitFeeUpdate({
|
|
1806
|
+
accounts: {
|
|
1807
|
+
vault,
|
|
1808
|
+
admin: this.driftClient.wallet.publicKey,
|
|
1809
|
+
feeUpdate,
|
|
1810
|
+
systemProgram: web3_js_1.SystemProgram.programId,
|
|
1811
|
+
},
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
async adminDeleteFeeUpdate(vault, uiTxParams) {
|
|
1815
|
+
const ix = await this.getAdminDeleteFeeUpdateIx(vault);
|
|
1816
|
+
return await this.createAndSendTxn([ix], uiTxParams);
|
|
1817
|
+
}
|
|
1818
|
+
async getAdminDeleteFeeUpdateIx(vault) {
|
|
1819
|
+
const feeUpdate = (0, addresses_1.getFeeUpdateAddressSync)(this.program.programId, vault);
|
|
1820
|
+
return this.program.instruction.adminDeleteFeeUpdate({
|
|
1821
|
+
accounts: {
|
|
1822
|
+
vault,
|
|
1823
|
+
admin: this.driftClient.wallet.publicKey,
|
|
1824
|
+
feeUpdate,
|
|
1825
|
+
},
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1828
|
+
async adminUpdateVaultClass(vault, newVaultClass, uiTxParams) {
|
|
1829
|
+
const ix = await this.getAdminUpdateVaultClassIx(vault, newVaultClass);
|
|
1830
|
+
return await this.createAndSendTxn([ix], uiTxParams);
|
|
1831
|
+
}
|
|
1832
|
+
async getAdminUpdateVaultClassIx(vault, newVaultClass) {
|
|
1833
|
+
return this.program.methods
|
|
1834
|
+
.adminUpdateVaultClass(newVaultClass)
|
|
1835
|
+
.accounts({
|
|
1836
|
+
vault,
|
|
1837
|
+
admin: this.driftClient.wallet.publicKey,
|
|
1838
|
+
})
|
|
1839
|
+
.instruction();
|
|
1840
|
+
}
|
|
1841
|
+
async managerUpdateFees(vault, params, uiTxParams) {
|
|
1842
|
+
const feeUpdate = (0, addresses_1.getFeeUpdateAddressSync)(this.program.programId, vault);
|
|
1843
|
+
const ixs = [];
|
|
1844
|
+
if (!(await this.checkIfAccountExists(feeUpdate))) {
|
|
1845
|
+
throw new Error('Fee update account does not exist, it must be created by an admin first');
|
|
1846
|
+
}
|
|
1847
|
+
ixs.push(await this.getManagerUpdateFeesIx(vault, params));
|
|
1848
|
+
return await this.createAndSendTxn(ixs, uiTxParams);
|
|
1849
|
+
}
|
|
1850
|
+
async getManagerUpdateFeesIx(vault, params) {
|
|
1851
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1852
|
+
const feeUpdate = (0, addresses_1.getFeeUpdateAddressSync)(this.program.programId, vault);
|
|
1853
|
+
return this.program.instruction.managerUpdateFees(params, {
|
|
1854
|
+
accounts: {
|
|
1855
|
+
vault,
|
|
1856
|
+
manager: vaultAccount.manager,
|
|
1857
|
+
feeUpdate,
|
|
1858
|
+
},
|
|
1859
|
+
});
|
|
1860
|
+
}
|
|
1861
|
+
async managerCancelFeeUpdate(vault, uiTxParams) {
|
|
1862
|
+
const ix = await this.getManagerCancelFeeUpdateIx(vault);
|
|
1863
|
+
return await this.createAndSendTxn([ix], uiTxParams);
|
|
1864
|
+
}
|
|
1865
|
+
async getManagerCancelFeeUpdateIx(vault) {
|
|
1866
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1867
|
+
const feeUpdate = (0, addresses_1.getFeeUpdateAddressSync)(this.program.programId, vault);
|
|
1868
|
+
return this.program.instruction.managerCancelFeeUpdate({
|
|
1869
|
+
accounts: {
|
|
1870
|
+
vault,
|
|
1871
|
+
manager: vaultAccount.manager,
|
|
1872
|
+
feeUpdate,
|
|
1873
|
+
},
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
/**
|
|
1877
|
+
* Calculate the vault share price (base value per share)
|
|
1878
|
+
* @param params vault address or vault account, and precision exponent
|
|
1879
|
+
* @returns BigNum representing the base value per share
|
|
1880
|
+
*/
|
|
1881
|
+
async calcVaultSharePrice(params) {
|
|
1882
|
+
let spotPrecisionExp = sdk_1.QUOTE_PRECISION_EXP;
|
|
1883
|
+
try {
|
|
1884
|
+
let vaultAccount;
|
|
1885
|
+
if (params.address !== undefined) {
|
|
1886
|
+
vaultAccount = await this.program.account.vault.fetch(params.address);
|
|
1887
|
+
}
|
|
1888
|
+
else if (params.vault !== undefined) {
|
|
1889
|
+
vaultAccount = params.vault;
|
|
1890
|
+
}
|
|
1891
|
+
else {
|
|
1892
|
+
throw new Error('Must supply address or vault');
|
|
1893
|
+
}
|
|
1894
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
|
|
1895
|
+
spotPrecisionExp = new sdk_1.BN(spotMarket.decimals);
|
|
1896
|
+
const totalAccountValue = await this.calculateVaultEquityInDepositAsset({
|
|
1897
|
+
vault: vaultAccount,
|
|
1898
|
+
factorUnrealizedPNL: true,
|
|
1899
|
+
});
|
|
1900
|
+
const vaultTotalShares = vaultAccount.totalShares.toString();
|
|
1901
|
+
const totalAccountValueStr = totalAccountValue.toString();
|
|
1902
|
+
return vaultTotalShares === '0'
|
|
1903
|
+
? sdk_1.BigNum.from(0, spotPrecisionExp)
|
|
1904
|
+
: new sdk_1.BigNum(totalAccountValueStr, spotPrecisionExp)
|
|
1905
|
+
.shift(constants_1.VAULT_SHARES_PRECISION_EXP)
|
|
1906
|
+
.div(new sdk_1.BigNum(vaultTotalShares, constants_1.VAULT_SHARES_PRECISION_EXP));
|
|
1907
|
+
}
|
|
1908
|
+
catch (err) {
|
|
1909
|
+
console.error('VaultClient calcVaultSharePrice error:', err);
|
|
1910
|
+
return sdk_1.BigNum.from(0, spotPrecisionExp);
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
exports.VaultClient = VaultClient;
|