@drift-labs/vaults-sdk 0.1.416 → 0.1.417
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/accounts/vaultAccount.d.ts +6 -1
- package/lib/accounts/vaultAccount.js +116 -0
- package/lib/addresses.d.ts +1 -0
- package/lib/addresses.js +7 -0
- package/lib/math/vaultDepositor.d.ts +11 -2
- package/lib/math/vaultDepositor.js +20 -2
- package/lib/types/drift_vaults.d.ts +450 -24
- package/lib/types/drift_vaults.js +450 -24
- package/lib/types/types.d.ts +66 -1
- package/lib/vaultClient.d.ts +53 -5
- package/lib/vaultClient.js +407 -42
- package/package.json +1 -1
- package/src/accounts/vaultAccount.ts +164 -3
- package/src/addresses.ts +13 -0
- package/src/idl/drift_vaults.json +453 -24
- package/src/math/vaultDepositor.ts +36 -4
- package/src/types/drift_vaults.ts +907 -55
- package/src/types/types.ts +79 -1
- package/src/vaultClient.ts +540 -42
package/src/vaultClient.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
getUserStatsAccountPublicKey,
|
|
9
9
|
TEN,
|
|
10
10
|
UserMap,
|
|
11
|
+
unstakeSharesToAmount as depositSharesToVaultAmount,
|
|
11
12
|
ZERO,
|
|
12
13
|
} from '@drift-labs/sdk';
|
|
13
14
|
import { BorshAccountsCoder, Program, ProgramAccount } from '@coral-xyz/anchor';
|
|
@@ -21,8 +22,10 @@ import {
|
|
|
21
22
|
getTokenVaultAddressSync,
|
|
22
23
|
getVaultAddressSync,
|
|
23
24
|
getVaultDepositorAddressSync,
|
|
25
|
+
getVaultProtocolAddressSync,
|
|
24
26
|
} from './addresses';
|
|
25
27
|
import {
|
|
28
|
+
AccountMeta,
|
|
26
29
|
AddressLookupTableAccount,
|
|
27
30
|
ComputeBudgetProgram,
|
|
28
31
|
PublicKey,
|
|
@@ -37,9 +40,17 @@ import {
|
|
|
37
40
|
getAssociatedTokenAddressSync,
|
|
38
41
|
TOKEN_PROGRAM_ID,
|
|
39
42
|
} from '@solana/spl-token';
|
|
40
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
Vault,
|
|
45
|
+
VaultDepositor,
|
|
46
|
+
VaultParams,
|
|
47
|
+
VaultProtocol,
|
|
48
|
+
VaultProtocolParams,
|
|
49
|
+
WithdrawUnit,
|
|
50
|
+
} from './types/types';
|
|
41
51
|
import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
|
|
42
52
|
import { UserMapConfig } from '@drift-labs/sdk/lib/userMap/userMapConfig';
|
|
53
|
+
import { calculateRealizedVaultDepositorEquity } from './math';
|
|
43
54
|
|
|
44
55
|
export type TxParams = {
|
|
45
56
|
cuLimit?: number;
|
|
@@ -87,8 +98,14 @@ export class VaultClient {
|
|
|
87
98
|
}
|
|
88
99
|
}
|
|
89
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Unsubscribes from the vault users map. Call this to clean up any dangling promises.
|
|
103
|
+
*/
|
|
104
|
+
public async unsubscribe() {
|
|
105
|
+
await this.vaultUsers.unsubscribe();
|
|
106
|
+
}
|
|
107
|
+
|
|
90
108
|
public async getVault(vault: PublicKey): Promise<Vault> {
|
|
91
|
-
// @ts-ignore
|
|
92
109
|
return await this.program.account.vault.fetch(vault);
|
|
93
110
|
}
|
|
94
111
|
|
|
@@ -119,6 +136,27 @@ export class VaultClient {
|
|
|
119
136
|
};
|
|
120
137
|
}
|
|
121
138
|
|
|
139
|
+
public getVaultProtocolAddress(vault: PublicKey): PublicKey {
|
|
140
|
+
return getVaultProtocolAddressSync(this.program.programId, vault);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public async getVaultProtocol(
|
|
144
|
+
vaultProtocol: PublicKey
|
|
145
|
+
): Promise<VaultProtocol> {
|
|
146
|
+
return await this.program.account.vaultProtocol.fetch(vaultProtocol);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public async getVaultProtocolAndSlot(
|
|
150
|
+
vaultProtocol: PublicKey
|
|
151
|
+
): Promise<{ vaultProtocol: VaultProtocol; slot: number }> {
|
|
152
|
+
const vaultProtocolAndSlot =
|
|
153
|
+
await this.program.account.vaultProtocol.fetchAndContext(vaultProtocol);
|
|
154
|
+
return {
|
|
155
|
+
vaultProtocol: vaultProtocolAndSlot.data as VaultProtocol,
|
|
156
|
+
slot: vaultProtocolAndSlot.context.slot,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
122
160
|
public async getAllVaultDepositorsWithNoWithdrawRequest(
|
|
123
161
|
vault: PublicKey
|
|
124
162
|
): Promise<ProgramAccount<VaultDepositor>[]> {
|
|
@@ -189,13 +227,21 @@ export class VaultClient {
|
|
|
189
227
|
/**
|
|
190
228
|
*
|
|
191
229
|
* @param vault pubkey
|
|
230
|
+
* @param factorUnrealizedPNL add unrealized pnl to net balance
|
|
192
231
|
* @returns vault equity, in USDC
|
|
193
232
|
*/
|
|
194
233
|
public async calculateVaultEquity(params: {
|
|
195
234
|
address?: PublicKey;
|
|
196
235
|
vault?: Vault;
|
|
236
|
+
factorUnrealizedPNL?: boolean;
|
|
197
237
|
}): Promise<BN> {
|
|
198
238
|
try {
|
|
239
|
+
// defaults to true if undefined
|
|
240
|
+
let factorUnrealizedPNL = true;
|
|
241
|
+
if (params.factorUnrealizedPNL !== undefined) {
|
|
242
|
+
factorUnrealizedPNL = params.factorUnrealizedPNL;
|
|
243
|
+
}
|
|
244
|
+
|
|
199
245
|
let vaultAccount: Vault;
|
|
200
246
|
if (params.address !== undefined) {
|
|
201
247
|
// @ts-ignore
|
|
@@ -209,9 +255,13 @@ export class VaultClient {
|
|
|
209
255
|
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
210
256
|
|
|
211
257
|
const netSpotValue = user.getNetSpotMarketValue();
|
|
212
|
-
const unrealizedPnl = user.getUnrealizedPNL(true, undefined, undefined);
|
|
213
258
|
|
|
214
|
-
|
|
259
|
+
if (factorUnrealizedPNL) {
|
|
260
|
+
const unrealizedPnl = user.getUnrealizedPNL(true, undefined, undefined);
|
|
261
|
+
return netSpotValue.add(unrealizedPnl);
|
|
262
|
+
} else {
|
|
263
|
+
return netSpotValue;
|
|
264
|
+
}
|
|
215
265
|
} catch (err) {
|
|
216
266
|
console.error('VaultClient ~ err:', err);
|
|
217
267
|
return ZERO;
|
|
@@ -221,15 +271,16 @@ export class VaultClient {
|
|
|
221
271
|
/**
|
|
222
272
|
*
|
|
223
273
|
* @param vault pubkey
|
|
224
|
-
* @
|
|
274
|
+
* @param factorUnrealizedPNL add unrealized pnl to existing equity
|
|
275
|
+
* @returns total vault equity, in spot deposit asset
|
|
225
276
|
*/
|
|
226
277
|
public async calculateVaultEquityInDepositAsset(params: {
|
|
227
278
|
address?: PublicKey;
|
|
228
279
|
vault?: Vault;
|
|
280
|
+
factorUnrealizedPNL?: boolean;
|
|
229
281
|
}): Promise<BN> {
|
|
230
282
|
let vaultAccount: Vault;
|
|
231
283
|
if (params.address !== undefined) {
|
|
232
|
-
// @ts-ignore
|
|
233
284
|
vaultAccount = await this.program.account.vault.fetch(params.address);
|
|
234
285
|
} else if (params.vault !== undefined) {
|
|
235
286
|
vaultAccount = params.vault;
|
|
@@ -238,6 +289,7 @@ export class VaultClient {
|
|
|
238
289
|
}
|
|
239
290
|
const vaultEquity = await this.calculateVaultEquity({
|
|
240
291
|
vault: vaultAccount,
|
|
292
|
+
factorUnrealizedPNL: params.factorUnrealizedPNL,
|
|
241
293
|
});
|
|
242
294
|
const spotMarket = this.driftClient.getSpotMarketAccount(
|
|
243
295
|
vaultAccount.spotMarketIndex
|
|
@@ -250,6 +302,124 @@ export class VaultClient {
|
|
|
250
302
|
return vaultEquity.mul(spotPrecision).div(spotOracle.price);
|
|
251
303
|
}
|
|
252
304
|
|
|
305
|
+
/**
|
|
306
|
+
* @param params
|
|
307
|
+
* @returns vault depositor equity, in spot market value (which is usually USDC)
|
|
308
|
+
*/
|
|
309
|
+
public async calculateWithdrawableVaultDepositorEquity(params: {
|
|
310
|
+
vaultDepositorAddress?: PublicKey;
|
|
311
|
+
vaultDepositor?: VaultDepositor;
|
|
312
|
+
vaultAddress?: PublicKey;
|
|
313
|
+
vault?: Vault;
|
|
314
|
+
}): Promise<BN> {
|
|
315
|
+
let vaultAccount: Vault;
|
|
316
|
+
if (params.vaultAddress !== undefined) {
|
|
317
|
+
vaultAccount = await this.program.account.vault.fetch(
|
|
318
|
+
params.vaultAddress
|
|
319
|
+
);
|
|
320
|
+
} else if (params.vault !== undefined) {
|
|
321
|
+
vaultAccount = params.vault;
|
|
322
|
+
} else {
|
|
323
|
+
throw new Error('Must supply vaultAddress or vault');
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
let vaultDepositorAccount: VaultDepositor;
|
|
327
|
+
if (params.vaultDepositorAddress !== undefined) {
|
|
328
|
+
vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(
|
|
329
|
+
params.vaultDepositorAddress
|
|
330
|
+
);
|
|
331
|
+
} else if (params.vaultDepositor !== undefined) {
|
|
332
|
+
vaultDepositorAccount = params.vaultDepositor;
|
|
333
|
+
} else {
|
|
334
|
+
throw new Error('Must supply vaultDepositorAddress or vaultDepositor');
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const vaultEquity = await this.calculateVaultEquity({
|
|
338
|
+
vault: vaultAccount,
|
|
339
|
+
factorUnrealizedPNL: false,
|
|
340
|
+
});
|
|
341
|
+
return calculateRealizedVaultDepositorEquity(
|
|
342
|
+
vaultDepositorAccount,
|
|
343
|
+
vaultEquity,
|
|
344
|
+
vaultAccount
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
public async calculateWithdrawableVaultDepositorEquityInDepositAsset(params: {
|
|
349
|
+
vaultDepositorAddress?: PublicKey;
|
|
350
|
+
vaultDepositor?: VaultDepositor;
|
|
351
|
+
vaultAddress?: PublicKey;
|
|
352
|
+
vault?: Vault;
|
|
353
|
+
}): Promise<BN> {
|
|
354
|
+
let vaultAccount: Vault;
|
|
355
|
+
if (params.vaultAddress !== undefined) {
|
|
356
|
+
vaultAccount = await this.program.account.vault.fetch(
|
|
357
|
+
params.vaultAddress
|
|
358
|
+
);
|
|
359
|
+
} else if (params.vault !== undefined) {
|
|
360
|
+
vaultAccount = params.vault;
|
|
361
|
+
} else {
|
|
362
|
+
throw new Error('Must supply vaultAddress or vault');
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
let vaultDepositorAccount: VaultDepositor;
|
|
366
|
+
if (params.vaultDepositorAddress !== undefined) {
|
|
367
|
+
vaultDepositorAccount = await this.program.account.vaultDepositor.fetch(
|
|
368
|
+
params.vaultDepositorAddress
|
|
369
|
+
);
|
|
370
|
+
} else if (params.vaultDepositor !== undefined) {
|
|
371
|
+
vaultDepositorAccount = params.vaultDepositor;
|
|
372
|
+
} else {
|
|
373
|
+
throw new Error('Must supply vaultDepositorAddress or vaultDepositor');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
let vaultProtocol: VaultProtocol | undefined = undefined;
|
|
377
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
378
|
+
vaultProtocol = await this.program.account.vaultProtocol.fetch(
|
|
379
|
+
vaultAccount.vaultProtocol
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const vaultEquity = await this.calculateVaultEquity({
|
|
384
|
+
vault: vaultAccount,
|
|
385
|
+
factorUnrealizedPNL: false,
|
|
386
|
+
});
|
|
387
|
+
const vdEquity = calculateRealizedVaultDepositorEquity(
|
|
388
|
+
vaultDepositorAccount,
|
|
389
|
+
vaultEquity,
|
|
390
|
+
vaultAccount,
|
|
391
|
+
vaultProtocol
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(
|
|
395
|
+
vaultAccount.spotMarketIndex
|
|
396
|
+
);
|
|
397
|
+
const spotOracle = this.driftClient.getOracleDataForSpotMarket(
|
|
398
|
+
vaultAccount.spotMarketIndex
|
|
399
|
+
);
|
|
400
|
+
const spotPrecision = TEN.pow(new BN(spotMarket!.decimals));
|
|
401
|
+
|
|
402
|
+
return vdEquity.mul(spotPrecision).div(spotOracle.price);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
public async calculateVaultProtocolEquity(params: {
|
|
406
|
+
vault: PublicKey;
|
|
407
|
+
}): Promise<BN> {
|
|
408
|
+
const vaultAccount = await this.program.account.vault.fetch(params.vault);
|
|
409
|
+
const vaultTotalEquity = await this.calculateVaultEquity({
|
|
410
|
+
vault: vaultAccount,
|
|
411
|
+
});
|
|
412
|
+
const vaultProtocol = this.getVaultProtocolAddress(params.vault);
|
|
413
|
+
const vpAccount = await this.program.account.vaultProtocol.fetch(
|
|
414
|
+
vaultProtocol
|
|
415
|
+
);
|
|
416
|
+
return depositSharesToVaultAmount(
|
|
417
|
+
vpAccount.protocolProfitAndFeeShares,
|
|
418
|
+
vaultAccount.totalShares,
|
|
419
|
+
vaultTotalEquity
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
253
423
|
public async initializeVault(params: {
|
|
254
424
|
name: number[];
|
|
255
425
|
spotMarketIndex: number;
|
|
@@ -260,7 +430,17 @@ export class VaultClient {
|
|
|
260
430
|
profitShare: number;
|
|
261
431
|
hurdleRate: number;
|
|
262
432
|
permissioned: boolean;
|
|
433
|
+
vaultProtocol?: VaultProtocolParams;
|
|
263
434
|
}): Promise<TransactionSignature> {
|
|
435
|
+
// This is a workaround to make client backwards compatible.
|
|
436
|
+
// VaultProtocol is optionally undefined, but the anchor type is optionally null.
|
|
437
|
+
// Old clients will default to undefined which prevents old clients from having to pass in a null value.
|
|
438
|
+
// Instead, we can cast to null internally.
|
|
439
|
+
const _params: VaultParams = {
|
|
440
|
+
...params,
|
|
441
|
+
vaultProtocol: params.vaultProtocol ? params.vaultProtocol : null,
|
|
442
|
+
};
|
|
443
|
+
|
|
264
444
|
const vault = getVaultAddressSync(this.program.programId, params.name);
|
|
265
445
|
const tokenAccount = getTokenVaultAddressSync(
|
|
266
446
|
this.program.programId,
|
|
@@ -297,18 +477,44 @@ export class VaultClient {
|
|
|
297
477
|
driftProgram: this.driftClient.program.programId,
|
|
298
478
|
};
|
|
299
479
|
|
|
300
|
-
|
|
301
|
-
.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
.
|
|
480
|
+
if (params.vaultProtocol) {
|
|
481
|
+
const vaultProtocol = this.getVaultProtocolAddress(
|
|
482
|
+
getVaultAddressSync(this.program.programId, params.name)
|
|
483
|
+
);
|
|
484
|
+
const remainingAccounts: AccountMeta[] = [
|
|
485
|
+
{
|
|
486
|
+
pubkey: vaultProtocol,
|
|
487
|
+
isSigner: false,
|
|
488
|
+
isWritable: true,
|
|
489
|
+
},
|
|
490
|
+
];
|
|
491
|
+
return await this.program.methods
|
|
492
|
+
.initializeVault(_params)
|
|
493
|
+
.preInstructions([
|
|
494
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
495
|
+
units: 400_000,
|
|
496
|
+
}),
|
|
497
|
+
ComputeBudgetProgram.setComputeUnitPrice({
|
|
498
|
+
microLamports: 300_000,
|
|
499
|
+
}),
|
|
500
|
+
])
|
|
501
|
+
.accounts(accounts)
|
|
502
|
+
.remainingAccounts(remainingAccounts)
|
|
503
|
+
.rpc();
|
|
504
|
+
} else {
|
|
505
|
+
return await this.program.methods
|
|
506
|
+
.initializeVault(_params)
|
|
507
|
+
.preInstructions([
|
|
508
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
509
|
+
units: 400_000,
|
|
510
|
+
}),
|
|
511
|
+
ComputeBudgetProgram.setComputeUnitPrice({
|
|
512
|
+
microLamports: 300_000,
|
|
513
|
+
}),
|
|
514
|
+
])
|
|
515
|
+
.accounts(accounts)
|
|
516
|
+
.rpc();
|
|
517
|
+
}
|
|
312
518
|
}
|
|
313
519
|
|
|
314
520
|
/**
|
|
@@ -344,7 +550,7 @@ export class VaultClient {
|
|
|
344
550
|
/**
|
|
345
551
|
* Updates the vault margin trading status.
|
|
346
552
|
* @param vault vault address to update
|
|
347
|
-
* @param
|
|
553
|
+
* @param enabled whether to enable margin trading
|
|
348
554
|
* @returns
|
|
349
555
|
*/
|
|
350
556
|
public async updateMarginTradingEnabled(
|
|
@@ -388,6 +594,14 @@ export class VaultClient {
|
|
|
388
594
|
userAccounts: [user.getUserAccount()],
|
|
389
595
|
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
390
596
|
});
|
|
597
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
598
|
+
const vaultProtocol = this.getVaultProtocolAddress(vault);
|
|
599
|
+
remainingAccounts.push({
|
|
600
|
+
pubkey: vaultProtocol,
|
|
601
|
+
isSigner: false,
|
|
602
|
+
isWritable: true,
|
|
603
|
+
});
|
|
604
|
+
}
|
|
391
605
|
|
|
392
606
|
return await this.program.methods
|
|
393
607
|
.managerDeposit(amount)
|
|
@@ -435,6 +649,14 @@ export class VaultClient {
|
|
|
435
649
|
userAccounts: [user.getUserAccount()],
|
|
436
650
|
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
437
651
|
});
|
|
652
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
653
|
+
const vaultProtocol = this.getVaultProtocolAddress(vault);
|
|
654
|
+
remainingAccounts.push({
|
|
655
|
+
pubkey: vaultProtocol,
|
|
656
|
+
isSigner: false,
|
|
657
|
+
isWritable: true,
|
|
658
|
+
});
|
|
659
|
+
}
|
|
438
660
|
|
|
439
661
|
const userStatsKey = getUserStatsAccountPublicKey(
|
|
440
662
|
this.driftClient.program.programId,
|
|
@@ -499,6 +721,14 @@ export class VaultClient {
|
|
|
499
721
|
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
500
722
|
userAccounts: [user.getUserAccount()],
|
|
501
723
|
});
|
|
724
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
725
|
+
const vaultProtocol = this.getVaultProtocolAddress(vault);
|
|
726
|
+
remainingAccounts.push({
|
|
727
|
+
pubkey: vaultProtocol,
|
|
728
|
+
isSigner: false,
|
|
729
|
+
isWritable: true,
|
|
730
|
+
});
|
|
731
|
+
}
|
|
502
732
|
|
|
503
733
|
if (this.cliMode) {
|
|
504
734
|
return await this.program.methods
|
|
@@ -535,6 +765,14 @@ export class VaultClient {
|
|
|
535
765
|
userAccounts: [user.getUserAccount()],
|
|
536
766
|
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
537
767
|
});
|
|
768
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
769
|
+
const vaultProtocol = this.getVaultProtocolAddress(vault);
|
|
770
|
+
remainingAccounts.push({
|
|
771
|
+
pubkey: vaultProtocol,
|
|
772
|
+
isSigner: false,
|
|
773
|
+
isWritable: true,
|
|
774
|
+
});
|
|
775
|
+
}
|
|
538
776
|
|
|
539
777
|
const spotMarket = this.driftClient.getSpotMarketAccount(
|
|
540
778
|
vaultAccount.spotMarketIndex
|
|
@@ -728,6 +966,14 @@ export class VaultClient {
|
|
|
728
966
|
userAccounts: [user.getUserAccount()],
|
|
729
967
|
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
730
968
|
});
|
|
969
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
970
|
+
const vaultProtocol = this.getVaultProtocolAddress(vaultPubKey);
|
|
971
|
+
remainingAccounts.push({
|
|
972
|
+
pubkey: vaultProtocol,
|
|
973
|
+
isSigner: false,
|
|
974
|
+
isWritable: true,
|
|
975
|
+
});
|
|
976
|
+
}
|
|
731
977
|
|
|
732
978
|
const userStatsKey = getUserStatsAccountPublicKey(
|
|
733
979
|
this.driftClient.program.programId,
|
|
@@ -769,6 +1015,15 @@ export class VaultClient {
|
|
|
769
1015
|
};
|
|
770
1016
|
}
|
|
771
1017
|
|
|
1018
|
+
/**
|
|
1019
|
+
* Creates a transaction to deposit funds into the specified vault.
|
|
1020
|
+
* Uses the associated token account of the vault depositor authority and spot market mint,
|
|
1021
|
+
* and assumes it exists before calling this function.
|
|
1022
|
+
* @param vaultDepositor
|
|
1023
|
+
* @param amount
|
|
1024
|
+
* @param initVaultDepositor If true, will initialize the vault depositor account
|
|
1025
|
+
* @returns transaction
|
|
1026
|
+
*/
|
|
772
1027
|
public async createDepositTx(
|
|
773
1028
|
vaultDepositor: PublicKey,
|
|
774
1029
|
amount: BN,
|
|
@@ -781,23 +1036,28 @@ export class VaultClient {
|
|
|
781
1036
|
const { vaultAccount, accounts, remainingAccounts } =
|
|
782
1037
|
await this.prepDepositTx(vaultDepositor, amount, initVaultDepositor);
|
|
783
1038
|
|
|
784
|
-
const
|
|
785
|
-
accounts: {
|
|
786
|
-
authority: this.driftClient.wallet.publicKey,
|
|
787
|
-
...accounts,
|
|
788
|
-
},
|
|
789
|
-
remainingAccounts,
|
|
790
|
-
});
|
|
1039
|
+
const ixs: TransactionInstruction[] = [];
|
|
791
1040
|
|
|
792
1041
|
if (initVaultDepositor) {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
1042
|
+
ixs.push(
|
|
1043
|
+
this.createInitVaultDepositorIx(
|
|
1044
|
+
vaultAccount.pubkey,
|
|
1045
|
+
initVaultDepositor.authority
|
|
1046
|
+
)
|
|
796
1047
|
);
|
|
797
|
-
return await this.createTxn([initIx, depositIx], txParams);
|
|
798
|
-
} else {
|
|
799
|
-
return await this.createTxn([depositIx], txParams);
|
|
800
1048
|
}
|
|
1049
|
+
|
|
1050
|
+
const depositIx = await this.program.methods
|
|
1051
|
+
.deposit(amount)
|
|
1052
|
+
.accounts({
|
|
1053
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1054
|
+
...accounts,
|
|
1055
|
+
})
|
|
1056
|
+
.remainingAccounts(remainingAccounts)
|
|
1057
|
+
.instruction();
|
|
1058
|
+
ixs.push(depositIx);
|
|
1059
|
+
|
|
1060
|
+
return await this.createTxn(ixs, txParams);
|
|
801
1061
|
}
|
|
802
1062
|
|
|
803
1063
|
/**
|
|
@@ -805,6 +1065,7 @@ export class VaultClient {
|
|
|
805
1065
|
* @param vaultDepositor
|
|
806
1066
|
* @param amount
|
|
807
1067
|
* @param initVaultDepositor If true, will initialize the vault depositor account
|
|
1068
|
+
* @param txParams
|
|
808
1069
|
* @returns
|
|
809
1070
|
*/
|
|
810
1071
|
public async deposit(
|
|
@@ -859,6 +1120,16 @@ export class VaultClient {
|
|
|
859
1120
|
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
860
1121
|
userAccounts: [user.getUserAccount()],
|
|
861
1122
|
});
|
|
1123
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
1124
|
+
const vaultProtocol = this.getVaultProtocolAddress(
|
|
1125
|
+
vaultDepositorAccount.vault
|
|
1126
|
+
);
|
|
1127
|
+
remainingAccounts.push({
|
|
1128
|
+
pubkey: vaultProtocol,
|
|
1129
|
+
isSigner: false,
|
|
1130
|
+
isWritable: true,
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
862
1133
|
|
|
863
1134
|
const userStatsKey = getUserStatsAccountPublicKey(
|
|
864
1135
|
this.driftClient.program.programId,
|
|
@@ -915,6 +1186,16 @@ export class VaultClient {
|
|
|
915
1186
|
userAccounts: [user.getUserAccount()],
|
|
916
1187
|
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
917
1188
|
});
|
|
1189
|
+
const vaultProtocol = this.getVaultProtocolAddress(
|
|
1190
|
+
vaultDepositorAccount.vault
|
|
1191
|
+
);
|
|
1192
|
+
if (!vaultProtocol.equals(SystemProgram.programId)) {
|
|
1193
|
+
remainingAccounts.push({
|
|
1194
|
+
pubkey: vaultProtocol,
|
|
1195
|
+
isSigner: false,
|
|
1196
|
+
isWritable: true,
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
918
1199
|
|
|
919
1200
|
const userStatsKey = getUserStatsAccountPublicKey(
|
|
920
1201
|
this.driftClient.program.programId,
|
|
@@ -966,20 +1247,30 @@ export class VaultClient {
|
|
|
966
1247
|
};
|
|
967
1248
|
|
|
968
1249
|
if (this.cliMode) {
|
|
969
|
-
|
|
970
|
-
.
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1250
|
+
if (createAtaIx) {
|
|
1251
|
+
return await this.program.methods
|
|
1252
|
+
.withdraw()
|
|
1253
|
+
.accounts(accounts)
|
|
1254
|
+
.remainingAccounts(remainingAccounts)
|
|
1255
|
+
.preInstructions([createAtaIx])
|
|
1256
|
+
.rpc();
|
|
1257
|
+
} else {
|
|
1258
|
+
return await this.program.methods
|
|
1259
|
+
.withdraw()
|
|
1260
|
+
.accounts(accounts)
|
|
1261
|
+
.remainingAccounts(remainingAccounts)
|
|
1262
|
+
.rpc();
|
|
1263
|
+
}
|
|
974
1264
|
} else {
|
|
975
1265
|
const ixs = [
|
|
976
|
-
this.program.
|
|
977
|
-
|
|
1266
|
+
await this.program.methods
|
|
1267
|
+
.withdraw()
|
|
1268
|
+
.accounts({
|
|
978
1269
|
authority: this.driftClient.wallet.publicKey,
|
|
979
1270
|
...accounts,
|
|
980
|
-
}
|
|
981
|
-
remainingAccounts
|
|
982
|
-
|
|
1271
|
+
})
|
|
1272
|
+
.remainingAccounts(remainingAccounts)
|
|
1273
|
+
.instruction(),
|
|
983
1274
|
];
|
|
984
1275
|
if (createAtaIx) {
|
|
985
1276
|
ixs.unshift(createAtaIx);
|
|
@@ -1006,6 +1297,16 @@ export class VaultClient {
|
|
|
1006
1297
|
userAccounts: [user.getUserAccount()],
|
|
1007
1298
|
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
1008
1299
|
});
|
|
1300
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
1301
|
+
const vaultProtocol = this.getVaultProtocolAddress(
|
|
1302
|
+
vaultDepositorAccount.vault
|
|
1303
|
+
);
|
|
1304
|
+
remainingAccounts.push({
|
|
1305
|
+
pubkey: vaultProtocol,
|
|
1306
|
+
isSigner: false,
|
|
1307
|
+
isWritable: true,
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1009
1310
|
|
|
1010
1311
|
const userStatsKey = getUserStatsAccountPublicKey(
|
|
1011
1312
|
this.driftClient.program.programId,
|
|
@@ -1096,6 +1397,16 @@ export class VaultClient {
|
|
|
1096
1397
|
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
1097
1398
|
userAccounts: [user.getUserAccount()],
|
|
1098
1399
|
});
|
|
1400
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
1401
|
+
const vaultProtocol = this.getVaultProtocolAddress(
|
|
1402
|
+
vaultDepositorAccount.vault
|
|
1403
|
+
);
|
|
1404
|
+
remainingAccounts.push({
|
|
1405
|
+
pubkey: vaultProtocol,
|
|
1406
|
+
isSigner: false,
|
|
1407
|
+
isWritable: true,
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1099
1410
|
|
|
1100
1411
|
if (this.cliMode) {
|
|
1101
1412
|
return await this.program.methods
|
|
@@ -1326,4 +1637,191 @@ export class VaultClient {
|
|
|
1326
1637
|
})
|
|
1327
1638
|
.rpc();
|
|
1328
1639
|
}
|
|
1640
|
+
|
|
1641
|
+
public async protocolRequestWithdraw(
|
|
1642
|
+
vault: PublicKey,
|
|
1643
|
+
amount: BN,
|
|
1644
|
+
withdrawUnit: WithdrawUnit
|
|
1645
|
+
): Promise<TransactionSignature> {
|
|
1646
|
+
// @ts-ignore
|
|
1647
|
+
const vaultAccount = (await this.program.account.vault.fetch(
|
|
1648
|
+
vault
|
|
1649
|
+
)) as Vault;
|
|
1650
|
+
const vp = this.getVaultProtocolAddress(vault);
|
|
1651
|
+
const vpAccount = (await this.program.account.vaultProtocol.fetch(
|
|
1652
|
+
vp
|
|
1653
|
+
)) as VaultProtocol;
|
|
1654
|
+
|
|
1655
|
+
if (!this.driftClient.wallet.publicKey.equals(vpAccount.protocol)) {
|
|
1656
|
+
throw new Error(`Only the protocol of the vault can request a withdraw.`);
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1660
|
+
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
1661
|
+
userAccounts: [user.getUserAccount()],
|
|
1662
|
+
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
1663
|
+
});
|
|
1664
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
1665
|
+
const vaultProtocol = this.getVaultProtocolAddress(vault);
|
|
1666
|
+
remainingAccounts.push({
|
|
1667
|
+
pubkey: vaultProtocol,
|
|
1668
|
+
isSigner: false,
|
|
1669
|
+
isWritable: true,
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
const userStatsKey = getUserStatsAccountPublicKey(
|
|
1674
|
+
this.driftClient.program.programId,
|
|
1675
|
+
vault
|
|
1676
|
+
);
|
|
1677
|
+
|
|
1678
|
+
const driftStateKey = await this.driftClient.getStatePublicKey();
|
|
1679
|
+
|
|
1680
|
+
const accounts = {
|
|
1681
|
+
vault,
|
|
1682
|
+
driftUserStats: userStatsKey,
|
|
1683
|
+
driftUser: vaultAccount.user,
|
|
1684
|
+
driftState: driftStateKey,
|
|
1685
|
+
};
|
|
1686
|
+
|
|
1687
|
+
if (this.cliMode) {
|
|
1688
|
+
return await this.program.methods
|
|
1689
|
+
// @ts-ignore, 0.29.0 anchor issues..
|
|
1690
|
+
.managerRequestWithdraw(amount, withdrawUnit)
|
|
1691
|
+
.accounts(accounts)
|
|
1692
|
+
.remainingAccounts(remainingAccounts)
|
|
1693
|
+
.rpc();
|
|
1694
|
+
} else {
|
|
1695
|
+
const requestWithdrawIx = this.program.instruction.managerRequestWithdraw(
|
|
1696
|
+
// @ts-ignore
|
|
1697
|
+
amount,
|
|
1698
|
+
withdrawUnit,
|
|
1699
|
+
{
|
|
1700
|
+
accounts: {
|
|
1701
|
+
manager: this.driftClient.wallet.publicKey,
|
|
1702
|
+
...accounts,
|
|
1703
|
+
},
|
|
1704
|
+
remainingAccounts,
|
|
1705
|
+
}
|
|
1706
|
+
);
|
|
1707
|
+
|
|
1708
|
+
return await this.createAndSendTxn([requestWithdrawIx]);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
public async protocolCancelWithdrawRequest(
|
|
1713
|
+
vault: PublicKey
|
|
1714
|
+
): Promise<TransactionSignature> {
|
|
1715
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1716
|
+
|
|
1717
|
+
const userStatsKey = getUserStatsAccountPublicKey(
|
|
1718
|
+
this.driftClient.program.programId,
|
|
1719
|
+
vault
|
|
1720
|
+
);
|
|
1721
|
+
|
|
1722
|
+
const driftStateKey = await this.driftClient.getStatePublicKey();
|
|
1723
|
+
|
|
1724
|
+
const accounts = {
|
|
1725
|
+
manager: this.driftClient.wallet.publicKey,
|
|
1726
|
+
vault,
|
|
1727
|
+
driftUserStats: userStatsKey,
|
|
1728
|
+
driftUser: vaultAccount.user,
|
|
1729
|
+
driftState: driftStateKey,
|
|
1730
|
+
};
|
|
1731
|
+
|
|
1732
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1733
|
+
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
1734
|
+
userAccounts: [user.getUserAccount()],
|
|
1735
|
+
});
|
|
1736
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
1737
|
+
const vaultProtocol = this.getVaultProtocolAddress(vault);
|
|
1738
|
+
remainingAccounts.push({
|
|
1739
|
+
pubkey: vaultProtocol,
|
|
1740
|
+
isSigner: false,
|
|
1741
|
+
isWritable: true,
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
if (this.cliMode) {
|
|
1746
|
+
return await this.program.methods
|
|
1747
|
+
.mangerCancelWithdrawRequest()
|
|
1748
|
+
.accounts(accounts)
|
|
1749
|
+
.remainingAccounts(remainingAccounts)
|
|
1750
|
+
.rpc();
|
|
1751
|
+
} else {
|
|
1752
|
+
const cancelRequestWithdrawIx =
|
|
1753
|
+
this.program.instruction.mangerCancelWithdrawRequest({
|
|
1754
|
+
accounts: {
|
|
1755
|
+
...accounts,
|
|
1756
|
+
manager: this.driftClient.wallet.publicKey,
|
|
1757
|
+
},
|
|
1758
|
+
remainingAccounts,
|
|
1759
|
+
});
|
|
1760
|
+
|
|
1761
|
+
return await this.createAndSendTxn([cancelRequestWithdrawIx]);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
public async protocolWithdraw(
|
|
1766
|
+
vault: PublicKey
|
|
1767
|
+
): Promise<TransactionSignature> {
|
|
1768
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1769
|
+
|
|
1770
|
+
if (!this.driftClient.wallet.publicKey.equals(vaultAccount.manager)) {
|
|
1771
|
+
throw new Error(`Only the manager of the vault can request a withdraw.`);
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1775
|
+
|
|
1776
|
+
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
1777
|
+
userAccounts: [user.getUserAccount()],
|
|
1778
|
+
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
1779
|
+
});
|
|
1780
|
+
if (!vaultAccount.vaultProtocol.equals(SystemProgram.programId)) {
|
|
1781
|
+
const vaultProtocol = this.getVaultProtocolAddress(vault);
|
|
1782
|
+
remainingAccounts.push({
|
|
1783
|
+
pubkey: vaultProtocol,
|
|
1784
|
+
isSigner: false,
|
|
1785
|
+
isWritable: true,
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(
|
|
1790
|
+
vaultAccount.spotMarketIndex
|
|
1791
|
+
);
|
|
1792
|
+
if (!spotMarket) {
|
|
1793
|
+
throw new Error(
|
|
1794
|
+
`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
const ix = this.program.instruction.managerWithdraw({
|
|
1799
|
+
accounts: {
|
|
1800
|
+
vault,
|
|
1801
|
+
manager: this.driftClient.wallet.publicKey,
|
|
1802
|
+
vaultTokenAccount: vaultAccount.tokenAccount,
|
|
1803
|
+
driftUser: await getUserAccountPublicKey(
|
|
1804
|
+
this.driftClient.program.programId,
|
|
1805
|
+
vault
|
|
1806
|
+
),
|
|
1807
|
+
driftProgram: this.driftClient.program.programId,
|
|
1808
|
+
driftUserStats: getUserStatsAccountPublicKey(
|
|
1809
|
+
this.driftClient.program.programId,
|
|
1810
|
+
vault
|
|
1811
|
+
),
|
|
1812
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
1813
|
+
driftSpotMarketVault: spotMarket.vault,
|
|
1814
|
+
userTokenAccount: getAssociatedTokenAddressSync(
|
|
1815
|
+
spotMarket.mint,
|
|
1816
|
+
this.driftClient.wallet.publicKey
|
|
1817
|
+
),
|
|
1818
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
1819
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1820
|
+
},
|
|
1821
|
+
remainingAccounts,
|
|
1822
|
+
});
|
|
1823
|
+
return this.createAndSendTxn([ix], {
|
|
1824
|
+
cuLimit: 1_000_000,
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1329
1827
|
}
|