@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.
- package/.env.example +3 -0
- package/README.md +152 -0
- package/cli/cli.ts +751 -0
- package/cli/commands/adminDeleteFeeUpdate.ts +73 -0
- package/cli/commands/adminInitFeeUpdate.ts +73 -0
- package/cli/commands/adminUpdateVaultClass.ts +49 -0
- package/cli/commands/applyProfitShare.ts +139 -0
- package/cli/commands/decodeLogs.ts +98 -0
- package/cli/commands/deposit.ts +98 -0
- package/cli/commands/deriveVaultAddress.ts +14 -0
- package/cli/commands/forceWithdraw.ts +56 -0
- package/cli/commands/forceWithdrawAll.ts +142 -0
- package/cli/commands/index.ts +28 -0
- package/cli/commands/initVault.ts +227 -0
- package/cli/commands/initVaultDepositor.ts +42 -0
- package/cli/commands/listDepositorsForVault.ts +32 -0
- package/cli/commands/managerApplyProfitShare.ts +32 -0
- package/cli/commands/managerBorrow.ts +77 -0
- package/cli/commands/managerCancelWithdraw.ts +30 -0
- package/cli/commands/managerDeposit.ts +45 -0
- package/cli/commands/managerRepay.ts +94 -0
- package/cli/commands/managerRequestWithdraw.ts +86 -0
- package/cli/commands/managerUpdateBorrow.ts +56 -0
- package/cli/commands/managerUpdateFees.ts +156 -0
- package/cli/commands/managerUpdateMarginTradingEnabled.ts +32 -0
- package/cli/commands/managerUpdatePoolId.ts +36 -0
- package/cli/commands/managerUpdateVault.ts +210 -0
- package/cli/commands/managerUpdateVaultDelegate.ts +43 -0
- package/cli/commands/managerUpdateVaultManager.ts +77 -0
- package/cli/commands/managerWithdraw.ts +30 -0
- package/cli/commands/requestWithdraw.ts +58 -0
- package/cli/commands/vaultDeposit.ts +42 -0
- package/cli/commands/vaultInvariantChecks.ts +407 -0
- package/cli/commands/vaultWithdraw.ts +42 -0
- package/cli/commands/viewVault.ts +50 -0
- package/cli/commands/viewVaultDepositor.ts +36 -0
- package/cli/commands/withdraw.ts +40 -0
- package/cli/ledgerWallet.test.ts +49 -0
- package/cli/ledgerWallet.ts +111 -0
- package/cli/utils.ts +389 -0
- package/package.json +48 -0
- package/src/accountSubscribers/index.ts +2 -0
- package/src/accountSubscribers/pollingVaultDepositorSubscriber.ts +69 -0
- package/src/accountSubscribers/pollingVaultSubscriber.ts +63 -0
- package/src/accountSubscribers/pollingVaultsProgramAccountSubscriber.ts +114 -0
- package/src/accounts/index.ts +2 -0
- package/src/accounts/vaultAccount.ts +255 -0
- package/src/accounts/vaultDepositorAccount.ts +77 -0
- package/src/accounts/vaultsProgramAccount.ts +38 -0
- package/src/addresses.ts +114 -0
- package/src/constants/index.ts +15 -0
- package/src/idl/drift_vaults.json +5698 -0
- package/src/index.ts +11 -0
- package/src/math/index.ts +2 -0
- package/src/math/vault.ts +71 -0
- package/src/math/vaultDepositor.ts +90 -0
- package/src/name.ts +18 -0
- package/src/parsers/index.ts +1 -0
- package/src/parsers/logParser.ts +28 -0
- package/src/types/drift_vaults.ts +6211 -0
- package/src/types/types.ts +336 -0
- package/src/utils.ts +74 -0
- package/src/vaultClient.ts +3666 -0
- package/tsconfig.json +24 -0
- package/velocity-exchange-vaults-sdk-0.0.1.tgz +0 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import {
|
|
3
|
+
OptionValues,
|
|
4
|
+
Command
|
|
5
|
+
} from "commander";
|
|
6
|
+
import { dumpTransactionMessage, getCommandContext } from "../utils";
|
|
7
|
+
import { VAULT_ADMIN_KEY } from "../../src";
|
|
8
|
+
|
|
9
|
+
export const adminDeleteFeeUpdate = async (program: Command, cmdOpts: OptionValues) => {
|
|
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 (!driftClient.wallet.publicKey.equals(VAULT_ADMIN_KEY)) {
|
|
24
|
+
console.error("Only vault admin can delete fee update");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const vault = await driftVault.getVault(vaultAddress);
|
|
29
|
+
|
|
30
|
+
console.log(`Deleting fee update for vault:`);
|
|
31
|
+
console.log(` Vault: ${vault.pubkey.toBase58()}`);
|
|
32
|
+
|
|
33
|
+
const readline = require('readline').createInterface({
|
|
34
|
+
input: process.stdin,
|
|
35
|
+
output: process.stdout
|
|
36
|
+
});
|
|
37
|
+
console.log('');
|
|
38
|
+
const answer = await new Promise(resolve => {
|
|
39
|
+
readline.question('Are you sure you want to delete the fee update? (yes/no) ', (answer: string) => {
|
|
40
|
+
readline.close();
|
|
41
|
+
resolve(answer);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
if ((answer as string).toLowerCase() !== 'yes') {
|
|
45
|
+
console.log('Fee update deletion canceled.');
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
console.log('Deleting fee update...');
|
|
49
|
+
|
|
50
|
+
let done = false;
|
|
51
|
+
while (!done) {
|
|
52
|
+
try {
|
|
53
|
+
if (cmdOpts.dumpTransactionMessage) {
|
|
54
|
+
const tx = await driftVault.getAdminDeleteFeeUpdateIx(vaultAddress);
|
|
55
|
+
console.log(dumpTransactionMessage(driftClient.wallet.publicKey, [tx]));
|
|
56
|
+
} else {
|
|
57
|
+
const tx = await driftVault.adminDeleteFeeUpdate(vaultAddress);
|
|
58
|
+
console.log(`Deleted fee update as admin: https://solana.fm/tx/${tx}${driftClient.env === "devnet" ? "?cluster=devnet-solana" : ""}`);
|
|
59
|
+
done = true;
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
} catch (e) {
|
|
63
|
+
const err = e as Error;
|
|
64
|
+
if (err.message.includes('TransactionExpiredTimeoutError')) {
|
|
65
|
+
console.log(err.message);
|
|
66
|
+
console.log('Transaction timeout. Retrying...');
|
|
67
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
68
|
+
} else {
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import {
|
|
3
|
+
OptionValues,
|
|
4
|
+
Command
|
|
5
|
+
} from "commander";
|
|
6
|
+
import { dumpTransactionMessage, getCommandContext } from "../utils";
|
|
7
|
+
import { VAULT_ADMIN_KEY } from "../../src";
|
|
8
|
+
|
|
9
|
+
export const adminInitFeeUpdate = async (program: Command, cmdOpts: OptionValues) => {
|
|
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 (!driftClient.wallet.publicKey.equals(VAULT_ADMIN_KEY)) {
|
|
24
|
+
console.error("Only vault admin can initialize fee update");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const vault = await driftVault.getVault(vaultAddress);
|
|
29
|
+
|
|
30
|
+
console.log(`Initializing fee update for vault:`);
|
|
31
|
+
console.log(` Vault: ${vault.pubkey.toBase58()}`);
|
|
32
|
+
|
|
33
|
+
const readline = require('readline').createInterface({
|
|
34
|
+
input: process.stdin,
|
|
35
|
+
output: process.stdout
|
|
36
|
+
});
|
|
37
|
+
console.log('');
|
|
38
|
+
const answer = await new Promise(resolve => {
|
|
39
|
+
readline.question('Is the above information correct? (yes/no) ', (answer: string) => {
|
|
40
|
+
readline.close();
|
|
41
|
+
resolve(answer);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
if ((answer as string).toLowerCase() !== 'yes') {
|
|
45
|
+
console.log('Fee update initialization canceled.');
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
console.log('Initializing fee update...');
|
|
49
|
+
|
|
50
|
+
let done = false;
|
|
51
|
+
while (!done) {
|
|
52
|
+
try {
|
|
53
|
+
if (cmdOpts.dumpTransactionMessage) {
|
|
54
|
+
const tx = await driftVault.getAdminInitFeeUpdateIx(vaultAddress);
|
|
55
|
+
console.log(dumpTransactionMessage(driftClient.wallet.publicKey, [tx]));
|
|
56
|
+
} else {
|
|
57
|
+
const tx = await driftVault.adminInitFeeUpdate(vaultAddress);
|
|
58
|
+
console.log(`Initialized fee update as admin: https://solana.fm/tx/${tx}${driftClient.env === "devnet" ? "?cluster=devnet-solana" : ""}`);
|
|
59
|
+
done = true;
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
} catch (e) {
|
|
63
|
+
const err = e as Error;
|
|
64
|
+
if (err.message.includes('TransactionExpiredTimeoutError')) {
|
|
65
|
+
console.log(err.message);
|
|
66
|
+
console.log('Transaction timeout. Retrying...');
|
|
67
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
68
|
+
} else {
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
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, calculateApplyProfitShare } from '../../src';
|
|
12
|
+
import { BN, TEN, ZERO, numberToSafeBN } from '@velocity-exchange/sdk';
|
|
13
|
+
import { ProgramAccount } from '@coral-xyz/anchor';
|
|
14
|
+
|
|
15
|
+
export const applyProfitShare = async (
|
|
16
|
+
program: Command,
|
|
17
|
+
cmdOpts: OptionValues
|
|
18
|
+
) => {
|
|
19
|
+
let vaultAddress: PublicKey;
|
|
20
|
+
try {
|
|
21
|
+
vaultAddress = new PublicKey(cmdOpts.vaultAddress as string);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
console.error('Invalid vault address');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const { driftVault, driftClient, wallet } = await getCommandContext(
|
|
28
|
+
program,
|
|
29
|
+
true
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const vault = await driftVault.getVault(vaultAddress);
|
|
33
|
+
const vdWithNoWithdrawRequests =
|
|
34
|
+
await driftVault.getAllVaultDepositorsWithNoWithdrawRequest(vaultAddress);
|
|
35
|
+
const vaultEquitySpot = await driftVault.calculateVaultEquityInDepositAsset({
|
|
36
|
+
vault,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const spotMarket = driftClient.getSpotMarketAccount(vault.spotMarketIndex);
|
|
40
|
+
if (!spotMarket) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Spot market account ${vault.spotMarketIndex} has not been loaded`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
const spotMarketPrecision = TEN.pow(new BN(spotMarket.decimals));
|
|
46
|
+
const thresholdNumber = parseFloat(cmdOpts.threshold);
|
|
47
|
+
const thresholdBN = numberToSafeBN(thresholdNumber, spotMarketPrecision);
|
|
48
|
+
let pendingProfitShareToRealize = ZERO;
|
|
49
|
+
const vdWithPendingProfitShare = vdWithNoWithdrawRequests.filter(
|
|
50
|
+
(vd: ProgramAccount<VaultDepositor>) => {
|
|
51
|
+
if (vault.managementFee.gt(ZERO)) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
const pendingProfitShares = calculateApplyProfitShare(
|
|
55
|
+
vd.account,
|
|
56
|
+
vaultEquitySpot,
|
|
57
|
+
vault
|
|
58
|
+
);
|
|
59
|
+
const doRealize = pendingProfitShares.profitShareAmount.gte(thresholdBN);
|
|
60
|
+
if (doRealize) {
|
|
61
|
+
pendingProfitShareToRealize = pendingProfitShareToRealize.add(
|
|
62
|
+
pendingProfitShares.profitShareAmount
|
|
63
|
+
);
|
|
64
|
+
return true;
|
|
65
|
+
} else {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
console.log(
|
|
72
|
+
`${vdWithPendingProfitShare.length}/${
|
|
73
|
+
vdWithNoWithdrawRequests.length
|
|
74
|
+
} depositors have pending profit shares above threshold ${
|
|
75
|
+
cmdOpts.threshold
|
|
76
|
+
} (${thresholdBN.toString()})`
|
|
77
|
+
);
|
|
78
|
+
console.log(
|
|
79
|
+
`Applying profit share for ${vdWithPendingProfitShare.length} depositors.`
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const chunkSize = 1;
|
|
83
|
+
const ixChunks: Array<Array<TransactionInstruction>> = [];
|
|
84
|
+
for (let i = 0; i < vdWithPendingProfitShare.length; i += chunkSize) {
|
|
85
|
+
const chunk = vdWithPendingProfitShare.slice(i, i + chunkSize);
|
|
86
|
+
const ixs = await Promise.all(
|
|
87
|
+
chunk.map((vd: ProgramAccount<VaultDepositor>) => {
|
|
88
|
+
return driftVault.getApplyProfitShareIx(vaultAddress, vd.publicKey);
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
ixChunks.push(ixs);
|
|
93
|
+
}
|
|
94
|
+
console.log(`Sending ${ixChunks.length} transactions...`);
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < ixChunks.length; i++) {
|
|
97
|
+
const ixs = ixChunks[i];
|
|
98
|
+
console.log(`Sending chunk ${i + 1}/${ixChunks.length}`);
|
|
99
|
+
try {
|
|
100
|
+
ixs.unshift(
|
|
101
|
+
ComputeBudgetProgram.setComputeUnitPrice({
|
|
102
|
+
microLamports: 10000,
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
ixs.unshift(
|
|
106
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
107
|
+
units: 170_000,
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const message = new TransactionMessage({
|
|
112
|
+
payerKey: driftClient.wallet.publicKey,
|
|
113
|
+
recentBlockhash: (
|
|
114
|
+
await driftClient.connection.getLatestBlockhash('finalized')
|
|
115
|
+
).blockhash,
|
|
116
|
+
instructions: ixs,
|
|
117
|
+
}).compileToV0Message();
|
|
118
|
+
|
|
119
|
+
const tx = await wallet.signVersionedTransaction(
|
|
120
|
+
new VersionedTransaction(message)
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const txid = await driftClient.connection.sendTransaction(tx);
|
|
125
|
+
console.log(
|
|
126
|
+
`Sent chunk: https://solana.fm/tx/${txid}${
|
|
127
|
+
driftClient.env === 'devnet' ? '?cluster=devnet-solana' : ''
|
|
128
|
+
}`
|
|
129
|
+
);
|
|
130
|
+
} catch (e) {
|
|
131
|
+
console.error(`Error sending chunk: ${e}`);
|
|
132
|
+
console.log((e as SendTransactionError).logs);
|
|
133
|
+
}
|
|
134
|
+
} catch (e) {
|
|
135
|
+
console.error(e);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { OptionValues, Command } from 'commander';
|
|
2
|
+
import { getCommandContext } from '../utils';
|
|
3
|
+
import { VaultDepositorRecord } from '../../src';
|
|
4
|
+
import { BN, TEN, convertToNumber, getVariant } from '@velocity-exchange/sdk';
|
|
5
|
+
|
|
6
|
+
export const decodeLogs = async (program: Command, cmdOpts: OptionValues) => {
|
|
7
|
+
let txId: string;
|
|
8
|
+
try {
|
|
9
|
+
txId = cmdOpts.tx as string;
|
|
10
|
+
} catch (err) {
|
|
11
|
+
console.error('Invalid transaction hash');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
if (!txId) {
|
|
15
|
+
console.error('Invalid transaction hash');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { driftVault, driftClient } = await getCommandContext(program, false);
|
|
20
|
+
|
|
21
|
+
const tx = await driftClient.connection.getParsedTransaction(txId, {
|
|
22
|
+
commitment: 'confirmed',
|
|
23
|
+
maxSupportedTransactionVersion: 0,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
let i = 0;
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
for (const event of driftVault.program._events._eventParser.parseLogs(
|
|
29
|
+
tx!.meta!.logMessages
|
|
30
|
+
)) {
|
|
31
|
+
console.log(`--------------- Event: ${i} ${event.name} -----------------`);
|
|
32
|
+
i++;
|
|
33
|
+
|
|
34
|
+
/* eslint-disable no-case-declarations */
|
|
35
|
+
switch (event.name) {
|
|
36
|
+
case 'VaultDepositorRecord':
|
|
37
|
+
const data: VaultDepositorRecord = event.data;
|
|
38
|
+
const spotMarket = driftClient.getSpotMarketAccount(
|
|
39
|
+
data.spotMarketIndex
|
|
40
|
+
);
|
|
41
|
+
const spotPrecision = TEN.pow(new BN(spotMarket!.decimals));
|
|
42
|
+
const date = new Date(data.ts.toNumber() * 1000);
|
|
43
|
+
|
|
44
|
+
console.log(event.name);
|
|
45
|
+
console.log(` ts: ${date.toISOString()} (${data.ts.toNumber()})`);
|
|
46
|
+
console.log(` vault: ${data.vault.toBase58()}`);
|
|
47
|
+
console.log(
|
|
48
|
+
` depositorAuthority: ${data.depositorAuthority.toBase58()}`
|
|
49
|
+
);
|
|
50
|
+
console.log(` action: ${getVariant(data.action)}`);
|
|
51
|
+
console.log(` amount: ${convertToNumber(data.amount, spotPrecision)}`);
|
|
52
|
+
console.log(` vaultSharesBefore: ${data.vaultSharesBefore.toNumber()}`);
|
|
53
|
+
console.log(
|
|
54
|
+
` vaultSharesAfter: ${data.vaultSharesAfter.toNumber()} (${
|
|
55
|
+
data.vaultSharesAfter.toNumber() - data.vaultSharesBefore.toNumber()
|
|
56
|
+
})`
|
|
57
|
+
);
|
|
58
|
+
console.log(
|
|
59
|
+
` vaultEquityBefore: ${convertToNumber(
|
|
60
|
+
data.vaultEquityBefore,
|
|
61
|
+
spotPrecision
|
|
62
|
+
)}`
|
|
63
|
+
);
|
|
64
|
+
console.log(
|
|
65
|
+
` userVaultSharesBefore: ${data.userVaultSharesBefore.toNumber()}`
|
|
66
|
+
);
|
|
67
|
+
console.log(
|
|
68
|
+
` userVaultSharesAfter: ${data.userVaultSharesAfter.toNumber()} (${
|
|
69
|
+
data.userVaultSharesAfter.toNumber() -
|
|
70
|
+
data.userVaultSharesBefore.toNumber()
|
|
71
|
+
})`
|
|
72
|
+
);
|
|
73
|
+
console.log(
|
|
74
|
+
` totalVaultSharesBefore: ${data.totalVaultSharesBefore.toNumber()}`
|
|
75
|
+
);
|
|
76
|
+
console.log(
|
|
77
|
+
` totalVaultSharesAfter: ${data.totalVaultSharesAfter.toNumber()} (${
|
|
78
|
+
data.totalVaultSharesAfter.toNumber() -
|
|
79
|
+
data.totalVaultSharesBefore.toNumber()
|
|
80
|
+
})`
|
|
81
|
+
);
|
|
82
|
+
console.log(` profitShare: ${data.profitShare.toNumber()}`);
|
|
83
|
+
console.log(` managementFee: ${data.managementFee.toNumber()}`);
|
|
84
|
+
console.log(
|
|
85
|
+
` managementFeeShares: ${data.managementFeeShares.toNumber()}`
|
|
86
|
+
);
|
|
87
|
+
// @ts-ignore
|
|
88
|
+
console.log(
|
|
89
|
+
` depositOraclePrice: ${data.depositOraclePrice?.toNumber()}`
|
|
90
|
+
);
|
|
91
|
+
break;
|
|
92
|
+
default:
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log('----------Raw Event-------------');
|
|
96
|
+
console.log(event);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { BN, TEN } from '@velocity-exchange/sdk';
|
|
2
|
+
import { PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { OptionValues, Command } from 'commander';
|
|
4
|
+
import { getCommandContext } from '../utils';
|
|
5
|
+
import { getVaultDepositorAddressSync, VAULT_PROGRAM_ID } from '../../src';
|
|
6
|
+
|
|
7
|
+
export const deposit = async (program: Command, cmdOpts: OptionValues) => {
|
|
8
|
+
// verify correct args provided
|
|
9
|
+
if (!cmdOpts.vaultDepositorAddress) {
|
|
10
|
+
if (!cmdOpts.vaultAddress || !cmdOpts.depositAuthority) {
|
|
11
|
+
console.error(
|
|
12
|
+
'Must provide --vault-address and --deposit-authority if not providing --vault-depositor-address'
|
|
13
|
+
);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { driftClient, driftVault } = await getCommandContext(program, true);
|
|
19
|
+
|
|
20
|
+
let vaultDepositorAddress: PublicKey;
|
|
21
|
+
let vaultAddress: PublicKey | undefined;
|
|
22
|
+
let depositAuthority: PublicKey | undefined;
|
|
23
|
+
if (cmdOpts.vaultDepositorAddress) {
|
|
24
|
+
vaultDepositorAddress = new PublicKey(
|
|
25
|
+
cmdOpts.vaultDepositorAddress as string
|
|
26
|
+
);
|
|
27
|
+
} else {
|
|
28
|
+
vaultAddress = new PublicKey(cmdOpts.vaultAddress as string);
|
|
29
|
+
depositAuthority = new PublicKey(cmdOpts.depositAuthority as string);
|
|
30
|
+
vaultDepositorAddress = getVaultDepositorAddressSync(
|
|
31
|
+
VAULT_PROGRAM_ID,
|
|
32
|
+
vaultAddress,
|
|
33
|
+
depositAuthority
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const vaultDepositorAccount =
|
|
38
|
+
await driftVault.program.account.vaultDepositor.fetchNullable(
|
|
39
|
+
vaultDepositorAddress
|
|
40
|
+
);
|
|
41
|
+
if (!vaultDepositorAccount) {
|
|
42
|
+
if (!vaultAddress || !depositAuthority) {
|
|
43
|
+
console.error(
|
|
44
|
+
'Must provide --vault-address and --deposit-authority if not providing --vault-depositor-address, and VaultDepositor account does not exist'
|
|
45
|
+
);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const vaultAccount = await driftVault.program.account.vault.fetch(
|
|
50
|
+
vaultAddress
|
|
51
|
+
);
|
|
52
|
+
const spotMarket = driftClient.getSpotMarketAccount(
|
|
53
|
+
vaultAccount.spotMarketIndex
|
|
54
|
+
);
|
|
55
|
+
if (!spotMarket) {
|
|
56
|
+
throw new Error('No spot market found');
|
|
57
|
+
}
|
|
58
|
+
const spotPrecision = TEN.pow(new BN(spotMarket.decimals));
|
|
59
|
+
const depositBN = new BN(cmdOpts.amount * spotPrecision.toNumber());
|
|
60
|
+
|
|
61
|
+
console.log(
|
|
62
|
+
`depositing (initializing VaultDepositor account): ${depositBN.toString()}`
|
|
63
|
+
);
|
|
64
|
+
const tx = await driftVault.deposit(vaultDepositorAddress, depositBN, {
|
|
65
|
+
authority: depositAuthority,
|
|
66
|
+
vault: vaultAddress,
|
|
67
|
+
});
|
|
68
|
+
console.log(
|
|
69
|
+
`Deposited ${cmdOpts.amount} to vault: https://solana.fm/tx/${tx}${
|
|
70
|
+
driftClient.env === 'devnet' ? '?cluster=devnet-solana' : ''
|
|
71
|
+
}`
|
|
72
|
+
);
|
|
73
|
+
} else {
|
|
74
|
+
// VaultDepositor exists
|
|
75
|
+
const vaultAddress = vaultDepositorAccount.vault;
|
|
76
|
+
const vaultAccount = await driftVault.program.account.vault.fetch(
|
|
77
|
+
vaultAddress
|
|
78
|
+
);
|
|
79
|
+
const spotMarket = driftClient.getSpotMarketAccount(
|
|
80
|
+
vaultAccount.spotMarketIndex
|
|
81
|
+
);
|
|
82
|
+
if (!spotMarket) {
|
|
83
|
+
throw new Error('No spot market found');
|
|
84
|
+
}
|
|
85
|
+
const spotPrecision = TEN.pow(new BN(spotMarket.decimals));
|
|
86
|
+
const depositBN = new BN(cmdOpts.amount * spotPrecision.toNumber());
|
|
87
|
+
|
|
88
|
+
console.log(
|
|
89
|
+
`depositing (existing VaultDepositor account): ${depositBN.toString()}`
|
|
90
|
+
);
|
|
91
|
+
const tx = await driftVault.deposit(vaultDepositorAddress, depositBN);
|
|
92
|
+
console.log(
|
|
93
|
+
`Deposited ${cmdOpts.amount} to vault: https://solana.fm/tx/${tx}${
|
|
94
|
+
driftClient.env === 'devnet' ? '?cluster=devnet-solana' : ''
|
|
95
|
+
}`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OptionValues, Command } from 'commander';
|
|
2
|
+
import { encodeName } from '@velocity-exchange/sdk';
|
|
3
|
+
import { VAULT_PROGRAM_ID, getVaultAddressSync } from '../../src';
|
|
4
|
+
|
|
5
|
+
export const deriveVaultAddress = async (
|
|
6
|
+
_program: Command,
|
|
7
|
+
cmdOpts: OptionValues
|
|
8
|
+
) => {
|
|
9
|
+
const vaultName = cmdOpts.vaultName;
|
|
10
|
+
const vaultNameBytes = encodeName(vaultName!);
|
|
11
|
+
const vaultAddress = getVaultAddressSync(VAULT_PROGRAM_ID, vaultNameBytes);
|
|
12
|
+
|
|
13
|
+
console.log(`Vault address: ${vaultAddress.toBase58()}`);
|
|
14
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import {
|
|
3
|
+
OptionValues,
|
|
4
|
+
Command
|
|
5
|
+
} from "commander";
|
|
6
|
+
import { getCommandContext } from "../utils";
|
|
7
|
+
import { getVaultDepositorAddressSync } from "../../src/addresses";
|
|
8
|
+
import { VAULT_PROGRAM_ID } from "../../src";
|
|
9
|
+
|
|
10
|
+
export const forceWithdraw = async (program: Command, cmdOpts: OptionValues) => {
|
|
11
|
+
|
|
12
|
+
let vaultDepositorAddress: PublicKey | undefined;
|
|
13
|
+
try {
|
|
14
|
+
vaultDepositorAddress = new PublicKey(cmdOpts.vaultDepositorAddress as string);
|
|
15
|
+
} catch (err) {
|
|
16
|
+
console.error("Failed to parse vaultDepositorAddress trying vaultDepositorAuthority");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let vaultDepositorAuthority: PublicKey | undefined;
|
|
20
|
+
try {
|
|
21
|
+
vaultDepositorAuthority = new PublicKey(cmdOpts.vaultDepositorAuthority as string);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
console.error("Failed to parse vaultDepositorAuthority");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!vaultDepositorAuthority && !vaultDepositorAddress) {
|
|
27
|
+
throw new Error("VaultDepositor address or authority must be provided");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let vaultAddress: PublicKey | undefined;
|
|
31
|
+
if (vaultDepositorAuthority && !vaultDepositorAddress) {
|
|
32
|
+
try {
|
|
33
|
+
vaultAddress = new PublicKey(cmdOpts.vaultAddress as string);
|
|
34
|
+
} catch (err) {
|
|
35
|
+
throw new Error("Must provide --vault-address if only --vault-depositor-authority is provided");
|
|
36
|
+
}
|
|
37
|
+
vaultDepositorAddress = getVaultDepositorAddressSync(
|
|
38
|
+
VAULT_PROGRAM_ID,
|
|
39
|
+
vaultAddress,
|
|
40
|
+
vaultDepositorAuthority);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!vaultDepositorAddress) {
|
|
44
|
+
throw new Error("Failed to derive vault depositor address");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const {
|
|
48
|
+
driftVault,
|
|
49
|
+
driftClient,
|
|
50
|
+
} = await getCommandContext(program, true);
|
|
51
|
+
|
|
52
|
+
const tx = await driftVault.forceWithdraw(vaultDepositorAddress, {
|
|
53
|
+
lookupTables: await driftClient.fetchAllLookupTableAccounts()
|
|
54
|
+
});
|
|
55
|
+
console.log(`Forced withdraw from vault: ${tx}`);
|
|
56
|
+
};
|