@drift-labs/sdk 0.2.0-master.3 → 0.2.0-master.31
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/README.md +13 -13
- package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/accounts/bulkUserSubscription.js +0 -1
- package/lib/accounts/fetch.d.ts +2 -1
- package/lib/accounts/fetch.js +9 -1
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +16 -16
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +31 -28
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +22 -11
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +17 -17
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +37 -35
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/marketAddresses.d.ts +1 -3
- package/lib/addresses/pda.d.ts +10 -4
- package/lib/addresses/pda.js +51 -14
- package/lib/admin.d.ts +42 -26
- package/lib/admin.js +228 -81
- package/lib/clearingHouse.d.ts +130 -49
- package/lib/clearingHouse.js +1256 -367
- package/lib/clearingHouseConfig.d.ts +4 -4
- package/lib/clearingHouseUser.d.ts +51 -39
- package/lib/clearingHouseUser.js +408 -191
- package/lib/clearingHouseUserStats.d.ts +18 -0
- package/lib/clearingHouseUserStats.js +49 -0
- package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
- package/lib/clearingHouseUserStatsConfig.js +2 -0
- package/lib/config.d.ts +7 -9
- package/lib/config.js +21 -21
- package/lib/constants/numericConstants.d.ts +25 -12
- package/lib/constants/numericConstants.js +35 -21
- package/lib/constants/perpMarkets.d.ts +18 -0
- package/lib/constants/{markets.js → perpMarkets.js} +7 -7
- package/lib/constants/spotMarkets.d.ts +19 -0
- package/lib/constants/spotMarkets.js +53 -0
- package/lib/dlob/DLOB.d.ts +74 -0
- package/lib/dlob/DLOB.js +595 -0
- package/lib/dlob/DLOBNode.d.ts +54 -0
- package/lib/dlob/DLOBNode.js +85 -0
- package/lib/dlob/NodeList.d.ts +26 -0
- package/lib/dlob/NodeList.js +139 -0
- package/lib/events/eventList.js +3 -0
- package/lib/events/eventSubscriber.d.ts +4 -2
- package/lib/events/eventSubscriber.js +16 -9
- package/lib/events/fetchLogs.d.ts +10 -1
- package/lib/events/fetchLogs.js +27 -7
- package/lib/events/pollingLogProvider.d.ts +2 -1
- package/lib/events/pollingLogProvider.js +6 -2
- package/lib/events/sort.js +8 -11
- package/lib/events/types.d.ts +8 -2
- package/lib/events/types.js +6 -0
- package/lib/examples/makeTradeExample.js +20 -8
- package/lib/factory/bigNum.d.ts +2 -0
- package/lib/factory/bigNum.js +48 -10
- package/lib/idl/clearing_house.json +4889 -1529
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +21 -6
- package/lib/index.js +25 -6
- package/lib/math/amm.d.ts +9 -6
- package/lib/math/amm.js +91 -66
- package/lib/math/auction.js +4 -1
- package/lib/math/conversion.js +1 -1
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +11 -10
- package/lib/math/insurance.d.ts +4 -0
- package/lib/math/insurance.js +27 -0
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +77 -0
- package/lib/math/market.d.ts +14 -9
- package/lib/math/market.js +72 -10
- package/lib/math/oracles.d.ts +4 -0
- package/lib/math/oracles.js +36 -8
- package/lib/math/orders.d.ts +6 -2
- package/lib/math/orders.js +78 -3
- package/lib/math/position.d.ts +21 -13
- package/lib/math/position.js +76 -36
- package/lib/math/repeg.js +14 -5
- package/lib/math/spotBalance.d.ts +22 -0
- package/lib/math/spotBalance.js +192 -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/trade.d.ts +10 -10
- package/lib/math/trade.js +32 -39
- package/lib/oracles/pythClient.js +1 -1
- package/lib/oracles/quoteAssetOracleClient.js +1 -1
- package/lib/oracles/switchboardClient.js +1 -1
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +12 -92
- 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/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.d.ts +1 -1
- package/lib/tx/retryTxSender.js +13 -4
- package/lib/tx/types.d.ts +1 -1
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +566 -138
- package/lib/types.js +129 -5
- 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/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +12 -6
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +0 -1
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +46 -42
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +31 -11
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +64 -59
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.ts +1 -2
- package/src/addresses/pda.ts +88 -14
- package/src/admin.ts +452 -147
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +2066 -467
- package/src/clearingHouseConfig.ts +4 -3
- package/src/clearingHouseUser.ts +747 -294
- package/src/clearingHouseUserStats.ts +75 -0
- package/src/clearingHouseUserStatsConfig.ts +18 -0
- package/src/config.ts +30 -31
- package/src/constants/numericConstants.ts +48 -25
- package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
- package/src/constants/spotMarkets.ts +73 -0
- package/src/dlob/DLOB.ts +953 -0
- package/src/dlob/DLOBNode.ts +167 -0
- package/src/dlob/NodeList.ts +189 -0
- package/src/events/eventList.js +77 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/eventSubscriber.ts +20 -12
- package/src/events/fetchLogs.ts +35 -8
- package/src/events/pollingLogProvider.ts +10 -2
- package/src/events/sort.ts +11 -15
- package/src/events/types.ts +19 -1
- package/src/examples/makeTradeExample.js +157 -0
- package/src/examples/makeTradeExample.ts +32 -14
- package/src/factory/bigNum.ts +65 -13
- package/src/idl/clearing_house.json +4889 -1529
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.ts +21 -6
- package/src/math/amm.ts +171 -88
- package/src/math/auction.ts +5 -1
- package/src/math/conversion.ts +2 -2
- package/src/math/funding.ts +20 -18
- package/src/math/insurance.ts +35 -0
- package/src/math/margin.ts +127 -0
- package/src/math/market.ts +145 -14
- package/src/math/oracles.ts +63 -9
- package/src/math/orders.ts +138 -4
- package/src/math/position.ts +119 -58
- package/src/math/repeg.ts +16 -6
- package/src/math/spotBalance.ts +319 -0
- package/src/math/spotMarket.ts +9 -0
- package/src/math/spotPosition.ts +47 -0
- package/src/math/trade.ts +53 -59
- package/src/oracles/pythClient.ts +2 -2
- package/src/oracles/quoteAssetOracleClient.ts +2 -2
- package/src/oracles/switchboardClient.ts +2 -2
- package/src/orderParams.ts +24 -137
- package/src/serum/serumSubscriber.ts +80 -0
- package/src/serum/types.ts +13 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +16 -5
- package/src/tx/types.js +2 -0
- package/src/tx/types.ts +2 -1
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +533 -140
- package/src/userMap/userMap.ts +100 -0
- package/src/userMap/userStatsMap.ts +110 -0
- package/src/util/computeUnits.js +21 -11
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/tests/bn/test.ts +24 -10
- package/tests/dlob/helpers.ts +397 -0
- package/tests/dlob/test.ts +3688 -0
- package/lib/constants/banks.d.ts +0 -16
- package/lib/constants/banks.js +0 -34
- package/lib/constants/markets.d.ts +0 -19
- package/lib/math/bankBalance.d.ts +0 -9
- package/lib/math/bankBalance.js +0 -75
- package/lib/math/state.d.ts +0 -8
- package/lib/math/state.js +0 -15
- package/lib/orders.d.ts +0 -8
- package/lib/orders.js +0 -134
- package/src/constants/banks.ts +0 -43
- package/src/math/bankBalance.ts +0 -112
- package/src/math/state.ts +0 -14
- package/src/math/utils.js +0 -27
- package/src/math/utils.js.map +0 -1
- package/src/orders.ts +0 -244
- package/src/util/computeUnits.js.map +0 -1
package/src/clearingHouse.ts
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
import { AnchorProvider, BN, Idl, Program } from '@project-serum/anchor';
|
|
2
|
-
import
|
|
2
|
+
import bs58 from 'bs58';
|
|
3
|
+
import {
|
|
4
|
+
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
5
|
+
Token,
|
|
6
|
+
TOKEN_PROGRAM_ID,
|
|
7
|
+
} from '@solana/spl-token';
|
|
3
8
|
import {
|
|
4
9
|
StateAccount,
|
|
5
10
|
IWallet,
|
|
6
11
|
PositionDirection,
|
|
7
12
|
UserAccount,
|
|
8
|
-
|
|
13
|
+
PerpMarketAccount,
|
|
9
14
|
OrderParams,
|
|
10
15
|
Order,
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
SpotMarketAccount,
|
|
17
|
+
SpotPosition,
|
|
13
18
|
MakerInfo,
|
|
19
|
+
TakerInfo,
|
|
20
|
+
OptionalOrderParams,
|
|
21
|
+
DefaultOrderParams,
|
|
22
|
+
OrderType,
|
|
23
|
+
ReferrerInfo,
|
|
24
|
+
MarketType,
|
|
25
|
+
SerumV3FulfillmentConfigAccount,
|
|
26
|
+
isVariant,
|
|
14
27
|
} from './types';
|
|
15
28
|
import * as anchor from '@project-serum/anchor';
|
|
16
29
|
import clearingHouseIDL from './idl/clearing_house.json';
|
|
@@ -23,16 +36,26 @@ import {
|
|
|
23
36
|
Transaction,
|
|
24
37
|
TransactionInstruction,
|
|
25
38
|
AccountMeta,
|
|
39
|
+
Keypair,
|
|
40
|
+
LAMPORTS_PER_SOL,
|
|
41
|
+
Signer,
|
|
42
|
+
SystemProgram,
|
|
43
|
+
ComputeBudgetProgram,
|
|
26
44
|
} from '@solana/web3.js';
|
|
27
45
|
|
|
28
|
-
import {
|
|
46
|
+
import { TokenFaucet } from './tokenFaucet';
|
|
29
47
|
import { EventEmitter } from 'events';
|
|
30
48
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
31
49
|
import {
|
|
50
|
+
getClearingHouseSignerPublicKey,
|
|
32
51
|
getClearingHouseStateAccountPublicKey,
|
|
52
|
+
getInsuranceFundStakeAccountPublicKey,
|
|
33
53
|
getMarketPublicKey,
|
|
54
|
+
getSerumFulfillmentConfigPublicKey,
|
|
55
|
+
getSerumSignerPublicKey,
|
|
34
56
|
getUserAccountPublicKey,
|
|
35
57
|
getUserAccountPublicKeySync,
|
|
58
|
+
getUserStatsAccountPublicKey,
|
|
36
59
|
} from './addresses/pda';
|
|
37
60
|
import {
|
|
38
61
|
ClearingHouseAccountSubscriber,
|
|
@@ -41,9 +64,9 @@ import {
|
|
|
41
64
|
} from './accounts/types';
|
|
42
65
|
import { TxSender } from './tx/types';
|
|
43
66
|
import { wrapInTx } from './tx/utils';
|
|
44
|
-
import {
|
|
67
|
+
import { QUOTE_SPOT_MARKET_INDEX } from './constants/numericConstants';
|
|
45
68
|
import { findDirectionToClose, positionIsAvailable } from './math/position';
|
|
46
|
-
import { getTokenAmount } from './math/
|
|
69
|
+
import { getTokenAmount } from './math/spotBalance';
|
|
47
70
|
import { DEFAULT_USER_NAME, encodeName } from './userName';
|
|
48
71
|
import { OraclePriceData } from './oracles/types';
|
|
49
72
|
import { ClearingHouseConfig } from './clearingHouseConfig';
|
|
@@ -52,8 +75,19 @@ import { WebSocketClearingHouseAccountSubscriber } from './accounts/webSocketCle
|
|
|
52
75
|
import { RetryTxSender } from './tx/retryTxSender';
|
|
53
76
|
import { ClearingHouseUser } from './clearingHouseUser';
|
|
54
77
|
import { ClearingHouseUserAccountSubscriptionConfig } from './clearingHouseUserConfig';
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
78
|
+
import { getMarketsAndOraclesForSubscription } from './config';
|
|
79
|
+
import { WRAPPED_SOL_MINT } from './constants/spotMarkets';
|
|
80
|
+
import { ClearingHouseUserStats } from './clearingHouseUserStats';
|
|
81
|
+
import { isSpotPositionAvailable } from './math/spotPosition';
|
|
82
|
+
|
|
83
|
+
type RemainingAccountParams = {
|
|
84
|
+
userAccounts: UserAccount[];
|
|
85
|
+
writablePerpMarketIndexes?: number[];
|
|
86
|
+
writableSpotMarketIndexes?: number[];
|
|
87
|
+
readablePerpMarketIndex?: number;
|
|
88
|
+
readableSpotMarketIndex?: number;
|
|
89
|
+
useMarketLastSlotCache?: boolean;
|
|
90
|
+
};
|
|
57
91
|
|
|
58
92
|
/**
|
|
59
93
|
* # ClearingHouse
|
|
@@ -66,6 +100,7 @@ export class ClearingHouse {
|
|
|
66
100
|
provider: AnchorProvider;
|
|
67
101
|
opts?: ConfirmOptions;
|
|
68
102
|
users = new Map<number, ClearingHouseUser>();
|
|
103
|
+
userStats?: ClearingHouseUserStats;
|
|
69
104
|
activeUserId: number;
|
|
70
105
|
userAccountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig;
|
|
71
106
|
accountSubscriber: ClearingHouseAccountSubscriber;
|
|
@@ -73,6 +108,7 @@ export class ClearingHouse {
|
|
|
73
108
|
_isSubscribed = false;
|
|
74
109
|
txSender: TxSender;
|
|
75
110
|
marketLastSlotCache = new Map<number, number>();
|
|
111
|
+
authority: PublicKey;
|
|
76
112
|
|
|
77
113
|
public get isSubscribed() {
|
|
78
114
|
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
@@ -97,6 +133,7 @@ export class ClearingHouse {
|
|
|
97
133
|
this.provider
|
|
98
134
|
);
|
|
99
135
|
|
|
136
|
+
this.authority = config.authority ?? this.wallet.publicKey;
|
|
100
137
|
const userIds = config.userIds ?? [0];
|
|
101
138
|
this.activeUserId = config.activeUserId ?? userIds[0];
|
|
102
139
|
this.userAccountSubscriptionConfig =
|
|
@@ -109,18 +146,32 @@ export class ClearingHouse {
|
|
|
109
146
|
type: 'websocket',
|
|
110
147
|
};
|
|
111
148
|
this.createUsers(userIds, this.userAccountSubscriptionConfig);
|
|
149
|
+
if (config.userStats) {
|
|
150
|
+
this.userStats = new ClearingHouseUserStats({
|
|
151
|
+
clearingHouse: this,
|
|
152
|
+
userStatsAccountPublicKey: getUserStatsAccountPublicKey(
|
|
153
|
+
this.program.programId,
|
|
154
|
+
this.authority
|
|
155
|
+
),
|
|
156
|
+
accountSubscription: this.userAccountSubscriptionConfig,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
112
159
|
|
|
113
|
-
let
|
|
114
|
-
let
|
|
160
|
+
let perpMarketIndexes = config.perpMarketIndexes;
|
|
161
|
+
let spotMarketIndexes = config.spotMarketIndexes;
|
|
115
162
|
let oracleInfos = config.oracleInfos;
|
|
116
163
|
if (config.env) {
|
|
117
164
|
const {
|
|
118
|
-
|
|
119
|
-
|
|
165
|
+
perpMarketIndexes: envPerpMarketIndexes,
|
|
166
|
+
spotMarketIndexes: envSpotMarketIndexes,
|
|
120
167
|
oracleInfos: envOralceInfos,
|
|
121
|
-
} =
|
|
122
|
-
|
|
123
|
-
|
|
168
|
+
} = getMarketsAndOraclesForSubscription(config.env);
|
|
169
|
+
perpMarketIndexes = perpMarketIndexes
|
|
170
|
+
? perpMarketIndexes
|
|
171
|
+
: envPerpMarketIndexes;
|
|
172
|
+
spotMarketIndexes = spotMarketIndexes
|
|
173
|
+
? spotMarketIndexes
|
|
174
|
+
: envSpotMarketIndexes;
|
|
124
175
|
oracleInfos = oracleInfos ? oracleInfos : envOralceInfos;
|
|
125
176
|
}
|
|
126
177
|
|
|
@@ -128,15 +179,15 @@ export class ClearingHouse {
|
|
|
128
179
|
this.accountSubscriber = new PollingClearingHouseAccountSubscriber(
|
|
129
180
|
this.program,
|
|
130
181
|
config.accountSubscription.accountLoader,
|
|
131
|
-
|
|
132
|
-
|
|
182
|
+
perpMarketIndexes ?? [],
|
|
183
|
+
spotMarketIndexes ?? [],
|
|
133
184
|
oracleInfos ?? []
|
|
134
185
|
);
|
|
135
186
|
} else {
|
|
136
187
|
this.accountSubscriber = new WebSocketClearingHouseAccountSubscriber(
|
|
137
188
|
this.program,
|
|
138
|
-
config.
|
|
139
|
-
config.
|
|
189
|
+
config.perpMarketIndexes ?? [],
|
|
190
|
+
config.spotMarketIndexes ?? [],
|
|
140
191
|
config.oracleInfos ?? []
|
|
141
192
|
);
|
|
142
193
|
}
|
|
@@ -165,7 +216,7 @@ export class ClearingHouse {
|
|
|
165
216
|
): ClearingHouseUser {
|
|
166
217
|
const userAccountPublicKey = getUserAccountPublicKeySync(
|
|
167
218
|
this.program.programId,
|
|
168
|
-
this.
|
|
219
|
+
this.authority,
|
|
169
220
|
userId
|
|
170
221
|
);
|
|
171
222
|
|
|
@@ -180,6 +231,9 @@ export class ClearingHouse {
|
|
|
180
231
|
const subscribePromises = this.subscribeUsers().concat(
|
|
181
232
|
this.accountSubscriber.subscribe()
|
|
182
233
|
);
|
|
234
|
+
if (this.userStats !== undefined) {
|
|
235
|
+
subscribePromises.concat(this.userStats.subscribe());
|
|
236
|
+
}
|
|
183
237
|
this.isSubscribed = (await Promise.all(subscribePromises)).reduce(
|
|
184
238
|
(success, prevSuccess) => success && prevSuccess
|
|
185
239
|
);
|
|
@@ -194,17 +248,22 @@ export class ClearingHouse {
|
|
|
194
248
|
* Forces the accountSubscriber to fetch account updates from rpc
|
|
195
249
|
*/
|
|
196
250
|
public async fetchAccounts(): Promise<void> {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
251
|
+
const promises = [...this.users.values()]
|
|
252
|
+
.map((user) => user.fetchAccounts())
|
|
253
|
+
.concat(this.accountSubscriber.fetch());
|
|
254
|
+
if (this.userStats) {
|
|
255
|
+
promises.concat(this.userStats.fetchAccounts());
|
|
256
|
+
}
|
|
257
|
+
await Promise.all(promises);
|
|
202
258
|
}
|
|
203
259
|
|
|
204
260
|
public async unsubscribe(): Promise<void> {
|
|
205
261
|
const unsubscribePromises = this.unsubscribeUsers().concat(
|
|
206
262
|
this.accountSubscriber.unsubscribe()
|
|
207
263
|
);
|
|
264
|
+
if (this.userStats !== undefined) {
|
|
265
|
+
unsubscribePromises.concat(this.userStats.unsubscribe());
|
|
266
|
+
}
|
|
208
267
|
await Promise.all(unsubscribePromises);
|
|
209
268
|
this.isSubscribed = false;
|
|
210
269
|
}
|
|
@@ -224,29 +283,49 @@ export class ClearingHouse {
|
|
|
224
283
|
return this.statePublicKey;
|
|
225
284
|
}
|
|
226
285
|
|
|
286
|
+
signerPublicKey?: PublicKey;
|
|
287
|
+
public getSignerPublicKey(): PublicKey {
|
|
288
|
+
if (this.signerPublicKey) {
|
|
289
|
+
return this.signerPublicKey;
|
|
290
|
+
}
|
|
291
|
+
this.signerPublicKey = getClearingHouseSignerPublicKey(
|
|
292
|
+
this.program.programId
|
|
293
|
+
);
|
|
294
|
+
return this.signerPublicKey;
|
|
295
|
+
}
|
|
296
|
+
|
|
227
297
|
public getStateAccount(): StateAccount {
|
|
228
298
|
return this.accountSubscriber.getStateAccountAndSlot().data;
|
|
229
299
|
}
|
|
230
300
|
|
|
231
|
-
public
|
|
232
|
-
marketIndex
|
|
301
|
+
public getPerpMarketAccount(
|
|
302
|
+
marketIndex: number
|
|
303
|
+
): PerpMarketAccount | undefined {
|
|
233
304
|
return this.accountSubscriber.getMarketAccountAndSlot(marketIndex)?.data;
|
|
234
305
|
}
|
|
235
306
|
|
|
236
|
-
public
|
|
307
|
+
public getPerpMarketAccounts(): PerpMarketAccount[] {
|
|
237
308
|
return this.accountSubscriber
|
|
238
309
|
.getMarketAccountsAndSlots()
|
|
239
310
|
.map((value) => value.data);
|
|
240
311
|
}
|
|
241
312
|
|
|
242
|
-
public
|
|
243
|
-
|
|
244
|
-
|
|
313
|
+
public getSpotMarketAccount(
|
|
314
|
+
marketIndex: number
|
|
315
|
+
): SpotMarketAccount | undefined {
|
|
316
|
+
return this.accountSubscriber.getSpotMarketAccountAndSlot(marketIndex).data;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
public getSpotMarketAccounts(): SpotMarketAccount[] {
|
|
320
|
+
return this.accountSubscriber
|
|
321
|
+
.getSpotMarketAccountsAndSlots()
|
|
322
|
+
.map((value) => value.data);
|
|
245
323
|
}
|
|
246
324
|
|
|
247
|
-
public
|
|
248
|
-
return this.accountSubscriber.
|
|
249
|
-
|
|
325
|
+
public getQuoteSpotMarketAccount(): SpotMarketAccount {
|
|
326
|
+
return this.accountSubscriber.getSpotMarketAccountAndSlot(
|
|
327
|
+
QUOTE_SPOT_MARKET_INDEX
|
|
328
|
+
).data;
|
|
250
329
|
}
|
|
251
330
|
|
|
252
331
|
public getOraclePriceDataAndSlot(
|
|
@@ -255,6 +334,18 @@ export class ClearingHouse {
|
|
|
255
334
|
return this.accountSubscriber.getOraclePriceDataAndSlot(oraclePublicKey);
|
|
256
335
|
}
|
|
257
336
|
|
|
337
|
+
public async getSerumV3FulfillmentConfig(
|
|
338
|
+
serumMarket: PublicKey
|
|
339
|
+
): Promise<SerumV3FulfillmentConfigAccount> {
|
|
340
|
+
const address = await getSerumFulfillmentConfigPublicKey(
|
|
341
|
+
this.program.programId,
|
|
342
|
+
serumMarket
|
|
343
|
+
);
|
|
344
|
+
return (await this.program.account.serumV3FulfillmentConfig.fetch(
|
|
345
|
+
address
|
|
346
|
+
)) as SerumV3FulfillmentConfigAccount;
|
|
347
|
+
}
|
|
348
|
+
|
|
258
349
|
/**
|
|
259
350
|
* Update the wallet to use for clearing house transactions and linked user account
|
|
260
351
|
* @param newWallet
|
|
@@ -283,6 +374,7 @@ export class ClearingHouse {
|
|
|
283
374
|
this.wallet = newWallet;
|
|
284
375
|
this.provider = newProvider;
|
|
285
376
|
this.program = newProgram;
|
|
377
|
+
this.authority = newWallet.publicKey;
|
|
286
378
|
|
|
287
379
|
if (this.isSubscribed) {
|
|
288
380
|
await Promise.all(this.unsubscribeUsers());
|
|
@@ -294,6 +386,7 @@ export class ClearingHouse {
|
|
|
294
386
|
}
|
|
295
387
|
|
|
296
388
|
this.activeUserId = activeUserId;
|
|
389
|
+
this.userStatsAccountPublicKey = undefined;
|
|
297
390
|
}
|
|
298
391
|
|
|
299
392
|
public async switchActiveUser(userId: number): Promise<void> {
|
|
@@ -312,19 +405,26 @@ export class ClearingHouse {
|
|
|
312
405
|
|
|
313
406
|
public async initializeUserAccount(
|
|
314
407
|
userId = 0,
|
|
315
|
-
name = DEFAULT_USER_NAME
|
|
408
|
+
name = DEFAULT_USER_NAME,
|
|
409
|
+
referrerInfo?: ReferrerInfo
|
|
316
410
|
): Promise<[TransactionSignature, PublicKey]> {
|
|
317
411
|
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
318
|
-
await this.getInitializeUserInstructions(userId, name);
|
|
412
|
+
await this.getInitializeUserInstructions(userId, name, referrerInfo);
|
|
319
413
|
|
|
320
|
-
const tx = new Transaction()
|
|
414
|
+
const tx = new Transaction();
|
|
415
|
+
if (userId === 0) {
|
|
416
|
+
// not the safest assumption, can explicitly check if user stats account exists if it causes problems
|
|
417
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
418
|
+
}
|
|
419
|
+
tx.add(initializeUserAccountIx);
|
|
321
420
|
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
322
421
|
return [txSig, userAccountPublicKey];
|
|
323
422
|
}
|
|
324
423
|
|
|
325
424
|
async getInitializeUserInstructions(
|
|
326
425
|
userId = 0,
|
|
327
|
-
name = DEFAULT_USER_NAME
|
|
426
|
+
name = DEFAULT_USER_NAME,
|
|
427
|
+
referrerInfo?: ReferrerInfo
|
|
328
428
|
): Promise<[PublicKey, TransactionInstruction]> {
|
|
329
429
|
const userAccountPublicKey = await getUserAccountPublicKey(
|
|
330
430
|
this.program.programId,
|
|
@@ -332,22 +432,147 @@ export class ClearingHouse {
|
|
|
332
432
|
userId
|
|
333
433
|
);
|
|
334
434
|
|
|
435
|
+
const remainingAccounts = new Array<AccountMeta>();
|
|
436
|
+
if (referrerInfo !== undefined) {
|
|
437
|
+
remainingAccounts.push({
|
|
438
|
+
pubkey: referrerInfo.referrer,
|
|
439
|
+
isWritable: true,
|
|
440
|
+
isSigner: false,
|
|
441
|
+
});
|
|
442
|
+
remainingAccounts.push({
|
|
443
|
+
pubkey: referrerInfo.referrerStats,
|
|
444
|
+
isWritable: true,
|
|
445
|
+
isSigner: false,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const state = this.getStateAccount();
|
|
450
|
+
if (!state.whitelistMint.equals(PublicKey.default)) {
|
|
451
|
+
const associatedTokenPublicKey = await Token.getAssociatedTokenAddress(
|
|
452
|
+
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
453
|
+
TOKEN_PROGRAM_ID,
|
|
454
|
+
state.whitelistMint,
|
|
455
|
+
this.wallet.publicKey
|
|
456
|
+
);
|
|
457
|
+
remainingAccounts.push({
|
|
458
|
+
pubkey: associatedTokenPublicKey,
|
|
459
|
+
isWritable: false,
|
|
460
|
+
isSigner: false,
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
335
464
|
const nameBuffer = encodeName(name);
|
|
336
465
|
const initializeUserAccountIx =
|
|
337
466
|
await this.program.instruction.initializeUser(userId, nameBuffer, {
|
|
338
467
|
accounts: {
|
|
339
468
|
user: userAccountPublicKey,
|
|
469
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
340
470
|
authority: this.wallet.publicKey,
|
|
341
471
|
payer: this.wallet.publicKey,
|
|
342
472
|
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
343
473
|
systemProgram: anchor.web3.SystemProgram.programId,
|
|
344
474
|
state: await this.getStatePublicKey(),
|
|
345
475
|
},
|
|
476
|
+
remainingAccounts,
|
|
346
477
|
});
|
|
347
478
|
|
|
348
479
|
return [userAccountPublicKey, initializeUserAccountIx];
|
|
349
480
|
}
|
|
350
481
|
|
|
482
|
+
async getInitializeUserStatsIx(): Promise<TransactionInstruction> {
|
|
483
|
+
return await this.program.instruction.initializeUserStats({
|
|
484
|
+
accounts: {
|
|
485
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
486
|
+
authority: this.wallet.publicKey,
|
|
487
|
+
payer: this.wallet.publicKey,
|
|
488
|
+
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
489
|
+
systemProgram: anchor.web3.SystemProgram.programId,
|
|
490
|
+
state: await this.getStatePublicKey(),
|
|
491
|
+
},
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
public async updateUserName(
|
|
496
|
+
name: string,
|
|
497
|
+
userId = 0
|
|
498
|
+
): Promise<TransactionSignature> {
|
|
499
|
+
const nameBuffer = encodeName(name);
|
|
500
|
+
return await this.program.rpc.updateUserName(userId, nameBuffer, {
|
|
501
|
+
accounts: {
|
|
502
|
+
user: await this.getUserAccountPublicKey(),
|
|
503
|
+
authority: this.wallet.publicKey,
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
public async updateUserCustomMarginRatio(
|
|
509
|
+
marginRatio: number,
|
|
510
|
+
userId = 0
|
|
511
|
+
): Promise<TransactionSignature> {
|
|
512
|
+
return await this.program.rpc.updateUserCustomMarginRatio(
|
|
513
|
+
userId,
|
|
514
|
+
marginRatio,
|
|
515
|
+
{
|
|
516
|
+
accounts: {
|
|
517
|
+
user: await this.getUserAccountPublicKey(),
|
|
518
|
+
authority: this.wallet.publicKey,
|
|
519
|
+
},
|
|
520
|
+
}
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
public async updateUserDelegate(
|
|
525
|
+
delegate: PublicKey,
|
|
526
|
+
userId = 0
|
|
527
|
+
): Promise<TransactionSignature> {
|
|
528
|
+
return await this.program.rpc.updateUserDelegate(userId, delegate, {
|
|
529
|
+
accounts: {
|
|
530
|
+
user: await this.getUserAccountPublicKey(),
|
|
531
|
+
authority: this.wallet.publicKey,
|
|
532
|
+
},
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
public async getUserAccountsForDelegate(
|
|
537
|
+
delegate: PublicKey
|
|
538
|
+
): Promise<UserAccount[]> {
|
|
539
|
+
const programAccounts = await this.program.account.user.all([
|
|
540
|
+
{
|
|
541
|
+
memcmp: {
|
|
542
|
+
offset: 40,
|
|
543
|
+
/** data to match, as base-58 encoded string and limited to less than 129 bytes */
|
|
544
|
+
bytes: bs58.encode(delegate.toBuffer()),
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
]);
|
|
548
|
+
|
|
549
|
+
return programAccounts.map(
|
|
550
|
+
(programAccount) => programAccount.account as UserAccount
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
public async deleteUser(userId = 0): Promise<TransactionSignature> {
|
|
555
|
+
const userAccountPublicKey = getUserAccountPublicKeySync(
|
|
556
|
+
this.program.programId,
|
|
557
|
+
this.wallet.publicKey,
|
|
558
|
+
userId
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
const txSig = await this.program.rpc.deleteUser({
|
|
562
|
+
accounts: {
|
|
563
|
+
user: userAccountPublicKey,
|
|
564
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
565
|
+
authority: this.wallet.publicKey,
|
|
566
|
+
state: await this.getStatePublicKey(),
|
|
567
|
+
},
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
await this.users.get(userId)?.unsubscribe();
|
|
571
|
+
this.users.delete(userId);
|
|
572
|
+
|
|
573
|
+
return txSig;
|
|
574
|
+
}
|
|
575
|
+
|
|
351
576
|
public getUser(userId?: number): ClearingHouseUser {
|
|
352
577
|
userId = userId ?? this.activeUserId;
|
|
353
578
|
if (!this.users.has(userId)) {
|
|
@@ -360,6 +585,23 @@ export class ClearingHouse {
|
|
|
360
585
|
return [...this.users.values()];
|
|
361
586
|
}
|
|
362
587
|
|
|
588
|
+
public getUserStats(): ClearingHouseUserStats {
|
|
589
|
+
return this.userStats;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
userStatsAccountPublicKey: PublicKey;
|
|
593
|
+
public getUserStatsAccountPublicKey(): PublicKey {
|
|
594
|
+
if (this.userStatsAccountPublicKey) {
|
|
595
|
+
return this.userStatsAccountPublicKey;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
this.userStatsAccountPublicKey = getUserStatsAccountPublicKey(
|
|
599
|
+
this.program.programId,
|
|
600
|
+
this.authority
|
|
601
|
+
);
|
|
602
|
+
return this.userStatsAccountPublicKey;
|
|
603
|
+
}
|
|
604
|
+
|
|
363
605
|
public async getUserAccountPublicKey(): Promise<PublicKey> {
|
|
364
606
|
return this.getUser().userAccountPublicKey;
|
|
365
607
|
}
|
|
@@ -374,72 +616,76 @@ export class ClearingHouse {
|
|
|
374
616
|
return this.getUser(userId).getUserAccountAndSlot();
|
|
375
617
|
}
|
|
376
618
|
|
|
377
|
-
public
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const bankIndexBN = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
|
|
381
|
-
return this.getUserAccount().bankBalances.find((bankBalance) =>
|
|
382
|
-
bankBalance.bankIndex.eq(bankIndexBN)
|
|
619
|
+
public getSpotPosition(marketIndex: number): SpotPosition | undefined {
|
|
620
|
+
return this.getUserAccount().spotPositions.find(
|
|
621
|
+
(spotPosition) => spotPosition.marketIndex === marketIndex
|
|
383
622
|
);
|
|
384
623
|
}
|
|
385
624
|
|
|
386
625
|
public getQuoteAssetTokenAmount(): BN {
|
|
387
|
-
const
|
|
388
|
-
const
|
|
626
|
+
const spotMarket = this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX);
|
|
627
|
+
const spotPosition = this.getSpotPosition(QUOTE_SPOT_MARKET_INDEX);
|
|
389
628
|
return getTokenAmount(
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
629
|
+
spotPosition.balance,
|
|
630
|
+
spotMarket,
|
|
631
|
+
spotPosition.balanceType
|
|
393
632
|
);
|
|
394
633
|
}
|
|
395
634
|
|
|
396
|
-
getRemainingAccounts(params: {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}): AccountMeta[] {
|
|
400
|
-
const userAccountAndSlot = this.getUserAccountAndSlot();
|
|
401
|
-
if (!userAccountAndSlot) {
|
|
402
|
-
throw Error(
|
|
403
|
-
'No user account found. Most likely user account does not exist or failed to fetch account'
|
|
404
|
-
);
|
|
405
|
-
}
|
|
406
|
-
const { data: userAccount, slot: lastUserPositionsSlot } =
|
|
407
|
-
userAccountAndSlot;
|
|
635
|
+
getRemainingAccounts(params: RemainingAccountParams): AccountMeta[] {
|
|
636
|
+
const { oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap } =
|
|
637
|
+
this.getRemainingAccountMapsForUsers(params.userAccounts);
|
|
408
638
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
|
|
639
|
+
if (params.useMarketLastSlotCache) {
|
|
640
|
+
const lastUserPositionsSlot = this.getUserAccountAndSlot()?.slot;
|
|
641
|
+
for (const [marketIndex, slot] of this.marketLastSlotCache.entries()) {
|
|
642
|
+
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
643
|
+
// otherwise remove from slot
|
|
644
|
+
if (slot > lastUserPositionsSlot) {
|
|
645
|
+
const marketAccount = this.getPerpMarketAccount(marketIndex);
|
|
646
|
+
perpMarketAccountMap.set(marketIndex, {
|
|
647
|
+
pubkey: marketAccount.pubkey,
|
|
648
|
+
isSigner: false,
|
|
649
|
+
isWritable: false,
|
|
650
|
+
});
|
|
651
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
652
|
+
pubkey: marketAccount.amm.oracle,
|
|
653
|
+
isSigner: false,
|
|
654
|
+
isWritable: false,
|
|
655
|
+
});
|
|
656
|
+
} else {
|
|
657
|
+
this.marketLastSlotCache.delete(marketIndex);
|
|
658
|
+
}
|
|
429
659
|
}
|
|
430
660
|
}
|
|
431
661
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
662
|
+
if (params.readablePerpMarketIndex !== undefined) {
|
|
663
|
+
const marketAccount = this.getPerpMarketAccount(
|
|
664
|
+
params.readablePerpMarketIndex
|
|
665
|
+
);
|
|
666
|
+
perpMarketAccountMap.set(params.readablePerpMarketIndex, {
|
|
667
|
+
pubkey: marketAccount.pubkey,
|
|
668
|
+
isSigner: false,
|
|
669
|
+
isWritable: false,
|
|
670
|
+
});
|
|
671
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
672
|
+
pubkey: marketAccount.amm.oracle,
|
|
673
|
+
isSigner: false,
|
|
674
|
+
isWritable: false,
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
if (params.writablePerpMarketIndexes !== undefined) {
|
|
679
|
+
for (const writablePerpMarketIndex of params.writablePerpMarketIndexes) {
|
|
680
|
+
const marketAccount = this.getPerpMarketAccount(
|
|
681
|
+
writablePerpMarketIndex
|
|
682
|
+
);
|
|
683
|
+
perpMarketAccountMap.set(writablePerpMarketIndex, {
|
|
437
684
|
pubkey: marketAccount.pubkey,
|
|
438
685
|
isSigner: false,
|
|
439
|
-
// isWritable: false, // TODO
|
|
440
686
|
isWritable: true,
|
|
441
687
|
});
|
|
442
|
-
oracleAccountMap.set(marketAccount.
|
|
688
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
443
689
|
pubkey: marketAccount.amm.oracle,
|
|
444
690
|
isSigner: false,
|
|
445
691
|
isWritable: false,
|
|
@@ -447,67 +693,108 @@ export class ClearingHouse {
|
|
|
447
693
|
}
|
|
448
694
|
}
|
|
449
695
|
|
|
450
|
-
if (params.
|
|
451
|
-
const
|
|
452
|
-
params.
|
|
696
|
+
if (params.readableSpotMarketIndex !== undefined) {
|
|
697
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
698
|
+
params.readableSpotMarketIndex
|
|
453
699
|
);
|
|
454
|
-
|
|
455
|
-
pubkey:
|
|
456
|
-
isSigner: false,
|
|
457
|
-
isWritable: true,
|
|
458
|
-
});
|
|
459
|
-
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
460
|
-
pubkey: marketAccount.amm.oracle,
|
|
700
|
+
spotMarketAccountMap.set(params.readableSpotMarketIndex, {
|
|
701
|
+
pubkey: spotMarketAccount.pubkey,
|
|
461
702
|
isSigner: false,
|
|
462
703
|
isWritable: false,
|
|
463
704
|
});
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (!userBankBalance.balance.eq(ZERO)) {
|
|
468
|
-
const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
|
|
469
|
-
bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
|
|
470
|
-
pubkey: bankAccount.pubkey,
|
|
705
|
+
if (spotMarketAccount.marketIndex !== 0) {
|
|
706
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
707
|
+
pubkey: spotMarketAccount.oracle,
|
|
471
708
|
isSigner: false,
|
|
472
709
|
isWritable: false,
|
|
473
710
|
});
|
|
474
|
-
if (!bankAccount.bankIndex.eq(ZERO)) {
|
|
475
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
476
|
-
pubkey: bankAccount.oracle,
|
|
477
|
-
isSigner: false,
|
|
478
|
-
isWritable: false,
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
711
|
}
|
|
482
712
|
}
|
|
483
713
|
|
|
484
|
-
if (params.
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
if (!bankAccount.bankIndex.eq(ZERO)) {
|
|
492
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
493
|
-
pubkey: bankAccount.oracle,
|
|
714
|
+
if (params.writableSpotMarketIndexes !== undefined) {
|
|
715
|
+
for (const writableSpotMarketIndex of params.writableSpotMarketIndexes) {
|
|
716
|
+
const spotMarketAccount = this.getSpotMarketAccount(
|
|
717
|
+
writableSpotMarketIndex
|
|
718
|
+
);
|
|
719
|
+
spotMarketAccountMap.set(spotMarketAccount.marketIndex, {
|
|
720
|
+
pubkey: spotMarketAccount.pubkey,
|
|
494
721
|
isSigner: false,
|
|
495
|
-
isWritable:
|
|
722
|
+
isWritable: true,
|
|
496
723
|
});
|
|
724
|
+
if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
|
|
725
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
726
|
+
pubkey: spotMarketAccount.oracle,
|
|
727
|
+
isSigner: false,
|
|
728
|
+
isWritable: false,
|
|
729
|
+
});
|
|
730
|
+
}
|
|
497
731
|
}
|
|
498
732
|
}
|
|
499
733
|
|
|
500
734
|
return [
|
|
501
735
|
...oracleAccountMap.values(),
|
|
502
|
-
...
|
|
503
|
-
...
|
|
736
|
+
...spotMarketAccountMap.values(),
|
|
737
|
+
...perpMarketAccountMap.values(),
|
|
504
738
|
];
|
|
505
739
|
}
|
|
506
740
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
741
|
+
getRemainingAccountMapsForUsers(userAccounts: UserAccount[]): {
|
|
742
|
+
oracleAccountMap: Map<string, AccountMeta>;
|
|
743
|
+
spotMarketAccountMap: Map<number, AccountMeta>;
|
|
744
|
+
perpMarketAccountMap: Map<number, AccountMeta>;
|
|
745
|
+
} {
|
|
746
|
+
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
747
|
+
const spotMarketAccountMap = new Map<number, AccountMeta>();
|
|
748
|
+
const perpMarketAccountMap = new Map<number, AccountMeta>();
|
|
749
|
+
|
|
750
|
+
for (const userAccount of userAccounts) {
|
|
751
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
752
|
+
if (!isSpotPositionAvailable(spotPosition)) {
|
|
753
|
+
const spotMarket = this.getSpotMarketAccount(
|
|
754
|
+
spotPosition.marketIndex
|
|
755
|
+
);
|
|
756
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
757
|
+
pubkey: spotMarket.pubkey,
|
|
758
|
+
isSigner: false,
|
|
759
|
+
isWritable: false,
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
if (!spotMarket.oracle.equals(PublicKey.default)) {
|
|
763
|
+
oracleAccountMap.set(spotMarket.oracle.toString(), {
|
|
764
|
+
pubkey: spotMarket.oracle,
|
|
765
|
+
isSigner: false,
|
|
766
|
+
isWritable: false,
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
for (const position of userAccount.perpPositions) {
|
|
772
|
+
if (!positionIsAvailable(position)) {
|
|
773
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
774
|
+
perpMarketAccountMap.set(position.marketIndex, {
|
|
775
|
+
pubkey: market.pubkey,
|
|
776
|
+
isWritable: false,
|
|
777
|
+
isSigner: false,
|
|
778
|
+
});
|
|
779
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
780
|
+
pubkey: market.amm.oracle,
|
|
781
|
+
isWritable: false,
|
|
782
|
+
isSigner: false,
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
return {
|
|
789
|
+
oracleAccountMap,
|
|
790
|
+
spotMarketAccountMap,
|
|
791
|
+
perpMarketAccountMap,
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
public getOrder(orderId: number): Order | undefined {
|
|
796
|
+
return this.getUserAccount()?.orders.find(
|
|
797
|
+
(order) => order.orderId === orderId
|
|
511
798
|
);
|
|
512
799
|
}
|
|
513
800
|
|
|
@@ -519,29 +806,71 @@ export class ClearingHouse {
|
|
|
519
806
|
|
|
520
807
|
public async deposit(
|
|
521
808
|
amount: BN,
|
|
522
|
-
|
|
809
|
+
marketIndex: number,
|
|
523
810
|
collateralAccountPublicKey: PublicKey,
|
|
524
811
|
userId?: number,
|
|
525
812
|
reduceOnly = false
|
|
526
813
|
): Promise<TransactionSignature> {
|
|
814
|
+
const tx = new Transaction();
|
|
815
|
+
const additionalSigners: Array<Signer> = [];
|
|
816
|
+
|
|
817
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
818
|
+
|
|
819
|
+
const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
|
|
820
|
+
|
|
821
|
+
const authority = this.authority;
|
|
822
|
+
|
|
823
|
+
const createWSOLTokenAccount =
|
|
824
|
+
isSolMarket && collateralAccountPublicKey.equals(authority);
|
|
825
|
+
|
|
826
|
+
if (createWSOLTokenAccount) {
|
|
827
|
+
const { ixs, signers, pubkey } =
|
|
828
|
+
await this.getWrappedSolAccountCreationIxs(amount, true);
|
|
829
|
+
|
|
830
|
+
collateralAccountPublicKey = pubkey;
|
|
831
|
+
|
|
832
|
+
ixs.forEach((ix) => {
|
|
833
|
+
tx.add(ix);
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
837
|
+
}
|
|
838
|
+
|
|
527
839
|
const depositCollateralIx = await this.getDepositInstruction(
|
|
528
840
|
amount,
|
|
529
|
-
|
|
841
|
+
marketIndex,
|
|
530
842
|
collateralAccountPublicKey,
|
|
531
843
|
userId,
|
|
532
844
|
reduceOnly,
|
|
533
845
|
true
|
|
534
846
|
);
|
|
535
847
|
|
|
536
|
-
|
|
848
|
+
tx.add(depositCollateralIx);
|
|
849
|
+
|
|
850
|
+
// Close the wrapped sol account at the end of the transaction
|
|
851
|
+
if (createWSOLTokenAccount) {
|
|
852
|
+
tx.add(
|
|
853
|
+
Token.createCloseAccountInstruction(
|
|
854
|
+
TOKEN_PROGRAM_ID,
|
|
855
|
+
collateralAccountPublicKey,
|
|
856
|
+
authority,
|
|
857
|
+
authority,
|
|
858
|
+
[]
|
|
859
|
+
)
|
|
860
|
+
);
|
|
861
|
+
}
|
|
537
862
|
|
|
538
|
-
const { txSig } = await this.txSender.send(
|
|
863
|
+
const { txSig } = await this.txSender.send(
|
|
864
|
+
tx,
|
|
865
|
+
additionalSigners,
|
|
866
|
+
this.opts
|
|
867
|
+
);
|
|
539
868
|
return txSig;
|
|
540
869
|
}
|
|
541
870
|
|
|
542
871
|
async getDepositInstruction(
|
|
543
872
|
amount: BN,
|
|
544
|
-
|
|
873
|
+
marketIndex: number,
|
|
545
874
|
userTokenAccount: PublicKey,
|
|
546
875
|
userId?: number,
|
|
547
876
|
reduceOnly = false,
|
|
@@ -550,7 +879,7 @@ export class ClearingHouse {
|
|
|
550
879
|
const userAccountPublicKey = userId
|
|
551
880
|
? await getUserAccountPublicKey(
|
|
552
881
|
this.program.programId,
|
|
553
|
-
this.
|
|
882
|
+
this.authority,
|
|
554
883
|
userId
|
|
555
884
|
)
|
|
556
885
|
: await this.getUserAccountPublicKey();
|
|
@@ -558,30 +887,30 @@ export class ClearingHouse {
|
|
|
558
887
|
let remainingAccounts = [];
|
|
559
888
|
if (userInitialized) {
|
|
560
889
|
remainingAccounts = this.getRemainingAccounts({
|
|
561
|
-
|
|
890
|
+
userAccounts: [this.getUserAccount()],
|
|
891
|
+
useMarketLastSlotCache: true,
|
|
892
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
562
893
|
});
|
|
563
894
|
} else {
|
|
564
|
-
remainingAccounts =
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
isWritable: true,
|
|
569
|
-
},
|
|
570
|
-
];
|
|
895
|
+
remainingAccounts = this.getRemainingAccounts({
|
|
896
|
+
userAccounts: [],
|
|
897
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
898
|
+
});
|
|
571
899
|
}
|
|
572
900
|
|
|
573
|
-
const
|
|
901
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
574
902
|
|
|
575
903
|
return await this.program.instruction.deposit(
|
|
576
|
-
|
|
904
|
+
marketIndex,
|
|
577
905
|
amount,
|
|
578
906
|
reduceOnly,
|
|
579
907
|
{
|
|
580
908
|
accounts: {
|
|
581
909
|
state: await this.getStatePublicKey(),
|
|
582
|
-
|
|
583
|
-
|
|
910
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
911
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
584
912
|
user: userAccountPublicKey,
|
|
913
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
585
914
|
userTokenAccount: userTokenAccount,
|
|
586
915
|
authority: this.wallet.publicKey,
|
|
587
916
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
@@ -591,43 +920,172 @@ export class ClearingHouse {
|
|
|
591
920
|
);
|
|
592
921
|
}
|
|
593
922
|
|
|
923
|
+
private async checkIfAccountExists(account: PublicKey): Promise<boolean> {
|
|
924
|
+
try {
|
|
925
|
+
const accountInfo = await this.connection.getAccountInfo(account);
|
|
926
|
+
return accountInfo != null;
|
|
927
|
+
} catch (e) {
|
|
928
|
+
// Doesn't already exist
|
|
929
|
+
return false;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
private async getWrappedSolAccountCreationIxs(
|
|
934
|
+
amount: BN,
|
|
935
|
+
isDeposit?: boolean
|
|
936
|
+
): Promise<{
|
|
937
|
+
ixs: anchor.web3.TransactionInstruction[];
|
|
938
|
+
signers: Signer[];
|
|
939
|
+
pubkey: PublicKey;
|
|
940
|
+
}> {
|
|
941
|
+
const wrappedSolAccount = new Keypair();
|
|
942
|
+
|
|
943
|
+
const result = {
|
|
944
|
+
ixs: [],
|
|
945
|
+
signers: [],
|
|
946
|
+
pubkey: wrappedSolAccount.publicKey,
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
const rentSpaceLamports = new BN(LAMPORTS_PER_SOL / 100);
|
|
950
|
+
|
|
951
|
+
const lamports = isDeposit
|
|
952
|
+
? amount.add(rentSpaceLamports)
|
|
953
|
+
: rentSpaceLamports;
|
|
954
|
+
|
|
955
|
+
const authority = this.wallet.publicKey;
|
|
956
|
+
|
|
957
|
+
result.ixs.push(
|
|
958
|
+
SystemProgram.createAccount({
|
|
959
|
+
fromPubkey: authority,
|
|
960
|
+
newAccountPubkey: wrappedSolAccount.publicKey,
|
|
961
|
+
lamports: lamports.toNumber(),
|
|
962
|
+
space: 165,
|
|
963
|
+
programId: TOKEN_PROGRAM_ID,
|
|
964
|
+
})
|
|
965
|
+
);
|
|
966
|
+
|
|
967
|
+
result.ixs.push(
|
|
968
|
+
Token.createInitAccountInstruction(
|
|
969
|
+
TOKEN_PROGRAM_ID,
|
|
970
|
+
WRAPPED_SOL_MINT,
|
|
971
|
+
wrappedSolAccount.publicKey,
|
|
972
|
+
authority
|
|
973
|
+
)
|
|
974
|
+
);
|
|
975
|
+
|
|
976
|
+
result.signers.push(wrappedSolAccount);
|
|
977
|
+
|
|
978
|
+
return result;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
public getAssociatedTokenAccountCreationIx(
|
|
982
|
+
tokenMintAddress: PublicKey,
|
|
983
|
+
associatedTokenAddress: PublicKey
|
|
984
|
+
): anchor.web3.TransactionInstruction {
|
|
985
|
+
const createAssociatedAccountIx =
|
|
986
|
+
Token.createAssociatedTokenAccountInstruction(
|
|
987
|
+
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
988
|
+
TOKEN_PROGRAM_ID,
|
|
989
|
+
tokenMintAddress,
|
|
990
|
+
associatedTokenAddress,
|
|
991
|
+
this.wallet.publicKey,
|
|
992
|
+
this.wallet.publicKey
|
|
993
|
+
);
|
|
994
|
+
|
|
995
|
+
return createAssociatedAccountIx;
|
|
996
|
+
}
|
|
997
|
+
|
|
594
998
|
/**
|
|
595
999
|
* Creates the Clearing House User account for a user, and deposits some initial collateral
|
|
596
|
-
* @param userId
|
|
597
|
-
* @param name
|
|
598
1000
|
* @param amount
|
|
599
1001
|
* @param userTokenAccount
|
|
1002
|
+
* @param marketIndex
|
|
1003
|
+
* @param userId
|
|
1004
|
+
* @param name
|
|
600
1005
|
* @param fromUserId
|
|
601
1006
|
* @returns
|
|
602
1007
|
*/
|
|
603
1008
|
public async initializeUserAccountAndDepositCollateral(
|
|
604
1009
|
amount: BN,
|
|
605
1010
|
userTokenAccount: PublicKey,
|
|
606
|
-
|
|
1011
|
+
marketIndex = 0,
|
|
607
1012
|
userId = 0,
|
|
608
1013
|
name = DEFAULT_USER_NAME,
|
|
609
|
-
fromUserId?: number
|
|
1014
|
+
fromUserId?: number,
|
|
1015
|
+
referrerInfo?: ReferrerInfo
|
|
610
1016
|
): Promise<[TransactionSignature, PublicKey]> {
|
|
611
1017
|
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
612
|
-
await this.getInitializeUserInstructions(userId, name);
|
|
1018
|
+
await this.getInitializeUserInstructions(userId, name, referrerInfo);
|
|
1019
|
+
|
|
1020
|
+
const additionalSigners: Array<Signer> = [];
|
|
1021
|
+
|
|
1022
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
1023
|
+
|
|
1024
|
+
const isSolMarket = spotMarket.mint.equals(WRAPPED_SOL_MINT);
|
|
1025
|
+
|
|
1026
|
+
const tx = new Transaction();
|
|
1027
|
+
|
|
1028
|
+
const authority = this.wallet.publicKey;
|
|
1029
|
+
|
|
1030
|
+
const createWSOLTokenAccount =
|
|
1031
|
+
isSolMarket && userTokenAccount.equals(authority);
|
|
1032
|
+
|
|
1033
|
+
if (createWSOLTokenAccount) {
|
|
1034
|
+
const {
|
|
1035
|
+
ixs: startIxs,
|
|
1036
|
+
signers,
|
|
1037
|
+
pubkey,
|
|
1038
|
+
} = await this.getWrappedSolAccountCreationIxs(amount, true);
|
|
1039
|
+
|
|
1040
|
+
userTokenAccount = pubkey;
|
|
1041
|
+
|
|
1042
|
+
startIxs.forEach((ix) => {
|
|
1043
|
+
tx.add(ix);
|
|
1044
|
+
});
|
|
1045
|
+
|
|
1046
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
1047
|
+
}
|
|
613
1048
|
|
|
614
1049
|
const depositCollateralIx =
|
|
615
1050
|
fromUserId != null
|
|
616
|
-
? await this.getTransferDepositIx(
|
|
1051
|
+
? await this.getTransferDepositIx(
|
|
1052
|
+
amount,
|
|
1053
|
+
marketIndex,
|
|
1054
|
+
fromUserId,
|
|
1055
|
+
userId
|
|
1056
|
+
)
|
|
617
1057
|
: await this.getDepositInstruction(
|
|
618
1058
|
amount,
|
|
619
|
-
|
|
1059
|
+
marketIndex,
|
|
620
1060
|
userTokenAccount,
|
|
621
1061
|
userId,
|
|
622
1062
|
false,
|
|
623
1063
|
false
|
|
624
1064
|
);
|
|
625
1065
|
|
|
626
|
-
|
|
627
|
-
.add(
|
|
628
|
-
|
|
1066
|
+
if (userId === 0) {
|
|
1067
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
1068
|
+
}
|
|
1069
|
+
tx.add(initializeUserAccountIx).add(depositCollateralIx);
|
|
1070
|
+
|
|
1071
|
+
// Close the wrapped sol account at the end of the transaction
|
|
1072
|
+
if (createWSOLTokenAccount) {
|
|
1073
|
+
tx.add(
|
|
1074
|
+
Token.createCloseAccountInstruction(
|
|
1075
|
+
TOKEN_PROGRAM_ID,
|
|
1076
|
+
userTokenAccount,
|
|
1077
|
+
authority,
|
|
1078
|
+
authority,
|
|
1079
|
+
[]
|
|
1080
|
+
)
|
|
1081
|
+
);
|
|
1082
|
+
}
|
|
629
1083
|
|
|
630
|
-
const { txSig } = await this.txSender.send(
|
|
1084
|
+
const { txSig } = await this.txSender.send(
|
|
1085
|
+
tx,
|
|
1086
|
+
additionalSigners,
|
|
1087
|
+
this.opts
|
|
1088
|
+
);
|
|
631
1089
|
|
|
632
1090
|
return [txSig, userAccountPublicKey];
|
|
633
1091
|
}
|
|
@@ -635,54 +1093,109 @@ export class ClearingHouse {
|
|
|
635
1093
|
public async initializeUserAccountForDevnet(
|
|
636
1094
|
userId = 0,
|
|
637
1095
|
name = DEFAULT_USER_NAME,
|
|
638
|
-
|
|
639
|
-
|
|
1096
|
+
marketIndex: number,
|
|
1097
|
+
tokenFaucet: TokenFaucet,
|
|
1098
|
+
amount: BN,
|
|
1099
|
+
referrerInfo?: ReferrerInfo
|
|
640
1100
|
): Promise<[TransactionSignature, PublicKey]> {
|
|
641
1101
|
const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] =
|
|
642
|
-
await
|
|
1102
|
+
await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(
|
|
643
1103
|
this.wallet.publicKey,
|
|
644
1104
|
amount
|
|
645
1105
|
);
|
|
646
1106
|
|
|
647
1107
|
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
648
|
-
await this.getInitializeUserInstructions(userId, name);
|
|
1108
|
+
await this.getInitializeUserInstructions(userId, name, referrerInfo);
|
|
649
1109
|
|
|
650
1110
|
const depositCollateralIx = await this.getDepositInstruction(
|
|
651
1111
|
amount,
|
|
652
|
-
|
|
1112
|
+
marketIndex,
|
|
653
1113
|
associateTokenPublicKey,
|
|
654
1114
|
userId,
|
|
655
1115
|
false,
|
|
656
1116
|
false
|
|
657
1117
|
);
|
|
658
1118
|
|
|
659
|
-
const tx = new Transaction()
|
|
660
|
-
.add(createAssociatedAccountIx)
|
|
661
|
-
.add(mintToIx)
|
|
662
|
-
.add(initializeUserAccountIx)
|
|
663
|
-
.add(depositCollateralIx);
|
|
1119
|
+
const tx = new Transaction().add(createAssociatedAccountIx).add(mintToIx);
|
|
664
1120
|
|
|
665
|
-
|
|
1121
|
+
if (userId === 0) {
|
|
1122
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
1123
|
+
}
|
|
1124
|
+
tx.add(initializeUserAccountIx).add(depositCollateralIx);
|
|
1125
|
+
|
|
1126
|
+
const txSig = await this.program.provider.sendAndConfirm(tx, []);
|
|
666
1127
|
|
|
667
1128
|
return [txSig, userAccountPublicKey];
|
|
668
1129
|
}
|
|
669
1130
|
|
|
670
1131
|
public async withdraw(
|
|
671
1132
|
amount: BN,
|
|
672
|
-
|
|
1133
|
+
marketIndex: number,
|
|
673
1134
|
userTokenAccount: PublicKey,
|
|
674
1135
|
reduceOnly = false
|
|
675
1136
|
): Promise<TransactionSignature> {
|
|
676
|
-
const
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
1137
|
+
const tx = new Transaction();
|
|
1138
|
+
const additionalSigners: Array<Signer> = [];
|
|
1139
|
+
|
|
1140
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
1141
|
+
|
|
1142
|
+
const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
|
|
1143
|
+
|
|
1144
|
+
const authority = this.wallet.publicKey;
|
|
1145
|
+
|
|
1146
|
+
const createWSOLTokenAccount =
|
|
1147
|
+
isSolMarket && userTokenAccount.equals(authority);
|
|
1148
|
+
|
|
1149
|
+
if (createWSOLTokenAccount) {
|
|
1150
|
+
const { ixs, signers, pubkey } =
|
|
1151
|
+
await this.getWrappedSolAccountCreationIxs(amount, false);
|
|
1152
|
+
|
|
1153
|
+
userTokenAccount = pubkey;
|
|
1154
|
+
|
|
1155
|
+
ixs.forEach((ix) => {
|
|
1156
|
+
tx.add(ix);
|
|
1157
|
+
});
|
|
1158
|
+
|
|
1159
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
1160
|
+
} else {
|
|
1161
|
+
const accountExists = await this.checkIfAccountExists(userTokenAccount);
|
|
1162
|
+
|
|
1163
|
+
if (!accountExists) {
|
|
1164
|
+
const createAssociatedTokenAccountIx =
|
|
1165
|
+
this.getAssociatedTokenAccountCreationIx(
|
|
1166
|
+
spotMarketAccount.mint,
|
|
1167
|
+
userTokenAccount
|
|
1168
|
+
);
|
|
1169
|
+
|
|
1170
|
+
tx.add(createAssociatedTokenAccountIx);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
const withdrawCollateral = await this.getWithdrawIx(
|
|
1175
|
+
amount,
|
|
1176
|
+
spotMarketAccount.marketIndex,
|
|
1177
|
+
userTokenAccount,
|
|
1178
|
+
reduceOnly
|
|
1179
|
+
);
|
|
1180
|
+
|
|
1181
|
+
tx.add(withdrawCollateral);
|
|
1182
|
+
|
|
1183
|
+
// Close the wrapped sol account at the end of the transaction
|
|
1184
|
+
if (createWSOLTokenAccount) {
|
|
1185
|
+
tx.add(
|
|
1186
|
+
Token.createCloseAccountInstruction(
|
|
1187
|
+
TOKEN_PROGRAM_ID,
|
|
681
1188
|
userTokenAccount,
|
|
682
|
-
|
|
1189
|
+
authority,
|
|
1190
|
+
authority,
|
|
1191
|
+
[]
|
|
683
1192
|
)
|
|
684
|
-
)
|
|
685
|
-
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
const { txSig } = await this.txSender.send(
|
|
1197
|
+
tx,
|
|
1198
|
+
additionalSigners,
|
|
686
1199
|
this.opts
|
|
687
1200
|
);
|
|
688
1201
|
return txSig;
|
|
@@ -690,29 +1203,32 @@ export class ClearingHouse {
|
|
|
690
1203
|
|
|
691
1204
|
public async getWithdrawIx(
|
|
692
1205
|
amount: BN,
|
|
693
|
-
|
|
1206
|
+
marketIndex: number,
|
|
694
1207
|
userTokenAccount: PublicKey,
|
|
695
1208
|
reduceOnly = false
|
|
696
1209
|
): Promise<TransactionInstruction> {
|
|
697
1210
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
698
1211
|
|
|
699
1212
|
const remainingAccounts = this.getRemainingAccounts({
|
|
700
|
-
|
|
1213
|
+
userAccounts: [this.getUserAccount()],
|
|
1214
|
+
useMarketLastSlotCache: true,
|
|
1215
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
701
1216
|
});
|
|
702
1217
|
|
|
703
|
-
const
|
|
1218
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
704
1219
|
|
|
705
1220
|
return await this.program.instruction.withdraw(
|
|
706
|
-
|
|
1221
|
+
marketIndex,
|
|
707
1222
|
amount,
|
|
708
1223
|
reduceOnly,
|
|
709
1224
|
{
|
|
710
1225
|
accounts: {
|
|
711
1226
|
state: await this.getStatePublicKey(),
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
1227
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
1228
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
1229
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
715
1230
|
user: userAccountPublicKey,
|
|
1231
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
716
1232
|
userTokenAccount: userTokenAccount,
|
|
717
1233
|
authority: this.wallet.publicKey,
|
|
718
1234
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
@@ -724,13 +1240,18 @@ export class ClearingHouse {
|
|
|
724
1240
|
|
|
725
1241
|
public async transferDeposit(
|
|
726
1242
|
amount: BN,
|
|
727
|
-
|
|
1243
|
+
marketIndex: number,
|
|
728
1244
|
fromUserId: number,
|
|
729
1245
|
toUserId: number
|
|
730
1246
|
): Promise<TransactionSignature> {
|
|
731
1247
|
const { txSig } = await this.txSender.send(
|
|
732
1248
|
wrapInTx(
|
|
733
|
-
await this.getTransferDepositIx(
|
|
1249
|
+
await this.getTransferDepositIx(
|
|
1250
|
+
amount,
|
|
1251
|
+
marketIndex,
|
|
1252
|
+
fromUserId,
|
|
1253
|
+
toUserId
|
|
1254
|
+
)
|
|
734
1255
|
),
|
|
735
1256
|
[],
|
|
736
1257
|
this.opts
|
|
@@ -740,7 +1261,7 @@ export class ClearingHouse {
|
|
|
740
1261
|
|
|
741
1262
|
public async getTransferDepositIx(
|
|
742
1263
|
amount: BN,
|
|
743
|
-
|
|
1264
|
+
marketIndex: number,
|
|
744
1265
|
fromUserId: number,
|
|
745
1266
|
toUserId: number
|
|
746
1267
|
): Promise<TransactionInstruction> {
|
|
@@ -755,93 +1276,292 @@ export class ClearingHouse {
|
|
|
755
1276
|
toUserId
|
|
756
1277
|
);
|
|
757
1278
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
1279
|
+
let remainingAccounts;
|
|
1280
|
+
if (this.users.has(fromUserId)) {
|
|
1281
|
+
remainingAccounts = this.getRemainingAccounts({
|
|
1282
|
+
userAccounts: [this.users.get(fromUserId).getUserAccount()],
|
|
1283
|
+
useMarketLastSlotCache: true,
|
|
1284
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
1285
|
+
});
|
|
1286
|
+
} else {
|
|
1287
|
+
const userAccountPublicKey = getUserAccountPublicKeySync(
|
|
1288
|
+
this.program.programId,
|
|
1289
|
+
this.authority,
|
|
1290
|
+
fromUserId
|
|
1291
|
+
);
|
|
1292
|
+
|
|
1293
|
+
const fromUserAccount = (await this.program.account.user.fetch(
|
|
1294
|
+
userAccountPublicKey
|
|
1295
|
+
)) as UserAccount;
|
|
1296
|
+
remainingAccounts = this.getRemainingAccounts({
|
|
1297
|
+
userAccounts: [fromUserAccount],
|
|
1298
|
+
useMarketLastSlotCache: true,
|
|
1299
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
761
1302
|
|
|
762
|
-
return await this.program.instruction.transferDeposit(
|
|
1303
|
+
return await this.program.instruction.transferDeposit(marketIndex, amount, {
|
|
763
1304
|
accounts: {
|
|
764
1305
|
authority: this.wallet.publicKey,
|
|
765
1306
|
fromUser,
|
|
766
1307
|
toUser,
|
|
1308
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
767
1309
|
state: await this.getStatePublicKey(),
|
|
768
1310
|
},
|
|
769
1311
|
remainingAccounts,
|
|
770
1312
|
});
|
|
771
1313
|
}
|
|
772
1314
|
|
|
773
|
-
public async
|
|
774
|
-
|
|
1315
|
+
public async updateSpotMarketCumulativeInterest(
|
|
1316
|
+
marketIndex: number
|
|
1317
|
+
): Promise<TransactionSignature> {
|
|
1318
|
+
const { txSig } = await this.txSender.send(
|
|
1319
|
+
wrapInTx(await this.updateSpotMarketCumulativeInterestIx(marketIndex)),
|
|
1320
|
+
[],
|
|
1321
|
+
this.opts
|
|
1322
|
+
);
|
|
1323
|
+
return txSig;
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
public async updateSpotMarketCumulativeInterestIx(
|
|
1327
|
+
marketIndex: number
|
|
1328
|
+
): Promise<TransactionInstruction> {
|
|
1329
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
1330
|
+
return await this.program.instruction.updateSpotMarketCumulativeInterest({
|
|
1331
|
+
accounts: {
|
|
1332
|
+
state: await this.getStatePublicKey(),
|
|
1333
|
+
spotMarket: spotMarket.pubkey,
|
|
1334
|
+
},
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
public async settleLP(
|
|
1339
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
1340
|
+
marketIndex: number
|
|
1341
|
+
): Promise<TransactionSignature> {
|
|
1342
|
+
const { txSig } = await this.txSender.send(
|
|
1343
|
+
wrapInTx(await this.settleLPIx(settleeUserAccountPublicKey, marketIndex)),
|
|
1344
|
+
[],
|
|
1345
|
+
this.opts
|
|
1346
|
+
);
|
|
1347
|
+
return txSig;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
public async settleLPIx(
|
|
1351
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
1352
|
+
marketIndex: number
|
|
1353
|
+
): Promise<TransactionInstruction> {
|
|
1354
|
+
const settleeUserAccount = (await this.program.account.user.fetch(
|
|
1355
|
+
settleeUserAccountPublicKey
|
|
1356
|
+
)) as UserAccount;
|
|
1357
|
+
|
|
1358
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1359
|
+
userAccounts: [settleeUserAccount],
|
|
1360
|
+
writablePerpMarketIndexes: [marketIndex],
|
|
1361
|
+
});
|
|
1362
|
+
|
|
1363
|
+
return this.program.instruction.settleLp(marketIndex, {
|
|
1364
|
+
accounts: {
|
|
1365
|
+
state: await this.getStatePublicKey(),
|
|
1366
|
+
user: settleeUserAccountPublicKey,
|
|
1367
|
+
},
|
|
1368
|
+
remainingAccounts: remainingAccounts,
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
public async removeLiquidity(
|
|
1373
|
+
marketIndex: number,
|
|
1374
|
+
sharesToBurn?: BN
|
|
775
1375
|
): Promise<TransactionSignature> {
|
|
776
1376
|
const { txSig } = await this.txSender.send(
|
|
777
|
-
wrapInTx(await this.
|
|
1377
|
+
wrapInTx(await this.getRemoveLiquidityIx(marketIndex, sharesToBurn)),
|
|
1378
|
+
[],
|
|
1379
|
+
this.opts
|
|
1380
|
+
);
|
|
1381
|
+
return txSig;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
public async getRemoveLiquidityIx(
|
|
1385
|
+
marketIndex: number,
|
|
1386
|
+
sharesToBurn?: BN
|
|
1387
|
+
): Promise<TransactionInstruction> {
|
|
1388
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1389
|
+
|
|
1390
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1391
|
+
userAccounts: [this.getUserAccount()],
|
|
1392
|
+
useMarketLastSlotCache: true,
|
|
1393
|
+
writablePerpMarketIndexes: [marketIndex],
|
|
1394
|
+
});
|
|
1395
|
+
|
|
1396
|
+
if (sharesToBurn == undefined) {
|
|
1397
|
+
const userAccount = this.getUserAccount();
|
|
1398
|
+
const perpPosition = userAccount.perpPositions.filter(
|
|
1399
|
+
(position) => position.marketIndex === marketIndex
|
|
1400
|
+
)[0];
|
|
1401
|
+
sharesToBurn = perpPosition.lpShares;
|
|
1402
|
+
console.log('burning lp shares:', sharesToBurn.toString());
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
return this.program.instruction.removeLiquidity(sharesToBurn, marketIndex, {
|
|
1406
|
+
accounts: {
|
|
1407
|
+
state: await this.getStatePublicKey(),
|
|
1408
|
+
user: userAccountPublicKey,
|
|
1409
|
+
authority: this.wallet.publicKey,
|
|
1410
|
+
},
|
|
1411
|
+
remainingAccounts: remainingAccounts,
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
public async addLiquidity(
|
|
1416
|
+
amount: BN,
|
|
1417
|
+
marketIndex: number
|
|
1418
|
+
): Promise<TransactionSignature> {
|
|
1419
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1420
|
+
wrapInTx(await this.getAddLiquidityIx(amount, marketIndex)),
|
|
778
1421
|
[],
|
|
779
1422
|
this.opts
|
|
780
1423
|
);
|
|
1424
|
+
this.marketLastSlotCache.set(marketIndex, slot);
|
|
781
1425
|
return txSig;
|
|
782
1426
|
}
|
|
783
1427
|
|
|
784
|
-
public async
|
|
785
|
-
|
|
1428
|
+
public async getAddLiquidityIx(
|
|
1429
|
+
amount: BN,
|
|
1430
|
+
marketIndex: number
|
|
786
1431
|
): Promise<TransactionInstruction> {
|
|
787
|
-
const
|
|
788
|
-
|
|
1432
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1433
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1434
|
+
userAccounts: [this.getUserAccount()],
|
|
1435
|
+
useMarketLastSlotCache: true,
|
|
1436
|
+
writablePerpMarketIndexes: [marketIndex],
|
|
1437
|
+
});
|
|
1438
|
+
|
|
1439
|
+
return this.program.instruction.addLiquidity(amount, marketIndex, {
|
|
789
1440
|
accounts: {
|
|
790
|
-
|
|
1441
|
+
state: await this.getStatePublicKey(),
|
|
1442
|
+
user: userAccountPublicKey,
|
|
1443
|
+
authority: this.wallet.publicKey,
|
|
791
1444
|
},
|
|
1445
|
+
remainingAccounts: remainingAccounts,
|
|
792
1446
|
});
|
|
793
1447
|
}
|
|
794
1448
|
|
|
795
1449
|
public async openPosition(
|
|
796
1450
|
direction: PositionDirection,
|
|
797
1451
|
amount: BN,
|
|
798
|
-
marketIndex:
|
|
1452
|
+
marketIndex: number,
|
|
799
1453
|
limitPrice?: BN
|
|
800
1454
|
): Promise<TransactionSignature> {
|
|
801
|
-
return await this.placeAndTake(
|
|
802
|
-
|
|
1455
|
+
return await this.placeAndTake({
|
|
1456
|
+
orderType: OrderType.MARKET,
|
|
1457
|
+
marketIndex,
|
|
1458
|
+
direction,
|
|
1459
|
+
baseAssetAmount: amount,
|
|
1460
|
+
price: limitPrice,
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
public async sendSignedTx(tx: Transaction): Promise<TransactionSignature> {
|
|
1465
|
+
const { txSig } = await this.txSender.send(tx, undefined, this.opts, true);
|
|
1466
|
+
|
|
1467
|
+
return txSig;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
/**
|
|
1471
|
+
* 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.
|
|
1472
|
+
* @param orderParams
|
|
1473
|
+
* @param userAccountPublicKey
|
|
1474
|
+
* @param userAccount
|
|
1475
|
+
* @returns
|
|
1476
|
+
*/
|
|
1477
|
+
public async sendMarketOrderAndGetSignedFillTx(
|
|
1478
|
+
orderParams: OptionalOrderParams,
|
|
1479
|
+
userAccountPublicKey: PublicKey,
|
|
1480
|
+
userAccount: UserAccount
|
|
1481
|
+
): Promise<{ txSig: TransactionSignature; signedFillTx: Transaction }> {
|
|
1482
|
+
const marketIndex = orderParams.marketIndex;
|
|
1483
|
+
const orderId = userAccount.nextOrderId;
|
|
1484
|
+
|
|
1485
|
+
const marketOrderTx = wrapInTx(await this.getPlaceOrderIx(orderParams));
|
|
1486
|
+
const fillTx = wrapInTx(
|
|
1487
|
+
await this.getFillOrderIx(userAccountPublicKey, userAccount, {
|
|
1488
|
+
orderId,
|
|
803
1489
|
marketIndex,
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
)
|
|
1490
|
+
})
|
|
1491
|
+
);
|
|
1492
|
+
|
|
1493
|
+
// Apply the latest blockhash to the txs so that we can sign before sending them
|
|
1494
|
+
const currentBlockHash = (
|
|
1495
|
+
await this.connection.getLatestBlockhash('finalized')
|
|
1496
|
+
).blockhash;
|
|
1497
|
+
marketOrderTx.recentBlockhash = currentBlockHash;
|
|
1498
|
+
fillTx.recentBlockhash = currentBlockHash;
|
|
1499
|
+
|
|
1500
|
+
marketOrderTx.feePayer = userAccount.authority;
|
|
1501
|
+
fillTx.feePayer = userAccount.authority;
|
|
1502
|
+
|
|
1503
|
+
const [signedMarketOrderTx, signedFillTx] =
|
|
1504
|
+
await this.provider.wallet.signAllTransactions([marketOrderTx, fillTx]);
|
|
1505
|
+
|
|
1506
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1507
|
+
signedMarketOrderTx,
|
|
1508
|
+
[],
|
|
1509
|
+
this.opts,
|
|
1510
|
+
true
|
|
810
1511
|
);
|
|
1512
|
+
|
|
1513
|
+
this.marketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
1514
|
+
|
|
1515
|
+
return { txSig, signedFillTx };
|
|
811
1516
|
}
|
|
812
1517
|
|
|
813
1518
|
public async placeOrder(
|
|
814
|
-
orderParams:
|
|
1519
|
+
orderParams: OptionalOrderParams
|
|
815
1520
|
): Promise<TransactionSignature> {
|
|
816
1521
|
const { txSig, slot } = await this.txSender.send(
|
|
817
1522
|
wrapInTx(await this.getPlaceOrderIx(orderParams)),
|
|
818
1523
|
[],
|
|
819
1524
|
this.opts
|
|
820
1525
|
);
|
|
821
|
-
this.marketLastSlotCache.set(orderParams.marketIndex
|
|
1526
|
+
this.marketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
822
1527
|
return txSig;
|
|
823
1528
|
}
|
|
824
1529
|
|
|
1530
|
+
getOrderParams(
|
|
1531
|
+
optionalOrderParams: OptionalOrderParams,
|
|
1532
|
+
marketType: MarketType
|
|
1533
|
+
): OrderParams {
|
|
1534
|
+
return Object.assign({}, DefaultOrderParams, optionalOrderParams, {
|
|
1535
|
+
marketType,
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
|
|
825
1539
|
public async getPlaceOrderIx(
|
|
826
|
-
orderParams:
|
|
1540
|
+
orderParams: OptionalOrderParams
|
|
827
1541
|
): Promise<TransactionInstruction> {
|
|
1542
|
+
orderParams = this.getOrderParams(orderParams, MarketType.PERP);
|
|
828
1543
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
829
1544
|
|
|
830
1545
|
const remainingAccounts = this.getRemainingAccounts({
|
|
831
|
-
|
|
1546
|
+
userAccounts: [this.getUserAccount()],
|
|
1547
|
+
useMarketLastSlotCache: true,
|
|
1548
|
+
readablePerpMarketIndex: orderParams.marketIndex,
|
|
832
1549
|
});
|
|
833
1550
|
|
|
834
1551
|
return await this.program.instruction.placeOrder(orderParams, {
|
|
835
1552
|
accounts: {
|
|
836
1553
|
state: await this.getStatePublicKey(),
|
|
837
1554
|
user: userAccountPublicKey,
|
|
1555
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
838
1556
|
authority: this.wallet.publicKey,
|
|
839
1557
|
},
|
|
840
1558
|
remainingAccounts,
|
|
841
1559
|
});
|
|
842
1560
|
}
|
|
843
1561
|
|
|
844
|
-
public async updateAMMs(
|
|
1562
|
+
public async updateAMMs(
|
|
1563
|
+
marketIndexes: number[]
|
|
1564
|
+
): Promise<TransactionSignature> {
|
|
845
1565
|
const { txSig } = await this.txSender.send(
|
|
846
1566
|
wrapInTx(await this.getUpdateAMMsIx(marketIndexes)),
|
|
847
1567
|
[],
|
|
@@ -851,16 +1571,16 @@ export class ClearingHouse {
|
|
|
851
1571
|
}
|
|
852
1572
|
|
|
853
1573
|
public async getUpdateAMMsIx(
|
|
854
|
-
marketIndexes:
|
|
1574
|
+
marketIndexes: number[]
|
|
855
1575
|
): Promise<TransactionInstruction> {
|
|
856
1576
|
for (let i = marketIndexes.length; i < 5; i++) {
|
|
857
|
-
marketIndexes.push(
|
|
1577
|
+
marketIndexes.push(100);
|
|
858
1578
|
}
|
|
859
1579
|
const marketAccountInfos = [];
|
|
860
1580
|
const oracleAccountInfos = [];
|
|
861
1581
|
for (const marketIndex of marketIndexes) {
|
|
862
|
-
if (
|
|
863
|
-
const market = this.
|
|
1582
|
+
if (marketIndex !== 100) {
|
|
1583
|
+
const market = this.getPerpMarketAccount(marketIndex);
|
|
864
1584
|
marketAccountInfos.push({
|
|
865
1585
|
pubkey: market.pubkey,
|
|
866
1586
|
isWritable: true,
|
|
@@ -884,7 +1604,55 @@ export class ClearingHouse {
|
|
|
884
1604
|
});
|
|
885
1605
|
}
|
|
886
1606
|
|
|
887
|
-
public async
|
|
1607
|
+
public async settleExpiredMarket(
|
|
1608
|
+
marketIndex: number
|
|
1609
|
+
): Promise<TransactionSignature> {
|
|
1610
|
+
const { txSig } = await this.txSender.send(
|
|
1611
|
+
wrapInTx(await this.getSettleExpiredMarketIx(marketIndex)),
|
|
1612
|
+
[],
|
|
1613
|
+
this.opts
|
|
1614
|
+
);
|
|
1615
|
+
return txSig;
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
public async getSettleExpiredMarketIx(
|
|
1619
|
+
marketIndex: number
|
|
1620
|
+
): Promise<TransactionInstruction> {
|
|
1621
|
+
const marketAccountInfos = [];
|
|
1622
|
+
const oracleAccountInfos = [];
|
|
1623
|
+
const spotMarketAccountInfos = [];
|
|
1624
|
+
const market = this.getPerpMarketAccount(marketIndex);
|
|
1625
|
+
marketAccountInfos.push({
|
|
1626
|
+
pubkey: market.pubkey,
|
|
1627
|
+
isWritable: true,
|
|
1628
|
+
isSigner: false,
|
|
1629
|
+
});
|
|
1630
|
+
oracleAccountInfos.push({
|
|
1631
|
+
pubkey: market.amm.oracle,
|
|
1632
|
+
isWritable: false,
|
|
1633
|
+
isSigner: false,
|
|
1634
|
+
});
|
|
1635
|
+
|
|
1636
|
+
spotMarketAccountInfos.push({
|
|
1637
|
+
pubkey: this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX).pubkey,
|
|
1638
|
+
isSigner: false,
|
|
1639
|
+
isWritable: true,
|
|
1640
|
+
});
|
|
1641
|
+
|
|
1642
|
+
const remainingAccounts = oracleAccountInfos
|
|
1643
|
+
.concat(spotMarketAccountInfos)
|
|
1644
|
+
.concat(marketAccountInfos);
|
|
1645
|
+
|
|
1646
|
+
return await this.program.instruction.settleExpiredMarket(marketIndex, {
|
|
1647
|
+
accounts: {
|
|
1648
|
+
state: await this.getStatePublicKey(),
|
|
1649
|
+
authority: this.wallet.publicKey,
|
|
1650
|
+
},
|
|
1651
|
+
remainingAccounts,
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
public async cancelOrder(orderId?: number): Promise<TransactionSignature> {
|
|
888
1656
|
const { txSig } = await this.txSender.send(
|
|
889
1657
|
wrapInTx(await this.getCancelOrderIx(orderId)),
|
|
890
1658
|
[],
|
|
@@ -893,10 +1661,15 @@ export class ClearingHouse {
|
|
|
893
1661
|
return txSig;
|
|
894
1662
|
}
|
|
895
1663
|
|
|
896
|
-
public async getCancelOrderIx(
|
|
1664
|
+
public async getCancelOrderIx(
|
|
1665
|
+
orderId?: number
|
|
1666
|
+
): Promise<TransactionInstruction> {
|
|
897
1667
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
898
1668
|
|
|
899
|
-
const remainingAccounts = this.getRemainingAccounts({
|
|
1669
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1670
|
+
userAccounts: [this.getUserAccount()],
|
|
1671
|
+
useMarketLastSlotCache: true,
|
|
1672
|
+
});
|
|
900
1673
|
|
|
901
1674
|
return await this.program.instruction.cancelOrder(orderId ?? null, {
|
|
902
1675
|
accounts: {
|
|
@@ -925,9 +1698,12 @@ export class ClearingHouse {
|
|
|
925
1698
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
926
1699
|
|
|
927
1700
|
const order = this.getOrderByUserId(userOrderId);
|
|
928
|
-
const oracle = this.
|
|
1701
|
+
const oracle = this.getPerpMarketAccount(order.marketIndex).amm.oracle;
|
|
929
1702
|
|
|
930
|
-
const remainingAccounts = this.getRemainingAccounts({
|
|
1703
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1704
|
+
userAccounts: [this.getUserAccount()],
|
|
1705
|
+
useMarketLastSlotCache: true,
|
|
1706
|
+
});
|
|
931
1707
|
|
|
932
1708
|
return await this.program.instruction.cancelOrderByUserId(userOrderId, {
|
|
933
1709
|
accounts: {
|
|
@@ -943,12 +1719,19 @@ export class ClearingHouse {
|
|
|
943
1719
|
public async fillOrder(
|
|
944
1720
|
userAccountPublicKey: PublicKey,
|
|
945
1721
|
user: UserAccount,
|
|
946
|
-
order?: Order,
|
|
947
|
-
makerInfo?: MakerInfo
|
|
1722
|
+
order?: Pick<Order, 'marketIndex' | 'orderId'>,
|
|
1723
|
+
makerInfo?: MakerInfo,
|
|
1724
|
+
referrerInfo?: ReferrerInfo
|
|
948
1725
|
): Promise<TransactionSignature> {
|
|
949
1726
|
const { txSig } = await this.txSender.send(
|
|
950
1727
|
wrapInTx(
|
|
951
|
-
await this.getFillOrderIx(
|
|
1728
|
+
await this.getFillOrderIx(
|
|
1729
|
+
userAccountPublicKey,
|
|
1730
|
+
user,
|
|
1731
|
+
order,
|
|
1732
|
+
makerInfo,
|
|
1733
|
+
referrerInfo
|
|
1734
|
+
)
|
|
952
1735
|
),
|
|
953
1736
|
[],
|
|
954
1737
|
this.opts
|
|
@@ -959,60 +1742,54 @@ export class ClearingHouse {
|
|
|
959
1742
|
public async getFillOrderIx(
|
|
960
1743
|
userAccountPublicKey: PublicKey,
|
|
961
1744
|
userAccount: UserAccount,
|
|
962
|
-
order: Order,
|
|
963
|
-
makerInfo?: MakerInfo
|
|
1745
|
+
order: Pick<Order, 'marketIndex' | 'orderId'>,
|
|
1746
|
+
makerInfo?: MakerInfo,
|
|
1747
|
+
referrerInfo?: ReferrerInfo
|
|
964
1748
|
): Promise<TransactionInstruction> {
|
|
1749
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
1750
|
+
this.program.programId,
|
|
1751
|
+
userAccount.authority
|
|
1752
|
+
);
|
|
1753
|
+
|
|
965
1754
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1755
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
966
1756
|
|
|
967
|
-
const marketIndex = order
|
|
968
|
-
|
|
1757
|
+
const marketIndex = order
|
|
1758
|
+
? order.marketIndex
|
|
1759
|
+
: userAccount.orders.find(
|
|
1760
|
+
(order) => order.orderId === userAccount.nextOrderId - 1
|
|
1761
|
+
).marketIndex;
|
|
969
1762
|
|
|
970
|
-
const
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1763
|
+
const userAccounts = [userAccount];
|
|
1764
|
+
if (makerInfo !== undefined) {
|
|
1765
|
+
userAccounts.push(makerInfo.makerUserAccount);
|
|
1766
|
+
}
|
|
1767
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1768
|
+
userAccounts,
|
|
1769
|
+
writablePerpMarketIndexes: [marketIndex],
|
|
1770
|
+
});
|
|
1771
|
+
|
|
1772
|
+
if (makerInfo) {
|
|
1773
|
+
remainingAccounts.push({
|
|
1774
|
+
pubkey: makerInfo.maker,
|
|
980
1775
|
isWritable: true,
|
|
981
1776
|
isSigner: false,
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
pubkey: marketAccount.amm.oracle,
|
|
987
|
-
isWritable: false,
|
|
1777
|
+
});
|
|
1778
|
+
remainingAccounts.push({
|
|
1779
|
+
pubkey: makerInfo.makerStats,
|
|
1780
|
+
isWritable: true,
|
|
988
1781
|
isSigner: false,
|
|
989
|
-
}
|
|
990
|
-
];
|
|
991
|
-
for (const position of userAccount.positions) {
|
|
992
|
-
if (
|
|
993
|
-
!positionIsAvailable(position) &&
|
|
994
|
-
!position.marketIndex.eq(order.marketIndex)
|
|
995
|
-
) {
|
|
996
|
-
const market = this.getMarketAccount(position.marketIndex);
|
|
997
|
-
marketAccountInfos.push({
|
|
998
|
-
pubkey: market.pubkey,
|
|
999
|
-
isWritable: false,
|
|
1000
|
-
isSigner: false,
|
|
1001
|
-
});
|
|
1002
|
-
oracleAccountInfos.push({
|
|
1003
|
-
pubkey: market.amm.oracle,
|
|
1004
|
-
isWritable: false,
|
|
1005
|
-
isSigner: false,
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1782
|
+
});
|
|
1008
1783
|
}
|
|
1009
|
-
const remainingAccounts = oracleAccountInfos.concat(
|
|
1010
|
-
bankAccountInfos.concat(marketAccountInfos)
|
|
1011
|
-
);
|
|
1012
1784
|
|
|
1013
|
-
if (
|
|
1785
|
+
if (referrerInfo) {
|
|
1014
1786
|
remainingAccounts.push({
|
|
1015
|
-
pubkey:
|
|
1787
|
+
pubkey: referrerInfo.referrer,
|
|
1788
|
+
isWritable: true,
|
|
1789
|
+
isSigner: false,
|
|
1790
|
+
});
|
|
1791
|
+
remainingAccounts.push({
|
|
1792
|
+
pubkey: referrerInfo.referrerStats,
|
|
1016
1793
|
isWritable: true,
|
|
1017
1794
|
isSigner: false,
|
|
1018
1795
|
});
|
|
@@ -1020,81 +1797,279 @@ export class ClearingHouse {
|
|
|
1020
1797
|
|
|
1021
1798
|
const orderId = order.orderId;
|
|
1022
1799
|
const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
|
|
1800
|
+
|
|
1023
1801
|
return await this.program.instruction.fillOrder(orderId, makerOrderId, {
|
|
1024
1802
|
accounts: {
|
|
1025
1803
|
state: await this.getStatePublicKey(),
|
|
1026
1804
|
filler: fillerPublicKey,
|
|
1805
|
+
fillerStats: fillerStatsPublicKey,
|
|
1027
1806
|
user: userAccountPublicKey,
|
|
1807
|
+
userStats: userStatsPublicKey,
|
|
1028
1808
|
authority: this.wallet.publicKey,
|
|
1029
1809
|
},
|
|
1030
1810
|
remainingAccounts,
|
|
1031
1811
|
});
|
|
1032
1812
|
}
|
|
1033
1813
|
|
|
1034
|
-
public async
|
|
1035
|
-
|
|
1036
|
-
user: UserAccount,
|
|
1037
|
-
order: Order
|
|
1814
|
+
public async placeSpotOrder(
|
|
1815
|
+
orderParams: OptionalOrderParams
|
|
1038
1816
|
): Promise<TransactionSignature> {
|
|
1039
1817
|
const { txSig } = await this.txSender.send(
|
|
1040
|
-
wrapInTx(await this.
|
|
1818
|
+
wrapInTx(await this.getPlaceSpotOrderIx(orderParams)),
|
|
1041
1819
|
[],
|
|
1042
1820
|
this.opts
|
|
1043
1821
|
);
|
|
1044
1822
|
return txSig;
|
|
1045
1823
|
}
|
|
1046
1824
|
|
|
1047
|
-
public async
|
|
1048
|
-
|
|
1049
|
-
userAccount: UserAccount,
|
|
1050
|
-
order: Order
|
|
1825
|
+
public async getPlaceSpotOrderIx(
|
|
1826
|
+
orderParams: OptionalOrderParams
|
|
1051
1827
|
): Promise<TransactionInstruction> {
|
|
1052
|
-
|
|
1828
|
+
orderParams = this.getOrderParams(orderParams, MarketType.SPOT);
|
|
1829
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1053
1830
|
|
|
1054
|
-
const
|
|
1055
|
-
|
|
1831
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1832
|
+
userAccounts: [this.getUserAccount()],
|
|
1833
|
+
useMarketLastSlotCache: true,
|
|
1834
|
+
readableSpotMarketIndex: orderParams.marketIndex,
|
|
1835
|
+
});
|
|
1056
1836
|
|
|
1057
|
-
|
|
1058
|
-
{
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
];
|
|
1064
|
-
const marketAccountInfos = [
|
|
1065
|
-
{
|
|
1066
|
-
pubkey: marketAccount.pubkey,
|
|
1067
|
-
isWritable: true,
|
|
1068
|
-
isSigner: false,
|
|
1837
|
+
return await this.program.instruction.placeSpotOrder(orderParams, {
|
|
1838
|
+
accounts: {
|
|
1839
|
+
state: await this.getStatePublicKey(),
|
|
1840
|
+
user: userAccountPublicKey,
|
|
1841
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
1842
|
+
authority: this.wallet.publicKey,
|
|
1069
1843
|
},
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1844
|
+
remainingAccounts,
|
|
1845
|
+
});
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
public async fillSpotOrder(
|
|
1849
|
+
userAccountPublicKey: PublicKey,
|
|
1850
|
+
user: UserAccount,
|
|
1851
|
+
order?: Order,
|
|
1852
|
+
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
|
|
1853
|
+
makerInfo?: MakerInfo,
|
|
1854
|
+
referrerInfo?: ReferrerInfo
|
|
1855
|
+
): Promise<TransactionSignature> {
|
|
1856
|
+
const { txSig } = await this.txSender.send(
|
|
1857
|
+
wrapInTx(
|
|
1858
|
+
await this.getFillSpotOrderIx(
|
|
1859
|
+
userAccountPublicKey,
|
|
1860
|
+
user,
|
|
1861
|
+
order,
|
|
1862
|
+
fulfillmentConfig,
|
|
1863
|
+
makerInfo,
|
|
1864
|
+
referrerInfo
|
|
1865
|
+
)
|
|
1866
|
+
),
|
|
1867
|
+
[],
|
|
1868
|
+
this.opts
|
|
1869
|
+
);
|
|
1870
|
+
return txSig;
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
public async getFillSpotOrderIx(
|
|
1874
|
+
userAccountPublicKey: PublicKey,
|
|
1875
|
+
userAccount: UserAccount,
|
|
1876
|
+
order?: Order,
|
|
1877
|
+
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
|
|
1878
|
+
makerInfo?: MakerInfo,
|
|
1879
|
+
referrerInfo?: ReferrerInfo
|
|
1880
|
+
): Promise<TransactionInstruction> {
|
|
1881
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
1882
|
+
this.program.programId,
|
|
1883
|
+
userAccount.authority
|
|
1884
|
+
);
|
|
1885
|
+
|
|
1886
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1887
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1888
|
+
|
|
1889
|
+
const marketIndex = order
|
|
1890
|
+
? order.marketIndex
|
|
1891
|
+
: userAccount.orders.find(
|
|
1892
|
+
(order) => order.orderId === userAccount.nextOrderId - 1
|
|
1893
|
+
).marketIndex;
|
|
1894
|
+
|
|
1895
|
+
const userAccounts = [userAccount];
|
|
1896
|
+
if (makerInfo !== undefined) {
|
|
1897
|
+
userAccounts.push(makerInfo.makerUserAccount);
|
|
1898
|
+
}
|
|
1899
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1900
|
+
userAccounts,
|
|
1901
|
+
writableSpotMarketIndexes: [marketIndex, QUOTE_SPOT_MARKET_INDEX],
|
|
1902
|
+
});
|
|
1903
|
+
|
|
1904
|
+
if (makerInfo) {
|
|
1905
|
+
remainingAccounts.push({
|
|
1906
|
+
pubkey: makerInfo.maker,
|
|
1907
|
+
isWritable: true,
|
|
1908
|
+
isSigner: false,
|
|
1909
|
+
});
|
|
1910
|
+
remainingAccounts.push({
|
|
1911
|
+
pubkey: makerInfo.makerStats,
|
|
1912
|
+
isWritable: true,
|
|
1913
|
+
isSigner: false,
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
if (referrerInfo) {
|
|
1918
|
+
remainingAccounts.push({
|
|
1919
|
+
pubkey: referrerInfo.referrer,
|
|
1920
|
+
isWritable: true,
|
|
1921
|
+
isSigner: false,
|
|
1922
|
+
});
|
|
1923
|
+
remainingAccounts.push({
|
|
1924
|
+
pubkey: referrerInfo.referrerStats,
|
|
1925
|
+
isWritable: true,
|
|
1926
|
+
isSigner: false,
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
const orderId = order.orderId;
|
|
1931
|
+
const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
|
|
1932
|
+
|
|
1933
|
+
if (fulfillmentConfig) {
|
|
1934
|
+
remainingAccounts.push({
|
|
1935
|
+
pubkey: fulfillmentConfig.pubkey,
|
|
1074
1936
|
isWritable: false,
|
|
1075
1937
|
isSigner: false,
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1938
|
+
});
|
|
1939
|
+
remainingAccounts.push({
|
|
1940
|
+
pubkey: fulfillmentConfig.serumProgramId,
|
|
1941
|
+
isWritable: false,
|
|
1942
|
+
isSigner: false,
|
|
1943
|
+
});
|
|
1944
|
+
remainingAccounts.push({
|
|
1945
|
+
pubkey: fulfillmentConfig.serumMarket,
|
|
1946
|
+
isWritable: true,
|
|
1947
|
+
isSigner: false,
|
|
1948
|
+
});
|
|
1949
|
+
remainingAccounts.push({
|
|
1950
|
+
pubkey: fulfillmentConfig.serumRequestQueue,
|
|
1951
|
+
isWritable: true,
|
|
1952
|
+
isSigner: false,
|
|
1953
|
+
});
|
|
1954
|
+
remainingAccounts.push({
|
|
1955
|
+
pubkey: fulfillmentConfig.serumEventQueue,
|
|
1956
|
+
isWritable: true,
|
|
1957
|
+
isSigner: false,
|
|
1958
|
+
});
|
|
1959
|
+
remainingAccounts.push({
|
|
1960
|
+
pubkey: fulfillmentConfig.serumBids,
|
|
1961
|
+
isWritable: true,
|
|
1962
|
+
isSigner: false,
|
|
1963
|
+
});
|
|
1964
|
+
remainingAccounts.push({
|
|
1965
|
+
pubkey: fulfillmentConfig.serumAsks,
|
|
1966
|
+
isWritable: true,
|
|
1967
|
+
isSigner: false,
|
|
1968
|
+
});
|
|
1969
|
+
remainingAccounts.push({
|
|
1970
|
+
pubkey: fulfillmentConfig.serumBaseVault,
|
|
1971
|
+
isWritable: true,
|
|
1972
|
+
isSigner: false,
|
|
1973
|
+
});
|
|
1974
|
+
remainingAccounts.push({
|
|
1975
|
+
pubkey: fulfillmentConfig.serumQuoteVault,
|
|
1976
|
+
isWritable: true,
|
|
1977
|
+
isSigner: false,
|
|
1978
|
+
});
|
|
1979
|
+
remainingAccounts.push({
|
|
1980
|
+
pubkey: fulfillmentConfig.serumOpenOrders,
|
|
1981
|
+
isWritable: true,
|
|
1982
|
+
isSigner: false,
|
|
1983
|
+
});
|
|
1984
|
+
remainingAccounts.push({
|
|
1985
|
+
pubkey: getSerumSignerPublicKey(
|
|
1986
|
+
fulfillmentConfig.serumProgramId,
|
|
1987
|
+
fulfillmentConfig.serumMarket,
|
|
1988
|
+
fulfillmentConfig.serumSignerNonce
|
|
1989
|
+
),
|
|
1990
|
+
isWritable: false,
|
|
1991
|
+
isSigner: false,
|
|
1992
|
+
});
|
|
1993
|
+
remainingAccounts.push({
|
|
1994
|
+
pubkey: this.getSignerPublicKey(),
|
|
1995
|
+
isWritable: false,
|
|
1996
|
+
isSigner: false,
|
|
1997
|
+
});
|
|
1998
|
+
remainingAccounts.push({
|
|
1999
|
+
pubkey: TOKEN_PROGRAM_ID,
|
|
2000
|
+
isWritable: false,
|
|
2001
|
+
isSigner: false,
|
|
2002
|
+
});
|
|
2003
|
+
remainingAccounts.push({
|
|
2004
|
+
pubkey: this.getSpotMarketAccount(marketIndex).vault,
|
|
2005
|
+
isWritable: true,
|
|
2006
|
+
isSigner: false,
|
|
2007
|
+
});
|
|
2008
|
+
remainingAccounts.push({
|
|
2009
|
+
pubkey: this.getQuoteSpotMarketAccount().vault,
|
|
2010
|
+
isWritable: true,
|
|
2011
|
+
isSigner: false,
|
|
2012
|
+
});
|
|
2013
|
+
remainingAccounts.push({
|
|
2014
|
+
pubkey: this.getStateAccount().srmVault,
|
|
2015
|
+
isWritable: false,
|
|
2016
|
+
isSigner: false,
|
|
2017
|
+
});
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
return await this.program.instruction.fillSpotOrder(
|
|
2021
|
+
orderId,
|
|
2022
|
+
fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null,
|
|
2023
|
+
makerOrderId,
|
|
2024
|
+
{
|
|
2025
|
+
accounts: {
|
|
2026
|
+
state: await this.getStatePublicKey(),
|
|
2027
|
+
filler: fillerPublicKey,
|
|
2028
|
+
fillerStats: fillerStatsPublicKey,
|
|
2029
|
+
user: userAccountPublicKey,
|
|
2030
|
+
userStats: userStatsPublicKey,
|
|
2031
|
+
authority: this.wallet.publicKey,
|
|
2032
|
+
},
|
|
2033
|
+
remainingAccounts,
|
|
1094
2034
|
}
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
2037
|
+
|
|
2038
|
+
public async triggerOrder(
|
|
2039
|
+
userAccountPublicKey: PublicKey,
|
|
2040
|
+
user: UserAccount,
|
|
2041
|
+
order: Order
|
|
2042
|
+
): Promise<TransactionSignature> {
|
|
2043
|
+
const { txSig } = await this.txSender.send(
|
|
2044
|
+
wrapInTx(await this.getTriggerOrderIx(userAccountPublicKey, user, order)),
|
|
2045
|
+
[],
|
|
2046
|
+
this.opts
|
|
2047
|
+
);
|
|
2048
|
+
return txSig;
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
public async getTriggerOrderIx(
|
|
2052
|
+
userAccountPublicKey: PublicKey,
|
|
2053
|
+
userAccount: UserAccount,
|
|
2054
|
+
order: Order
|
|
2055
|
+
): Promise<TransactionInstruction> {
|
|
2056
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
2057
|
+
|
|
2058
|
+
let remainingAccountsParams;
|
|
2059
|
+
if (isVariant(order.marketType, 'perp')) {
|
|
2060
|
+
remainingAccountsParams = {
|
|
2061
|
+
userAccounts: [userAccount],
|
|
2062
|
+
writablePerpMarketIndexes: [order.marketIndex],
|
|
2063
|
+
};
|
|
2064
|
+
} else {
|
|
2065
|
+
remainingAccountsParams = {
|
|
2066
|
+
userAccounts: [userAccount],
|
|
2067
|
+
writableSpotMarketIndexes: [order.marketIndex, QUOTE_SPOT_MARKET_INDEX],
|
|
2068
|
+
};
|
|
1095
2069
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
2070
|
+
|
|
2071
|
+
const remainingAccounts = this.getRemainingAccounts(
|
|
2072
|
+
remainingAccountsParams
|
|
1098
2073
|
);
|
|
1099
2074
|
|
|
1100
2075
|
const orderId = order.orderId;
|
|
@@ -1110,27 +2085,38 @@ export class ClearingHouse {
|
|
|
1110
2085
|
}
|
|
1111
2086
|
|
|
1112
2087
|
public async placeAndTake(
|
|
1113
|
-
orderParams:
|
|
1114
|
-
makerInfo?: MakerInfo
|
|
2088
|
+
orderParams: OptionalOrderParams,
|
|
2089
|
+
makerInfo?: MakerInfo,
|
|
2090
|
+
referrerInfo?: ReferrerInfo
|
|
1115
2091
|
): Promise<TransactionSignature> {
|
|
1116
2092
|
const { txSig, slot } = await this.txSender.send(
|
|
1117
|
-
wrapInTx(
|
|
2093
|
+
wrapInTx(
|
|
2094
|
+
await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)
|
|
2095
|
+
),
|
|
1118
2096
|
[],
|
|
1119
2097
|
this.opts
|
|
1120
2098
|
);
|
|
1121
|
-
this.marketLastSlotCache.set(orderParams.marketIndex
|
|
2099
|
+
this.marketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
1122
2100
|
return txSig;
|
|
1123
2101
|
}
|
|
1124
2102
|
|
|
1125
2103
|
public async getPlaceAndTakeIx(
|
|
1126
|
-
orderParams:
|
|
1127
|
-
makerInfo?: MakerInfo
|
|
2104
|
+
orderParams: OptionalOrderParams,
|
|
2105
|
+
makerInfo?: MakerInfo,
|
|
2106
|
+
referrerInfo?: ReferrerInfo
|
|
1128
2107
|
): Promise<TransactionInstruction> {
|
|
2108
|
+
orderParams = this.getOrderParams(orderParams, MarketType.PERP);
|
|
2109
|
+
const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
1129
2110
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1130
2111
|
|
|
2112
|
+
const userAccounts = [this.getUserAccount()];
|
|
2113
|
+
if (makerInfo !== undefined) {
|
|
2114
|
+
userAccounts.push(makerInfo.makerUserAccount);
|
|
2115
|
+
}
|
|
1131
2116
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1132
|
-
|
|
1133
|
-
|
|
2117
|
+
userAccounts,
|
|
2118
|
+
useMarketLastSlotCache: true,
|
|
2119
|
+
writablePerpMarketIndexes: [orderParams.marketIndex],
|
|
1134
2120
|
});
|
|
1135
2121
|
|
|
1136
2122
|
let makerOrderId = null;
|
|
@@ -1141,6 +2127,24 @@ export class ClearingHouse {
|
|
|
1141
2127
|
isSigner: false,
|
|
1142
2128
|
isWritable: true,
|
|
1143
2129
|
});
|
|
2130
|
+
remainingAccounts.push({
|
|
2131
|
+
pubkey: makerInfo.makerStats,
|
|
2132
|
+
isSigner: false,
|
|
2133
|
+
isWritable: true,
|
|
2134
|
+
});
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
if (referrerInfo) {
|
|
2138
|
+
remainingAccounts.push({
|
|
2139
|
+
pubkey: referrerInfo.referrer,
|
|
2140
|
+
isWritable: true,
|
|
2141
|
+
isSigner: false,
|
|
2142
|
+
});
|
|
2143
|
+
remainingAccounts.push({
|
|
2144
|
+
pubkey: referrerInfo.referrerStats,
|
|
2145
|
+
isWritable: true,
|
|
2146
|
+
isSigner: false,
|
|
2147
|
+
});
|
|
1144
2148
|
}
|
|
1145
2149
|
|
|
1146
2150
|
return await this.program.instruction.placeAndTake(
|
|
@@ -1150,6 +2154,71 @@ export class ClearingHouse {
|
|
|
1150
2154
|
accounts: {
|
|
1151
2155
|
state: await this.getStatePublicKey(),
|
|
1152
2156
|
user: userAccountPublicKey,
|
|
2157
|
+
userStats: userStatsPublicKey,
|
|
2158
|
+
authority: this.wallet.publicKey,
|
|
2159
|
+
},
|
|
2160
|
+
remainingAccounts,
|
|
2161
|
+
}
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
public async placeAndMake(
|
|
2166
|
+
orderParams: OptionalOrderParams,
|
|
2167
|
+
takerInfo: TakerInfo,
|
|
2168
|
+
referrerInfo?: ReferrerInfo
|
|
2169
|
+
): Promise<TransactionSignature> {
|
|
2170
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2171
|
+
wrapInTx(
|
|
2172
|
+
await this.getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo)
|
|
2173
|
+
),
|
|
2174
|
+
[],
|
|
2175
|
+
this.opts
|
|
2176
|
+
);
|
|
2177
|
+
|
|
2178
|
+
this.marketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2179
|
+
|
|
2180
|
+
return txSig;
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
public async getPlaceAndMakeIx(
|
|
2184
|
+
orderParams: OptionalOrderParams,
|
|
2185
|
+
takerInfo: TakerInfo,
|
|
2186
|
+
referrerInfo?: ReferrerInfo
|
|
2187
|
+
): Promise<TransactionInstruction> {
|
|
2188
|
+
orderParams = this.getOrderParams(orderParams, MarketType.PERP);
|
|
2189
|
+
const userStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
2190
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
2191
|
+
|
|
2192
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2193
|
+
userAccounts: [this.getUserAccount(), takerInfo.takerUserAccount],
|
|
2194
|
+
useMarketLastSlotCache: true,
|
|
2195
|
+
writablePerpMarketIndexes: [orderParams.marketIndex],
|
|
2196
|
+
});
|
|
2197
|
+
|
|
2198
|
+
if (referrerInfo) {
|
|
2199
|
+
remainingAccounts.push({
|
|
2200
|
+
pubkey: referrerInfo.referrer,
|
|
2201
|
+
isWritable: true,
|
|
2202
|
+
isSigner: false,
|
|
2203
|
+
});
|
|
2204
|
+
remainingAccounts.push({
|
|
2205
|
+
pubkey: referrerInfo.referrerStats,
|
|
2206
|
+
isWritable: true,
|
|
2207
|
+
isSigner: false,
|
|
2208
|
+
});
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
const takerOrderId = takerInfo.order.orderId;
|
|
2212
|
+
return await this.program.instruction.placeAndMake(
|
|
2213
|
+
orderParams,
|
|
2214
|
+
takerOrderId,
|
|
2215
|
+
{
|
|
2216
|
+
accounts: {
|
|
2217
|
+
state: await this.getStatePublicKey(),
|
|
2218
|
+
user: userAccountPublicKey,
|
|
2219
|
+
userStats: userStatsPublicKey,
|
|
2220
|
+
taker: takerInfo.taker,
|
|
2221
|
+
takerStats: takerInfo.takerStats,
|
|
1153
2222
|
authority: this.wallet.publicKey,
|
|
1154
2223
|
},
|
|
1155
2224
|
remainingAccounts,
|
|
@@ -1162,22 +2231,23 @@ export class ClearingHouse {
|
|
|
1162
2231
|
* @param marketIndex
|
|
1163
2232
|
* @returns
|
|
1164
2233
|
*/
|
|
1165
|
-
public async closePosition(
|
|
2234
|
+
public async closePosition(
|
|
2235
|
+
marketIndex: number,
|
|
2236
|
+
limitPrice?: BN
|
|
2237
|
+
): Promise<TransactionSignature> {
|
|
1166
2238
|
const userPosition = this.getUser().getUserPosition(marketIndex);
|
|
1167
2239
|
if (!userPosition) {
|
|
1168
2240
|
throw Error(`No position in market ${marketIndex.toString()}`);
|
|
1169
2241
|
}
|
|
1170
2242
|
|
|
1171
|
-
return await this.placeAndTake(
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
)
|
|
1180
|
-
);
|
|
2243
|
+
return await this.placeAndTake({
|
|
2244
|
+
orderType: OrderType.MARKET,
|
|
2245
|
+
marketIndex,
|
|
2246
|
+
direction: findDirectionToClose(userPosition),
|
|
2247
|
+
baseAssetAmount: userPosition.baseAssetAmount.abs(),
|
|
2248
|
+
reduceOnly: true,
|
|
2249
|
+
price: limitPrice,
|
|
2250
|
+
});
|
|
1181
2251
|
}
|
|
1182
2252
|
|
|
1183
2253
|
public async settlePNLs(
|
|
@@ -1185,7 +2255,7 @@ export class ClearingHouse {
|
|
|
1185
2255
|
settleeUserAccountPublicKey: PublicKey;
|
|
1186
2256
|
settleeUserAccount: UserAccount;
|
|
1187
2257
|
}[],
|
|
1188
|
-
marketIndex:
|
|
2258
|
+
marketIndex: number
|
|
1189
2259
|
): Promise<TransactionSignature> {
|
|
1190
2260
|
const ixs = [];
|
|
1191
2261
|
for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
|
|
@@ -1198,7 +2268,14 @@ export class ClearingHouse {
|
|
|
1198
2268
|
);
|
|
1199
2269
|
}
|
|
1200
2270
|
|
|
1201
|
-
const tx = new Transaction()
|
|
2271
|
+
const tx = new Transaction()
|
|
2272
|
+
.add(
|
|
2273
|
+
ComputeBudgetProgram.requestUnits({
|
|
2274
|
+
units: 1_000_000,
|
|
2275
|
+
additionalFee: 0,
|
|
2276
|
+
})
|
|
2277
|
+
)
|
|
2278
|
+
.add(...ixs);
|
|
1202
2279
|
|
|
1203
2280
|
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
1204
2281
|
return txSig;
|
|
@@ -1207,7 +2284,7 @@ export class ClearingHouse {
|
|
|
1207
2284
|
public async settlePNL(
|
|
1208
2285
|
settleeUserAccountPublicKey: PublicKey,
|
|
1209
2286
|
settleeUserAccount: UserAccount,
|
|
1210
|
-
marketIndex:
|
|
2287
|
+
marketIndex: number
|
|
1211
2288
|
): Promise<TransactionSignature> {
|
|
1212
2289
|
const { txSig } = await this.txSender.send(
|
|
1213
2290
|
wrapInTx(
|
|
@@ -1226,70 +2303,55 @@ export class ClearingHouse {
|
|
|
1226
2303
|
public async settlePNLIx(
|
|
1227
2304
|
settleeUserAccountPublicKey: PublicKey,
|
|
1228
2305
|
settleeUserAccount: UserAccount,
|
|
1229
|
-
marketIndex:
|
|
2306
|
+
marketIndex: number
|
|
1230
2307
|
): Promise<TransactionInstruction> {
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
const market = this.getMarketAccount(position.marketIndex);
|
|
1237
|
-
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1238
|
-
pubkey: market.pubkey,
|
|
1239
|
-
isWritable: true, // TODO
|
|
1240
|
-
isSigner: false,
|
|
1241
|
-
});
|
|
1242
|
-
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1243
|
-
pubkey: market.amm.oracle,
|
|
1244
|
-
isWritable: false,
|
|
1245
|
-
isSigner: false,
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
for (const userBankBalance of settleeUserAccount.bankBalances) {
|
|
1251
|
-
if (!userBankBalance.balance.eq(QUOTE_ASSET_BANK_INDEX)) {
|
|
1252
|
-
const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
|
|
1253
|
-
bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
|
|
1254
|
-
pubkey: bankAccount.pubkey,
|
|
1255
|
-
isSigner: false,
|
|
1256
|
-
isWritable: false,
|
|
1257
|
-
});
|
|
1258
|
-
if (!bankAccount.bankIndex.eq(ZERO)) {
|
|
1259
|
-
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1260
|
-
pubkey: bankAccount.oracle,
|
|
1261
|
-
isSigner: false,
|
|
1262
|
-
isWritable: false,
|
|
1263
|
-
});
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
2308
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2309
|
+
userAccounts: [settleeUserAccount],
|
|
2310
|
+
writablePerpMarketIndexes: [marketIndex],
|
|
2311
|
+
writableSpotMarketIndexes: [QUOTE_SPOT_MARKET_INDEX],
|
|
2312
|
+
});
|
|
1267
2313
|
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
pubkey: marketAccount.amm.oracle,
|
|
1276
|
-
isSigner: false,
|
|
1277
|
-
isWritable: false,
|
|
2314
|
+
return await this.program.instruction.settlePnl(marketIndex, {
|
|
2315
|
+
accounts: {
|
|
2316
|
+
state: await this.getStatePublicKey(),
|
|
2317
|
+
authority: this.wallet.publicKey,
|
|
2318
|
+
user: settleeUserAccountPublicKey,
|
|
2319
|
+
},
|
|
2320
|
+
remainingAccounts: remainingAccounts,
|
|
1278
2321
|
});
|
|
2322
|
+
}
|
|
1279
2323
|
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
2324
|
+
public async settleExpiredPosition(
|
|
2325
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
2326
|
+
settleeUserAccount: UserAccount,
|
|
2327
|
+
marketIndex: number
|
|
2328
|
+
): Promise<TransactionSignature> {
|
|
2329
|
+
const { txSig } = await this.txSender.send(
|
|
2330
|
+
wrapInTx(
|
|
2331
|
+
await this.getSettleExpiredPositionIx(
|
|
2332
|
+
settleeUserAccountPublicKey,
|
|
2333
|
+
settleeUserAccount,
|
|
2334
|
+
marketIndex
|
|
2335
|
+
)
|
|
2336
|
+
),
|
|
2337
|
+
[],
|
|
2338
|
+
this.opts
|
|
2339
|
+
);
|
|
2340
|
+
return txSig;
|
|
2341
|
+
}
|
|
1285
2342
|
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
2343
|
+
public async getSettleExpiredPositionIx(
|
|
2344
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
2345
|
+
settleeUserAccount: UserAccount,
|
|
2346
|
+
marketIndex: number
|
|
2347
|
+
): Promise<TransactionInstruction> {
|
|
2348
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2349
|
+
userAccounts: [settleeUserAccount],
|
|
2350
|
+
writablePerpMarketIndexes: [marketIndex],
|
|
2351
|
+
writableSpotMarketIndexes: [QUOTE_SPOT_MARKET_INDEX],
|
|
2352
|
+
});
|
|
1291
2353
|
|
|
1292
|
-
return await this.program.instruction.
|
|
2354
|
+
return await this.program.instruction.settleExpiredPosition(marketIndex, {
|
|
1293
2355
|
accounts: {
|
|
1294
2356
|
state: await this.getStatePublicKey(),
|
|
1295
2357
|
authority: this.wallet.publicKey,
|
|
@@ -1299,68 +2361,364 @@ export class ClearingHouse {
|
|
|
1299
2361
|
});
|
|
1300
2362
|
}
|
|
1301
2363
|
|
|
1302
|
-
public async
|
|
1303
|
-
|
|
2364
|
+
public async liquidatePerp(
|
|
2365
|
+
userAccountPublicKey: PublicKey,
|
|
2366
|
+
userAccount: UserAccount,
|
|
2367
|
+
marketIndex: number,
|
|
2368
|
+
maxBaseAssetAmount: BN
|
|
2369
|
+
): Promise<TransactionSignature> {
|
|
2370
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2371
|
+
wrapInTx(
|
|
2372
|
+
await this.getLiquidatePerpIx(
|
|
2373
|
+
userAccountPublicKey,
|
|
2374
|
+
userAccount,
|
|
2375
|
+
marketIndex,
|
|
2376
|
+
maxBaseAssetAmount
|
|
2377
|
+
)
|
|
2378
|
+
),
|
|
2379
|
+
[],
|
|
2380
|
+
this.opts
|
|
2381
|
+
);
|
|
2382
|
+
this.marketLastSlotCache.set(marketIndex, slot);
|
|
2383
|
+
return txSig;
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
public async getLiquidatePerpIx(
|
|
2387
|
+
userAccountPublicKey: PublicKey,
|
|
2388
|
+
userAccount: UserAccount,
|
|
2389
|
+
marketIndex: number,
|
|
2390
|
+
maxBaseAssetAmount: BN
|
|
2391
|
+
): Promise<TransactionInstruction> {
|
|
2392
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
2393
|
+
this.program.programId,
|
|
2394
|
+
userAccount.authority
|
|
2395
|
+
);
|
|
2396
|
+
|
|
2397
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2398
|
+
const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
2399
|
+
|
|
2400
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2401
|
+
userAccounts: [this.getUserAccount(), userAccount],
|
|
2402
|
+
useMarketLastSlotCache: true,
|
|
2403
|
+
writablePerpMarketIndexes: [marketIndex],
|
|
2404
|
+
});
|
|
2405
|
+
|
|
2406
|
+
return await this.program.instruction.liquidatePerp(
|
|
2407
|
+
marketIndex,
|
|
2408
|
+
maxBaseAssetAmount,
|
|
2409
|
+
{
|
|
2410
|
+
accounts: {
|
|
2411
|
+
state: await this.getStatePublicKey(),
|
|
2412
|
+
authority: this.wallet.publicKey,
|
|
2413
|
+
user: userAccountPublicKey,
|
|
2414
|
+
userStats: userStatsPublicKey,
|
|
2415
|
+
liquidator: liquidatorPublicKey,
|
|
2416
|
+
liquidatorStats: liquidatorStatsPublicKey,
|
|
2417
|
+
},
|
|
2418
|
+
remainingAccounts: remainingAccounts,
|
|
2419
|
+
}
|
|
2420
|
+
);
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
public async liquidateSpot(
|
|
2424
|
+
userAccountPublicKey: PublicKey,
|
|
2425
|
+
userAccount: UserAccount,
|
|
2426
|
+
assetMarketIndex: number,
|
|
2427
|
+
liabilityMarketIndex: number,
|
|
2428
|
+
maxLiabilityTransfer: BN
|
|
1304
2429
|
): Promise<TransactionSignature> {
|
|
1305
2430
|
const { txSig } = await this.txSender.send(
|
|
1306
|
-
wrapInTx(
|
|
2431
|
+
wrapInTx(
|
|
2432
|
+
await this.getLiquidateSpotIx(
|
|
2433
|
+
userAccountPublicKey,
|
|
2434
|
+
userAccount,
|
|
2435
|
+
assetMarketIndex,
|
|
2436
|
+
liabilityMarketIndex,
|
|
2437
|
+
maxLiabilityTransfer
|
|
2438
|
+
)
|
|
2439
|
+
),
|
|
1307
2440
|
[],
|
|
1308
2441
|
this.opts
|
|
1309
2442
|
);
|
|
1310
2443
|
return txSig;
|
|
1311
2444
|
}
|
|
1312
2445
|
|
|
1313
|
-
public async
|
|
1314
|
-
|
|
2446
|
+
public async getLiquidateSpotIx(
|
|
2447
|
+
userAccountPublicKey: PublicKey,
|
|
2448
|
+
userAccount: UserAccount,
|
|
2449
|
+
assetMarketIndex: number,
|
|
2450
|
+
liabilityMarketIndex: number,
|
|
2451
|
+
maxLiabilityTransfer: BN
|
|
1315
2452
|
): Promise<TransactionInstruction> {
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
)
|
|
2453
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
2454
|
+
this.program.programId,
|
|
2455
|
+
userAccount.authority
|
|
2456
|
+
);
|
|
2457
|
+
|
|
2458
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2459
|
+
const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
2460
|
+
|
|
2461
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2462
|
+
userAccounts: [this.getUserAccount(), userAccount],
|
|
2463
|
+
useMarketLastSlotCache: true,
|
|
2464
|
+
writableSpotMarketIndexes: [liabilityMarketIndex, assetMarketIndex],
|
|
2465
|
+
});
|
|
1320
2466
|
|
|
1321
|
-
|
|
2467
|
+
return await this.program.instruction.liquidateSpot(
|
|
2468
|
+
assetMarketIndex,
|
|
2469
|
+
liabilityMarketIndex,
|
|
2470
|
+
maxLiabilityTransfer,
|
|
1322
2471
|
{
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
const market = this.getMarketAccount(position.marketIndex);
|
|
1333
|
-
const marketPublicKey = await getMarketPublicKey(
|
|
1334
|
-
this.program.programId,
|
|
1335
|
-
position.marketIndex
|
|
1336
|
-
);
|
|
1337
|
-
marketAccountInfos.push({
|
|
1338
|
-
pubkey: marketPublicKey,
|
|
1339
|
-
isWritable: true,
|
|
1340
|
-
isSigner: false,
|
|
1341
|
-
});
|
|
1342
|
-
oracleAccountInfos.push({
|
|
1343
|
-
pubkey: market.amm.oracle,
|
|
1344
|
-
isWritable: false,
|
|
1345
|
-
isSigner: false,
|
|
1346
|
-
});
|
|
2472
|
+
accounts: {
|
|
2473
|
+
state: await this.getStatePublicKey(),
|
|
2474
|
+
authority: this.wallet.publicKey,
|
|
2475
|
+
user: userAccountPublicKey,
|
|
2476
|
+
userStats: userStatsPublicKey,
|
|
2477
|
+
liquidator: liquidatorPublicKey,
|
|
2478
|
+
liquidatorStats: liquidatorStatsPublicKey,
|
|
2479
|
+
},
|
|
2480
|
+
remainingAccounts: remainingAccounts,
|
|
1347
2481
|
}
|
|
1348
|
-
}
|
|
1349
|
-
const remainingAccounts = oracleAccountInfos.concat(
|
|
1350
|
-
bankAccountInfos.concat(marketAccountInfos)
|
|
1351
2482
|
);
|
|
2483
|
+
}
|
|
1352
2484
|
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
2485
|
+
public async liquidateBorrowForPerpPnl(
|
|
2486
|
+
userAccountPublicKey: PublicKey,
|
|
2487
|
+
userAccount: UserAccount,
|
|
2488
|
+
perpMarketIndex: number,
|
|
2489
|
+
liabilityMarketIndex: number,
|
|
2490
|
+
maxLiabilityTransfer: BN
|
|
2491
|
+
): Promise<TransactionSignature> {
|
|
2492
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2493
|
+
wrapInTx(
|
|
2494
|
+
await this.getLiquidateBorrowForPerpPnlIx(
|
|
2495
|
+
userAccountPublicKey,
|
|
2496
|
+
userAccount,
|
|
2497
|
+
perpMarketIndex,
|
|
2498
|
+
liabilityMarketIndex,
|
|
2499
|
+
maxLiabilityTransfer
|
|
2500
|
+
)
|
|
2501
|
+
),
|
|
2502
|
+
[],
|
|
2503
|
+
this.opts
|
|
2504
|
+
);
|
|
2505
|
+
this.marketLastSlotCache.set(perpMarketIndex, slot);
|
|
2506
|
+
return txSig;
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2509
|
+
public async getLiquidateBorrowForPerpPnlIx(
|
|
2510
|
+
userAccountPublicKey: PublicKey,
|
|
2511
|
+
userAccount: UserAccount,
|
|
2512
|
+
perpMarketIndex: number,
|
|
2513
|
+
liabilityMarketIndex: number,
|
|
2514
|
+
maxLiabilityTransfer: BN
|
|
2515
|
+
): Promise<TransactionInstruction> {
|
|
2516
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
2517
|
+
this.program.programId,
|
|
2518
|
+
userAccount.authority
|
|
2519
|
+
);
|
|
2520
|
+
|
|
2521
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2522
|
+
const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
2523
|
+
|
|
2524
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2525
|
+
userAccounts: [this.getUserAccount(), userAccount],
|
|
2526
|
+
writablePerpMarketIndexes: [perpMarketIndex],
|
|
2527
|
+
writableSpotMarketIndexes: [liabilityMarketIndex],
|
|
2528
|
+
});
|
|
2529
|
+
|
|
2530
|
+
return await this.program.instruction.liquidateBorrowForPerpPnl(
|
|
2531
|
+
perpMarketIndex,
|
|
2532
|
+
liabilityMarketIndex,
|
|
2533
|
+
maxLiabilityTransfer,
|
|
2534
|
+
{
|
|
2535
|
+
accounts: {
|
|
2536
|
+
state: await this.getStatePublicKey(),
|
|
2537
|
+
authority: this.wallet.publicKey,
|
|
2538
|
+
user: userAccountPublicKey,
|
|
2539
|
+
userStats: userStatsPublicKey,
|
|
2540
|
+
liquidator: liquidatorPublicKey,
|
|
2541
|
+
liquidatorStats: liquidatorStatsPublicKey,
|
|
2542
|
+
},
|
|
2543
|
+
remainingAccounts: remainingAccounts,
|
|
2544
|
+
}
|
|
2545
|
+
);
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
public async liquidatePerpPnlForDeposit(
|
|
2549
|
+
userAccountPublicKey: PublicKey,
|
|
2550
|
+
userAccount: UserAccount,
|
|
2551
|
+
perpMarketIndex: number,
|
|
2552
|
+
assetMarketIndex: number,
|
|
2553
|
+
maxPnlTransfer: BN
|
|
2554
|
+
): Promise<TransactionSignature> {
|
|
2555
|
+
const { txSig, slot } = await this.txSender.send(
|
|
2556
|
+
wrapInTx(
|
|
2557
|
+
await this.getLiquidatePerpPnlForDepositIx(
|
|
2558
|
+
userAccountPublicKey,
|
|
2559
|
+
userAccount,
|
|
2560
|
+
perpMarketIndex,
|
|
2561
|
+
assetMarketIndex,
|
|
2562
|
+
maxPnlTransfer
|
|
2563
|
+
)
|
|
2564
|
+
),
|
|
2565
|
+
[],
|
|
2566
|
+
this.opts
|
|
2567
|
+
);
|
|
2568
|
+
this.marketLastSlotCache.set(perpMarketIndex, slot);
|
|
2569
|
+
return txSig;
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
public async getLiquidatePerpPnlForDepositIx(
|
|
2573
|
+
userAccountPublicKey: PublicKey,
|
|
2574
|
+
userAccount: UserAccount,
|
|
2575
|
+
perpMarketIndex: number,
|
|
2576
|
+
assetMarketIndex: number,
|
|
2577
|
+
maxPnlTransfer: BN
|
|
2578
|
+
): Promise<TransactionInstruction> {
|
|
2579
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
2580
|
+
this.program.programId,
|
|
2581
|
+
userAccount.authority
|
|
2582
|
+
);
|
|
2583
|
+
|
|
2584
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2585
|
+
const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
2586
|
+
|
|
2587
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2588
|
+
userAccounts: [this.getUserAccount(), userAccount],
|
|
2589
|
+
writablePerpMarketIndexes: [perpMarketIndex],
|
|
2590
|
+
writableSpotMarketIndexes: [assetMarketIndex],
|
|
2591
|
+
});
|
|
2592
|
+
|
|
2593
|
+
return await this.program.instruction.liquidatePerpPnlForDeposit(
|
|
2594
|
+
perpMarketIndex,
|
|
2595
|
+
assetMarketIndex,
|
|
2596
|
+
maxPnlTransfer,
|
|
2597
|
+
{
|
|
2598
|
+
accounts: {
|
|
2599
|
+
state: await this.getStatePublicKey(),
|
|
2600
|
+
authority: this.wallet.publicKey,
|
|
2601
|
+
user: userAccountPublicKey,
|
|
2602
|
+
userStats: userStatsPublicKey,
|
|
2603
|
+
liquidator: liquidatorPublicKey,
|
|
2604
|
+
liquidatorStats: liquidatorStatsPublicKey,
|
|
2605
|
+
},
|
|
2606
|
+
remainingAccounts: remainingAccounts,
|
|
2607
|
+
}
|
|
2608
|
+
);
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
public async resolvePerpBankruptcy(
|
|
2612
|
+
userAccountPublicKey: PublicKey,
|
|
2613
|
+
userAccount: UserAccount,
|
|
2614
|
+
marketIndex: number
|
|
2615
|
+
): Promise<TransactionSignature> {
|
|
2616
|
+
const { txSig } = await this.txSender.send(
|
|
2617
|
+
wrapInTx(
|
|
2618
|
+
await this.getResolvePerpBankruptcyIx(
|
|
2619
|
+
userAccountPublicKey,
|
|
2620
|
+
userAccount,
|
|
2621
|
+
marketIndex
|
|
2622
|
+
)
|
|
2623
|
+
),
|
|
2624
|
+
[],
|
|
2625
|
+
this.opts
|
|
2626
|
+
);
|
|
2627
|
+
return txSig;
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
public async getResolvePerpBankruptcyIx(
|
|
2631
|
+
userAccountPublicKey: PublicKey,
|
|
2632
|
+
userAccount: UserAccount,
|
|
2633
|
+
marketIndex: number
|
|
2634
|
+
): Promise<TransactionInstruction> {
|
|
2635
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
2636
|
+
this.program.programId,
|
|
2637
|
+
userAccount.authority
|
|
2638
|
+
);
|
|
2639
|
+
|
|
2640
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2641
|
+
const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
2642
|
+
|
|
2643
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2644
|
+
userAccounts: [this.getUserAccount(), userAccount],
|
|
2645
|
+
writablePerpMarketIndexes: [marketIndex],
|
|
2646
|
+
writableSpotMarketIndexes: [QUOTE_SPOT_MARKET_INDEX],
|
|
2647
|
+
});
|
|
2648
|
+
|
|
2649
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
2650
|
+
|
|
2651
|
+
return await this.program.instruction.resolvePerpBankruptcy(
|
|
2652
|
+
QUOTE_SPOT_MARKET_INDEX,
|
|
2653
|
+
marketIndex,
|
|
2654
|
+
{
|
|
2655
|
+
accounts: {
|
|
2656
|
+
state: await this.getStatePublicKey(),
|
|
2657
|
+
authority: this.wallet.publicKey,
|
|
2658
|
+
user: userAccountPublicKey,
|
|
2659
|
+
userStats: userStatsPublicKey,
|
|
2660
|
+
liquidator: liquidatorPublicKey,
|
|
2661
|
+
liquidatorStats: liquidatorStatsPublicKey,
|
|
2662
|
+
spotMarketVault: spotMarket.vault,
|
|
2663
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
2664
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2665
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
2666
|
+
},
|
|
2667
|
+
remainingAccounts: remainingAccounts,
|
|
2668
|
+
}
|
|
2669
|
+
);
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
public async resolveSpotBankruptcy(
|
|
2673
|
+
userAccountPublicKey: PublicKey,
|
|
2674
|
+
userAccount: UserAccount,
|
|
2675
|
+
marketIndex: number
|
|
2676
|
+
): Promise<TransactionSignature> {
|
|
2677
|
+
const { txSig } = await this.txSender.send(
|
|
2678
|
+
wrapInTx(
|
|
2679
|
+
await this.getResolveSpotBankruptcyIx(
|
|
2680
|
+
userAccountPublicKey,
|
|
2681
|
+
userAccount,
|
|
2682
|
+
marketIndex
|
|
2683
|
+
)
|
|
2684
|
+
),
|
|
2685
|
+
[],
|
|
2686
|
+
this.opts
|
|
2687
|
+
);
|
|
2688
|
+
return txSig;
|
|
2689
|
+
}
|
|
2690
|
+
|
|
2691
|
+
public async getResolveSpotBankruptcyIx(
|
|
2692
|
+
userAccountPublicKey: PublicKey,
|
|
2693
|
+
userAccount: UserAccount,
|
|
2694
|
+
marketIndex: number
|
|
2695
|
+
): Promise<TransactionInstruction> {
|
|
2696
|
+
const userStatsPublicKey = getUserStatsAccountPublicKey(
|
|
2697
|
+
this.program.programId,
|
|
2698
|
+
userAccount.authority
|
|
2699
|
+
);
|
|
2700
|
+
|
|
2701
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
2702
|
+
const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
2703
|
+
|
|
2704
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2705
|
+
userAccounts: [this.getUserAccount(), userAccount],
|
|
2706
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
2707
|
+
});
|
|
2708
|
+
|
|
2709
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
2710
|
+
|
|
2711
|
+
return await this.program.instruction.resolveSpotBankruptcy(marketIndex, {
|
|
1356
2712
|
accounts: {
|
|
1357
2713
|
state: await this.getStatePublicKey(),
|
|
1358
2714
|
authority: this.wallet.publicKey,
|
|
1359
|
-
user:
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
2715
|
+
user: userAccountPublicKey,
|
|
2716
|
+
userStats: userStatsPublicKey,
|
|
2717
|
+
liquidatorStats: liquidatorStatsPublicKey,
|
|
2718
|
+
liquidator: liquidatorPublicKey,
|
|
2719
|
+
spotMarketVault: spotMarket.vault,
|
|
2720
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
2721
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
1364
2722
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1365
2723
|
},
|
|
1366
2724
|
remainingAccounts: remainingAccounts,
|
|
@@ -1369,7 +2727,7 @@ export class ClearingHouse {
|
|
|
1369
2727
|
|
|
1370
2728
|
public async updateFundingRate(
|
|
1371
2729
|
oracle: PublicKey,
|
|
1372
|
-
marketIndex:
|
|
2730
|
+
marketIndex: number
|
|
1373
2731
|
): Promise<TransactionSignature> {
|
|
1374
2732
|
const { txSig } = await this.txSender.send(
|
|
1375
2733
|
wrapInTx(await this.getUpdateFundingRateIx(oracle, marketIndex)),
|
|
@@ -1381,7 +2739,7 @@ export class ClearingHouse {
|
|
|
1381
2739
|
|
|
1382
2740
|
public async getUpdateFundingRateIx(
|
|
1383
2741
|
oracle: PublicKey,
|
|
1384
|
-
marketIndex:
|
|
2742
|
+
marketIndex: number
|
|
1385
2743
|
): Promise<TransactionInstruction> {
|
|
1386
2744
|
return await this.program.instruction.updateFundingRate(marketIndex, {
|
|
1387
2745
|
accounts: {
|
|
@@ -1393,10 +2751,10 @@ export class ClearingHouse {
|
|
|
1393
2751
|
}
|
|
1394
2752
|
|
|
1395
2753
|
public async settleFundingPayment(
|
|
1396
|
-
|
|
2754
|
+
userAccountPublicKey: PublicKey
|
|
1397
2755
|
): Promise<TransactionSignature> {
|
|
1398
2756
|
const { txSig } = await this.txSender.send(
|
|
1399
|
-
wrapInTx(await this.getSettleFundingPaymentIx(
|
|
2757
|
+
wrapInTx(await this.getSettleFundingPaymentIx(userAccountPublicKey)),
|
|
1400
2758
|
[],
|
|
1401
2759
|
this.opts
|
|
1402
2760
|
);
|
|
@@ -1404,33 +2762,28 @@ export class ClearingHouse {
|
|
|
1404
2762
|
}
|
|
1405
2763
|
|
|
1406
2764
|
public async getSettleFundingPaymentIx(
|
|
1407
|
-
|
|
2765
|
+
userAccountPublicKey: PublicKey
|
|
1408
2766
|
): Promise<TransactionInstruction> {
|
|
1409
|
-
const
|
|
1410
|
-
|
|
2767
|
+
const userAccount = (await this.program.account.user.fetch(
|
|
2768
|
+
userAccountPublicKey
|
|
1411
2769
|
)) as UserAccount;
|
|
1412
2770
|
|
|
1413
|
-
const
|
|
1414
|
-
|
|
1415
|
-
const remainingAccounts = [];
|
|
1416
|
-
for (const position of userPositions) {
|
|
2771
|
+
const writablePerpMarketIndexes = [];
|
|
2772
|
+
for (const position of userAccount.perpPositions) {
|
|
1417
2773
|
if (!positionIsAvailable(position)) {
|
|
1418
|
-
|
|
1419
|
-
this.program.programId,
|
|
1420
|
-
position.marketIndex
|
|
1421
|
-
);
|
|
1422
|
-
remainingAccounts.push({
|
|
1423
|
-
pubkey: marketPublicKey,
|
|
1424
|
-
isWritable: false,
|
|
1425
|
-
isSigner: false,
|
|
1426
|
-
});
|
|
2774
|
+
writablePerpMarketIndexes.push(position.marketIndex);
|
|
1427
2775
|
}
|
|
1428
2776
|
}
|
|
1429
2777
|
|
|
2778
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2779
|
+
userAccounts: [userAccount],
|
|
2780
|
+
writablePerpMarketIndexes,
|
|
2781
|
+
});
|
|
2782
|
+
|
|
1430
2783
|
return await this.program.instruction.settleFundingPayment({
|
|
1431
2784
|
accounts: {
|
|
1432
2785
|
state: await this.getStatePublicKey(),
|
|
1433
|
-
user:
|
|
2786
|
+
user: userAccountPublicKey,
|
|
1434
2787
|
},
|
|
1435
2788
|
remainingAccounts,
|
|
1436
2789
|
});
|
|
@@ -1440,10 +2793,256 @@ export class ClearingHouse {
|
|
|
1440
2793
|
this.eventEmitter.emit(eventName, data);
|
|
1441
2794
|
}
|
|
1442
2795
|
|
|
1443
|
-
public getOracleDataForMarket(marketIndex:
|
|
1444
|
-
const oracleKey = this.
|
|
2796
|
+
public getOracleDataForMarket(marketIndex: number): OraclePriceData {
|
|
2797
|
+
const oracleKey = this.getPerpMarketAccount(marketIndex).amm.oracle;
|
|
1445
2798
|
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
1446
2799
|
|
|
1447
2800
|
return oracleData;
|
|
1448
2801
|
}
|
|
2802
|
+
|
|
2803
|
+
public getOracleDataForSpotMarket(marketIndex: number): OraclePriceData {
|
|
2804
|
+
const oracleKey = this.getSpotMarketAccount(marketIndex).oracle;
|
|
2805
|
+
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
2806
|
+
|
|
2807
|
+
return oracleData;
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
public async initializeInsuranceFundStake(
|
|
2811
|
+
marketIndex: number
|
|
2812
|
+
): Promise<TransactionSignature> {
|
|
2813
|
+
const { txSig } = await this.txSender.send(
|
|
2814
|
+
wrapInTx(await this.getInitializeInsuranceFundStakeIx(marketIndex)),
|
|
2815
|
+
[],
|
|
2816
|
+
this.opts
|
|
2817
|
+
);
|
|
2818
|
+
return txSig;
|
|
2819
|
+
}
|
|
2820
|
+
|
|
2821
|
+
public async getInitializeInsuranceFundStakeIx(
|
|
2822
|
+
marketIndex: number
|
|
2823
|
+
): Promise<TransactionInstruction> {
|
|
2824
|
+
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2825
|
+
this.program.programId,
|
|
2826
|
+
this.wallet.publicKey,
|
|
2827
|
+
marketIndex
|
|
2828
|
+
);
|
|
2829
|
+
|
|
2830
|
+
return await this.program.instruction.initializeInsuranceFundStake(
|
|
2831
|
+
marketIndex,
|
|
2832
|
+
{
|
|
2833
|
+
accounts: {
|
|
2834
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2835
|
+
spotMarket: this.getSpotMarketAccount(marketIndex).pubkey,
|
|
2836
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2837
|
+
authority: this.wallet.publicKey,
|
|
2838
|
+
payer: this.wallet.publicKey,
|
|
2839
|
+
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
2840
|
+
systemProgram: anchor.web3.SystemProgram.programId,
|
|
2841
|
+
state: await this.getStatePublicKey(),
|
|
2842
|
+
},
|
|
2843
|
+
}
|
|
2844
|
+
);
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
public async addInsuranceFundStake(
|
|
2848
|
+
marketIndex: number,
|
|
2849
|
+
amount: BN,
|
|
2850
|
+
collateralAccountPublicKey: PublicKey
|
|
2851
|
+
): Promise<TransactionSignature> {
|
|
2852
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
2853
|
+
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2854
|
+
this.program.programId,
|
|
2855
|
+
this.wallet.publicKey,
|
|
2856
|
+
marketIndex
|
|
2857
|
+
);
|
|
2858
|
+
|
|
2859
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2860
|
+
userAccounts: [this.getUserAccount()],
|
|
2861
|
+
useMarketLastSlotCache: true,
|
|
2862
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
2863
|
+
});
|
|
2864
|
+
|
|
2865
|
+
return await this.program.rpc.addInsuranceFundStake(marketIndex, amount, {
|
|
2866
|
+
accounts: {
|
|
2867
|
+
state: await this.getStatePublicKey(),
|
|
2868
|
+
spotMarket: spotMarket.pubkey,
|
|
2869
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2870
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2871
|
+
authority: this.wallet.publicKey,
|
|
2872
|
+
spotMarketVault: spotMarket.vault,
|
|
2873
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
2874
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2875
|
+
userTokenAccount: collateralAccountPublicKey,
|
|
2876
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
2877
|
+
},
|
|
2878
|
+
remainingAccounts,
|
|
2879
|
+
});
|
|
2880
|
+
}
|
|
2881
|
+
|
|
2882
|
+
public async requestRemoveInsuranceFundStake(
|
|
2883
|
+
marketIndex: number,
|
|
2884
|
+
amount: BN
|
|
2885
|
+
): Promise<TransactionSignature> {
|
|
2886
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2887
|
+
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2888
|
+
this.program.programId,
|
|
2889
|
+
this.wallet.publicKey,
|
|
2890
|
+
marketIndex
|
|
2891
|
+
);
|
|
2892
|
+
|
|
2893
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2894
|
+
userAccounts: [this.getUserAccount()],
|
|
2895
|
+
useMarketLastSlotCache: true,
|
|
2896
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
2897
|
+
});
|
|
2898
|
+
|
|
2899
|
+
return await this.program.rpc.requestRemoveInsuranceFundStake(
|
|
2900
|
+
marketIndex,
|
|
2901
|
+
amount,
|
|
2902
|
+
{
|
|
2903
|
+
accounts: {
|
|
2904
|
+
state: await this.getStatePublicKey(),
|
|
2905
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2906
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2907
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2908
|
+
authority: this.wallet.publicKey,
|
|
2909
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2910
|
+
},
|
|
2911
|
+
remainingAccounts,
|
|
2912
|
+
}
|
|
2913
|
+
);
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
public async cancelRequestRemoveInsuranceFundStake(
|
|
2917
|
+
marketIndex: number
|
|
2918
|
+
): Promise<TransactionSignature> {
|
|
2919
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2920
|
+
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2921
|
+
this.program.programId,
|
|
2922
|
+
this.wallet.publicKey,
|
|
2923
|
+
marketIndex
|
|
2924
|
+
);
|
|
2925
|
+
|
|
2926
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2927
|
+
userAccounts: [this.getUserAccount()],
|
|
2928
|
+
useMarketLastSlotCache: true,
|
|
2929
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
2930
|
+
});
|
|
2931
|
+
|
|
2932
|
+
return await this.program.rpc.cancelRequestRemoveInsuranceFundStake(
|
|
2933
|
+
marketIndex,
|
|
2934
|
+
{
|
|
2935
|
+
accounts: {
|
|
2936
|
+
state: await this.getStatePublicKey(),
|
|
2937
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2938
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2939
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2940
|
+
authority: this.wallet.publicKey,
|
|
2941
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2942
|
+
},
|
|
2943
|
+
remainingAccounts,
|
|
2944
|
+
}
|
|
2945
|
+
);
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2948
|
+
public async removeInsuranceFundStake(
|
|
2949
|
+
marketIndex: number,
|
|
2950
|
+
collateralAccountPublicKey: PublicKey
|
|
2951
|
+
): Promise<TransactionSignature> {
|
|
2952
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2953
|
+
const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
|
|
2954
|
+
this.program.programId,
|
|
2955
|
+
this.wallet.publicKey,
|
|
2956
|
+
marketIndex
|
|
2957
|
+
);
|
|
2958
|
+
|
|
2959
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2960
|
+
userAccounts: [this.getUserAccount()],
|
|
2961
|
+
useMarketLastSlotCache: true,
|
|
2962
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
2963
|
+
});
|
|
2964
|
+
|
|
2965
|
+
return await this.program.rpc.removeInsuranceFundStake(marketIndex, {
|
|
2966
|
+
accounts: {
|
|
2967
|
+
state: await this.getStatePublicKey(),
|
|
2968
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2969
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2970
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2971
|
+
authority: this.wallet.publicKey,
|
|
2972
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2973
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2974
|
+
userTokenAccount: collateralAccountPublicKey,
|
|
2975
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
2976
|
+
},
|
|
2977
|
+
remainingAccounts,
|
|
2978
|
+
});
|
|
2979
|
+
}
|
|
2980
|
+
|
|
2981
|
+
public async settleRevenueToInsuranceFund(
|
|
2982
|
+
marketIndex: number
|
|
2983
|
+
): Promise<TransactionSignature> {
|
|
2984
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2985
|
+
|
|
2986
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2987
|
+
userAccounts: [this.getUserAccount()],
|
|
2988
|
+
useMarketLastSlotCache: true,
|
|
2989
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
2990
|
+
});
|
|
2991
|
+
|
|
2992
|
+
return await this.program.rpc.settleRevenueToInsuranceFund(marketIndex, {
|
|
2993
|
+
accounts: {
|
|
2994
|
+
state: await this.getStatePublicKey(),
|
|
2995
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2996
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
2997
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2998
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2999
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
3000
|
+
},
|
|
3001
|
+
remainingAccounts,
|
|
3002
|
+
});
|
|
3003
|
+
}
|
|
3004
|
+
|
|
3005
|
+
public async resolvePerpPnlDeficit(
|
|
3006
|
+
spotMarketIndex: number,
|
|
3007
|
+
perpMarketIndex: number
|
|
3008
|
+
): Promise<TransactionSignature> {
|
|
3009
|
+
const { txSig } = await this.txSender.send(
|
|
3010
|
+
wrapInTx(
|
|
3011
|
+
await this.getResolvePerpPnlDeficitIx(spotMarketIndex, perpMarketIndex)
|
|
3012
|
+
),
|
|
3013
|
+
[],
|
|
3014
|
+
this.opts
|
|
3015
|
+
);
|
|
3016
|
+
return txSig;
|
|
3017
|
+
}
|
|
3018
|
+
|
|
3019
|
+
public async getResolvePerpPnlDeficitIx(
|
|
3020
|
+
spotMarketIndex: number,
|
|
3021
|
+
perpMarketIndex: number
|
|
3022
|
+
): Promise<TransactionInstruction> {
|
|
3023
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
3024
|
+
userAccounts: [this.getUserAccount()],
|
|
3025
|
+
useMarketLastSlotCache: true,
|
|
3026
|
+
writablePerpMarketIndexes: [perpMarketIndex],
|
|
3027
|
+
writableSpotMarketIndexes: [spotMarketIndex],
|
|
3028
|
+
});
|
|
3029
|
+
|
|
3030
|
+
const spotMarket = this.getSpotMarketAccount(spotMarketIndex);
|
|
3031
|
+
|
|
3032
|
+
return await this.program.instruction.resolvePerpPnlDeficit(
|
|
3033
|
+
spotMarketIndex,
|
|
3034
|
+
perpMarketIndex,
|
|
3035
|
+
{
|
|
3036
|
+
accounts: {
|
|
3037
|
+
state: await this.getStatePublicKey(),
|
|
3038
|
+
authority: this.wallet.publicKey,
|
|
3039
|
+
spotMarketVault: spotMarket.vault,
|
|
3040
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
3041
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
3042
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
3043
|
+
},
|
|
3044
|
+
remainingAccounts: remainingAccounts,
|
|
3045
|
+
}
|
|
3046
|
+
);
|
|
3047
|
+
}
|
|
1449
3048
|
}
|