@drift-labs/vaults-sdk 0.8.29 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli/cli.ts CHANGED
@@ -22,6 +22,10 @@ import {
22
22
  managerUpdateMarginTradingEnabled,
23
23
  decodeLogs,
24
24
  vaultInvariantChecks,
25
+ managerBorrow,
26
+ managerRepay,
27
+ managerUpdateBorrow,
28
+ adminUpdateVaultClass,
25
29
  } from "./commands";
26
30
 
27
31
  import { Command, Option } from 'commander';
@@ -80,7 +84,7 @@ program
80
84
  .command("manager-deposit")
81
85
  .description("Make a deposit to your vault")
82
86
  .addOption(new Option("--vault-address <address>", "Address of the vault to deposit to").makeOptionMandatory(true))
83
- .addOption(new Option("--amount <amount>", "Amount to deposit (human format, 5 for 5 USDC)").makeOptionMandatory(true))
87
+ .addOption(new Option("--amount <amount>", "Amount to deposit (in deposit precision, 5 for 5 USDC)").makeOptionMandatory(true))
84
88
  .addOption(new Option("--dump-transaction-message", "Dump the transaction message to the console").makeOptionMandatory(false))
85
89
  .action((opts) => managerDeposit(program, opts));
86
90
  program
@@ -88,7 +92,7 @@ program
88
92
  .description("Make a withdraw request from your vault")
89
93
  .addOption(new Option("--vault-address <address>", "Address of the vault to withdraw from").makeOptionMandatory(true))
90
94
  .addOption(new Option("--shares <shares>", "Amount of shares to withdraw (raw precision, as expected by contract)").makeOptionMandatory(false))
91
- .addOption(new Option("--amount <amount>", "Amount of spot asset to withdraw (human format, 5 for 5 USDC)").makeOptionMandatory(false))
95
+ .addOption(new Option("--amount <amount>", "Amount of spot asset to withdraw (in deposit precision, 5 for 5 USDC)").makeOptionMandatory(false))
92
96
  .addOption(new Option("--dump-transaction-message", "Dump the transaction message to the console").makeOptionMandatory(false))
93
97
  .action((opts) => managerRequestWithdraw(program, opts));
94
98
  program
@@ -169,7 +173,7 @@ program
169
173
  .addOption(new Option("--vault-depositor-address <vaultDepositorAddress>", "VaultDepositor address").makeOptionMandatory(false))
170
174
  .addOption(new Option("--vault-address <address>", "Address of the vault to deposit into").makeOptionMandatory(false))
171
175
  .addOption(new Option("--deposit-authority <vaultDepositorAuthority>", "VaultDepositor authority address").makeOptionMandatory(false))
172
- .addOption(new Option("--amount <amount>", "Amount to deposit (human format, 5 for 5 USDC)").makeOptionMandatory(true))
176
+ .addOption(new Option("--amount <amount>", "Amount to deposit (in deposit precision, 5 for 5 USDC)").makeOptionMandatory(true))
173
177
  .action((opts) => deposit(program, opts));
174
178
  program
175
179
  .command("request-withdraw")
@@ -244,6 +248,43 @@ program
244
248
  .addOption(new Option("--dump-transaction-message", "Dump the transaction message to the console").makeOptionMandatory(false))
245
249
  .action((opts) => managerUpdateFuelDistributionMode(program, opts));
246
250
 
