@drift-labs/sdk 0.2.0-master.25 → 0.2.0-master.27
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/pollingClearingHouseAccountSubscriber.d.ts +14 -13
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +30 -27
- package/lib/accounts/types.d.ts +9 -9
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +15 -14
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +38 -34
- package/lib/addresses/pda.d.ts +7 -6
- package/lib/addresses/pda.js +31 -27
- package/lib/admin.d.ts +13 -7
- package/lib/admin.js +111 -44
- package/lib/clearingHouse.d.ts +71 -42
- package/lib/clearingHouse.js +767 -278
- package/lib/clearingHouseConfig.d.ts +2 -2
- package/lib/clearingHouseUser.d.ts +24 -22
- package/lib/clearingHouseUser.js +273 -177
- package/lib/config.d.ts +7 -7
- package/lib/config.js +21 -21
- package/lib/constants/numericConstants.d.ts +12 -12
- package/lib/constants/numericConstants.js +13 -13
- package/lib/constants/{markets.d.ts → perpMarkets.d.ts} +5 -5
- package/lib/constants/{markets.js → perpMarkets.js} +4 -4
- package/lib/constants/{banks.d.ts → spotMarkets.d.ts} +6 -6
- package/lib/constants/{banks.js → spotMarkets.js} +16 -16
- package/lib/dlob/DLOB.d.ts +73 -0
- package/lib/dlob/DLOB.js +557 -0
- package/lib/dlob/DLOBNode.d.ts +52 -0
- package/lib/dlob/DLOBNode.js +82 -0
- package/lib/dlob/NodeList.d.ts +26 -0
- package/lib/dlob/NodeList.js +138 -0
- package/lib/events/types.d.ts +2 -1
- package/lib/events/types.js +1 -0
- package/lib/examples/makeTradeExample.js +7 -7
- package/lib/idl/clearing_house.json +1152 -503
- package/lib/index.d.ts +10 -3
- package/lib/index.js +10 -3
- package/lib/math/amm.d.ts +2 -2
- package/lib/math/amm.js +1 -1
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +2 -1
- package/lib/math/margin.d.ts +4 -4
- package/lib/math/margin.js +18 -11
- package/lib/math/market.d.ts +11 -10
- package/lib/math/market.js +30 -7
- package/lib/math/oracles.d.ts +2 -1
- package/lib/math/oracles.js +11 -1
- package/lib/math/orders.d.ts +6 -6
- package/lib/math/orders.js +31 -16
- package/lib/math/position.d.ts +13 -13
- package/lib/math/position.js +19 -19
- package/lib/math/spotBalance.d.ts +22 -0
- package/lib/math/spotBalance.js +193 -0
- package/lib/math/spotMarket.d.ts +4 -0
- package/lib/math/spotMarket.js +8 -0
- package/lib/math/spotPosition.d.ts +6 -0
- package/lib/math/spotPosition.js +23 -0
- package/lib/math/state.js +2 -2
- package/lib/math/trade.d.ts +4 -4
- package/lib/orderParams.d.ts +4 -4
- package/lib/orderParams.js +12 -4
- package/lib/serum/serumSubscriber.d.ts +23 -0
- package/lib/serum/serumSubscriber.js +41 -0
- package/lib/serum/types.d.ts +11 -0
- package/lib/serum/types.js +2 -0
- package/lib/tx/retryTxSender.d.ts +1 -1
- package/lib/tx/retryTxSender.js +4 -2
- package/lib/tx/types.d.ts +1 -1
- package/lib/types.d.ts +148 -57
- package/lib/types.js +39 -11
- package/lib/userMap/userMap.d.ts +25 -0
- package/lib/userMap/userMap.js +73 -0
- package/lib/userMap/userStatsMap.d.ts +19 -0
- package/lib/userMap/userStatsMap.js +68 -0
- package/package.json +6 -3
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +42 -38
- package/src/accounts/types.ts +12 -9
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +65 -52
- package/src/addresses/pda.ts +49 -44
- package/src/admin.ts +190 -55
- package/src/clearingHouse.ts +1092 -365
- package/src/clearingHouseConfig.ts +2 -2
- package/src/clearingHouseUser.ts +518 -255
- package/src/config.ts +30 -30
- package/src/constants/numericConstants.ts +17 -15
- package/src/constants/{markets.ts → perpMarkets.ts} +5 -5
- package/src/constants/{banks.ts → spotMarkets.ts} +19 -19
- package/src/dlob/DLOB.ts +884 -0
- package/src/dlob/DLOBNode.ts +163 -0
- package/src/dlob/NodeList.ts +185 -0
- package/src/events/types.ts +3 -0
- package/src/examples/makeTradeExample.js +152 -75
- package/src/examples/makeTradeExample.ts +10 -8
- package/src/idl/clearing_house.json +1152 -503
- package/src/index.ts +10 -3
- package/src/math/amm.ts +6 -3
- package/src/math/funding.ts +7 -7
- package/src/math/margin.ts +34 -23
- package/src/math/market.ts +72 -20
- package/src/math/oracles.ts +18 -1
- package/src/math/orders.ts +33 -25
- package/src/math/position.ts +31 -31
- package/src/math/spotBalance.ts +316 -0
- package/src/math/spotMarket.ts +9 -0
- package/src/math/spotPosition.ts +47 -0
- package/src/math/state.ts +2 -2
- package/src/math/trade.ts +4 -4
- package/src/orderParams.ts +16 -8
- package/src/serum/serumSubscriber.ts +80 -0
- package/src/serum/types.ts +13 -0
- package/src/tx/retryTxSender.ts +5 -2
- package/src/tx/types.ts +2 -1
- package/src/types.ts +135 -56
- package/src/userMap/userMap.ts +100 -0
- package/src/userMap/userStatsMap.ts +110 -0
- package/tests/bn/test.ts +2 -3
- package/tests/dlob/helpers.ts +322 -0
- package/tests/dlob/test.ts +2865 -0
- package/lib/math/bankBalance.d.ts +0 -15
- package/lib/math/bankBalance.js +0 -150
- package/src/constants/numericConstants.js +0 -41
- package/src/math/bankBalance.ts +0 -258
- package/src/math/oracles.js +0 -26
- package/src/math/state.js +0 -15
- package/src/orderParams.js +0 -20
- package/src/slot/SlotSubscriber.js +0 -39
- package/src/tokenFaucet.js +0 -189
package/src/clearingHouse.ts
CHANGED
|
@@ -5,17 +5,19 @@ import {
|
|
|
5
5
|
IWallet,
|
|
6
6
|
PositionDirection,
|
|
7
7
|
UserAccount,
|
|
8
|
-
|
|
8
|
+
PerpMarketAccount,
|
|
9
9
|
OrderParams,
|
|
10
10
|
Order,
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
SpotMarketAccount,
|
|
12
|
+
SpotPosition,
|
|
13
13
|
MakerInfo,
|
|
14
14
|
TakerInfo,
|
|
15
15
|
OptionalOrderParams,
|
|
16
16
|
DefaultOrderParams,
|
|
17
17
|
OrderType,
|
|
18
18
|
ReferrerInfo,
|
|
19
|
+
MarketType,
|
|
20
|
+
SerumV3FulfillmentConfigAccount,
|
|
19
21
|
} from './types';
|
|
20
22
|
import * as anchor from '@project-serum/anchor';
|
|
21
23
|
import clearingHouseIDL from './idl/clearing_house.json';
|
|
@@ -43,6 +45,8 @@ import {
|
|
|
43
45
|
getClearingHouseStateAccountPublicKey,
|
|
44
46
|
getInsuranceFundStakeAccountPublicKey,
|
|
45
47
|
getMarketPublicKey,
|
|
48
|
+
getSerumFulfillmentConfigPublicKey,
|
|
49
|
+
getSerumSignerPublicKey,
|
|
46
50
|
getUserAccountPublicKey,
|
|
47
51
|
getUserAccountPublicKeySync,
|
|
48
52
|
getUserStatsAccountPublicKey,
|
|
@@ -56,11 +60,11 @@ import { TxSender } from './tx/types';
|
|
|
56
60
|
import { wrapInTx } from './tx/utils';
|
|
57
61
|
import {
|
|
58
62
|
ONE,
|
|
59
|
-
|
|
63
|
+
QUOTE_SPOT_MARKET_INDEX,
|
|
60
64
|
ZERO,
|
|
61
65
|
} from './constants/numericConstants';
|
|
62
66
|
import { findDirectionToClose, positionIsAvailable } from './math/position';
|
|
63
|
-
import { getTokenAmount } from './math/
|
|
67
|
+
import { getTokenAmount } from './math/spotBalance';
|
|
64
68
|
import { DEFAULT_USER_NAME, encodeName } from './userName';
|
|
65
69
|
import { OraclePriceData } from './oracles/types';
|
|
66
70
|
import { ClearingHouseConfig } from './clearingHouseConfig';
|
|
@@ -69,9 +73,10 @@ import { WebSocketClearingHouseAccountSubscriber } from './accounts/webSocketCle
|
|
|
69
73
|
import { RetryTxSender } from './tx/retryTxSender';
|
|
70
74
|
import { ClearingHouseUser } from './clearingHouseUser';
|
|
71
75
|
import { ClearingHouseUserAccountSubscriptionConfig } from './clearingHouseUserConfig';
|
|
72
|
-
import {
|
|
73
|
-
import { WRAPPED_SOL_MINT } from './constants/
|
|
76
|
+
import { getMarketsAndOraclesForSubscription } from './config';
|
|
77
|
+
import { WRAPPED_SOL_MINT } from './constants/spotMarkets';
|
|
74
78
|
import { ClearingHouseUserStats } from './clearingHouseUserStats';
|
|
79
|
+
import { isSpotPositionAvailable } from './math/spotPosition';
|
|
75
80
|
|
|
76
81
|
/**
|
|
77
82
|
* # ClearingHouse
|
|
@@ -139,17 +144,21 @@ export class ClearingHouse {
|
|
|
139
144
|
});
|
|
140
145
|
}
|
|
141
146
|
|
|
142
|
-
let
|
|
143
|
-
let
|
|
147
|
+
let perpMarketIndexes = config.perpMarketIndexes;
|
|
148
|
+
let spotMarketIndexes = config.spotMarketIndexes;
|
|
144
149
|
let oracleInfos = config.oracleInfos;
|
|
145
150
|
if (config.env) {
|
|
146
151
|
const {
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
perpMarketIndexes: envPerpMarketIndexes,
|
|
153
|
+
spotMarketIndexes: envSpotMarketIndexes,
|
|
149
154
|
oracleInfos: envOralceInfos,
|
|
150
|
-
} =
|
|
151
|
-
|
|
152
|
-
|
|
155
|
+
} = getMarketsAndOraclesForSubscription(config.env);
|
|
156
|
+
perpMarketIndexes = perpMarketIndexes
|
|
157
|
+
? perpMarketIndexes
|
|
158
|
+
: envPerpMarketIndexes;
|
|
159
|
+
spotMarketIndexes = spotMarketIndexes
|
|
160
|
+
? spotMarketIndexes
|
|
161
|
+
: envSpotMarketIndexes;
|
|
153
162
|
oracleInfos = oracleInfos ? oracleInfos : envOralceInfos;
|
|
154
163
|
}
|
|
155
164
|
|
|
@@ -157,15 +166,15 @@ export class ClearingHouse {
|
|
|
157
166
|
this.accountSubscriber = new PollingClearingHouseAccountSubscriber(
|
|
158
167
|
this.program,
|
|
159
168
|
config.accountSubscription.accountLoader,
|
|
160
|
-
|
|
161
|
-
|
|
169
|
+
perpMarketIndexes ?? [],
|
|
170
|
+
spotMarketIndexes ?? [],
|
|
162
171
|
oracleInfos ?? []
|
|
163
172
|
);
|
|
164
173
|
} else {
|
|
165
174
|
this.accountSubscriber = new WebSocketClearingHouseAccountSubscriber(
|
|
166
175
|
this.program,
|
|
167
|
-
config.
|
|
168
|
-
config.
|
|
176
|
+
config.perpMarketIndexes ?? [],
|
|
177
|
+
config.spotMarketIndexes ?? [],
|
|
169
178
|
config.oracleInfos ?? []
|
|
170
179
|
);
|
|
171
180
|
}
|
|
@@ -276,25 +285,36 @@ export class ClearingHouse {
|
|
|
276
285
|
return this.accountSubscriber.getStateAccountAndSlot().data;
|
|
277
286
|
}
|
|
278
287
|
|
|
279
|
-
public
|
|
288
|
+
public getPerpMarketAccount(
|
|
289
|
+
marketIndex: BN | number
|
|
290
|
+
): PerpMarketAccount | undefined {
|
|
280
291
|
marketIndex = marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
|
|
281
292
|
return this.accountSubscriber.getMarketAccountAndSlot(marketIndex)?.data;
|
|
282
293
|
}
|
|
283
294
|
|
|
284
|
-
public
|
|
295
|
+
public getPerpMarketAccounts(): PerpMarketAccount[] {
|
|
285
296
|
return this.accountSubscriber
|
|
286
297
|
.getMarketAccountsAndSlots()
|
|
287
298
|
.map((value) => value.data);
|
|
288
299
|
}
|
|
289
300
|
|
|
290
|
-
public
|
|
291
|
-
|
|
292
|
-
|
|
301
|
+
public getSpotMarketAccount(
|
|
302
|
+
marketIndex: BN | number
|
|
303
|
+
): SpotMarketAccount | undefined {
|
|
304
|
+
marketIndex = marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
|
|
305
|
+
return this.accountSubscriber.getSpotMarketAccountAndSlot(marketIndex).data;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
public getSpotMarketAccounts(): SpotMarketAccount[] {
|
|
309
|
+
return this.accountSubscriber
|
|
310
|
+
.getSpotMarketAccountsAndSlots()
|
|
311
|
+
.map((value) => value.data);
|
|
293
312
|
}
|
|
294
313
|
|
|
295
|
-
public
|
|
296
|
-
return this.accountSubscriber.
|
|
297
|
-
|
|
314
|
+
public getQuoteSpotMarketAccount(): SpotMarketAccount {
|
|
315
|
+
return this.accountSubscriber.getSpotMarketAccountAndSlot(
|
|
316
|
+
QUOTE_SPOT_MARKET_INDEX
|
|
317
|
+
).data;
|
|
298
318
|
}
|
|
299
319
|
|
|
300
320
|
public getOraclePriceDataAndSlot(
|
|
@@ -303,6 +323,18 @@ export class ClearingHouse {
|
|
|
303
323
|
return this.accountSubscriber.getOraclePriceDataAndSlot(oraclePublicKey);
|
|
304
324
|
}
|
|
305
325
|
|
|
326
|
+
public async getSerumV3FulfillmentConfig(
|
|
327
|
+
serumMarket: PublicKey
|
|
328
|
+
): Promise<SerumV3FulfillmentConfigAccount> {
|
|
329
|
+
const address = await getSerumFulfillmentConfigPublicKey(
|
|
330
|
+
this.program.programId,
|
|
331
|
+
serumMarket
|
|
332
|
+
);
|
|
333
|
+
return (await this.program.account.serumV3FulfillmentConfig.fetch(
|
|
334
|
+
address
|
|
335
|
+
)) as SerumV3FulfillmentConfigAccount;
|
|
336
|
+
}
|
|
337
|
+
|
|
306
338
|
/**
|
|
307
339
|
* Update the wallet to use for clearing house transactions and linked user account
|
|
308
340
|
* @param newWallet
|
|
@@ -433,6 +465,35 @@ export class ClearingHouse {
|
|
|
433
465
|
});
|
|
434
466
|
}
|
|
435
467
|
|
|
468
|
+
public async updateUserName(
|
|
469
|
+
name: string,
|
|
470
|
+
userId = 0
|
|
471
|
+
): Promise<TransactionSignature> {
|
|
472
|
+
const nameBuffer = encodeName(name);
|
|
473
|
+
return await this.program.rpc.updateUserName(userId, nameBuffer, {
|
|
474
|
+
accounts: {
|
|
475
|
+
user: await this.getUserAccountPublicKey(),
|
|
476
|
+
authority: this.wallet.publicKey,
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
public async updateUserCustomMarginRatio(
|
|
482
|
+
marginRatio: number,
|
|
483
|
+
userId = 0
|
|
484
|
+
): Promise<TransactionSignature> {
|
|
485
|
+
return await this.program.rpc.updateUserCustomMarginRatio(
|
|
486
|
+
userId,
|
|
487
|
+
marginRatio,
|
|
488
|
+
{
|
|
489
|
+
accounts: {
|
|
490
|
+
user: await this.getUserAccountPublicKey(),
|
|
491
|
+
authority: this.wallet.publicKey,
|
|
492
|
+
},
|
|
493
|
+
}
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
|
|
436
497
|
public getUser(userId?: number): ClearingHouseUser {
|
|
437
498
|
userId = userId ?? this.activeUserId;
|
|
438
499
|
if (!this.users.has(userId)) {
|
|
@@ -476,29 +537,29 @@ export class ClearingHouse {
|
|
|
476
537
|
return this.getUser(userId).getUserAccountAndSlot();
|
|
477
538
|
}
|
|
478
539
|
|
|
479
|
-
public
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
bankBalance.bankIndex.eq(bankIndexBN)
|
|
540
|
+
public getSpotPosition(marketIndex: number | BN): SpotPosition | undefined {
|
|
541
|
+
const marketIndexBN =
|
|
542
|
+
marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
|
|
543
|
+
return this.getUserAccount().spotPositions.find((spotPosition) =>
|
|
544
|
+
spotPosition.marketIndex.eq(marketIndexBN)
|
|
485
545
|
);
|
|
486
546
|
}
|
|
487
547
|
|
|
488
548
|
public getQuoteAssetTokenAmount(): BN {
|
|
489
|
-
const
|
|
490
|
-
const
|
|
549
|
+
const spotMarket = this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX);
|
|
550
|
+
const spotPosition = this.getSpotPosition(QUOTE_SPOT_MARKET_INDEX);
|
|
491
551
|
return getTokenAmount(
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
552
|
+
spotPosition.balance,
|
|
553
|
+
spotMarket,
|
|
554
|
+
spotPosition.balanceType
|
|
495
555
|
);
|
|
496
556
|
}
|
|
497
557
|
|
|
498
558
|
getRemainingAccounts(params: {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
559
|
+
writablePerpMarketIndex?: BN;
|
|
560
|
+
writableSpotMarketIndex?: BN;
|
|
561
|
+
readablePerpMarketIndex?: BN;
|
|
562
|
+
readableSpotMarketIndex?: BN;
|
|
502
563
|
}): AccountMeta[] {
|
|
503
564
|
const userAccountAndSlot = this.getUserAccountAndSlot();
|
|
504
565
|
if (!userAccountAndSlot) {
|
|
@@ -510,14 +571,14 @@ export class ClearingHouse {
|
|
|
510
571
|
userAccountAndSlot;
|
|
511
572
|
|
|
512
573
|
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
513
|
-
const
|
|
514
|
-
const
|
|
574
|
+
const spotMarketAccountMap = new Map<number, AccountMeta>();
|
|
575
|
+
const perpMarketAccountMap = new Map<number, AccountMeta>();
|
|
515
576
|
for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
|
|
516
577
|
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
517
578
|
// otherwise remove from slot
|
|
518
579
|
if (slot > lastUserPositionsSlot) {
|
|
519
|
-
const marketAccount = this.
|
|
520
|
-
|
|
580
|
+
const marketAccount = this.getPerpMarketAccount(marketIndexNum);
|
|
581
|
+
perpMarketAccountMap.set(marketIndexNum, {
|
|
521
582
|
pubkey: marketAccount.pubkey,
|
|
522
583
|
isSigner: false,
|
|
523
584
|
isWritable: false,
|
|
@@ -532,11 +593,11 @@ export class ClearingHouse {
|
|
|
532
593
|
}
|
|
533
594
|
}
|
|
534
595
|
|
|
535
|
-
for (const position of userAccount.
|
|
596
|
+
for (const position of userAccount.perpPositions) {
|
|
536
597
|
if (!positionIsAvailable(position)) {
|
|
537
598
|
const marketIndexNum = position.marketIndex.toNumber();
|
|
538
|
-
const marketAccount = this.
|
|
539
|
-
|
|
599
|
+
const marketAccount = this.getPerpMarketAccount(marketIndexNum);
|
|
600
|
+
perpMarketAccountMap.set(marketIndexNum, {
|
|
540
601
|
pubkey: marketAccount.pubkey,
|
|
541
602
|
isSigner: false,
|
|
542
603
|
isWritable: false,
|
|
@@ -549,14 +610,14 @@ export class ClearingHouse {
|
|
|
549
610
|
}
|
|
550
611
|
}
|
|
551
612
|
|
|
552
|
-
if (params.
|
|
553
|
-
const marketAccount = this.
|
|
554
|
-
params.
|
|
613
|
+
if (params.readablePerpMarketIndex) {
|
|
614
|
+
const marketAccount = this.getPerpMarketAccount(
|
|
615
|
+
params.readablePerpMarketIndex.toNumber()
|
|
555
616
|
);
|
|
556
|
-
|
|
617
|
+
perpMarketAccountMap.set(params.readablePerpMarketIndex.toNumber(), {
|
|
557
618
|
pubkey: marketAccount.pubkey,
|
|
558
619
|
isSigner: false,
|
|
559
|
-
isWritable:
|
|
620
|
+
isWritable: false,
|
|
560
621
|
});
|
|
561
622
|
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
562
623
|
pubkey: marketAccount.amm.oracle,
|
|
@@ -565,11 +626,11 @@ export class ClearingHouse {
|
|
|
565
626
|
});
|
|
566
627
|
}
|
|
567
628
|
|
|
568
|
-
if (params.
|
|
569
|
-
const marketAccount = this.
|
|
570
|
-
params.
|
|
629
|
+
if (params.writablePerpMarketIndex) {
|
|
630
|
+
const marketAccount = this.getPerpMarketAccount(
|
|
631
|
+
params.writablePerpMarketIndex.toNumber()
|
|
571
632
|
);
|
|
572
|
-
|
|
633
|
+
perpMarketAccountMap.set(params.writablePerpMarketIndex.toNumber(), {
|
|
573
634
|
pubkey: marketAccount.pubkey,
|
|
574
635
|
isSigner: false,
|
|
575
636
|
isWritable: true,
|
|
@@ -581,17 +642,19 @@ export class ClearingHouse {
|
|
|
581
642
|
});
|
|
582
643
|
}
|
|
583
644
|
|
|
584
|
-
for (const
|
|
585
|
-
if (!
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
|
|
645
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
646
|
+
if (!isSpotPositionAvailable(spotPosition)) {
|
|
647
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
648
|
+
spotPosition.marketIndex
|
|
649
|
+
);
|
|
650
|
+
spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
|
|
651
|
+
pubkey: spotMarketAccount.pubkey,
|
|
589
652
|
isSigner: false,
|
|
590
653
|
isWritable: false,
|
|
591
654
|
});
|
|
592
|
-
if (!
|
|
593
|
-
oracleAccountMap.set(
|
|
594
|
-
pubkey:
|
|
655
|
+
if (!spotMarketAccount.marketIndex.eq(ZERO)) {
|
|
656
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
657
|
+
pubkey: spotMarketAccount.oracle,
|
|
595
658
|
isSigner: false,
|
|
596
659
|
isWritable: false,
|
|
597
660
|
});
|
|
@@ -599,16 +662,36 @@ export class ClearingHouse {
|
|
|
599
662
|
}
|
|
600
663
|
}
|
|
601
664
|
|
|
602
|
-
if (params.
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
|
|
665
|
+
if (params.readableSpotMarketIndex) {
|
|
666
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
667
|
+
params.readableSpotMarketIndex
|
|
668
|
+
);
|
|
669
|
+
spotMarketAccountMap.set(params.readableSpotMarketIndex.toNumber(), {
|
|
670
|
+
pubkey: spotMarketAccount.pubkey,
|
|
671
|
+
isSigner: false,
|
|
672
|
+
isWritable: false,
|
|
673
|
+
});
|
|
674
|
+
if (!spotMarketAccount.marketIndex.eq(ZERO)) {
|
|
675
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
676
|
+
pubkey: spotMarketAccount.oracle,
|
|
677
|
+
isSigner: false,
|
|
678
|
+
isWritable: false,
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
if (params.writableSpotMarketIndex) {
|
|
684
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
685
|
+
params.writableSpotMarketIndex
|
|
686
|
+
);
|
|
687
|
+
spotMarketAccountMap.set(params.writableSpotMarketIndex.toNumber(), {
|
|
688
|
+
pubkey: spotMarketAccount.pubkey,
|
|
606
689
|
isSigner: false,
|
|
607
690
|
isWritable: true,
|
|
608
691
|
});
|
|
609
|
-
if (!
|
|
610
|
-
oracleAccountMap.set(
|
|
611
|
-
pubkey:
|
|
692
|
+
if (!spotMarketAccount.marketIndex.eq(ZERO)) {
|
|
693
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
694
|
+
pubkey: spotMarketAccount.oracle,
|
|
612
695
|
isSigner: false,
|
|
613
696
|
isWritable: false,
|
|
614
697
|
});
|
|
@@ -617,8 +700,8 @@ export class ClearingHouse {
|
|
|
617
700
|
|
|
618
701
|
return [
|
|
619
702
|
...oracleAccountMap.values(),
|
|
620
|
-
...
|
|
621
|
-
...
|
|
703
|
+
...spotMarketAccountMap.values(),
|
|
704
|
+
...perpMarketAccountMap.values(),
|
|
622
705
|
];
|
|
623
706
|
}
|
|
624
707
|
|
|
@@ -637,7 +720,7 @@ export class ClearingHouse {
|
|
|
637
720
|
|
|
638
721
|
public async deposit(
|
|
639
722
|
amount: BN,
|
|
640
|
-
|
|
723
|
+
marketIndex: BN,
|
|
641
724
|
collateralAccountPublicKey: PublicKey,
|
|
642
725
|
userId?: number,
|
|
643
726
|
reduceOnly = false
|
|
@@ -645,14 +728,14 @@ export class ClearingHouse {
|
|
|
645
728
|
const tx = new Transaction();
|
|
646
729
|
const additionalSigners: Array<Signer> = [];
|
|
647
730
|
|
|
648
|
-
const
|
|
731
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
649
732
|
|
|
650
|
-
const
|
|
733
|
+
const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
|
|
651
734
|
|
|
652
735
|
const authority = this.wallet.publicKey;
|
|
653
736
|
|
|
654
737
|
const createWSOLTokenAccount =
|
|
655
|
-
|
|
738
|
+
isSolMarket && collateralAccountPublicKey.equals(authority);
|
|
656
739
|
|
|
657
740
|
if (createWSOLTokenAccount) {
|
|
658
741
|
const { ixs, signers, pubkey } =
|
|
@@ -669,7 +752,7 @@ export class ClearingHouse {
|
|
|
669
752
|
|
|
670
753
|
const depositCollateralIx = await this.getDepositInstruction(
|
|
671
754
|
amount,
|
|
672
|
-
|
|
755
|
+
marketIndex,
|
|
673
756
|
collateralAccountPublicKey,
|
|
674
757
|
userId,
|
|
675
758
|
reduceOnly,
|
|
@@ -701,7 +784,7 @@ export class ClearingHouse {
|
|
|
701
784
|
|
|
702
785
|
async getDepositInstruction(
|
|
703
786
|
amount: BN,
|
|
704
|
-
|
|
787
|
+
marketIndex: BN,
|
|
705
788
|
userTokenAccount: PublicKey,
|
|
706
789
|
userId?: number,
|
|
707
790
|
reduceOnly = false,
|
|
@@ -718,35 +801,35 @@ export class ClearingHouse {
|
|
|
718
801
|
let remainingAccounts = [];
|
|
719
802
|
if (userInitialized) {
|
|
720
803
|
remainingAccounts = this.getRemainingAccounts({
|
|
721
|
-
|
|
804
|
+
writableSpotMarketIndex: marketIndex,
|
|
722
805
|
});
|
|
723
806
|
} else {
|
|
724
|
-
const
|
|
725
|
-
if (!
|
|
807
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
808
|
+
if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
|
|
726
809
|
remainingAccounts.push({
|
|
727
|
-
pubkey:
|
|
810
|
+
pubkey: spotMarketAccount.oracle,
|
|
728
811
|
isSigner: false,
|
|
729
812
|
isWritable: false,
|
|
730
813
|
});
|
|
731
814
|
}
|
|
732
815
|
remainingAccounts.push({
|
|
733
|
-
pubkey:
|
|
816
|
+
pubkey: spotMarketAccount.pubkey,
|
|
734
817
|
isSigner: false,
|
|
735
818
|
isWritable: true,
|
|
736
819
|
});
|
|
737
820
|
}
|
|
738
821
|
|
|
739
|
-
const
|
|
822
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
740
823
|
|
|
741
824
|
return await this.program.instruction.deposit(
|
|
742
|
-
|
|
825
|
+
marketIndex,
|
|
743
826
|
amount,
|
|
744
827
|
reduceOnly,
|
|
745
828
|
{
|
|
746
829
|
accounts: {
|
|
747
830
|
state: await this.getStatePublicKey(),
|
|
748
|
-
|
|
749
|
-
|
|
831
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
832
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
750
833
|
user: userAccountPublicKey,
|
|
751
834
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
752
835
|
userTokenAccount: userTokenAccount,
|
|
@@ -769,7 +852,7 @@ export class ClearingHouse {
|
|
|
769
852
|
}
|
|
770
853
|
|
|
771
854
|
private async getSolWithdrawalIxs(
|
|
772
|
-
|
|
855
|
+
marketIndex: BN,
|
|
773
856
|
amount: BN
|
|
774
857
|
): Promise<{
|
|
775
858
|
ixs: anchor.web3.TransactionInstruction[];
|
|
@@ -801,7 +884,7 @@ export class ClearingHouse {
|
|
|
801
884
|
|
|
802
885
|
const withdrawIx = await this.getWithdrawIx(
|
|
803
886
|
amount,
|
|
804
|
-
|
|
887
|
+
marketIndex,
|
|
805
888
|
pubkey,
|
|
806
889
|
true
|
|
807
890
|
);
|
|
@@ -868,7 +951,7 @@ export class ClearingHouse {
|
|
|
868
951
|
* Creates the Clearing House User account for a user, and deposits some initial collateral
|
|
869
952
|
* @param amount
|
|
870
953
|
* @param userTokenAccount
|
|
871
|
-
* @param
|
|
954
|
+
* @param marketIndex
|
|
872
955
|
* @param userId
|
|
873
956
|
* @param name
|
|
874
957
|
* @param fromUserId
|
|
@@ -877,7 +960,7 @@ export class ClearingHouse {
|
|
|
877
960
|
public async initializeUserAccountAndDepositCollateral(
|
|
878
961
|
amount: BN,
|
|
879
962
|
userTokenAccount: PublicKey,
|
|
880
|
-
|
|
963
|
+
marketIndex = new BN(0),
|
|
881
964
|
userId = 0,
|
|
882
965
|
name = DEFAULT_USER_NAME,
|
|
883
966
|
fromUserId?: number,
|
|
@@ -888,16 +971,16 @@ export class ClearingHouse {
|
|
|
888
971
|
|
|
889
972
|
const additionalSigners: Array<Signer> = [];
|
|
890
973
|
|
|
891
|
-
const
|
|
974
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
892
975
|
|
|
893
|
-
const
|
|
976
|
+
const isSolMarket = spotMarket.mint.equals(WRAPPED_SOL_MINT);
|
|
894
977
|
|
|
895
978
|
const tx = new Transaction();
|
|
896
979
|
|
|
897
980
|
const authority = this.wallet.publicKey;
|
|
898
981
|
|
|
899
982
|
const createWSOLTokenAccount =
|
|
900
|
-
|
|
983
|
+
isSolMarket && userTokenAccount.equals(authority);
|
|
901
984
|
|
|
902
985
|
if (createWSOLTokenAccount) {
|
|
903
986
|
const {
|
|
@@ -917,10 +1000,15 @@ export class ClearingHouse {
|
|
|
917
1000
|
|
|
918
1001
|
const depositCollateralIx =
|
|
919
1002
|
fromUserId != null
|
|
920
|
-
? await this.getTransferDepositIx(
|
|
1003
|
+
? await this.getTransferDepositIx(
|
|
1004
|
+
amount,
|
|
1005
|
+
marketIndex,
|
|
1006
|
+
fromUserId,
|
|
1007
|
+
userId
|
|
1008
|
+
)
|
|
921
1009
|
: await this.getDepositInstruction(
|
|
922
1010
|
amount,
|
|
923
|
-
|
|
1011
|
+
marketIndex,
|
|
924
1012
|
userTokenAccount,
|
|
925
1013
|
userId,
|
|
926
1014
|
false,
|
|
@@ -957,7 +1045,7 @@ export class ClearingHouse {
|
|
|
957
1045
|
public async initializeUserAccountForDevnet(
|
|
958
1046
|
userId = 0,
|
|
959
1047
|
name = DEFAULT_USER_NAME,
|
|
960
|
-
|
|
1048
|
+
marketIndex: BN,
|
|
961
1049
|
tokenFaucet: TokenFaucet,
|
|
962
1050
|
amount: BN,
|
|
963
1051
|
referrerInfo?: ReferrerInfo
|
|
@@ -973,7 +1061,7 @@ export class ClearingHouse {
|
|
|
973
1061
|
|
|
974
1062
|
const depositCollateralIx = await this.getDepositInstruction(
|
|
975
1063
|
amount,
|
|
976
|
-
|
|
1064
|
+
marketIndex,
|
|
977
1065
|
associateTokenPublicKey,
|
|
978
1066
|
userId,
|
|
979
1067
|
false,
|
|
@@ -994,21 +1082,21 @@ export class ClearingHouse {
|
|
|
994
1082
|
|
|
995
1083
|
public async withdraw(
|
|
996
1084
|
amount: BN,
|
|
997
|
-
|
|
1085
|
+
marketIndex: BN,
|
|
998
1086
|
userTokenAccount: PublicKey,
|
|
999
1087
|
reduceOnly = false
|
|
1000
1088
|
): Promise<TransactionSignature> {
|
|
1001
1089
|
const tx = new Transaction();
|
|
1002
1090
|
const additionalSigners: Array<Signer> = [];
|
|
1003
1091
|
|
|
1004
|
-
const
|
|
1092
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
1005
1093
|
|
|
1006
|
-
const
|
|
1094
|
+
const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
|
|
1007
1095
|
|
|
1008
1096
|
const authority = this.wallet.publicKey;
|
|
1009
1097
|
|
|
1010
1098
|
const createWSOLTokenAccount =
|
|
1011
|
-
|
|
1099
|
+
isSolMarket && userTokenAccount.equals(authority);
|
|
1012
1100
|
|
|
1013
1101
|
if (createWSOLTokenAccount) {
|
|
1014
1102
|
const { ixs, signers, pubkey } =
|
|
@@ -1025,7 +1113,7 @@ export class ClearingHouse {
|
|
|
1025
1113
|
|
|
1026
1114
|
const withdrawCollateral = await this.getWithdrawIx(
|
|
1027
1115
|
amount,
|
|
1028
|
-
|
|
1116
|
+
spotMarketAccount.marketIndex,
|
|
1029
1117
|
userTokenAccount,
|
|
1030
1118
|
reduceOnly
|
|
1031
1119
|
);
|
|
@@ -1055,27 +1143,27 @@ export class ClearingHouse {
|
|
|
1055
1143
|
|
|
1056
1144
|
public async getWithdrawIx(
|
|
1057
1145
|
amount: BN,
|
|
1058
|
-
|
|
1146
|
+
marketIndex: BN,
|
|
1059
1147
|
userTokenAccount: PublicKey,
|
|
1060
1148
|
reduceOnly = false
|
|
1061
1149
|
): Promise<TransactionInstruction> {
|
|
1062
1150
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1063
1151
|
|
|
1064
1152
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1065
|
-
|
|
1153
|
+
writableSpotMarketIndex: marketIndex,
|
|
1066
1154
|
});
|
|
1067
1155
|
|
|
1068
|
-
const
|
|
1156
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
1069
1157
|
|
|
1070
1158
|
return await this.program.instruction.withdraw(
|
|
1071
|
-
|
|
1159
|
+
marketIndex,
|
|
1072
1160
|
amount,
|
|
1073
1161
|
reduceOnly,
|
|
1074
1162
|
{
|
|
1075
1163
|
accounts: {
|
|
1076
1164
|
state: await this.getStatePublicKey(),
|
|
1077
|
-
|
|
1078
|
-
|
|
1165
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
1166
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
1079
1167
|
clearingHouseSigner: this.getSignerPublicKey(),
|
|
1080
1168
|
user: userAccountPublicKey,
|
|
1081
1169
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
@@ -1090,13 +1178,18 @@ export class ClearingHouse {
|
|
|
1090
1178
|
|
|
1091
1179
|
public async transferDeposit(
|
|
1092
1180
|
amount: BN,
|
|
1093
|
-
|
|
1181
|
+
marketIndex: BN,
|
|
1094
1182
|
fromUserId: number,
|
|
1095
1183
|
toUserId: number
|
|
1096
1184
|
): Promise<TransactionSignature> {
|
|
1097
1185
|
const { txSig } = await this.txSender.send(
|
|
1098
1186
|
wrapInTx(
|
|
1099
|
-
await this.getTransferDepositIx(
|
|
1187
|
+
await this.getTransferDepositIx(
|
|
1188
|
+
amount,
|
|
1189
|
+
marketIndex,
|
|
1190
|
+
fromUserId,
|
|
1191
|
+
toUserId
|
|
1192
|
+
)
|
|
1100
1193
|
),
|
|
1101
1194
|
[],
|
|
1102
1195
|
this.opts
|
|
@@ -1106,7 +1199,7 @@ export class ClearingHouse {
|
|
|
1106
1199
|
|
|
1107
1200
|
public async getTransferDepositIx(
|
|
1108
1201
|
amount: BN,
|
|
1109
|
-
|
|
1202
|
+
marketIndex: BN,
|
|
1110
1203
|
fromUserId: number,
|
|
1111
1204
|
toUserId: number
|
|
1112
1205
|
): Promise<TransactionInstruction> {
|
|
@@ -1122,10 +1215,10 @@ export class ClearingHouse {
|
|
|
1122
1215
|
);
|
|
1123
1216
|
|
|
1124
1217
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1125
|
-
|
|
1218
|
+
writableSpotMarketIndex: marketIndex,
|
|
1126
1219
|
});
|
|
1127
1220
|
|
|
1128
|
-
return await this.program.instruction.transferDeposit(
|
|
1221
|
+
return await this.program.instruction.transferDeposit(marketIndex, amount, {
|
|
1129
1222
|
accounts: {
|
|
1130
1223
|
authority: this.wallet.publicKey,
|
|
1131
1224
|
fromUser,
|
|
@@ -1137,24 +1230,24 @@ export class ClearingHouse {
|
|
|
1137
1230
|
});
|
|
1138
1231
|
}
|
|
1139
1232
|
|
|
1140
|
-
public async
|
|
1141
|
-
|
|
1233
|
+
public async updateSpotMarketCumulativeInterest(
|
|
1234
|
+
marketIndex: BN
|
|
1142
1235
|
): Promise<TransactionSignature> {
|
|
1143
1236
|
const { txSig } = await this.txSender.send(
|
|
1144
|
-
wrapInTx(await this.
|
|
1237
|
+
wrapInTx(await this.updateSpotMarketCumulativeInterestIx(marketIndex)),
|
|
1145
1238
|
[],
|
|
1146
1239
|
this.opts
|
|
1147
1240
|
);
|
|
1148
1241
|
return txSig;
|
|
1149
1242
|
}
|
|
1150
1243
|
|
|
1151
|
-
public async
|
|
1152
|
-
|
|
1244
|
+
public async updateSpotMarketCumulativeInterestIx(
|
|
1245
|
+
marketIndex: BN
|
|
1153
1246
|
): Promise<TransactionInstruction> {
|
|
1154
|
-
const
|
|
1155
|
-
return await this.program.instruction.
|
|
1247
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
1248
|
+
return await this.program.instruction.updateSpotMarketCumulativeInterest({
|
|
1156
1249
|
accounts: {
|
|
1157
|
-
|
|
1250
|
+
spotMarket: spotMarket.pubkey,
|
|
1158
1251
|
},
|
|
1159
1252
|
});
|
|
1160
1253
|
}
|
|
@@ -1178,7 +1271,7 @@ export class ClearingHouse {
|
|
|
1178
1271
|
const settleeUserAccount = (await this.program.account.user.fetch(
|
|
1179
1272
|
settleeUserAccountPublicKey
|
|
1180
1273
|
)) as UserAccount;
|
|
1181
|
-
const userPositions = settleeUserAccount.
|
|
1274
|
+
const userPositions = settleeUserAccount.perpPositions;
|
|
1182
1275
|
const remainingAccounts = [];
|
|
1183
1276
|
|
|
1184
1277
|
let foundMarket = false;
|
|
@@ -1234,15 +1327,15 @@ export class ClearingHouse {
|
|
|
1234
1327
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1235
1328
|
|
|
1236
1329
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1237
|
-
|
|
1330
|
+
writablePerpMarketIndex: marketIndex,
|
|
1238
1331
|
});
|
|
1239
1332
|
|
|
1240
1333
|
if (sharesToBurn == undefined) {
|
|
1241
1334
|
const userAccount = this.getUserAccount();
|
|
1242
|
-
const
|
|
1335
|
+
const perpPosition = userAccount.perpPositions.filter((position) =>
|
|
1243
1336
|
position.marketIndex.eq(marketIndex)
|
|
1244
1337
|
)[0];
|
|
1245
|
-
sharesToBurn =
|
|
1338
|
+
sharesToBurn = perpPosition.lpShares;
|
|
1246
1339
|
console.log('burning lp shares:', sharesToBurn.toString());
|
|
1247
1340
|
}
|
|
1248
1341
|
|
|
@@ -1275,7 +1368,7 @@ export class ClearingHouse {
|
|
|
1275
1368
|
): Promise<TransactionInstruction> {
|
|
1276
1369
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1277
1370
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1278
|
-
|
|
1371
|
+
writablePerpMarketIndex: marketIndex,
|
|
1279
1372
|
});
|
|
1280
1373
|
|
|
1281
1374
|
return this.program.instruction.addLiquidity(amount, marketIndex, {
|
|
@@ -1303,6 +1396,60 @@ export class ClearingHouse {
|
|
|
1303
1396
|
});
|
|
1304
1397
|
}
|
|
1305
1398
|
|
|
1399
|
+
public async sendSignedTx(tx: Transaction): Promise<TransactionSignature> {
|
|
1400
|
+
const { txSig } = await this.txSender.send(tx, undefined, this.opts, true);
|
|
1401
|
+
|
|
1402
|
+
return txSig;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
/**
|
|
1406
|
+
* Sends a market order and returns a signed tx which can fill the order against the vamm, which the caller can use to fill their own order if required.
|
|
1407
|
+
* @param orderParams
|
|
1408
|
+
* @param userAccountPublicKey
|
|
1409
|
+
* @param userAccount
|
|
1410
|
+
* @returns
|
|
1411
|
+
*/
|
|
1412
|
+
public async sendMarketOrderAndGetSignedFillTx(
|
|
1413
|
+
orderParams: OptionalOrderParams,
|
|
1414
|
+
userAccountPublicKey: PublicKey,
|
|
1415
|
+
userAccount: UserAccount
|
|
1416
|
+
): Promise<{ txSig: TransactionSignature; signedFillTx: Transaction }> {
|
|
1417
|
+
const marketIndex = orderParams.marketIndex;
|
|
1418
|
+
const orderId = userAccount.nextOrderId;
|
|
1419
|
+
|
|
1420
|
+
const marketOrderTx = wrapInTx(await this.getPlaceOrderIx(orderParams));
|
|
1421
|
+
const fillTx = wrapInTx(
|
|
1422
|
+
await this.getFillOrderIx(userAccountPublicKey, userAccount, {
|
|
1423
|
+
orderId,
|
|
1424
|
+
marketIndex,
|
|
1425
|
+
})
|
|
1426
|
+
);
|
|
1427
|
+
|
|
1428
|
+
// Apply the latest blockhash to the txs so that we can sign before sending them
|
|
1429
|
+
const currentBlockHash = (
|
|
1430
|
+
await this.connection.getLatestBlockhash('finalized')
|
|
1431
|
+
).blockhash;
|
|
1432
|
+
marketOrderTx.recentBlockhash = currentBlockHash;
|
|
1433
|
+
fillTx.recentBlockhash = currentBlockHash;
|
|
1434
|
+
|
|
1435
|
+
marketOrderTx.feePayer = userAccount.authority;
|
|
1436
|
+
fillTx.feePayer = userAccount.authority;
|
|
1437
|
+
|
|
1438
|
+
const [signedMarketOrderTx, signedFillTx] =
|
|
1439
|
+
await this.provider.wallet.signAllTransactions([marketOrderTx, fillTx]);
|
|
1440
|
+
|
|
1441
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1442
|
+
signedMarketOrderTx,
|
|
1443
|
+
[],
|
|
1444
|
+
this.opts,
|
|
1445
|
+
true
|
|
1446
|
+
);
|
|
1447
|
+
|
|
1448
|
+
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
1449
|
+
|
|
1450
|
+
return { txSig, signedFillTx };
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1306
1453
|
public async placeOrder(
|
|
1307
1454
|
orderParams: OptionalOrderParams
|
|
1308
1455
|
): Promise<TransactionSignature> {
|
|
@@ -1315,18 +1462,23 @@ export class ClearingHouse {
|
|
|
1315
1462
|
return txSig;
|
|
1316
1463
|
}
|
|
1317
1464
|
|
|
1318
|
-
getOrderParams(
|
|
1319
|
-
|
|
1465
|
+
getOrderParams(
|
|
1466
|
+
optionalOrderParams: OptionalOrderParams,
|
|
1467
|
+
marketType: MarketType
|
|
1468
|
+
): OrderParams {
|
|
1469
|
+
return Object.assign({}, DefaultOrderParams, optionalOrderParams, {
|
|
1470
|
+
marketType,
|
|
1471
|
+
});
|
|
1320
1472
|
}
|
|
1321
1473
|
|
|
1322
1474
|
public async getPlaceOrderIx(
|
|
1323
1475
|
orderParams: OptionalOrderParams
|
|
1324
1476
|
): Promise<TransactionInstruction> {
|
|
1325
|
-
orderParams = this.getOrderParams(orderParams);
|
|
1477
|
+
orderParams = this.getOrderParams(orderParams, MarketType.PERP);
|
|
1326
1478
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1327
1479
|
|
|
1328
1480
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1329
|
-
|
|
1481
|
+
readablePerpMarketIndex: orderParams.marketIndex,
|
|
1330
1482
|
});
|
|
1331
1483
|
|
|
1332
1484
|
return await this.program.instruction.placeOrder(orderParams, {
|
|
@@ -1359,7 +1511,7 @@ export class ClearingHouse {
|
|
|
1359
1511
|
const oracleAccountInfos = [];
|
|
1360
1512
|
for (const marketIndex of marketIndexes) {
|
|
1361
1513
|
if (!marketIndex.eq(new BN(100))) {
|
|
1362
|
-
const market = this.
|
|
1514
|
+
const market = this.getPerpMarketAccount(marketIndex);
|
|
1363
1515
|
marketAccountInfos.push({
|
|
1364
1516
|
pubkey: market.pubkey,
|
|
1365
1517
|
isWritable: true,
|
|
@@ -1383,6 +1535,54 @@ export class ClearingHouse {
|
|
|
1383
1535
|
});
|
|
1384
1536
|
}
|
|
1385
1537
|
|
|
1538
|
+
public async settleExpiredMarket(
|
|
1539
|
+
marketIndex: BN
|
|
1540
|
+
): Promise<TransactionSignature> {
|
|
1541
|
+
const { txSig } = await this.txSender.send(
|
|
1542
|
+
wrapInTx(await this.getSettleExpiredMarketIx(marketIndex)),
|
|
1543
|
+
[],
|
|
1544
|
+
this.opts
|
|
1545
|
+
);
|
|
1546
|
+
return txSig;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
public async getSettleExpiredMarketIx(
|
|
1550
|
+
marketIndex: BN
|
|
1551
|
+
): Promise<TransactionInstruction> {
|
|
1552
|
+
const marketAccountInfos = [];
|
|
1553
|
+
const oracleAccountInfos = [];
|
|
1554
|
+
const spotMarketAccountInfos = [];
|
|
1555
|
+
const market = this.getPerpMarketAccount(marketIndex);
|
|
1556
|
+
marketAccountInfos.push({
|
|
1557
|
+
pubkey: market.pubkey,
|
|
1558
|
+
isWritable: true,
|
|
1559
|
+
isSigner: false,
|
|
1560
|
+
});
|
|
1561
|
+
oracleAccountInfos.push({
|
|
1562
|
+
pubkey: market.amm.oracle,
|
|
1563
|
+
isWritable: false,
|
|
1564
|
+
isSigner: false,
|
|
1565
|
+
});
|
|
1566
|
+
|
|
1567
|
+
spotMarketAccountInfos.push({
|
|
1568
|
+
pubkey: this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX).pubkey,
|
|
1569
|
+
isSigner: false,
|
|
1570
|
+
isWritable: true,
|
|
1571
|
+
});
|
|
1572
|
+
|
|
1573
|
+
const remainingAccounts = oracleAccountInfos
|
|
1574
|
+
.concat(spotMarketAccountInfos)
|
|
1575
|
+
.concat(marketAccountInfos);
|
|
1576
|
+
|
|
1577
|
+
return await this.program.instruction.settleExpiredMarket(marketIndex, {
|
|
1578
|
+
accounts: {
|
|
1579
|
+
state: await this.getStatePublicKey(),
|
|
1580
|
+
authority: this.wallet.publicKey,
|
|
1581
|
+
},
|
|
1582
|
+
remainingAccounts,
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1386
1586
|
public async cancelOrder(orderId?: BN): Promise<TransactionSignature> {
|
|
1387
1587
|
const { txSig } = await this.txSender.send(
|
|
1388
1588
|
wrapInTx(await this.getCancelOrderIx(orderId)),
|
|
@@ -1424,7 +1624,7 @@ export class ClearingHouse {
|
|
|
1424
1624
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1425
1625
|
|
|
1426
1626
|
const order = this.getOrderByUserId(userOrderId);
|
|
1427
|
-
const oracle = this.
|
|
1627
|
+
const oracle = this.getPerpMarketAccount(order.marketIndex).amm.oracle;
|
|
1428
1628
|
|
|
1429
1629
|
const remainingAccounts = this.getRemainingAccounts({});
|
|
1430
1630
|
|
|
@@ -1465,7 +1665,7 @@ export class ClearingHouse {
|
|
|
1465
1665
|
public async getFillOrderIx(
|
|
1466
1666
|
userAccountPublicKey: PublicKey,
|
|
1467
1667
|
userAccount: UserAccount,
|
|
1468
|
-
order: Order,
|
|
1668
|
+
order: Pick<Order, 'marketIndex' | 'orderId'>,
|
|
1469
1669
|
makerInfo?: MakerInfo,
|
|
1470
1670
|
referrerInfo?: ReferrerInfo
|
|
1471
1671
|
): Promise<TransactionInstruction> {
|
|
@@ -1482,24 +1682,26 @@ export class ClearingHouse {
|
|
|
1482
1682
|
: userAccount.orders.find((order) =>
|
|
1483
1683
|
order.orderId.eq(userAccount.nextOrderId.sub(ONE))
|
|
1484
1684
|
).marketIndex;
|
|
1485
|
-
const marketAccount = this.
|
|
1685
|
+
const marketAccount = this.getPerpMarketAccount(marketIndex);
|
|
1486
1686
|
|
|
1487
1687
|
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
1488
|
-
const
|
|
1489
|
-
const
|
|
1688
|
+
const spotMarketAccountMap = new Map<number, AccountMeta>();
|
|
1689
|
+
const perpMarketAccountMap = new Map<number, AccountMeta>();
|
|
1490
1690
|
|
|
1491
|
-
for (const
|
|
1492
|
-
if (!
|
|
1493
|
-
const
|
|
1494
|
-
|
|
1495
|
-
|
|
1691
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
1692
|
+
if (!isSpotPositionAvailable(spotPosition)) {
|
|
1693
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
1694
|
+
spotPosition.marketIndex
|
|
1695
|
+
);
|
|
1696
|
+
spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
|
|
1697
|
+
pubkey: spotMarketAccount.pubkey,
|
|
1496
1698
|
isSigner: false,
|
|
1497
1699
|
isWritable: false,
|
|
1498
1700
|
});
|
|
1499
1701
|
|
|
1500
|
-
if (!
|
|
1501
|
-
oracleAccountMap.set(
|
|
1502
|
-
pubkey:
|
|
1702
|
+
if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
|
|
1703
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
1704
|
+
pubkey: spotMarketAccount.oracle,
|
|
1503
1705
|
isSigner: false,
|
|
1504
1706
|
isWritable: false,
|
|
1505
1707
|
});
|
|
@@ -1507,13 +1709,13 @@ export class ClearingHouse {
|
|
|
1507
1709
|
}
|
|
1508
1710
|
}
|
|
1509
1711
|
|
|
1510
|
-
for (const position of userAccount.
|
|
1712
|
+
for (const position of userAccount.perpPositions) {
|
|
1511
1713
|
if (
|
|
1512
1714
|
!positionIsAvailable(position) &&
|
|
1513
1715
|
!position.marketIndex.eq(order.marketIndex)
|
|
1514
1716
|
) {
|
|
1515
|
-
const market = this.
|
|
1516
|
-
|
|
1717
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1718
|
+
perpMarketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1517
1719
|
pubkey: market.pubkey,
|
|
1518
1720
|
isWritable: false,
|
|
1519
1721
|
isSigner: false,
|
|
@@ -1526,7 +1728,7 @@ export class ClearingHouse {
|
|
|
1526
1728
|
}
|
|
1527
1729
|
}
|
|
1528
1730
|
|
|
1529
|
-
|
|
1731
|
+
perpMarketAccountMap.set(marketIndex.toNumber(), {
|
|
1530
1732
|
pubkey: marketAccount.pubkey,
|
|
1531
1733
|
isWritable: true,
|
|
1532
1734
|
isSigner: false,
|
|
@@ -1539,8 +1741,8 @@ export class ClearingHouse {
|
|
|
1539
1741
|
|
|
1540
1742
|
const remainingAccounts = [
|
|
1541
1743
|
...oracleAccountMap.values(),
|
|
1542
|
-
...
|
|
1543
|
-
...
|
|
1744
|
+
...spotMarketAccountMap.values(),
|
|
1745
|
+
...perpMarketAccountMap.values(),
|
|
1544
1746
|
];
|
|
1545
1747
|
|
|
1546
1748
|
if (makerInfo) {
|
|
@@ -1585,45 +1787,101 @@ export class ClearingHouse {
|
|
|
1585
1787
|
});
|
|
1586
1788
|
}
|
|
1587
1789
|
|
|
1588
|
-
public async
|
|
1790
|
+
public async placeSpotOrder(
|
|
1791
|
+
orderParams: OptionalOrderParams
|
|
1792
|
+
): Promise<TransactionSignature> {
|
|
1793
|
+
const { txSig } = await this.txSender.send(
|
|
1794
|
+
wrapInTx(await this.getPlaceSpotOrderIx(orderParams)),
|
|
1795
|
+
[],
|
|
1796
|
+
this.opts
|
|
1797
|
+
);
|
|
1798
|
+
return txSig;
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
public async getPlaceSpotOrderIx(
|
|
1802
|
+
orderParams: OptionalOrderParams
|
|
1803
|
+
): Promise<TransactionInstruction> {
|
|
1804
|
+
orderParams = this.getOrderParams(orderParams, MarketType.SPOT);
|
|
1805
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1806
|
+
|
|
1807
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1808
|
+
readableSpotMarketIndex: orderParams.marketIndex,
|
|
1809
|
+
});
|
|
1810
|
+
|
|
1811
|
+
return await this.program.instruction.placeSpotOrder(orderParams, {
|
|
1812
|
+
accounts: {
|
|
1813
|
+
state: await this.getStatePublicKey(),
|
|
1814
|
+
user: userAccountPublicKey,
|
|
1815
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
1816
|
+
authority: this.wallet.publicKey,
|
|
1817
|
+
},
|
|
1818
|
+
remainingAccounts,
|
|
1819
|
+
});
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
public async fillSpotOrder(
|
|
1589
1823
|
userAccountPublicKey: PublicKey,
|
|
1590
1824
|
user: UserAccount,
|
|
1591
|
-
order
|
|
1825
|
+
order?: Order,
|
|
1826
|
+
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
|
|
1827
|
+
makerInfo?: MakerInfo,
|
|
1828
|
+
referrerInfo?: ReferrerInfo
|
|
1592
1829
|
): Promise<TransactionSignature> {
|
|
1593
1830
|
const { txSig } = await this.txSender.send(
|
|
1594
|
-
wrapInTx(
|
|
1831
|
+
wrapInTx(
|
|
1832
|
+
await this.getFillSpotOrderIx(
|
|
1833
|
+
userAccountPublicKey,
|
|
1834
|
+
user,
|
|
1835
|
+
order,
|
|
1836
|
+
fulfillmentConfig,
|
|
1837
|
+
makerInfo,
|
|
1838
|
+
referrerInfo
|
|
1839
|
+
)
|
|
1840
|
+
),
|
|
1595
1841
|
[],
|
|
1596
1842
|
this.opts
|
|
1597
1843
|
);
|
|
1598
1844
|
return txSig;
|
|
1599
1845
|
}
|
|
1600
1846
|
|
|
1601
|
-
public async
|
|
1847
|
+
public async getFillSpotOrderIx(
|
|
1602
1848
|
userAccountPublicKey: PublicKey,
|
|
1603
1849
|
userAccount: UserAccount,
|
|
1604
|
-
order
|
|
1850
|
+
order?: Order,
|
|
1851
|
+
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
|
|
1852
|
+
makerInfo?: MakerInfo,
|
|
1853
|
+
referrerInfo?: ReferrerInfo
|
|
1605
1854
|
): Promise<TransactionInstruction> {
|
|
1855
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
1856
|
+
this.program.programId,
|
|
1857
|
+
userAccount.authority
|
|
1858
|
+
);
|
|
1859
|
+
|
|
1606
1860
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1861
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1607
1862
|
|
|
1608
|
-
const marketIndex = order
|
|
1609
|
-
|
|
1863
|
+
const marketIndex = order
|
|
1864
|
+
? order.marketIndex
|
|
1865
|
+
: userAccount.orders.find((order) =>
|
|
1866
|
+
order.orderId.eq(userAccount.nextOrderId.sub(ONE))
|
|
1867
|
+
).marketIndex;
|
|
1610
1868
|
|
|
1611
1869
|
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
1612
|
-
const
|
|
1613
|
-
const
|
|
1614
|
-
|
|
1615
|
-
for (const
|
|
1616
|
-
if (!
|
|
1617
|
-
const
|
|
1618
|
-
|
|
1619
|
-
pubkey:
|
|
1870
|
+
const spotMarketAccountMap = new Map<number, AccountMeta>();
|
|
1871
|
+
const perpMarketAccountMap = new Map<number, AccountMeta>();
|
|
1872
|
+
|
|
1873
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
1874
|
+
if (!isSpotPositionAvailable(spotPosition)) {
|
|
1875
|
+
const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1876
|
+
spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
|
|
1877
|
+
pubkey: spotMarket.pubkey,
|
|
1620
1878
|
isSigner: false,
|
|
1621
1879
|
isWritable: false,
|
|
1622
1880
|
});
|
|
1623
1881
|
|
|
1624
|
-
if (!
|
|
1625
|
-
oracleAccountMap.set(
|
|
1626
|
-
pubkey:
|
|
1882
|
+
if (!spotMarket.oracle.equals(PublicKey.default)) {
|
|
1883
|
+
oracleAccountMap.set(spotMarket.oracle.toString(), {
|
|
1884
|
+
pubkey: spotMarket.oracle,
|
|
1627
1885
|
isSigner: false,
|
|
1628
1886
|
isWritable: false,
|
|
1629
1887
|
});
|
|
@@ -1631,13 +1889,13 @@ export class ClearingHouse {
|
|
|
1631
1889
|
}
|
|
1632
1890
|
}
|
|
1633
1891
|
|
|
1634
|
-
for (const position of userAccount.
|
|
1892
|
+
for (const position of userAccount.perpPositions) {
|
|
1635
1893
|
if (
|
|
1636
1894
|
!positionIsAvailable(position) &&
|
|
1637
1895
|
!position.marketIndex.eq(order.marketIndex)
|
|
1638
1896
|
) {
|
|
1639
|
-
const market = this.
|
|
1640
|
-
|
|
1897
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1898
|
+
perpMarketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1641
1899
|
pubkey: market.pubkey,
|
|
1642
1900
|
isWritable: false,
|
|
1643
1901
|
isSigner: false,
|
|
@@ -1650,77 +1908,42 @@ export class ClearingHouse {
|
|
|
1650
1908
|
}
|
|
1651
1909
|
}
|
|
1652
1910
|
|
|
1653
|
-
|
|
1654
|
-
|
|
1911
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
1912
|
+
spotMarketAccountMap.set(marketIndex.toNumber(), {
|
|
1913
|
+
pubkey: spotMarketAccount.pubkey,
|
|
1655
1914
|
isWritable: true,
|
|
1656
1915
|
isSigner: false,
|
|
1657
1916
|
});
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1917
|
+
if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
|
|
1918
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
1919
|
+
pubkey: spotMarketAccount.oracle,
|
|
1920
|
+
isWritable: false,
|
|
1921
|
+
isSigner: false,
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
const quoteMarketAccount = this.getQuoteSpotMarketAccount();
|
|
1925
|
+
spotMarketAccountMap.set(quoteMarketAccount.marketIndex.toNumber(), {
|
|
1926
|
+
pubkey: quoteMarketAccount.pubkey,
|
|
1927
|
+
isWritable: true,
|
|
1661
1928
|
isSigner: false,
|
|
1662
1929
|
});
|
|
1663
1930
|
|
|
1664
1931
|
const remainingAccounts = [
|
|
1665
1932
|
...oracleAccountMap.values(),
|
|
1666
|
-
...
|
|
1667
|
-
...
|
|
1933
|
+
...spotMarketAccountMap.values(),
|
|
1934
|
+
...perpMarketAccountMap.values(),
|
|
1668
1935
|
];
|
|
1669
1936
|
|
|
1670
|
-
const orderId = order.orderId;
|
|
1671
|
-
return await this.program.instruction.triggerOrder(orderId, {
|
|
1672
|
-
accounts: {
|
|
1673
|
-
state: await this.getStatePublicKey(),
|
|
1674
|
-
filler: fillerPublicKey,
|
|
1675
|
-
user: userAccountPublicKey,
|
|
1676
|
-
authority: this.wallet.publicKey,
|
|
1677
|
-
},
|
|
1678
|
-
remainingAccounts,
|
|
1679
|
-
});
|
|
1680
|
-
}
|
|
1681
|
-
|
|
1682
|
-
public async placeAndTake(
|
|
1683
|
-
orderParams: OptionalOrderParams,
|
|
1684
|
-
makerInfo?: MakerInfo,
|
|
1685
|
-
referrerInfo?: ReferrerInfo
|
|
1686
|
-
): Promise<TransactionSignature> {
|
|
1687
|
-
const { txSig, slot } = await this.txSender.send(
|
|
1688
|
-
wrapInTx(
|
|
1689
|
-
await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)
|
|
1690
|
-
),
|
|
1691
|
-
[],
|
|
1692
|
-
this.opts
|
|
1693
|
-
);
|
|
1694
|
-
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
1695
|
-
return txSig;
|
|
1696
|
-
}
|
|
1697
|
-
|
|
1698
|
-
public async getPlaceAndTakeIx(
|
|
1699
|
-
orderParams: OptionalOrderParams,
|
|
1700
|
-
makerInfo?: MakerInfo,
|
|
1701
|
-
referrerInfo?: ReferrerInfo
|
|
1702
|
-
): Promise<TransactionInstruction> {
|
|
1703
|
-
orderParams = this.getOrderParams(orderParams);
|
|
1704
|
-
const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
1705
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1706
|
-
|
|
1707
|
-
const remainingAccounts = this.getRemainingAccounts({
|
|
1708
|
-
writableMarketIndex: orderParams.marketIndex,
|
|
1709
|
-
writableBankIndex: QUOTE_ASSET_BANK_INDEX,
|
|
1710
|
-
});
|
|
1711
|
-
|
|
1712
|
-
let makerOrderId = null;
|
|
1713
1937
|
if (makerInfo) {
|
|
1714
|
-
makerOrderId = makerInfo.order.orderId;
|
|
1715
1938
|
remainingAccounts.push({
|
|
1716
1939
|
pubkey: makerInfo.maker,
|
|
1717
|
-
isSigner: false,
|
|
1718
1940
|
isWritable: true,
|
|
1941
|
+
isSigner: false,
|
|
1719
1942
|
});
|
|
1720
1943
|
remainingAccounts.push({
|
|
1721
1944
|
pubkey: makerInfo.makerStats,
|
|
1722
|
-
isSigner: false,
|
|
1723
1945
|
isWritable: true,
|
|
1946
|
+
isSigner: false,
|
|
1724
1947
|
});
|
|
1725
1948
|
}
|
|
1726
1949
|
|
|
@@ -1737,9 +1960,370 @@ export class ClearingHouse {
|
|
|
1737
1960
|
});
|
|
1738
1961
|
}
|
|
1739
1962
|
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1963
|
+
const orderId = order.orderId;
|
|
1964
|
+
const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
|
|
1965
|
+
|
|
1966
|
+
if (fulfillmentConfig) {
|
|
1967
|
+
remainingAccounts.push({
|
|
1968
|
+
pubkey: fulfillmentConfig.pubkey,
|
|
1969
|
+
isWritable: false,
|
|
1970
|
+
isSigner: false,
|
|
1971
|
+
});
|
|
1972
|
+
remainingAccounts.push({
|
|
1973
|
+
pubkey: fulfillmentConfig.serumProgramId,
|
|
1974
|
+
isWritable: false,
|
|
1975
|
+
isSigner: false,
|
|
1976
|
+
});
|
|
1977
|
+
remainingAccounts.push({
|
|
1978
|
+
pubkey: fulfillmentConfig.serumMarket,
|
|
1979
|
+
isWritable: true,
|
|
1980
|
+
isSigner: false,
|
|
1981
|
+
});
|
|
1982
|
+
remainingAccounts.push({
|
|
1983
|
+
pubkey: fulfillmentConfig.serumRequestQueue,
|
|
1984
|
+
isWritable: true,
|
|
1985
|
+
isSigner: false,
|
|
1986
|
+
});
|
|
1987
|
+
remainingAccounts.push({
|
|
1988
|
+
pubkey: fulfillmentConfig.serumEventQueue,
|
|
1989
|
+
isWritable: true,
|
|
1990
|
+
isSigner: false,
|
|
1991
|
+
});
|
|
1992
|
+
remainingAccounts.push({
|
|
1993
|
+
pubkey: fulfillmentConfig.serumBids,
|
|
1994
|
+
isWritable: true,
|
|
1995
|
+
isSigner: false,
|
|
1996
|
+
});
|
|
1997
|
+
remainingAccounts.push({
|
|
1998
|
+
pubkey: fulfillmentConfig.serumAsks,
|
|
1999
|
+
isWritable: true,
|
|
2000
|
+
isSigner: false,
|
|
2001
|
+
});
|
|
2002
|
+
remainingAccounts.push({
|
|
2003
|
+
pubkey: fulfillmentConfig.serumBaseVault,
|
|
2004
|
+
isWritable: true,
|
|
2005
|
+
isSigner: false,
|
|
2006
|
+
});
|
|
2007
|
+
remainingAccounts.push({
|
|
2008
|
+
pubkey: fulfillmentConfig.serumQuoteVault,
|
|
2009
|
+
isWritable: true,
|
|
2010
|
+
isSigner: false,
|
|
2011
|
+
});
|
|
2012
|
+
remainingAccounts.push({
|
|
2013
|
+
pubkey: fulfillmentConfig.serumOpenOrders,
|
|
2014
|
+
isWritable: true,
|
|
2015
|
+
isSigner: false,
|
|
2016
|
+
});
|
|
2017
|
+
remainingAccounts.push({
|
|
2018
|
+
pubkey: getSerumSignerPublicKey(
|
|
2019
|
+
fulfillmentConfig.serumProgramId,
|
|
2020
|
+
fulfillmentConfig.serumMarket,
|
|
2021
|
+
fulfillmentConfig.serumSignerNonce
|
|
2022
|
+
),
|
|
2023
|
+
isWritable: false,
|
|
2024
|
+
isSigner: false,
|
|
2025
|
+
});
|
|
2026
|
+
remainingAccounts.push({
|
|
2027
|
+
pubkey: this.getSignerPublicKey(),
|
|
2028
|
+
isWritable: false,
|
|
2029
|
+
isSigner: false,
|
|
2030
|
+
});
|
|
2031
|
+
remainingAccounts.push({
|
|
2032
|
+
pubkey: TOKEN_PROGRAM_ID,
|
|
2033
|
+
isWritable: false,
|
|
2034
|
+
isSigner: false,
|
|
2035
|
+
});
|
|
2036
|
+
remainingAccounts.push({
|
|
2037
|
+
pubkey: spotMarketAccount.vault,
|
|
2038
|
+
isWritable: true,
|
|
2039
|
+
isSigner: false,
|
|
2040
|
+
});
|
|
2041
|
+
remainingAccounts.push({
|
|
2042
|
+
pubkey: quoteMarketAccount.vault,
|
|
2043
|
+
isWritable: true,
|
|
2044
|
+
isSigner: false,
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
return await this.program.instruction.fillSpotOrder(
|
|
2049
|
+
orderId,
|
|
2050
|
+
fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null,
|
|
2051
|
+
makerOrderId,
|
|
2052
|
+
{
|
|
2053
|
+
accounts: {
|
|
2054
|
+
state: await this.getStatePublicKey(),
|
|
2055
|
+
filler: fillerPublicKey,
|
|
2056
|
+
fillerStats: fillerStatsPublicKey,
|
|
2057
|
+
user: userAccountPublicKey,
|
|
2058
|
+
userStats: userStatsPublicKey,
|
|
2059
|
+
authority: this.wallet.publicKey,
|
|
2060
|
+
},
|
|
2061
|
+
remainingAccounts,
|
|
2062
|
+
}
|
|
2063
|
+
);
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
public async triggerOrder(
|
|
2067
|
+
userAccountPublicKey: PublicKey,
|
|
2068
|
+
user: UserAccount,
|
|
2069
|
+
order: Order
|
|
2070
|
+
): Promise<TransactionSignature> {
|
|
2071
|
+
const { txSig } = await this.txSender.send(
|
|
2072
|
+
wrapInTx(await this.getTriggerOrderIx(userAccountPublicKey, user, order)),
|
|
2073
|
+
[],
|
|
2074
|
+
this.opts
|
|
2075
|
+
);
|
|
2076
|
+
return txSig;
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
public async getTriggerOrderIx(
|
|
2080
|
+
userAccountPublicKey: PublicKey,
|
|
2081
|
+
userAccount: UserAccount,
|
|
2082
|
+
order: Order
|
|
2083
|
+
): Promise<TransactionInstruction> {
|
|
2084
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
2085
|
+
|
|
2086
|
+
const marketIndex = order.marketIndex;
|
|
2087
|
+
const marketAccount = this.getPerpMarketAccount(marketIndex);
|
|
2088
|
+
|
|
2089
|
+
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
2090
|
+
const spotMarketAccountMap = new Map<number, AccountMeta>();
|
|
2091
|
+
const perpMarketAccountMap = new Map<number, AccountMeta>();
|
|
2092
|
+
|
|
2093
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
2094
|
+
if (!isSpotPositionAvailable(spotPosition)) {
|
|
2095
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
2096
|
+
spotPosition.marketIndex
|
|
2097
|
+
);
|
|
2098
|
+
spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
|
|
2099
|
+
pubkey: spotMarketAccount.pubkey,
|
|
2100
|
+
isSigner: false,
|
|
2101
|
+
isWritable: false,
|
|
2102
|
+
});
|
|
2103
|
+
|
|
2104
|
+
if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
|
|
2105
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
2106
|
+
pubkey: spotMarketAccount.oracle,
|
|
2107
|
+
isSigner: false,
|
|
2108
|
+
isWritable: false,
|
|
2109
|
+
});
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
for (const position of userAccount.perpPositions) {
|
|
2115
|
+
if (
|
|
2116
|
+
!positionIsAvailable(position) &&
|
|
2117
|
+
!position.marketIndex.eq(order.marketIndex)
|
|
2118
|
+
) {
|
|
2119
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
2120
|
+
perpMarketAccountMap.set(position.marketIndex.toNumber(), {
|
|
2121
|
+
pubkey: market.pubkey,
|
|
2122
|
+
isWritable: false,
|
|
2123
|
+
isSigner: false,
|
|
2124
|
+
});
|
|
2125
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
2126
|
+
pubkey: market.amm.oracle,
|
|
2127
|
+
isWritable: false,
|
|
2128
|
+
isSigner: false,
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
perpMarketAccountMap.set(marketIndex.toNumber(), {
|
|
2134
|
+
pubkey: marketAccount.pubkey,
|
|
2135
|
+
isWritable: true,
|
|
2136
|
+
isSigner: false,
|
|
2137
|
+
});
|
|
2138
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
2139
|
+
pubkey: marketAccount.amm.oracle,
|
|
2140
|
+
isWritable: false,
|
|
2141
|
+
isSigner: false,
|
|
2142
|
+
});
|
|
2143
|
+
|
|
2144
|
+
const remainingAccounts = [
|
|
2145
|
+
...oracleAccountMap.values(),
|
|
2146
|
+
...spotMarketAccountMap.values(),
|
|
2147
|
+
...perpMarketAccountMap.values(),
|
|
2148
|
+
];
|
|
2149
|
+
|
|
2150
|
+
const orderId = order.orderId;
|
|
2151
|
+
return await this.program.instruction.triggerOrder(orderId, {
|
|
2152
|
+
accounts: {
|
|
2153
|
+
state: await this.getStatePublicKey(),
|
|
2154
|
+
filler: fillerPublicKey,
|
|
2155
|
+
user: userAccountPublicKey,
|
|
2156
|
+
authority: this.wallet.publicKey,
|
|
2157
|
+
},
|
|
2158
|
+
remainingAccounts,
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
public async triggerSpotOrder(
|
|
2163
|
+
userAccountPublicKey: PublicKey,
|
|
2164
|
+
user: UserAccount,
|
|
2165
|
+
order: Order
|
|
2166
|
+
): Promise<TransactionSignature> {
|
|
2167
|
+
const { txSig } = await this.txSender.send(
|
|
2168
|
+
wrapInTx(
|
|
2169
|
+
await this.getTriggerSpotOrderIx(userAccountPublicKey, user, order)
|
|
2170
|
+
),
|
|
2171
|
+
[],
|
|
2172
|
+
this.opts
|
|
2173
|
+
);
|
|
2174
|
+
return txSig;
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
public async getTriggerSpotOrderIx(
|
|
2178
|
+
userAccountPublicKey: PublicKey,
|
|
2179
|
+
userAccount: UserAccount,
|
|
2180
|
+
order: Order
|
|
2181
|
+
): Promise<TransactionInstruction> {
|
|
2182
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
2183
|
+
|
|
2184
|
+
const marketIndex = order.marketIndex;
|
|
2185
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2186
|
+
|
|
2187
|
+
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
2188
|
+
const spotMarketAccountMap = new Map<number, AccountMeta>();
|
|
2189
|
+
const perpMarketAccountMap = new Map<number, AccountMeta>();
|
|
2190
|
+
|
|
2191
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
2192
|
+
if (!isSpotPositionAvailable(spotPosition)) {
|
|
2193
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
2194
|
+
spotPosition.marketIndex
|
|
2195
|
+
);
|
|
2196
|
+
spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
|
|
2197
|
+
pubkey: spotMarketAccount.pubkey,
|
|
2198
|
+
isSigner: false,
|
|
2199
|
+
isWritable: false,
|
|
2200
|
+
});
|
|
2201
|
+
|
|
2202
|
+
if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
|
|
2203
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
2204
|
+
pubkey: spotMarketAccount.oracle,
|
|
2205
|
+
isSigner: false,
|
|
2206
|
+
isWritable: false,
|
|
2207
|
+
});
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
for (const position of userAccount.perpPositions) {
|
|
2213
|
+
if (
|
|
2214
|
+
!positionIsAvailable(position) &&
|
|
2215
|
+
!position.marketIndex.eq(order.marketIndex)
|
|
2216
|
+
) {
|
|
2217
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
2218
|
+
perpMarketAccountMap.set(position.marketIndex.toNumber(), {
|
|
2219
|
+
pubkey: market.pubkey,
|
|
2220
|
+
isWritable: false,
|
|
2221
|
+
isSigner: false,
|
|
2222
|
+
});
|
|
2223
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
2224
|
+
pubkey: market.amm.oracle,
|
|
2225
|
+
isWritable: false,
|
|
2226
|
+
isSigner: false,
|
|
2227
|
+
});
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
const quoteSpotMarket = this.getQuoteSpotMarketAccount();
|
|
2232
|
+
spotMarketAccountMap.set(quoteSpotMarket.marketIndex.toNumber(), {
|
|
2233
|
+
pubkey: quoteSpotMarket.pubkey,
|
|
2234
|
+
isWritable: true,
|
|
2235
|
+
isSigner: false,
|
|
2236
|
+
});
|
|
2237
|
+
spotMarketAccountMap.set(marketIndex.toNumber(), {
|
|
2238
|
+
pubkey: spotMarketAccount.pubkey,
|
|
2239
|
+
isWritable: false,
|
|
2240
|
+
isSigner: false,
|
|
2241
|
+
});
|
|
2242
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
2243
|
+
pubkey: spotMarketAccount.oracle,
|
|
2244
|
+
isWritable: false,
|
|
2245
|
+
isSigner: false,
|
|
2246
|
+
});
|
|
2247
|
+
|
|
2248
|
+
const remainingAccounts = [
|
|
2249
|
+
...oracleAccountMap.values(),
|
|
2250
|
+
...spotMarketAccountMap.values(),
|
|
2251
|
+
...perpMarketAccountMap.values(),
|
|
2252
|
+
];
|
|
2253
|
+
|
|
2254
|
+
const orderId = order.orderId;
|
|
2255
|
+
return await this.program.instruction.triggerSpotOrder(orderId, {
|
|
2256
|
+
accounts: {
|
|
2257
|
+
state: await this.getStatePublicKey(),
|
|
2258
|
+
filler: fillerPublicKey,
|
|
2259
|
+
user: userAccountPublicKey,
|
|
2260
|
+
authority: this.wallet.publicKey,
|
|
2261
|
+
},
|
|
2262
|
+
remainingAccounts,
|
|
2263
|
+
});
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
public async placeAndTake(
|
|
2267
|
+
orderParams: OptionalOrderParams,
|
|
2268
|
+
makerInfo?: MakerInfo,
|
|
2269
|
+
referrerInfo?: ReferrerInfo
|
|
2270
|
+
): Promise<TransactionSignature> {
|
|
2271
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2272
|
+
wrapInTx(
|
|
2273
|
+
await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)
|
|
2274
|
+
),
|
|
2275
|
+
[],
|
|
2276
|
+
this.opts
|
|
2277
|
+
);
|
|
2278
|
+
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
2279
|
+
return txSig;
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
public async getPlaceAndTakeIx(
|
|
2283
|
+
orderParams: OptionalOrderParams,
|
|
2284
|
+
makerInfo?: MakerInfo,
|
|
2285
|
+
referrerInfo?: ReferrerInfo
|
|
2286
|
+
): Promise<TransactionInstruction> {
|
|
2287
|
+
orderParams = this.getOrderParams(orderParams, MarketType.PERP);
|
|
2288
|
+
const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
2289
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
2290
|
+
|
|
2291
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2292
|
+
writablePerpMarketIndex: orderParams.marketIndex,
|
|
2293
|
+
writableSpotMarketIndex: QUOTE_SPOT_MARKET_INDEX,
|
|
2294
|
+
});
|
|
2295
|
+
|
|
2296
|
+
let makerOrderId = null;
|
|
2297
|
+
if (makerInfo) {
|
|
2298
|
+
makerOrderId = makerInfo.order.orderId;
|
|
2299
|
+
remainingAccounts.push({
|
|
2300
|
+
pubkey: makerInfo.maker,
|
|
2301
|
+
isSigner: false,
|
|
2302
|
+
isWritable: true,
|
|
2303
|
+
});
|
|
2304
|
+
remainingAccounts.push({
|
|
2305
|
+
pubkey: makerInfo.makerStats,
|
|
2306
|
+
isSigner: false,
|
|
2307
|
+
isWritable: true,
|
|
2308
|
+
});
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
if (referrerInfo) {
|
|
2312
|
+
remainingAccounts.push({
|
|
2313
|
+
pubkey: referrerInfo.referrer,
|
|
2314
|
+
isWritable: true,
|
|
2315
|
+
isSigner: false,
|
|
2316
|
+
});
|
|
2317
|
+
remainingAccounts.push({
|
|
2318
|
+
pubkey: referrerInfo.referrerStats,
|
|
2319
|
+
isWritable: true,
|
|
2320
|
+
isSigner: false,
|
|
2321
|
+
});
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
return await this.program.instruction.placeAndTake(
|
|
2325
|
+
orderParams,
|
|
2326
|
+
makerOrderId,
|
|
1743
2327
|
{
|
|
1744
2328
|
accounts: {
|
|
1745
2329
|
state: await this.getStatePublicKey(),
|
|
@@ -1775,14 +2359,14 @@ export class ClearingHouse {
|
|
|
1775
2359
|
takerInfo: TakerInfo,
|
|
1776
2360
|
referrerInfo?: ReferrerInfo
|
|
1777
2361
|
): Promise<TransactionInstruction> {
|
|
1778
|
-
orderParams = this.getOrderParams(orderParams);
|
|
2362
|
+
orderParams = this.getOrderParams(orderParams, MarketType.PERP);
|
|
1779
2363
|
const userStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1780
2364
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1781
2365
|
|
|
1782
2366
|
// todo merge this with getRemainingAccounts
|
|
1783
2367
|
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1784
2368
|
counterPartyUserAccount: takerInfo.takerUserAccount,
|
|
1785
|
-
|
|
2369
|
+
writablePerpMarketIndex: orderParams.marketIndex,
|
|
1786
2370
|
});
|
|
1787
2371
|
|
|
1788
2372
|
if (referrerInfo) {
|
|
@@ -1895,13 +2479,110 @@ export class ClearingHouse {
|
|
|
1895
2479
|
settleeUserAccount: UserAccount,
|
|
1896
2480
|
marketIndex: BN
|
|
1897
2481
|
): Promise<TransactionInstruction> {
|
|
1898
|
-
const
|
|
2482
|
+
const perpMarketAccountMap = new Map<number, AccountMeta>();
|
|
1899
2483
|
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
1900
|
-
const
|
|
2484
|
+
const spotMarketAccountMap = new Map<number, AccountMeta>();
|
|
2485
|
+
|
|
2486
|
+
for (const position of settleeUserAccount.perpPositions) {
|
|
2487
|
+
if (!positionIsAvailable(position)) {
|
|
2488
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
2489
|
+
perpMarketAccountMap.set(position.marketIndex.toNumber(), {
|
|
2490
|
+
pubkey: market.pubkey,
|
|
2491
|
+
isWritable: false,
|
|
2492
|
+
isSigner: false,
|
|
2493
|
+
});
|
|
2494
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
2495
|
+
pubkey: market.amm.oracle,
|
|
2496
|
+
isWritable: false,
|
|
2497
|
+
isSigner: false,
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
for (const spotPosition of settleeUserAccount.spotPositions) {
|
|
2503
|
+
if (!isSpotPositionAvailable(spotPosition)) {
|
|
2504
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
2505
|
+
spotPosition.marketIndex
|
|
2506
|
+
);
|
|
2507
|
+
spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
|
|
2508
|
+
pubkey: spotMarketAccount.pubkey,
|
|
2509
|
+
isSigner: false,
|
|
2510
|
+
isWritable: false,
|
|
2511
|
+
});
|
|
2512
|
+
if (!spotMarketAccount.marketIndex.eq(ZERO)) {
|
|
2513
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
2514
|
+
pubkey: spotMarketAccount.oracle,
|
|
2515
|
+
isSigner: false,
|
|
2516
|
+
isWritable: false,
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
const marketAccount = this.getPerpMarketAccount(marketIndex.toNumber());
|
|
2523
|
+
perpMarketAccountMap.set(marketIndex.toNumber(), {
|
|
2524
|
+
pubkey: marketAccount.pubkey,
|
|
2525
|
+
isSigner: false,
|
|
2526
|
+
isWritable: true,
|
|
2527
|
+
});
|
|
2528
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
2529
|
+
pubkey: marketAccount.amm.oracle,
|
|
2530
|
+
isSigner: false,
|
|
2531
|
+
isWritable: false,
|
|
2532
|
+
});
|
|
1901
2533
|
|
|
1902
|
-
|
|
2534
|
+
spotMarketAccountMap.set(QUOTE_SPOT_MARKET_INDEX.toNumber(), {
|
|
2535
|
+
pubkey: this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX).pubkey,
|
|
2536
|
+
isSigner: false,
|
|
2537
|
+
isWritable: true,
|
|
2538
|
+
});
|
|
2539
|
+
|
|
2540
|
+
const remainingAccounts = [
|
|
2541
|
+
...oracleAccountMap.values(),
|
|
2542
|
+
...spotMarketAccountMap.values(),
|
|
2543
|
+
...perpMarketAccountMap.values(),
|
|
2544
|
+
];
|
|
2545
|
+
|
|
2546
|
+
return await this.program.instruction.settlePnl(marketIndex, {
|
|
2547
|
+
accounts: {
|
|
2548
|
+
state: await this.getStatePublicKey(),
|
|
2549
|
+
authority: this.wallet.publicKey,
|
|
2550
|
+
user: settleeUserAccountPublicKey,
|
|
2551
|
+
},
|
|
2552
|
+
remainingAccounts: remainingAccounts,
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
public async settleExpiredPosition(
|
|
2557
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
2558
|
+
settleeUserAccount: UserAccount,
|
|
2559
|
+
marketIndex: BN
|
|
2560
|
+
): Promise<TransactionSignature> {
|
|
2561
|
+
const { txSig } = await this.txSender.send(
|
|
2562
|
+
wrapInTx(
|
|
2563
|
+
await this.getSettleExpiredPositionIx(
|
|
2564
|
+
settleeUserAccountPublicKey,
|
|
2565
|
+
settleeUserAccount,
|
|
2566
|
+
marketIndex
|
|
2567
|
+
)
|
|
2568
|
+
),
|
|
2569
|
+
[],
|
|
2570
|
+
this.opts
|
|
2571
|
+
);
|
|
2572
|
+
return txSig;
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
public async getSettleExpiredPositionIx(
|
|
2576
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
2577
|
+
settleeUserAccount: UserAccount,
|
|
2578
|
+
marketIndex: BN
|
|
2579
|
+
): Promise<TransactionInstruction> {
|
|
2580
|
+
const marketAccountMap = new Map<number, AccountMeta>();
|
|
2581
|
+
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
2582
|
+
const spotMarketAccountMap = new Map<number, AccountMeta>();
|
|
2583
|
+
for (const position of settleeUserAccount.perpPositions) {
|
|
1903
2584
|
if (!positionIsAvailable(position)) {
|
|
1904
|
-
const market = this.
|
|
2585
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1905
2586
|
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1906
2587
|
pubkey: market.pubkey,
|
|
1907
2588
|
isWritable: false,
|
|
@@ -1915,15 +2596,17 @@ export class ClearingHouse {
|
|
|
1915
2596
|
}
|
|
1916
2597
|
}
|
|
1917
2598
|
|
|
1918
|
-
for (const userBankBalance of settleeUserAccount.
|
|
1919
|
-
if (!userBankBalance.balance.eq(
|
|
1920
|
-
const bankAccount = this.
|
|
1921
|
-
|
|
2599
|
+
for (const userBankBalance of settleeUserAccount.spotPositions) {
|
|
2600
|
+
if (!userBankBalance.balance.eq(ZERO)) {
|
|
2601
|
+
const bankAccount = this.getSpotMarketAccount(
|
|
2602
|
+
userBankBalance.marketIndex
|
|
2603
|
+
);
|
|
2604
|
+
spotMarketAccountMap.set(userBankBalance.marketIndex.toNumber(), {
|
|
1922
2605
|
pubkey: bankAccount.pubkey,
|
|
1923
2606
|
isSigner: false,
|
|
1924
2607
|
isWritable: false,
|
|
1925
2608
|
});
|
|
1926
|
-
if (!bankAccount.
|
|
2609
|
+
if (!bankAccount.marketIndex.eq(ZERO)) {
|
|
1927
2610
|
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1928
2611
|
pubkey: bankAccount.oracle,
|
|
1929
2612
|
isSigner: false,
|
|
@@ -1933,7 +2616,7 @@ export class ClearingHouse {
|
|
|
1933
2616
|
}
|
|
1934
2617
|
}
|
|
1935
2618
|
|
|
1936
|
-
const marketAccount = this.
|
|
2619
|
+
const marketAccount = this.getPerpMarketAccount(marketIndex.toNumber());
|
|
1937
2620
|
marketAccountMap.set(marketIndex.toNumber(), {
|
|
1938
2621
|
pubkey: marketAccount.pubkey,
|
|
1939
2622
|
isSigner: false,
|
|
@@ -1945,19 +2628,19 @@ export class ClearingHouse {
|
|
|
1945
2628
|
isWritable: false,
|
|
1946
2629
|
});
|
|
1947
2630
|
|
|
1948
|
-
|
|
1949
|
-
pubkey: this.
|
|
2631
|
+
spotMarketAccountMap.set(QUOTE_SPOT_MARKET_INDEX.toNumber(), {
|
|
2632
|
+
pubkey: this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX).pubkey,
|
|
1950
2633
|
isSigner: false,
|
|
1951
2634
|
isWritable: true,
|
|
1952
2635
|
});
|
|
1953
2636
|
|
|
1954
2637
|
const remainingAccounts = [
|
|
1955
2638
|
...oracleAccountMap.values(),
|
|
1956
|
-
...
|
|
2639
|
+
...spotMarketAccountMap.values(),
|
|
1957
2640
|
...marketAccountMap.values(),
|
|
1958
2641
|
];
|
|
1959
2642
|
|
|
1960
|
-
return await this.program.instruction.
|
|
2643
|
+
return await this.program.instruction.settleExpiredPosition(marketIndex, {
|
|
1961
2644
|
accounts: {
|
|
1962
2645
|
state: await this.getStatePublicKey(),
|
|
1963
2646
|
authority: this.wallet.publicKey,
|
|
@@ -1973,7 +2656,7 @@ export class ClearingHouse {
|
|
|
1973
2656
|
marketIndex: BN,
|
|
1974
2657
|
maxBaseAssetAmount: BN
|
|
1975
2658
|
): Promise<TransactionSignature> {
|
|
1976
|
-
const { txSig } = await this.txSender.send(
|
|
2659
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1977
2660
|
wrapInTx(
|
|
1978
2661
|
await this.getLiquidatePerpIx(
|
|
1979
2662
|
userAccountPublicKey,
|
|
@@ -1985,6 +2668,7 @@ export class ClearingHouse {
|
|
|
1985
2668
|
[],
|
|
1986
2669
|
this.opts
|
|
1987
2670
|
);
|
|
2671
|
+
this.marketLastSlotCache.set(marketIndex.toNumber(), slot);
|
|
1988
2672
|
return txSig;
|
|
1989
2673
|
}
|
|
1990
2674
|
|
|
@@ -2003,7 +2687,7 @@ export class ClearingHouse {
|
|
|
2003
2687
|
const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
2004
2688
|
|
|
2005
2689
|
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
2006
|
-
|
|
2690
|
+
writablePerpMarketIndex: marketIndex,
|
|
2007
2691
|
counterPartyUserAccount: userAccount,
|
|
2008
2692
|
});
|
|
2009
2693
|
|
|
@@ -2027,8 +2711,8 @@ export class ClearingHouse {
|
|
|
2027
2711
|
public async liquidateBorrow(
|
|
2028
2712
|
userAccountPublicKey: PublicKey,
|
|
2029
2713
|
userAccount: UserAccount,
|
|
2030
|
-
|
|
2031
|
-
|
|
2714
|
+
assetmarketIndex: BN,
|
|
2715
|
+
liabilitymarketIndex: BN,
|
|
2032
2716
|
maxLiabilityTransfer: BN
|
|
2033
2717
|
): Promise<TransactionSignature> {
|
|
2034
2718
|
const { txSig } = await this.txSender.send(
|
|
@@ -2036,8 +2720,8 @@ export class ClearingHouse {
|
|
|
2036
2720
|
await this.getLiquidateBorrowIx(
|
|
2037
2721
|
userAccountPublicKey,
|
|
2038
2722
|
userAccount,
|
|
2039
|
-
|
|
2040
|
-
|
|
2723
|
+
assetmarketIndex,
|
|
2724
|
+
liabilitymarketIndex,
|
|
2041
2725
|
maxLiabilityTransfer
|
|
2042
2726
|
)
|
|
2043
2727
|
),
|
|
@@ -2050,20 +2734,20 @@ export class ClearingHouse {
|
|
|
2050
2734
|
public async getLiquidateBorrowIx(
|
|
2051
2735
|
userAccountPublicKey: PublicKey,
|
|
2052
2736
|
userAccount: UserAccount,
|
|
2053
|
-
|
|
2054
|
-
|
|
2737
|
+
assetmarketIndex: BN,
|
|
2738
|
+
liabilitymarketIndex: BN,
|
|
2055
2739
|
maxLiabilityTransfer: BN
|
|
2056
2740
|
): Promise<TransactionInstruction> {
|
|
2057
2741
|
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2058
2742
|
|
|
2059
2743
|
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
2060
2744
|
counterPartyUserAccount: userAccount,
|
|
2061
|
-
|
|
2745
|
+
writableSpotMarketIndexes: [liabilitymarketIndex, assetmarketIndex],
|
|
2062
2746
|
});
|
|
2063
2747
|
|
|
2064
2748
|
return await this.program.instruction.liquidateBorrow(
|
|
2065
|
-
|
|
2066
|
-
|
|
2749
|
+
assetmarketIndex,
|
|
2750
|
+
liabilitymarketIndex,
|
|
2067
2751
|
maxLiabilityTransfer,
|
|
2068
2752
|
{
|
|
2069
2753
|
accounts: {
|
|
@@ -2081,22 +2765,23 @@ export class ClearingHouse {
|
|
|
2081
2765
|
userAccountPublicKey: PublicKey,
|
|
2082
2766
|
userAccount: UserAccount,
|
|
2083
2767
|
perpMarketIndex: BN,
|
|
2084
|
-
|
|
2768
|
+
liabilitymarketIndex: BN,
|
|
2085
2769
|
maxLiabilityTransfer: BN
|
|
2086
2770
|
): Promise<TransactionSignature> {
|
|
2087
|
-
const { txSig } = await this.txSender.send(
|
|
2771
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2088
2772
|
wrapInTx(
|
|
2089
2773
|
await this.getLiquidateBorrowForPerpPnlIx(
|
|
2090
2774
|
userAccountPublicKey,
|
|
2091
2775
|
userAccount,
|
|
2092
2776
|
perpMarketIndex,
|
|
2093
|
-
|
|
2777
|
+
liabilitymarketIndex,
|
|
2094
2778
|
maxLiabilityTransfer
|
|
2095
2779
|
)
|
|
2096
2780
|
),
|
|
2097
2781
|
[],
|
|
2098
2782
|
this.opts
|
|
2099
2783
|
);
|
|
2784
|
+
this.marketLastSlotCache.set(perpMarketIndex.toNumber(), slot);
|
|
2100
2785
|
return txSig;
|
|
2101
2786
|
}
|
|
2102
2787
|
|
|
@@ -2104,20 +2789,20 @@ export class ClearingHouse {
|
|
|
2104
2789
|
userAccountPublicKey: PublicKey,
|
|
2105
2790
|
userAccount: UserAccount,
|
|
2106
2791
|
perpMarketIndex: BN,
|
|
2107
|
-
|
|
2792
|
+
liabilitymarketIndex: BN,
|
|
2108
2793
|
maxLiabilityTransfer: BN
|
|
2109
2794
|
): Promise<TransactionInstruction> {
|
|
2110
2795
|
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2111
2796
|
|
|
2112
2797
|
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
2113
2798
|
counterPartyUserAccount: userAccount,
|
|
2114
|
-
|
|
2115
|
-
|
|
2799
|
+
writablePerpMarketIndex: perpMarketIndex,
|
|
2800
|
+
writableSpotMarketIndexes: [liabilitymarketIndex],
|
|
2116
2801
|
});
|
|
2117
2802
|
|
|
2118
2803
|
return await this.program.instruction.liquidateBorrowForPerpPnl(
|
|
2119
2804
|
perpMarketIndex,
|
|
2120
|
-
|
|
2805
|
+
liabilitymarketIndex,
|
|
2121
2806
|
maxLiabilityTransfer,
|
|
2122
2807
|
{
|
|
2123
2808
|
accounts: {
|
|
@@ -2135,22 +2820,23 @@ export class ClearingHouse {
|
|
|
2135
2820
|
userAccountPublicKey: PublicKey,
|
|
2136
2821
|
userAccount: UserAccount,
|
|
2137
2822
|
perpMarketIndex: BN,
|
|
2138
|
-
|
|
2823
|
+
assetMarketIndex: BN,
|
|
2139
2824
|
maxPnlTransfer: BN
|
|
2140
2825
|
): Promise<TransactionSignature> {
|
|
2141
|
-
const { txSig } = await this.txSender.send(
|
|
2826
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2142
2827
|
wrapInTx(
|
|
2143
2828
|
await this.getLiquidatePerpPnlForDepositIx(
|
|
2144
2829
|
userAccountPublicKey,
|
|
2145
2830
|
userAccount,
|
|
2146
2831
|
perpMarketIndex,
|
|
2147
|
-
|
|
2832
|
+
assetMarketIndex,
|
|
2148
2833
|
maxPnlTransfer
|
|
2149
2834
|
)
|
|
2150
2835
|
),
|
|
2151
2836
|
[],
|
|
2152
2837
|
this.opts
|
|
2153
2838
|
);
|
|
2839
|
+
this.marketLastSlotCache.set(perpMarketIndex.toNumber(), slot);
|
|
2154
2840
|
return txSig;
|
|
2155
2841
|
}
|
|
2156
2842
|
|
|
@@ -2158,20 +2844,20 @@ export class ClearingHouse {
|
|
|
2158
2844
|
userAccountPublicKey: PublicKey,
|
|
2159
2845
|
userAccount: UserAccount,
|
|
2160
2846
|
perpMarketIndex: BN,
|
|
2161
|
-
|
|
2847
|
+
assetMarketIndex: BN,
|
|
2162
2848
|
maxPnlTransfer: BN
|
|
2163
2849
|
): Promise<TransactionInstruction> {
|
|
2164
2850
|
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2165
2851
|
|
|
2166
2852
|
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
2167
2853
|
counterPartyUserAccount: userAccount,
|
|
2168
|
-
|
|
2169
|
-
|
|
2854
|
+
writablePerpMarketIndex: perpMarketIndex,
|
|
2855
|
+
writableSpotMarketIndexes: [assetMarketIndex],
|
|
2170
2856
|
});
|
|
2171
2857
|
|
|
2172
2858
|
return await this.program.instruction.liquidatePerpPnlForDeposit(
|
|
2173
2859
|
perpMarketIndex,
|
|
2174
|
-
|
|
2860
|
+
assetMarketIndex,
|
|
2175
2861
|
maxPnlTransfer,
|
|
2176
2862
|
{
|
|
2177
2863
|
accounts: {
|
|
@@ -2188,7 +2874,6 @@ export class ClearingHouse {
|
|
|
2188
2874
|
public async resolvePerpBankruptcy(
|
|
2189
2875
|
userAccountPublicKey: PublicKey,
|
|
2190
2876
|
userAccount: UserAccount,
|
|
2191
|
-
bankIndex: BN,
|
|
2192
2877
|
marketIndex: BN
|
|
2193
2878
|
): Promise<TransactionSignature> {
|
|
2194
2879
|
const { txSig } = await this.txSender.send(
|
|
@@ -2196,7 +2881,6 @@ export class ClearingHouse {
|
|
|
2196
2881
|
await this.getResolvePerpBankruptcyIx(
|
|
2197
2882
|
userAccountPublicKey,
|
|
2198
2883
|
userAccount,
|
|
2199
|
-
bankIndex,
|
|
2200
2884
|
marketIndex
|
|
2201
2885
|
)
|
|
2202
2886
|
),
|
|
@@ -2209,21 +2893,20 @@ export class ClearingHouse {
|
|
|
2209
2893
|
public async getResolvePerpBankruptcyIx(
|
|
2210
2894
|
userAccountPublicKey: PublicKey,
|
|
2211
2895
|
userAccount: UserAccount,
|
|
2212
|
-
bankIndex: BN,
|
|
2213
2896
|
marketIndex: BN
|
|
2214
2897
|
): Promise<TransactionInstruction> {
|
|
2215
2898
|
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2216
2899
|
|
|
2217
2900
|
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
2218
|
-
|
|
2219
|
-
|
|
2901
|
+
writablePerpMarketIndex: marketIndex,
|
|
2902
|
+
writableSpotMarketIndexes: [QUOTE_SPOT_MARKET_INDEX],
|
|
2220
2903
|
counterPartyUserAccount: userAccount,
|
|
2221
2904
|
});
|
|
2222
2905
|
|
|
2223
|
-
const
|
|
2906
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
2224
2907
|
|
|
2225
2908
|
return await this.program.instruction.resolvePerpBankruptcy(
|
|
2226
|
-
|
|
2909
|
+
QUOTE_SPOT_MARKET_INDEX,
|
|
2227
2910
|
marketIndex,
|
|
2228
2911
|
{
|
|
2229
2912
|
accounts: {
|
|
@@ -2231,8 +2914,8 @@ export class ClearingHouse {
|
|
|
2231
2914
|
authority: this.wallet.publicKey,
|
|
2232
2915
|
user: userAccountPublicKey,
|
|
2233
2916
|
liquidator: liquidatorPublicKey,
|
|
2234
|
-
|
|
2235
|
-
insuranceFundVault:
|
|
2917
|
+
spotMarketVault: spotMarket.vault,
|
|
2918
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
2236
2919
|
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2237
2920
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
2238
2921
|
},
|
|
@@ -2244,14 +2927,14 @@ export class ClearingHouse {
|
|
|
2244
2927
|
public async resolveBorrowBankruptcy(
|
|
2245
2928
|
userAccountPublicKey: PublicKey,
|
|
2246
2929
|
userAccount: UserAccount,
|
|
2247
|
-
|
|
2930
|
+
marketIndex: BN
|
|
2248
2931
|
): Promise<TransactionSignature> {
|
|
2249
2932
|
const { txSig } = await this.txSender.send(
|
|
2250
2933
|
wrapInTx(
|
|
2251
2934
|
await this.getResolveBorrowBankruptcyIx(
|
|
2252
2935
|
userAccountPublicKey,
|
|
2253
2936
|
userAccount,
|
|
2254
|
-
|
|
2937
|
+
marketIndex
|
|
2255
2938
|
)
|
|
2256
2939
|
),
|
|
2257
2940
|
[],
|
|
@@ -2263,25 +2946,25 @@ export class ClearingHouse {
|
|
|
2263
2946
|
public async getResolveBorrowBankruptcyIx(
|
|
2264
2947
|
userAccountPublicKey: PublicKey,
|
|
2265
2948
|
userAccount: UserAccount,
|
|
2266
|
-
|
|
2949
|
+
marketIndex: BN
|
|
2267
2950
|
): Promise<TransactionInstruction> {
|
|
2268
2951
|
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2269
2952
|
|
|
2270
2953
|
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
2271
|
-
|
|
2954
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
2272
2955
|
counterPartyUserAccount: userAccount,
|
|
2273
2956
|
});
|
|
2274
2957
|
|
|
2275
|
-
const
|
|
2958
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
2276
2959
|
|
|
2277
|
-
return await this.program.instruction.resolveBorrowBankruptcy(
|
|
2960
|
+
return await this.program.instruction.resolveBorrowBankruptcy(marketIndex, {
|
|
2278
2961
|
accounts: {
|
|
2279
2962
|
state: await this.getStatePublicKey(),
|
|
2280
2963
|
authority: this.wallet.publicKey,
|
|
2281
2964
|
user: userAccountPublicKey,
|
|
2282
2965
|
liquidator: liquidatorPublicKey,
|
|
2283
|
-
|
|
2284
|
-
insuranceFundVault:
|
|
2966
|
+
spotMarketVault: spotMarket.vault,
|
|
2967
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
2285
2968
|
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2286
2969
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
2287
2970
|
},
|
|
@@ -2291,35 +2974,35 @@ export class ClearingHouse {
|
|
|
2291
2974
|
|
|
2292
2975
|
getRemainingAccountsWithCounterparty(params: {
|
|
2293
2976
|
counterPartyUserAccount: UserAccount;
|
|
2294
|
-
|
|
2295
|
-
|
|
2977
|
+
writablePerpMarketIndex?: BN;
|
|
2978
|
+
writableSpotMarketIndexes?: BN[];
|
|
2296
2979
|
}): AccountMeta[] {
|
|
2297
2980
|
const counterPartyUserAccount = params.counterPartyUserAccount;
|
|
2298
2981
|
|
|
2299
2982
|
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
2300
|
-
const
|
|
2983
|
+
const spotMarketAccountMap = new Map<number, AccountMeta>();
|
|
2301
2984
|
const marketAccountMap = new Map<number, AccountMeta>();
|
|
2302
|
-
for (const
|
|
2303
|
-
if (!
|
|
2304
|
-
const
|
|
2305
|
-
|
|
2306
|
-
pubkey:
|
|
2985
|
+
for (const spotPosition of counterPartyUserAccount.spotPositions) {
|
|
2986
|
+
if (!isSpotPositionAvailable(spotPosition)) {
|
|
2987
|
+
const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
2988
|
+
spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
|
|
2989
|
+
pubkey: spotMarket.pubkey,
|
|
2307
2990
|
isSigner: false,
|
|
2308
2991
|
isWritable: false,
|
|
2309
2992
|
});
|
|
2310
2993
|
|
|
2311
|
-
if (!
|
|
2312
|
-
oracleAccountMap.set(
|
|
2313
|
-
pubkey:
|
|
2994
|
+
if (!spotMarket.oracle.equals(PublicKey.default)) {
|
|
2995
|
+
oracleAccountMap.set(spotMarket.oracle.toString(), {
|
|
2996
|
+
pubkey: spotMarket.oracle,
|
|
2314
2997
|
isSigner: false,
|
|
2315
2998
|
isWritable: false,
|
|
2316
2999
|
});
|
|
2317
3000
|
}
|
|
2318
3001
|
}
|
|
2319
3002
|
}
|
|
2320
|
-
for (const position of counterPartyUserAccount.
|
|
3003
|
+
for (const position of counterPartyUserAccount.perpPositions) {
|
|
2321
3004
|
if (!positionIsAvailable(position)) {
|
|
2322
|
-
const market = this.
|
|
3005
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
2323
3006
|
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
2324
3007
|
pubkey: market.pubkey,
|
|
2325
3008
|
isWritable: false,
|
|
@@ -2346,7 +3029,7 @@ export class ClearingHouse {
|
|
|
2346
3029
|
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
2347
3030
|
// otherwise remove from slot
|
|
2348
3031
|
if (slot > lastUserPositionsSlot) {
|
|
2349
|
-
const marketAccount = this.
|
|
3032
|
+
const marketAccount = this.getPerpMarketAccount(marketIndexNum);
|
|
2350
3033
|
marketAccountMap.set(marketIndexNum, {
|
|
2351
3034
|
pubkey: marketAccount.pubkey,
|
|
2352
3035
|
isSigner: false,
|
|
@@ -2361,27 +3044,27 @@ export class ClearingHouse {
|
|
|
2361
3044
|
this.marketLastSlotCache.delete(marketIndexNum);
|
|
2362
3045
|
}
|
|
2363
3046
|
}
|
|
2364
|
-
for (const
|
|
2365
|
-
if (!
|
|
2366
|
-
const
|
|
2367
|
-
|
|
2368
|
-
pubkey:
|
|
3047
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
3048
|
+
if (!isSpotPositionAvailable(spotPosition)) {
|
|
3049
|
+
const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
3050
|
+
spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
|
|
3051
|
+
pubkey: spotMarket.pubkey,
|
|
2369
3052
|
isSigner: false,
|
|
2370
3053
|
isWritable: false,
|
|
2371
3054
|
});
|
|
2372
3055
|
|
|
2373
|
-
if (!
|
|
2374
|
-
oracleAccountMap.set(
|
|
2375
|
-
pubkey:
|
|
3056
|
+
if (!spotMarket.oracle.equals(PublicKey.default)) {
|
|
3057
|
+
oracleAccountMap.set(spotMarket.oracle.toString(), {
|
|
3058
|
+
pubkey: spotMarket.oracle,
|
|
2376
3059
|
isSigner: false,
|
|
2377
3060
|
isWritable: false,
|
|
2378
3061
|
});
|
|
2379
3062
|
}
|
|
2380
3063
|
}
|
|
2381
3064
|
}
|
|
2382
|
-
for (const position of userAccount.
|
|
3065
|
+
for (const position of userAccount.perpPositions) {
|
|
2383
3066
|
if (!positionIsAvailable(position)) {
|
|
2384
|
-
const market = this.
|
|
3067
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
2385
3068
|
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
2386
3069
|
pubkey: market.pubkey,
|
|
2387
3070
|
isWritable: false,
|
|
@@ -2395,8 +3078,8 @@ export class ClearingHouse {
|
|
|
2395
3078
|
}
|
|
2396
3079
|
}
|
|
2397
3080
|
|
|
2398
|
-
if (params.
|
|
2399
|
-
const market = this.
|
|
3081
|
+
if (params.writablePerpMarketIndex) {
|
|
3082
|
+
const market = this.getPerpMarketAccount(params.writablePerpMarketIndex);
|
|
2400
3083
|
marketAccountMap.set(market.marketIndex.toNumber(), {
|
|
2401
3084
|
pubkey: market.pubkey,
|
|
2402
3085
|
isSigner: false,
|
|
@@ -2409,17 +3092,19 @@ export class ClearingHouse {
|
|
|
2409
3092
|
});
|
|
2410
3093
|
}
|
|
2411
3094
|
|
|
2412
|
-
if (params.
|
|
2413
|
-
for (const
|
|
2414
|
-
const
|
|
2415
|
-
|
|
2416
|
-
|
|
3095
|
+
if (params.writableSpotMarketIndexes) {
|
|
3096
|
+
for (const writableSpotMarketIndex of params.writableSpotMarketIndexes) {
|
|
3097
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
3098
|
+
writableSpotMarketIndex
|
|
3099
|
+
);
|
|
3100
|
+
spotMarketAccountMap.set(spotMarketAccount.marketIndex.toNumber(), {
|
|
3101
|
+
pubkey: spotMarketAccount.pubkey,
|
|
2417
3102
|
isSigner: false,
|
|
2418
3103
|
isWritable: true,
|
|
2419
3104
|
});
|
|
2420
|
-
if (!
|
|
2421
|
-
oracleAccountMap.set(
|
|
2422
|
-
pubkey:
|
|
3105
|
+
if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
|
|
3106
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
3107
|
+
pubkey: spotMarketAccount.oracle,
|
|
2423
3108
|
isSigner: false,
|
|
2424
3109
|
isWritable: false,
|
|
2425
3110
|
});
|
|
@@ -2429,7 +3114,7 @@ export class ClearingHouse {
|
|
|
2429
3114
|
|
|
2430
3115
|
return [
|
|
2431
3116
|
...oracleAccountMap.values(),
|
|
2432
|
-
...
|
|
3117
|
+
...spotMarketAccountMap.values(),
|
|
2433
3118
|
...marketAccountMap.values(),
|
|
2434
3119
|
];
|
|
2435
3120
|
}
|
|
@@ -2477,7 +3162,7 @@ export class ClearingHouse {
|
|
|
2477
3162
|
userAccount
|
|
2478
3163
|
)) as UserAccount;
|
|
2479
3164
|
|
|
2480
|
-
const userPositions = user.
|
|
3165
|
+
const userPositions = user.perpPositions;
|
|
2481
3166
|
|
|
2482
3167
|
const remainingAccounts = [];
|
|
2483
3168
|
for (const position of userPositions) {
|
|
@@ -2508,17 +3193,17 @@ export class ClearingHouse {
|
|
|
2508
3193
|
}
|
|
2509
3194
|
|
|
2510
3195
|
public getOracleDataForMarket(marketIndex: BN): OraclePriceData {
|
|
2511
|
-
const oracleKey = this.
|
|
3196
|
+
const oracleKey = this.getPerpMarketAccount(marketIndex).amm.oracle;
|
|
2512
3197
|
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
2513
3198
|
|
|
2514
3199
|
return oracleData;
|
|
2515
3200
|
}
|
|
2516
3201
|
|
|
2517
3202
|
public async initializeInsuranceFundStake(
|
|
2518
|
-
|
|
3203
|
+
marketIndex: BN
|
|
2519
3204
|
): Promise<TransactionSignature> {
|
|
2520
3205
|
const { txSig } = await this.txSender.send(
|
|
2521
|
-
wrapInTx(await this.getInitializeInsuranceFundStakeIx(
|
|
3206
|
+
wrapInTx(await this.getInitializeInsuranceFundStakeIx(marketIndex)),
|
|
2522
3207
|
[],
|
|
2523
3208
|
this.opts
|
|
2524
3209
|
);
|
|
@@ -2526,20 +3211,20 @@ export class ClearingHouse {
|
|
|
2526
3211
|
}
|
|
2527
3212
|
|
|
2528
3213
|
public async getInitializeInsuranceFundStakeIx(
|
|
2529
|
-
|
|
3214
|
+
marketIndex: BN
|
|
2530
3215
|
): Promise<TransactionInstruction> {
|
|
2531
3216
|
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2532
3217
|
this.program.programId,
|
|
2533
3218
|
this.wallet.publicKey,
|
|
2534
|
-
|
|
3219
|
+
marketIndex
|
|
2535
3220
|
);
|
|
2536
3221
|
|
|
2537
3222
|
return await this.program.instruction.initializeInsuranceFundStake(
|
|
2538
|
-
|
|
3223
|
+
marketIndex,
|
|
2539
3224
|
{
|
|
2540
3225
|
accounts: {
|
|
2541
3226
|
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2542
|
-
|
|
3227
|
+
spotMarket: this.getSpotMarketAccount(marketIndex).pubkey,
|
|
2543
3228
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
2544
3229
|
authority: this.wallet.publicKey,
|
|
2545
3230
|
payer: this.wallet.publicKey,
|
|
@@ -2552,29 +3237,29 @@ export class ClearingHouse {
|
|
|
2552
3237
|
}
|
|
2553
3238
|
|
|
2554
3239
|
public async addInsuranceFundStake(
|
|
2555
|
-
|
|
3240
|
+
marketIndex: BN,
|
|
2556
3241
|
amount: BN,
|
|
2557
3242
|
collateralAccountPublicKey: PublicKey
|
|
2558
3243
|
): Promise<TransactionSignature> {
|
|
2559
|
-
const
|
|
3244
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
2560
3245
|
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2561
3246
|
this.program.programId,
|
|
2562
3247
|
this.wallet.publicKey,
|
|
2563
|
-
|
|
3248
|
+
marketIndex
|
|
2564
3249
|
);
|
|
2565
3250
|
|
|
2566
3251
|
const remainingAccounts = this.getRemainingAccounts({
|
|
2567
|
-
|
|
3252
|
+
writableSpotMarketIndex: marketIndex,
|
|
2568
3253
|
});
|
|
2569
3254
|
|
|
2570
|
-
return await this.program.rpc.addInsuranceFundStake(
|
|
3255
|
+
return await this.program.rpc.addInsuranceFundStake(marketIndex, amount, {
|
|
2571
3256
|
accounts: {
|
|
2572
3257
|
state: await this.getStatePublicKey(),
|
|
2573
|
-
|
|
3258
|
+
spotMarket: spotMarket.pubkey,
|
|
2574
3259
|
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2575
3260
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
2576
3261
|
authority: this.wallet.publicKey,
|
|
2577
|
-
insuranceFundVault:
|
|
3262
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
2578
3263
|
userTokenAccount: collateralAccountPublicKey,
|
|
2579
3264
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
2580
3265
|
},
|
|
@@ -2583,31 +3268,31 @@ export class ClearingHouse {
|
|
|
2583
3268
|
}
|
|
2584
3269
|
|
|
2585
3270
|
public async requestRemoveInsuranceFundStake(
|
|
2586
|
-
|
|
3271
|
+
marketIndex: BN,
|
|
2587
3272
|
amount: BN
|
|
2588
3273
|
): Promise<TransactionSignature> {
|
|
2589
|
-
const
|
|
3274
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2590
3275
|
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2591
3276
|
this.program.programId,
|
|
2592
3277
|
this.wallet.publicKey,
|
|
2593
|
-
|
|
3278
|
+
marketIndex
|
|
2594
3279
|
);
|
|
2595
3280
|
|
|
2596
3281
|
const remainingAccounts = this.getRemainingAccounts({
|
|
2597
|
-
|
|
3282
|
+
writableSpotMarketIndex: marketIndex,
|
|
2598
3283
|
});
|
|
2599
3284
|
|
|
2600
3285
|
return await this.program.rpc.requestRemoveInsuranceFundStake(
|
|
2601
|
-
|
|
3286
|
+
marketIndex,
|
|
2602
3287
|
amount,
|
|
2603
3288
|
{
|
|
2604
3289
|
accounts: {
|
|
2605
3290
|
state: await this.getStatePublicKey(),
|
|
2606
|
-
|
|
3291
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2607
3292
|
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2608
3293
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
2609
3294
|
authority: this.wallet.publicKey,
|
|
2610
|
-
insuranceFundVault:
|
|
3295
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2611
3296
|
// userTokenAccount: collateralAccountPublicKey,
|
|
2612
3297
|
// tokenProgram: TOKEN_PROGRAM_ID,
|
|
2613
3298
|
},
|
|
@@ -2617,29 +3302,29 @@ export class ClearingHouse {
|
|
|
2617
3302
|
}
|
|
2618
3303
|
|
|
2619
3304
|
public async cancelRequestRemoveInsuranceFundStake(
|
|
2620
|
-
|
|
3305
|
+
marketIndex: BN
|
|
2621
3306
|
): Promise<TransactionSignature> {
|
|
2622
|
-
const
|
|
3307
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2623
3308
|
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2624
3309
|
this.program.programId,
|
|
2625
3310
|
this.wallet.publicKey,
|
|
2626
|
-
|
|
3311
|
+
marketIndex
|
|
2627
3312
|
);
|
|
2628
3313
|
|
|
2629
3314
|
const remainingAccounts = this.getRemainingAccounts({
|
|
2630
|
-
|
|
3315
|
+
writableSpotMarketIndex: marketIndex,
|
|
2631
3316
|
});
|
|
2632
3317
|
|
|
2633
3318
|
return await this.program.rpc.cancelRequestRemoveInsuranceFundStake(
|
|
2634
|
-
|
|
3319
|
+
marketIndex,
|
|
2635
3320
|
{
|
|
2636
3321
|
accounts: {
|
|
2637
3322
|
state: await this.getStatePublicKey(),
|
|
2638
|
-
|
|
3323
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2639
3324
|
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2640
3325
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
2641
3326
|
authority: this.wallet.publicKey,
|
|
2642
|
-
insuranceFundVault:
|
|
3327
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2643
3328
|
// userTokenAccount: collateralAccountPublicKey,
|
|
2644
3329
|
// tokenProgram: TOKEN_PROGRAM_ID,
|
|
2645
3330
|
},
|
|
@@ -2649,28 +3334,28 @@ export class ClearingHouse {
|
|
|
2649
3334
|
}
|
|
2650
3335
|
|
|
2651
3336
|
public async removeInsuranceFundStake(
|
|
2652
|
-
|
|
3337
|
+
marketIndex: BN,
|
|
2653
3338
|
collateralAccountPublicKey: PublicKey
|
|
2654
3339
|
): Promise<TransactionSignature> {
|
|
2655
|
-
const
|
|
3340
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2656
3341
|
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2657
3342
|
this.program.programId,
|
|
2658
3343
|
this.wallet.publicKey,
|
|
2659
|
-
|
|
3344
|
+
marketIndex
|
|
2660
3345
|
);
|
|
2661
3346
|
|
|
2662
3347
|
const remainingAccounts = this.getRemainingAccounts({
|
|
2663
|
-
|
|
3348
|
+
writableSpotMarketIndex: marketIndex,
|
|
2664
3349
|
});
|
|
2665
3350
|
|
|
2666
|
-
return await this.program.rpc.removeInsuranceFundStake(
|
|
3351
|
+
return await this.program.rpc.removeInsuranceFundStake(marketIndex, {
|
|
2667
3352
|
accounts: {
|
|
2668
3353
|
state: await this.getStatePublicKey(),
|
|
2669
|
-
|
|
3354
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2670
3355
|
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2671
3356
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
2672
3357
|
authority: this.wallet.publicKey,
|
|
2673
|
-
insuranceFundVault:
|
|
3358
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2674
3359
|
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2675
3360
|
userTokenAccount: collateralAccountPublicKey,
|
|
2676
3361
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
@@ -2680,24 +3365,66 @@ export class ClearingHouse {
|
|
|
2680
3365
|
}
|
|
2681
3366
|
|
|
2682
3367
|
public async settleRevenueToInsuranceFund(
|
|
2683
|
-
|
|
3368
|
+
marketIndex: BN
|
|
2684
3369
|
): Promise<TransactionSignature> {
|
|
2685
|
-
const
|
|
3370
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2686
3371
|
|
|
2687
3372
|
const remainingAccounts = this.getRemainingAccounts({
|
|
2688
|
-
|
|
3373
|
+
writableSpotMarketIndex: marketIndex,
|
|
2689
3374
|
});
|
|
2690
3375
|
|
|
2691
|
-
return await this.program.rpc.settleRevenueToInsuranceFund(
|
|
3376
|
+
return await this.program.rpc.settleRevenueToInsuranceFund(marketIndex, {
|
|
2692
3377
|
accounts: {
|
|
2693
3378
|
state: await this.getStatePublicKey(),
|
|
2694
|
-
|
|
2695
|
-
|
|
3379
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
3380
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
2696
3381
|
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2697
|
-
insuranceFundVault:
|
|
3382
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2698
3383
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
2699
3384
|
},
|
|
2700
3385
|
remainingAccounts,
|
|
2701
3386
|
});
|
|
2702
3387
|
}
|
|
3388
|
+
|
|
3389
|
+
public async resolvePerpPnlDeficit(
|
|
3390
|
+
spotMarketIndex: BN,
|
|
3391
|
+
perpMarketIndex: BN
|
|
3392
|
+
): Promise<TransactionSignature> {
|
|
3393
|
+
const { txSig } = await this.txSender.send(
|
|
3394
|
+
wrapInTx(
|
|
3395
|
+
await this.getResolvePerpPnlDeficitIx(spotMarketIndex, perpMarketIndex)
|
|
3396
|
+
),
|
|
3397
|
+
[],
|
|
3398
|
+
this.opts
|
|
3399
|
+
);
|
|
3400
|
+
return txSig;
|
|
3401
|
+
}
|
|
3402
|
+
|
|
3403
|
+
public async getResolvePerpPnlDeficitIx(
|
|
3404
|
+
spotMarketIndex: BN,
|
|
3405
|
+
perpMarketIndex: BN
|
|
3406
|
+
): Promise<TransactionInstruction> {
|
|
3407
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
3408
|
+
writablePerpMarketIndex: perpMarketIndex,
|
|
3409
|
+
writableSpotMarketIndex: spotMarketIndex,
|
|
3410
|
+
});
|
|
3411
|
+
|
|
3412
|
+
const spotMarket = this.getSpotMarketAccount(spotMarketIndex);
|
|
3413
|
+
|
|
3414
|
+
return await this.program.instruction.resolvePerpPnlDeficit(
|
|
3415
|
+
spotMarketIndex,
|
|
3416
|
+
perpMarketIndex,
|
|
3417
|
+
{
|
|
3418
|
+
accounts: {
|
|
3419
|
+
state: await this.getStatePublicKey(),
|
|
3420
|
+
authority: this.wallet.publicKey,
|
|
3421
|
+
spotMarketVault: spotMarket.vault,
|
|
3422
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
3423
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
3424
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
3425
|
+
},
|
|
3426
|
+
remainingAccounts: remainingAccounts,
|
|
3427
|
+
}
|
|
3428
|
+
);
|
|
3429
|
+
}
|
|
2703
3430
|
}
|