@velocity-exchange/vaults-sdk 0.0.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.
Files changed (65) hide show
  1. package/.env.example +3 -0
  2. package/README.md +152 -0
  3. package/cli/cli.ts +751 -0
  4. package/cli/commands/adminDeleteFeeUpdate.ts +73 -0
  5. package/cli/commands/adminInitFeeUpdate.ts +73 -0
  6. package/cli/commands/adminUpdateVaultClass.ts +49 -0
  7. package/cli/commands/applyProfitShare.ts +139 -0
  8. package/cli/commands/decodeLogs.ts +98 -0
  9. package/cli/commands/deposit.ts +98 -0
  10. package/cli/commands/deriveVaultAddress.ts +14 -0
  11. package/cli/commands/forceWithdraw.ts +56 -0
  12. package/cli/commands/forceWithdrawAll.ts +142 -0
  13. package/cli/commands/index.ts +28 -0
  14. package/cli/commands/initVault.ts +227 -0
  15. package/cli/commands/initVaultDepositor.ts +42 -0
  16. package/cli/commands/listDepositorsForVault.ts +32 -0
  17. package/cli/commands/managerApplyProfitShare.ts +32 -0
  18. package/cli/commands/managerBorrow.ts +77 -0
  19. package/cli/commands/managerCancelWithdraw.ts +30 -0
  20. package/cli/commands/managerDeposit.ts +45 -0
  21. package/cli/commands/managerRepay.ts +94 -0
  22. package/cli/commands/managerRequestWithdraw.ts +86 -0
  23. package/cli/commands/managerUpdateBorrow.ts +56 -0
  24. package/cli/commands/managerUpdateFees.ts +156 -0
  25. package/cli/commands/managerUpdateMarginTradingEnabled.ts +32 -0
  26. package/cli/commands/managerUpdatePoolId.ts +36 -0
  27. package/cli/commands/managerUpdateVault.ts +210 -0
  28. package/cli/commands/managerUpdateVaultDelegate.ts +43 -0
  29. package/cli/commands/managerUpdateVaultManager.ts +77 -0
  30. package/cli/commands/managerWithdraw.ts +30 -0
  31. package/cli/commands/requestWithdraw.ts +58 -0
  32. package/cli/commands/vaultDeposit.ts +42 -0
  33. package/cli/commands/vaultInvariantChecks.ts +407 -0
  34. package/cli/commands/vaultWithdraw.ts +42 -0
  35. package/cli/commands/viewVault.ts +50 -0
  36. package/cli/commands/viewVaultDepositor.ts +36 -0
  37. package/cli/commands/withdraw.ts +40 -0
  38. package/cli/ledgerWallet.test.ts +49 -0
  39. package/cli/ledgerWallet.ts +111 -0
  40. package/cli/utils.ts +389 -0
  41. package/package.json +48 -0
  42. package/src/accountSubscribers/index.ts +2 -0
  43. package/src/accountSubscribers/pollingVaultDepositorSubscriber.ts +69 -0
  44. package/src/accountSubscribers/pollingVaultSubscriber.ts +63 -0
  45. package/src/accountSubscribers/pollingVaultsProgramAccountSubscriber.ts +114 -0
  46. package/src/accounts/index.ts +2 -0
  47. package/src/accounts/vaultAccount.ts +255 -0
  48. package/src/accounts/vaultDepositorAccount.ts +77 -0
  49. package/src/accounts/vaultsProgramAccount.ts +38 -0
  50. package/src/addresses.ts +114 -0
  51. package/src/constants/index.ts +15 -0
  52. package/src/idl/drift_vaults.json +5698 -0
  53. package/src/index.ts +11 -0
  54. package/src/math/index.ts +2 -0
  55. package/src/math/vault.ts +71 -0
  56. package/src/math/vaultDepositor.ts +90 -0
  57. package/src/name.ts +18 -0
  58. package/src/parsers/index.ts +1 -0
  59. package/src/parsers/logParser.ts +28 -0
  60. package/src/types/drift_vaults.ts +6211 -0
  61. package/src/types/types.ts +336 -0
  62. package/src/utils.ts +74 -0
  63. package/src/vaultClient.ts +3666 -0
  64. package/tsconfig.json +24 -0
  65. package/velocity-exchange-vaults-sdk-0.0.1.tgz +0 -0