251
+ program
252
+ .command("manager-borrow")
253
+ .description("Manager borrow from a spot market")
254
+ .addOption(new Option("--vault-address <address>", "Address of the vault").makeOptionMandatory(true))
255
+ .addOption(new Option("--borrow-spot-market-index <index>", "Spot market index to borrow from").makeOptionMandatory(true))
256
+ .addOption(new Option("--borrow-amount <amount>", "Amount to borrow (in borrow precision, 5 for 5 USDC)").makeOptionMandatory(true))
257
+ .addOption(new Option("--manager-token-account <address>", "Manager token account address (optional, ATA will be used if not provided)").makeOptionMandatory(false))
258
+ .addOption(new Option("--dump-transaction-message", "Dump the transaction message to the console").makeOptionMandatory(false))
259
+ .action((opts) => managerBorrow(program, opts));
260
+
261
+ program
262
+ .command("manager-repay")
263
+ .description("Manager repay to a spot market")
264
+ .addOption(new Option("--vault-address <address>", "Address of the vault").makeOptionMandatory(true))
265
+ .addOption(new Option("--repay-spot-market-index <index>", "Spot market index to repay to").makeOptionMandatory(true))
266
+ .addOption(new Option("--repay-amount <amount>", "Amount to repay (in repay market precision, 5 for 5 USDC)").makeOptionMandatory(true))
267
+ .addOption(new Option("--repay-value <value>", "Value (in deposit precision, 5 for 5 USDC) of the repay (optional, if not provided will assume repaying the full outstanding amount)").makeOptionMandatory(false))
268
+ .addOption(new Option("--manager-token-account <address>", "Manager token account address to receive repay tokens from (optional, ATA will be used if not provided)").makeOptionMandatory(false))
269
+ .addOption(new Option("--dump-transaction-message", "Dump the transaction message to the console").makeOptionMandatory(false))
270
+ .action((opts) => managerRepay(program, opts));
271
+
272
+ program
273
+ .command("manager-update-borrow")
274
+ .description("Update the manager borrow value for a vault")
275
+ .addOption(new Option("--vault-address <address>", "Address of the vault").makeOptionMandatory(true))
276
+ .addOption(new Option("--new-borrow-value <value>", "New borrow value (in deposit precision, 5 for 5 USDC)").makeOptionMandatory(true))
277
+ .addOption(new Option("--dump-transaction-message", "Dump the transaction message to the console").makeOptionMandatory(false))
278
+ .action((opts) => managerUpdateBorrow(program, opts));
279
+
280
+ program
281
+ .command("admin-update-vault-class")
282
+ .description("Admin update the vault class")
283
+ .addOption(new Option("--vault-address <address>", "Address of the vault").makeOptionMandatory(true))
284
+ .addOption(new Option("--vault-class <class>", "New vault class (trusted)").makeOptionMandatory(true))
285
+ .addOption(new Option("--dump-transaction-message", "Dump the transaction message to the console").makeOptionMandatory(false))
286
+ .action((opts) => adminUpdateVaultClass(program, opts));
287
+
247
288
  program.parseAsync().then(() => {
248
289
  process.exit(0);
249
290
  });
@@ -0,0 +1,49 @@
1
+ import { Command, OptionValues } from "commander";
2
+ import { PublicKey } from "@solana/web3.js";
3
+ import { VaultClass } from "../../src";
4
+ import { dumpTransactionMessage, getCommandContext } from "../utils";
5
+
6
+ export async function adminUpdateVaultClass(program: Command, cmdOpts: OptionValues): Promise<void> {
7
+ const { vaultAddress, vaultClass, dumpTransactionMessage: dumpTx } = cmdOpts;
8
+
9
+ const {
10
+ driftClient,
11
+ driftVault
12
+ } = await getCommandContext(program, true);
13
+
14
+ if (!vaultAddress) {
15
+ throw new Error("Must provide vault address with --vault-address");
16
+ }
17
+
18
+ if (!vaultClass) {
19
+ throw new Error("Must provide vault class with --vault-class");
20
+ }
21
+
22
+ const vault = new PublicKey(vaultAddress);
23
+
24
+ // Parse vault class from string input
25
+ let newVaultClass: VaultClass;
26
+ switch (vaultClass.toLowerCase()) {
27
+ case 'trusted':
28
+ newVaultClass = VaultClass.TRUSTED;
29
+ break;
30
+ default:
31
+ throw new Error(`Invalid vault class: ${vaultClass}. Must be 'trusted'`);
32
+ }
33
+
34
+ try {
35
+ if (dumpTx) {
36
+ const ix = await driftVault.getAdminUpdateVaultClassIx(vault, newVaultClass);
37
+ console.log("Transaction Instruction:");
38
+ console.log(dumpTransactionMessage(driftClient.wallet.publicKey, [ix]));
39
+ return;
40
+ }
41
+
42
+ const txSig = await driftVault.adminUpdateVaultClass(vault, newVaultClass);
43
+ console.log(`Admin update vault class transaction signature: ${txSig}`);
44
+ console.log(`Transaction: https://solana.fm/tx/${txSig}${driftClient.env === "devnet" ? "?cluster=devnet-solana" : ""}`);
45
+ } catch (error) {
46
+ console.error("Error updating vault class:", error);
47
+ throw error;
48
+ }
49
+ }
@@ -21,4 +21,8 @@ export * from './decodeLogs';
21
21
  export * from './vaultInvariantChecks';
22
22
  export * from './adminInitFeeUpdate';
23
23
  export * from './adminDeleteFeeUpdate';
24
+ export * from './managerBorrow';
25
+ export * from './managerRepay';
26
+ export * from './managerUpdateBorrow';
27
+ export * from './adminUpdateVaultClass';
24
28
 
