@drift-labs/sdk 0.2.0-master.2 → 0.2.0-master.22
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/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/accounts/bulkUserSubscription.js +0 -1
- package/lib/accounts/fetch.d.ts +2 -1
- package/lib/accounts/fetch.js +9 -1
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +14 -1
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/pda.d.ts +1 -0
- package/lib/addresses/pda.js +8 -1
- package/lib/admin.d.ts +9 -5
- package/lib/admin.js +52 -11
- package/lib/clearingHouse.d.ts +52 -23
- package/lib/clearingHouse.js +736 -200
- package/lib/clearingHouseConfig.d.ts +1 -0
- package/lib/clearingHouseUser.d.ts +24 -16
- package/lib/clearingHouseUser.js +223 -101
- package/lib/clearingHouseUserStats.d.ts +18 -0
- package/lib/clearingHouseUserStats.js +49 -0
- package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
- package/lib/clearingHouseUserStatsConfig.js +2 -0
- package/lib/config.js +1 -1
- package/lib/constants/banks.d.ts +2 -2
- package/lib/constants/banks.js +12 -4
- package/lib/constants/numericConstants.d.ts +5 -0
- package/lib/constants/numericConstants.js +8 -3
- package/lib/events/eventList.js +3 -0
- package/lib/events/types.d.ts +3 -1
- package/lib/events/types.js +2 -0
- package/lib/factory/bigNum.d.ts +1 -0
- package/lib/factory/bigNum.js +34 -10
- package/lib/idl/clearing_house.json +1603 -377
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +9 -3
- package/lib/index.js +13 -3
- package/lib/math/amm.d.ts +1 -0
- package/lib/math/amm.js +22 -38
- package/lib/math/auction.js +4 -1
- package/lib/math/bankBalance.d.ts +7 -1
- package/lib/math/bankBalance.js +77 -2
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +72 -0
- package/lib/math/market.d.ts +4 -1
- package/lib/math/market.js +35 -1
- package/lib/math/oracles.d.ts +3 -0
- package/lib/math/oracles.js +25 -5
- package/lib/math/orders.d.ts +6 -2
- package/lib/math/orders.js +62 -12
- package/lib/math/position.d.ts +8 -0
- package/lib/math/position.js +45 -12
- package/lib/math/trade.d.ts +1 -1
- package/lib/math/trade.js +7 -10
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +8 -96
- package/lib/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.js +9 -2
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +236 -26
- package/lib/types.js +64 -1
- package/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +3 -3
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +0 -1
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +18 -0
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.js +26 -0
- package/src/addresses/pda.ts +13 -0
- package/src/admin.ts +82 -15
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +1232 -323
- package/src/clearingHouseConfig.ts +1 -0
- package/src/clearingHouseUser.ts +343 -155
- package/src/clearingHouseUserStats.ts +75 -0
- package/src/clearingHouseUserStatsConfig.ts +18 -0
- package/src/config.ts +1 -1
- package/src/constants/banks.js +42 -0
- package/src/constants/banks.ts +14 -4
- package/src/constants/markets.js +42 -0
- package/src/constants/numericConstants.js +41 -0
- package/src/constants/numericConstants.ts +14 -2
- package/src/events/eventList.js +77 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/eventSubscriber.js +139 -0
- package/src/events/sort.js +44 -0
- package/src/events/txEventCache.js +71 -0
- package/src/events/types.ts +6 -0
- package/src/examples/makeTradeExample.js +80 -0
- package/src/factory/bigNum.js +390 -0
- package/src/factory/bigNum.ts +42 -13
- package/src/factory/oracleClient.js +20 -0
- package/src/idl/clearing_house.json +1603 -377
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.ts +9 -3
- package/src/math/amm.ts +54 -55
- package/src/math/auction.js +42 -0
- package/src/math/auction.ts +5 -1
- package/src/math/bankBalance.ts +148 -2
- package/src/math/conversion.js +11 -0
- package/src/math/funding.js +248 -0
- package/src/math/margin.ts +124 -0
- package/src/math/market.ts +66 -1
- package/src/math/oracles.js +26 -0
- package/src/math/oracles.ts +42 -5
- package/src/math/orders.ts +129 -13
- package/src/math/position.ts +64 -9
- package/src/math/repeg.js +128 -0
- package/src/math/state.js +15 -0
- package/src/math/trade.js +253 -0
- package/src/math/trade.ts +23 -25
- package/src/math/utils.js +0 -1
- package/src/oracles/oracleClientCache.js +19 -0
- package/src/oracles/pythClient.js +46 -0
- package/src/oracles/quoteAssetOracleClient.js +32 -0
- package/src/oracles/switchboardClient.js +69 -0
- package/src/oracles/types.js +2 -0
- package/src/orderParams.js +20 -0
- package/src/orderParams.ts +20 -141
- package/src/slot/SlotSubscriber.js +39 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/tokenFaucet.js +189 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +11 -3
- package/src/tx/types.js +2 -0
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +239 -27
- package/src/userName.js +20 -0
- package/src/util/computeUnits.js +21 -11
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/src/wallet.js +35 -0
- package/tests/bn/test.ts +10 -0
- package/lib/orders.d.ts +0 -8
- package/lib/orders.js +0 -142
- package/src/orders.ts +0 -251
- package/src/util/computeUnits.js.map +0 -1
package/lib/clearingHouse.js
CHANGED
|
@@ -29,6 +29,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
exports.ClearingHouse = void 0;
|
|
30
30
|
const anchor_1 = require("@project-serum/anchor");
|
|
31
31
|
const spl_token_1 = require("@solana/spl-token");
|
|
32
|
+
const types_1 = require("./types");
|
|
32
33
|
const anchor = __importStar(require("@project-serum/anchor"));
|
|
33
34
|
const clearing_house_json_1 = __importDefault(require("./idl/clearing_house.json"));
|
|
34
35
|
const web3_js_1 = require("@solana/web3.js");
|
|
@@ -42,8 +43,9 @@ const pollingClearingHouseAccountSubscriber_1 = require("./accounts/pollingClear
|
|
|
42
43
|
const webSocketClearingHouseAccountSubscriber_1 = require("./accounts/webSocketClearingHouseAccountSubscriber");
|
|
43
44
|
const retryTxSender_1 = require("./tx/retryTxSender");
|
|
44
45
|
const clearingHouseUser_1 = require("./clearingHouseUser");
|
|
45
|
-
const orderParams_1 = require("./orderParams");
|
|
46
46
|
const config_1 = require("./config");
|
|
47
|
+
const banks_1 = require("./constants/banks");
|
|
48
|
+
const clearingHouseUserStats_1 = require("./clearingHouseUserStats");
|
|
47
49
|
/**
|
|
48
50
|
* # ClearingHouse
|
|
49
51
|
* This class is the main way to interact with Drift Protocol. It allows you to subscribe to the various accounts where the Market's state is stored, as well as: opening positions, liquidating, settling funding, depositing & withdrawing, and more.
|
|
@@ -71,6 +73,13 @@ class ClearingHouse {
|
|
|
71
73
|
type: 'websocket',
|
|
72
74
|
};
|
|
73
75
|
this.createUsers(userIds, this.userAccountSubscriptionConfig);
|
|
76
|
+
if (config.userStats) {
|
|
77
|
+
this.userStats = new clearingHouseUserStats_1.ClearingHouseUserStats({
|
|
78
|
+
clearingHouse: this,
|
|
79
|
+
userStatsAccountPublicKey: (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, this.wallet.publicKey),
|
|
80
|
+
accountSubscription: this.userAccountSubscriptionConfig,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
74
83
|
let marketIndexes = config.marketIndexes;
|
|
75
84
|
let bankIndexes = config.bankIndexes;
|
|
76
85
|
let oracleInfos = config.oracleInfos;
|
|
@@ -111,6 +120,9 @@ class ClearingHouse {
|
|
|
111
120
|
}
|
|
112
121
|
async subscribe() {
|
|
113
122
|
const subscribePromises = this.subscribeUsers().concat(this.accountSubscriber.subscribe());
|
|
123
|
+
if (this.userStats !== undefined) {
|
|
124
|
+
subscribePromises.concat(this.userStats.subscribe());
|
|
125
|
+
}
|
|
114
126
|
this.isSubscribed = (await Promise.all(subscribePromises)).reduce((success, prevSuccess) => success && prevSuccess);
|
|
115
127
|
return this.isSubscribed;
|
|
116
128
|
}
|
|
@@ -121,12 +133,19 @@ class ClearingHouse {
|
|
|
121
133
|
* Forces the accountSubscriber to fetch account updates from rpc
|
|
122
134
|
*/
|
|
123
135
|
async fetchAccounts() {
|
|
124
|
-
|
|
136
|
+
const promises = [...this.users.values()]
|
|
125
137
|
.map((user) => user.fetchAccounts())
|
|
126
|
-
.concat(this.accountSubscriber.fetch())
|
|
138
|
+
.concat(this.accountSubscriber.fetch());
|
|
139
|
+
if (this.userStats) {
|
|
140
|
+
promises.concat(this.userStats.fetchAccounts());
|
|
141
|
+
}
|
|
142
|
+
await Promise.all(promises);
|
|
127
143
|
}
|
|
128
144
|
async unsubscribe() {
|
|
129
145
|
const unsubscribePromises = this.unsubscribeUsers().concat(this.accountSubscriber.unsubscribe());
|
|
146
|
+
if (this.userStats !== undefined) {
|
|
147
|
+
unsubscribePromises.concat(this.userStats.unsubscribe());
|
|
148
|
+
}
|
|
130
149
|
await Promise.all(unsubscribePromises);
|
|
131
150
|
this.isSubscribed = false;
|
|
132
151
|
}
|
|
@@ -187,6 +206,7 @@ class ClearingHouse {
|
|
|
187
206
|
await Promise.all(this.subscribeUsers());
|
|
188
207
|
}
|
|
189
208
|
this.activeUserId = activeUserId;
|
|
209
|
+
this.userStatsAccountPublicKey = undefined;
|
|
190
210
|
}
|
|
191
211
|
async switchActiveUser(userId) {
|
|
192
212
|
this.activeUserId = userId;
|
|
@@ -199,27 +219,59 @@ class ClearingHouse {
|
|
|
199
219
|
await user.subscribe();
|
|
200
220
|
this.users.set(userId, user);
|
|
201
221
|
}
|
|
202
|
-
async initializeUserAccount(userId = 0, name = userName_1.DEFAULT_USER_NAME) {
|
|
203
|
-
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
|
|
204
|
-
const tx = new web3_js_1.Transaction()
|
|
222
|
+
async initializeUserAccount(userId = 0, name = userName_1.DEFAULT_USER_NAME, referrerInfo) {
|
|
223
|
+
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
|
|
224
|
+
const tx = new web3_js_1.Transaction();
|
|
225
|
+
if (userId === 0) {
|
|
226
|
+
// not the safest assumption, can explicitly check if user stats account exists if it causes problems
|
|
227
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
228
|
+
}
|
|
229
|
+
tx.add(initializeUserAccountIx);
|
|
205
230
|
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
206
231
|
return [txSig, userAccountPublicKey];
|
|
207
232
|
}
|
|
208
|
-
async getInitializeUserInstructions(userId = 0, name = userName_1.DEFAULT_USER_NAME) {
|
|
233
|
+
async getInitializeUserInstructions(userId = 0, name = userName_1.DEFAULT_USER_NAME, referrerInfo) {
|
|
209
234
|
const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, userId);
|
|
235
|
+
const remainingAccounts = new Array();
|
|
236
|
+
if (referrerInfo !== undefined) {
|
|
237
|
+
remainingAccounts.push({
|
|
238
|
+
pubkey: referrerInfo.referrer,
|
|
239
|
+
isWritable: true,
|
|
240
|
+
isSigner: false,
|
|
241
|
+
});
|
|
242
|
+
remainingAccounts.push({
|
|
243
|
+
pubkey: referrerInfo.referrerStats,
|
|
244
|
+
isWritable: true,
|
|
245
|
+
isSigner: false,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
210
248
|
const nameBuffer = (0, userName_1.encodeName)(name);
|
|
211
249
|
const initializeUserAccountIx = await this.program.instruction.initializeUser(userId, nameBuffer, {
|
|
212
250
|
accounts: {
|
|
213
251
|
user: userAccountPublicKey,
|
|
252
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
214
253
|
authority: this.wallet.publicKey,
|
|
215
254
|
payer: this.wallet.publicKey,
|
|
216
255
|
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
217
256
|
systemProgram: anchor.web3.SystemProgram.programId,
|
|
218
257
|
state: await this.getStatePublicKey(),
|
|
219
258
|
},
|
|
259
|
+
remainingAccounts,
|
|
220
260
|
});
|
|
221
261
|
return [userAccountPublicKey, initializeUserAccountIx];
|
|
222
262
|
}
|
|
263
|
+
async getInitializeUserStatsIx() {
|
|
264
|
+
return await this.program.instruction.initializeUserStats({
|
|
265
|
+
accounts: {
|
|
266
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
267
|
+
authority: this.wallet.publicKey,
|
|
268
|
+
payer: this.wallet.publicKey,
|
|
269
|
+
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
270
|
+
systemProgram: anchor.web3.SystemProgram.programId,
|
|
271
|
+
state: await this.getStatePublicKey(),
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
}
|
|
223
275
|
getUser(userId) {
|
|
224
276
|
userId = userId !== null && userId !== void 0 ? userId : this.activeUserId;
|
|
225
277
|
if (!this.users.has(userId)) {
|
|
@@ -230,6 +282,16 @@ class ClearingHouse {
|
|
|
230
282
|
getUsers() {
|
|
231
283
|
return [...this.users.values()];
|
|
232
284
|
}
|
|
285
|
+
getUserStats() {
|
|
286
|
+
return this.userStats;
|
|
287
|
+
}
|
|
288
|
+
getUserStatsAccountPublicKey() {
|
|
289
|
+
if (this.userStatsAccountPublicKey) {
|
|
290
|
+
return this.userStatsAccountPublicKey;
|
|
291
|
+
}
|
|
292
|
+
this.userStatsAccountPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, this.wallet.publicKey);
|
|
293
|
+
return this.userStatsAccountPublicKey;
|
|
294
|
+
}
|
|
233
295
|
async getUserAccountPublicKey() {
|
|
234
296
|
return this.getUser().userAccountPublicKey;
|
|
235
297
|
}
|
|
@@ -284,8 +346,7 @@ class ClearingHouse {
|
|
|
284
346
|
marketAccountMap.set(marketIndexNum, {
|
|
285
347
|
pubkey: marketAccount.pubkey,
|
|
286
348
|
isSigner: false,
|
|
287
|
-
|
|
288
|
-
isWritable: true,
|
|
349
|
+
isWritable: false,
|
|
289
350
|
});
|
|
290
351
|
oracleAccountMap.set(marketAccount.pubkey.toString(), {
|
|
291
352
|
pubkey: marketAccount.amm.oracle,
|
|
@@ -294,6 +355,19 @@ class ClearingHouse {
|
|
|
294
355
|
});
|
|
295
356
|
}
|
|
296
357
|
}
|
|
358
|
+
if (params.readableMarketIndex) {
|
|
359
|
+
const marketAccount = this.getMarketAccount(params.readableMarketIndex.toNumber());
|
|
360
|
+
marketAccountMap.set(params.readableMarketIndex.toNumber(), {
|
|
361
|
+
pubkey: marketAccount.pubkey,
|
|
362
|
+
isSigner: false,
|
|
363
|
+
isWritable: true,
|
|
364
|
+
});
|
|
365
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
366
|
+
pubkey: marketAccount.amm.oracle,
|
|
367
|
+
isSigner: false,
|
|
368
|
+
isWritable: false,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
297
371
|
if (params.writableMarketIndex) {
|
|
298
372
|
const marketAccount = this.getMarketAccount(params.writableMarketIndex.toNumber());
|
|
299
373
|
marketAccountMap.set(params.writableMarketIndex.toNumber(), {
|
|
@@ -355,9 +429,27 @@ class ClearingHouse {
|
|
|
355
429
|
return (_a = this.getUserAccount()) === null || _a === void 0 ? void 0 : _a.orders.find((order) => order.userOrderId === userOrderId);
|
|
356
430
|
}
|
|
357
431
|
async deposit(amount, bankIndex, collateralAccountPublicKey, userId, reduceOnly = false) {
|
|
432
|
+
const tx = new web3_js_1.Transaction();
|
|
433
|
+
const additionalSigners = [];
|
|
434
|
+
const bank = this.getBankAccount(bankIndex);
|
|
435
|
+
const isSolBank = bank.mint.equals(banks_1.WRAPPED_SOL_MINT);
|
|
436
|
+
const authority = this.wallet.publicKey;
|
|
437
|
+
const createWSOLTokenAccount = isSolBank && collateralAccountPublicKey.equals(authority);
|
|
438
|
+
if (createWSOLTokenAccount) {
|
|
439
|
+
const { ixs, signers, pubkey } = await this.getWrappedSolAccountCreationIxs(amount);
|
|
440
|
+
collateralAccountPublicKey = pubkey;
|
|
441
|
+
ixs.forEach((ix) => {
|
|
442
|
+
tx.add(ix);
|
|
443
|
+
});
|
|
444
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
445
|
+
}
|
|
358
446
|
const depositCollateralIx = await this.getDepositInstruction(amount, bankIndex, collateralAccountPublicKey, userId, reduceOnly, true);
|
|
359
|
-
|
|
360
|
-
|
|
447
|
+
tx.add(depositCollateralIx);
|
|
448
|
+
// Close the wrapped sol account at the end of the transaction
|
|
449
|
+
if (createWSOLTokenAccount) {
|
|
450
|
+
tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, collateralAccountPublicKey, authority, authority, []));
|
|
451
|
+
}
|
|
452
|
+
const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
|
|
361
453
|
return txSig;
|
|
362
454
|
}
|
|
363
455
|
async getDepositInstruction(amount, bankIndex, userTokenAccount, userId, reduceOnly = false, userInitialized = true) {
|
|
@@ -371,13 +463,19 @@ class ClearingHouse {
|
|
|
371
463
|
});
|
|
372
464
|
}
|
|
373
465
|
else {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
466
|
+
const bankAccount = this.getBankAccount(bankIndex);
|
|
467
|
+
if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
468
|
+
remainingAccounts.push({
|
|
469
|
+
pubkey: bankAccount.oracle,
|
|
377
470
|
isSigner: false,
|
|
378
|
-
isWritable:
|
|
379
|
-
}
|
|
380
|
-
|
|
471
|
+
isWritable: false,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
remainingAccounts.push({
|
|
475
|
+
pubkey: bankAccount.pubkey,
|
|
476
|
+
isSigner: false,
|
|
477
|
+
isWritable: true,
|
|
478
|
+
});
|
|
381
479
|
}
|
|
382
480
|
const bank = this.getBankAccount(bankIndex);
|
|
383
481
|
return await this.program.instruction.deposit(bankIndex, amount, reduceOnly, {
|
|
@@ -386,6 +484,7 @@ class ClearingHouse {
|
|
|
386
484
|
bank: bank.pubkey,
|
|
387
485
|
bankVault: bank.vault,
|
|
388
486
|
user: userAccountPublicKey,
|
|
487
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
389
488
|
userTokenAccount: userTokenAccount,
|
|
390
489
|
authority: this.wallet.publicKey,
|
|
391
490
|
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
@@ -393,40 +492,132 @@ class ClearingHouse {
|
|
|
393
492
|
remainingAccounts,
|
|
394
493
|
});
|
|
395
494
|
}
|
|
495
|
+
async checkIfAccountExists(account) {
|
|
496
|
+
try {
|
|
497
|
+
const accountInfo = await this.connection.getAccountInfo(account);
|
|
498
|
+
return accountInfo && true;
|
|
499
|
+
}
|
|
500
|
+
catch (e) {
|
|
501
|
+
// Doesn't already exist
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
async getSolWithdrawalIxs(bankIndex, amount) {
|
|
506
|
+
const result = {
|
|
507
|
+
ixs: [],
|
|
508
|
+
signers: [],
|
|
509
|
+
pubkey: web3_js_1.PublicKey.default,
|
|
510
|
+
};
|
|
511
|
+
// Create a temporary wrapped SOL account to store the SOL that we're withdrawing
|
|
512
|
+
const authority = this.wallet.publicKey;
|
|
513
|
+
const { ixs, signers, pubkey } = await this.getWrappedSolAccountCreationIxs(amount);
|
|
514
|
+
result.pubkey = pubkey;
|
|
515
|
+
ixs.forEach((ix) => {
|
|
516
|
+
result.ixs.push(ix);
|
|
517
|
+
});
|
|
518
|
+
signers.forEach((ix) => {
|
|
519
|
+
result.signers.push(ix);
|
|
520
|
+
});
|
|
521
|
+
const withdrawIx = await this.getWithdrawIx(amount, bankIndex, pubkey, true);
|
|
522
|
+
result.ixs.push(withdrawIx);
|
|
523
|
+
result.ixs.push(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, pubkey, authority, authority, []));
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
526
|
+
async getWrappedSolAccountCreationIxs(amount) {
|
|
527
|
+
const wrappedSolAccount = new web3_js_1.Keypair();
|
|
528
|
+
const result = {
|
|
529
|
+
ixs: [],
|
|
530
|
+
signers: [],
|
|
531
|
+
pubkey: wrappedSolAccount.publicKey,
|
|
532
|
+
};
|
|
533
|
+
const rentSpaceLamports = new anchor_1.BN(web3_js_1.LAMPORTS_PER_SOL / 100);
|
|
534
|
+
const depositAmountLamports = amount.add(rentSpaceLamports);
|
|
535
|
+
const authority = this.wallet.publicKey;
|
|
536
|
+
result.ixs.push(web3_js_1.SystemProgram.createAccount({
|
|
537
|
+
fromPubkey: authority,
|
|
538
|
+
newAccountPubkey: wrappedSolAccount.publicKey,
|
|
539
|
+
lamports: depositAmountLamports.toNumber(),
|
|
540
|
+
space: 165,
|
|
541
|
+
programId: spl_token_1.TOKEN_PROGRAM_ID,
|
|
542
|
+
}));
|
|
543
|
+
result.ixs.push(spl_token_1.Token.createInitAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, banks_1.WRAPPED_SOL_MINT, wrappedSolAccount.publicKey, authority));
|
|
544
|
+
result.signers.push(wrappedSolAccount);
|
|
545
|
+
return result;
|
|
546
|
+
}
|
|
396
547
|
/**
|
|
397
548
|
* Creates the Clearing House User account for a user, and deposits some initial collateral
|
|
398
|
-
* @param userId
|
|
399
|
-
* @param name
|
|
400
549
|
* @param amount
|
|
401
550
|
* @param userTokenAccount
|
|
551
|
+
* @param bankIndex
|
|
552
|
+
* @param userId
|
|
553
|
+
* @param name
|
|
402
554
|
* @param fromUserId
|
|
403
555
|
* @returns
|
|
404
556
|
*/
|
|
405
|
-
async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, bankIndex = new anchor_1.BN(0), userId = 0, name = userName_1.DEFAULT_USER_NAME, fromUserId) {
|
|
406
|
-
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
|
|
557
|
+
async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, bankIndex = new anchor_1.BN(0), userId = 0, name = userName_1.DEFAULT_USER_NAME, fromUserId, referrerInfo) {
|
|
558
|
+
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
|
|
559
|
+
const additionalSigners = [];
|
|
560
|
+
const bank = this.getBankAccount(bankIndex);
|
|
561
|
+
const isSolBank = bank.mint.equals(banks_1.WRAPPED_SOL_MINT);
|
|
562
|
+
const tx = new web3_js_1.Transaction();
|
|
563
|
+
const authority = this.wallet.publicKey;
|
|
564
|
+
const createWSOLTokenAccount = isSolBank && userTokenAccount.equals(authority);
|
|
565
|
+
if (createWSOLTokenAccount) {
|
|
566
|
+
const { ixs: startIxs, signers, pubkey, } = await this.getWrappedSolAccountCreationIxs(amount);
|
|
567
|
+
userTokenAccount = pubkey;
|
|
568
|
+
startIxs.forEach((ix) => {
|
|
569
|
+
tx.add(ix);
|
|
570
|
+
});
|
|
571
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
572
|
+
}
|
|
407
573
|
const depositCollateralIx = fromUserId != null
|
|
408
574
|
? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
|
|
409
575
|
: await this.getDepositInstruction(amount, bankIndex, userTokenAccount, userId, false, false);
|
|
410
|
-
|
|
411
|
-
.add(
|
|
412
|
-
|
|
413
|
-
|
|
576
|
+
if (userId === 0) {
|
|
577
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
578
|
+
}
|
|
579
|
+
tx.add(initializeUserAccountIx).add(depositCollateralIx);
|
|
580
|
+
// Close the wrapped sol account at the end of the transaction
|
|
581
|
+
if (createWSOLTokenAccount) {
|
|
582
|
+
tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, userTokenAccount, authority, authority, []));
|
|
583
|
+
}
|
|
584
|
+
const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
|
|
414
585
|
return [txSig, userAccountPublicKey];
|
|
415
586
|
}
|
|
416
|
-
async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME,
|
|
417
|
-
const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await
|
|
418
|
-
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
|
|
419
|
-
const depositCollateralIx = await this.getDepositInstruction(amount,
|
|
420
|
-
const tx = new web3_js_1.Transaction()
|
|
421
|
-
|
|
422
|
-
.add(
|
|
423
|
-
|
|
424
|
-
|
|
587
|
+
async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME, bankIndex, tokenFaucet, amount, referrerInfo) {
|
|
588
|
+
const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
|
|
589
|
+
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
|
|
590
|
+
const depositCollateralIx = await this.getDepositInstruction(amount, bankIndex, associateTokenPublicKey, userId, false, false);
|
|
591
|
+
const tx = new web3_js_1.Transaction().add(createAssociatedAccountIx).add(mintToIx);
|
|
592
|
+
if (userId === 0) {
|
|
593
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
594
|
+
}
|
|
595
|
+
tx.add(initializeUserAccountIx).add(depositCollateralIx);
|
|
425
596
|
const txSig = await this.program.provider.sendAndConfirm(tx, []);
|
|
426
597
|
return [txSig, userAccountPublicKey];
|
|
427
598
|
}
|
|
428
599
|
async withdraw(amount, bankIndex, userTokenAccount, reduceOnly = false) {
|
|
429
|
-
const
|
|
600
|
+
const tx = new web3_js_1.Transaction();
|
|
601
|
+
const additionalSigners = [];
|
|
602
|
+
const bank = this.getBankAccount(bankIndex);
|
|
603
|
+
const isSolBank = bank.mint.equals(banks_1.WRAPPED_SOL_MINT);
|
|
604
|
+
const authority = this.wallet.publicKey;
|
|
605
|
+
const createWSOLTokenAccount = isSolBank && userTokenAccount.equals(authority);
|
|
606
|
+
if (createWSOLTokenAccount) {
|
|
607
|
+
const { ixs, signers, pubkey } = await this.getWrappedSolAccountCreationIxs(amount);
|
|
608
|
+
userTokenAccount = pubkey;
|
|
609
|
+
ixs.forEach((ix) => {
|
|
610
|
+
tx.add(ix);
|
|
611
|
+
});
|
|
612
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
613
|
+
}
|
|
614
|
+
const withdrawCollateral = await this.getWithdrawIx(amount, bank.bankIndex, userTokenAccount, reduceOnly);
|
|
615
|
+
tx.add(withdrawCollateral);
|
|
616
|
+
// Close the wrapped sol account at the end of the transaction
|
|
617
|
+
if (createWSOLTokenAccount) {
|
|
618
|
+
tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, userTokenAccount, authority, authority, []));
|
|
619
|
+
}
|
|
620
|
+
const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
|
|
430
621
|
return txSig;
|
|
431
622
|
}
|
|
432
623
|
async getWithdrawIx(amount, bankIndex, userTokenAccount, reduceOnly = false) {
|
|
@@ -442,6 +633,7 @@ class ClearingHouse {
|
|
|
442
633
|
bankVault: bank.vault,
|
|
443
634
|
bankVaultAuthority: bank.vaultAuthority,
|
|
444
635
|
user: userAccountPublicKey,
|
|
636
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
445
637
|
userTokenAccount: userTokenAccount,
|
|
446
638
|
authority: this.wallet.publicKey,
|
|
447
639
|
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
@@ -464,6 +656,7 @@ class ClearingHouse {
|
|
|
464
656
|
authority: this.wallet.publicKey,
|
|
465
657
|
fromUser,
|
|
466
658
|
toUser,
|
|
659
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
467
660
|
state: await this.getStatePublicKey(),
|
|
468
661
|
},
|
|
469
662
|
remainingAccounts,
|
|
@@ -481,44 +674,113 @@ class ClearingHouse {
|
|
|
481
674
|
},
|
|
482
675
|
});
|
|
483
676
|
}
|
|
484
|
-
async
|
|
485
|
-
|
|
677
|
+
async settleLP(settleeUserAccountPublicKey, marketIndex) {
|
|
678
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.settleLPIx(settleeUserAccountPublicKey, marketIndex)), [], this.opts);
|
|
679
|
+
return txSig;
|
|
486
680
|
}
|
|
487
|
-
async
|
|
488
|
-
const
|
|
489
|
-
|
|
681
|
+
async settleLPIx(settleeUserAccountPublicKey, marketIndex) {
|
|
682
|
+
const settleeUserAccount = (await this.program.account.user.fetch(settleeUserAccountPublicKey));
|
|
683
|
+
const userPositions = settleeUserAccount.positions;
|
|
684
|
+
const remainingAccounts = [];
|
|
685
|
+
let foundMarket = false;
|
|
686
|
+
for (const position of userPositions) {
|
|
687
|
+
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
688
|
+
const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, position.marketIndex);
|
|
689
|
+
remainingAccounts.push({
|
|
690
|
+
pubkey: marketPublicKey,
|
|
691
|
+
isWritable: true,
|
|
692
|
+
isSigner: false,
|
|
693
|
+
});
|
|
694
|
+
if (marketIndex.eq(position.marketIndex)) {
|
|
695
|
+
foundMarket = true;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
if (!foundMarket) {
|
|
700
|
+
console.log('Warning: lp is not in the market specified -- tx will likely fail');
|
|
701
|
+
}
|
|
702
|
+
return this.program.instruction.settleLp(marketIndex, {
|
|
703
|
+
accounts: {
|
|
704
|
+
state: await this.getStatePublicKey(),
|
|
705
|
+
user: settleeUserAccountPublicKey,
|
|
706
|
+
},
|
|
707
|
+
remainingAccounts: remainingAccounts,
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
async removeLiquidity(marketIndex, sharesToBurn) {
|
|
711
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getRemoveLiquidityIx(marketIndex, sharesToBurn)), [], this.opts);
|
|
490
712
|
return txSig;
|
|
491
713
|
}
|
|
492
|
-
async
|
|
714
|
+
async getRemoveLiquidityIx(marketIndex, sharesToBurn) {
|
|
493
715
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
494
|
-
const priceOracle = this.getMarketAccount(orderParams.marketIndex).amm
|
|
495
|
-
.oracle;
|
|
496
716
|
const remainingAccounts = this.getRemainingAccounts({
|
|
497
|
-
writableMarketIndex:
|
|
717
|
+
writableMarketIndex: marketIndex,
|
|
498
718
|
});
|
|
499
|
-
|
|
719
|
+
if (sharesToBurn == undefined) {
|
|
720
|
+
const userAccount = this.getUserAccount();
|
|
721
|
+
const marketPosition = userAccount.positions.filter((position) => position.marketIndex.eq(marketIndex))[0];
|
|
722
|
+
sharesToBurn = marketPosition.lpShares;
|
|
723
|
+
console.log('burning lp shares:', sharesToBurn.toString());
|
|
724
|
+
}
|
|
725
|
+
return this.program.instruction.removeLiquidity(sharesToBurn, marketIndex, {
|
|
500
726
|
accounts: {
|
|
501
727
|
state: await this.getStatePublicKey(),
|
|
502
728
|
user: userAccountPublicKey,
|
|
503
729
|
authority: this.wallet.publicKey,
|
|
504
|
-
oracle: priceOracle,
|
|
505
730
|
},
|
|
506
|
-
remainingAccounts,
|
|
731
|
+
remainingAccounts: remainingAccounts,
|
|
507
732
|
});
|
|
508
733
|
}
|
|
509
|
-
async
|
|
510
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.
|
|
734
|
+
async addLiquidity(amount, marketIndex) {
|
|
735
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getAddLiquidityIx(amount, marketIndex)), [], this.opts);
|
|
736
|
+
this.marketLastSlotCache.set(marketIndex.toNumber(), slot);
|
|
511
737
|
return txSig;
|
|
512
738
|
}
|
|
513
|
-
async
|
|
514
|
-
const
|
|
515
|
-
|
|
739
|
+
async getAddLiquidityIx(amount, marketIndex) {
|
|
740
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
741
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
742
|
+
writableMarketIndex: marketIndex,
|
|
743
|
+
});
|
|
744
|
+
return this.program.instruction.addLiquidity(amount, marketIndex, {
|
|
745
|
+
accounts: {
|
|
746
|
+
state: await this.getStatePublicKey(),
|
|
747
|
+
user: userAccountPublicKey,
|
|
748
|
+
authority: this.wallet.publicKey,
|
|
749
|
+
},
|
|
750
|
+
remainingAccounts: remainingAccounts,
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
async openPosition(direction, amount, marketIndex, limitPrice) {
|
|
754
|
+
return await this.placeAndTake({
|
|
755
|
+
orderType: types_1.OrderType.MARKET,
|
|
756
|
+
marketIndex,
|
|
757
|
+
direction,
|
|
758
|
+
baseAssetAmount: amount,
|
|
759
|
+
price: limitPrice,
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
async placeOrder(orderParams) {
|
|
763
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceOrderIx(orderParams)), [], this.opts);
|
|
764
|
+
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
765
|
+
return txSig;
|
|
766
|
+
}
|
|
767
|
+
getOrderParams(optionalOrderParams) {
|
|
768
|
+
return Object.assign({}, types_1.DefaultOrderParams, optionalOrderParams);
|
|
769
|
+
}
|
|
770
|
+
async getPlaceOrderIx(orderParams) {
|
|
771
|
+
orderParams = this.getOrderParams(orderParams);
|
|
772
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
773
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
774
|
+
readableMarketIndex: orderParams.marketIndex,
|
|
775
|
+
});
|
|
776
|
+
return await this.program.instruction.placeOrder(orderParams, {
|
|
516
777
|
accounts: {
|
|
517
778
|
state: await this.getStatePublicKey(),
|
|
518
|
-
filler: fillerPublicKey,
|
|
519
779
|
user: userAccountPublicKey,
|
|
780
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
520
781
|
authority: this.wallet.publicKey,
|
|
521
782
|
},
|
|
783
|
+
remainingAccounts,
|
|
522
784
|
});
|
|
523
785
|
}
|
|
524
786
|
async updateAMMs(marketIndexes) {
|
|
@@ -590,107 +852,92 @@ class ClearingHouse {
|
|
|
590
852
|
remainingAccounts,
|
|
591
853
|
});
|
|
592
854
|
}
|
|
593
|
-
async
|
|
594
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.
|
|
595
|
-
return txSig;
|
|
596
|
-
}
|
|
597
|
-
async getCancelAllOrdersIx(bestEffort) {
|
|
598
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
599
|
-
const remainingAccounts = this.getRemainingAccounts({});
|
|
600
|
-
for (const order of this.getUserAccount().orders) {
|
|
601
|
-
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
602
|
-
remainingAccounts.push({
|
|
603
|
-
pubkey: oracle,
|
|
604
|
-
isWritable: false,
|
|
605
|
-
isSigner: false,
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
return await this.program.instruction.cancelAllOrders(bestEffort, {
|
|
609
|
-
accounts: {
|
|
610
|
-
state: await this.getStatePublicKey(),
|
|
611
|
-
user: userAccountPublicKey,
|
|
612
|
-
authority: this.wallet.publicKey,
|
|
613
|
-
},
|
|
614
|
-
remainingAccounts,
|
|
615
|
-
});
|
|
616
|
-
}
|
|
617
|
-
async cancelOrdersByMarketAndSide(bestEffort, marketIndexOnly, directionOnly) {
|
|
618
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getCancelOrdersByMarketAndSideIx(bestEffort, marketIndexOnly, directionOnly)), [], this.opts);
|
|
619
|
-
return txSig;
|
|
620
|
-
}
|
|
621
|
-
async getCancelOrdersByMarketAndSideIx(bestEffort, marketIndexOnly, directionOnly) {
|
|
622
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
623
|
-
const remainingAccounts = this.getRemainingAccounts({});
|
|
624
|
-
for (const order of this.getUserAccount().orders) {
|
|
625
|
-
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
626
|
-
remainingAccounts.push({
|
|
627
|
-
pubkey: oracle,
|
|
628
|
-
isWritable: false,
|
|
629
|
-
isSigner: false,
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
return await this.program.instruction.cancelOrdersByMarketAndSide(bestEffort, marketIndexOnly, directionOnly, {
|
|
633
|
-
accounts: {
|
|
634
|
-
state: await this.getStatePublicKey(),
|
|
635
|
-
user: userAccountPublicKey,
|
|
636
|
-
authority: this.wallet.publicKey,
|
|
637
|
-
},
|
|
638
|
-
remainingAccounts,
|
|
639
|
-
});
|
|
640
|
-
}
|
|
641
|
-
async fillOrder(userAccountPublicKey, user, order, makerInfo) {
|
|
642
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)), [], this.opts);
|
|
855
|
+
async fillOrder(userAccountPublicKey, user, order, makerInfo, referrerInfo) {
|
|
856
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo, referrerInfo)), [], this.opts);
|
|
643
857
|
return txSig;
|
|
644
858
|
}
|
|
645
|
-
async getFillOrderIx(userAccountPublicKey, userAccount, order, makerInfo) {
|
|
859
|
+
async getFillOrderIx(userAccountPublicKey, userAccount, order, makerInfo, referrerInfo) {
|
|
860
|
+
const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
|
|
646
861
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
647
|
-
const
|
|
862
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
863
|
+
const marketIndex = order
|
|
864
|
+
? order.marketIndex
|
|
865
|
+
: userAccount.orders.find((order) => order.orderId.eq(userAccount.nextOrderId.sub(numericConstants_1.ONE))).marketIndex;
|
|
648
866
|
const marketAccount = this.getMarketAccount(marketIndex);
|
|
649
|
-
const
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
},
|
|
670
|
-
];
|
|
867
|
+
const oracleAccountMap = new Map();
|
|
868
|
+
const bankAccountMap = new Map();
|
|
869
|
+
const marketAccountMap = new Map();
|
|
870
|
+
for (const bankBalance of userAccount.bankBalances) {
|
|
871
|
+
if (!bankBalance.balance.eq(numericConstants_1.ZERO)) {
|
|
872
|
+
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
873
|
+
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
874
|
+
pubkey: bankAccount.pubkey,
|
|
875
|
+
isSigner: false,
|
|
876
|
+
isWritable: false,
|
|
877
|
+
});
|
|
878
|
+
if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
879
|
+
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
880
|
+
pubkey: bankAccount.oracle,
|
|
881
|
+
isSigner: false,
|
|
882
|
+
isWritable: false,
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
671
887
|
for (const position of userAccount.positions) {
|
|
672
888
|
if (!(0, position_1.positionIsAvailable)(position) &&
|
|
673
889
|
!position.marketIndex.eq(order.marketIndex)) {
|
|
674
890
|
const market = this.getMarketAccount(position.marketIndex);
|
|
675
|
-
|
|
891
|
+
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
676
892
|
pubkey: market.pubkey,
|
|
677
893
|
isWritable: false,
|
|
678
894
|
isSigner: false,
|
|
679
895
|
});
|
|
680
|
-
|
|
896
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
681
897
|
pubkey: market.amm.oracle,
|
|
682
898
|
isWritable: false,
|
|
683
899
|
isSigner: false,
|
|
684
900
|
});
|
|
685
901
|
}
|
|
686
902
|
}
|
|
687
|
-
|
|
903
|
+
marketAccountMap.set(marketIndex.toNumber(), {
|
|
904
|
+
pubkey: marketAccount.pubkey,
|
|
905
|
+
isWritable: true,
|
|
906
|
+
isSigner: false,
|
|
907
|
+
});
|
|
908
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
909
|
+
pubkey: marketAccount.amm.oracle,
|
|
910
|
+
isWritable: false,
|
|
911
|
+
isSigner: false,
|
|
912
|
+
});
|
|
913
|
+
const remainingAccounts = [
|
|
914
|
+
...oracleAccountMap.values(),
|
|
915
|
+
...bankAccountMap.values(),
|
|
916
|
+
...marketAccountMap.values(),
|
|
917
|
+
];
|
|
688
918
|
if (makerInfo) {
|
|
689
919
|
remainingAccounts.push({
|
|
690
920
|
pubkey: makerInfo.maker,
|
|
691
921
|
isWritable: true,
|
|
692
922
|
isSigner: false,
|
|
693
923
|
});
|
|
924
|
+
remainingAccounts.push({
|
|
925
|
+
pubkey: makerInfo.makerStats,
|
|
926
|
+
isWritable: true,
|
|
927
|
+
isSigner: false,
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
if (referrerInfo) {
|
|
931
|
+
remainingAccounts.push({
|
|
932
|
+
pubkey: referrerInfo.referrer,
|
|
933
|
+
isWritable: true,
|
|
934
|
+
isSigner: false,
|
|
935
|
+
});
|
|
936
|
+
remainingAccounts.push({
|
|
937
|
+
pubkey: referrerInfo.referrerStats,
|
|
938
|
+
isWritable: true,
|
|
939
|
+
isSigner: false,
|
|
940
|
+
});
|
|
694
941
|
}
|
|
695
942
|
const orderId = order.orderId;
|
|
696
943
|
const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
|
|
@@ -698,9 +945,10 @@ class ClearingHouse {
|
|
|
698
945
|
accounts: {
|
|
699
946
|
state: await this.getStatePublicKey(),
|
|
700
947
|
filler: fillerPublicKey,
|
|
948
|
+
fillerStats: fillerStatsPublicKey,
|
|
701
949
|
user: userAccountPublicKey,
|
|
950
|
+
userStats: userStatsPublicKey,
|
|
702
951
|
authority: this.wallet.publicKey,
|
|
703
|
-
oracle: oracle,
|
|
704
952
|
},
|
|
705
953
|
remainingAccounts,
|
|
706
954
|
});
|
|
@@ -713,44 +961,57 @@ class ClearingHouse {
|
|
|
713
961
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
714
962
|
const marketIndex = order.marketIndex;
|
|
715
963
|
const marketAccount = this.getMarketAccount(marketIndex);
|
|
716
|
-
const
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
];
|
|
964
|
+
const oracleAccountMap = new Map();
|
|
965
|
+
const bankAccountMap = new Map();
|
|
966
|
+
const marketAccountMap = new Map();
|
|
967
|
+
for (const bankBalance of userAccount.bankBalances) {
|
|
968
|
+
if (!bankBalance.balance.eq(numericConstants_1.ZERO)) {
|
|
969
|
+
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
970
|
+
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
971
|
+
pubkey: bankAccount.pubkey,
|
|
972
|
+
isSigner: false,
|
|
973
|
+
isWritable: false,
|
|
974
|
+
});
|
|
975
|
+
if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
976
|
+
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
977
|
+
pubkey: bankAccount.oracle,
|
|
978
|
+
isSigner: false,
|
|
979
|
+
isWritable: false,
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
737
984
|
for (const position of userAccount.positions) {
|
|
738
985
|
if (!(0, position_1.positionIsAvailable)(position) &&
|
|
739
986
|
!position.marketIndex.eq(order.marketIndex)) {
|
|
740
987
|
const market = this.getMarketAccount(position.marketIndex);
|
|
741
|
-
|
|
988
|
+
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
742
989
|
pubkey: market.pubkey,
|
|
743
990
|
isWritable: false,
|
|
744
991
|
isSigner: false,
|
|
745
992
|
});
|
|
746
|
-
|
|
993
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
747
994
|
pubkey: market.amm.oracle,
|
|
748
995
|
isWritable: false,
|
|
749
996
|
isSigner: false,
|
|
750
997
|
});
|
|
751
998
|
}
|
|
752
999
|
}
|
|
753
|
-
|
|
1000
|
+
marketAccountMap.set(marketIndex.toNumber(), {
|
|
1001
|
+
pubkey: marketAccount.pubkey,
|
|
1002
|
+
isWritable: true,
|
|
1003
|
+
isSigner: false,
|
|
1004
|
+
});
|
|
1005
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1006
|
+
pubkey: marketAccount.amm.oracle,
|
|
1007
|
+
isWritable: false,
|
|
1008
|
+
isSigner: false,
|
|
1009
|
+
});
|
|
1010
|
+
const remainingAccounts = [
|
|
1011
|
+
...oracleAccountMap.values(),
|
|
1012
|
+
...bankAccountMap.values(),
|
|
1013
|
+
...marketAccountMap.values(),
|
|
1014
|
+
];
|
|
754
1015
|
const orderId = order.orderId;
|
|
755
1016
|
return await this.program.instruction.triggerOrder(orderId, {
|
|
756
1017
|
accounts: {
|
|
@@ -762,15 +1023,15 @@ class ClearingHouse {
|
|
|
762
1023
|
remainingAccounts,
|
|
763
1024
|
});
|
|
764
1025
|
}
|
|
765
|
-
async placeAndTake(orderParams, makerInfo) {
|
|
766
|
-
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeIx(orderParams, makerInfo)), [], this.opts);
|
|
1026
|
+
async placeAndTake(orderParams, makerInfo, referrerInfo) {
|
|
1027
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)), [], this.opts);
|
|
767
1028
|
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
768
1029
|
return txSig;
|
|
769
1030
|
}
|
|
770
|
-
async getPlaceAndTakeIx(orderParams, makerInfo) {
|
|
1031
|
+
async getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo) {
|
|
1032
|
+
orderParams = this.getOrderParams(orderParams);
|
|
1033
|
+
const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
771
1034
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
772
|
-
const priceOracle = this.getMarketAccount(orderParams.marketIndex).amm
|
|
773
|
-
.oracle;
|
|
774
1035
|
const remainingAccounts = this.getRemainingAccounts({
|
|
775
1036
|
writableMarketIndex: orderParams.marketIndex,
|
|
776
1037
|
writableBankIndex: numericConstants_1.QUOTE_ASSET_BANK_INDEX,
|
|
@@ -783,13 +1044,69 @@ class ClearingHouse {
|
|
|
783
1044
|
isSigner: false,
|
|
784
1045
|
isWritable: true,
|
|
785
1046
|
});
|
|
1047
|
+
remainingAccounts.push({
|
|
1048
|
+
pubkey: makerInfo.makerStats,
|
|
1049
|
+
isSigner: false,
|
|
1050
|
+
isWritable: true,
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
1053
|
+
if (referrerInfo) {
|
|
1054
|
+
remainingAccounts.push({
|
|
1055
|
+
pubkey: referrerInfo.referrer,
|
|
1056
|
+
isWritable: true,
|
|
1057
|
+
isSigner: false,
|
|
1058
|
+
});
|
|
1059
|
+
remainingAccounts.push({
|
|
1060
|
+
pubkey: referrerInfo.referrerStats,
|
|
1061
|
+
isWritable: true,
|
|
1062
|
+
isSigner: false,
|
|
1063
|
+
});
|
|
786
1064
|
}
|
|
787
1065
|
return await this.program.instruction.placeAndTake(orderParams, makerOrderId, {
|
|
788
1066
|
accounts: {
|
|
789
1067
|
state: await this.getStatePublicKey(),
|
|
790
1068
|
user: userAccountPublicKey,
|
|
1069
|
+
userStats: userStatsPublicKey,
|
|
1070
|
+
authority: this.wallet.publicKey,
|
|
1071
|
+
},
|
|
1072
|
+
remainingAccounts,
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
async placeAndMake(orderParams, takerInfo, referrerInfo) {
|
|
1076
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo)), [], this.opts);
|
|
1077
|
+
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
1078
|
+
return txSig;
|
|
1079
|
+
}
|
|
1080
|
+
async getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo) {
|
|
1081
|
+
orderParams = this.getOrderParams(orderParams);
|
|
1082
|
+
const userStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1083
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1084
|
+
// todo merge this with getRemainingAccounts
|
|
1085
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1086
|
+
counterPartyUserAccount: takerInfo.takerUserAccount,
|
|
1087
|
+
writableMarketIndex: orderParams.marketIndex,
|
|
1088
|
+
});
|
|
1089
|
+
if (referrerInfo) {
|
|
1090
|
+
remainingAccounts.push({
|
|
1091
|
+
pubkey: referrerInfo.referrer,
|
|
1092
|
+
isWritable: true,
|
|
1093
|
+
isSigner: false,
|
|
1094
|
+
});
|
|
1095
|
+
remainingAccounts.push({
|
|
1096
|
+
pubkey: referrerInfo.referrerStats,
|
|
1097
|
+
isWritable: true,
|
|
1098
|
+
isSigner: false,
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
const takerOrderId = takerInfo.order.orderId;
|
|
1102
|
+
return await this.program.instruction.placeAndMake(orderParams, takerOrderId, {
|
|
1103
|
+
accounts: {
|
|
1104
|
+
state: await this.getStatePublicKey(),
|
|
1105
|
+
user: userAccountPublicKey,
|
|
1106
|
+
userStats: userStatsPublicKey,
|
|
1107
|
+
taker: takerInfo.taker,
|
|
1108
|
+
takerStats: takerInfo.takerStats,
|
|
791
1109
|
authority: this.wallet.publicKey,
|
|
792
|
-
oracle: priceOracle,
|
|
793
1110
|
},
|
|
794
1111
|
remainingAccounts,
|
|
795
1112
|
});
|
|
@@ -799,19 +1116,31 @@ class ClearingHouse {
|
|
|
799
1116
|
* @param marketIndex
|
|
800
1117
|
* @returns
|
|
801
1118
|
*/
|
|
802
|
-
async closePosition(marketIndex) {
|
|
1119
|
+
async closePosition(marketIndex, limitPrice) {
|
|
803
1120
|
const userPosition = this.getUser().getUserPosition(marketIndex);
|
|
804
1121
|
if (!userPosition) {
|
|
805
1122
|
throw Error(`No position in market ${marketIndex.toString()}`);
|
|
806
1123
|
}
|
|
807
|
-
return await this.placeAndTake(
|
|
1124
|
+
return await this.placeAndTake({
|
|
1125
|
+
orderType: types_1.OrderType.MARKET,
|
|
1126
|
+
marketIndex,
|
|
1127
|
+
direction: (0, position_1.findDirectionToClose)(userPosition),
|
|
1128
|
+
baseAssetAmount: userPosition.baseAssetAmount.abs(),
|
|
1129
|
+
reduceOnly: true,
|
|
1130
|
+
price: limitPrice,
|
|
1131
|
+
});
|
|
808
1132
|
}
|
|
809
1133
|
async settlePNLs(users, marketIndex) {
|
|
810
1134
|
const ixs = [];
|
|
811
1135
|
for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
|
|
812
1136
|
ixs.push(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex));
|
|
813
1137
|
}
|
|
814
|
-
const tx = new web3_js_1.Transaction()
|
|
1138
|
+
const tx = new web3_js_1.Transaction()
|
|
1139
|
+
.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
1140
|
+
units: 1000000,
|
|
1141
|
+
additionalFee: 0,
|
|
1142
|
+
}))
|
|
1143
|
+
.add(...ixs);
|
|
815
1144
|
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
816
1145
|
return txSig;
|
|
817
1146
|
}
|
|
@@ -828,7 +1157,7 @@ class ClearingHouse {
|
|
|
828
1157
|
const market = this.getMarketAccount(position.marketIndex);
|
|
829
1158
|
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
830
1159
|
pubkey: market.pubkey,
|
|
831
|
-
isWritable:
|
|
1160
|
+
isWritable: false,
|
|
832
1161
|
isSigner: false,
|
|
833
1162
|
});
|
|
834
1163
|
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
@@ -885,54 +1214,261 @@ class ClearingHouse {
|
|
|
885
1214
|
remainingAccounts: remainingAccounts,
|
|
886
1215
|
});
|
|
887
1216
|
}
|
|
888
|
-
async
|
|
889
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.
|
|
1217
|
+
async liquidatePerp(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
|
|
1218
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount)), [], this.opts);
|
|
890
1219
|
return txSig;
|
|
891
1220
|
}
|
|
892
|
-
async
|
|
893
|
-
const
|
|
894
|
-
const
|
|
895
|
-
const
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1221
|
+
async getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
|
|
1222
|
+
const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
|
|
1223
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1224
|
+
const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1225
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1226
|
+
writableMarketIndex: marketIndex,
|
|
1227
|
+
counterPartyUserAccount: userAccount,
|
|
1228
|
+
});
|
|
1229
|
+
return await this.program.instruction.liquidatePerp(marketIndex, maxBaseAssetAmount, {
|
|
1230
|
+
accounts: {
|
|
1231
|
+
state: await this.getStatePublicKey(),
|
|
1232
|
+
authority: this.wallet.publicKey,
|
|
1233
|
+
user: userAccountPublicKey,
|
|
1234
|
+
userStats: userStatsPublicKey,
|
|
1235
|
+
liquidator: liquidatorPublicKey,
|
|
1236
|
+
liquidatorStats: liquidatorStatsPublicKey,
|
|
900
1237
|
},
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1238
|
+
remainingAccounts: remainingAccounts,
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
async liquidateBorrow(userAccountPublicKey, userAccount, assetBankIndex, liabilityBankIndex, maxLiabilityTransfer) {
|
|
1242
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateBorrowIx(userAccountPublicKey, userAccount, assetBankIndex, liabilityBankIndex, maxLiabilityTransfer)), [], this.opts);
|
|
1243
|
+
return txSig;
|
|
1244
|
+
}
|
|
1245
|
+
async getLiquidateBorrowIx(userAccountPublicKey, userAccount, assetBankIndex, liabilityBankIndex, maxLiabilityTransfer) {
|
|
1246
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1247
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1248
|
+
counterPartyUserAccount: userAccount,
|
|
1249
|
+
writableBankIndexes: [liabilityBankIndex, assetBankIndex],
|
|
1250
|
+
});
|
|
1251
|
+
return await this.program.instruction.liquidateBorrow(assetBankIndex, liabilityBankIndex, maxLiabilityTransfer, {
|
|
1252
|
+
accounts: {
|
|
1253
|
+
state: await this.getStatePublicKey(),
|
|
1254
|
+
authority: this.wallet.publicKey,
|
|
1255
|
+
user: userAccountPublicKey,
|
|
1256
|
+
liquidator: liquidatorPublicKey,
|
|
1257
|
+
},
|
|
1258
|
+
remainingAccounts: remainingAccounts,
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
async liquidateBorrowForPerpPnl(userAccountPublicKey, userAccount, perpMarketIndex, liabilityBankIndex, maxLiabilityTransfer) {
|
|
1262
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityBankIndex, maxLiabilityTransfer)), [], this.opts);
|
|
1263
|
+
return txSig;
|
|
1264
|
+
}
|
|
1265
|
+
async getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityBankIndex, maxLiabilityTransfer) {
|
|
1266
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1267
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1268
|
+
counterPartyUserAccount: userAccount,
|
|
1269
|
+
writableMarketIndex: perpMarketIndex,
|
|
1270
|
+
writableBankIndexes: [liabilityBankIndex],
|
|
1271
|
+
});
|
|
1272
|
+
return await this.program.instruction.liquidateBorrowForPerpPnl(perpMarketIndex, liabilityBankIndex, maxLiabilityTransfer, {
|
|
1273
|
+
accounts: {
|
|
1274
|
+
state: await this.getStatePublicKey(),
|
|
1275
|
+
authority: this.wallet.publicKey,
|
|
1276
|
+
user: userAccountPublicKey,
|
|
1277
|
+
liquidator: liquidatorPublicKey,
|
|
1278
|
+
},
|
|
1279
|
+
remainingAccounts: remainingAccounts,
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
async liquidatePerpPnlForDeposit(userAccountPublicKey, userAccount, perpMarketIndex, assetBankIndex, maxPnlTransfer) {
|
|
1283
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetBankIndex, maxPnlTransfer)), [], this.opts);
|
|
1284
|
+
return txSig;
|
|
1285
|
+
}
|
|
1286
|
+
async getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetBankIndex, maxPnlTransfer) {
|
|
1287
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1288
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1289
|
+
counterPartyUserAccount: userAccount,
|
|
1290
|
+
writableMarketIndex: perpMarketIndex,
|
|
1291
|
+
writableBankIndexes: [assetBankIndex],
|
|
1292
|
+
});
|
|
1293
|
+
return await this.program.instruction.liquidatePerpPnlForDeposit(perpMarketIndex, assetBankIndex, maxPnlTransfer, {
|
|
1294
|
+
accounts: {
|
|
1295
|
+
state: await this.getStatePublicKey(),
|
|
1296
|
+
authority: this.wallet.publicKey,
|
|
1297
|
+
user: userAccountPublicKey,
|
|
1298
|
+
liquidator: liquidatorPublicKey,
|
|
1299
|
+
},
|
|
1300
|
+
remainingAccounts: remainingAccounts,
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
async resolvePerpBankruptcy(userAccountPublicKey, userAccount, marketIndex) {
|
|
1304
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolvePerpBankruptcyIx(userAccountPublicKey, userAccount, marketIndex)), [], this.opts);
|
|
1305
|
+
return txSig;
|
|
1306
|
+
}
|
|
1307
|
+
async getResolvePerpBankruptcyIx(userAccountPublicKey, userAccount, marketIndex) {
|
|
1308
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1309
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1310
|
+
writableMarketIndex: marketIndex,
|
|
1311
|
+
counterPartyUserAccount: userAccount,
|
|
1312
|
+
});
|
|
1313
|
+
return await this.program.instruction.resolvePerpBankruptcy(marketIndex, {
|
|
1314
|
+
accounts: {
|
|
1315
|
+
state: await this.getStatePublicKey(),
|
|
1316
|
+
authority: this.wallet.publicKey,
|
|
1317
|
+
user: userAccountPublicKey,
|
|
1318
|
+
liquidator: liquidatorPublicKey,
|
|
1319
|
+
},
|
|
1320
|
+
remainingAccounts: remainingAccounts,
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
async resolveBorrowBankruptcy(userAccountPublicKey, userAccount, bankIndex) {
|
|
1324
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolveBorrowBankruptcyIx(userAccountPublicKey, userAccount, bankIndex)), [], this.opts);
|
|
1325
|
+
return txSig;
|
|
1326
|
+
}
|
|
1327
|
+
async getResolveBorrowBankruptcyIx(userAccountPublicKey, userAccount, bankIndex) {
|
|
1328
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1329
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1330
|
+
writableBankIndexes: [bankIndex],
|
|
1331
|
+
counterPartyUserAccount: userAccount,
|
|
1332
|
+
});
|
|
1333
|
+
return await this.program.instruction.resolveBorrowBankruptcy(bankIndex, {
|
|
1334
|
+
accounts: {
|
|
1335
|
+
state: await this.getStatePublicKey(),
|
|
1336
|
+
authority: this.wallet.publicKey,
|
|
1337
|
+
user: userAccountPublicKey,
|
|
1338
|
+
liquidator: liquidatorPublicKey,
|
|
1339
|
+
},
|
|
1340
|
+
remainingAccounts: remainingAccounts,
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
getRemainingAccountsWithCounterparty(params) {
|
|
1344
|
+
const counterPartyUserAccount = params.counterPartyUserAccount;
|
|
1345
|
+
const oracleAccountMap = new Map();
|
|
1346
|
+
const bankAccountMap = new Map();
|
|
1347
|
+
const marketAccountMap = new Map();
|
|
1348
|
+
for (const bankBalance of counterPartyUserAccount.bankBalances) {
|
|
1349
|
+
if (!bankBalance.balance.eq(numericConstants_1.ZERO)) {
|
|
1350
|
+
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
1351
|
+
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
1352
|
+
pubkey: bankAccount.pubkey,
|
|
1353
|
+
isSigner: false,
|
|
1354
|
+
isWritable: false,
|
|
1355
|
+
});
|
|
1356
|
+
if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1357
|
+
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1358
|
+
pubkey: bankAccount.oracle,
|
|
1359
|
+
isSigner: false,
|
|
1360
|
+
isWritable: false,
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
for (const position of counterPartyUserAccount.positions) {
|
|
905
1366
|
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
906
1367
|
const market = this.getMarketAccount(position.marketIndex);
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
isWritable: true,
|
|
1368
|
+
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1369
|
+
pubkey: market.pubkey,
|
|
1370
|
+
isWritable: false,
|
|
911
1371
|
isSigner: false,
|
|
912
1372
|
});
|
|
913
|
-
|
|
1373
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
914
1374
|
pubkey: market.amm.oracle,
|
|
915
1375
|
isWritable: false,
|
|
916
1376
|
isSigner: false,
|
|
917
1377
|
});
|
|
918
1378
|
}
|
|
919
1379
|
}
|
|
920
|
-
const
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1380
|
+
const userAccountAndSlot = this.getUserAccountAndSlot();
|
|
1381
|
+
if (!userAccountAndSlot) {
|
|
1382
|
+
throw Error('No user account found. Most likely user account does not exist or failed to fetch account');
|
|
1383
|
+
}
|
|
1384
|
+
const { data: userAccount, slot: lastUserPositionsSlot } = userAccountAndSlot;
|
|
1385
|
+
for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
|
|
1386
|
+
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
1387
|
+
// otherwise remove from slot
|
|
1388
|
+
if (slot > lastUserPositionsSlot) {
|
|
1389
|
+
const marketAccount = this.getMarketAccount(marketIndexNum);
|
|
1390
|
+
marketAccountMap.set(marketIndexNum, {
|
|
1391
|
+
pubkey: marketAccount.pubkey,
|
|
1392
|
+
isSigner: false,
|
|
1393
|
+
isWritable: false,
|
|
1394
|
+
});
|
|
1395
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1396
|
+
pubkey: marketAccount.amm.oracle,
|
|
1397
|
+
isSigner: false,
|
|
1398
|
+
isWritable: false,
|
|
1399
|
+
});
|
|
1400
|
+
}
|
|
1401
|
+
else {
|
|
1402
|
+
this.marketLastSlotCache.delete(marketIndexNum);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
for (const bankBalance of userAccount.bankBalances) {
|
|
1406
|
+
if (!bankBalance.balance.eq(numericConstants_1.ZERO)) {
|
|
1407
|
+
const bankAccount = this.getBankAccount(bankBalance.bankIndex);
|
|
1408
|
+
bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
|
|
1409
|
+
pubkey: bankAccount.pubkey,
|
|
1410
|
+
isSigner: false,
|
|
1411
|
+
isWritable: false,
|
|
1412
|
+
});
|
|
1413
|
+
if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1414
|
+
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1415
|
+
pubkey: bankAccount.oracle,
|
|
1416
|
+
isSigner: false,
|
|
1417
|
+
isWritable: false,
|
|
1418
|
+
});
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
for (const position of userAccount.positions) {
|
|
1423
|
+
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
1424
|
+
const market = this.getMarketAccount(position.marketIndex);
|
|
1425
|
+
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1426
|
+
pubkey: market.pubkey,
|
|
1427
|
+
isWritable: false,
|
|
1428
|
+
isSigner: false,
|
|
1429
|
+
});
|
|
1430
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1431
|
+
pubkey: market.amm.oracle,
|
|
1432
|
+
isWritable: false,
|
|
1433
|
+
isSigner: false,
|
|
1434
|
+
});
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
if (params.writableMarketIndex) {
|
|
1438
|
+
const market = this.getMarketAccount(params.writableMarketIndex);
|
|
1439
|
+
marketAccountMap.set(market.marketIndex.toNumber(), {
|
|
1440
|
+
pubkey: market.pubkey,
|
|
1441
|
+
isSigner: false,
|
|
1442
|
+
isWritable: true,
|
|
1443
|
+
});
|
|
1444
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1445
|
+
pubkey: market.amm.oracle,
|
|
1446
|
+
isSigner: false,
|
|
1447
|
+
isWritable: false,
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
if (params.writableBankIndexes) {
|
|
1451
|
+
for (const writableBankIndex of params.writableBankIndexes) {
|
|
1452
|
+
const bank = this.getBankAccount(writableBankIndex);
|
|
1453
|
+
bankAccountMap.set(bank.bankIndex.toNumber(), {
|
|
1454
|
+
pubkey: bank.pubkey,
|
|
1455
|
+
isSigner: false,
|
|
1456
|
+
isWritable: true,
|
|
1457
|
+
});
|
|
1458
|
+
if (!bank.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1459
|
+
oracleAccountMap.set(bank.oracle.toString(), {
|
|
1460
|
+
pubkey: bank.oracle,
|
|
1461
|
+
isSigner: false,
|
|
1462
|
+
isWritable: false,
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
return [
|
|
1468
|
+
...oracleAccountMap.values(),
|
|
1469
|
+
...bankAccountMap.values(),
|
|
1470
|
+
...marketAccountMap.values(),
|
|
1471
|
+
];
|
|
936
1472
|
}
|
|
937
1473
|
async updateFundingRate(oracle, marketIndex) {
|
|
938
1474
|
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateFundingRateIx(oracle, marketIndex)), [], this.opts);
|