@@ -0,0 +1,142 @@
1
+ import {
2
+ ComputeBudgetProgram,
3
+ PublicKey,
4
+ SendTransactionError,
5
+ TransactionInstruction,
6
+ TransactionMessage,
7
+ VersionedTransaction,
8
+ } from '@solana/web3.js';
9
+ import { OptionValues, Command } from 'commander';
10
+ import { getCommandContext } from '../utils';
11
+ import { VaultDepositor } from '../../src';
12
+ import { BN, convertToNumber } from '@velocity-exchange/sdk';
13
+ import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
14
+
15
+ export const forceWithdrawAll = async (
16
+ program: Command,
17
+ cmdOpts: OptionValues
18
+ ) => {
19
+ let vaultAddress: PublicKey | undefined;
20
+ try {
21
+ vaultAddress = new PublicKey(cmdOpts.vaultAddress as string);
22
+ } catch (err) {
23
+ throw new Error('Must provide --vault-address');
24
+ }
25
+
26
+ if (!vaultAddress) {
27
+ throw new Error('Failed to derive vault depositor address');
28
+ }
29
+
30
+ const { driftVault, driftClient, wallet } = await getCommandContext(
31
+ program,
32
+ true
33
+ );
34
+
35
+ const vault = await driftVault.getVault(vaultAddress);
36
+ const allVaultDepositors = await driftVault.getAllVaultDepositors(
37
+ vaultAddress
38
+ );
39
+ const spotMarket = driftVault.driftClient.getSpotMarketAccount(
40
+ vault.spotMarketIndex
41
+ );
42
+ const spotPrecision = new BN(10).pow(new BN(spotMarket!.decimals));
43
+
44
+ const withdrawables: Array<PublicKey> = [];
45
+ for (const vd of allVaultDepositors) {
46
+ const vdAccount = vd.account as VaultDepositor;
47
+ if (vdAccount.lastWithdrawRequest.shares.gt(new BN(0))) {
48
+ const withdrawRequested = vdAccount.lastWithdrawRequest.ts.toNumber();
49
+ const secToWithdrawal =
50
+ withdrawRequested + vault.redeemPeriod.toNumber() - Date.now() / 1000;
51
+ const withdrawAvailable = secToWithdrawal < 0;
52
+ const pct =
53
+ vdAccount.lastWithdrawRequest.shares.toNumber() /
54
+ vd.account.vaultShares.toNumber();
55
+ const daysUntilWithdraw = Math.floor(secToWithdrawal / 86400);
56
+ const hoursUntilWithdraw = Math.floor((secToWithdrawal % 86400) / 3600);
57
+
58
+ if (secToWithdrawal < 0) {
59
+ console.log(`Withdraw available for ${vdAccount.authority.toBase58()}`);
60
+ console.log(
61
+ ` - pending withdrawal: ${vdAccount.lastWithdrawRequest.shares.toString()} ($${convertToNumber(
62
+ vd.account.lastWithdrawRequest.value,
63
+ spotPrecision
64
+ )}), ${(pct * 100.0).toFixed(2)}% of their deposit ${
65
+ withdrawAvailable ? '<--- WITHDRAWABLE' : ''
66
+ }`
67
+ );
68
+ console.log(
69
+ ` - requested at: ${new Date(
70
+ withdrawRequested * 1000
71
+ ).toISOString()}`
72
+ );
73
+ console.log(
74
+ ` - can withdraw in: ${daysUntilWithdraw} days and ${hoursUntilWithdraw} hours`
75
+ );
76
+ withdrawables.push(vdAccount.pubkey);
77
+ }
78
+ }
79
+ }
80
+
81
+ console.log(`Withdrawing ${withdrawables.length} depositors`);
82
+ const luts = await driftClient.fetchAllLookupTableAccounts();
83
+ const chunkSize = 1;
84
+ for (let i = 0; i < withdrawables.length; i += chunkSize) {
85
+ const chunk = withdrawables.slice(i, i + chunkSize);
86
+ console.log(
87
+ `Processing chunk ${i / chunkSize + 1} of ${Math.ceil(
88
+ withdrawables.length / chunkSize
89
+ )}`
90
+ );
91
+ const ixs: TransactionInstruction[] = [
92
+ new TransactionInstruction({
93
+ keys: [{ pubkey: wallet.publicKey, isSigner: true, isWritable: true }],
94
+ data: Buffer.from('Drift Vaults manager initiated withdrawal', 'utf-8'),
95
+ programId: new PublicKey('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'),
96
+ }),
97
+ ];
98
+ for (const depositorAddress of chunk) {
99
+ try {
100
+ console.log(`Trying deposit: ${depositorAddress.toBase58()}`);
101
+ ixs.push(...(await driftVault.getForceWithdrawIx(depositorAddress)));
102
+ } catch (error) {
103
+ console.error(
104
+ `Error withdrawing for ${depositorAddress.toBase58()}:`,
105
+ error
106
+ );
107
+ }
108
+ }
109
+
110
+ const message = new TransactionMessage({
111
+ payerKey: driftClient.wallet.publicKey,
112
+ recentBlockhash: (
113
+ await driftClient.connection.getLatestBlockhash('finalized')
114
+ ).blockhash,
115
+ instructions: [
116
+ ComputeBudgetProgram.setComputeUnitLimit({
117
+ units: 800_000,
118
+ }),
119
+ ComputeBudgetProgram.setComputeUnitPrice({
120
+ microLamports: 10_000,
121
+ }),
122
+ ...ixs,
123
+ ],
124
+ }).compileToV0Message(luts);
125
+
126
+ const tx = await wallet.signVersionedTransaction(
127
+ new VersionedTransaction(message)
128
+ );
129
+
130
+ console.log(`Sending chunk: ${bs58.encode(tx.signatures[0])}`);
131
+ try {
132
+ const txid = await driftClient.connection.sendTransaction(tx);
133
+ console.log(`Sent chunk: https://solana.fm/tx/${txid}`);
134
+ } catch (e) {
135
+ console.error(`Error sending chunk: ${e}`);
136
+ console.log((e as SendTransactionError).logs);
137
+ }
138
+ }
139
+
140
+ // const tx = await driftVault.forceWithdraw(vaultDepositorAddress);
141
+ // console.log(`Forced withdraw from vault: ${tx}`);
142
+ };
@@ -0,0 +1,28 @@
1
+ export * from './initVault';
2
+ export * from './viewVault';
3
+ export * from './deriveVaultAddress';
4
+ export * from './managerDeposit';
5
+ export * from './managerRequestWithdraw';
6
+ export * from './managerCancelWithdraw';
7
+ export * from './managerWithdraw';
8
+ export * from './managerUpdateVault';
9
+ export * from './managerUpdateVaultManager';
10
+ export * from './managerUpdateVaultDelegate';
11
+ export * from './applyProfitShare';
12
+ export * from './initVaultDepositor';
13
+ export * from './deposit';
14
+ export * from './requestWithdraw';
15
+ export * from './forceWithdraw';
16
+ export * from './forceWithdrawAll';
17
+ export * from './withdraw';
18
+ export * from './listDepositorsForVault';
19
+ export * from './managerUpdateMarginTradingEnabled';
20
+ export * from './decodeLogs';
21
+ export * from './vaultInvariantChecks';
22
+ export * from './adminInitFeeUpdate';
23
+ export * from './adminDeleteFeeUpdate';
24
+ export * from './managerBorrow';
25
+ export * from './managerRepay';
26
+ export * from './managerUpdateBorrow';
27
+ export * from './adminUpdateVaultClass';
28
+
@@ -0,0 +1,227 @@
1
+ import {
2
+ BN,
3
+ PERCENTAGE_PRECISION,
4
+ PublicKey,
5
+ TEN,
6
+ convertToNumber,
7
+ decodeName,
8
+ getSignedMsgUserAccountPublicKey,
9
+ getUserAccountPublicKey,
10
+ } from '@velocity-exchange/sdk';
11
+ import { OptionValues, Command } from 'commander';
12
+ import { encodeName, getVaultAddressSync } from '../../src';
13
+ import { dumpTransactionMessage, getCommandContext } from '../utils';
14
+ import { VAULT_PROGRAM_ID } from '../../src/types/types';
15
+
16
+ export const initVault = async (program: Command, cmdOpts: OptionValues) => {
17
+ const { driftClient, driftVault } = await getCommandContext(program, true);
18
+
19
+ const newVaultName = cmdOpts.name;
20
+ if (!newVaultName) {
21
+ throw new Error('Must provide vault name with -n/--name');
22
+ }
23
+ const vaultNameBytes = encodeName(newVaultName!);
24
+
25
+ let spotMarketIndex = cmdOpts.marketIndex;
26
+ if (!spotMarketIndex) {
27
+ spotMarketIndex = '0';
28
+ }
29
+ spotMarketIndex = parseInt(spotMarketIndex);
30
+ const spotMarket = driftClient.getSpotMarketAccount(spotMarketIndex);
31
+ if (!spotMarket) {
32
+ throw new Error('No spot market found');
33
+ }
34
+ const spotPrecision = TEN.pow(new BN(spotMarket.decimals));
35
+ const spotMarketName = decodeName(spotMarket.name);
36
+
37
+ let redeemPeriodSec = cmdOpts.redeemPeriod;
38
+ if (!redeemPeriodSec) {
39
+ redeemPeriodSec = (7 * 60 * 60 * 24).toString(); // 7 days
40
+ }
41
+ redeemPeriodSec = parseInt(redeemPeriodSec);
42
+
43
+ let maxTokens = cmdOpts.maxTokens;
44
+ if (!maxTokens) {
45
+ maxTokens = '0';
46
+ }
47
+ maxTokens = parseInt(maxTokens);
48
+ const maxTokensBN = new BN(maxTokens).mul(spotPrecision);
49
+
50
+ let managementFee = cmdOpts.managementFee;
51
+ if (!managementFee) {
52
+ managementFee = '0';
53
+ }
54
+ managementFee = parseInt(managementFee);
55
+ const managementFeeBN = new BN(managementFee)
56
+ .mul(PERCENTAGE_PRECISION)
57
+ .div(new BN(100));
58
+
59
+ let profitShare = cmdOpts.profitShare;
60
+ if (!profitShare) {
61
+ profitShare = '0';
62
+ }
63
+ profitShare = parseInt(profitShare);
64
+ const profitShareBN = new BN(profitShare)
65
+ .mul(PERCENTAGE_PRECISION)
66
+ .div(new BN(100));
67
+
68
+ let permissioned = cmdOpts.permissioned;
69
+ if (!permissioned) {
70
+ permissioned = false;
71
+ }
72
+
73
+ let minDepositAmount = cmdOpts.minDepositAmount;
74
+ if (!minDepositAmount) {
75
+ minDepositAmount = '0';
76
+ }
77
+ minDepositAmount = parseFloat(minDepositAmount);
78
+ const minDepositAmountBN = new BN(
79
+ spotPrecision.toNumber() * minDepositAmount
80
+ );
81
+
82
+ let delegate = cmdOpts.delegate;
83
+ if (!delegate) {
84
+ delegate = driftClient.wallet.publicKey;
85
+ } else {
86
+ try {
87
+ delegate = new PublicKey(delegate);
88
+ } catch (err) {
89
+ console.error(`Invalid delegate address: ${err}`);
90
+ delegate = driftClient.wallet.publicKey;
91
+ }
92
+ }
93
+
94
+ console.log(`Initializing a new vault with params:`);
95
+ console.log(` VaultName: ${newVaultName}`);
96
+ console.log(
97
+ ` DepositSpotMarketIndex: ${spotMarketIndex} (${spotMarketName})`
98
+ );
99
+ console.log(
100
+ ` MaxTokens: ${convertToNumber(
101
+ maxTokensBN,
102
+ spotPrecision
103
+ )} ${spotMarketName}`
104
+ );
105
+ console.log(
106
+ ` MinDepositAmount: ${convertToNumber(
107
+ minDepositAmountBN,
108
+ spotPrecision
109
+ )} ${spotMarketName}`
110
+ );
111
+ console.log(
112
+ ` ManagementFee: ${
113
+ convertToNumber(managementFeeBN, PERCENTAGE_PRECISION) * 100.0
114
+ }%`
115
+ );
116
+ console.log(
117
+ ` ProfitShare: ${
118
+ convertToNumber(profitShareBN, PERCENTAGE_PRECISION) * 100.0
119
+ }%`
120
+ );
121
+ console.log(` Permissioned: ${permissioned}`);
122
+ console.log(` Delegate: ${delegate.toBase58()}`);
123
+ console.log(
124
+ ` Manager: ${
125
+ cmdOpts.manager
126
+ ? cmdOpts.manager
127
+ : driftClient.wallet.publicKey.toBase58()
128
+ }`
129
+ );
130
+
131
+ const readline = require('readline').createInterface({
132
+ input: process.stdin,
133
+ output: process.stdout,
134
+ });
135
+ console.log('');
136
+ const answer = await new Promise((resolve) => {
137
+ readline.question(
138
+ 'Is the above information correct? (yes/no) ',
139
+ (answer: string) => {
140
+ readline.close();
141
+ resolve(answer);
142
+ }
143
+ );
144
+ });
145
+ if ((answer as string).toLowerCase() !== 'yes') {
146
+ console.log('Initialization cancelled.');
147
+ readline.close();
148
+ process.exit(0);
149
+ }
150
+
151
+ const vaultAddress = getVaultAddressSync(VAULT_PROGRAM_ID, vaultNameBytes);
152
+ const vaultDriftUser = await getUserAccountPublicKey(
153
+ driftClient.program.programId,
154
+ vaultAddress,
155
+ 0
156
+ );
157
+
158
+ const ixs = [
159
+ await driftVault.getInitializeVaultIx({
160
+ name: vaultNameBytes,
161
+ spotMarketIndex,
162
+ redeemPeriod: new BN(redeemPeriodSec),
163
+ maxTokens: maxTokensBN,
164
+ managementFee: managementFeeBN,
165
+ profitShare: profitShareBN.toNumber(),
166
+ hurdleRate: 0,
167
+ permissioned,
168
+ minDepositAmount: minDepositAmountBN,
169
+ manager: cmdOpts.manager,
170
+ }),
171
+ await driftVault.getUpdateDelegateIx(
172
+ vaultAddress,
173
+ delegate,
174
+ vaultDriftUser,
175
+ cmdOpts.manager
176
+ ),
177
+ ];
178
+
179
+ const signedOrdersAccountAddress = getSignedMsgUserAccountPublicKey(
180
+ driftClient.program.programId,
181
+ vaultAddress
182
+ );
183
+
184
+ let swiftUsersAccountExists = false;
185
+ try {
186
+ const acc = await driftClient.connection.getAccountInfo(
187
+ signedOrdersAccountAddress
188
+ );
189
+ swiftUsersAccountExists = acc !== null;
190
+ } catch (_err) {
191
+ // Error getting account info is non-critical, default to false
192
+ }
193
+
194
+ if (!swiftUsersAccountExists) {
195
+ ixs.push(
196
+ (
197
+ await driftClient.getInitializeSignedMsgUserOrdersAccountIx(
198
+ vaultAddress,
199
+ 8
200
+ )
201
+ )[1]
202
+ );
203
+ }
204
+
205
+ console.log(`New vault address will be: ${vaultAddress.toBase58()}`);
206
+ console.log(`Setting trading delegate to: ${delegate.toBase58()}`);
207
+ console.log('');
208
+
209
+ if (cmdOpts.dumpTransactionMessage) {
210
+ console.log(`Base 58 encoded transaction:`);
211
+ console.log(
212
+ dumpTransactionMessage(
213
+ cmdOpts.manager
214
+ ? new PublicKey(cmdOpts.manager)
215
+ : driftClient.wallet.publicKey,
216
+ ixs
217
+ )
218
+ );
219
+ } else {
220
+ const initTx = await driftVault.createAndSendTxn(ixs);
221
+ console.log(
222
+ `Initialized vault, tx: https://solana.fm/tx/${initTx}${
223
+ driftClient.env === 'devnet' ? '?cluster=devnet-solana' : ''
224
+ }`
225
+ );
226
+ }
227
+ };
@@ -0,0 +1,42 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ import {
3
+ getVaultDepositorAddressSync
4
+ } from "../../src/addresses";
5
+ import {
6
+ OptionValues,
7
+ Command
8
+ } from "commander";
9
+ import { getCommandContext } from "../utils";
10
+ import { VAULT_PROGRAM_ID } from "../../src/types/types";
11
+
12
+ export const initVaultDepositor = async (program: Command, cmdOpts: OptionValues) => {
13
+
14
+ let vaultAddress: PublicKey;
15
+ try {
16
+ vaultAddress = new PublicKey(cmdOpts.vaultAddress as string);
17
+ } catch (err) {
18
+ console.error("Invalid vault address");
19
+ process.exit(1);
20
+ }
21
+
22
+ let depositAuthority: PublicKey;
23
+ try {
24
+ depositAuthority = new PublicKey(cmdOpts.depositAuthority as string);
25
+ } catch (err) {
26
+ console.error("Invalid deposit authority");
27
+ process.exit(1);
28
+ }
29
+
30
+ const {
31
+ driftVault
32
+ } = await getCommandContext(program, true);
33
+
34
+ const vaultDepositorAddress = getVaultDepositorAddressSync(
35
+ VAULT_PROGRAM_ID,
36
+ vaultAddress,
37
+ depositAuthority,
38
+ );
39
+ const tx = await driftVault.initializeVaultDepositor(vaultAddress, depositAuthority, driftVault.driftClient.wallet.publicKey);
40
+ console.log(`VaultDepositor initialized for ${depositAuthority}: ${tx}`);
41
+ console.log(`VaultDepositor address: ${vaultDepositorAddress}`);
42
+ };
@@ -0,0 +1,32 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ import {
3
+ OptionValues,
4
+ Command
5
+ } from "commander";
6
+ import { getCommandContext } from "../utils";
7
+
8
+ export const listDepositorsForVault = async (program: Command, cmdOpts: OptionValues) => {
9
+
10
+ const {
11
+ driftVault
12
+ } = await getCommandContext(program, false);
13
+
14
+ let vaultAddress: PublicKey | undefined = undefined;
15
+ try {
16
+ if (cmdOpts.vaultAddress !== undefined) {
17
+ vaultAddress = new PublicKey(cmdOpts.vaultAddress as string);
18
+ } else {
19
+ console.error("Must supply --vault-address");
20
+ process.exit(1);
21
+ }
22
+ } catch (err) {
23
+ console.error("Failed to load VaultDepositor address");
24
+ process.exit(1);
25
+ }
26
+
27
+ const vaultDepositors = await driftVault.getAllVaultDepositors(vaultAddress);
28
+ vaultDepositors.forEach((vaultDepositor) => {
29
+ console.log(vaultDepositor.publicKey.toBase58());
30
+ });
31
+ // printVaultDepositor(vaultDepositor);
32
+ };
@@ -0,0 +1,32 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ import {
3
+ OptionValues,
4
+ Command
5
+ } from "commander";
6
+ import { dumpTransactionMessage, getCommandContext } from "../utils";
7
+
8
+ export const managerApplyProfitShare = async (program: Command, cmdOpts: OptionValues) => {
9
+
10
+ let vaultAddress: PublicKey;
11
+ try {
12
+ vaultAddress = new PublicKey(cmdOpts.vaultAddress as string);
13
+ } catch (err) {
14
+ console.error("Invalid vault address");
15
+ process.exit(1);
16
+ }
17
+
18
+ const {
19
+ driftVault,
20
+ driftClient
21
+ } = await getCommandContext(program, true);
22
+
23
+ const vaultDepositorAddress = new PublicKey(cmdOpts.vaultDepositor as string);
24
+
25
+ if (cmdOpts.dumpTransactionMessage) {
26
+ const tx = await driftVault.getApplyProfitShareIx(vaultAddress, vaultDepositorAddress);
27
+ console.log(dumpTransactionMessage(driftClient.wallet.publicKey, [tx]));
28
+ } else {
29
+ const tx = await driftVault.applyProfitShare(vaultAddress, vaultDepositorAddress);
30
+ console.log(`Applied profit share: https://solana.fm/tx/${tx}${driftClient.env === "devnet" ? "?cluster=devnet-solana" : ""}`);
31
+ }
32
+ };
@@ -0,0 +1,77 @@
1
+ import { Command, OptionValues } from 'commander';
2
+ import { PublicKey } from '@solana/web3.js';
3
+ import { BN, TEN } from '@velocity-exchange/sdk';
4
+ import { dumpTransactionMessage, getCommandContext } from '../utils';
5
+
6
+ export async function managerBorrow(
7
+ program: Command,
8
+ cmdOpts: OptionValues
9
+ ): Promise<void> {
10
+ const {
11
+ vaultAddress,
12
+ borrowSpotMarketIndex,
13
+ borrowAmount,
14
+ managerTokenAccount,
15
+ dumpTransactionMessage: dumpTx,
16
+ } = cmdOpts;
17
+
18
+ const { driftClient, driftVault } = await getCommandContext(program, true);
19
+
20
+ if (!vaultAddress) {
21
+ throw new Error('Must provide vault address with --vault-address');
22
+ }
23
+
24
+ if (!borrowSpotMarketIndex) {
25
+ throw new Error(
26
+ 'Must provide borrow spot market index with --borrow-spot-market-index'
27
+ );
28
+ }
29
+
30
+ if (!borrowAmount) {
31
+ throw new Error('Must provide borrow amount with --borrow-amount');
32
+ }
33
+
34
+ const vault = new PublicKey(vaultAddress);
35
+ const borrowIndex = parseInt(borrowSpotMarketIndex);
36
+
37
+ const borrowSpotMarket = driftClient.getSpotMarketAccount(borrowIndex);
38
+ if (!borrowSpotMarket) {
39
+ throw new Error('No borrow spot market found');
40
+ }
41
+ const borrowPrecision = TEN.pow(new BN(borrowSpotMarket.decimals));
42
+ const borrowBN = new BN(borrowAmount * borrowPrecision.toNumber());
43
+
44
+ const managerTokenAccountPubkey = managerTokenAccount
45
+ ? new PublicKey(managerTokenAccount)
46
+ : undefined;
47
+
48
+ try {
49
+ if (dumpTx) {
50
+ const ixs = await driftVault.getManagerBorrowIx(
51
+ vault,
52
+ borrowIndex,
53
+ borrowBN,
54
+ managerTokenAccountPubkey
55
+ );
56
+ console.log('Transaction Instructions:');
57
+ console.log(dumpTransactionMessage(driftClient.wallet.publicKey, ixs));
58
+ return;
59
+ }
60
+
61
+ const txSig = await driftVault.managerBorrow(
62
+ vault,
63
+ borrowIndex,
64
+ borrowBN,
65
+ managerTokenAccountPubkey
66
+ );
67
+ console.log(`Manager borrow transaction signature: ${txSig}`);
68
+ console.log(
69
+ `Transaction: https://solana.fm/tx/${txSig}${
70
+ driftClient.env === 'devnet' ? '?cluster=devnet-solana' : ''
71
+ }`
72
+ );
73
+ } catch (error) {
74
+ console.error('Error borrowing:', error);
75
+ throw error;
76
+ }
77
+ }
@@ -0,0 +1,30 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ import {
3
+ OptionValues,
4
+ Command
5
+ } from "commander";
6
+ import { dumpTransactionMessage, getCommandContext } from "../utils";
7
+
8
+ export const managerCancelWithdraw = async (program: Command, cmdOpts: OptionValues) => {
9
+
10
+ let vaultAddress: PublicKey;
11
+ try {
12
+ vaultAddress = new PublicKey(cmdOpts.vaultAddress as string);
13
+ } catch (err) {
14
+ console.error("Invalid vault address");
15
+ process.exit(1);
16
+ }
17
+
18
+ const {
19
+ driftVault,
20
+ driftClient
21
+ } = await getCommandContext(program, true);
22
+
23
+ if (cmdOpts.dumpTransactionMessage) {
24
+ const tx = await driftVault.getManagerCancelWithdrawRequestIx(vaultAddress);
25
+ console.log(dumpTransactionMessage(driftClient.wallet.publicKey, [tx]));
26
+ } else {
27
+ const tx = await driftVault.managerCancelWithdrawRequest(vaultAddress);
28
+ console.log(`Canceled withdraw as vault manager: https://solana.fm/tx/${tx}${driftClient.env === "devnet" ? "?cluster=devnet-solana" : ""}`);
29
+ }
30
+ };
@@ -0,0 +1,45 @@
1
+ import { BN, TEN } from '@velocity-exchange/sdk';
2
+ import { PublicKey } from '@solana/web3.js';
3
+ import { OptionValues, Command } from 'commander';
4
+ import { dumpTransactionMessage, getCommandContext } from '../utils';
5
+
6
+ export const managerDeposit = async (
7
+ program: Command,
8
+ cmdOpts: OptionValues
9
+ ) => {
10
+ let vaultAddress: PublicKey;
11
+ try {
12
+ vaultAddress = new PublicKey(cmdOpts.vaultAddress as string);
13
+ } catch (err) {
14
+ console.error('Invalid vault address');
15
+ process.exit(1);
16
+ }
17
+
18
+ const { driftClient, driftVault } = await getCommandContext(program, true);
19
+
20
+ const vaultAccount = await driftVault.program.account.vault.fetch(
21
+ vaultAddress
22
+ );
23
+ const spotMarket = driftClient.getSpotMarketAccount(
24
+ vaultAccount.spotMarketIndex
25
+ );
26
+ if (!spotMarket) {
27
+ throw new Error('No spot market found');
28
+ }
29
+ const spotPrecision = TEN.pow(new BN(spotMarket.decimals));
30
+ const depositBN = new BN(cmdOpts.amount * spotPrecision.toNumber());
31
+
32
+ if (cmdOpts.dumpTransactionMessage) {
33
+ const txs = await driftVault.getManagerDepositIx(vaultAddress, depositBN);
34
+ console.log(dumpTransactionMessage(driftClient.wallet.publicKey, txs));
35
+ } else {
36
+ const tx = await driftVault.managerDeposit(vaultAddress, depositBN);
37
+ console.log(
38
+ `Deposited ${
39
+ cmdOpts.amount
40
+ } to vault as manager: https://solana.fm/tx/${tx}${
41
+ driftClient.env === 'devnet' ? '?cluster=devnet-solana' : ''
42
+ }`
43
+ );
44
+ }
45
+ };