@drift-labs/vaults-sdk 0.1.531 → 0.1.533
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 +6 -0
- package/cli/commands/applyProfitShare.ts +14 -16
- package/cli/commands/forceWithdrawAll.ts +101 -0
- package/cli/commands/index.ts +1 -0
- package/cli/utils.ts +2 -0
- package/lib/addresses.d.ts +3 -0
- package/lib/addresses.js +24 -0
- package/lib/types/drift_vaults.d.ts +673 -60
- package/lib/types/drift_vaults.js +668 -55
- package/lib/utils.d.ts +2 -1
- package/lib/utils.js +20 -1
- package/lib/vaultClient.d.ts +39 -8
- package/lib/vaultClient.js +347 -44
- package/package.json +2 -2
- package/src/addresses.ts +45 -0
- package/src/idl/drift_vaults.json +1527 -207
- package/src/types/drift_vaults.ts +1322 -96
- package/src/utils.ts +37 -1
- package/src/vaultClient.ts +642 -60
package/src/vaultClient.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BN,
|
|
3
3
|
DriftClient,
|
|
4
|
-
encodeName,
|
|
5
4
|
getInsuranceFundStakeAccountPublicKey,
|
|
6
5
|
getUserAccountPublicKey,
|
|
7
6
|
getUserAccountPublicKeySync,
|
|
@@ -10,15 +9,14 @@ import {
|
|
|
10
9
|
UserMap,
|
|
11
10
|
unstakeSharesToAmount as depositSharesToVaultAmount,
|
|
12
11
|
ZERO,
|
|
12
|
+
getInsuranceFundVaultPublicKey,
|
|
13
13
|
} from '@drift-labs/sdk';
|
|
14
14
|
import { BorshAccountsCoder, Program, ProgramAccount } from '@coral-xyz/anchor';
|
|
15
15
|
import { DriftVaults } from './types/drift_vaults';
|
|
16
16
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} from '@drift-labs/competitions-sdk';
|
|
21
|
-
import {
|
|
17
|
+
getTokenizedVaultAddressSync,
|
|
18
|
+
getTokenizedVaultMintAddressSync,
|
|
19
|
+
getInsuranceFundTokenVaultAddressSync,
|
|
22
20
|
getTokenVaultAddressSync,
|
|
23
21
|
getVaultAddressSync,
|
|
24
22
|
getVaultDepositorAddressSync,
|
|
@@ -30,6 +28,7 @@ import {
|
|
|
30
28
|
PublicKey,
|
|
31
29
|
SystemProgram,
|
|
32
30
|
SYSVAR_RENT_PUBKEY,
|
|
31
|
+
Transaction,
|
|
33
32
|
TransactionInstruction,
|
|
34
33
|
TransactionSignature,
|
|
35
34
|
VersionedTransaction,
|
|
@@ -51,6 +50,8 @@ import {
|
|
|
51
50
|
import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
|
|
52
51
|
import { UserMapConfig } from '@drift-labs/sdk';
|
|
53
52
|
import { calculateRealizedVaultDepositorEquity } from './math';
|
|
53
|
+
import { Metaplex } from '@metaplex-foundation/js';
|
|
54
|
+
import { getOrCreateATAInstruction } from './utils';
|
|
54
55
|
|
|
55
56
|
export type TxParams = {
|
|
56
57
|
cuLimit?: number;
|
|
@@ -61,6 +62,7 @@ export type TxParams = {
|
|
|
61
62
|
|
|
62
63
|
export class VaultClient {
|
|
63
64
|
driftClient: DriftClient;
|
|
65
|
+
metaplex?: Metaplex;
|
|
64
66
|
program: Program<DriftVaults>;
|
|
65
67
|
cliMode: boolean;
|
|
66
68
|
|
|
@@ -72,15 +74,18 @@ export class VaultClient {
|
|
|
72
74
|
constructor({
|
|
73
75
|
driftClient,
|
|
74
76
|
program,
|
|
77
|
+
metaplex,
|
|
75
78
|
cliMode,
|
|
76
79
|
userMapConfig,
|
|
77
80
|
}: {
|
|
78
81
|
driftClient: DriftClient;
|
|
79
82
|
program: Program<DriftVaults>;
|
|
83
|
+
metaplex?: Metaplex;
|
|
80
84
|
cliMode?: boolean;
|
|
81
85
|
userMapConfig?: UserMapConfig;
|
|
82
86
|
}) {
|
|
83
87
|
this.driftClient = driftClient;
|
|
88
|
+
this.metaplex = metaplex;
|
|
84
89
|
this.program = program;
|
|
85
90
|
this.cliMode = !!cliMode;
|
|
86
91
|
|
|
@@ -876,6 +881,111 @@ export class VaultClient {
|
|
|
876
881
|
});
|
|
877
882
|
}
|
|
878
883
|
|
|
884
|
+
public async getApplyRebaseTokenizedDepositorIx(
|
|
885
|
+
vault: PublicKey,
|
|
886
|
+
tokenizedVaultDepositor: PublicKey
|
|
887
|
+
): Promise<TransactionInstruction> {
|
|
888
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
889
|
+
|
|
890
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
891
|
+
|
|
892
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(
|
|
893
|
+
vaultAccount.spotMarketIndex
|
|
894
|
+
);
|
|
895
|
+
if (!spotMarket) {
|
|
896
|
+
throw new Error(
|
|
897
|
+
`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
902
|
+
userAccounts: [user.getUserAccount()],
|
|
903
|
+
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
const accounts = {
|
|
907
|
+
vault,
|
|
908
|
+
tokenizedVaultDepositor,
|
|
909
|
+
driftUser: await getUserAccountPublicKey(
|
|
910
|
+
this.driftClient.program.programId,
|
|
911
|
+
vault
|
|
912
|
+
),
|
|
913
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
914
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
915
|
+
driftProgram: this.driftClient.program.programId,
|
|
916
|
+
};
|
|
917
|
+
|
|
918
|
+
return this.program.instruction.applyRebaseTokenizedDepositor({
|
|
919
|
+
accounts: {
|
|
920
|
+
...accounts,
|
|
921
|
+
},
|
|
922
|
+
remainingAccounts,
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
public async applyRebase(
|
|
927
|
+
vault: PublicKey,
|
|
928
|
+
vaultDepositor: PublicKey
|
|
929
|
+
): Promise<TransactionSignature> {
|
|
930
|
+
return await this.createAndSendTxn([
|
|
931
|
+
await this.getApplyRebaseIx(vault, vaultDepositor),
|
|
932
|
+
]);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
public async getApplyRebaseIx(
|
|
936
|
+
vault: PublicKey,
|
|
937
|
+
vaultDepositor: PublicKey
|
|
938
|
+
): Promise<TransactionInstruction> {
|
|
939
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
940
|
+
|
|
941
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
942
|
+
|
|
943
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(
|
|
944
|
+
vaultAccount.spotMarketIndex
|
|
945
|
+
);
|
|
946
|
+
if (!spotMarket) {
|
|
947
|
+
throw new Error(
|
|
948
|
+
`Spot market ${vaultAccount.spotMarketIndex} not found on driftClient`
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
953
|
+
userAccounts: [user.getUserAccount()],
|
|
954
|
+
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
const accounts = {
|
|
958
|
+
vault,
|
|
959
|
+
vaultDepositor,
|
|
960
|
+
driftUser: await getUserAccountPublicKey(
|
|
961
|
+
this.driftClient.program.programId,
|
|
962
|
+
vault
|
|
963
|
+
),
|
|
964
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
965
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
966
|
+
driftProgram: this.driftClient.program.programId,
|
|
967
|
+
};
|
|
968
|
+
|
|
969
|
+
return this.program.instruction.applyRebase({
|
|
970
|
+
accounts: {
|
|
971
|
+
...accounts,
|
|
972
|
+
},
|
|
973
|
+
remainingAccounts,
|
|
974
|
+
});
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
public async applyRebaseTokenizedDepositor(
|
|
978
|
+
vault: PublicKey,
|
|
979
|
+
tokenizedVaultDepositor: PublicKey
|
|
980
|
+
): Promise<TransactionSignature> {
|
|
981
|
+
return await this.createAndSendTxn([
|
|
982
|
+
await this.getApplyRebaseTokenizedDepositorIx(
|
|
983
|
+
vault,
|
|
984
|
+
tokenizedVaultDepositor
|
|
985
|
+
),
|
|
986
|
+
]);
|
|
987
|
+
}
|
|
988
|
+
|
|
879
989
|
private createInitVaultDepositorIx(vault: PublicKey, authority?: PublicKey) {
|
|
880
990
|
const vaultDepositor = getVaultDepositorAddressSync(
|
|
881
991
|
this.program.programId,
|
|
@@ -924,9 +1034,14 @@ export class VaultClient {
|
|
|
924
1034
|
};
|
|
925
1035
|
|
|
926
1036
|
if (this.cliMode) {
|
|
927
|
-
return
|
|
1037
|
+
return this.program.methods
|
|
928
1038
|
.initializeVaultDepositor()
|
|
929
|
-
.accounts(
|
|
1039
|
+
.accounts({
|
|
1040
|
+
...accounts,
|
|
1041
|
+
payer: authority || this.driftClient.wallet.publicKey,
|
|
1042
|
+
rent: SYSVAR_RENT_PUBKEY,
|
|
1043
|
+
systemProgram: SystemProgram.programId,
|
|
1044
|
+
})
|
|
930
1045
|
.rpc();
|
|
931
1046
|
} else {
|
|
932
1047
|
const initIx = this.createInitVaultDepositorIx(vault, authority);
|
|
@@ -934,13 +1049,297 @@ export class VaultClient {
|
|
|
934
1049
|
}
|
|
935
1050
|
}
|
|
936
1051
|
|
|
1052
|
+
public async initializeTokenizedVaultDepositor(params: {
|
|
1053
|
+
vault: PublicKey;
|
|
1054
|
+
tokenName: string;
|
|
1055
|
+
tokenSymbol: string;
|
|
1056
|
+
tokenUri: string;
|
|
1057
|
+
decimals?: number;
|
|
1058
|
+
sharesBase?: number;
|
|
1059
|
+
}): Promise<TransactionSignature> {
|
|
1060
|
+
if (!this.metaplex) {
|
|
1061
|
+
throw new Error(
|
|
1062
|
+
'Metaplex instance is required when constructing VaultClient to initialize a tokenized vault depositor'
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
let spotMarketDecimals = 6;
|
|
1067
|
+
let sharesBase = 0;
|
|
1068
|
+
if (params.decimals === undefined || params.sharesBase === undefined) {
|
|
1069
|
+
const vault = await this.program.account.vault.fetch(params.vault);
|
|
1070
|
+
const spotMarketAccount = this.driftClient.getSpotMarketAccount(
|
|
1071
|
+
vault.spotMarketIndex
|
|
1072
|
+
);
|
|
1073
|
+
if (!spotMarketAccount) {
|
|
1074
|
+
throw new Error(
|
|
1075
|
+
`DriftClient failed to load vault's spot market (marketIndex: ${vault.spotMarketIndex})`
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
spotMarketDecimals = spotMarketAccount.decimals;
|
|
1079
|
+
sharesBase = vault.sharesBase;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
const mintAddress = getTokenizedVaultMintAddressSync(
|
|
1083
|
+
this.program.programId,
|
|
1084
|
+
params.vault,
|
|
1085
|
+
sharesBase
|
|
1086
|
+
);
|
|
1087
|
+
|
|
1088
|
+
const accounts = {
|
|
1089
|
+
vault: params.vault,
|
|
1090
|
+
vaultDepositor: getTokenizedVaultAddressSync(
|
|
1091
|
+
this.program.programId,
|
|
1092
|
+
params.vault,
|
|
1093
|
+
sharesBase
|
|
1094
|
+
),
|
|
1095
|
+
mintAccount: mintAddress,
|
|
1096
|
+
metadataAccount: this.metaplex.nfts().pdas().metadata({
|
|
1097
|
+
mint: mintAddress,
|
|
1098
|
+
}),
|
|
1099
|
+
tokenMetadataProgram: this.metaplex.programs().getTokenMetadata().address,
|
|
1100
|
+
payer: this.driftClient.wallet.publicKey,
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
const vaultTokenAta = getAssociatedTokenAddressSync(
|
|
1104
|
+
mintAddress,
|
|
1105
|
+
params.vault,
|
|
1106
|
+
true
|
|
1107
|
+
);
|
|
1108
|
+
const createAtaIx = createAssociatedTokenAccountInstruction(
|
|
1109
|
+
this.driftClient.wallet.publicKey,
|
|
1110
|
+
vaultTokenAta,
|
|
1111
|
+
params.vault,
|
|
1112
|
+
mintAddress
|
|
1113
|
+
);
|
|
1114
|
+
|
|
1115
|
+
if (!this.cliMode) {
|
|
1116
|
+
throw new Error(
|
|
1117
|
+
'CLI mode is not supported for initializeTokenizedVaultDepositor'
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
return await this.program.methods
|
|
1121
|
+
.initializeTokenizedVaultDepositor({
|
|
1122
|
+
...params,
|
|
1123
|
+
decimals: params.decimals ?? spotMarketDecimals,
|
|
1124
|
+
})
|
|
1125
|
+
.preInstructions([
|
|
1126
|
+
ComputeBudgetProgram.setComputeUnitPrice({
|
|
1127
|
+
microLamports: 50_000,
|
|
1128
|
+
}),
|
|
1129
|
+
])
|
|
1130
|
+
.postInstructions([createAtaIx])
|
|
1131
|
+
.accounts(accounts)
|
|
1132
|
+
.rpc();
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
public async createTokenizeSharesIx(
|
|
1136
|
+
vaultDepositor: PublicKey,
|
|
1137
|
+
amount: BN,
|
|
1138
|
+
unit: WithdrawUnit,
|
|
1139
|
+
mint?: PublicKey
|
|
1140
|
+
): Promise<TransactionInstruction[]> {
|
|
1141
|
+
const vaultDepositorAccount =
|
|
1142
|
+
await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1143
|
+
const vaultAccount = await this.program.account.vault.fetch(
|
|
1144
|
+
vaultDepositorAccount.vault
|
|
1145
|
+
);
|
|
1146
|
+
|
|
1147
|
+
mint =
|
|
1148
|
+
mint ??
|
|
1149
|
+
getTokenizedVaultMintAddressSync(
|
|
1150
|
+
this.program.programId,
|
|
1151
|
+
vaultDepositorAccount.vault,
|
|
1152
|
+
vaultAccount.sharesBase
|
|
1153
|
+
);
|
|
1154
|
+
|
|
1155
|
+
const userAta = getAssociatedTokenAddressSync(
|
|
1156
|
+
mint,
|
|
1157
|
+
this.driftClient.wallet.publicKey,
|
|
1158
|
+
true
|
|
1159
|
+
);
|
|
1160
|
+
|
|
1161
|
+
const ixs = [];
|
|
1162
|
+
|
|
1163
|
+
const userAtaExists = await this.driftClient.connection.getAccountInfo(
|
|
1164
|
+
userAta
|
|
1165
|
+
);
|
|
1166
|
+
if (userAtaExists === null) {
|
|
1167
|
+
ixs.push(
|
|
1168
|
+
createAssociatedTokenAccountInstruction(
|
|
1169
|
+
this.driftClient.wallet.publicKey,
|
|
1170
|
+
userAta,
|
|
1171
|
+
this.driftClient.wallet.publicKey,
|
|
1172
|
+
mint
|
|
1173
|
+
)
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1178
|
+
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
1179
|
+
userAccounts: [user.getUserAccount()],
|
|
1180
|
+
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
1181
|
+
});
|
|
1182
|
+
|
|
1183
|
+
ixs.push(
|
|
1184
|
+
await this.program.methods
|
|
1185
|
+
// anchor idl bug: https://github.com/coral-xyz/anchor/issues/2914
|
|
1186
|
+
// @ts-ignore
|
|
1187
|
+
.tokenizeShares(amount, unit)
|
|
1188
|
+
.accounts({
|
|
1189
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1190
|
+
vault: vaultDepositorAccount.vault,
|
|
1191
|
+
vaultDepositor,
|
|
1192
|
+
tokenizedVaultDepositor: getTokenizedVaultAddressSync(
|
|
1193
|
+
this.program.programId,
|
|
1194
|
+
vaultDepositorAccount.vault,
|
|
1195
|
+
vaultAccount.sharesBase
|
|
1196
|
+
),
|
|
1197
|
+
mint,
|
|
1198
|
+
userTokenAccount: userAta,
|
|
1199
|
+
driftUser: vaultAccount.user,
|
|
1200
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1201
|
+
})
|
|
1202
|
+
.remainingAccounts(remainingAccounts)
|
|
1203
|
+
.instruction()
|
|
1204
|
+
);
|
|
1205
|
+
|
|
1206
|
+
return ixs;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
public async tokenizeShares(
|
|
1210
|
+
vaultDepositor: PublicKey,
|
|
1211
|
+
amount: BN,
|
|
1212
|
+
unit: WithdrawUnit,
|
|
1213
|
+
mint?: PublicKey,
|
|
1214
|
+
txParams?: TxParams
|
|
1215
|
+
): Promise<TransactionSignature> {
|
|
1216
|
+
const ixs = await this.createTokenizeSharesIx(
|
|
1217
|
+
vaultDepositor,
|
|
1218
|
+
amount,
|
|
1219
|
+
unit,
|
|
1220
|
+
mint
|
|
1221
|
+
);
|
|
1222
|
+
if (this.cliMode) {
|
|
1223
|
+
try {
|
|
1224
|
+
const tx = new Transaction().add(...ixs);
|
|
1225
|
+
const txSig = await this.driftClient.txSender.send(
|
|
1226
|
+
tx,
|
|
1227
|
+
undefined,
|
|
1228
|
+
undefined,
|
|
1229
|
+
false
|
|
1230
|
+
);
|
|
1231
|
+
return txSig.txSig;
|
|
1232
|
+
} catch (e) {
|
|
1233
|
+
console.error(e);
|
|
1234
|
+
throw e;
|
|
1235
|
+
}
|
|
1236
|
+
} else {
|
|
1237
|
+
return await this.createAndSendTxn(ixs, txParams);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
public async createRedeemTokensIx(
|
|
1242
|
+
vaultDepositor: PublicKey,
|
|
1243
|
+
tokensToBurn: BN,
|
|
1244
|
+
sharesBase?: number
|
|
1245
|
+
): Promise<TransactionInstruction> {
|
|
1246
|
+
const vaultDepositorAccount =
|
|
1247
|
+
await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1248
|
+
const vaultAccount = await this.program.account.vault.fetch(
|
|
1249
|
+
vaultDepositorAccount.vault
|
|
1250
|
+
);
|
|
1251
|
+
|
|
1252
|
+
const mint = getTokenizedVaultMintAddressSync(
|
|
1253
|
+
this.program.programId,
|
|
1254
|
+
vaultDepositorAccount.vault,
|
|
1255
|
+
sharesBase ?? vaultAccount.sharesBase
|
|
1256
|
+
);
|
|
1257
|
+
|
|
1258
|
+
const userAta = getAssociatedTokenAddressSync(
|
|
1259
|
+
mint,
|
|
1260
|
+
this.driftClient.wallet.publicKey,
|
|
1261
|
+
true
|
|
1262
|
+
);
|
|
1263
|
+
|
|
1264
|
+
const vaultTokenAta = getAssociatedTokenAddressSync(
|
|
1265
|
+
mint,
|
|
1266
|
+
vaultDepositorAccount.vault,
|
|
1267
|
+
true
|
|
1268
|
+
);
|
|
1269
|
+
|
|
1270
|
+
const user = await this.getSubscribedVaultUser(vaultAccount.user);
|
|
1271
|
+
const remainingAccounts = this.driftClient.getRemainingAccounts({
|
|
1272
|
+
userAccounts: [user.getUserAccount()],
|
|
1273
|
+
writableSpotMarketIndexes: [vaultAccount.spotMarketIndex],
|
|
1274
|
+
});
|
|
1275
|
+
|
|
1276
|
+
return await this.program.methods
|
|
1277
|
+
.redeemTokens(tokensToBurn)
|
|
1278
|
+
.accounts({
|
|
1279
|
+
authority: this.driftClient.wallet.publicKey,
|
|
1280
|
+
vault: vaultDepositorAccount.vault,
|
|
1281
|
+
vaultDepositor,
|
|
1282
|
+
tokenizedVaultDepositor: getTokenizedVaultAddressSync(
|
|
1283
|
+
this.program.programId,
|
|
1284
|
+
vaultDepositorAccount.vault,
|
|
1285
|
+
sharesBase ?? vaultAccount.sharesBase
|
|
1286
|
+
),
|
|
1287
|
+
mint,
|
|
1288
|
+
userTokenAccount: userAta,
|
|
1289
|
+
vaultTokenAccount: vaultTokenAta,
|
|
1290
|
+
driftUser: vaultAccount.user,
|
|
1291
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1292
|
+
})
|
|
1293
|
+
.remainingAccounts(remainingAccounts)
|
|
1294
|
+
.instruction();
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
/**
|
|
1298
|
+
* Redeems tokens from the vault.
|
|
1299
|
+
* @param vaultDepositor
|
|
1300
|
+
* @param tokensToBurn
|
|
1301
|
+
* @param mint optionally provide a mint, or infer the mint from the current vault share base
|
|
1302
|
+
* @param txParams
|
|
1303
|
+
* @returns
|
|
1304
|
+
*/
|
|
1305
|
+
public async redeemTokens(
|
|
1306
|
+
vaultDepositor: PublicKey,
|
|
1307
|
+
tokensToBurn: BN,
|
|
1308
|
+
sharesBase?: number,
|
|
1309
|
+
txParams?: TxParams
|
|
1310
|
+
): Promise<TransactionSignature> {
|
|
1311
|
+
const ix = await this.createRedeemTokensIx(
|
|
1312
|
+
vaultDepositor,
|
|
1313
|
+
tokensToBurn,
|
|
1314
|
+
sharesBase
|
|
1315
|
+
);
|
|
1316
|
+
if (this.cliMode) {
|
|
1317
|
+
try {
|
|
1318
|
+
const tx = new Transaction().add(ix);
|
|
1319
|
+
const txSig = await this.driftClient.txSender.send(
|
|
1320
|
+
tx,
|
|
1321
|
+
undefined,
|
|
1322
|
+
undefined,
|
|
1323
|
+
false
|
|
1324
|
+
);
|
|
1325
|
+
return txSig.txSig;
|
|
1326
|
+
} catch (e) {
|
|
1327
|
+
console.error(e);
|
|
1328
|
+
throw e;
|
|
1329
|
+
}
|
|
1330
|
+
} else {
|
|
1331
|
+
return await this.createAndSendTxn([ix], txParams);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
|
|
937
1335
|
public async prepDepositTx(
|
|
938
1336
|
vaultDepositor: PublicKey,
|
|
939
1337
|
amount: BN,
|
|
940
1338
|
initVaultDepositor?: {
|
|
941
1339
|
authority: PublicKey;
|
|
942
1340
|
vault: PublicKey;
|
|
943
|
-
}
|
|
1341
|
+
},
|
|
1342
|
+
userTokenAccount?: PublicKey
|
|
944
1343
|
) {
|
|
945
1344
|
let vaultPubKey: PublicKey;
|
|
946
1345
|
if (initVaultDepositor) {
|
|
@@ -991,11 +1390,13 @@ export class VaultClient {
|
|
|
991
1390
|
driftUser: vaultAccount.user,
|
|
992
1391
|
driftState: driftStateKey,
|
|
993
1392
|
driftSpotMarketVault: spotMarket.vault,
|
|
994
|
-
userTokenAccount:
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1393
|
+
userTokenAccount:
|
|
1394
|
+
userTokenAccount ??
|
|
1395
|
+
getAssociatedTokenAddressSync(
|
|
1396
|
+
spotMarket.mint,
|
|
1397
|
+
this.driftClient.wallet.publicKey,
|
|
1398
|
+
true
|
|
1399
|
+
),
|
|
999
1400
|
driftProgram: this.driftClient.program.programId,
|
|
1000
1401
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1001
1402
|
};
|
|
@@ -1067,11 +1468,17 @@ export class VaultClient {
|
|
|
1067
1468
|
authority: PublicKey;
|
|
1068
1469
|
vault: PublicKey;
|
|
1069
1470
|
},
|
|
1070
|
-
txParams?: TxParams
|
|
1471
|
+
txParams?: TxParams,
|
|
1472
|
+
userTokenAccount?: PublicKey
|
|
1071
1473
|
): Promise<TransactionSignature> {
|
|
1072
1474
|
if (this.cliMode) {
|
|
1073
1475
|
const { vaultAccount, accounts, remainingAccounts } =
|
|
1074
|
-
await this.prepDepositTx(
|
|
1476
|
+
await this.prepDepositTx(
|
|
1477
|
+
vaultDepositor,
|
|
1478
|
+
amount,
|
|
1479
|
+
initVaultDepositor,
|
|
1480
|
+
userTokenAccount
|
|
1481
|
+
);
|
|
1075
1482
|
|
|
1076
1483
|
if (initVaultDepositor) {
|
|
1077
1484
|
await this.initializeVaultDepositor(
|
|
@@ -1079,7 +1486,7 @@ export class VaultClient {
|
|
|
1079
1486
|
initVaultDepositor.authority
|
|
1080
1487
|
);
|
|
1081
1488
|
}
|
|
1082
|
-
return
|
|
1489
|
+
return this.program.methods
|
|
1083
1490
|
.deposit(amount)
|
|
1084
1491
|
.accounts(accounts)
|
|
1085
1492
|
.remainingAccounts(remainingAccounts)
|
|
@@ -1278,6 +1685,13 @@ export class VaultClient {
|
|
|
1278
1685
|
public async forceWithdraw(
|
|
1279
1686
|
vaultDepositor: PublicKey
|
|
1280
1687
|
): Promise<TransactionSignature> {
|
|
1688
|
+
const ix = await this.getForceWithdrawIx(vaultDepositor);
|
|
1689
|
+
return await this.createAndSendTxn(ix);
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
public async getForceWithdrawIx(
|
|
1693
|
+
vaultDepositor: PublicKey
|
|
1694
|
+
): Promise<TransactionInstruction[]> {
|
|
1281
1695
|
const vaultDepositorAccount =
|
|
1282
1696
|
await this.program.account.vaultDepositor.fetch(vaultDepositor);
|
|
1283
1697
|
const vaultAccount = await this.program.account.vault.fetch(
|
|
@@ -1316,6 +1730,20 @@ export class VaultClient {
|
|
|
1316
1730
|
);
|
|
1317
1731
|
}
|
|
1318
1732
|
|
|
1733
|
+
const [userTokenAccount, createAtaIx] = await getOrCreateATAInstruction(
|
|
1734
|
+
spotMarket.mint,
|
|
1735
|
+
vaultDepositorAccount.authority,
|
|
1736
|
+
this.driftClient.connection,
|
|
1737
|
+
true,
|
|
1738
|
+
this.driftClient.wallet.publicKey
|
|
1739
|
+
);
|
|
1740
|
+
|
|
1741
|
+
if (createAtaIx) {
|
|
1742
|
+
console.log(
|
|
1743
|
+
`Creating ATA for ${vaultDepositorAccount.authority.toBase58()} to ${userTokenAccount.toBase58()}`
|
|
1744
|
+
);
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1319
1747
|
const accounts = {
|
|
1320
1748
|
manager: this.driftClient.wallet.publicKey,
|
|
1321
1749
|
vault: vaultDepositorAccount.vault,
|
|
@@ -1326,38 +1754,26 @@ export class VaultClient {
|
|
|
1326
1754
|
driftState: driftStateKey,
|
|
1327
1755
|
driftSpotMarketVault: spotMarket.vault,
|
|
1328
1756
|
driftSigner: this.driftClient.getStateAccount().signer,
|
|
1329
|
-
userTokenAccount
|
|
1330
|
-
spotMarket.mint,
|
|
1331
|
-
vaultDepositorAccount.authority,
|
|
1332
|
-
true
|
|
1333
|
-
),
|
|
1757
|
+
userTokenAccount,
|
|
1334
1758
|
driftProgram: this.driftClient.program.programId,
|
|
1335
1759
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1336
1760
|
};
|
|
1337
1761
|
|
|
1338
|
-
|
|
1339
|
-
|
|
1762
|
+
const ixs = [];
|
|
1763
|
+
|
|
1764
|
+
if (createAtaIx) {
|
|
1765
|
+
ixs.push(createAtaIx);
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
ixs.push(
|
|
1769
|
+
await this.program.methods
|
|
1340
1770
|
.forceWithdraw()
|
|
1341
|
-
.preInstructions([
|
|
1342
|
-
ComputeBudgetProgram.setComputeUnitLimit({
|
|
1343
|
-
units: 500_000,
|
|
1344
|
-
}),
|
|
1345
|
-
ComputeBudgetProgram.setComputeUnitPrice({
|
|
1346
|
-
microLamports: 50_000,
|
|
1347
|
-
}),
|
|
1348
|
-
])
|
|
1349
1771
|
.accounts(accounts)
|
|
1350
1772
|
.remainingAccounts(remainingAccounts)
|
|
1351
|
-
.
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
...accounts,
|
|
1356
|
-
},
|
|
1357
|
-
remainingAccounts,
|
|
1358
|
-
});
|
|
1359
|
-
return await this.createAndSendTxn([forceWithdrawIx]);
|
|
1360
|
-
}
|
|
1773
|
+
.instruction()
|
|
1774
|
+
);
|
|
1775
|
+
|
|
1776
|
+
return ixs;
|
|
1361
1777
|
}
|
|
1362
1778
|
|
|
1363
1779
|
public async cancelRequestWithdraw(
|
|
@@ -1580,11 +1996,19 @@ export class VaultClient {
|
|
|
1580
1996
|
);
|
|
1581
1997
|
}
|
|
1582
1998
|
|
|
1999
|
+
const ifVaultTokenAccount = getInsuranceFundTokenVaultAddressSync(
|
|
2000
|
+
this.program.programId,
|
|
2001
|
+
vault,
|
|
2002
|
+
spotMarketIndex
|
|
2003
|
+
);
|
|
2004
|
+
|
|
1583
2005
|
return await this.program.methods
|
|
1584
2006
|
.initializeInsuranceFundStake(spotMarketIndex)
|
|
1585
2007
|
.accounts({
|
|
1586
2008
|
vault: vault,
|
|
1587
2009
|
driftSpotMarket: spotMarket.pubkey,
|
|
2010
|
+
driftSpotMarketMint: spotMarket.mint,
|
|
2011
|
+
vaultTokenAccount: ifVaultTokenAccount,
|
|
1588
2012
|
insuranceFundStake: ifStakeAccountPublicKey,
|
|
1589
2013
|
driftUserStats: vaultAccount.userStats,
|
|
1590
2014
|
driftState: await this.driftClient.getStatePublicKey(),
|
|
@@ -1594,38 +2018,196 @@ export class VaultClient {
|
|
|
1594
2018
|
}
|
|
1595
2019
|
|
|
1596
2020
|
/**
|
|
1597
|
-
*
|
|
1598
|
-
* @param vault vault address to
|
|
1599
|
-
* @param
|
|
2021
|
+
* Adds an amount to an insurance fund stake for the vault.
|
|
2022
|
+
* @param vault vault address to update
|
|
2023
|
+
* @param spotMarketIndex spot market index of the insurance fund stake
|
|
2024
|
+
* @param amount amount to add to the insurance fund stake, in spotMarketIndex precision
|
|
1600
2025
|
* @returns
|
|
1601
2026
|
*/
|
|
1602
|
-
public async
|
|
2027
|
+
public async addToInsuranceFundStake(
|
|
1603
2028
|
vault: PublicKey,
|
|
1604
|
-
|
|
1605
|
-
|
|
2029
|
+
spotMarketIndex: number,
|
|
2030
|
+
amount: BN,
|
|
2031
|
+
managerTokenAccount?: PublicKey
|
|
1606
2032
|
): Promise<TransactionSignature> {
|
|
1607
2033
|
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
1608
2034
|
|
|
1609
|
-
|
|
2035
|
+
if (!vaultAccount.manager.equals(this.driftClient.wallet.publicKey)) {
|
|
2036
|
+
throw new Error(
|
|
2037
|
+
`Only the manager of the vault can add to the insurance fund stake.`
|
|
2038
|
+
);
|
|
2039
|
+
}
|
|
1610
2040
|
|
|
1611
|
-
const
|
|
1612
|
-
|
|
1613
|
-
|
|
2041
|
+
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2042
|
+
this.driftClient.program.programId,
|
|
2043
|
+
vault,
|
|
2044
|
+
spotMarketIndex
|
|
1614
2045
|
);
|
|
1615
|
-
const
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
2046
|
+
const ifVaultPublicKey = await getInsuranceFundVaultPublicKey(
|
|
2047
|
+
this.driftClient.program.programId,
|
|
2048
|
+
spotMarketIndex
|
|
2049
|
+
);
|
|
2050
|
+
|
|
2051
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex);
|
|
2052
|
+
if (!spotMarket) {
|
|
2053
|
+
throw new Error(
|
|
2054
|
+
`Spot market ${spotMarketIndex} not found on driftClient`
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
if (!managerTokenAccount) {
|
|
2059
|
+
managerTokenAccount = getAssociatedTokenAddressSync(
|
|
2060
|
+
spotMarket.mint,
|
|
2061
|
+
this.driftClient.wallet.publicKey
|
|
2062
|
+
);
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
const ifVaultTokenAccount = getInsuranceFundTokenVaultAddressSync(
|
|
2066
|
+
this.program.programId,
|
|
2067
|
+
vault,
|
|
2068
|
+
spotMarketIndex
|
|
1619
2069
|
);
|
|
1620
2070
|
|
|
1621
2071
|
return await this.program.methods
|
|
1622
|
-
.
|
|
2072
|
+
.addInsuranceFundStake(spotMarketIndex, amount)
|
|
1623
2073
|
.accounts({
|
|
1624
2074
|
vault: vault,
|
|
1625
|
-
|
|
1626
|
-
|
|
2075
|
+
driftSpotMarket: spotMarket.pubkey,
|
|
2076
|
+
driftSpotMarketVault: spotMarket.vault,
|
|
2077
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2078
|
+
insuranceFundVault: ifVaultPublicKey,
|
|
2079
|
+
managerTokenAccount,
|
|
2080
|
+
vaultIfTokenAccount: ifVaultTokenAccount,
|
|
1627
2081
|
driftUserStats: vaultAccount.userStats,
|
|
1628
|
-
|
|
2082
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
2083
|
+
driftProgram: this.driftClient.program.programId,
|
|
2084
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
2085
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
2086
|
+
})
|
|
2087
|
+
.rpc();
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
public async requestRemoveInsuranceFundStake(
|
|
2091
|
+
vault: PublicKey,
|
|
2092
|
+
spotMarketIndex: number,
|
|
2093
|
+
amount: BN
|
|
2094
|
+
): Promise<TransactionSignature> {
|
|
2095
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
2096
|
+
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2097
|
+
this.driftClient.program.programId,
|
|
2098
|
+
vault,
|
|
2099
|
+
spotMarketIndex
|
|
2100
|
+
);
|
|
2101
|
+
const ifVaultPublicKey = await getInsuranceFundVaultPublicKey(
|
|
2102
|
+
this.driftClient.program.programId,
|
|
2103
|
+
spotMarketIndex
|
|
2104
|
+
);
|
|
2105
|
+
|
|
2106
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex);
|
|
2107
|
+
if (!spotMarket) {
|
|
2108
|
+
throw new Error(
|
|
2109
|
+
`Spot market ${spotMarketIndex} not found on driftClient`
|
|
2110
|
+
);
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
return await this.program.methods
|
|
2114
|
+
.requestRemoveInsuranceFundStake(spotMarketIndex, amount)
|
|
2115
|
+
.accounts({
|
|
2116
|
+
vault,
|
|
2117
|
+
manager: this.driftClient.wallet.publicKey,
|
|
2118
|
+
driftSpotMarket: spotMarket.pubkey,
|
|
2119
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2120
|
+
insuranceFundVault: ifVaultPublicKey,
|
|
2121
|
+
driftUserStats: vaultAccount.userStats,
|
|
2122
|
+
driftProgram: this.driftClient.program.programId,
|
|
2123
|
+
})
|
|
2124
|
+
.rpc();
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
public async cancelRequestRemoveInsuranceFundStake(
|
|
2128
|
+
vault: PublicKey,
|
|
2129
|
+
spotMarketIndex: number
|
|
2130
|
+
): Promise<TransactionSignature> {
|
|
2131
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
2132
|
+
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2133
|
+
this.driftClient.program.programId,
|
|
2134
|
+
vault,
|
|
2135
|
+
spotMarketIndex
|
|
2136
|
+
);
|
|
2137
|
+
const ifVaultPublicKey = await getInsuranceFundVaultPublicKey(
|
|
2138
|
+
this.driftClient.program.programId,
|
|
2139
|
+
spotMarketIndex
|
|
2140
|
+
);
|
|
2141
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex);
|
|
2142
|
+
if (!spotMarket) {
|
|
2143
|
+
throw new Error(
|
|
2144
|
+
`Spot market ${spotMarketIndex} not found on driftClient`
|
|
2145
|
+
);
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
return await this.program.methods
|
|
2149
|
+
.cancelRequestRemoveInsuranceFundStake(spotMarketIndex)
|
|
2150
|
+
.accounts({
|
|
2151
|
+
vault: vault,
|
|
2152
|
+
manager: this.driftClient.wallet.publicKey,
|
|
2153
|
+
driftSpotMarket: spotMarket.pubkey,
|
|
2154
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2155
|
+
insuranceFundVault: ifVaultPublicKey,
|
|
2156
|
+
driftUserStats: vaultAccount.userStats,
|
|
2157
|
+
driftProgram: this.driftClient.program.programId,
|
|
2158
|
+
})
|
|
2159
|
+
.rpc();
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
public async removeInsuranceFundStake(
|
|
2163
|
+
vault: PublicKey,
|
|
2164
|
+
spotMarketIndex: number,
|
|
2165
|
+
managerTokenAccount?: PublicKey
|
|
2166
|
+
): Promise<TransactionSignature> {
|
|
2167
|
+
const vaultAccount = await this.program.account.vault.fetch(vault);
|
|
2168
|
+
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2169
|
+
this.driftClient.program.programId,
|
|
2170
|
+
vault,
|
|
2171
|
+
spotMarketIndex
|
|
2172
|
+
);
|
|
2173
|
+
const ifVaultPublicKey = await getInsuranceFundVaultPublicKey(
|
|
2174
|
+
this.driftClient.program.programId,
|
|
2175
|
+
spotMarketIndex
|
|
2176
|
+
);
|
|
2177
|
+
const spotMarket = this.driftClient.getSpotMarketAccount(spotMarketIndex);
|
|
2178
|
+
if (!spotMarket) {
|
|
2179
|
+
throw new Error(
|
|
2180
|
+
`Spot market ${spotMarketIndex} not found on driftClient`
|
|
2181
|
+
);
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
if (!managerTokenAccount) {
|
|
2185
|
+
managerTokenAccount = getAssociatedTokenAddressSync(
|
|
2186
|
+
spotMarket.mint,
|
|
2187
|
+
this.driftClient.wallet.publicKey
|
|
2188
|
+
);
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
const ifVaultTokenAccount = getInsuranceFundTokenVaultAddressSync(
|
|
2192
|
+
this.program.programId,
|
|
2193
|
+
vault,
|
|
2194
|
+
spotMarketIndex
|
|
2195
|
+
);
|
|
2196
|
+
|
|
2197
|
+
return await this.program.methods
|
|
2198
|
+
.removeInsuranceFundStake(spotMarketIndex)
|
|
2199
|
+
.accounts({
|
|
2200
|
+
vault: vault,
|
|
2201
|
+
driftSpotMarket: spotMarket.pubkey,
|
|
2202
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2203
|
+
insuranceFundVault: ifVaultPublicKey,
|
|
2204
|
+
managerTokenAccount,
|
|
2205
|
+
vaultIfTokenAccount: ifVaultTokenAccount,
|
|
2206
|
+
driftState: await this.driftClient.getStatePublicKey(),
|
|
2207
|
+
driftUserStats: vaultAccount.userStats,
|
|
2208
|
+
driftSigner: this.driftClient.getStateAccount().signer,
|
|
2209
|
+
driftProgram: this.driftClient.program.programId,
|
|
2210
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1629
2211
|
})
|
|
1630
2212
|
.rpc();
|
|
1631
2213
|
}
|