@drift-labs/sdk 0.1.36-master.7 → 0.2.0-master.2
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 +9 -17
- package/lib/admin.js +375 -558
- package/lib/clearingHouse.d.ts +86 -109
- package/lib/clearingHouse.js +828 -895
- 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 +17 -0
- package/lib/constants/numericConstants.js +23 -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 +118 -0
- package/lib/factory/bigNum.js +364 -0
- package/lib/factory/oracleClient.d.ts +1 -2
- package/lib/factory/oracleClient.js +6 -2
- package/lib/idl/clearing_house.json +2287 -2938
- package/lib/index.d.ts +12 -4
- package/lib/index.js +12 -4
- package/lib/math/amm.d.ts +24 -29
- package/lib/math/amm.js +239 -178
- 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 -7
- package/lib/orders.js +10 -80
- 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 +110 -109
- package/lib/types.js +14 -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 +11 -4
- 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 +218 -346
- package/src/clearingHouse.ts +983 -952
- 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 +34 -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 +524 -0
- package/src/factory/oracleClient.ts +7 -4
- package/src/idl/clearing_house.json +2287 -2938
- package/src/index.ts +12 -4
- package/src/math/amm.ts +414 -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 +176 -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 +24 -126
- 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 +111 -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
|
-
);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
public getMarketsAccount(): MarketsAccount {
|
|
207
|
-
return this.accountSubscriber.getMarketsAccount();
|
|
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];
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
public getFundingPaymentHistoryAccount(): FundingPaymentHistoryAccount {
|
|
218
|
-
return this.accountSubscriber.getFundingPaymentHistoryAccount();
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
public getFundingRateHistoryAccount(): FundingRateHistoryAccount {
|
|
222
|
-
return this.accountSubscriber.getFundingRateHistoryAccount();
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
public getTradeHistoryAccount(): TradeHistoryAccount {
|
|
226
|
-
return this.accountSubscriber.getTradeHistoryAccount();
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
public getLiquidationHistoryAccount(): LiquidationHistoryAccount {
|
|
230
|
-
return this.accountSubscriber.getLiquidationHistoryAccount();
|
|
228
|
+
return this.accountSubscriber.getStateAccountAndSlot().data;
|
|
231
229
|
}
|
|
232
230
|
|
|
233
|
-
public
|
|
234
|
-
|
|
231
|
+
public getMarketAccount(marketIndex: BN | number): MarketAccount | undefined {
|
|
232
|
+
marketIndex = marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
|
|
233
|
+
return this.accountSubscriber.getMarketAccountAndSlot(marketIndex)?.data;
|
|
235
234
|
}
|
|
236
235
|
|
|
237
|
-
public
|
|
238
|
-
return this.accountSubscriber
|
|
236
|
+
public getMarketAccounts(): MarketAccount[] {
|
|
237
|
+
return this.accountSubscriber
|
|
238
|
+
.getMarketAccountsAndSlots()
|
|
239
|
+
.map((value) => value.data);
|
|
239
240
|
}
|
|
240
241
|
|
|
241
|
-
public
|
|
242
|
-
|
|
242
|
+
public getBankAccount(bankIndex: BN | number): BankAccount | undefined {
|
|
243
|
+
bankIndex = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
|
|
244
|
+
return this.accountSubscriber.getBankAccountAndSlot(bankIndex).data;
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return this.orderStatePublicKey;
|
|
249
|
-
}
|
|
250
|
-
this.orderStatePublicKey = await getOrderStateAccountPublicKey(
|
|
251
|
-
this.program.programId
|
|
252
|
-
);
|
|
253
|
-
return this.orderStatePublicKey;
|
|
247
|
+
public getQuoteAssetBankAccount(): BankAccount {
|
|
248
|
+
return this.accountSubscriber.getBankAccountAndSlot(QUOTE_ASSET_BANK_INDEX)
|
|
249
|
+
.data;
|
|
254
250
|
}
|
|
255
251
|
|
|
256
|
-
public
|
|
257
|
-
|
|
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)
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
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
|
|
438
393
|
);
|
|
439
|
-
return this.userOrdersAccountPublicKey;
|
|
440
394
|
}
|
|
441
395
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
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
|
+
);
|
|
405
|
+
}
|
|
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
|
+
}
|
|
446
448
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
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
|
+
}
|
|
483
|
+
|
|
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
|
+
];
|
|
505
|
+
}
|
|
506
|
+
|
|
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
|
+
}
|
|
451
513
|
|
|
452
|
-
|
|
453
|
-
return this.
|
|
514
|
+
public getOrderByUserId(userOrderId: number): Order | undefined {
|
|
515
|
+
return this.getUserAccount()?.orders.find(
|
|
516
|
+
(order) => order.userOrderId === userOrderId
|
|
517
|
+
);
|
|
454
518
|
}
|
|
455
519
|
|
|
456
|
-
public async
|
|
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,352 @@ 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
|
|
570
|
-
amount: BN,
|
|
571
|
-
collateralAccountPublicKey: PublicKey
|
|
572
|
-
): Promise<TransactionSignature> {
|
|
573
|
-
return this.txSender.send(
|
|
574
|
-
wrapInTx(
|
|
575
|
-
await this.getWithdrawCollateralIx(amount, collateralAccountPublicKey)
|
|
576
|
-
),
|
|
577
|
-
[],
|
|
578
|
-
this.opts
|
|
579
|
-
);
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
public async getWithdrawCollateralIx(
|
|
583
|
-
amount: BN,
|
|
584
|
-
collateralAccountPublicKey: PublicKey
|
|
585
|
-
): Promise<TransactionInstruction> {
|
|
586
|
-
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
587
|
-
const user: any = await this.program.account.user.fetch(
|
|
588
|
-
userAccountPublicKey
|
|
589
|
-
);
|
|
590
|
-
|
|
591
|
-
const state = this.getStateAccount();
|
|
592
|
-
return await this.program.instruction.withdrawCollateral(amount, {
|
|
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
|
-
},
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
public async openPosition(
|
|
612
|
-
direction: PositionDirection,
|
|
670
|
+
public async withdraw(
|
|
613
671
|
amount: BN,
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
referrer?: PublicKey
|
|
672
|
+
bankIndex: BN,
|
|
673
|
+
userTokenAccount: PublicKey,
|
|
674
|
+
reduceOnly = false
|
|
618
675
|
): Promise<TransactionSignature> {
|
|
619
|
-
|
|
676
|
+
const { txSig } = await this.txSender.send(
|
|
620
677
|
wrapInTx(
|
|
621
|
-
await this.
|
|
622
|
-
direction,
|
|
678
|
+
await this.getWithdrawIx(
|
|
623
679
|
amount,
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
referrer
|
|
680
|
+
bankIndex,
|
|
681
|
+
userTokenAccount,
|
|
682
|
+
reduceOnly
|
|
628
683
|
)
|
|
629
684
|
),
|
|
630
685
|
[],
|
|
631
686
|
this.opts
|
|
632
687
|
);
|
|
688
|
+
return txSig;
|
|
633
689
|
}
|
|
634
690
|
|
|
635
|
-
public async
|
|
636
|
-
direction: PositionDirection,
|
|
691
|
+
public async getWithdrawIx(
|
|
637
692
|
amount: BN,
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
referrer?: PublicKey
|
|
693
|
+
bankIndex: BN,
|
|
694
|
+
userTokenAccount: PublicKey,
|
|
695
|
+
reduceOnly = false
|
|
642
696
|
): Promise<TransactionInstruction> {
|
|
643
697
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
644
|
-
const userAccount = await this.getUserAccount();
|
|
645
|
-
|
|
646
|
-
if (limitPrice == undefined) {
|
|
647
|
-
limitPrice = new BN(0); // no limit
|
|
648
|
-
}
|
|
649
698
|
|
|
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
|
-
}
|
|
699
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
700
|
+
writableBankIndex: bankIndex,
|
|
701
|
+
});
|
|
671
702
|
|
|
672
|
-
const
|
|
673
|
-
this.getMarketsAccount().markets[marketIndex.toNumber()].amm.oracle;
|
|
703
|
+
const bank = this.getBankAccount(bankIndex);
|
|
674
704
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
direction,
|
|
705
|
+
return await this.program.instruction.withdraw(
|
|
706
|
+
bankIndex,
|
|
678
707
|
amount,
|
|
679
|
-
|
|
680
|
-
limitPrice,
|
|
681
|
-
optionalAccounts,
|
|
708
|
+
reduceOnly,
|
|
682
709
|
{
|
|
683
710
|
accounts: {
|
|
684
711
|
state: await this.getStatePublicKey(),
|
|
712
|
+
bank: bank.pubkey,
|
|
713
|
+
bankVault: bank.vault,
|
|
714
|
+
bankVaultAuthority: bank.vaultAuthority,
|
|
685
715
|
user: userAccountPublicKey,
|
|
716
|
+
userTokenAccount: userTokenAccount,
|
|
686
717
|
authority: this.wallet.publicKey,
|
|
687
|
-
|
|
688
|
-
userPositions: userAccount.positions,
|
|
689
|
-
tradeHistory: state.tradeHistory,
|
|
690
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
691
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
692
|
-
oracle: priceOracle,
|
|
718
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
693
719
|
},
|
|
694
|
-
remainingAccounts
|
|
720
|
+
remainingAccounts,
|
|
695
721
|
}
|
|
696
722
|
);
|
|
697
723
|
}
|
|
698
724
|
|
|
699
|
-
public async
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
const instructions: anchor.web3.TransactionInstruction[] = [];
|
|
705
|
-
const userOrdersAccountExists = await this.userOrdersAccountExists();
|
|
706
|
-
if (!userOrdersAccountExists) {
|
|
707
|
-
instructions.push(await this.getInitializeUserOrdersInstruction());
|
|
708
|
-
}
|
|
709
|
-
instructions.push(
|
|
710
|
-
await this.getPlaceOrderIx(orderParams, discountToken, referrer)
|
|
711
|
-
);
|
|
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
|
-
}
|
|
719
|
-
|
|
720
|
-
public async placeOrder(
|
|
721
|
-
orderParams: OrderParams,
|
|
722
|
-
discountToken?: PublicKey,
|
|
723
|
-
referrer?: PublicKey
|
|
725
|
+
public async transferDeposit(
|
|
726
|
+
amount: BN,
|
|
727
|
+
bankIndex: BN,
|
|
728
|
+
fromUserId: number,
|
|
729
|
+
toUserId: number
|
|
724
730
|
): Promise<TransactionSignature> {
|
|
725
|
-
|
|
731
|
+
const { txSig } = await this.txSender.send(
|
|
726
732
|
wrapInTx(
|
|
727
|
-
await this.
|
|
733
|
+
await this.getTransferDepositIx(amount, bankIndex, fromUserId, toUserId)
|
|
728
734
|
),
|
|
729
735
|
[],
|
|
730
736
|
this.opts
|
|
731
737
|
);
|
|
738
|
+
return txSig;
|
|
732
739
|
}
|
|
733
740
|
|
|
734
|
-
public async
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
741
|
+
public async getTransferDepositIx(
|
|
742
|
+
amount: BN,
|
|
743
|
+
bankIndex: BN,
|
|
744
|
+
fromUserId: number,
|
|
745
|
+
toUserId: number
|
|
738
746
|
): Promise<TransactionInstruction> {
|
|
739
|
-
const
|
|
740
|
-
|
|
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
|
+
);
|
|
741
757
|
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
|
|
758
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
759
|
+
writableBankIndex: bankIndex,
|
|
760
|
+
});
|
|
745
761
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
)
|
|
752
|
-
}
|
|
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
|
+
}
|
|
753
772
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
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
|
|
780
|
+
);
|
|
781
|
+
return txSig;
|
|
782
|
+
}
|
|
760
783
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
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
|
+
}
|
|
767
794
|
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
795
|
+
public async openPosition(
|
|
796
|
+
direction: PositionDirection,
|
|
797
|
+
amount: BN,
|
|
798
|
+
marketIndex: BN,
|
|
799
|
+
limitPrice?: BN
|
|
800
|
+
): Promise<TransactionSignature> {
|
|
801
|
+
return await this.placeAndTake(
|
|
802
|
+
getMarketOrderParams(
|
|
803
|
+
marketIndex,
|
|
804
|
+
direction,
|
|
805
|
+
ZERO,
|
|
806
|
+
amount,
|
|
807
|
+
false,
|
|
808
|
+
limitPrice
|
|
809
|
+
)
|
|
810
|
+
);
|
|
811
|
+
}
|
|
774
812
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
813
|
+
public async placeOrder(
|
|
814
|
+
orderParams: OrderParams
|
|
815
|
+
): Promise<TransactionSignature> {
|
|
816
|
+
const { txSig, slot } = await this.txSender.send(
|
|
817
|
+
wrapInTx(await this.getPlaceOrderIx(orderParams)),
|
|
818
|
+
[],
|
|
819
|
+
this.opts
|
|
820
|
+
);
|
|
821
|
+
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
822
|
+
return txSig;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
public async getPlaceOrderIx(
|
|
826
|
+
orderParams: OrderParams
|
|
827
|
+
): Promise<TransactionInstruction> {
|
|
828
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
829
|
+
|
|
830
|
+
const priceOracle = this.getMarketAccount(orderParams.marketIndex).amm
|
|
831
|
+
.oracle;
|
|
832
|
+
|
|
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
|
-
): Promise<TransactionSignature> {
|
|
846
|
-
return await this.txSender.send(
|
|
847
|
-
wrapInTx(await this.getCancelOrderIx(orderId, oracle)),
|
|
874
|
+
public async updateAMMs(marketIndexes: BN[]): Promise<TransactionSignature> {
|
|
875
|
+
const { txSig } = await this.txSender.send(
|
|
876
|
+
wrapInTx(await this.getUpdateAMMsIx(marketIndexes)),
|
|
848
877
|
[],
|
|
849
878
|
this.opts
|
|
850
879
|
);
|
|
880
|
+
return txSig;
|
|
851
881
|
}
|
|
852
882
|
|
|
853
|
-
public async
|
|
854
|
-
|
|
855
|
-
oracle?: PublicKey
|
|
883
|
+
public async getUpdateAMMsIx(
|
|
884
|
+
marketIndexes: BN[]
|
|
856
885
|
): Promise<TransactionInstruction> {
|
|
857
|
-
|
|
858
|
-
|
|
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);
|
|
859
907
|
|
|
860
|
-
|
|
861
|
-
|
|
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
|
+
}
|
|
862
916
|
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
917
|
+
public async cancelOrder(orderId?: BN): Promise<TransactionSignature> {
|
|
918
|
+
const { txSig } = await this.txSender.send(
|
|
919
|
+
wrapInTx(await this.getCancelOrderIx(orderId)),
|
|
920
|
+
[],
|
|
921
|
+
this.opts
|
|
922
|
+
);
|
|
923
|
+
return txSig;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
public async getCancelOrderIx(orderId?: BN): Promise<TransactionInstruction> {
|
|
927
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
871
928
|
|
|
872
|
-
|
|
929
|
+
const remainingAccounts = this.getRemainingAccounts({});
|
|
930
|
+
|
|
931
|
+
return await this.program.instruction.cancelOrder(orderId ?? null, {
|
|
873
932
|
accounts: {
|
|
874
933
|
state: await this.getStatePublicKey(),
|
|
875
934
|
user: userAccountPublicKey,
|
|
876
935
|
authority: this.wallet.publicKey,
|
|
877
|
-
markets: state.markets,
|
|
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,
|
|
884
936
|
},
|
|
885
937
|
remainingAccounts,
|
|
886
938
|
});
|
|
887
939
|
}
|
|
888
940
|
|
|
889
941
|
public async cancelOrderByUserId(
|
|
890
|
-
userOrderId: number
|
|
891
|
-
oracle?: PublicKey
|
|
942
|
+
userOrderId: number
|
|
892
943
|
): Promise<TransactionSignature> {
|
|
893
|
-
|
|
894
|
-
wrapInTx(await this.getCancelOrderByUserIdIx(userOrderId
|
|
944
|
+
const { txSig } = await this.txSender.send(
|
|
945
|
+
wrapInTx(await this.getCancelOrderByUserIdIx(userOrderId)),
|
|
895
946
|
[],
|
|
896
947
|
this.opts
|
|
897
948
|
);
|
|
949
|
+
return txSig;
|
|
898
950
|
}
|
|
899
951
|
|
|
900
952
|
public async getCancelOrderByUserIdIx(
|
|
901
|
-
userOrderId: number
|
|
902
|
-
oracle?: PublicKey
|
|
953
|
+
userOrderId: number
|
|
903
954
|
): Promise<TransactionInstruction> {
|
|
904
955
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
905
|
-
const userAccount = await this.getUserAccount();
|
|
906
956
|
|
|
907
|
-
const
|
|
908
|
-
const
|
|
957
|
+
const order = this.getOrderByUserId(userOrderId);
|
|
958
|
+
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
909
959
|
|
|
910
|
-
const remainingAccounts =
|
|
911
|
-
if (oracle) {
|
|
912
|
-
remainingAccounts.push({
|
|
913
|
-
pubkey: oracle,
|
|
914
|
-
isWritable: false,
|
|
915
|
-
isSigner: false,
|
|
916
|
-
});
|
|
917
|
-
}
|
|
960
|
+
const remainingAccounts = this.getRemainingAccounts({});
|
|
918
961
|
|
|
919
962
|
return await this.program.instruction.cancelOrderByUserId(userOrderId, {
|
|
920
963
|
accounts: {
|
|
921
964
|
state: await this.getStatePublicKey(),
|
|
922
965
|
user: userAccountPublicKey,
|
|
923
966
|
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,
|
|
967
|
+
oracle,
|
|
931
968
|
},
|
|
932
969
|
remainingAccounts,
|
|
933
970
|
});
|
|
934
971
|
}
|
|
935
972
|
|
|
936
973
|
public async cancelAllOrders(
|
|
937
|
-
oracles?: PublicKey[],
|
|
938
974
|
bestEffort?: boolean
|
|
939
975
|
): Promise<TransactionSignature> {
|
|
940
|
-
|
|
941
|
-
wrapInTx(await this.getCancelAllOrdersIx(
|
|
976
|
+
const { txSig } = await this.txSender.send(
|
|
977
|
+
wrapInTx(await this.getCancelAllOrdersIx(bestEffort)),
|
|
942
978
|
[],
|
|
943
979
|
this.opts
|
|
944
980
|
);
|
|
981
|
+
return txSig;
|
|
945
982
|
}
|
|
946
983
|
|
|
947
984
|
public async getCancelAllOrdersIx(
|
|
948
|
-
oracles: PublicKey[],
|
|
949
985
|
bestEffort?: boolean
|
|
950
986
|
): Promise<TransactionInstruction> {
|
|
951
987
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
952
|
-
const userAccount = await this.getUserAccount();
|
|
953
988
|
|
|
954
|
-
const
|
|
955
|
-
const orderState = this.getOrderStateAccount();
|
|
989
|
+
const remainingAccounts = this.getRemainingAccounts({});
|
|
956
990
|
|
|
957
|
-
const
|
|
958
|
-
|
|
991
|
+
for (const order of this.getUserAccount().orders) {
|
|
992
|
+
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
959
993
|
remainingAccounts.push({
|
|
960
994
|
pubkey: oracle,
|
|
961
995
|
isWritable: false,
|
|
@@ -968,28 +1002,19 @@ export class ClearingHouse {
|
|
|
968
1002
|
state: await this.getStatePublicKey(),
|
|
969
1003
|
user: userAccountPublicKey,
|
|
970
1004
|
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
1005
|
},
|
|
979
1006
|
remainingAccounts,
|
|
980
1007
|
});
|
|
981
1008
|
}
|
|
982
1009
|
|
|
983
1010
|
public async cancelOrdersByMarketAndSide(
|
|
984
|
-
oracles?: PublicKey[],
|
|
985
1011
|
bestEffort?: boolean,
|
|
986
1012
|
marketIndexOnly?: BN,
|
|
987
1013
|
directionOnly?: PositionDirection
|
|
988
1014
|
): Promise<TransactionSignature> {
|
|
989
|
-
|
|
1015
|
+
const { txSig } = await this.txSender.send(
|
|
990
1016
|
wrapInTx(
|
|
991
1017
|
await this.getCancelOrdersByMarketAndSideIx(
|
|
992
|
-
oracles,
|
|
993
1018
|
bestEffort,
|
|
994
1019
|
marketIndexOnly,
|
|
995
1020
|
directionOnly
|
|
@@ -998,22 +1023,20 @@ export class ClearingHouse {
|
|
|
998
1023
|
[],
|
|
999
1024
|
this.opts
|
|
1000
1025
|
);
|
|
1026
|
+
return txSig;
|
|
1001
1027
|
}
|
|
1002
1028
|
|
|
1003
1029
|
public async getCancelOrdersByMarketAndSideIx(
|
|
1004
|
-
oracles: PublicKey[],
|
|
1005
1030
|
bestEffort?: boolean,
|
|
1006
1031
|
marketIndexOnly?: BN,
|
|
1007
1032
|
directionOnly?: PositionDirection
|
|
1008
1033
|
): Promise<TransactionInstruction> {
|
|
1009
1034
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1010
|
-
const userAccount = await this.getUserAccount();
|
|
1011
1035
|
|
|
1012
|
-
const
|
|
1013
|
-
const orderState = this.getOrderStateAccount();
|
|
1036
|
+
const remainingAccounts = this.getRemainingAccounts({});
|
|
1014
1037
|
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1038
|
+
for (const order of this.getUserAccount().orders) {
|
|
1039
|
+
const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
|
|
1017
1040
|
remainingAccounts.push({
|
|
1018
1041
|
pubkey: oracle,
|
|
1019
1042
|
isWritable: false,
|
|
@@ -1030,13 +1053,6 @@ export class ClearingHouse {
|
|
|
1030
1053
|
state: await this.getStatePublicKey(),
|
|
1031
1054
|
user: userAccountPublicKey,
|
|
1032
1055
|
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
1056
|
},
|
|
1041
1057
|
remainingAccounts,
|
|
1042
1058
|
}
|
|
@@ -1045,320 +1061,432 @@ export class ClearingHouse {
|
|
|
1045
1061
|
|
|
1046
1062
|
public async fillOrder(
|
|
1047
1063
|
userAccountPublicKey: PublicKey,
|
|
1048
|
-
|
|
1049
|
-
order
|
|
1064
|
+
user: UserAccount,
|
|
1065
|
+
order?: Order,
|
|
1066
|
+
makerInfo?: MakerInfo
|
|
1050
1067
|
): Promise<TransactionSignature> {
|
|
1051
|
-
|
|
1068
|
+
const { txSig } = await this.txSender.send(
|
|
1052
1069
|
wrapInTx(
|
|
1053
|
-
await this.getFillOrderIx(
|
|
1054
|
-
userAccountPublicKey,
|
|
1055
|
-
userOrdersAccountPublicKey,
|
|
1056
|
-
order
|
|
1057
|
-
)
|
|
1070
|
+
await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)
|
|
1058
1071
|
),
|
|
1059
1072
|
[],
|
|
1060
1073
|
this.opts
|
|
1061
1074
|
);
|
|
1075
|
+
return txSig;
|
|
1062
1076
|
}
|
|
1063
1077
|
|
|
1064
1078
|
public async getFillOrderIx(
|
|
1065
1079
|
userAccountPublicKey: PublicKey,
|
|
1066
|
-
|
|
1067
|
-
order: Order
|
|
1080
|
+
userAccount: UserAccount,
|
|
1081
|
+
order: Order,
|
|
1082
|
+
makerInfo?: MakerInfo
|
|
1068
1083
|
): Promise<TransactionInstruction> {
|
|
1069
1084
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1070
|
-
const userAccount: any = await this.program.account.user.fetch(
|
|
1071
|
-
userAccountPublicKey
|
|
1072
|
-
);
|
|
1073
1085
|
|
|
1074
1086
|
const marketIndex = order.marketIndex;
|
|
1075
|
-
const
|
|
1087
|
+
const marketAccount = this.getMarketAccount(marketIndex);
|
|
1088
|
+
const oracle = marketAccount.amm.oracle;
|
|
1076
1089
|
|
|
1077
|
-
const
|
|
1078
|
-
|
|
1090
|
+
const bankAccountInfos = [
|
|
1091
|
+
{
|
|
1092
|
+
pubkey: this.getQuoteAssetBankAccount().pubkey,
|
|
1093
|
+
isSigner: false,
|
|
1094
|
+
isWritable: true,
|
|
1095
|
+
},
|
|
1096
|
+
];
|
|
1097
|
+
const marketAccountInfos = [
|
|
1098
|
+
{
|
|
1099
|
+
pubkey: marketAccount.pubkey,
|
|
1100
|
+
isWritable: true,
|
|
1101
|
+
isSigner: false,
|
|
1102
|
+
},
|
|
1103
|
+
];
|
|
1104
|
+
const oracleAccountInfos = [
|
|
1105
|
+
{
|
|
1106
|
+
pubkey: marketAccount.amm.oracle,
|
|
1107
|
+
isWritable: false,
|
|
1108
|
+
isSigner: false,
|
|
1109
|
+
},
|
|
1110
|
+
];
|
|
1111
|
+
for (const position of userAccount.positions) {
|
|
1112
|
+
if (
|
|
1113
|
+
!positionIsAvailable(position) &&
|
|
1114
|
+
!position.marketIndex.eq(order.marketIndex)
|
|
1115
|
+
) {
|
|
1116
|
+
const market = this.getMarketAccount(position.marketIndex);
|
|
1117
|
+
marketAccountInfos.push({
|
|
1118
|
+
pubkey: market.pubkey,
|
|
1119
|
+
isWritable: false,
|
|
1120
|
+
isSigner: false,
|
|
1121
|
+
});
|
|
1122
|
+
oracleAccountInfos.push({
|
|
1123
|
+
pubkey: market.amm.oracle,
|
|
1124
|
+
isWritable: false,
|
|
1125
|
+
isSigner: false,
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
const remainingAccounts = oracleAccountInfos.concat(
|
|
1130
|
+
bankAccountInfos.concat(marketAccountInfos)
|
|
1131
|
+
);
|
|
1079
1132
|
|
|
1080
|
-
|
|
1081
|
-
if (!order.referrer.equals(PublicKey.default)) {
|
|
1133
|
+
if (makerInfo) {
|
|
1082
1134
|
remainingAccounts.push({
|
|
1083
|
-
pubkey:
|
|
1135
|
+
pubkey: makerInfo.maker,
|
|
1084
1136
|
isWritable: true,
|
|
1085
1137
|
isSigner: false,
|
|
1086
1138
|
});
|
|
1087
1139
|
}
|
|
1088
1140
|
|
|
1089
1141
|
const orderId = order.orderId;
|
|
1090
|
-
|
|
1142
|
+
const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
|
|
1143
|
+
return await this.program.instruction.fillOrder(orderId, makerOrderId, {
|
|
1091
1144
|
accounts: {
|
|
1092
1145
|
state: await this.getStatePublicKey(),
|
|
1093
1146
|
filler: fillerPublicKey,
|
|
1094
1147
|
user: userAccountPublicKey,
|
|
1095
1148
|
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
1149
|
oracle: oracle,
|
|
1106
1150
|
},
|
|
1107
1151
|
remainingAccounts,
|
|
1108
1152
|
});
|
|
1109
1153
|
}
|
|
1110
1154
|
|
|
1111
|
-
public async
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
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(
|
|
1133
|
-
orderParams: OrderParams,
|
|
1134
|
-
discountToken?: PublicKey,
|
|
1135
|
-
referrer?: PublicKey
|
|
1155
|
+
public async triggerOrder(
|
|
1156
|
+
userAccountPublicKey: PublicKey,
|
|
1157
|
+
user: UserAccount,
|
|
1158
|
+
order: Order
|
|
1136
1159
|
): Promise<TransactionSignature> {
|
|
1137
|
-
|
|
1138
|
-
wrapInTx(
|
|
1139
|
-
await this.getPlaceAndFillOrderIx(orderParams, discountToken, referrer)
|
|
1140
|
-
),
|
|
1160
|
+
const { txSig } = await this.txSender.send(
|
|
1161
|
+
wrapInTx(await this.getTriggerOrderIx(userAccountPublicKey, user, order)),
|
|
1141
1162
|
[],
|
|
1142
1163
|
this.opts
|
|
1143
1164
|
);
|
|
1165
|
+
return txSig;
|
|
1144
1166
|
}
|
|
1145
1167
|
|
|
1146
|
-
public async
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1168
|
+
public async getTriggerOrderIx(
|
|
1169
|
+
userAccountPublicKey: PublicKey,
|
|
1170
|
+
userAccount: UserAccount,
|
|
1171
|
+
order: Order
|
|
1150
1172
|
): Promise<TransactionInstruction> {
|
|
1151
|
-
const
|
|
1152
|
-
const userAccount = await this.getUserAccount();
|
|
1153
|
-
|
|
1154
|
-
const priceOracle =
|
|
1155
|
-
this.getMarketsAccount().markets[orderParams.marketIndex.toNumber()].amm
|
|
1156
|
-
.oracle;
|
|
1173
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1157
1174
|
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
if (!discountToken) {
|
|
1161
|
-
throw Error(
|
|
1162
|
-
'Optional accounts specified discount token but no discount token present'
|
|
1163
|
-
);
|
|
1164
|
-
}
|
|
1175
|
+
const marketIndex = order.marketIndex;
|
|
1176
|
+
const marketAccount = this.getMarketAccount(marketIndex);
|
|
1165
1177
|
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1178
|
+
const bankAccountInfos = [
|
|
1179
|
+
{
|
|
1180
|
+
pubkey: this.getQuoteAssetBankAccount().pubkey,
|
|
1169
1181
|
isSigner: false,
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
'Optional accounts specified referrer but no referrer present'
|
|
1177
|
-
);
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
remainingAccounts.push({
|
|
1181
|
-
pubkey: referrer,
|
|
1182
|
+
isWritable: true,
|
|
1183
|
+
},
|
|
1184
|
+
];
|
|
1185
|
+
const marketAccountInfos = [
|
|
1186
|
+
{
|
|
1187
|
+
pubkey: marketAccount.pubkey,
|
|
1182
1188
|
isWritable: true,
|
|
1183
1189
|
isSigner: false,
|
|
1184
|
-
}
|
|
1190
|
+
},
|
|
1191
|
+
];
|
|
1192
|
+
const oracleAccountInfos = [
|
|
1193
|
+
{
|
|
1194
|
+
pubkey: marketAccount.amm.oracle,
|
|
1195
|
+
isWritable: false,
|
|
1196
|
+
isSigner: false,
|
|
1197
|
+
},
|
|
1198
|
+
];
|
|
1199
|
+
for (const position of userAccount.positions) {
|
|
1200
|
+
if (
|
|
1201
|
+
!positionIsAvailable(position) &&
|
|
1202
|
+
!position.marketIndex.eq(order.marketIndex)
|
|
1203
|
+
) {
|
|
1204
|
+
const market = this.getMarketAccount(position.marketIndex);
|
|
1205
|
+
marketAccountInfos.push({
|
|
1206
|
+
pubkey: market.pubkey,
|
|
1207
|
+
isWritable: false,
|
|
1208
|
+
isSigner: false,
|
|
1209
|
+
});
|
|
1210
|
+
oracleAccountInfos.push({
|
|
1211
|
+
pubkey: market.amm.oracle,
|
|
1212
|
+
isWritable: false,
|
|
1213
|
+
isSigner: false,
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1185
1216
|
}
|
|
1217
|
+
const remainingAccounts = oracleAccountInfos.concat(
|
|
1218
|
+
bankAccountInfos.concat(marketAccountInfos)
|
|
1219
|
+
);
|
|
1186
1220
|
|
|
1187
|
-
const
|
|
1188
|
-
|
|
1189
|
-
return await this.program.instruction.placeAndFillOrder(orderParams, {
|
|
1221
|
+
const orderId = order.orderId;
|
|
1222
|
+
return await this.program.instruction.triggerOrder(orderId, {
|
|
1190
1223
|
accounts: {
|
|
1191
1224
|
state: await this.getStatePublicKey(),
|
|
1225
|
+
filler: fillerPublicKey,
|
|
1192
1226
|
user: userAccountPublicKey,
|
|
1193
1227
|
authority: this.wallet.publicKey,
|
|
1194
|
-
markets: state.markets,
|
|
1195
|
-
userOrders: await this.getUserOrdersAccountPublicKey(),
|
|
1196
|
-
userPositions: userAccount.positions,
|
|
1197
|
-
tradeHistory: state.tradeHistory,
|
|
1198
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
1199
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
1200
|
-
orderState: await this.getOrderStatePublicKey(),
|
|
1201
|
-
orderHistory: orderState.orderHistory,
|
|
1202
|
-
extendedCurveHistory: state.extendedCurveHistory,
|
|
1203
|
-
oracle: priceOracle,
|
|
1204
1228
|
},
|
|
1205
1229
|
remainingAccounts,
|
|
1206
1230
|
});
|
|
1207
1231
|
}
|
|
1208
1232
|
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
* @param discountToken
|
|
1213
|
-
* @param referrer
|
|
1214
|
-
* @returns
|
|
1215
|
-
*/
|
|
1216
|
-
public async closePosition(
|
|
1217
|
-
marketIndex: BN,
|
|
1218
|
-
discountToken?: PublicKey,
|
|
1219
|
-
referrer?: PublicKey
|
|
1233
|
+
public async placeAndTake(
|
|
1234
|
+
orderParams: OrderParams,
|
|
1235
|
+
makerInfo?: MakerInfo
|
|
1220
1236
|
): Promise<TransactionSignature> {
|
|
1221
|
-
|
|
1222
|
-
wrapInTx(
|
|
1223
|
-
await this.getClosePositionIx(marketIndex, discountToken, referrer)
|
|
1224
|
-
),
|
|
1237
|
+
const { txSig, slot } = await this.txSender.send(
|
|
1238
|
+
wrapInTx(await this.getPlaceAndTakeIx(orderParams, makerInfo)),
|
|
1225
1239
|
[],
|
|
1226
1240
|
this.opts
|
|
1227
1241
|
);
|
|
1242
|
+
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
1243
|
+
return txSig;
|
|
1228
1244
|
}
|
|
1229
1245
|
|
|
1230
|
-
public async
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
referrer?: PublicKey
|
|
1246
|
+
public async getPlaceAndTakeIx(
|
|
1247
|
+
orderParams: OrderParams,
|
|
1248
|
+
makerInfo?: MakerInfo
|
|
1234
1249
|
): Promise<TransactionInstruction> {
|
|
1235
1250
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1236
|
-
const userAccount = await this.getUserAccount();
|
|
1237
1251
|
|
|
1238
|
-
const priceOracle =
|
|
1239
|
-
|
|
1252
|
+
const priceOracle = this.getMarketAccount(orderParams.marketIndex).amm
|
|
1253
|
+
.oracle;
|
|
1240
1254
|
|
|
1241
|
-
const
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
};
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1255
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1256
|
+
writableMarketIndex: orderParams.marketIndex,
|
|
1257
|
+
writableBankIndex: QUOTE_ASSET_BANK_INDEX,
|
|
1258
|
+
});
|
|
1259
|
+
|
|
1260
|
+
let makerOrderId = null;
|
|
1261
|
+
if (makerInfo) {
|
|
1262
|
+
makerOrderId = makerInfo.order.orderId;
|
|
1248
1263
|
remainingAccounts.push({
|
|
1249
|
-
pubkey:
|
|
1250
|
-
isWritable: false,
|
|
1264
|
+
pubkey: makerInfo.maker,
|
|
1251
1265
|
isSigner: false,
|
|
1252
|
-
});
|
|
1253
|
-
}
|
|
1254
|
-
if (referrer) {
|
|
1255
|
-
optionalAccounts.referrer = true;
|
|
1256
|
-
remainingAccounts.push({
|
|
1257
|
-
pubkey: referrer,
|
|
1258
1266
|
isWritable: true,
|
|
1259
|
-
isSigner: false,
|
|
1260
1267
|
});
|
|
1261
1268
|
}
|
|
1262
1269
|
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
optionalAccounts,
|
|
1270
|
+
return await this.program.instruction.placeAndTake(
|
|
1271
|
+
orderParams,
|
|
1272
|
+
makerOrderId,
|
|
1267
1273
|
{
|
|
1268
1274
|
accounts: {
|
|
1269
1275
|
state: await this.getStatePublicKey(),
|
|
1270
1276
|
user: userAccountPublicKey,
|
|
1271
1277
|
authority: this.wallet.publicKey,
|
|
1272
|
-
markets: state.markets,
|
|
1273
|
-
userPositions: userAccount.positions,
|
|
1274
|
-
tradeHistory: state.tradeHistory,
|
|
1275
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
1276
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
1277
1278
|
oracle: priceOracle,
|
|
1278
1279
|
},
|
|
1279
|
-
remainingAccounts
|
|
1280
|
+
remainingAccounts,
|
|
1280
1281
|
}
|
|
1281
1282
|
);
|
|
1282
1283
|
}
|
|
1283
1284
|
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1285
|
+
/**
|
|
1286
|
+
* Close an entire position. If you want to reduce a position, use the {@link openPosition} method in the opposite direction of the current position.
|
|
1287
|
+
* @param marketIndex
|
|
1288
|
+
* @returns
|
|
1289
|
+
*/
|
|
1290
|
+
public async closePosition(marketIndex: BN): Promise<TransactionSignature> {
|
|
1291
|
+
const userPosition = this.getUser().getUserPosition(marketIndex);
|
|
1292
|
+
if (!userPosition) {
|
|
1293
|
+
throw Error(`No position in market ${marketIndex.toString()}`);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
return await this.placeAndTake(
|
|
1297
|
+
getMarketOrderParams(
|
|
1298
|
+
marketIndex,
|
|
1299
|
+
findDirectionToClose(userPosition),
|
|
1300
|
+
ZERO,
|
|
1301
|
+
userPosition.baseAssetAmount,
|
|
1302
|
+
true,
|
|
1303
|
+
undefined
|
|
1304
|
+
)
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1294
1307
|
|
|
1308
|
+
public async settlePNLs(
|
|
1309
|
+
users: {
|
|
1310
|
+
settleeUserAccountPublicKey: PublicKey;
|
|
1311
|
+
settleeUserAccount: UserAccount;
|
|
1312
|
+
}[],
|
|
1313
|
+
marketIndex: BN
|
|
1314
|
+
): Promise<TransactionSignature> {
|
|
1315
|
+
const ixs = [];
|
|
1316
|
+
for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
|
|
1295
1317
|
ixs.push(
|
|
1296
|
-
await this.
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1318
|
+
await this.settlePNLIx(
|
|
1319
|
+
settleeUserAccountPublicKey,
|
|
1320
|
+
settleeUserAccount,
|
|
1321
|
+
marketIndex
|
|
1300
1322
|
)
|
|
1301
1323
|
);
|
|
1302
1324
|
}
|
|
1303
1325
|
|
|
1304
1326
|
const tx = new Transaction().add(...ixs);
|
|
1305
1327
|
|
|
1306
|
-
|
|
1328
|
+
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
1329
|
+
return txSig;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
public async settlePNL(
|
|
1333
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
1334
|
+
settleeUserAccount: UserAccount,
|
|
1335
|
+
marketIndex: BN
|
|
1336
|
+
): Promise<TransactionSignature> {
|
|
1337
|
+
const { txSig } = await this.txSender.send(
|
|
1338
|
+
wrapInTx(
|
|
1339
|
+
await this.settlePNLIx(
|
|
1340
|
+
settleeUserAccountPublicKey,
|
|
1341
|
+
settleeUserAccount,
|
|
1342
|
+
marketIndex
|
|
1343
|
+
)
|
|
1344
|
+
),
|
|
1345
|
+
[],
|
|
1346
|
+
this.opts
|
|
1347
|
+
);
|
|
1348
|
+
return txSig;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
public async settlePNLIx(
|
|
1352
|
+
settleeUserAccountPublicKey: PublicKey,
|
|
1353
|
+
settleeUserAccount: UserAccount,
|
|
1354
|
+
marketIndex: BN
|
|
1355
|
+
): Promise<TransactionInstruction> {
|
|
1356
|
+
const marketAccountMap = new Map<number, AccountMeta>();
|
|
1357
|
+
const oracleAccountMap = new Map<string, AccountMeta>();
|
|
1358
|
+
const bankAccountMap = new Map<number, AccountMeta>();
|
|
1359
|
+
for (const position of settleeUserAccount.positions) {
|
|
1360
|
+
if (!positionIsAvailable(position)) {
|
|
1361
|
+
const market = this.getMarketAccount(position.marketIndex);
|
|
1362
|
+
marketAccountMap.set(position.marketIndex.toNumber(), {
|
|
1363
|
+
pubkey: market.pubkey,
|
|
1364
|
+
isWritable: true, // TODO
|
|
1365
|
+
isSigner: false,
|
|
1366
|
+
});
|
|
1367
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1368
|
+
pubkey: market.amm.oracle,
|
|
1369
|
+
isWritable: false,
|
|
1370
|
+
isSigner: false,
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
for (const userBankBalance of settleeUserAccount.bankBalances) {
|
|
1376
|
+
if (!userBankBalance.balance.eq(QUOTE_ASSET_BANK_INDEX)) {
|
|
1377
|
+
const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
|
|
1378
|
+
bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
|
|
1379
|
+
pubkey: bankAccount.pubkey,
|
|
1380
|
+
isSigner: false,
|
|
1381
|
+
isWritable: false,
|
|
1382
|
+
});
|
|
1383
|
+
if (!bankAccount.bankIndex.eq(ZERO)) {
|
|
1384
|
+
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
1385
|
+
pubkey: bankAccount.oracle,
|
|
1386
|
+
isSigner: false,
|
|
1387
|
+
isWritable: false,
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
const marketAccount = this.getMarketAccount(marketIndex.toNumber());
|
|
1394
|
+
marketAccountMap.set(marketIndex.toNumber(), {
|
|
1395
|
+
pubkey: marketAccount.pubkey,
|
|
1396
|
+
isSigner: false,
|
|
1397
|
+
isWritable: true,
|
|
1398
|
+
});
|
|
1399
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1400
|
+
pubkey: marketAccount.amm.oracle,
|
|
1401
|
+
isSigner: false,
|
|
1402
|
+
isWritable: false,
|
|
1403
|
+
});
|
|
1404
|
+
|
|
1405
|
+
bankAccountMap.set(QUOTE_ASSET_BANK_INDEX.toNumber(), {
|
|
1406
|
+
pubkey: this.getBankAccount(QUOTE_ASSET_BANK_INDEX).pubkey,
|
|
1407
|
+
isSigner: false,
|
|
1408
|
+
isWritable: true,
|
|
1409
|
+
});
|
|
1410
|
+
|
|
1411
|
+
const remainingAccounts = [
|
|
1412
|
+
...oracleAccountMap.values(),
|
|
1413
|
+
...bankAccountMap.values(),
|
|
1414
|
+
...marketAccountMap.values(),
|
|
1415
|
+
];
|
|
1416
|
+
|
|
1417
|
+
return await this.program.instruction.settlePnl(marketIndex, {
|
|
1418
|
+
accounts: {
|
|
1419
|
+
state: await this.getStatePublicKey(),
|
|
1420
|
+
authority: this.wallet.publicKey,
|
|
1421
|
+
user: settleeUserAccountPublicKey,
|
|
1422
|
+
},
|
|
1423
|
+
remainingAccounts: remainingAccounts,
|
|
1424
|
+
});
|
|
1307
1425
|
}
|
|
1308
1426
|
|
|
1309
1427
|
public async liquidate(
|
|
1310
1428
|
liquidateeUserAccountPublicKey: PublicKey
|
|
1311
1429
|
): Promise<TransactionSignature> {
|
|
1312
|
-
|
|
1430
|
+
const { txSig } = await this.txSender.send(
|
|
1313
1431
|
wrapInTx(await this.getLiquidateIx(liquidateeUserAccountPublicKey)),
|
|
1314
1432
|
[],
|
|
1315
1433
|
this.opts
|
|
1316
1434
|
);
|
|
1435
|
+
return txSig;
|
|
1317
1436
|
}
|
|
1318
1437
|
|
|
1319
1438
|
public async getLiquidateIx(
|
|
1320
1439
|
liquidateeUserAccountPublicKey: PublicKey
|
|
1321
1440
|
): Promise<TransactionInstruction> {
|
|
1322
1441
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1323
|
-
|
|
1324
|
-
const liquidateeUserAccount: any = await this.program.account.user.fetch(
|
|
1442
|
+
const liquidateeUserAccount = (await this.program.account.user.fetch(
|
|
1325
1443
|
liquidateeUserAccountPublicKey
|
|
1326
|
-
);
|
|
1327
|
-
const liquidateePositions: any =
|
|
1328
|
-
await this.program.account.userPositions.fetch(
|
|
1329
|
-
liquidateeUserAccount.positions
|
|
1330
|
-
);
|
|
1331
|
-
const markets = this.getMarketsAccount();
|
|
1444
|
+
)) as UserAccount;
|
|
1332
1445
|
|
|
1333
|
-
const
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1446
|
+
const bankAccountInfos = [
|
|
1447
|
+
{
|
|
1448
|
+
pubkey: this.getQuoteAssetBankAccount().pubkey,
|
|
1449
|
+
isSigner: false,
|
|
1450
|
+
isWritable: true,
|
|
1451
|
+
},
|
|
1452
|
+
];
|
|
1453
|
+
const marketAccountInfos = [];
|
|
1454
|
+
const oracleAccountInfos = [];
|
|
1455
|
+
for (const position of liquidateeUserAccount.positions) {
|
|
1456
|
+
if (!positionIsAvailable(position)) {
|
|
1457
|
+
const market = this.getMarketAccount(position.marketIndex);
|
|
1458
|
+
const marketPublicKey = await getMarketPublicKey(
|
|
1459
|
+
this.program.programId,
|
|
1460
|
+
position.marketIndex
|
|
1461
|
+
);
|
|
1462
|
+
marketAccountInfos.push({
|
|
1463
|
+
pubkey: marketPublicKey,
|
|
1464
|
+
isWritable: true,
|
|
1465
|
+
isSigner: false,
|
|
1466
|
+
});
|
|
1467
|
+
oracleAccountInfos.push({
|
|
1338
1468
|
pubkey: market.amm.oracle,
|
|
1339
1469
|
isWritable: false,
|
|
1340
1470
|
isSigner: false,
|
|
1341
1471
|
});
|
|
1342
1472
|
}
|
|
1343
1473
|
}
|
|
1474
|
+
const remainingAccounts = oracleAccountInfos.concat(
|
|
1475
|
+
bankAccountInfos.concat(marketAccountInfos)
|
|
1476
|
+
);
|
|
1344
1477
|
|
|
1345
1478
|
const state = this.getStateAccount();
|
|
1479
|
+
const quoteAssetBankAccount = this.getQuoteAssetBankAccount();
|
|
1346
1480
|
return await this.program.instruction.liquidate({
|
|
1347
1481
|
accounts: {
|
|
1348
1482
|
state: await this.getStatePublicKey(),
|
|
1349
1483
|
authority: this.wallet.publicKey,
|
|
1350
1484
|
user: liquidateeUserAccountPublicKey,
|
|
1351
1485
|
liquidator: userAccountPublicKey,
|
|
1352
|
-
|
|
1353
|
-
|
|
1486
|
+
bankVault: quoteAssetBankAccount.vault,
|
|
1487
|
+
bankVaultAuthority: quoteAssetBankAccount.vaultAuthority,
|
|
1354
1488
|
insuranceVault: state.insuranceVault,
|
|
1355
|
-
insuranceVaultAuthority: state.insuranceVaultAuthority,
|
|
1356
1489
|
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
1490
|
},
|
|
1363
1491
|
remainingAccounts: remainingAccounts,
|
|
1364
1492
|
});
|
|
@@ -1368,54 +1496,68 @@ export class ClearingHouse {
|
|
|
1368
1496
|
oracle: PublicKey,
|
|
1369
1497
|
marketIndex: BN
|
|
1370
1498
|
): Promise<TransactionSignature> {
|
|
1371
|
-
|
|
1499
|
+
const { txSig } = await this.txSender.send(
|
|
1372
1500
|
wrapInTx(await this.getUpdateFundingRateIx(oracle, marketIndex)),
|
|
1373
1501
|
[],
|
|
1374
1502
|
this.opts
|
|
1375
1503
|
);
|
|
1504
|
+
return txSig;
|
|
1376
1505
|
}
|
|
1377
1506
|
|
|
1378
1507
|
public async getUpdateFundingRateIx(
|
|
1379
1508
|
oracle: PublicKey,
|
|
1380
1509
|
marketIndex: BN
|
|
1381
1510
|
): Promise<TransactionInstruction> {
|
|
1382
|
-
const state = this.getStateAccount();
|
|
1383
1511
|
return await this.program.instruction.updateFundingRate(marketIndex, {
|
|
1384
1512
|
accounts: {
|
|
1385
1513
|
state: await this.getStatePublicKey(),
|
|
1386
|
-
|
|
1514
|
+
market: await getMarketPublicKey(this.program.programId, marketIndex),
|
|
1387
1515
|
oracle: oracle,
|
|
1388
|
-
fundingRateHistory: state.fundingRateHistory,
|
|
1389
1516
|
},
|
|
1390
1517
|
});
|
|
1391
1518
|
}
|
|
1392
1519
|
|
|
1393
1520
|
public async settleFundingPayment(
|
|
1394
|
-
userAccount: PublicKey
|
|
1395
|
-
userPositionsAccount: PublicKey
|
|
1521
|
+
userAccount: PublicKey
|
|
1396
1522
|
): Promise<TransactionSignature> {
|
|
1397
|
-
|
|
1398
|
-
wrapInTx(
|
|
1399
|
-
await this.getSettleFundingPaymentIx(userAccount, userPositionsAccount)
|
|
1400
|
-
),
|
|
1523
|
+
const { txSig } = await this.txSender.send(
|
|
1524
|
+
wrapInTx(await this.getSettleFundingPaymentIx(userAccount)),
|
|
1401
1525
|
[],
|
|
1402
1526
|
this.opts
|
|
1403
1527
|
);
|
|
1528
|
+
return txSig;
|
|
1404
1529
|
}
|
|
1405
1530
|
|
|
1406
1531
|
public async getSettleFundingPaymentIx(
|
|
1407
|
-
userAccount: PublicKey
|
|
1408
|
-
userPositionsAccount: PublicKey
|
|
1532
|
+
userAccount: PublicKey
|
|
1409
1533
|
): Promise<TransactionInstruction> {
|
|
1410
|
-
const
|
|
1534
|
+
const user = (await this.program.account.user.fetch(
|
|
1535
|
+
userAccount
|
|
1536
|
+
)) as UserAccount;
|
|
1537
|
+
|
|
1538
|
+
const userPositions = user.positions;
|
|
1539
|
+
|
|
1540
|
+
const remainingAccounts = [];
|
|
1541
|
+
for (const position of userPositions) {
|
|
1542
|
+
if (!positionIsAvailable(position)) {
|
|
1543
|
+
const marketPublicKey = await getMarketPublicKey(
|
|
1544
|
+
this.program.programId,
|
|
1545
|
+
position.marketIndex
|
|
1546
|
+
);
|
|
1547
|
+
remainingAccounts.push({
|
|
1548
|
+
pubkey: marketPublicKey,
|
|
1549
|
+
isWritable: false,
|
|
1550
|
+
isSigner: false,
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1411
1555
|
return await this.program.instruction.settleFundingPayment({
|
|
1412
1556
|
accounts: {
|
|
1413
1557
|
state: await this.getStatePublicKey(),
|
|
1414
|
-
markets: state.markets,
|
|
1415
1558
|
user: userAccount,
|
|
1416
|
-
userPositions: userPositionsAccount,
|
|
1417
|
-
fundingPaymentHistory: state.fundingPaymentHistory,
|
|
1418
1559
|
},
|
|
1560
|
+
remainingAccounts,
|
|
1419
1561
|
});
|
|
1420
1562
|
}
|
|
1421
1563
|
|
|
@@ -1423,121 +1565,10 @@ export class ClearingHouse {
|
|
|
1423
1565
|
this.eventEmitter.emit(eventName, data);
|
|
1424
1566
|
}
|
|
1425
1567
|
|
|
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
|
-
}
|
|
1568
|
+
public getOracleDataForMarket(marketIndex: BN): OraclePriceData {
|
|
1569
|
+
const oracleKey = this.getMarketAccount(marketIndex).amm.oracle;
|
|
1570
|
+
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
1437
1571
|
|
|
1438
|
-
|
|
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
|
-
}
|
|
1534
|
-
|
|
1535
|
-
public async updateUserForgoSettlement(): Promise<TransactionSignature> {
|
|
1536
|
-
return await this.program.rpc.updateUserForgoSettlement({
|
|
1537
|
-
accounts: {
|
|
1538
|
-
authority: this.wallet.publicKey,
|
|
1539
|
-
user: await this.getUserAccountPublicKey(),
|
|
1540
|
-
},
|
|
1541
|
-
});
|
|
1572
|
+
return oracleData;
|
|
1542
1573
|
}
|
|
1543
1574
|
}
|