@@ -6,6 +6,7 @@ import {
6
6
  convertToNumber,
7
7
  decodeName,
8
8
  getSignedMsgUserAccountPublicKey,
9
+ getUserAccountPublicKey,
9
10
  } from "@drift-labs/sdk";
10
11
  import {
11
12
  OptionValues,
@@ -122,6 +123,7 @@ export const initVault = async (program: Command, cmdOpts: OptionValues) => {
122
123
  }
123
124
 
124
125
  const vaultAddress = getVaultAddressSync(VAULT_PROGRAM_ID, vaultNameBytes);
126
+ const vaultDriftUser = await getUserAccountPublicKey(driftClient.program.programId, vaultAddress, 0);
125
127
 
126
128
  const ixs = [
127
129
  await driftVault.getInitializeVaultIx({
@@ -136,7 +138,7 @@ export const initVault = async (program: Command, cmdOpts: OptionValues) => {
136
138
  minDepositAmount: minDepositAmountBN,
137
139
  manager: cmdOpts.manager,
138
140
  }),
139
- await driftVault.getUpdateDelegateIx(vaultAddress, delegate)
141
+ await driftVault.getUpdateDelegateIx(vaultAddress, delegate, vaultDriftUser, cmdOpts.manager)
140
142
  ];
141
143
 
142
144
  const signedOrdersAccountAddress = getSignedMsgUserAccountPublicKey(
@@ -0,0 +1,53 @@
1
+ import { Command, OptionValues } from "commander";
2
+ import { PublicKey } from "@solana/web3.js";
3
+ import { BN, TEN } from "@drift-labs/sdk";
4
+ import { dumpTransactionMessage, getCommandContext } from "../utils";
5
+
6
+ export async function managerBorrow(program: Command, cmdOpts: OptionValues): Promise<void> {
7
+ const { vaultAddress, borrowSpotMarketIndex, borrowAmount, managerTokenAccount, dumpTransactionMessage: dumpTx } = cmdOpts;
8
+
9
+ const {
10
+ driftClient,
11
+ driftVault
12
+ } = await getCommandContext(program, true);
13
+
14
+ if (!vaultAddress) {
15
+ throw new Error("Must provide vault address with --vault-address");
16
+ }
17
+
18
+ if (!borrowSpotMarketIndex) {
19
+ throw new Error("Must provide borrow spot market index with --borrow-spot-market-index");
20
+ }
21
+
22
+ if (!borrowAmount) {
23
+ throw new Error("Must provide borrow amount with --borrow-amount");
24
+ }
25
+
26
+ const vault = new PublicKey(vaultAddress);
27
+ const borrowIndex = parseInt(borrowSpotMarketIndex);
28
+
29
+ const borrowSpotMarket = driftClient.getSpotMarketAccount(borrowIndex);
30
+ if (!borrowSpotMarket) {
31
+ throw new Error("No borrow spot market found");
32
+ }
33
+ const borrowPrecision = TEN.pow(new BN(borrowSpotMarket.decimals));
34
+ const borrowBN = new BN(borrowAmount * borrowPrecision.toNumber());
35
+
36
+ const managerTokenAccountPubkey = managerTokenAccount ? new PublicKey(managerTokenAccount) : undefined;
37
+
38
+ try {
39
+ if (dumpTx) {
40
+ const ixs = await driftVault.getManagerBorrowIx(vault, borrowIndex, borrowBN, managerTokenAccountPubkey);
41
+ console.log("Transaction Instructions:");
42
+ console.log(dumpTransactionMessage(driftClient.wallet.publicKey, ixs));
43
+ return;
44
+ }
45
+
46
+ const txSig = await driftVault.managerBorrow(vault, borrowIndex, borrowBN, managerTokenAccountPubkey);
47
+ console.log(`Manager borrow transaction signature: ${txSig}`);
48
+ console.log(`Transaction: https://solana.fm/tx/${txSig}${driftClient.env === "devnet" ? "?cluster=devnet-solana" : ""}`);
49
+ } catch (error) {
50
+ console.error("Error borrowing:", error);
51
+ throw error;
52
+ }
53
+ }
@@ -0,0 +1,63 @@
1
+ import { Command, OptionValues } from "commander";
2
+ import { PublicKey } from "@solana/web3.js";
3
+ import { BN, TEN } from "@drift-labs/sdk";
4
+ import { dumpTransactionMessage, getCommandContext } from "../utils";
5
+
6
+ export async function managerRepay(program: Command, cmdOpts: OptionValues): Promise<void> {
7
+ const { vaultAddress, repaySpotMarketIndex, repayAmount, repayValue, managerTokenAccount, dumpTransactionMessage: dumpTx } = cmdOpts;
8
+
9
+ const {
10
+ driftClient,
11
+ driftVault
12
+ } = await getCommandContext(program, true);
13
+
14
+ if (!vaultAddress) {
15
+ throw new Error("Must provide vault address with --vault-address");
16
+ }
17
+
18
+ if (!repaySpotMarketIndex) {
19
+ throw new Error("Must provide repay spot market index with --repay-spot-market-index");
20
+ }
21
+
22
+ if (!repayAmount) {
23
+ throw new Error("Must provide repay amount with --repay-amount");
24
+ }
25
+
26
+ const vault = new PublicKey(vaultAddress);
27
+ const repayIndex = parseInt(repaySpotMarketIndex);
28
+
29
+ const repaySpotMarket = driftClient.getSpotMarketAccount(repayIndex);
30
+ if (!repaySpotMarket) {
31
+ throw new Error("No repay spot market found");
32
+ }
33
+
34
+ const vaultAccount = await driftVault.program.account.vault.fetch(vault);
35
+ const depositSpotMarket = driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
36
+ if (!depositSpotMarket) {
37
+ throw new Error("No deposit spot market found");
38
+ }
39
+ const depositPrecision = TEN.pow(new BN(depositSpotMarket.decimals));
40
+
41
+ const repayPrecision = TEN.pow(new BN(repaySpotMarket.decimals));
42
+ const repayBN = new BN(repayAmount * repayPrecision.toNumber());
43
+
44
+ const valueBN = repayValue ? new BN(repayValue * depositPrecision.toNumber()) : null;
45
+
46
+ const managerTokenAccountPubkey = managerTokenAccount ? new PublicKey(managerTokenAccount) : undefined;
47
+
48
+ try {
49
+ if (dumpTx) {
50
+ const ixs = await driftVault.getManagerRepayIxs(vault, repayIndex, repayBN, valueBN, managerTokenAccountPubkey);
51
+ console.log("Transaction Instructions:");
52
+ console.log(dumpTransactionMessage(driftClient.wallet.publicKey, ixs));
53
+ return;
54
+ }
55
+
56
+ const txSig = await driftVault.managerRepay(vault, repayIndex, repayBN, valueBN, managerTokenAccountPubkey);
57
+ console.log(`Manager repay transaction signature: ${txSig}`);
58
+ console.log(`Transaction: https://solana.fm/tx/${txSig}${driftClient.env === "devnet" ? "?cluster=devnet-solana" : ""}`);
59
+ } catch (error) {
60
+ console.error("Error repaying:", error);
61
+ throw error;
62
+ }
63
+ }
@@ -0,0 +1,46 @@
1
+ import { Command, OptionValues } from "commander";
2
+ import { PublicKey } from "@solana/web3.js";
3
+ import { BN, TEN } from "@drift-labs/sdk";
4
+ import { dumpTransactionMessage, getCommandContext } from "../utils";
5
+
6
+ export async function managerUpdateBorrow(program: Command, cmdOpts: OptionValues): Promise<void> {
7
+ const { vaultAddress, newBorrowValue, dumpTransactionMessage: dumpTx } = cmdOpts;
8
+
9
+ const {
10
+ driftClient,
11
+ driftVault
12
+ } = await getCommandContext(program, true);
13
+
14
+ if (!vaultAddress) {
15
+ throw new Error("Must provide vault address with --vault-address");
16
+ }
17
+
18
+ if (!newBorrowValue) {
19
+ throw new Error("Must provide new borrow value with --new-borrow-value");
20
+ }
21
+
22
+ const vault = new PublicKey(vaultAddress);
23
+ const vaultAccount = await driftVault.program.account.vault.fetch(vault);
24
+ const depositSpotMarket = driftClient.getSpotMarketAccount(vaultAccount.spotMarketIndex);
25
+ if (!depositSpotMarket) {
26
+ throw new Error("No deposit spot market found");
27
+ }
28
+ const depositPrecision = TEN.pow(new BN(depositSpotMarket.decimals));
29
+ const borrowValue = new BN(newBorrowValue * depositPrecision.toNumber());
30
+
31
+ try {
32
+ if (dumpTx) {
33
+ const ix = await driftVault.getManagerUpdateBorrowIx(vault, borrowValue);
34
+ console.log("Transaction Instruction:");
35
+ console.log(dumpTransactionMessage(driftClient.wallet.publicKey, [ix]));
36
+ return;
37
+ }
38
+
39
+ const txSig = await driftVault.managerUpdateBorrow(vault, borrowValue);
40
+ console.log(`Manager update borrow transaction signature: ${txSig}`);
41
+ console.log(`Transaction: https://solana.fm/tx/${txSig}${driftClient.env === "devnet" ? "?cluster=devnet-solana" : ""}`);
42
+ } catch (error) {
43
+ console.error("Error updating borrow:", error);
44
+ throw error;
45
+ }
46
+ }
@@ -32,7 +32,8 @@ export const managerUpdateVaultDelegate = async (program: Command, cmdOpts: Opti
32
32
  }
33
33
 
34
34
  if (cmdOpts.dumpTransactionMessage) {
35
- const tx = await driftVault.getUpdateDelegateIx(vaultAddress, delegate);
35
+ const vaultAccount = await driftVault.program.account.vault.fetch(vaultAddress);
36
+ const tx = await driftVault.getUpdateDelegateIx(vaultAddress, delegate, vaultAccount.user, vaultAccount.manager);
36
37
  console.log(dumpTransactionMessage(driftClient.wallet.publicKey, [tx]));
37
38
  } else {
38
39
  const tx = await driftVault.updateDelegate(vaultAddress, delegate);
package/cli/utils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { BASE_PRECISION, BN, DriftClient, DriftEnv, OraclePriceData, PRICE_PRECISION, QUOTE_PRECISION, SpotMarketAccount, TEN, User, Wallet, WhileValidTxSender, convertToNumber, getSignedTokenAmount, getTokenAmount, loadKeypair } from "@drift-labs/sdk";
2
- import { FeeUpdate, VAULT_PROGRAM_ID, Vault, VaultClient, VaultDepositor, decodeName } from "../src";
2
+ import { FeeUpdate, VAULT_PROGRAM_ID, Vault, VaultClass, VaultClient, VaultDepositor, decodeName } from "../src";
3
3
  import { Command } from "commander";
4
4
  import { Connection, Keypair, PublicKey, Transaction, TransactionInstruction } from "@solana/web3.js";
5
5
  import { AnchorProvider, Wallet as AnchorWallet } from "@coral-xyz/anchor";
@@ -18,6 +18,10 @@ export async function printVault(slot: number, driftClient: DriftClient, vault:
18
18
 
19
19
  console.log(`slot: ${slot}`);
20
20
  console.log(`vault: ${decodeName(vault.name)}`);
21
+ console.log(`vaultClass: ${vault.vaultClass}`);
22
+ if (vault.vaultClass === VaultClass.TRUSTED) {
23
+ console.log(` managerBorrowedValue: ${convertToNumber(vault.managerBorrowedValue, spotPrecision)} ${spotSymbol}`);
24
+ }
21
25
  console.log(`pubkey: ${vault.pubkey.toBase58()}`);
22
26
  console.log(`manager: ${vault.manager.toBase58()}`);
23
27
  console.log(`tokenAccount: ${vault.tokenAccount.toBase58()}`);
@@ -41,7 +45,7 @@ export async function printVault(slot: number, driftClient: DriftClient, vault:
41
45
  console.log(`initTs: ${vault.initTs.toString()}`);
42
46
  console.log(`netDeposits: ${convertToNumber(vault.netDeposits, spotPrecision)} ${spotSymbol} (${vault.netDeposits.toString()})`);
43
47
  console.log(`totalDeposits: ${convertToNumber(vault.totalDeposits, spotPrecision)} ${spotSymbol} (${vault.totalDeposits.toString()})`);
44
- console.log(`totalWithdraws: ${convertToNumber(vault.totalWithdraws, spotPrecision)} ${spotSymbol} (${vault.totalWithdraws.toString()})`);
48
+ console.log(`totalWithdraws: ${convertToNumber(vault.totalWithdraws, spotPrecision)} ${spotSymbol} (${vault.totalWithdraws.toString()})`);
45
49
  console.log(`managerNetDeposits: ${convertToNumber(vault.managerNetDeposits, spotPrecision)} ${spotSymbol} (${vault.managerNetDeposits.toString()})`);
46
50
  console.log(`managerTotalDeposits: ${convertToNumber(vault.managerTotalDeposits, spotPrecision)} ${spotSymbol} (${vault.managerTotalDeposits.toString()})`);
47
51
  console.log(`managerTotalWithdraws: ${convertToNumber(vault.managerTotalWithdraws, spotPrecision)} ${spotSymbol} (${vault.managerTotalWithdraws.toString()})`);