@drift-labs/sdk 0.1.36-master.7 → 0.2.0-master.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/accounts/bulkAccountLoader.d.ts +6 -6
- package/lib/accounts/bulkAccountLoader.js +81 -95
- package/lib/accounts/bulkUserSubscription.js +13 -57
- package/lib/accounts/fetch.d.ts +4 -0
- package/lib/accounts/fetch.js +18 -0
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +34 -38
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +224 -224
- package/lib/accounts/pollingOracleSubscriber.d.ts +3 -3
- package/lib/accounts/pollingOracleSubscriber.js +37 -49
- package/lib/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
- package/lib/accounts/pollingTokenAccountSubscriber.js +35 -50
- package/lib/accounts/pollingUserAccountSubscriber.d.ts +7 -13
- package/lib/accounts/pollingUserAccountSubscriber.js +71 -134
- package/lib/accounts/types.d.ts +34 -41
- package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -4
- package/lib/accounts/webSocketAccountSubscriber.js +39 -35
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +33 -28
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +153 -185
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts +5 -11
- package/lib/accounts/webSocketUserAccountSubscriber.js +22 -67
- package/lib/addresses/marketAddresses.d.ts +4 -0
- package/lib/addresses/marketAddresses.js +15 -0
- package/lib/addresses/pda.d.ts +12 -0
- package/lib/addresses/pda.js +83 -0
- package/lib/admin.d.ts +8 -17
- package/lib/admin.js +366 -558
- package/lib/clearingHouse.d.ts +84 -109
- package/lib/clearingHouse.js +778 -899
- package/lib/clearingHouseConfig.d.ts +34 -0
- package/lib/clearingHouseConfig.js +2 -0
- package/lib/clearingHouseUser.d.ts +19 -22
- package/lib/clearingHouseUser.js +155 -141
- package/lib/clearingHouseUserConfig.d.ts +14 -0
- package/lib/clearingHouseUserConfig.js +2 -0
- package/lib/config.d.ts +12 -0
- package/lib/config.js +35 -4
- package/lib/constants/banks.d.ts +16 -0
- package/lib/constants/banks.js +34 -0
- package/lib/constants/markets.d.ts +8 -3
- package/lib/constants/markets.js +13 -206
- package/lib/constants/numericConstants.d.ts +16 -0
- package/lib/constants/numericConstants.js +22 -6
- package/lib/events/eventList.d.ts +22 -0
- package/lib/events/eventList.js +77 -0
- package/lib/events/eventSubscriber.d.ts +34 -0
- package/lib/events/eventSubscriber.js +126 -0
- package/lib/events/fetchLogs.d.ts +13 -0
- package/lib/events/fetchLogs.js +39 -0
- package/lib/events/pollingLogProvider.d.ts +15 -0
- package/lib/events/pollingLogProvider.js +53 -0
- package/lib/events/sort.d.ts +2 -0
- package/lib/events/sort.js +44 -0
- package/lib/events/txEventCache.d.ts +24 -0
- package/lib/events/txEventCache.js +71 -0
- package/lib/events/types.d.ts +49 -0
- package/lib/events/types.js +20 -0
- package/lib/events/webSocketLogProvider.d.ts +12 -0
- package/lib/events/webSocketLogProvider.js +30 -0
- package/lib/examples/makeTradeExample.js +26 -27
- package/lib/factory/bigNum.d.ts +112 -0
- package/lib/factory/bigNum.js +356 -0
- package/lib/factory/oracleClient.d.ts +1 -2
- package/lib/factory/oracleClient.js +6 -2
- package/lib/idl/clearing_house.json +2213 -2951
- package/lib/index.d.ts +12 -4
- package/lib/index.js +12 -4
- package/lib/math/amm.d.ts +19 -29
- package/lib/math/amm.js +129 -179
- package/lib/math/auction.d.ts +5 -0
- package/lib/math/auction.js +39 -0
- package/lib/math/bankBalance.d.ts +9 -0
- package/lib/math/bankBalance.js +75 -0
- package/lib/math/conversion.d.ts +0 -1
- package/lib/math/conversion.js +1 -5
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +158 -175
- package/lib/math/market.d.ts +6 -6
- package/lib/math/market.js +10 -9
- package/lib/math/orders.d.ts +5 -0
- package/lib/math/orders.js +31 -1
- package/lib/math/position.d.ts +7 -5
- package/lib/math/position.js +27 -27
- package/lib/math/repeg.d.ts +22 -0
- package/lib/math/repeg.js +128 -0
- package/lib/math/trade.d.ts +5 -4
- package/lib/math/trade.js +29 -21
- package/lib/mockUSDCFaucet.js +87 -116
- package/lib/oracles/oracleClientCache.d.ts +8 -0
- package/lib/oracles/oracleClientCache.js +19 -0
- package/lib/oracles/pythClient.d.ts +3 -5
- package/lib/oracles/pythClient.js +12 -31
- package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
- package/lib/oracles/quoteAssetOracleClient.js +21 -0
- package/lib/oracles/switchboardClient.d.ts +3 -5
- package/lib/oracles/switchboardClient.js +29 -50
- package/lib/oracles/types.d.ts +6 -1
- package/lib/orders.d.ts +6 -6
- package/lib/orders.js +10 -9
- package/lib/slot/SlotSubscriber.d.ts +12 -0
- package/lib/slot/SlotSubscriber.js +23 -0
- package/lib/tx/retryTxSender.d.ts +2 -2
- package/lib/tx/retryTxSender.js +108 -123
- package/lib/tx/types.d.ts +5 -1
- package/lib/tx/utils.d.ts +1 -1
- package/lib/tx/utils.js +11 -2
- package/lib/types.d.ts +105 -109
- package/lib/types.js +13 -1
- package/lib/userName.d.ts +4 -0
- package/lib/userName.js +20 -0
- package/lib/util/computeUnits.js +10 -21
- package/lib/util/tps.js +11 -22
- package/lib/wallet.js +7 -20
- package/package.json +10 -3
- package/src/accounts/bulkAccountLoader.ts +21 -15
- package/src/accounts/bulkUserSubscription.ts +1 -45
- package/src/accounts/fetch.ts +33 -0
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
- package/src/accounts/pollingOracleSubscriber.ts +16 -8
- package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
- package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
- package/src/accounts/types.ts +41 -70
- package/src/accounts/webSocketAccountSubscriber.ts +33 -16
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
- package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
- package/src/addresses/marketAddresses.ts +18 -0
- package/src/addresses/pda.ts +118 -0
- package/src/admin.ts +205 -346
- package/src/clearingHouse.ts +918 -961
- package/src/clearingHouseConfig.ts +37 -0
- package/src/clearingHouseUser.ts +275 -185
- package/src/clearingHouseUserConfig.ts +18 -0
- package/src/config.ts +54 -1
- package/src/constants/banks.ts +43 -0
- package/src/constants/markets.ts +16 -207
- package/src/constants/numericConstants.ts +33 -5
- package/src/events/eventList.ts +94 -0
- package/src/events/eventSubscriber.ts +194 -0
- package/src/events/fetchLogs.ts +80 -0
- package/src/events/pollingLogProvider.ts +79 -0
- package/src/events/sort.ts +65 -0
- package/src/events/txEventCache.ts +74 -0
- package/src/events/types.ts +98 -0
- package/src/events/webSocketLogProvider.ts +38 -0
- package/src/examples/makeTradeExample.ts +20 -11
- package/src/factory/bigNum.ts +507 -0
- package/src/factory/oracleClient.ts +7 -4
- package/src/idl/clearing_house.json +2213 -2951
- package/src/index.ts +12 -4
- package/src/math/amm.ts +229 -245
- package/src/math/auction.ts +39 -0
- package/src/math/bankBalance.ts +112 -0
- package/src/math/conversion.ts +1 -11
- package/src/math/funding.ts +12 -9
- package/src/math/market.ts +37 -30
- package/src/math/orders.ts +38 -0
- package/src/math/position.ts +48 -35
- package/src/math/repeg.ts +175 -0
- package/src/math/trade.ts +45 -35
- package/src/math/utils.js +27 -0
- package/src/math/utils.js.map +1 -0
- package/src/oracles/oracleClientCache.ts +20 -0
- package/src/oracles/pythClient.ts +4 -11
- package/src/oracles/quoteAssetOracleClient.ts +25 -0
- package/src/oracles/switchboardClient.ts +11 -24
- package/src/oracles/types.ts +7 -1
- package/src/orders.ts +35 -20
- package/src/slot/SlotSubscriber.ts +32 -0
- package/src/tx/retryTxSender.ts +6 -4
- package/src/tx/types.ts +6 -1
- package/src/tx/utils.ts +22 -3
- package/src/types.ts +108 -122
- package/src/userName.ts +20 -0
- package/src/util/computeUnits.js +17 -0
- package/src/util/computeUnits.js.map +1 -0
- package/tests/bn/test.ts +255 -0
- package/tsconfig.json +12 -12
- package/lib/addresses.d.ts +0 -10
- package/lib/addresses.js +0 -93
- package/lib/constants/accounts.d.ts +0 -15
- package/lib/constants/accounts.js +0 -18
- package/lib/factory/clearingHouse.d.ts +0 -35
- package/lib/factory/clearingHouse.js +0 -81
- package/lib/factory/clearingHouseUser.d.ts +0 -19
- package/lib/factory/clearingHouseUser.js +0 -34
- package/lib/math/insuranceFund.d.ts +0 -15
- package/lib/math/insuranceFund.js +0 -33
- package/lib/settlement.d.ts +0 -4
- package/lib/settlement.js +0 -10
- package/lib/tx/defaultTxSender.d.ts +0 -8
- package/lib/tx/defaultTxSender.js +0 -12
- package/src/addresses.ts +0 -82
- package/src/constants/accounts.ts +0 -26
- package/src/factory/clearingHouse.ts +0 -173
- package/src/factory/clearingHouseUser.ts +0 -73
- package/src/math/insuranceFund.ts +0 -29
- package/src/settlement.ts +0 -9
- package/src/tx/defaultTxSender.ts +0 -24
package/src/clearingHouse.ts
CHANGED
|
@@ -1,28 +1,16 @@
|
|
|
1
1
|
import { AnchorProvider, BN, Idl, Program } from '@project-serum/anchor';
|
|
2
|
+
import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
2
3
|
import {
|
|
3
|
-
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
4
|
-
Token,
|
|
5
|
-
TOKEN_PROGRAM_ID,
|
|
6
|
-
} from '@solana/spl-token';
|
|
7
|
-
import {
|
|
8
|
-
MarketsAccount,
|
|
9
4
|
StateAccount,
|
|
10
|
-
DepositHistoryAccount,
|
|
11
|
-
FundingPaymentHistoryAccount,
|
|
12
|
-
FundingRateHistoryAccount,
|
|
13
5
|
IWallet,
|
|
14
|
-
LiquidationHistoryAccount,
|
|
15
6
|
PositionDirection,
|
|
16
|
-
TradeHistoryAccount,
|
|
17
7
|
UserAccount,
|
|
18
|
-
|
|
19
|
-
OrderHistoryAccount,
|
|
20
|
-
OrderStateAccount,
|
|
8
|
+
MarketAccount,
|
|
21
9
|
OrderParams,
|
|
22
10
|
Order,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
BankAccount,
|
|
12
|
+
UserBankBalance,
|
|
13
|
+
MakerInfo,
|
|
26
14
|
} from './types';
|
|
27
15
|
import * as anchor from '@project-serum/anchor';
|
|
28
16
|
import clearingHouseIDL from './idl/clearing_house.json';
|
|
@@ -31,10 +19,10 @@ import {
|
|
|
31
19
|
Connection,
|
|
32
20
|
PublicKey,
|
|
33
21
|
TransactionSignature,
|
|
34
|
-
Keypair,
|
|
35
22
|
ConfirmOptions,
|
|
36
23
|
Transaction,
|
|
37
24
|
TransactionInstruction,
|
|
25
|
+
AccountMeta,
|
|
38
26
|
} from '@solana/web3.js';
|
|
39
27
|
|
|
40
28
|
import { MockUSDCFaucet } from './mockUSDCFaucet';
|
|
@@ -42,40 +30,34 @@ import { EventEmitter } from 'events';
|
|
|
42
30
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
43
31
|
import {
|
|
44
32
|
getClearingHouseStateAccountPublicKey,
|
|
45
|
-
|
|
46
|
-
getSettlementStatePublicKey,
|
|
33
|
+
getMarketPublicKey,
|
|
47
34
|
getUserAccountPublicKey,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
getUserOrdersAccountPublicKeyAndNonce,
|
|
51
|
-
} from './addresses';
|
|
35
|
+
getUserAccountPublicKeySync,
|
|
36
|
+
} from './addresses/pda';
|
|
52
37
|
import {
|
|
53
38
|
ClearingHouseAccountSubscriber,
|
|
54
39
|
ClearingHouseAccountEvents,
|
|
55
|
-
|
|
40
|
+
DataAndSlot,
|
|
56
41
|
} from './accounts/types';
|
|
57
42
|
import { TxSender } from './tx/types';
|
|
58
43
|
import { wrapInTx } from './tx/utils';
|
|
59
|
-
import {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
} from './
|
|
64
|
-
import {
|
|
65
|
-
import {
|
|
44
|
+
import { QUOTE_ASSET_BANK_INDEX, ZERO } from './constants/numericConstants';
|
|
45
|
+
import { findDirectionToClose, positionIsAvailable } from './math/position';
|
|
46
|
+
import { getTokenAmount } from './math/bankBalance';
|
|
47
|
+
import { DEFAULT_USER_NAME, encodeName } from './userName';
|
|
48
|
+
import { OraclePriceData } from './oracles/types';
|
|
49
|
+
import { ClearingHouseConfig } from './clearingHouseConfig';
|
|
50
|
+
import { PollingClearingHouseAccountSubscriber } from './accounts/pollingClearingHouseAccountSubscriber';
|
|
51
|
+
import { WebSocketClearingHouseAccountSubscriber } from './accounts/webSocketClearingHouseAccountSubscriber';
|
|
52
|
+
import { RetryTxSender } from './tx/retryTxSender';
|
|
66
53
|
import { ClearingHouseUser } from './clearingHouseUser';
|
|
67
|
-
import {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} from './factory/clearingHouseUser';
|
|
71
|
-
import { bulkPollingUserSubscribe } from './accounts/bulkUserSubscription';
|
|
54
|
+
import { ClearingHouseUserAccountSubscriptionConfig } from './clearingHouseUserConfig';
|
|
55
|
+
import { getMarketOrderParams } from './orderParams';
|
|
56
|
+
import { getMarketsBanksAndOraclesForSubscription } from './config';
|
|
72
57
|
|
|
73
58
|
/**
|
|
74
59
|
* # ClearingHouse
|
|
75
60
|
* This class is the main way to interact with Drift Protocol. It allows you to subscribe to the various accounts where the Market's state is stored, as well as: opening positions, liquidating, settling funding, depositing & withdrawing, and more.
|
|
76
|
-
*
|
|
77
|
-
* The default way to construct a ClearingHouse instance is using the {@link from} method. This will create an instance using the static {@link WebSocketClearingHouseAccountSubscriber}, which will use a websocket for each state account subscription.
|
|
78
|
-
* Alternatively, if you want to implement your own method of subscribing to the state accounts on the blockchain, you can implement a {@link ClearingHouseAccountSubscriber} and use it in the {@link ClearingHouse.constructor}
|
|
79
61
|
*/
|
|
80
62
|
export class ClearingHouse {
|
|
81
63
|
connection: Connection;
|
|
@@ -83,10 +65,14 @@ export class ClearingHouse {
|
|
|
83
65
|
public program: Program;
|
|
84
66
|
provider: AnchorProvider;
|
|
85
67
|
opts?: ConfirmOptions;
|
|
68
|
+
users = new Map<number, ClearingHouseUser>();
|
|
69
|
+
activeUserId: number;
|
|
70
|
+
userAccountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig;
|
|
86
71
|
accountSubscriber: ClearingHouseAccountSubscriber;
|
|
87
72
|
eventEmitter: StrictEventEmitter<EventEmitter, ClearingHouseAccountEvents>;
|
|
88
73
|
_isSubscribed = false;
|
|
89
74
|
txSender: TxSender;
|
|
75
|
+
marketLastSlotCache = new Map<number, number>();
|
|
90
76
|
|
|
91
77
|
public get isSubscribed() {
|
|
92
78
|
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
@@ -96,91 +82,137 @@ export class ClearingHouse {
|
|
|
96
82
|
this._isSubscribed = val;
|
|
97
83
|
}
|
|
98
84
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
): ClearingHouse {
|
|
113
|
-
const config = getWebSocketClearingHouseConfig(
|
|
114
|
-
connection,
|
|
115
|
-
wallet,
|
|
116
|
-
clearingHouseProgramId,
|
|
117
|
-
opts
|
|
85
|
+
public constructor(config: ClearingHouseConfig) {
|
|
86
|
+
this.connection = config.connection;
|
|
87
|
+
this.wallet = config.wallet;
|
|
88
|
+
this.opts = config.opts || AnchorProvider.defaultOptions();
|
|
89
|
+
this.provider = new AnchorProvider(
|
|
90
|
+
config.connection,
|
|
91
|
+
config.wallet,
|
|
92
|
+
this.opts
|
|
93
|
+
);
|
|
94
|
+
this.program = new Program(
|
|
95
|
+
clearingHouseIDL as Idl,
|
|
96
|
+
config.programID,
|
|
97
|
+
this.provider
|
|
118
98
|
);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
this.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
99
|
+
|
|
100
|
+
const userIds = config.userIds ?? [0];
|
|
101
|
+
this.activeUserId = config.activeUserId ?? userIds[0];
|
|
102
|
+
this.userAccountSubscriptionConfig =
|
|
103
|
+
config.accountSubscription?.type === 'polling'
|
|
104
|
+
? {
|
|
105
|
+
type: 'polling',
|
|
106
|
+
accountLoader: config.accountSubscription.accountLoader,
|
|
107
|
+
}
|
|
108
|
+
: {
|
|
109
|
+
type: 'websocket',
|
|
110
|
+
};
|
|
111
|
+
this.createUsers(userIds, this.userAccountSubscriptionConfig);
|
|
112
|
+
|
|
113
|
+
let marketIndexes = config.marketIndexes;
|
|
114
|
+
let bankIndexes = config.bankIndexes;
|
|
115
|
+
let oracleInfos = config.oracleInfos;
|
|
116
|
+
if (config.env) {
|
|
117
|
+
const {
|
|
118
|
+
marketIndexes: envMarketIndexes,
|
|
119
|
+
bankIndexes: envBankIndexes,
|
|
120
|
+
oracleInfos: envOralceInfos,
|
|
121
|
+
} = getMarketsBanksAndOraclesForSubscription(config.env);
|
|
122
|
+
marketIndexes = marketIndexes ? marketIndexes : envMarketIndexes;
|
|
123
|
+
bankIndexes = bankIndexes ? bankIndexes : envBankIndexes;
|
|
124
|
+
oracleInfos = oracleInfos ? oracleInfos : envOralceInfos;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (config.accountSubscription?.type === 'polling') {
|
|
128
|
+
this.accountSubscriber = new PollingClearingHouseAccountSubscriber(
|
|
129
|
+
this.program,
|
|
130
|
+
config.accountSubscription.accountLoader,
|
|
131
|
+
marketIndexes ?? [],
|
|
132
|
+
bankIndexes ?? [],
|
|
133
|
+
oracleInfos ?? []
|
|
134
|
+
);
|
|
135
|
+
} else {
|
|
136
|
+
this.accountSubscriber = new WebSocketClearingHouseAccountSubscriber(
|
|
137
|
+
this.program,
|
|
138
|
+
config.marketIndexes ?? [],
|
|
139
|
+
config.bankIndexes ?? [],
|
|
140
|
+
config.oracleInfos ?? []
|
|
141
|
+
);
|
|
142
|
+
}
|
|
135
143
|
this.eventEmitter = this.accountSubscriber.eventEmitter;
|
|
136
|
-
this.txSender =
|
|
144
|
+
this.txSender = new RetryTxSender(
|
|
145
|
+
this.provider,
|
|
146
|
+
config.txSenderConfig?.timeout,
|
|
147
|
+
config.txSenderConfig?.retrySleep,
|
|
148
|
+
config.txSenderConfig?.additionalConnections
|
|
149
|
+
);
|
|
137
150
|
}
|
|
138
151
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
createUsers(
|
|
153
|
+
userIds: number[],
|
|
154
|
+
accountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig
|
|
155
|
+
): void {
|
|
156
|
+
for (const userId of userIds) {
|
|
157
|
+
const user = this.createUser(userId, accountSubscriptionConfig);
|
|
158
|
+
this.users.set(userId, user);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
createUser(
|
|
163
|
+
userId: number,
|
|
164
|
+
accountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig
|
|
165
|
+
): ClearingHouseUser {
|
|
166
|
+
const userAccountPublicKey = getUserAccountPublicKeySync(
|
|
167
|
+
this.program.programId,
|
|
168
|
+
this.wallet.publicKey,
|
|
169
|
+
userId
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
return new ClearingHouseUser({
|
|
173
|
+
clearingHouse: this,
|
|
174
|
+
userAccountPublicKey,
|
|
175
|
+
accountSubscription: accountSubscriptionConfig,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public async subscribe(): Promise<boolean> {
|
|
180
|
+
const subscribePromises = this.subscribeUsers().concat(
|
|
181
|
+
this.accountSubscriber.subscribe()
|
|
182
|
+
);
|
|
183
|
+
this.isSubscribed = (await Promise.all(subscribePromises)).reduce(
|
|
184
|
+
(success, prevSuccess) => success && prevSuccess
|
|
149
185
|
);
|
|
150
186
|
return this.isSubscribed;
|
|
151
187
|
}
|
|
152
188
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
* @returns Promise<boolean> : SubscriptionSuccess
|
|
156
|
-
*/
|
|
157
|
-
public async subscribeToAll(): Promise<boolean> {
|
|
158
|
-
return this.subscribe([
|
|
159
|
-
'curveHistoryAccount',
|
|
160
|
-
'depositHistoryAccount',
|
|
161
|
-
'fundingPaymentHistoryAccount',
|
|
162
|
-
'fundingRateHistoryAccount',
|
|
163
|
-
'liquidationHistoryAccount',
|
|
164
|
-
'tradeHistoryAccount',
|
|
165
|
-
'orderHistoryAccount',
|
|
166
|
-
]);
|
|
189
|
+
subscribeUsers(): Promise<boolean>[] {
|
|
190
|
+
return [...this.users.values()].map((user) => user.subscribe());
|
|
167
191
|
}
|
|
168
192
|
|
|
169
193
|
/**
|
|
170
194
|
* Forces the accountSubscriber to fetch account updates from rpc
|
|
171
195
|
*/
|
|
172
196
|
public async fetchAccounts(): Promise<void> {
|
|
173
|
-
await
|
|
197
|
+
await Promise.all(
|
|
198
|
+
[...this.users.values()]
|
|
199
|
+
.map((user) => user.fetchAccounts())
|
|
200
|
+
.concat(this.accountSubscriber.fetch())
|
|
201
|
+
);
|
|
174
202
|
}
|
|
175
203
|
|
|
176
|
-
/**
|
|
177
|
-
* Unsubscribe from all currently subscribed state accounts
|
|
178
|
-
*/
|
|
179
204
|
public async unsubscribe(): Promise<void> {
|
|
180
|
-
|
|
205
|
+
const unsubscribePromises = this.unsubscribeUsers().concat(
|
|
206
|
+
this.accountSubscriber.unsubscribe()
|
|
207
|
+
);
|
|
208
|
+
await Promise.all(unsubscribePromises);
|
|
181
209
|
this.isSubscribed = false;
|
|
182
210
|
}
|
|
183
211
|
|
|
212
|
+
unsubscribeUsers(): Promise<void>[] {
|
|
213
|
+
return [...this.users.values()].map((user) => user.unsubscribe());
|
|
214
|
+
}
|
|
215
|
+
|
|
184
216
|
statePublicKey?: PublicKey;
|
|
185
217
|
public async getStatePublicKey(): Promise<PublicKey> {
|
|
186
218
|
if (this.statePublicKey) {
|
|
@@ -193,75 +225,47 @@ export class ClearingHouse {
|
|
|
193
225
|
}
|
|
194
226
|
|
|
195
227
|
public getStateAccount(): StateAccount {
|
|
196
|
-
return this.accountSubscriber.
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
public async getSettlementAccount(): Promise<SettlementStateAccount> {
|
|
200
|
-
// @ts-ignore
|
|
201
|
-
return await this.program.account.settlementState.fetch(
|
|
202
|
-
await getSettlementStatePublicKey(this.program.programId)
|
|
203
|
-
);
|
|
228
|
+
return this.accountSubscriber.getStateAccountAndSlot().data;
|
|
204
229
|
}
|
|
205
230
|
|
|
206
|
-
public
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
public getMarket(marketIndex: BN | number): Market {
|
|
211
|
-
if (marketIndex instanceof BN) {
|
|
212
|
-
marketIndex = marketIndex.toNumber();
|
|
213
|
-
}
|
|
214
|
-
return this.getMarketsAccount().markets[marketIndex];
|
|
231
|
+
public getMarketAccount(marketIndex: BN | number): MarketAccount | undefined {
|
|
232
|
+
marketIndex = marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
|
|
233
|
+
return this.accountSubscriber.getMarketAccountAndSlot(marketIndex)?.data;
|
|
215
234
|
}
|
|
216
235
|
|
|
217
|
-
public
|
|
218
|
-
return this.accountSubscriber
|
|
236
|
+
public getMarketAccounts(): MarketAccount[] {
|
|
237
|
+
return this.accountSubscriber
|
|
238
|
+
.getMarketAccountsAndSlots()
|
|
239
|
+
.map((value) => value.data);
|
|
219
240
|
}
|
|
220
241
|
|
|
221
|
-
public
|
|
222
|
-
|
|
242
|
+
public getBankAccount(bankIndex: BN | number): BankAccount | undefined {
|
|
243
|
+
bankIndex = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
|
|
244
|
+
return this.accountSubscriber.getBankAccountAndSlot(bankIndex).data;
|
|
223
245
|
}
|
|
224
246
|
|
|
225
|
-
public
|
|
226
|
-
return this.accountSubscriber.
|
|
247
|
+
public getQuoteAssetBankAccount(): BankAccount {
|
|
248
|
+
return this.accountSubscriber.getBankAccountAndSlot(QUOTE_ASSET_BANK_INDEX)
|
|
249
|
+
.data;
|
|
227
250
|
}
|
|
228
251
|
|
|
229
|
-
public
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
public getDepositHistoryAccount(): DepositHistoryAccount {
|
|
234
|
-
return this.accountSubscriber.getDepositHistoryAccount();
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
public getCurveHistoryAccount(): ExtendedCurveHistoryAccount {
|
|
238
|
-
return this.accountSubscriber.getCurveHistoryAccount();
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
public getOrderHistoryAccount(): OrderHistoryAccount {
|
|
242
|
-
return this.accountSubscriber.getOrderHistoryAccount();
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
orderStatePublicKey?: PublicKey;
|
|
246
|
-
public async getOrderStatePublicKey(): Promise<PublicKey> {
|
|
247
|
-
if (this.orderStatePublicKey) {
|
|
248
|
-
return this.orderStatePublicKey;
|
|
249
|
-
}
|
|
250
|
-
this.orderStatePublicKey = await getOrderStateAccountPublicKey(
|
|
251
|
-
this.program.programId
|
|
252
|
-
);
|
|
253
|
-
return this.orderStatePublicKey;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
public getOrderStateAccount(): OrderStateAccount {
|
|
257
|
-
return this.accountSubscriber.getOrderStateAccount();
|
|
252
|
+
public getOraclePriceDataAndSlot(
|
|
253
|
+
oraclePublicKey: PublicKey
|
|
254
|
+
): DataAndSlot<OraclePriceData> | undefined {
|
|
255
|
+
return this.accountSubscriber.getOraclePriceDataAndSlot(oraclePublicKey);
|
|
258
256
|
}
|
|
259
257
|
|
|
260
258
|
/**
|
|
261
259
|
* Update the wallet to use for clearing house transactions and linked user account
|
|
262
260
|
* @param newWallet
|
|
261
|
+
* @param userIds
|
|
262
|
+
* @param activeUserId
|
|
263
263
|
*/
|
|
264
|
-
public updateWallet(
|
|
264
|
+
public async updateWallet(
|
|
265
|
+
newWallet: IWallet,
|
|
266
|
+
userIds = [0],
|
|
267
|
+
activeUserId = 0
|
|
268
|
+
): Promise<void> {
|
|
265
269
|
const newProvider = new AnchorProvider(
|
|
266
270
|
this.connection,
|
|
267
271
|
newWallet,
|
|
@@ -279,257 +283,358 @@ export class ClearingHouse {
|
|
|
279
283
|
this.wallet = newWallet;
|
|
280
284
|
this.provider = newProvider;
|
|
281
285
|
this.program = newProgram;
|
|
282
|
-
this.userAccountPublicKey = undefined;
|
|
283
|
-
this.userAccount = undefined;
|
|
284
|
-
this.userOrdersAccountPublicKey = undefined;
|
|
285
|
-
this.userOrdersExist = undefined;
|
|
286
|
-
}
|
|
287
286
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
] = await this.getInitializeUserInstructions();
|
|
287
|
+
if (this.isSubscribed) {
|
|
288
|
+
await Promise.all(this.unsubscribeUsers());
|
|
289
|
+
}
|
|
290
|
+
this.users.clear();
|
|
291
|
+
this.createUsers(userIds, this.userAccountSubscriptionConfig);
|
|
292
|
+
if (this.isSubscribed) {
|
|
293
|
+
await Promise.all(this.subscribeUsers());
|
|
294
|
+
}
|
|
297
295
|
|
|
298
|
-
|
|
299
|
-
.add(initializeUserAccountIx)
|
|
300
|
-
.add(initializeUserOrdersAccountIx);
|
|
301
|
-
const txSig = await this.txSender.send(
|
|
302
|
-
tx,
|
|
303
|
-
[userPositionsAccount],
|
|
304
|
-
this.opts
|
|
305
|
-
);
|
|
306
|
-
return [txSig, userAccountPublicKey];
|
|
296
|
+
this.activeUserId = activeUserId;
|
|
307
297
|
}
|
|
308
298
|
|
|
309
|
-
async
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
const [userAccountPublicKey, userAccountNonce] =
|
|
313
|
-
await getUserAccountPublicKeyAndNonce(
|
|
314
|
-
this.program.programId,
|
|
315
|
-
this.wallet.publicKey
|
|
316
|
-
);
|
|
317
|
-
|
|
318
|
-
const remainingAccounts = [];
|
|
319
|
-
const optionalAccounts = {
|
|
320
|
-
whitelistToken: false,
|
|
321
|
-
};
|
|
299
|
+
public async switchActiveUser(userId: number): Promise<void> {
|
|
300
|
+
this.activeUserId = userId;
|
|
301
|
+
}
|
|
322
302
|
|
|
323
|
-
|
|
324
|
-
if (
|
|
325
|
-
|
|
326
|
-
const associatedTokenPublicKey = await Token.getAssociatedTokenAddress(
|
|
327
|
-
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
328
|
-
TOKEN_PROGRAM_ID,
|
|
329
|
-
state.whitelistMint,
|
|
330
|
-
this.wallet.publicKey
|
|
331
|
-
);
|
|
332
|
-
remainingAccounts.push({
|
|
333
|
-
pubkey: associatedTokenPublicKey,
|
|
334
|
-
isWritable: false,
|
|
335
|
-
isSigner: false,
|
|
336
|
-
});
|
|
303
|
+
public async addUser(userId: number): Promise<void> {
|
|
304
|
+
if (this.users.has(userId)) {
|
|
305
|
+
return;
|
|
337
306
|
}
|
|
338
307
|
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
optionalAccounts,
|
|
344
|
-
{
|
|
345
|
-
accounts: {
|
|
346
|
-
user: userAccountPublicKey,
|
|
347
|
-
authority: this.wallet.publicKey,
|
|
348
|
-
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
349
|
-
systemProgram: anchor.web3.SystemProgram.programId,
|
|
350
|
-
userPositions: userPositions.publicKey,
|
|
351
|
-
state: await this.getStatePublicKey(),
|
|
352
|
-
},
|
|
353
|
-
remainingAccounts: remainingAccounts,
|
|
354
|
-
}
|
|
355
|
-
);
|
|
308
|
+
const user = this.createUser(userId, this.userAccountSubscriptionConfig);
|
|
309
|
+
await user.subscribe();
|
|
310
|
+
this.users.set(userId, user);
|
|
311
|
+
}
|
|
356
312
|
|
|
357
|
-
|
|
358
|
-
|
|
313
|
+
public async initializeUserAccount(
|
|
314
|
+
userId = 0,
|
|
315
|
+
name = DEFAULT_USER_NAME
|
|
316
|
+
): Promise<[TransactionSignature, PublicKey]> {
|
|
317
|
+
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
318
|
+
await this.getInitializeUserInstructions(userId, name);
|
|
359
319
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
initializeUserAccountIx,
|
|
364
|
-
initializeUserOrdersAccountIx,
|
|
365
|
-
];
|
|
320
|
+
const tx = new Transaction().add(initializeUserAccountIx);
|
|
321
|
+
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
322
|
+
return [txSig, userAccountPublicKey];
|
|
366
323
|
}
|
|
367
324
|
|
|
368
|
-
async
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
this.program.programId,
|
|
378
|
-
userAccountPublicKey
|
|
379
|
-
);
|
|
325
|
+
async getInitializeUserInstructions(
|
|
326
|
+
userId = 0,
|
|
327
|
+
name = DEFAULT_USER_NAME
|
|
328
|
+
): Promise<[PublicKey, TransactionInstruction]> {
|
|
329
|
+
const userAccountPublicKey = await getUserAccountPublicKey(
|
|
330
|
+
this.program.programId,
|
|
331
|
+
this.wallet.publicKey,
|
|
332
|
+
userId
|
|
333
|
+
);
|
|
380
334
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
{
|
|
335
|
+
const nameBuffer = encodeName(name);
|
|
336
|
+
const initializeUserAccountIx =
|
|
337
|
+
await this.program.instruction.initializeUser(userId, nameBuffer, {
|
|
384
338
|
accounts: {
|
|
385
339
|
user: userAccountPublicKey,
|
|
386
340
|
authority: this.wallet.publicKey,
|
|
341
|
+
payer: this.wallet.publicKey,
|
|
387
342
|
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
388
343
|
systemProgram: anchor.web3.SystemProgram.programId,
|
|
389
|
-
userOrders: userOrdersAccountPublicKey,
|
|
390
344
|
state: await this.getStatePublicKey(),
|
|
391
345
|
},
|
|
392
|
-
}
|
|
393
|
-
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
return [userAccountPublicKey, initializeUserAccountIx];
|
|
394
349
|
}
|
|
395
350
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
*/
|
|
401
|
-
public async getUserAccountPublicKey(): Promise<PublicKey> {
|
|
402
|
-
if (this.userAccountPublicKey) {
|
|
403
|
-
return this.userAccountPublicKey;
|
|
351
|
+
public getUser(userId?: number): ClearingHouseUser {
|
|
352
|
+
userId = userId ?? this.activeUserId;
|
|
353
|
+
if (!this.users.has(userId)) {
|
|
354
|
+
throw new Error(`Clearing House has no user for user id ${userId}`);
|
|
404
355
|
}
|
|
356
|
+
return this.users.get(userId);
|
|
357
|
+
}
|
|
405
358
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
this.wallet.publicKey
|
|
409
|
-
);
|
|
410
|
-
return this.userAccountPublicKey;
|
|
359
|
+
public getUsers(): ClearingHouseUser[] {
|
|
360
|
+
return [...this.users.values()];
|
|
411
361
|
}
|
|
412
362
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
return this.userAccount;
|
|
417
|
-
}
|
|
363
|
+
public async getUserAccountPublicKey(): Promise<PublicKey> {
|
|
364
|
+
return this.getUser().userAccountPublicKey;
|
|
365
|
+
}
|
|
418
366
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
)) as UserAccount;
|
|
422
|
-
return this.userAccount;
|
|
367
|
+
public getUserAccount(userId?: number): UserAccount | undefined {
|
|
368
|
+
return this.getUser(userId).getUserAccount();
|
|
423
369
|
}
|
|
424
370
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
public async getUserOrdersAccountPublicKey(): Promise<PublicKey> {
|
|
431
|
-
if (this.userOrdersAccountPublicKey) {
|
|
432
|
-
return this.userOrdersAccountPublicKey;
|
|
433
|
-
}
|
|
371
|
+
public getUserAccountAndSlot(
|
|
372
|
+
userId?: number
|
|
373
|
+
): DataAndSlot<UserAccount> | undefined {
|
|
374
|
+
return this.getUser(userId).getUserAccountAndSlot();
|
|
375
|
+
}
|
|
434
376
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
377
|
+
public getUserBankBalance(
|
|
378
|
+
bankIndex: number | BN
|
|
379
|
+
): UserBankBalance | undefined {
|
|
380
|
+
const bankIndexBN = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
|
|
381
|
+
return this.getUserAccount().bankBalances.find((bankBalance) =>
|
|
382
|
+
bankBalance.bankIndex.eq(bankIndexBN)
|
|
438
383
|
);
|
|
439
|
-
return this.userOrdersAccountPublicKey;
|
|
440
384
|
}
|
|
441
385
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
386
|
+
public getQuoteAssetTokenAmount(): BN {
|
|
387
|
+
const bank = this.getBankAccount(QUOTE_ASSET_BANK_INDEX);
|
|
388
|
+
const userBankBalance = this.getUserBankBalance(QUOTE_ASSET_BANK_INDEX);
|
|
389
|
+
return getTokenAmount(
|
|
390
|
+
userBankBalance.balance,
|
|
391
|
+
bank,
|
|
392
|
+
userBankBalance.balanceType
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
getRemainingAccounts(params: {
|
|
397
|
+
writableMarketIndex?: BN;
|
|
398
|
+
writableBankIndex?: BN;
|
|
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
|
+
);
|
|
446
405
|
}
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
406
|
+
const { data: userAccount, slot: lastUserPositionsSlot } =
|
|
407
|
+
userAccountAndSlot;
|
|
408
|
+
|
|
409
|
+
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
410
|
+
const bankAccountMap = new Map<number, AccountMeta>();
|
|
411
|
+
const marketAccountMap = new Map<number, AccountMeta>();
|
|
412
|
+
for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
|
|
413
|
+
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
414
|
+
// otherwise remove from slot
|
|
415
|
+
if (slot > lastUserPositionsSlot) {
|
|
416
|
+
const marketAccount = this.getMarketAccount(marketIndexNum);
|
|
417
|
+
marketAccountMap.set(marketIndexNum, {
|
|
418
|
+
pubkey: marketAccount.pubkey,
|
|
419
|
+
isSigner: false,
|
|
420
|
+
isWritable: false,
|
|
421
|
+
});
|
|
422
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
423
|
+
pubkey: marketAccount.amm.oracle,
|
|
424
|
+
isSigner: false,
|
|
425
|
+
isWritable: false,
|
|
426
|
+
});
|
|
427
|
+
} else {
|
|
428
|
+
this.marketLastSlotCache.delete(marketIndexNum);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
for (const position of userAccount.positions) {
|
|
433
|
+
if (!positionIsAvailable(position)) {
|
|
434
|
+
const marketIndexNum = position.marketIndex.toNumber();
|
|
435
|
+
const marketAccount = this.getMarketAccount(marketIndexNum);
|
|
436
|
+
marketAccountMap.set(marketIndexNum, {
|
|
437
|
+
pubkey: marketAccount.pubkey,
|
|
438
|
+
isSigner: false,
|
|
439
|
+
// isWritable: false, // TODO
|
|
440
|
+
isWritable: true,
|
|
441
|
+
});
|
|
442
|
+
oracleAccountMap.set(marketAccount.pubkey.toString(), {
|
|
443
|
+
pubkey: marketAccount.amm.oracle,
|
|
444
|
+
isSigner: false,
|
|
445
|
+
isWritable: false,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (params.writableMarketIndex) {
|
|
451
|
+
const marketAccount = this.getMarketAccount(
|
|
452
|
+
params.writableMarketIndex.toNumber()
|
|
450
453
|
);
|
|
454
|
+
marketAccountMap.set(params.writableMarketIndex.toNumber(), {
|
|
455
|
+
pubkey: marketAccount.pubkey,
|
|
456
|
+
isSigner: false,
|
|
457
|
+
isWritable: true,
|
|
458
|
+
});
|
|
459
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
460
|
+
pubkey: marketAccount.amm.oracle,
|
|
461
|
+
isSigner: false,
|
|
462
|
+
isWritable: false,
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
for (const userBankBalance of userAccount.bankBalances) {
|
|
467
|
+
if (!userBankBalance.balance.eq(ZERO)) {
|
|
468
|
+
const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
|
|
469
|
+
bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
|
|
470
|
+
pubkey: bankAccount.pubkey,
|
|
471
|
+
isSigner: false,
|
|
472
|
+
isWritable: false,
|
|
473
|
+
});
|
|
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
|
+
}
|
|
482
|
+
}
|
|
451
483
|
|
|
452
|
-
|
|
453
|
-
|
|
484
|
+
if (params.writableBankIndex) {
|
|
485
|
+
const bankAccount = this.getBankAccount(params.writableBankIndex);
|
|
486
|
+
bankAccountMap.set(params.writableBankIndex.toNumber(), {
|
|
487
|
+
pubkey: bankAccount.pubkey,
|
|
488
|
+
isSigner: false,
|
|
489
|
+
isWritable: true,
|
|
490
|
+
});
|
|
491
|
+
if (!bankAccount.bankIndex.eq(ZERO)) {
|
|
492
|
+
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
493
|
+
pubkey: bankAccount.oracle,
|
|
494
|
+
isSigner: false,
|
|
495
|
+
isWritable: false,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return [
|
|
501
|
+
...oracleAccountMap.values(),
|
|
502
|
+
...bankAccountMap.values(),
|
|
503
|
+
...marketAccountMap.values(),
|
|
504
|
+
];
|
|
454
505
|
}
|
|
455
506
|
|
|
456
|
-
public
|
|
507
|
+
public getOrder(orderId: BN | number): Order | undefined {
|
|
508
|
+
const orderIdBN = orderId instanceof BN ? orderId : new BN(orderId);
|
|
509
|
+
return this.getUserAccount()?.orders.find((order) =>
|
|
510
|
+
order.orderId.eq(orderIdBN)
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
public getOrderByUserId(userOrderId: number): Order | undefined {
|
|
515
|
+
return this.getUserAccount()?.orders.find(
|
|
516
|
+
(order) => order.userOrderId === userOrderId
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
public async deposit(
|
|
457
521
|
amount: BN,
|
|
522
|
+
bankIndex: BN,
|
|
458
523
|
collateralAccountPublicKey: PublicKey,
|
|
459
|
-
|
|
524
|
+
userId?: number,
|
|
525
|
+
reduceOnly = false
|
|
460
526
|
): Promise<TransactionSignature> {
|
|
461
|
-
const depositCollateralIx = await this.
|
|
527
|
+
const depositCollateralIx = await this.getDepositInstruction(
|
|
462
528
|
amount,
|
|
529
|
+
bankIndex,
|
|
463
530
|
collateralAccountPublicKey,
|
|
464
|
-
|
|
531
|
+
userId,
|
|
532
|
+
reduceOnly,
|
|
533
|
+
true
|
|
465
534
|
);
|
|
466
535
|
|
|
467
536
|
const tx = new Transaction().add(depositCollateralIx);
|
|
468
537
|
|
|
469
|
-
|
|
538
|
+
const { txSig } = await this.txSender.send(tx);
|
|
539
|
+
return txSig;
|
|
470
540
|
}
|
|
471
541
|
|
|
472
|
-
async
|
|
542
|
+
async getDepositInstruction(
|
|
473
543
|
amount: BN,
|
|
474
|
-
|
|
475
|
-
|
|
544
|
+
bankIndex: BN,
|
|
545
|
+
userTokenAccount: PublicKey,
|
|
546
|
+
userId?: number,
|
|
547
|
+
reduceOnly = false,
|
|
548
|
+
userInitialized = true
|
|
476
549
|
): Promise<TransactionInstruction> {
|
|
477
|
-
const userAccountPublicKey =
|
|
478
|
-
|
|
479
|
-
|
|
550
|
+
const userAccountPublicKey = userId
|
|
551
|
+
? await getUserAccountPublicKey(
|
|
552
|
+
this.program.programId,
|
|
553
|
+
this.wallet.publicKey,
|
|
554
|
+
userId
|
|
555
|
+
)
|
|
556
|
+
: await this.getUserAccountPublicKey();
|
|
557
|
+
|
|
558
|
+
let remainingAccounts = [];
|
|
559
|
+
if (userInitialized) {
|
|
560
|
+
remainingAccounts = this.getRemainingAccounts({
|
|
561
|
+
writableBankIndex: bankIndex,
|
|
562
|
+
});
|
|
563
|
+
} else {
|
|
564
|
+
remainingAccounts = [
|
|
565
|
+
{
|
|
566
|
+
pubkey: this.getBankAccount(bankIndex).pubkey,
|
|
567
|
+
isSigner: false,
|
|
568
|
+
isWritable: true,
|
|
569
|
+
},
|
|
570
|
+
];
|
|
480
571
|
}
|
|
481
572
|
|
|
482
|
-
const
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
573
|
+
const bank = this.getBankAccount(bankIndex);
|
|
574
|
+
|
|
575
|
+
return await this.program.instruction.deposit(
|
|
576
|
+
bankIndex,
|
|
577
|
+
amount,
|
|
578
|
+
reduceOnly,
|
|
579
|
+
{
|
|
580
|
+
accounts: {
|
|
581
|
+
state: await this.getStatePublicKey(),
|
|
582
|
+
bank: bank.pubkey,
|
|
583
|
+
bankVault: bank.vault,
|
|
584
|
+
user: userAccountPublicKey,
|
|
585
|
+
userTokenAccount: userTokenAccount,
|
|
586
|
+
authority: this.wallet.publicKey,
|
|
587
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
588
|
+
},
|
|
589
|
+
remainingAccounts,
|
|
590
|
+
}
|
|
591
|
+
);
|
|
497
592
|
}
|
|
498
593
|
|
|
499
594
|
/**
|
|
500
595
|
* Creates the Clearing House User account for a user, and deposits some initial collateral
|
|
596
|
+
* @param userId
|
|
597
|
+
* @param name
|
|
501
598
|
* @param amount
|
|
502
|
-
* @param
|
|
599
|
+
* @param userTokenAccount
|
|
600
|
+
* @param fromUserId
|
|
503
601
|
* @returns
|
|
504
602
|
*/
|
|
505
603
|
public async initializeUserAccountAndDepositCollateral(
|
|
506
604
|
amount: BN,
|
|
507
|
-
|
|
605
|
+
userTokenAccount: PublicKey,
|
|
606
|
+
bankIndex = new BN(0),
|
|
607
|
+
userId = 0,
|
|
608
|
+
name = DEFAULT_USER_NAME,
|
|
609
|
+
fromUserId?: number
|
|
508
610
|
): Promise<[TransactionSignature, PublicKey]> {
|
|
509
|
-
const [
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
611
|
+
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
612
|
+
await this.getInitializeUserInstructions(userId, name);
|
|
613
|
+
|
|
614
|
+
const depositCollateralIx =
|
|
615
|
+
fromUserId != null
|
|
616
|
+
? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
|
|
617
|
+
: await this.getDepositInstruction(
|
|
618
|
+
amount,
|
|
619
|
+
bankIndex,
|
|
620
|
+
userTokenAccount,
|
|
621
|
+
userId,
|
|
622
|
+
false,
|
|
623
|
+
false
|
|
624
|
+
);
|
|
521
625
|
|
|
522
626
|
const tx = new Transaction()
|
|
523
627
|
.add(initializeUserAccountIx)
|
|
524
|
-
.add(initializeUserOrdersAccountIx)
|
|
525
628
|
.add(depositCollateralIx);
|
|
526
629
|
|
|
527
|
-
const txSig = await this.txSender.send(tx, [
|
|
630
|
+
const { txSig } = await this.txSender.send(tx, []);
|
|
528
631
|
|
|
529
632
|
return [txSig, userAccountPublicKey];
|
|
530
633
|
}
|
|
531
634
|
|
|
532
635
|
public async initializeUserAccountForDevnet(
|
|
636
|
+
userId = 0,
|
|
637
|
+
name = DEFAULT_USER_NAME,
|
|
533
638
|
mockUSDCFaucet: MockUSDCFaucet,
|
|
534
639
|
amount: BN
|
|
535
640
|
): Promise<[TransactionSignature, PublicKey]> {
|
|
@@ -539,423 +644,356 @@ export class ClearingHouse {
|
|
|
539
644
|
amount
|
|
540
645
|
);
|
|
541
646
|
|
|
542
|
-
const [
|
|
543
|
-
|
|
544
|
-
userAccountPublicKey,
|
|
545
|
-
initializeUserAccountIx,
|
|
546
|
-
initializeUserOrdersAccountIx,
|
|
547
|
-
] = await this.getInitializeUserInstructions();
|
|
647
|
+
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
648
|
+
await this.getInitializeUserInstructions(userId, name);
|
|
548
649
|
|
|
549
|
-
const depositCollateralIx = await this.
|
|
650
|
+
const depositCollateralIx = await this.getDepositInstruction(
|
|
550
651
|
amount,
|
|
652
|
+
new BN(0),
|
|
551
653
|
associateTokenPublicKey,
|
|
552
|
-
|
|
654
|
+
userId,
|
|
655
|
+
false,
|
|
656
|
+
false
|
|
553
657
|
);
|
|
554
658
|
|
|
555
659
|
const tx = new Transaction()
|
|
556
660
|
.add(createAssociatedAccountIx)
|
|
557
661
|
.add(mintToIx)
|
|
558
662
|
.add(initializeUserAccountIx)
|
|
559
|
-
.add(initializeUserOrdersAccountIx)
|
|
560
663
|
.add(depositCollateralIx);
|
|
561
664
|
|
|
562
|
-
const txSig = await this.program.provider.sendAndConfirm(tx, [
|
|
563
|
-
userPositionsAccount,
|
|
564
|
-
]);
|
|
665
|
+
const txSig = await this.program.provider.sendAndConfirm(tx, []);
|
|
565
666
|
|
|
566
667
|
return [txSig, userAccountPublicKey];
|
|
567
668
|
}
|
|
568
669
|
|
|
569
|
-
public async
|
|
670
|
+
public async withdraw(
|
|
570
671
|
amount: BN,
|
|
571
|
-
|
|
672
|
+
bankIndex: BN,
|
|
673
|
+
userTokenAccount: PublicKey,
|
|
674
|
+
reduceOnly = false
|
|
572
675
|
): Promise<TransactionSignature> {
|
|
573
|
-
|
|
676
|
+
const { txSig } = await this.txSender.send(
|
|
574
677
|
wrapInTx(
|
|
575
|
-
await this.
|
|
678
|
+
await this.getWithdrawIx(
|
|
679
|
+
amount,
|
|
680
|
+
bankIndex,
|
|
681
|
+
userTokenAccount,
|
|
682
|
+
reduceOnly
|
|
683
|
+
)
|
|
576
684
|
),
|
|
577
685
|
[],
|
|
578
686
|
this.opts
|
|
579
687
|
);
|
|
688
|
+
return txSig;
|
|
580
689
|
}
|
|
581
690
|
|
|
582
|
-
public async
|
|
691
|
+
public async getWithdrawIx(
|
|
583
692
|
amount: BN,
|
|
584
|
-
|
|
693
|
+
bankIndex: BN,
|
|
694
|
+
userTokenAccount: PublicKey,
|
|
695
|
+
reduceOnly = false
|
|
585
696
|
): Promise<TransactionInstruction> {
|
|
586
697
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
587
|
-
const user: any = await this.program.account.user.fetch(
|
|
588
|
-
userAccountPublicKey
|
|
589
|
-
);
|
|
590
698
|
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
accounts: {
|
|
594
|
-
state: await this.getStatePublicKey(),
|
|
595
|
-
user: userAccountPublicKey,
|
|
596
|
-
collateralVault: state.collateralVault,
|
|
597
|
-
collateralVaultAuthority: state.collateralVaultAuthority,
|
|
598
|
-
insuranceVault: state.insuranceVault,
|
|
599
|
-
insuranceVaultAuthority: state.insuranceVaultAuthority,
|
|
600
|
-
userCollateralAccount: collateralAccountPublicKey,
|
|
601
|
-
authority: this.wallet.publicKey,
|
|
602
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
|
603
|
-
markets: state.markets,
|
|
604
|
-
userPositions: user.positions,
|
|
605
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
606
|
-
depositHistory: state.depositHistory,
|
|
607
|
-
},
|
|
699
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
700
|
+
writableBankIndex: bankIndex,
|
|
608
701
|
});
|
|
702
|
+
|
|
703
|
+
const bank = this.getBankAccount(bankIndex);
|
|
704
|
+
|
|
705
|
+
return await this.program.instruction.withdraw(
|
|
706
|
+
bankIndex,
|
|
707
|
+
amount,
|
|
708
|
+
reduceOnly,
|
|
709
|
+
{
|
|
710
|
+
accounts: {
|
|
711
|
+
state: await this.getStatePublicKey(),
|
|
712
|
+
bank: bank.pubkey,
|
|
713
|
+
bankVault: bank.vault,
|
|
714
|
+
bankVaultAuthority: bank.vaultAuthority,
|
|
715
|
+
user: userAccountPublicKey,
|
|
716
|
+
userTokenAccount: userTokenAccount,
|
|
717
|
+
authority: this.wallet.publicKey,
|
|
718
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
719
|
+
},
|
|
720
|
+
remainingAccounts,
|
|
721
|
+
}
|
|
722
|
+
);
|
|
609
723
|
}
|
|
610
724
|
|
|
611
|
-
public async
|
|
612
|
-
direction: PositionDirection,
|
|
725
|
+
public async transferDeposit(
|
|
613
726
|
amount: BN,
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
referrer?: PublicKey
|
|
727
|
+
bankIndex: BN,
|
|
728
|
+
fromUserId: number,
|
|
729
|
+
toUserId: number
|
|
618
730
|
): Promise<TransactionSignature> {
|
|
619
|
-
|
|
731
|
+
const { txSig } = await this.txSender.send(
|
|
620
732
|
wrapInTx(
|
|
621
|
-
await this.
|
|
622
|
-
direction,
|
|
623
|
-
amount,
|
|
624
|
-
marketIndex,
|
|
625
|
-
limitPrice,
|
|
626
|
-
discountToken,
|
|
627
|
-
referrer
|
|
628
|
-
)
|
|
733
|
+
await this.getTransferDepositIx(amount, bankIndex, fromUserId, toUserId)
|
|
629
734
|
),
|
|
630
735
|
[],
|
|
631
736
|
this.opts
|
|
632
737
|
);
|
|
738
|
+
return txSig;
|
|
633
739
|
}
|
|
634
740
|
|
|
635
|
-
public async
|
|
636
|
-
direction: PositionDirection,
|
|
741
|
+
public async getTransferDepositIx(
|
|
637
742
|
amount: BN,
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
referrer?: PublicKey
|
|
743
|
+
bankIndex: BN,
|
|
744
|
+
fromUserId: number,
|
|
745
|
+
toUserId: number
|
|
642
746
|
): Promise<TransactionInstruction> {
|
|
643
|
-
const
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
747
|
+
const fromUser = await getUserAccountPublicKey(
|
|
748
|
+
this.program.programId,
|
|
749
|
+
this.wallet.publicKey,
|
|
750
|
+
fromUserId
|
|
751
|
+
);
|
|
752
|
+
const toUser = await getUserAccountPublicKey(
|
|
753
|
+
this.program.programId,
|
|
754
|
+
this.wallet.publicKey,
|
|
755
|
+
toUserId
|
|
756
|
+
);
|
|
649
757
|
|
|
650
|
-
const
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
};
|
|
654
|
-
const remainingAccounts = [];
|
|
655
|
-
if (discountToken) {
|
|
656
|
-
optionalAccounts.discountToken = true;
|
|
657
|
-
remainingAccounts.push({
|
|
658
|
-
pubkey: discountToken,
|
|
659
|
-
isWritable: false,
|
|
660
|
-
isSigner: false,
|
|
661
|
-
});
|
|
662
|
-
}
|
|
663
|
-
if (referrer) {
|
|
664
|
-
optionalAccounts.referrer = true;
|
|
665
|
-
remainingAccounts.push({
|
|
666
|
-
pubkey: referrer,
|
|
667
|
-
isWritable: true,
|
|
668
|
-
isSigner: false,
|
|
669
|
-
});
|
|
670
|
-
}
|
|
758
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
759
|
+
writableBankIndex: bankIndex,
|
|
760
|
+
});
|
|
671
761
|
|
|
672
|
-
|
|
673
|
-
|
|
762
|
+
return await this.program.instruction.transferDeposit(bankIndex, amount, {
|
|
763
|
+
accounts: {
|
|
764
|
+
authority: this.wallet.publicKey,
|
|
765
|
+
fromUser,
|
|
766
|
+
toUser,
|
|
767
|
+
state: await this.getStatePublicKey(),
|
|
768
|
+
},
|
|
769
|
+
remainingAccounts,
|
|
770
|
+
});
|
|
771
|
+
}
|
|
674
772
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
{
|
|
683
|
-
accounts: {
|
|
684
|
-
state: await this.getStatePublicKey(),
|
|
685
|
-
user: userAccountPublicKey,
|
|
686
|
-
authority: this.wallet.publicKey,
|
|
687
|
-
markets: state.markets,
|
|
688
|
-
userPositions: userAccount.positions,
|
|
689
|
-
tradeHistory: state.tradeHistory,
|
|
690
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
691
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
692
|
-
oracle: priceOracle,
|
|
693
|
-
},
|
|
694
|
-
remainingAccounts: remainingAccounts,
|
|
695
|
-
}
|
|
773
|
+
public async updateBankCumulativeInterest(
|
|
774
|
+
bankIndex: BN
|
|
775
|
+
): Promise<TransactionSignature> {
|
|
776
|
+
const { txSig } = await this.txSender.send(
|
|
777
|
+
wrapInTx(await this.updateBankCumulativeInterestIx(bankIndex)),
|
|
778
|
+
[],
|
|
779
|
+
this.opts
|
|
696
780
|
);
|
|
781
|
+
return txSig;
|
|
697
782
|
}
|
|
698
783
|
|
|
699
|
-
public async
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
784
|
+
public async updateBankCumulativeInterestIx(
|
|
785
|
+
bankIndex: BN
|
|
786
|
+
): Promise<TransactionInstruction> {
|
|
787
|
+
const bank = this.getBankAccount(bankIndex);
|
|
788
|
+
return await this.program.instruction.updateBankCumulativeInterest({
|
|
789
|
+
accounts: {
|
|
790
|
+
bank: bank.pubkey,
|
|
791
|
+
},
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
public async openPosition(
|
|
796
|
+
direction: PositionDirection,
|
|
797
|
+
amount: BN,
|
|
798
|
+
marketIndex: BN,
|
|
799
|
+
limitPrice?: BN
|
|
703
800
|
): Promise<TransactionSignature> {
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
801
|
+
return await this.placeAndTake(
|
|
802
|
+
getMarketOrderParams(
|
|
803
|
+
marketIndex,
|
|
804
|
+
direction,
|
|
805
|
+
ZERO,
|
|
806
|
+
amount,
|
|
807
|
+
false,
|
|
808
|
+
limitPrice
|
|
809
|
+
)
|
|
711
810
|
);
|
|
712
|
-
const tx = new Transaction();
|
|
713
|
-
for (const instruction of instructions) {
|
|
714
|
-
tx.add(instruction);
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
return await this.txSender.send(tx, [], this.opts);
|
|
718
811
|
}
|
|
719
812
|
|
|
720
813
|
public async placeOrder(
|
|
721
|
-
orderParams: OrderParams
|
|
722
|
-
discountToken?: PublicKey,
|
|
723
|
-
referrer?: PublicKey
|
|
814
|
+
orderParams: OrderParams
|
|
724
815
|
): Promise<TransactionSignature> {
|
|
725
|
-
|
|
726
|
-
wrapInTx(
|
|
727
|
-
await this.getPlaceOrderIx(orderParams, discountToken, referrer)
|
|
728
|
-
),
|
|
816
|
+
const { txSig, slot } = await this.txSender.send(
|
|
817
|
+
wrapInTx(await this.getPlaceOrderIx(orderParams)),
|
|
729
818
|
[],
|
|
730
819
|
this.opts
|
|
731
820
|
);
|
|
821
|
+
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
822
|
+
return txSig;
|
|
732
823
|
}
|
|
733
824
|
|
|
734
825
|
public async getPlaceOrderIx(
|
|
735
|
-
orderParams: OrderParams
|
|
736
|
-
discountToken?: PublicKey,
|
|
737
|
-
referrer?: PublicKey
|
|
826
|
+
orderParams: OrderParams
|
|
738
827
|
): Promise<TransactionInstruction> {
|
|
739
828
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
740
|
-
const userAccount = await this.getUserAccount();
|
|
741
|
-
|
|
742
|
-
const priceOracle =
|
|
743
|
-
this.getMarketsAccount().markets[orderParams.marketIndex.toNumber()].amm
|
|
744
|
-
.oracle;
|
|
745
829
|
|
|
746
|
-
const
|
|
747
|
-
|
|
748
|
-
if (!discountToken) {
|
|
749
|
-
throw Error(
|
|
750
|
-
'Optional accounts specified discount token but no discount token present'
|
|
751
|
-
);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
remainingAccounts.push({
|
|
755
|
-
pubkey: discountToken,
|
|
756
|
-
isWritable: false,
|
|
757
|
-
isSigner: false,
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
if (orderParams.optionalAccounts.referrer) {
|
|
762
|
-
if (!referrer) {
|
|
763
|
-
throw Error(
|
|
764
|
-
'Optional accounts specified referrer but no referrer present'
|
|
765
|
-
);
|
|
766
|
-
}
|
|
830
|
+
const priceOracle = this.getMarketAccount(orderParams.marketIndex).amm
|
|
831
|
+
.oracle;
|
|
767
832
|
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
isSigner: false,
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
if (!orderParams.oraclePriceOffset.eq(ZERO)) {
|
|
776
|
-
remainingAccounts.push({
|
|
777
|
-
pubkey: priceOracle,
|
|
778
|
-
isWritable: false,
|
|
779
|
-
isSigner: false,
|
|
780
|
-
});
|
|
781
|
-
}
|
|
833
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
834
|
+
writableMarketIndex: orderParams.marketIndex,
|
|
835
|
+
});
|
|
782
836
|
|
|
783
|
-
const state = this.getStateAccount();
|
|
784
|
-
const orderState = this.getOrderStateAccount();
|
|
785
837
|
return await this.program.instruction.placeOrder(orderParams, {
|
|
786
838
|
accounts: {
|
|
787
839
|
state: await this.getStatePublicKey(),
|
|
788
840
|
user: userAccountPublicKey,
|
|
789
841
|
authority: this.wallet.publicKey,
|
|
790
|
-
|
|
791
|
-
userOrders: await this.getUserOrdersAccountPublicKey(),
|
|
792
|
-
userPositions: userAccount.positions,
|
|
793
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
794
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
795
|
-
orderState: await this.getOrderStatePublicKey(),
|
|
796
|
-
orderHistory: orderState.orderHistory,
|
|
842
|
+
oracle: priceOracle,
|
|
797
843
|
},
|
|
798
844
|
remainingAccounts,
|
|
799
845
|
});
|
|
800
846
|
}
|
|
801
847
|
|
|
802
848
|
public async expireOrders(
|
|
803
|
-
userAccountPublicKey: PublicKey
|
|
804
|
-
userOrdersAccountPublicKey: PublicKey
|
|
849
|
+
userAccountPublicKey: PublicKey
|
|
805
850
|
): Promise<TransactionSignature> {
|
|
806
|
-
|
|
807
|
-
wrapInTx(
|
|
808
|
-
await this.getExpireOrdersIx(
|
|
809
|
-
userAccountPublicKey,
|
|
810
|
-
userOrdersAccountPublicKey
|
|
811
|
-
)
|
|
812
|
-
),
|
|
851
|
+
const { txSig } = await this.txSender.send(
|
|
852
|
+
wrapInTx(await this.getExpireOrdersIx(userAccountPublicKey)),
|
|
813
853
|
[],
|
|
814
854
|
this.opts
|
|
815
855
|
);
|
|
856
|
+
return txSig;
|
|
816
857
|
}
|
|
817
858
|
|
|
818
859
|
public async getExpireOrdersIx(
|
|
819
|
-
userAccountPublicKey: PublicKey
|
|
820
|
-
userOrdersAccountPublicKey: PublicKey
|
|
860
|
+
userAccountPublicKey: PublicKey
|
|
821
861
|
): Promise<TransactionInstruction> {
|
|
822
862
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
823
|
-
const userAccount: any = await this.program.account.user.fetch(
|
|
824
|
-
userAccountPublicKey
|
|
825
|
-
);
|
|
826
863
|
|
|
827
|
-
const orderState = this.getOrderStateAccount();
|
|
828
864
|
return await this.program.instruction.expireOrders({
|
|
829
865
|
accounts: {
|
|
830
866
|
state: await this.getStatePublicKey(),
|
|
831
867
|
filler: fillerPublicKey,
|
|
832
868
|
user: userAccountPublicKey,
|
|
833
869
|
authority: this.wallet.publicKey,
|
|
834
|
-
userPositions: userAccount.positions,
|
|
835
|
-
userOrders: userOrdersAccountPublicKey,
|
|
836
|
-
orderState: await this.getOrderStatePublicKey(),
|
|
837
|
-
orderHistory: orderState.orderHistory,
|
|
838
870
|
},
|
|
839
871
|
});
|
|
840
872
|
}
|
|
841
873
|
|
|
842
|
-
public async
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
874
|
+
public async updateAMMs(marketIndexes: BN[]): Promise<TransactionSignature> {
|
|
875
|
+
const { txSig } = await this.txSender.send(
|
|
876
|
+
wrapInTx(await this.getUpdateAMMsIx(marketIndexes)),
|
|
877
|
+
[],
|
|
878
|
+
this.opts
|
|
879
|
+
);
|
|
880
|
+
return txSig;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
public async getUpdateAMMsIx(
|
|
884
|
+
marketIndexes: BN[]
|
|
885
|
+
): Promise<TransactionInstruction> {
|
|
886
|
+
for (let i = marketIndexes.length; i < 5; i++) {
|
|
887
|
+
marketIndexes.push(new BN(100));
|
|
888
|
+
}
|
|
889
|
+
const marketAccountInfos = [];
|
|
890
|
+
const oracleAccountInfos = [];
|
|
891
|
+
for (const marketIndex of marketIndexes) {
|
|
892
|
+
if (!marketIndex.eq(new BN(100))) {
|
|
893
|
+
const market = this.getMarketAccount(marketIndex);
|
|
894
|
+
marketAccountInfos.push({
|
|
895
|
+
pubkey: market.pubkey,
|
|
896
|
+
isWritable: true,
|
|
897
|
+
isSigner: false,
|
|
898
|
+
});
|
|
899
|
+
oracleAccountInfos.push({
|
|
900
|
+
pubkey: market.amm.oracle,
|
|
901
|
+
isWritable: false,
|
|
902
|
+
isSigner: false,
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
const remainingAccounts = oracleAccountInfos.concat(marketAccountInfos);
|
|
907
|
+
|
|
908
|
+
return await this.program.instruction.updateAmms(marketIndexes, {
|
|
909
|
+
accounts: {
|
|
910
|
+
state: await this.getStatePublicKey(),
|
|
911
|
+
authority: this.wallet.publicKey,
|
|
912
|
+
},
|
|
913
|
+
remainingAccounts,
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
public async cancelOrder(orderId: BN): Promise<TransactionSignature> {
|
|
918
|
+
const { txSig } = await this.txSender.send(
|
|
919
|
+
wrapInTx(await this.getCancelOrderIx(orderId)),
|
|
848
920
|
[],
|
|
849
921
|
this.opts
|
|
850
922
|
);
|
|
923
|
+
return txSig;
|
|
851
924
|
}
|
|
852
925
|
|
|
853
|
-
public async getCancelOrderIx(
|
|
854
|
-
orderId: BN,
|
|
855
|
-
oracle?: PublicKey
|
|
856
|
-
): Promise<TransactionInstruction> {
|
|
926
|
+
public async getCancelOrderIx(orderId: BN): Promise<TransactionInstruction> {
|
|
857
927
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
858
|
-
const userAccount = await this.getUserAccount();
|
|
859
928
|
|
|
860
|
-
const
|
|
861
|
-
const
|
|
929
|
+
const order = this.getOrder(orderId);
|
|
930
|
+
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
862
931
|
|
|
863
|
-
const remainingAccounts =
|
|
864
|
-
if (oracle) {
|
|
865
|
-
remainingAccounts.push({
|
|
866
|
-
pubkey: oracle,
|
|
867
|
-
isWritable: false,
|
|
868
|
-
isSigner: false,
|
|
869
|
-
});
|
|
870
|
-
}
|
|
932
|
+
const remainingAccounts = this.getRemainingAccounts({});
|
|
871
933
|
|
|
872
934
|
return await this.program.instruction.cancelOrder(orderId, {
|
|
873
935
|
accounts: {
|
|
874
936
|
state: await this.getStatePublicKey(),
|
|
875
937
|
user: userAccountPublicKey,
|
|
876
938
|
authority: this.wallet.publicKey,
|
|
877
|
-
|
|
878
|
-
userOrders: await this.getUserOrdersAccountPublicKey(),
|
|
879
|
-
userPositions: userAccount.positions,
|
|
880
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
881
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
882
|
-
orderState: await this.getOrderStatePublicKey(),
|
|
883
|
-
orderHistory: orderState.orderHistory,
|
|
939
|
+
oracle,
|
|
884
940
|
},
|
|
885
941
|
remainingAccounts,
|
|
886
942
|
});
|
|
887
943
|
}
|
|
888
944
|
|
|
889
945
|
public async cancelOrderByUserId(
|
|
890
|
-
userOrderId: number
|
|
891
|
-
oracle?: PublicKey
|
|
946
|
+
userOrderId: number
|
|
892
947
|
): Promise<TransactionSignature> {
|
|
893
|
-
|
|
894
|
-
wrapInTx(await this.getCancelOrderByUserIdIx(userOrderId
|
|
948
|
+
const { txSig } = await this.txSender.send(
|
|
949
|
+
wrapInTx(await this.getCancelOrderByUserIdIx(userOrderId)),
|
|
895
950
|
[],
|
|
896
951
|
this.opts
|
|
897
952
|
);
|
|
953
|
+
return txSig;
|
|
898
954
|
}
|
|
899
955
|
|
|
900
956
|
public async getCancelOrderByUserIdIx(
|
|
901
|
-
userOrderId: number
|
|
902
|
-
oracle?: PublicKey
|
|
957
|
+
userOrderId: number
|
|
903
958
|
): Promise<TransactionInstruction> {
|
|
904
959
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
905
|
-
const userAccount = await this.getUserAccount();
|
|
906
960
|
|
|
907
|
-
const
|
|
908
|
-
const
|
|
961
|
+
const order = this.getOrderByUserId(userOrderId);
|
|
962
|
+
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
909
963
|
|
|
910
|
-
const remainingAccounts =
|
|
911
|
-
if (oracle) {
|
|
912
|
-
remainingAccounts.push({
|
|
913
|
-
pubkey: oracle,
|
|
914
|
-
isWritable: false,
|
|
915
|
-
isSigner: false,
|
|
916
|
-
});
|
|
917
|
-
}
|
|
964
|
+
const remainingAccounts = this.getRemainingAccounts({});
|
|
918
965
|
|
|
919
966
|
return await this.program.instruction.cancelOrderByUserId(userOrderId, {
|
|
920
967
|
accounts: {
|
|
921
968
|
state: await this.getStatePublicKey(),
|
|
922
969
|
user: userAccountPublicKey,
|
|
923
970
|
authority: this.wallet.publicKey,
|
|
924
|
-
|
|
925
|
-
userOrders: await this.getUserOrdersAccountPublicKey(),
|
|
926
|
-
userPositions: userAccount.positions,
|
|
927
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
928
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
929
|
-
orderState: await this.getOrderStatePublicKey(),
|
|
930
|
-
orderHistory: orderState.orderHistory,
|
|
971
|
+
oracle,
|
|
931
972
|
},
|
|
932
973
|
remainingAccounts,
|
|
933
974
|
});
|
|
934
975
|
}
|
|
935
976
|
|
|
936
977
|
public async cancelAllOrders(
|
|
937
|
-
oracles?: PublicKey[],
|
|
938
978
|
bestEffort?: boolean
|
|
939
979
|
): Promise<TransactionSignature> {
|
|
940
|
-
|
|
941
|
-
wrapInTx(await this.getCancelAllOrdersIx(
|
|
980
|
+
const { txSig } = await this.txSender.send(
|
|
981
|
+
wrapInTx(await this.getCancelAllOrdersIx(bestEffort)),
|
|
942
982
|
[],
|
|
943
983
|
this.opts
|
|
944
984
|
);
|
|
985
|
+
return txSig;
|
|
945
986
|
}
|
|
946
987
|
|
|
947
988
|
public async getCancelAllOrdersIx(
|
|
948
|
-
oracles: PublicKey[],
|
|
949
989
|
bestEffort?: boolean
|
|
950
990
|
): Promise<TransactionInstruction> {
|
|
951
991
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
952
|
-
const userAccount = await this.getUserAccount();
|
|
953
992
|
|
|
954
|
-
const
|
|
955
|
-
const orderState = this.getOrderStateAccount();
|
|
993
|
+
const remainingAccounts = this.getRemainingAccounts({});
|
|
956
994
|
|
|
957
|
-
const
|
|
958
|
-
|
|
995
|
+
for (const order of this.getUserAccount().orders) {
|
|
996
|
+
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
959
997
|
remainingAccounts.push({
|
|
960
998
|
pubkey: oracle,
|
|
961
999
|
isWritable: false,
|
|
@@ -968,28 +1006,19 @@ export class ClearingHouse {
|
|
|
968
1006
|
state: await this.getStatePublicKey(),
|
|
969
1007
|
user: userAccountPublicKey,
|
|
970
1008
|
authority: this.wallet.publicKey,
|
|
971
|
-
markets: state.markets,
|
|
972
|
-
userOrders: await this.getUserOrdersAccountPublicKey(),
|
|
973
|
-
userPositions: userAccount.positions,
|
|
974
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
975
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
976
|
-
orderState: await this.getOrderStatePublicKey(),
|
|
977
|
-
orderHistory: orderState.orderHistory,
|
|
978
1009
|
},
|
|
979
1010
|
remainingAccounts,
|
|
980
1011
|
});
|
|
981
1012
|
}
|
|
982
1013
|
|
|
983
1014
|
public async cancelOrdersByMarketAndSide(
|
|
984
|
-
oracles?: PublicKey[],
|
|
985
1015
|
bestEffort?: boolean,
|
|
986
1016
|
marketIndexOnly?: BN,
|
|
987
1017
|
directionOnly?: PositionDirection
|
|
988
1018
|
): Promise<TransactionSignature> {
|
|
989
|
-
|
|
1019
|
+
const { txSig } = await this.txSender.send(
|
|
990
1020
|
wrapInTx(
|
|
991
1021
|
await this.getCancelOrdersByMarketAndSideIx(
|
|
992
|
-
oracles,
|
|
993
1022
|
bestEffort,
|
|
994
1023
|
marketIndexOnly,
|
|
995
1024
|
directionOnly
|
|
@@ -998,22 +1027,20 @@ export class ClearingHouse {
|
|
|
998
1027
|
[],
|
|
999
1028
|
this.opts
|
|
1000
1029
|
);
|
|
1030
|
+
return txSig;
|
|
1001
1031
|
}
|
|
1002
1032
|
|
|
1003
1033
|
public async getCancelOrdersByMarketAndSideIx(
|
|
1004
|
-
oracles: PublicKey[],
|
|
1005
1034
|
bestEffort?: boolean,
|
|
1006
1035
|
marketIndexOnly?: BN,
|
|
1007
1036
|
directionOnly?: PositionDirection
|
|
1008
1037
|
): Promise<TransactionInstruction> {
|
|
1009
1038
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1010
|
-
const userAccount = await this.getUserAccount();
|
|
1011
1039
|
|
|
1012
|
-
const
|
|
1013
|
-
const orderState = this.getOrderStateAccount();
|
|
1040
|
+
const remainingAccounts = this.getRemainingAccounts({});
|
|
1014
1041
|
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1042
|
+
for (const order of this.getUserAccount().orders) {
|
|
1043
|
+
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
1017
1044
|
remainingAccounts.push({
|
|
1018
1045
|
pubkey: oracle,
|
|
1019
1046
|
isWritable: false,
|
|
@@ -1030,13 +1057,6 @@ export class ClearingHouse {
|
|
|
1030
1057
|
state: await this.getStatePublicKey(),
|
|
1031
1058
|
user: userAccountPublicKey,
|
|
1032
1059
|
authority: this.wallet.publicKey,
|
|
1033
|
-
markets: state.markets,
|
|
1034
|
-
userOrders: await this.getUserOrdersAccountPublicKey(),
|
|
1035
|
-
userPositions: userAccount.positions,
|
|
1036
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
1037
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
1038
|
-
orderState: await this.getOrderStatePublicKey(),
|
|
1039
|
-
orderHistory: orderState.orderHistory,
|
|
1040
1060
|
},
|
|
1041
1061
|
remainingAccounts,
|
|
1042
1062
|
}
|
|
@@ -1045,320 +1065,354 @@ export class ClearingHouse {
|
|
|
1045
1065
|
|
|
1046
1066
|
public async fillOrder(
|
|
1047
1067
|
userAccountPublicKey: PublicKey,
|
|
1048
|
-
|
|
1049
|
-
order: Order
|
|
1068
|
+
user: UserAccount,
|
|
1069
|
+
order: Order,
|
|
1070
|
+
makerInfo?: MakerInfo
|
|
1050
1071
|
): Promise<TransactionSignature> {
|
|
1051
|
-
|
|
1072
|
+
const { txSig } = await this.txSender.send(
|
|
1052
1073
|
wrapInTx(
|
|
1053
|
-
await this.getFillOrderIx(
|
|
1054
|
-
userAccountPublicKey,
|
|
1055
|
-
userOrdersAccountPublicKey,
|
|
1056
|
-
order
|
|
1057
|
-
)
|
|
1074
|
+
await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)
|
|
1058
1075
|
),
|
|
1059
1076
|
[],
|
|
1060
1077
|
this.opts
|
|
1061
1078
|
);
|
|
1079
|
+
return txSig;
|
|
1062
1080
|
}
|
|
1063
1081
|
|
|
1064
1082
|
public async getFillOrderIx(
|
|
1065
1083
|
userAccountPublicKey: PublicKey,
|
|
1066
|
-
|
|
1067
|
-
order: Order
|
|
1084
|
+
userAccount: UserAccount,
|
|
1085
|
+
order: Order,
|
|
1086
|
+
makerInfo?: MakerInfo
|
|
1068
1087
|
): Promise<TransactionInstruction> {
|
|
1069
1088
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1070
|
-
const userAccount: any = await this.program.account.user.fetch(
|
|
1071
|
-
userAccountPublicKey
|
|
1072
|
-
);
|
|
1073
1089
|
|
|
1074
1090
|
const marketIndex = order.marketIndex;
|
|
1075
|
-
const
|
|
1091
|
+
const marketAccount = this.getMarketAccount(marketIndex);
|
|
1092
|
+
const oracle = marketAccount.amm.oracle;
|
|
1076
1093
|
|
|
1077
|
-
const
|
|
1078
|
-
|
|
1094
|
+
const bankAccountInfos = [
|
|
1095
|
+
{
|
|
1096
|
+
pubkey: this.getQuoteAssetBankAccount().pubkey,
|
|
1097
|
+
isSigner: false,
|
|
1098
|
+
isWritable: true,
|
|
1099
|
+
},
|
|
1100
|
+
];
|
|
1101
|
+
const marketAccountInfos = [
|
|
1102
|
+
{
|
|
1103
|
+
pubkey: marketAccount.pubkey,
|
|
1104
|
+
isWritable: true,
|
|
1105
|
+
isSigner: false,
|
|
1106
|
+
},
|
|
1107
|
+
];
|
|
1108
|
+
const oracleAccountInfos = [
|
|
1109
|
+
{
|
|
1110
|
+
pubkey: marketAccount.amm.oracle,
|
|
1111
|
+
isWritable: false,
|
|
1112
|
+
isSigner: false,
|
|
1113
|
+
},
|
|
1114
|
+
];
|
|
1115
|
+
for (const position of userAccount.positions) {
|
|
1116
|
+
if (
|
|
1117
|
+
!positionIsAvailable(position) &&
|
|
1118
|
+
!position.marketIndex.eq(order.marketIndex)
|
|
1119
|
+
) {
|
|
1120
|
+
const market = this.getMarketAccount(position.marketIndex);
|
|
1121
|
+
marketAccountInfos.push({
|
|
1122
|
+
pubkey: market.pubkey,
|
|
1123
|
+
isWritable: false,
|
|
1124
|
+
isSigner: false,
|
|
1125
|
+
});
|
|
1126
|
+
oracleAccountInfos.push({
|
|
1127
|
+
pubkey: market.amm.oracle,
|
|
1128
|
+
isWritable: false,
|
|
1129
|
+
isSigner: false,
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
const remainingAccounts = oracleAccountInfos.concat(
|
|
1134
|
+
bankAccountInfos.concat(marketAccountInfos)
|
|
1135
|
+
);
|
|
1079
1136
|
|
|
1080
|
-
|
|
1081
|
-
if (!order.referrer.equals(PublicKey.default)) {
|
|
1137
|
+
if (makerInfo) {
|
|
1082
1138
|
remainingAccounts.push({
|
|
1083
|
-
pubkey:
|
|
1139
|
+
pubkey: makerInfo.maker,
|
|
1084
1140
|
isWritable: true,
|
|
1085
1141
|
isSigner: false,
|
|
1086
1142
|
});
|
|
1087
1143
|
}
|
|
1088
1144
|
|
|
1089
1145
|
const orderId = order.orderId;
|
|
1090
|
-
|
|
1146
|
+
const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
|
|
1147
|
+
return await this.program.instruction.fillOrder(orderId, makerOrderId, {
|
|
1091
1148
|
accounts: {
|
|
1092
1149
|
state: await this.getStatePublicKey(),
|
|
1093
1150
|
filler: fillerPublicKey,
|
|
1094
1151
|
user: userAccountPublicKey,
|
|
1095
1152
|
authority: this.wallet.publicKey,
|
|
1096
|
-
markets: state.markets,
|
|
1097
|
-
userPositions: userAccount.positions,
|
|
1098
|
-
userOrders: userOrdersAccountPublicKey,
|
|
1099
|
-
tradeHistory: state.tradeHistory,
|
|
1100
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
1101
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
1102
|
-
orderState: await this.getOrderStatePublicKey(),
|
|
1103
|
-
orderHistory: orderState.orderHistory,
|
|
1104
|
-
extendedCurveHistory: state.extendedCurveHistory,
|
|
1105
1153
|
oracle: oracle,
|
|
1106
1154
|
},
|
|
1107
1155
|
remainingAccounts,
|
|
1108
1156
|
});
|
|
1109
1157
|
}
|
|
1110
1158
|
|
|
1111
|
-
public async
|
|
1112
|
-
orderParams: OrderParams,
|
|
1113
|
-
discountToken?: PublicKey,
|
|
1114
|
-
referrer?: PublicKey
|
|
1115
|
-
): Promise<TransactionSignature> {
|
|
1116
|
-
const instructions: anchor.web3.TransactionInstruction[] = [];
|
|
1117
|
-
const userOrdersAccountExists = await this.userOrdersAccountExists();
|
|
1118
|
-
if (!userOrdersAccountExists) {
|
|
1119
|
-
instructions.push(await this.getInitializeUserOrdersInstruction());
|
|
1120
|
-
}
|
|
1121
|
-
instructions.push(
|
|
1122
|
-
await this.getPlaceAndFillOrderIx(orderParams, discountToken, referrer)
|
|
1123
|
-
);
|
|
1124
|
-
const tx = new Transaction();
|
|
1125
|
-
for (const instruction of instructions) {
|
|
1126
|
-
tx.add(instruction);
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
return await this.txSender.send(tx, [], this.opts);
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
public async placeAndFillOrder(
|
|
1159
|
+
public async placeAndTake(
|
|
1133
1160
|
orderParams: OrderParams,
|
|
1134
|
-
|
|
1135
|
-
referrer?: PublicKey
|
|
1161
|
+
makerInfo?: MakerInfo
|
|
1136
1162
|
): Promise<TransactionSignature> {
|
|
1137
|
-
|
|
1138
|
-
wrapInTx(
|
|
1139
|
-
await this.getPlaceAndFillOrderIx(orderParams, discountToken, referrer)
|
|
1140
|
-
),
|
|
1163
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1164
|
+
wrapInTx(await this.getPlaceAndTakeIx(orderParams, makerInfo)),
|
|
1141
1165
|
[],
|
|
1142
1166
|
this.opts
|
|
1143
1167
|
);
|
|
1168
|
+
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
1169
|
+
return txSig;
|
|
1144
1170
|
}
|
|
1145
1171
|
|
|
1146
|
-
public async
|
|
1172
|
+
public async getPlaceAndTakeIx(
|
|
1147
1173
|
orderParams: OrderParams,
|
|
1148
|
-
|
|
1149
|
-
referrer?: PublicKey
|
|
1174
|
+
makerInfo?: MakerInfo
|
|
1150
1175
|
): Promise<TransactionInstruction> {
|
|
1151
1176
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1152
|
-
const userAccount = await this.getUserAccount();
|
|
1153
1177
|
|
|
1154
|
-
const priceOracle =
|
|
1155
|
-
|
|
1156
|
-
.oracle;
|
|
1178
|
+
const priceOracle = this.getMarketAccount(orderParams.marketIndex).amm
|
|
1179
|
+
.oracle;
|
|
1157
1180
|
|
|
1158
|
-
const remainingAccounts =
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
'Optional accounts specified discount token but no discount token present'
|
|
1163
|
-
);
|
|
1164
|
-
}
|
|
1181
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1182
|
+
writableMarketIndex: orderParams.marketIndex,
|
|
1183
|
+
writableBankIndex: QUOTE_ASSET_BANK_INDEX,
|
|
1184
|
+
});
|
|
1165
1185
|
|
|
1186
|
+
let makerOrderId = null;
|
|
1187
|
+
if (makerInfo) {
|
|
1188
|
+
makerOrderId = makerInfo.order.orderId;
|
|
1166
1189
|
remainingAccounts.push({
|
|
1167
|
-
pubkey:
|
|
1168
|
-
isWritable: false,
|
|
1190
|
+
pubkey: makerInfo.maker,
|
|
1169
1191
|
isSigner: false,
|
|
1170
|
-
});
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
if (orderParams.optionalAccounts.referrer) {
|
|
1174
|
-
if (!referrer) {
|
|
1175
|
-
throw Error(
|
|
1176
|
-
'Optional accounts specified referrer but no referrer present'
|
|
1177
|
-
);
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
remainingAccounts.push({
|
|
1181
|
-
pubkey: referrer,
|
|
1182
1192
|
isWritable: true,
|
|
1183
|
-
isSigner: false,
|
|
1184
1193
|
});
|
|
1185
1194
|
}
|
|
1186
1195
|
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
orderState: await this.getOrderStatePublicKey(),
|
|
1201
|
-
orderHistory: orderState.orderHistory,
|
|
1202
|
-
extendedCurveHistory: state.extendedCurveHistory,
|
|
1203
|
-
oracle: priceOracle,
|
|
1204
|
-
},
|
|
1205
|
-
remainingAccounts,
|
|
1206
|
-
});
|
|
1196
|
+
return await this.program.instruction.placeAndTake(
|
|
1197
|
+
orderParams,
|
|
1198
|
+
makerOrderId,
|
|
1199
|
+
{
|
|
1200
|
+
accounts: {
|
|
1201
|
+
state: await this.getStatePublicKey(),
|
|
1202
|
+
user: userAccountPublicKey,
|
|
1203
|
+
authority: this.wallet.publicKey,
|
|
1204
|
+
oracle: priceOracle,
|
|
1205
|
+
},
|
|
1206
|
+
remainingAccounts,
|
|
1207
|
+
}
|
|
1208
|
+
);
|
|
1207
1209
|
}
|
|
1208
1210
|
|
|
1209
1211
|
/**
|
|
1210
1212
|
* Close an entire position. If you want to reduce a position, use the {@link openPosition} method in the opposite direction of the current position.
|
|
1211
1213
|
* @param marketIndex
|
|
1212
|
-
* @param discountToken
|
|
1213
|
-
* @param referrer
|
|
1214
1214
|
* @returns
|
|
1215
1215
|
*/
|
|
1216
|
-
public async closePosition(
|
|
1217
|
-
marketIndex
|
|
1218
|
-
|
|
1219
|
-
|
|
1216
|
+
public async closePosition(marketIndex: BN): Promise<TransactionSignature> {
|
|
1217
|
+
const userPosition = this.getUser().getUserPosition(marketIndex);
|
|
1218
|
+
if (!userPosition) {
|
|
1219
|
+
throw Error(`No position in market ${marketIndex.toString()}`);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
return await this.placeAndTake(
|
|
1223
|
+
getMarketOrderParams(
|
|
1224
|
+
marketIndex,
|
|
1225
|
+
findDirectionToClose(userPosition),
|
|
1226
|
+
ZERO,
|
|
1227
|
+
userPosition.baseAssetAmount,
|
|
1228
|
+
true,
|
|
1229
|
+
undefined
|
|
1230
|
+
)
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
public async settlePNLs(
|
|
1235
|
+
users: {
|
|
1236
|
+
settleeUserAccountPublicKey: PublicKey;
|
|
1237
|
+
settleeUserAccount: UserAccount;
|
|
1238
|
+
}[],
|
|
1239
|
+
marketIndex: BN
|
|
1240
|
+
): Promise<TransactionSignature> {
|
|
1241
|
+
const ixs = [];
|
|
1242
|
+
for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
|
|
1243
|
+
ixs.push(
|
|
1244
|
+
await this.settlePNLIx(
|
|
1245
|
+
settleeUserAccountPublicKey,
|
|
1246
|
+
settleeUserAccount,
|
|
1247
|
+
marketIndex
|
|
1248
|
+
)
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
const tx = new Transaction().add(...ixs);
|
|
1253
|
+
|
|
1254
|
+
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
1255
|
+
return txSig;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
public async settlePNL(
|
|
1259
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
1260
|
+
settleeUserAccount: UserAccount,
|
|
1261
|
+
marketIndex: BN
|
|
1220
1262
|
): Promise<TransactionSignature> {
|
|
1221
|
-
|
|
1263
|
+
const { txSig } = await this.txSender.send(
|
|
1222
1264
|
wrapInTx(
|
|
1223
|
-
await this.
|
|
1265
|
+
await this.settlePNLIx(
|
|
1266
|
+
settleeUserAccountPublicKey,
|
|
1267
|
+
settleeUserAccount,
|
|
1268
|
+
marketIndex
|
|
1269
|
+
)
|
|
1224
1270
|
),
|
|
1225
1271
|
[],
|
|
1226
1272
|
this.opts
|
|
1227
1273
|
);
|
|
1274
|
+
return txSig;
|
|
1228
1275
|
}
|
|
1229
1276
|
|
|
1230
|
-
public async
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1277
|
+
public async settlePNLIx(
|
|
1278
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
1279
|
+
settleeUserAccount: UserAccount,
|
|
1280
|
+
marketIndex: BN
|
|
1234
1281
|
): Promise<TransactionInstruction> {
|
|
1235
|
-
const
|
|
1236
|
-
const
|
|
1237
|
-
|
|
1238
|
-
const
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
});
|
|
1253
|
-
}
|
|
1254
|
-
if (referrer) {
|
|
1255
|
-
optionalAccounts.referrer = true;
|
|
1256
|
-
remainingAccounts.push({
|
|
1257
|
-
pubkey: referrer,
|
|
1258
|
-
isWritable: true,
|
|
1259
|
-
isSigner: false,
|
|
1260
|
-
});
|
|
1282
|
+
const marketAccountMap = new Map<number, AccountMeta>();
|
|
1283
|
+
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
1284
|
+
const bankAccountMap = new Map<number, AccountMeta>();
|
|
1285
|
+
for (const position of settleeUserAccount.positions) {
|
|
1286
|
+
if (!positionIsAvailable(position)) {
|
|
1287
|
+
const market = this.getMarketAccount(position.marketIndex);
|
|
1288
|
+
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1289
|
+
pubkey: market.pubkey,
|
|
1290
|
+
isWritable: true, // TODO
|
|
1291
|
+
isSigner: false,
|
|
1292
|
+
});
|
|
1293
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1294
|
+
pubkey: market.amm.oracle,
|
|
1295
|
+
isWritable: false,
|
|
1296
|
+
isSigner: false,
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1261
1299
|
}
|
|
1262
1300
|
|
|
1263
|
-
const
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
},
|
|
1279
|
-
remainingAccounts: remainingAccounts,
|
|
1301
|
+
for (const userBankBalance of settleeUserAccount.bankBalances) {
|
|
1302
|
+
if (!userBankBalance.balance.eq(QUOTE_ASSET_BANK_INDEX)) {
|
|
1303
|
+
const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
|
|
1304
|
+
bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
|
|
1305
|
+
pubkey: bankAccount.pubkey,
|
|
1306
|
+
isSigner: false,
|
|
1307
|
+
isWritable: false,
|
|
1308
|
+
});
|
|
1309
|
+
if (!bankAccount.bankIndex.eq(ZERO)) {
|
|
1310
|
+
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1311
|
+
pubkey: bankAccount.oracle,
|
|
1312
|
+
isSigner: false,
|
|
1313
|
+
isWritable: false,
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1280
1316
|
}
|
|
1281
|
-
|
|
1282
|
-
}
|
|
1317
|
+
}
|
|
1283
1318
|
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1319
|
+
const marketAccount = this.getMarketAccount(marketIndex.toNumber());
|
|
1320
|
+
marketAccountMap.set(marketIndex.toNumber(), {
|
|
1321
|
+
pubkey: marketAccount.pubkey,
|
|
1322
|
+
isSigner: false,
|
|
1323
|
+
isWritable: true,
|
|
1324
|
+
});
|
|
1325
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1326
|
+
pubkey: marketAccount.amm.oracle,
|
|
1327
|
+
isSigner: false,
|
|
1328
|
+
isWritable: false,
|
|
1329
|
+
});
|
|
1294
1330
|
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
)
|
|
1301
|
-
);
|
|
1302
|
-
}
|
|
1331
|
+
bankAccountMap.set(QUOTE_ASSET_BANK_INDEX.toNumber(), {
|
|
1332
|
+
pubkey: this.getBankAccount(QUOTE_ASSET_BANK_INDEX).pubkey,
|
|
1333
|
+
isSigner: false,
|
|
1334
|
+
isWritable: true,
|
|
1335
|
+
});
|
|
1303
1336
|
|
|
1304
|
-
const
|
|
1337
|
+
const remainingAccounts = [
|
|
1338
|
+
...oracleAccountMap.values(),
|
|
1339
|
+
...bankAccountMap.values(),
|
|
1340
|
+
...marketAccountMap.values(),
|
|
1341
|
+
];
|
|
1305
1342
|
|
|
1306
|
-
return this.
|
|
1343
|
+
return await this.program.instruction.settlePnl(marketIndex, {
|
|
1344
|
+
accounts: {
|
|
1345
|
+
state: await this.getStatePublicKey(),
|
|
1346
|
+
authority: this.wallet.publicKey,
|
|
1347
|
+
user: settleeUserAccountPublicKey,
|
|
1348
|
+
},
|
|
1349
|
+
remainingAccounts: remainingAccounts,
|
|
1350
|
+
});
|
|
1307
1351
|
}
|
|
1308
1352
|
|
|
1309
1353
|
public async liquidate(
|
|
1310
1354
|
liquidateeUserAccountPublicKey: PublicKey
|
|
1311
1355
|
): Promise<TransactionSignature> {
|
|
1312
|
-
|
|
1356
|
+
const { txSig } = await this.txSender.send(
|
|
1313
1357
|
wrapInTx(await this.getLiquidateIx(liquidateeUserAccountPublicKey)),
|
|
1314
1358
|
[],
|
|
1315
1359
|
this.opts
|
|
1316
1360
|
);
|
|
1361
|
+
return txSig;
|
|
1317
1362
|
}
|
|
1318
1363
|
|
|
1319
1364
|
public async getLiquidateIx(
|
|
1320
1365
|
liquidateeUserAccountPublicKey: PublicKey
|
|
1321
1366
|
): Promise<TransactionInstruction> {
|
|
1322
1367
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1323
|
-
|
|
1324
|
-
const liquidateeUserAccount: any = await this.program.account.user.fetch(
|
|
1368
|
+
const liquidateeUserAccount = (await this.program.account.user.fetch(
|
|
1325
1369
|
liquidateeUserAccountPublicKey
|
|
1326
|
-
);
|
|
1327
|
-
const liquidateePositions: any =
|
|
1328
|
-
await this.program.account.userPositions.fetch(
|
|
1329
|
-
liquidateeUserAccount.positions
|
|
1330
|
-
);
|
|
1331
|
-
const markets = this.getMarketsAccount();
|
|
1370
|
+
)) as UserAccount;
|
|
1332
1371
|
|
|
1333
|
-
const
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1372
|
+
const bankAccountInfos = [
|
|
1373
|
+
{
|
|
1374
|
+
pubkey: this.getQuoteAssetBankAccount().pubkey,
|
|
1375
|
+
isSigner: false,
|
|
1376
|
+
isWritable: true,
|
|
1377
|
+
},
|
|
1378
|
+
];
|
|
1379
|
+
const marketAccountInfos = [];
|
|
1380
|
+
const oracleAccountInfos = [];
|
|
1381
|
+
for (const position of liquidateeUserAccount.positions) {
|
|
1382
|
+
if (!positionIsAvailable(position)) {
|
|
1383
|
+
const market = this.getMarketAccount(position.marketIndex);
|
|
1384
|
+
const marketPublicKey = await getMarketPublicKey(
|
|
1385
|
+
this.program.programId,
|
|
1386
|
+
position.marketIndex
|
|
1387
|
+
);
|
|
1388
|
+
marketAccountInfos.push({
|
|
1389
|
+
pubkey: marketPublicKey,
|
|
1390
|
+
isWritable: true,
|
|
1391
|
+
isSigner: false,
|
|
1392
|
+
});
|
|
1393
|
+
oracleAccountInfos.push({
|
|
1338
1394
|
pubkey: market.amm.oracle,
|
|
1339
1395
|
isWritable: false,
|
|
1340
1396
|
isSigner: false,
|
|
1341
1397
|
});
|
|
1342
1398
|
}
|
|
1343
1399
|
}
|
|
1400
|
+
const remainingAccounts = oracleAccountInfos.concat(
|
|
1401
|
+
bankAccountInfos.concat(marketAccountInfos)
|
|
1402
|
+
);
|
|
1344
1403
|
|
|
1345
1404
|
const state = this.getStateAccount();
|
|
1405
|
+
const quoteAssetBankAccount = this.getQuoteAssetBankAccount();
|
|
1346
1406
|
return await this.program.instruction.liquidate({
|
|
1347
1407
|
accounts: {
|
|
1348
1408
|
state: await this.getStatePublicKey(),
|
|
1349
1409
|
authority: this.wallet.publicKey,
|
|
1350
1410
|
user: liquidateeUserAccountPublicKey,
|
|
1351
1411
|
liquidator: userAccountPublicKey,
|
|
1352
|
-
|
|
1353
|
-
|
|
1412
|
+
bankVault: quoteAssetBankAccount.vault,
|
|
1413
|
+
bankVaultAuthority: quoteAssetBankAccount.vaultAuthority,
|
|
1354
1414
|
insuranceVault: state.insuranceVault,
|
|
1355
|
-
insuranceVaultAuthority: state.insuranceVaultAuthority,
|
|
1356
1415
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1357
|
-
markets: state.markets,
|
|
1358
|
-
userPositions: liquidateeUserAccount.positions,
|
|
1359
|
-
tradeHistory: state.tradeHistory,
|
|
1360
|
-
liquidationHistory: state.liquidationHistory,
|
|
1361
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
1362
1416
|
},
|
|
1363
1417
|
remainingAccounts: remainingAccounts,
|
|
1364
1418
|
});
|
|
@@ -1368,54 +1422,68 @@ export class ClearingHouse {
|
|
|
1368
1422
|
oracle: PublicKey,
|
|
1369
1423
|
marketIndex: BN
|
|
1370
1424
|
): Promise<TransactionSignature> {
|
|
1371
|
-
|
|
1425
|
+
const { txSig } = await this.txSender.send(
|
|
1372
1426
|
wrapInTx(await this.getUpdateFundingRateIx(oracle, marketIndex)),
|
|
1373
1427
|
[],
|
|
1374
1428
|
this.opts
|
|
1375
1429
|
);
|
|
1430
|
+
return txSig;
|
|
1376
1431
|
}
|
|
1377
1432
|
|
|
1378
1433
|
public async getUpdateFundingRateIx(
|
|
1379
1434
|
oracle: PublicKey,
|
|
1380
1435
|
marketIndex: BN
|
|
1381
1436
|
): Promise<TransactionInstruction> {
|
|
1382
|
-
const state = this.getStateAccount();
|
|
1383
1437
|
return await this.program.instruction.updateFundingRate(marketIndex, {
|
|
1384
1438
|
accounts: {
|
|
1385
1439
|
state: await this.getStatePublicKey(),
|
|
1386
|
-
|
|
1440
|
+
market: await getMarketPublicKey(this.program.programId, marketIndex),
|
|
1387
1441
|
oracle: oracle,
|
|
1388
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
1389
1442
|
},
|
|
1390
1443
|
});
|
|
1391
1444
|
}
|
|
1392
1445
|
|
|
1393
1446
|
public async settleFundingPayment(
|
|
1394
|
-
userAccount: PublicKey
|
|
1395
|
-
userPositionsAccount: PublicKey
|
|
1447
|
+
userAccount: PublicKey
|
|
1396
1448
|
): Promise<TransactionSignature> {
|
|
1397
|
-
|
|
1398
|
-
wrapInTx(
|
|
1399
|
-
await this.getSettleFundingPaymentIx(userAccount, userPositionsAccount)
|
|
1400
|
-
),
|
|
1449
|
+
const { txSig } = await this.txSender.send(
|
|
1450
|
+
wrapInTx(await this.getSettleFundingPaymentIx(userAccount)),
|
|
1401
1451
|
[],
|
|
1402
1452
|
this.opts
|
|
1403
1453
|
);
|
|
1454
|
+
return txSig;
|
|
1404
1455
|
}
|
|
1405
1456
|
|
|
1406
1457
|
public async getSettleFundingPaymentIx(
|
|
1407
|
-
userAccount: PublicKey
|
|
1408
|
-
userPositionsAccount: PublicKey
|
|
1458
|
+
userAccount: PublicKey
|
|
1409
1459
|
): Promise<TransactionInstruction> {
|
|
1410
|
-
const
|
|
1460
|
+
const user = (await this.program.account.user.fetch(
|
|
1461
|
+
userAccount
|
|
1462
|
+
)) as UserAccount;
|
|
1463
|
+
|
|
1464
|
+
const userPositions = user.positions;
|
|
1465
|
+
|
|
1466
|
+
const remainingAccounts = [];
|
|
1467
|
+
for (const position of userPositions) {
|
|
1468
|
+
if (!positionIsAvailable(position)) {
|
|
1469
|
+
const marketPublicKey = await getMarketPublicKey(
|
|
1470
|
+
this.program.programId,
|
|
1471
|
+
position.marketIndex
|
|
1472
|
+
);
|
|
1473
|
+
remainingAccounts.push({
|
|
1474
|
+
pubkey: marketPublicKey,
|
|
1475
|
+
isWritable: false,
|
|
1476
|
+
isSigner: false,
|
|
1477
|
+
});
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1411
1481
|
return await this.program.instruction.settleFundingPayment({
|
|
1412
1482
|
accounts: {
|
|
1413
1483
|
state: await this.getStatePublicKey(),
|
|
1414
|
-
markets: state.markets,
|
|
1415
1484
|
user: userAccount,
|
|
1416
|
-
userPositions: userPositionsAccount,
|
|
1417
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
1418
1485
|
},
|
|
1486
|
+
remainingAccounts,
|
|
1419
1487
|
});
|
|
1420
1488
|
}
|
|
1421
1489
|
|
|
@@ -1423,121 +1491,10 @@ export class ClearingHouse {
|
|
|
1423
1491
|
this.eventEmitter.emit(eventName, data);
|
|
1424
1492
|
}
|
|
1425
1493
|
|
|
1426
|
-
public
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
const settlePositionIx = await this.getSettlePositionIx();
|
|
1430
|
-
const claimCollateralIx = await this.getClaimCollateralIx(
|
|
1431
|
-
collateralAccountPublicKey
|
|
1432
|
-
);
|
|
1433
|
-
const tx = new Transaction().add(settlePositionIx).add(claimCollateralIx);
|
|
1434
|
-
|
|
1435
|
-
return this.txSender.send(tx, [], this.opts);
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
public async getSettlePositionIx(): Promise<TransactionInstruction> {
|
|
1439
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1440
|
-
const user: any = await this.program.account.user.fetch(
|
|
1441
|
-
userAccountPublicKey
|
|
1442
|
-
);
|
|
1443
|
-
const state = this.getStateAccount();
|
|
1444
|
-
|
|
1445
|
-
const settlementState = await getSettlementStatePublicKey(
|
|
1446
|
-
this.program.programId
|
|
1447
|
-
);
|
|
1448
|
-
|
|
1449
|
-
return await this.program.instruction.settlePosition({
|
|
1450
|
-
accounts: {
|
|
1451
|
-
state: await this.getStatePublicKey(),
|
|
1452
|
-
user: userAccountPublicKey,
|
|
1453
|
-
markets: state.markets,
|
|
1454
|
-
authority: this.wallet.publicKey,
|
|
1455
|
-
userPositions: user.positions,
|
|
1456
|
-
settlementState,
|
|
1457
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
1458
|
-
},
|
|
1459
|
-
});
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
public async getClaimCollateralIx(
|
|
1463
|
-
collateralAccountPublicKey: PublicKey
|
|
1464
|
-
): Promise<TransactionInstruction> {
|
|
1465
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1466
|
-
const state = this.getStateAccount();
|
|
1467
|
-
|
|
1468
|
-
const settlementState = await getSettlementStatePublicKey(
|
|
1469
|
-
this.program.programId
|
|
1470
|
-
);
|
|
1471
|
-
|
|
1472
|
-
return await this.program.instruction.claimCollateral({
|
|
1473
|
-
accounts: {
|
|
1474
|
-
state: await this.getStatePublicKey(),
|
|
1475
|
-
user: userAccountPublicKey,
|
|
1476
|
-
collateralVault: state.collateralVault,
|
|
1477
|
-
collateralVaultAuthority: state.collateralVaultAuthority,
|
|
1478
|
-
userCollateralAccount: collateralAccountPublicKey,
|
|
1479
|
-
authority: this.wallet.publicKey,
|
|
1480
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1481
|
-
settlementState,
|
|
1482
|
-
},
|
|
1483
|
-
});
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
public async getTotalSettlementSize(): Promise<BN> {
|
|
1487
|
-
const accountLoader = new BulkAccountLoader(
|
|
1488
|
-
this.connection,
|
|
1489
|
-
'processed',
|
|
1490
|
-
50000
|
|
1491
|
-
);
|
|
1492
|
-
const clearingHouse = getClearingHouse(
|
|
1493
|
-
getPollingClearingHouseConfig(
|
|
1494
|
-
this.connection,
|
|
1495
|
-
this.wallet,
|
|
1496
|
-
this.program.programId,
|
|
1497
|
-
accountLoader
|
|
1498
|
-
)
|
|
1499
|
-
);
|
|
1500
|
-
|
|
1501
|
-
console.log('loading all users');
|
|
1502
|
-
const programUserAccounts =
|
|
1503
|
-
(await this.program.account.user.all()) as any[];
|
|
1504
|
-
const userArray: ClearingHouseUser[] = [];
|
|
1505
|
-
for (const programUserAccount of programUserAccounts) {
|
|
1506
|
-
const user = getClearingHouseUser(
|
|
1507
|
-
getPollingClearingHouseUserConfig(
|
|
1508
|
-
clearingHouse,
|
|
1509
|
-
programUserAccount.account.authority,
|
|
1510
|
-
accountLoader
|
|
1511
|
-
)
|
|
1512
|
-
);
|
|
1513
|
-
userArray.push(user);
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
console.log('subscribing all users');
|
|
1517
|
-
await bulkPollingUserSubscribe(userArray, accountLoader);
|
|
1518
|
-
|
|
1519
|
-
console.log('calculating settlement size');
|
|
1520
|
-
const settlementSize = userArray.reduce((collateralToBeSettled, user) => {
|
|
1521
|
-
return collateralToBeSettled.add(
|
|
1522
|
-
user.getUserAccount().forgoPositionSettlement === 0
|
|
1523
|
-
? user.getSettledPositionValue()
|
|
1524
|
-
: ZERO
|
|
1525
|
-
);
|
|
1526
|
-
}, ZERO);
|
|
1527
|
-
|
|
1528
|
-
for (const user of userArray) {
|
|
1529
|
-
await user.unsubscribe();
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
|
-
return settlementSize;
|
|
1533
|
-
}
|
|
1494
|
+
public getOracleDataForMarket(marketIndex: BN): OraclePriceData {
|
|
1495
|
+
const oracleKey = this.getMarketAccount(marketIndex).amm.oracle;
|
|
1496
|
+
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
1534
1497
|
|
|
1535
|
-
|
|
1536
|
-
return await this.program.rpc.updateUserForgoSettlement({
|
|
1537
|
-
accounts: {
|
|
1538
|
-
authority: this.wallet.publicKey,
|
|
1539
|
-
user: await this.getUserAccountPublicKey(),
|
|
1540
|
-
},
|
|
1541
|
-
});
|
|
1498
|
+
return oracleData;
|
|
1542
1499
|
}
|
|
1543
1500
|
}
|