@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,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
|
+
};
|