@drift-labs/sdk 0.2.0-temp.2 → 2.0.1

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.
Files changed (278) hide show
  1. package/README.md +27 -29
  2. package/lib/accounts/bulkAccountLoader.d.ts +2 -0
  3. package/lib/accounts/bulkAccountLoader.js +36 -29
  4. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  5. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  6. package/lib/accounts/bulkUserSubscription.d.ts +2 -2
  7. package/lib/accounts/bulkUserSubscription.js +0 -1
  8. package/lib/accounts/fetch.d.ts +2 -1
  9. package/lib/accounts/fetch.js +9 -1
  10. package/lib/accounts/{pollingClearingHouseAccountSubscriber.d.ts → pollingDriftClientAccountSubscriber.d.ts} +20 -25
  11. package/lib/accounts/{pollingClearingHouseAccountSubscriber.js → pollingDriftClientAccountSubscriber.js} +45 -49
  12. package/lib/accounts/{pollingOracleSubscriber.d.ts → pollingOracleAccountSubscriber.d.ts} +2 -2
  13. package/lib/accounts/{pollingOracleSubscriber.js → pollingOracleAccountSubscriber.js} +3 -3
  14. package/lib/accounts/pollingUserAccountSubscriber.d.ts +1 -1
  15. package/lib/accounts/pollingUserAccountSubscriber.js +5 -11
  16. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  17. package/lib/accounts/pollingUserStatsAccountSubscriber.js +107 -0
  18. package/lib/accounts/types.d.ts +26 -15
  19. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +49 -0
  20. package/lib/accounts/{webSocketClearingHouseAccountSubscriber.js → webSocketDriftClientAccountSubscriber.js} +47 -45
  21. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  22. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  23. package/lib/addresses/marketAddresses.d.ts +1 -3
  24. package/lib/addresses/marketAddresses.js +1 -1
  25. package/lib/addresses/pda.d.ts +15 -9
  26. package/lib/addresses/pda.js +73 -35
  27. package/lib/adminClient.d.ts +65 -0
  28. package/lib/adminClient.js +637 -0
  29. package/lib/config.d.ts +10 -10
  30. package/lib/config.js +26 -22
  31. package/lib/constants/numericConstants.d.ts +29 -12
  32. package/lib/constants/numericConstants.js +40 -21
  33. package/lib/constants/perpMarkets.d.ts +18 -0
  34. package/lib/constants/{markets.js → perpMarkets.js} +20 -9
  35. package/lib/constants/spotMarkets.d.ts +19 -0
  36. package/lib/constants/spotMarkets.js +63 -0
  37. package/lib/dlob/DLOB.d.ts +82 -0
  38. package/lib/dlob/DLOB.js +694 -0
  39. package/lib/dlob/DLOBNode.d.ts +54 -0
  40. package/lib/dlob/DLOBNode.js +77 -0
  41. package/lib/dlob/NodeList.d.ts +27 -0
  42. package/lib/dlob/NodeList.js +144 -0
  43. package/lib/driftClient.d.ts +234 -0
  44. package/lib/driftClient.js +2108 -0
  45. package/lib/{clearingHouseConfig.d.ts → driftClientConfig.d.ts} +9 -9
  46. package/lib/{clearingHouseConfig.js → driftClientConfig.js} +0 -0
  47. package/lib/events/eventList.d.ts +0 -1
  48. package/lib/events/eventList.js +0 -7
  49. package/lib/events/eventSubscriber.d.ts +5 -2
  50. package/lib/events/eventSubscriber.js +25 -11
  51. package/lib/events/fetchLogs.d.ts +13 -2
  52. package/lib/events/fetchLogs.js +45 -14
  53. package/lib/events/pollingLogProvider.d.ts +2 -1
  54. package/lib/events/pollingLogProvider.js +7 -3
  55. package/lib/events/sort.js +8 -11
  56. package/lib/events/txEventCache.d.ts +0 -2
  57. package/lib/events/txEventCache.js +0 -14
  58. package/lib/events/types.d.ts +11 -3
  59. package/lib/events/types.js +8 -0
  60. package/lib/events/webSocketLogProvider.js +1 -1
  61. package/lib/examples/makeTradeExample.js +30 -18
  62. package/lib/factory/bigNum.d.ts +8 -4
  63. package/lib/factory/bigNum.js +109 -19
  64. package/lib/idl/drift.json +8392 -0
  65. package/lib/index.d.ts +29 -12
  66. package/lib/index.js +29 -12
  67. package/lib/math/amm.d.ts +9 -6
  68. package/lib/math/amm.js +91 -38
  69. package/lib/math/conversion.js +1 -1
  70. package/lib/math/exchangeStatus.d.ts +4 -0
  71. package/lib/math/exchangeStatus.js +18 -0
  72. package/lib/math/funding.d.ts +6 -6
  73. package/lib/math/funding.js +23 -21
  74. package/lib/math/insurance.d.ts +4 -0
  75. package/lib/math/insurance.js +27 -0
  76. package/lib/math/margin.d.ts +11 -0
  77. package/lib/math/margin.js +82 -0
  78. package/lib/math/market.d.ts +14 -9
  79. package/lib/math/market.js +70 -10
  80. package/lib/math/oracles.d.ts +4 -0
  81. package/lib/math/oracles.js +36 -8
  82. package/lib/math/orders.d.ts +16 -6
  83. package/lib/math/orders.js +97 -17
  84. package/lib/math/position.d.ts +27 -13
  85. package/lib/math/position.js +91 -37
  86. package/lib/math/repeg.js +17 -8
  87. package/lib/math/spotBalance.d.ts +22 -0
  88. package/lib/math/spotBalance.js +192 -0
  89. package/lib/math/spotMarket.d.ts +4 -0
  90. package/lib/math/spotMarket.js +8 -0
  91. package/lib/math/spotPosition.d.ts +6 -0
  92. package/lib/math/spotPosition.js +23 -0
  93. package/lib/math/trade.d.ts +10 -10
  94. package/lib/math/trade.js +27 -31
  95. package/lib/oracles/pythClient.js +1 -1
  96. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  97. package/lib/oracles/switchboardClient.js +1 -1
  98. package/lib/orderParams.d.ts +4 -4
  99. package/lib/orderParams.js +12 -4
  100. package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
  101. package/lib/serum/serumFulfillmentConfigMap.js +17 -0
  102. package/lib/serum/serumSubscriber.d.ts +27 -0
  103. package/lib/serum/serumSubscriber.js +56 -0
  104. package/lib/serum/types.d.ts +11 -0
  105. package/{src/oracles → lib/serum}/types.js +0 -0
  106. package/lib/tokenFaucet.d.ts +1 -0
  107. package/lib/tokenFaucet.js +23 -12
  108. package/lib/tx/retryTxSender.d.ts +1 -1
  109. package/lib/tx/retryTxSender.js +13 -4
  110. package/lib/tx/types.d.ts +1 -1
  111. package/lib/types.d.ts +631 -222
  112. package/lib/types.js +137 -24
  113. package/lib/user.d.ts +228 -0
  114. package/lib/user.js +959 -0
  115. package/lib/userConfig.d.ts +14 -0
  116. package/lib/{clearingHouseUserConfig.js → userConfig.js} +0 -0
  117. package/lib/userMap/userMap.d.ts +41 -0
  118. package/lib/userMap/userMap.js +85 -0
  119. package/lib/userMap/userStatsMap.d.ts +19 -0
  120. package/lib/userMap/userStatsMap.js +68 -0
  121. package/lib/userName.d.ts +1 -0
  122. package/lib/userName.js +3 -2
  123. package/lib/userStats.d.ts +18 -0
  124. package/lib/userStats.js +49 -0
  125. package/lib/userStatsConfig.d.ts +14 -0
  126. package/{src/clearingHouseConfig.js → lib/userStatsConfig.js} +0 -0
  127. package/lib/util/getTokenAddress.d.ts +2 -0
  128. package/lib/util/getTokenAddress.js +9 -0
  129. package/package.json +12 -5
  130. package/src/accounts/bulkAccountLoader.ts +44 -34
  131. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  132. package/src/accounts/bulkUserSubscription.ts +2 -3
  133. package/src/accounts/fetch.ts +27 -2
  134. package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
  135. package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
  136. package/src/accounts/pollingUserAccountSubscriber.ts +5 -12
  137. package/src/accounts/pollingUserStatsAccountSubscriber.ts +166 -0
  138. package/src/accounts/types.ts +35 -15
  139. package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
  140. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  141. package/src/addresses/marketAddresses.ts +3 -4
  142. package/src/addresses/pda.ts +105 -33
  143. package/src/adminClient.ts +1207 -0
  144. package/src/config.ts +41 -34
  145. package/src/constants/numericConstants.ts +59 -26
  146. package/src/constants/{markets.ts → perpMarkets.ts} +22 -11
  147. package/src/constants/spotMarkets.ts +83 -0
  148. package/src/dlob/DLOB.ts +1120 -0
  149. package/src/dlob/DLOBNode.ts +155 -0
  150. package/src/dlob/NodeList.ts +195 -0
  151. package/src/driftClient.ts +3594 -0
  152. package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
  153. package/src/events/eventList.ts +1 -8
  154. package/src/events/eventSubscriber.ts +36 -14
  155. package/src/events/fetchLogs.ts +60 -15
  156. package/src/events/pollingLogProvider.ts +11 -3
  157. package/src/events/sort.ts +11 -15
  158. package/src/events/txEventCache.ts +0 -16
  159. package/src/events/types.ts +27 -2
  160. package/src/events/webSocketLogProvider.ts +1 -1
  161. package/src/examples/makeTradeExample.js +152 -75
  162. package/src/examples/makeTradeExample.ts +44 -28
  163. package/src/factory/bigNum.ts +150 -22
  164. package/src/idl/drift.json +8392 -0
  165. package/src/idl/pyth.json +98 -2
  166. package/src/index.ts +29 -12
  167. package/src/math/amm.ts +161 -48
  168. package/src/math/conversion.ts +2 -2
  169. package/src/math/exchangeStatus.ts +31 -0
  170. package/src/math/funding.ts +41 -31
  171. package/src/math/insurance.ts +35 -0
  172. package/src/math/margin.ts +133 -0
  173. package/src/math/market.ts +143 -14
  174. package/src/math/oracles.ts +63 -9
  175. package/src/math/orders.ts +168 -26
  176. package/src/math/position.ts +133 -59
  177. package/src/math/repeg.ts +19 -9
  178. package/src/math/spotBalance.ts +319 -0
  179. package/src/math/spotMarket.ts +9 -0
  180. package/src/math/spotPosition.ts +47 -0
  181. package/src/math/trade.ts +33 -37
  182. package/src/oracles/pythClient.ts +2 -2
  183. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  184. package/src/oracles/switchboardClient.ts +2 -2
  185. package/src/orderParams.ts +16 -8
  186. package/src/serum/serumFulfillmentConfigMap.ts +26 -0
  187. package/src/serum/serumSubscriber.ts +99 -0
  188. package/src/serum/types.ts +13 -0
  189. package/src/tokenFaucet.ts +38 -15
  190. package/src/tx/retryTxSender.ts +16 -5
  191. package/src/tx/types.ts +2 -1
  192. package/src/types.ts +594 -195
  193. package/src/user.ts +1599 -0
  194. package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
  195. package/src/userMap/userMap.ts +124 -0
  196. package/src/userMap/userStatsMap.ts +108 -0
  197. package/src/userName.ts +2 -1
  198. package/src/userStats.ts +75 -0
  199. package/src/userStatsConfig.ts +18 -0
  200. package/src/util/getTokenAddress.ts +18 -0
  201. package/tests/bn/test.ts +46 -11
  202. package/tests/dlob/helpers.ts +619 -0
  203. package/tests/dlob/test.ts +4586 -0
  204. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
  205. package/lib/admin.d.ts +0 -44
  206. package/lib/admin.js +0 -438
  207. package/lib/clearingHouse.d.ts +0 -146
  208. package/lib/clearingHouse.js +0 -1154
  209. package/lib/clearingHouseUser.d.ts +0 -187
  210. package/lib/clearingHouseUser.js +0 -634
  211. package/lib/clearingHouseUserConfig.d.ts +0 -14
  212. package/lib/constants/banks.d.ts +0 -16
  213. package/lib/constants/banks.js +0 -41
  214. package/lib/constants/markets.d.ts +0 -19
  215. package/lib/idl/clearing_house.json +0 -4464
  216. package/lib/math/bankBalance.d.ts +0 -9
  217. package/lib/math/bankBalance.js +0 -75
  218. package/lib/math/state.d.ts +0 -8
  219. package/lib/math/state.js +0 -15
  220. package/lib/orders.d.ts +0 -8
  221. package/lib/orders.js +0 -134
  222. package/src/accounts/bulkAccountLoader.js +0 -197
  223. package/src/accounts/bulkUserSubscription.js +0 -33
  224. package/src/accounts/pollingClearingHouseAccountSubscriber.js +0 -311
  225. package/src/accounts/pollingOracleSubscriber.js +0 -93
  226. package/src/accounts/pollingTokenAccountSubscriber.js +0 -90
  227. package/src/accounts/pollingUserAccountSubscriber.js +0 -132
  228. package/src/accounts/types.js +0 -10
  229. package/src/accounts/utils.js +0 -7
  230. package/src/accounts/webSocketAccountSubscriber.js +0 -93
  231. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +0 -233
  232. package/src/accounts/webSocketUserAccountSubscriber.js +0 -62
  233. package/src/addresses/marketAddresses.js +0 -26
  234. package/src/admin.js +0 -517
  235. package/src/admin.ts +0 -730
  236. package/src/clearingHouse.ts +0 -1828
  237. package/src/clearingHouseUser.ts +0 -978
  238. package/src/clearingHouseUserConfig.js +0 -2
  239. package/src/config.js +0 -67
  240. package/src/constants/banks.js +0 -42
  241. package/src/constants/banks.ts +0 -50
  242. package/src/constants/markets.js +0 -42
  243. package/src/constants/numericConstants.js +0 -41
  244. package/src/events/eventSubscriber.js +0 -139
  245. package/src/events/fetchLogs.js +0 -50
  246. package/src/events/pollingLogProvider.js +0 -64
  247. package/src/events/sort.js +0 -44
  248. package/src/events/txEventCache.js +0 -71
  249. package/src/events/types.js +0 -20
  250. package/src/events/webSocketLogProvider.js +0 -41
  251. package/src/factory/bigNum.js +0 -390
  252. package/src/factory/oracleClient.js +0 -20
  253. package/src/idl/clearing_house.json +0 -4464
  254. package/src/index.js +0 -69
  255. package/src/math/amm.js +0 -369
  256. package/src/math/auction.js +0 -42
  257. package/src/math/bankBalance.ts +0 -112
  258. package/src/math/conversion.js +0 -11
  259. package/src/math/funding.js +0 -248
  260. package/src/math/oracles.js +0 -26
  261. package/src/math/repeg.js +0 -128
  262. package/src/math/state.js +0 -15
  263. package/src/math/state.ts +0 -14
  264. package/src/math/trade.js +0 -253
  265. package/src/math/utils.js +0 -26
  266. package/src/math/utils.js.map +0 -1
  267. package/src/mockUSDCFaucet.js +0 -280
  268. package/src/oracles/oracleClientCache.js +0 -19
  269. package/src/oracles/pythClient.js +0 -46
  270. package/src/oracles/quoteAssetOracleClient.js +0 -32
  271. package/src/oracles/switchboardClient.js +0 -69
  272. package/src/orderParams.js +0 -20
  273. package/src/orders.ts +0 -245
  274. package/src/slot/SlotSubscriber.js +0 -39
  275. package/src/tokenFaucet.js +0 -189
  276. package/src/types.js +0 -125
  277. package/src/userName.js +0 -20
  278. package/src/wallet.js +0 -35
@@ -1,1828 +0,0 @@
1
- import { AnchorProvider, BN, Idl, Program } from '@project-serum/anchor';
2
- import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
3
- import {
4
- StateAccount,
5
- IWallet,
6
- PositionDirection,
7
- UserAccount,
8
- MarketAccount,
9
- OrderParams,
10
- Order,
11
- BankAccount,
12
- UserBankBalance,
13
- MakerInfo,
14
- TakerInfo,
15
- OptionalOrderParams,
16
- DefaultOrderParams,
17
- OrderType,
18
- } from './types';
19
- import * as anchor from '@project-serum/anchor';
20
- import clearingHouseIDL from './idl/clearing_house.json';
21
-
22
- import {
23
- Connection,
24
- PublicKey,
25
- TransactionSignature,
26
- ConfirmOptions,
27
- Transaction,
28
- TransactionInstruction,
29
- AccountMeta,
30
- } from '@solana/web3.js';
31
-
32
- import { TokenFaucet } from './tokenFaucet';
33
- import { EventEmitter } from 'events';
34
- import StrictEventEmitter from 'strict-event-emitter-types';
35
- import {
36
- getClearingHouseStateAccountPublicKey,
37
- getMarketPublicKey,
38
- getUserAccountPublicKey,
39
- getUserAccountPublicKeySync,
40
- } from './addresses/pda';
41
- import {
42
- ClearingHouseAccountSubscriber,
43
- ClearingHouseAccountEvents,
44
- DataAndSlot,
45
- } from './accounts/types';
46
- import { TxSender } from './tx/types';
47
- import { wrapInTx } from './tx/utils';
48
- import { QUOTE_ASSET_BANK_INDEX, ZERO } from './constants/numericConstants';
49
- import { findDirectionToClose, positionIsAvailable } from './math/position';
50
- import { getTokenAmount } from './math/bankBalance';
51
- import { DEFAULT_USER_NAME, encodeName } from './userName';
52
- import { OraclePriceData } from './oracles/types';
53
- import { ClearingHouseConfig } from './clearingHouseConfig';
54
- import { PollingClearingHouseAccountSubscriber } from './accounts/pollingClearingHouseAccountSubscriber';
55
- import { WebSocketClearingHouseAccountSubscriber } from './accounts/webSocketClearingHouseAccountSubscriber';
56
- import { RetryTxSender } from './tx/retryTxSender';
57
- import { ClearingHouseUser } from './clearingHouseUser';
58
- import { ClearingHouseUserAccountSubscriptionConfig } from './clearingHouseUserConfig';
59
- import { getMarketsBanksAndOraclesForSubscription } from './config';
60
-
61
- /**
62
- * # ClearingHouse
63
- * 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.
64
- */
65
- export class ClearingHouse {
66
- connection: Connection;
67
- wallet: IWallet;
68
- public program: Program;
69
- provider: AnchorProvider;
70
- opts?: ConfirmOptions;
71
- users = new Map<number, ClearingHouseUser>();
72
- activeUserId: number;
73
- userAccountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig;
74
- accountSubscriber: ClearingHouseAccountSubscriber;
75
- eventEmitter: StrictEventEmitter<EventEmitter, ClearingHouseAccountEvents>;
76
- _isSubscribed = false;
77
- txSender: TxSender;
78
- marketLastSlotCache = new Map<number, number>();
79
-
80
- public get isSubscribed() {
81
- return this._isSubscribed && this.accountSubscriber.isSubscribed;
82
- }
83
-
84
- public set isSubscribed(val: boolean) {
85
- this._isSubscribed = val;
86
- }
87
-
88
- public constructor(config: ClearingHouseConfig) {
89
- this.connection = config.connection;
90
- this.wallet = config.wallet;
91
- this.opts = config.opts || AnchorProvider.defaultOptions();
92
- this.provider = new AnchorProvider(
93
- config.connection,
94
- config.wallet,
95
- this.opts
96
- );
97
- this.program = new Program(
98
- clearingHouseIDL as Idl,
99
- config.programID,
100
- this.provider
101
- );
102
-
103
- const userIds = config.userIds ?? [0];
104
- this.activeUserId = config.activeUserId ?? userIds[0];
105
- this.userAccountSubscriptionConfig =
106
- config.accountSubscription?.type === 'polling'
107
- ? {
108
- type: 'polling',
109
- accountLoader: config.accountSubscription.accountLoader,
110
- }
111
- : {
112
- type: 'websocket',
113
- };
114
- this.createUsers(userIds, this.userAccountSubscriptionConfig);
115
-
116
- let marketIndexes = config.marketIndexes;
117
- let bankIndexes = config.bankIndexes;
118
- let oracleInfos = config.oracleInfos;
119
- if (config.env) {
120
- const {
121
- marketIndexes: envMarketIndexes,
122
- bankIndexes: envBankIndexes,
123
- oracleInfos: envOralceInfos,
124
- } = getMarketsBanksAndOraclesForSubscription(config.env);
125
- marketIndexes = marketIndexes ? marketIndexes : envMarketIndexes;
126
- bankIndexes = bankIndexes ? bankIndexes : envBankIndexes;
127
- oracleInfos = oracleInfos ? oracleInfos : envOralceInfos;
128
- }
129
-
130
- if (config.accountSubscription?.type === 'polling') {
131
- this.accountSubscriber = new PollingClearingHouseAccountSubscriber(
132
- this.program,
133
- config.accountSubscription.accountLoader,
134
- marketIndexes ?? [],
135
- bankIndexes ?? [],
136
- oracleInfos ?? []
137
- );
138
- } else {
139
- this.accountSubscriber = new WebSocketClearingHouseAccountSubscriber(
140
- this.program,
141
- config.marketIndexes ?? [],
142
- config.bankIndexes ?? [],
143
- config.oracleInfos ?? []
144
- );
145
- }
146
- this.eventEmitter = this.accountSubscriber.eventEmitter;
147
- this.txSender = new RetryTxSender(
148
- this.provider,
149
- config.txSenderConfig?.timeout,
150
- config.txSenderConfig?.retrySleep,
151
- config.txSenderConfig?.additionalConnections
152
- );
153
- }
154
-
155
- createUsers(
156
- userIds: number[],
157
- accountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig
158
- ): void {
159
- for (const userId of userIds) {
160
- const user = this.createUser(userId, accountSubscriptionConfig);
161
- this.users.set(userId, user);
162
- }
163
- }
164
-
165
- createUser(
166
- userId: number,
167
- accountSubscriptionConfig: ClearingHouseUserAccountSubscriptionConfig
168
- ): ClearingHouseUser {
169
- const userAccountPublicKey = getUserAccountPublicKeySync(
170
- this.program.programId,
171
- this.wallet.publicKey,
172
- userId
173
- );
174
-
175
- return new ClearingHouseUser({
176
- clearingHouse: this,
177
- userAccountPublicKey,
178
- accountSubscription: accountSubscriptionConfig,
179
- });
180
- }
181
-
182
- public async subscribe(): Promise<boolean> {
183
- const subscribePromises = this.subscribeUsers().concat(
184
- this.accountSubscriber.subscribe()
185
- );
186
- this.isSubscribed = (await Promise.all(subscribePromises)).reduce(
187
- (success, prevSuccess) => success && prevSuccess
188
- );
189
- return this.isSubscribed;
190
- }
191
-
192
- subscribeUsers(): Promise<boolean>[] {
193
- return [...this.users.values()].map((user) => user.subscribe());
194
- }
195
-
196
- /**
197
- * Forces the accountSubscriber to fetch account updates from rpc
198
- */
199
- public async fetchAccounts(): Promise<void> {
200
- await Promise.all(
201
- [...this.users.values()]
202
- .map((user) => user.fetchAccounts())
203
- .concat(this.accountSubscriber.fetch())
204
- );
205
- }
206
-
207
- public async unsubscribe(): Promise<void> {
208
- const unsubscribePromises = this.unsubscribeUsers().concat(
209
- this.accountSubscriber.unsubscribe()
210
- );
211
- await Promise.all(unsubscribePromises);
212
- this.isSubscribed = false;
213
- }
214
-
215
- unsubscribeUsers(): Promise<void>[] {
216
- return [...this.users.values()].map((user) => user.unsubscribe());
217
- }
218
-
219
- statePublicKey?: PublicKey;
220
- public async getStatePublicKey(): Promise<PublicKey> {
221
- if (this.statePublicKey) {
222
- return this.statePublicKey;
223
- }
224
- this.statePublicKey = await getClearingHouseStateAccountPublicKey(
225
- this.program.programId
226
- );
227
- return this.statePublicKey;
228
- }
229
-
230
- public getStateAccount(): StateAccount {
231
- return this.accountSubscriber.getStateAccountAndSlot().data;
232
- }
233
-
234
- public getMarketAccount(marketIndex: BN | number): MarketAccount | undefined {
235
- marketIndex = marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
236
- return this.accountSubscriber.getMarketAccountAndSlot(marketIndex)?.data;
237
- }
238
-
239
- public getMarketAccounts(): MarketAccount[] {
240
- return this.accountSubscriber
241
- .getMarketAccountsAndSlots()
242
- .map((value) => value.data);
243
- }
244
-
245
- public getBankAccount(bankIndex: BN | number): BankAccount | undefined {
246
- bankIndex = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
247
- return this.accountSubscriber.getBankAccountAndSlot(bankIndex).data;
248
- }
249
-
250
- public getQuoteAssetBankAccount(): BankAccount {
251
- return this.accountSubscriber.getBankAccountAndSlot(QUOTE_ASSET_BANK_INDEX)
252
- .data;
253
- }
254
-
255
- public getOraclePriceDataAndSlot(
256
- oraclePublicKey: PublicKey
257
- ): DataAndSlot<OraclePriceData> | undefined {
258
- return this.accountSubscriber.getOraclePriceDataAndSlot(oraclePublicKey);
259
- }
260
-
261
- /**
262
- * Update the wallet to use for clearing house transactions and linked user account
263
- * @param newWallet
264
- * @param userIds
265
- * @param activeUserId
266
- */
267
- public async updateWallet(
268
- newWallet: IWallet,
269
- userIds = [0],
270
- activeUserId = 0
271
- ): Promise<void> {
272
- const newProvider = new AnchorProvider(
273
- this.connection,
274
- newWallet,
275
- this.opts
276
- );
277
- const newProgram = new Program(
278
- clearingHouseIDL as Idl,
279
- this.program.programId,
280
- newProvider
281
- );
282
-
283
- // Update provider for txSender with new wallet details
284
- this.txSender.provider = newProvider;
285
-
286
- this.wallet = newWallet;
287
- this.provider = newProvider;
288
- this.program = newProgram;
289
-
290
- if (this.isSubscribed) {
291
- await Promise.all(this.unsubscribeUsers());
292
- }
293
- this.users.clear();
294
- this.createUsers(userIds, this.userAccountSubscriptionConfig);
295
- if (this.isSubscribed) {
296
- await Promise.all(this.subscribeUsers());
297
- }
298
-
299
- this.activeUserId = activeUserId;
300
- }
301
-
302
- public async switchActiveUser(userId: number): Promise<void> {
303
- this.activeUserId = userId;
304
- }
305
-
306
- public async addUser(userId: number): Promise<void> {
307
- if (this.users.has(userId)) {
308
- return;
309
- }
310
-
311
- const user = this.createUser(userId, this.userAccountSubscriptionConfig);
312
- await user.subscribe();
313
- this.users.set(userId, user);
314
- }
315
-
316
- public async initializeUserAccount(
317
- userId = 0,
318
- name = DEFAULT_USER_NAME
319
- ): Promise<[TransactionSignature, PublicKey]> {
320
- const [userAccountPublicKey, initializeUserAccountIx] =
321
- await this.getInitializeUserInstructions(userId, name);
322
-
323
- const tx = new Transaction().add(initializeUserAccountIx);
324
- const { txSig } = await this.txSender.send(tx, [], this.opts);
325
- return [txSig, userAccountPublicKey];
326
- }
327
-
328
- async getInitializeUserInstructions(
329
- userId = 0,
330
- name = DEFAULT_USER_NAME
331
- ): Promise<[PublicKey, TransactionInstruction]> {
332
- const userAccountPublicKey = await getUserAccountPublicKey(
333
- this.program.programId,
334
- this.wallet.publicKey,
335
- userId
336
- );
337
-
338
- const nameBuffer = encodeName(name);
339
- const initializeUserAccountIx =
340
- await this.program.instruction.initializeUser(userId, nameBuffer, {
341
- accounts: {
342
- user: userAccountPublicKey,
343
- authority: this.wallet.publicKey,
344
- payer: this.wallet.publicKey,
345
- rent: anchor.web3.SYSVAR_RENT_PUBKEY,
346
- systemProgram: anchor.web3.SystemProgram.programId,
347
- state: await this.getStatePublicKey(),
348
- },
349
- });
350
-
351
- return [userAccountPublicKey, initializeUserAccountIx];
352
- }
353
-
354
- public getUser(userId?: number): ClearingHouseUser {
355
- userId = userId ?? this.activeUserId;
356
- if (!this.users.has(userId)) {
357
- throw new Error(`Clearing House has no user for user id ${userId}`);
358
- }
359
- return this.users.get(userId);
360
- }
361
-
362
- public getUsers(): ClearingHouseUser[] {
363
- return [...this.users.values()];
364
- }
365
-
366
- public async getUserAccountPublicKey(): Promise<PublicKey> {
367
- return this.getUser().userAccountPublicKey;
368
- }
369
-
370
- public getUserAccount(userId?: number): UserAccount | undefined {
371
- return this.getUser(userId).getUserAccount();
372
- }
373
-
374
- public getUserAccountAndSlot(
375
- userId?: number
376
- ): DataAndSlot<UserAccount> | undefined {
377
- return this.getUser(userId).getUserAccountAndSlot();
378
- }
379
-
380
- public getUserBankBalance(
381
- bankIndex: number | BN
382
- ): UserBankBalance | undefined {
383
- const bankIndexBN = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
384
- return this.getUserAccount().bankBalances.find((bankBalance) =>
385
- bankBalance.bankIndex.eq(bankIndexBN)
386
- );
387
- }
388
-
389
- public getQuoteAssetTokenAmount(): BN {
390
- const bank = this.getBankAccount(QUOTE_ASSET_BANK_INDEX);
391
- const userBankBalance = this.getUserBankBalance(QUOTE_ASSET_BANK_INDEX);
392
- return getTokenAmount(
393
- userBankBalance.balance,
394
- bank,
395
- userBankBalance.balanceType
396
- );
397
- }
398
-
399
- getRemainingAccounts(params: {
400
- writableMarketIndex?: BN;
401
- writableBankIndex?: BN;
402
- }): AccountMeta[] {
403
- const userAccountAndSlot = this.getUserAccountAndSlot();
404
- if (!userAccountAndSlot) {
405
- throw Error(
406
- 'No user account found. Most likely user account does not exist or failed to fetch account'
407
- );
408
- }
409
- const { data: userAccount, slot: lastUserPositionsSlot } =
410
- userAccountAndSlot;
411
-
412
- const oracleAccountMap = new Map<string, AccountMeta>();
413
- const bankAccountMap = new Map<number, AccountMeta>();
414
- const marketAccountMap = new Map<number, AccountMeta>();
415
- for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
416
- // if cache has more recent slot than user positions account slot, add market to remaining accounts
417
- // otherwise remove from slot
418
- if (slot > lastUserPositionsSlot) {
419
- const marketAccount = this.getMarketAccount(marketIndexNum);
420
- marketAccountMap.set(marketIndexNum, {
421
- pubkey: marketAccount.pubkey,
422
- isSigner: false,
423
- isWritable: false,
424
- });
425
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
426
- pubkey: marketAccount.amm.oracle,
427
- isSigner: false,
428
- isWritable: false,
429
- });
430
- } else {
431
- this.marketLastSlotCache.delete(marketIndexNum);
432
- }
433
- }
434
-
435
- for (const position of userAccount.positions) {
436
- if (!positionIsAvailable(position)) {
437
- const marketIndexNum = position.marketIndex.toNumber();
438
- const marketAccount = this.getMarketAccount(marketIndexNum);
439
- marketAccountMap.set(marketIndexNum, {
440
- pubkey: marketAccount.pubkey,
441
- isSigner: false,
442
- // isWritable: false, // TODO
443
- isWritable: true,
444
- });
445
- oracleAccountMap.set(marketAccount.pubkey.toString(), {
446
- pubkey: marketAccount.amm.oracle,
447
- isSigner: false,
448
- isWritable: false,
449
- });
450
- }
451
- }
452
-
453
- if (params.writableMarketIndex) {
454
- const marketAccount = this.getMarketAccount(
455
- params.writableMarketIndex.toNumber()
456
- );
457
- marketAccountMap.set(params.writableMarketIndex.toNumber(), {
458
- pubkey: marketAccount.pubkey,
459
- isSigner: false,
460
- isWritable: true,
461
- });
462
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
463
- pubkey: marketAccount.amm.oracle,
464
- isSigner: false,
465
- isWritable: false,
466
- });
467
- }
468
-
469
- for (const userBankBalance of userAccount.bankBalances) {
470
- if (!userBankBalance.balance.eq(ZERO)) {
471
- const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
472
- bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
473
- pubkey: bankAccount.pubkey,
474
- isSigner: false,
475
- isWritable: false,
476
- });
477
- if (!bankAccount.bankIndex.eq(ZERO)) {
478
- oracleAccountMap.set(bankAccount.oracle.toString(), {
479
- pubkey: bankAccount.oracle,
480
- isSigner: false,
481
- isWritable: false,
482
- });
483
- }
484
- }
485
- }
486
-
487
- if (params.writableBankIndex) {
488
- const bankAccount = this.getBankAccount(params.writableBankIndex);
489
- bankAccountMap.set(params.writableBankIndex.toNumber(), {
490
- pubkey: bankAccount.pubkey,
491
- isSigner: false,
492
- isWritable: true,
493
- });
494
- if (!bankAccount.bankIndex.eq(ZERO)) {
495
- oracleAccountMap.set(bankAccount.oracle.toString(), {
496
- pubkey: bankAccount.oracle,
497
- isSigner: false,
498
- isWritable: false,
499
- });
500
- }
501
- }
502
-
503
- return [
504
- ...oracleAccountMap.values(),
505
- ...bankAccountMap.values(),
506
- ...marketAccountMap.values(),
507
- ];
508
- }
509
-
510
- public getOrder(orderId: BN | number): Order | undefined {
511
- const orderIdBN = orderId instanceof BN ? orderId : new BN(orderId);
512
- return this.getUserAccount()?.orders.find((order) =>
513
- order.orderId.eq(orderIdBN)
514
- );
515
- }
516
-
517
- public getOrderByUserId(userOrderId: number): Order | undefined {
518
- return this.getUserAccount()?.orders.find(
519
- (order) => order.userOrderId === userOrderId
520
- );
521
- }
522
-
523
- public async deposit(
524
- amount: BN,
525
- bankIndex: BN,
526
- collateralAccountPublicKey: PublicKey,
527
- userId?: number,
528
- reduceOnly = false
529
- ): Promise<TransactionSignature> {
530
- const depositCollateralIx = await this.getDepositInstruction(
531
- amount,
532
- bankIndex,
533
- collateralAccountPublicKey,
534
- userId,
535
- reduceOnly,
536
- true
537
- );
538
-
539
- const tx = new Transaction().add(depositCollateralIx);
540
-
541
- const { txSig } = await this.txSender.send(tx);
542
- return txSig;
543
- }
544
-
545
- async getDepositInstruction(
546
- amount: BN,
547
- bankIndex: BN,
548
- userTokenAccount: PublicKey,
549
- userId?: number,
550
- reduceOnly = false,
551
- userInitialized = true
552
- ): Promise<TransactionInstruction> {
553
- const userAccountPublicKey = userId
554
- ? await getUserAccountPublicKey(
555
- this.program.programId,
556
- this.wallet.publicKey,
557
- userId
558
- )
559
- : await this.getUserAccountPublicKey();
560
-
561
- let remainingAccounts = [];
562
- if (userInitialized) {
563
- remainingAccounts = this.getRemainingAccounts({
564
- writableBankIndex: bankIndex,
565
- });
566
- } else {
567
- const bankAccount = this.getBankAccount(bankIndex);
568
- if (!bankAccount.oracle.equals(PublicKey.default)) {
569
- remainingAccounts.push({
570
- pubkey: bankAccount.oracle,
571
- isSigner: false,
572
- isWritable: false,
573
- });
574
- }
575
- remainingAccounts.push({
576
- pubkey: bankAccount.pubkey,
577
- isSigner: false,
578
- isWritable: true,
579
- });
580
- }
581
-
582
- const bank = this.getBankAccount(bankIndex);
583
-
584
- return await this.program.instruction.deposit(
585
- bankIndex,
586
- amount,
587
- reduceOnly,
588
- {
589
- accounts: {
590
- state: await this.getStatePublicKey(),
591
- bank: bank.pubkey,
592
- bankVault: bank.vault,
593
- user: userAccountPublicKey,
594
- userTokenAccount: userTokenAccount,
595
- authority: this.wallet.publicKey,
596
- tokenProgram: TOKEN_PROGRAM_ID,
597
- },
598
- remainingAccounts,
599
- }
600
- );
601
- }
602
-
603
- /**
604
- * Creates the Clearing House User account for a user, and deposits some initial collateral
605
- * @param userId
606
- * @param name
607
- * @param amount
608
- * @param userTokenAccount
609
- * @param fromUserId
610
- * @returns
611
- */
612
- public async initializeUserAccountAndDepositCollateral(
613
- amount: BN,
614
- userTokenAccount: PublicKey,
615
- bankIndex = new BN(0),
616
- userId = 0,
617
- name = DEFAULT_USER_NAME,
618
- fromUserId?: number
619
- ): Promise<[TransactionSignature, PublicKey]> {
620
- const [userAccountPublicKey, initializeUserAccountIx] =
621
- await this.getInitializeUserInstructions(userId, name);
622
-
623
- const depositCollateralIx =
624
- fromUserId != null
625
- ? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
626
- : await this.getDepositInstruction(
627
- amount,
628
- bankIndex,
629
- userTokenAccount,
630
- userId,
631
- false,
632
- false
633
- );
634
-
635
- const tx = new Transaction()
636
- .add(initializeUserAccountIx)
637
- .add(depositCollateralIx);
638
-
639
- const { txSig } = await this.txSender.send(tx, []);
640
-
641
- return [txSig, userAccountPublicKey];
642
- }
643
-
644
- public async initializeUserAccountForDevnet(
645
- userId = 0,
646
- name = DEFAULT_USER_NAME,
647
- bankIndex: BN,
648
- tokenFaucet: TokenFaucet,
649
- amount: BN
650
- ): Promise<[TransactionSignature, PublicKey]> {
651
- const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] =
652
- await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(
653
- this.wallet.publicKey,
654
- amount
655
- );
656
-
657
- const [userAccountPublicKey, initializeUserAccountIx] =
658
- await this.getInitializeUserInstructions(userId, name);
659
-
660
- const depositCollateralIx = await this.getDepositInstruction(
661
- amount,
662
- bankIndex,
663
- associateTokenPublicKey,
664
- userId,
665
- false,
666
- false
667
- );
668
-
669
- const tx = new Transaction()
670
- .add(createAssociatedAccountIx)
671
- .add(mintToIx)
672
- .add(initializeUserAccountIx)
673
- .add(depositCollateralIx);
674
-
675
- const txSig = await this.program.provider.sendAndConfirm(tx, []);
676
-
677
- return [txSig, userAccountPublicKey];
678
- }
679
-
680
- public async withdraw(
681
- amount: BN,
682
- bankIndex: BN,
683
- userTokenAccount: PublicKey,
684
- reduceOnly = false
685
- ): Promise<TransactionSignature> {
686
- const { txSig } = await this.txSender.send(
687
- wrapInTx(
688
- await this.getWithdrawIx(
689
- amount,
690
- bankIndex,
691
- userTokenAccount,
692
- reduceOnly
693
- )
694
- ),
695
- [],
696
- this.opts
697
- );
698
- return txSig;
699
- }
700
-
701
- public async getWithdrawIx(
702
- amount: BN,
703
- bankIndex: BN,
704
- userTokenAccount: PublicKey,
705
- reduceOnly = false
706
- ): Promise<TransactionInstruction> {
707
- const userAccountPublicKey = await this.getUserAccountPublicKey();
708
-
709
- const remainingAccounts = this.getRemainingAccounts({
710
- writableBankIndex: bankIndex,
711
- });
712
-
713
- const bank = this.getBankAccount(bankIndex);
714
-
715
- return await this.program.instruction.withdraw(
716
- bankIndex,
717
- amount,
718
- reduceOnly,
719
- {
720
- accounts: {
721
- state: await this.getStatePublicKey(),
722
- bank: bank.pubkey,
723
- bankVault: bank.vault,
724
- bankVaultAuthority: bank.vaultAuthority,
725
- user: userAccountPublicKey,
726
- userTokenAccount: userTokenAccount,
727
- authority: this.wallet.publicKey,
728
- tokenProgram: TOKEN_PROGRAM_ID,
729
- },
730
- remainingAccounts,
731
- }
732
- );
733
- }
734
-
735
- public async transferDeposit(
736
- amount: BN,
737
- bankIndex: BN,
738
- fromUserId: number,
739
- toUserId: number
740
- ): Promise<TransactionSignature> {
741
- const { txSig } = await this.txSender.send(
742
- wrapInTx(
743
- await this.getTransferDepositIx(amount, bankIndex, fromUserId, toUserId)
744
- ),
745
- [],
746
- this.opts
747
- );
748
- return txSig;
749
- }
750
-
751
- public async getTransferDepositIx(
752
- amount: BN,
753
- bankIndex: BN,
754
- fromUserId: number,
755
- toUserId: number
756
- ): Promise<TransactionInstruction> {
757
- const fromUser = await getUserAccountPublicKey(
758
- this.program.programId,
759
- this.wallet.publicKey,
760
- fromUserId
761
- );
762
- const toUser = await getUserAccountPublicKey(
763
- this.program.programId,
764
- this.wallet.publicKey,
765
- toUserId
766
- );
767
-
768
- const remainingAccounts = this.getRemainingAccounts({
769
- writableBankIndex: bankIndex,
770
- });
771
-
772
- return await this.program.instruction.transferDeposit(bankIndex, amount, {
773
- accounts: {
774
- authority: this.wallet.publicKey,
775
- fromUser,
776
- toUser,
777
- state: await this.getStatePublicKey(),
778
- },
779
- remainingAccounts,
780
- });
781
- }
782
-
783
- public async updateBankCumulativeInterest(
784
- bankIndex: BN
785
- ): Promise<TransactionSignature> {
786
- const { txSig } = await this.txSender.send(
787
- wrapInTx(await this.updateBankCumulativeInterestIx(bankIndex)),
788
- [],
789
- this.opts
790
- );
791
- return txSig;
792
- }
793
-
794
- public async updateBankCumulativeInterestIx(
795
- bankIndex: BN
796
- ): Promise<TransactionInstruction> {
797
- const bank = this.getBankAccount(bankIndex);
798
- return await this.program.instruction.updateBankCumulativeInterest({
799
- accounts: {
800
- bank: bank.pubkey,
801
- },
802
- });
803
- }
804
-
805
- public async openPosition(
806
- direction: PositionDirection,
807
- amount: BN,
808
- marketIndex: BN,
809
- limitPrice?: BN
810
- ): Promise<TransactionSignature> {
811
- return await this.placeAndTake({
812
- orderType: OrderType.MARKET,
813
- marketIndex,
814
- direction,
815
- baseAssetAmount: amount,
816
- price: limitPrice,
817
- });
818
- }
819
-
820
- public async placeOrder(
821
- orderParams: OptionalOrderParams
822
- ): Promise<TransactionSignature> {
823
- const { txSig, slot } = await this.txSender.send(
824
- wrapInTx(await this.getPlaceOrderIx(orderParams)),
825
- [],
826
- this.opts
827
- );
828
- this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
829
- return txSig;
830
- }
831
-
832
- getOrderParams(optionalOrderParams: OptionalOrderParams): OrderParams {
833
- return Object.assign({}, DefaultOrderParams, optionalOrderParams);
834
- }
835
-
836
- public async getPlaceOrderIx(
837
- orderParams: OptionalOrderParams
838
- ): Promise<TransactionInstruction> {
839
- orderParams = this.getOrderParams(orderParams);
840
- const userAccountPublicKey = await this.getUserAccountPublicKey();
841
-
842
- const remainingAccounts = this.getRemainingAccounts({
843
- writableMarketIndex: orderParams.marketIndex,
844
- });
845
-
846
- return await this.program.instruction.placeOrder(orderParams, {
847
- accounts: {
848
- state: await this.getStatePublicKey(),
849
- user: userAccountPublicKey,
850
- authority: this.wallet.publicKey,
851
- },
852
- remainingAccounts,
853
- });
854
- }
855
-
856
- public async updateAMMs(marketIndexes: BN[]): Promise<TransactionSignature> {
857
- const { txSig } = await this.txSender.send(
858
- wrapInTx(await this.getUpdateAMMsIx(marketIndexes)),
859
- [],
860
- this.opts
861
- );
862
- return txSig;
863
- }
864
-
865
- public async getUpdateAMMsIx(
866
- marketIndexes: BN[]
867
- ): Promise<TransactionInstruction> {
868
- for (let i = marketIndexes.length; i < 5; i++) {
869
- marketIndexes.push(new BN(100));
870
- }
871
- const marketAccountInfos = [];
872
- const oracleAccountInfos = [];
873
- for (const marketIndex of marketIndexes) {
874
- if (!marketIndex.eq(new BN(100))) {
875
- const market = this.getMarketAccount(marketIndex);
876
- marketAccountInfos.push({
877
- pubkey: market.pubkey,
878
- isWritable: true,
879
- isSigner: false,
880
- });
881
- oracleAccountInfos.push({
882
- pubkey: market.amm.oracle,
883
- isWritable: false,
884
- isSigner: false,
885
- });
886
- }
887
- }
888
- const remainingAccounts = oracleAccountInfos.concat(marketAccountInfos);
889
-
890
- return await this.program.instruction.updateAmms(marketIndexes, {
891
- accounts: {
892
- state: await this.getStatePublicKey(),
893
- authority: this.wallet.publicKey,
894
- },
895
- remainingAccounts,
896
- });
897
- }
898
-
899
- public async cancelOrder(orderId?: BN): Promise<TransactionSignature> {
900
- const { txSig } = await this.txSender.send(
901
- wrapInTx(await this.getCancelOrderIx(orderId)),
902
- [],
903
- this.opts
904
- );
905
- return txSig;
906
- }
907
-
908
- public async getCancelOrderIx(orderId?: BN): Promise<TransactionInstruction> {
909
- const userAccountPublicKey = await this.getUserAccountPublicKey();
910
-
911
- const remainingAccounts = this.getRemainingAccounts({});
912
-
913
- return await this.program.instruction.cancelOrder(orderId ?? null, {
914
- accounts: {
915
- state: await this.getStatePublicKey(),
916
- user: userAccountPublicKey,
917
- authority: this.wallet.publicKey,
918
- },
919
- remainingAccounts,
920
- });
921
- }
922
-
923
- public async cancelOrderByUserId(
924
- userOrderId: number
925
- ): Promise<TransactionSignature> {
926
- const { txSig } = await this.txSender.send(
927
- wrapInTx(await this.getCancelOrderByUserIdIx(userOrderId)),
928
- [],
929
- this.opts
930
- );
931
- return txSig;
932
- }
933
-
934
- public async getCancelOrderByUserIdIx(
935
- userOrderId: number
936
- ): Promise<TransactionInstruction> {
937
- const userAccountPublicKey = await this.getUserAccountPublicKey();
938
-
939
- const order = this.getOrderByUserId(userOrderId);
940
- const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
941
-
942
- const remainingAccounts = this.getRemainingAccounts({});
943
-
944
- return await this.program.instruction.cancelOrderByUserId(userOrderId, {
945
- accounts: {
946
- state: await this.getStatePublicKey(),
947
- user: userAccountPublicKey,
948
- authority: this.wallet.publicKey,
949
- oracle,
950
- },
951
- remainingAccounts,
952
- });
953
- }
954
-
955
- public async fillOrder(
956
- userAccountPublicKey: PublicKey,
957
- user: UserAccount,
958
- order?: Order,
959
- makerInfo?: MakerInfo
960
- ): Promise<TransactionSignature> {
961
- const { txSig } = await this.txSender.send(
962
- wrapInTx(
963
- await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)
964
- ),
965
- [],
966
- this.opts
967
- );
968
- return txSig;
969
- }
970
-
971
- public async getFillOrderIx(
972
- userAccountPublicKey: PublicKey,
973
- userAccount: UserAccount,
974
- order: Order,
975
- makerInfo?: MakerInfo
976
- ): Promise<TransactionInstruction> {
977
- const fillerPublicKey = await this.getUserAccountPublicKey();
978
-
979
- const marketIndex = order.marketIndex;
980
- const marketAccount = this.getMarketAccount(marketIndex);
981
-
982
- const oracleAccountMap = new Map<string, AccountMeta>();
983
- const bankAccountMap = new Map<number, AccountMeta>();
984
- const marketAccountMap = new Map<number, AccountMeta>();
985
-
986
- marketAccountMap.set(marketIndex.toNumber(), {
987
- pubkey: marketAccount.pubkey,
988
- isWritable: true,
989
- isSigner: false,
990
- });
991
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
992
- pubkey: marketAccount.amm.oracle,
993
- isWritable: false,
994
- isSigner: false,
995
- });
996
-
997
- for (const bankBalance of userAccount.bankBalances) {
998
- if (!bankBalance.balance.eq(ZERO)) {
999
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1000
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1001
- pubkey: bankAccount.pubkey,
1002
- isSigner: false,
1003
- isWritable: true,
1004
- });
1005
-
1006
- if (!bankAccount.oracle.equals(PublicKey.default)) {
1007
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1008
- pubkey: bankAccount.oracle,
1009
- isSigner: false,
1010
- isWritable: false,
1011
- });
1012
- }
1013
- }
1014
- }
1015
-
1016
- for (const position of userAccount.positions) {
1017
- if (
1018
- !positionIsAvailable(position) &&
1019
- !position.marketIndex.eq(order.marketIndex)
1020
- ) {
1021
- const market = this.getMarketAccount(position.marketIndex);
1022
- marketAccountMap.set(position.marketIndex.toNumber(), {
1023
- pubkey: market.pubkey,
1024
- isWritable: true,
1025
- isSigner: false,
1026
- });
1027
- oracleAccountMap.set(market.amm.oracle.toString(), {
1028
- pubkey: market.amm.oracle,
1029
- isWritable: false,
1030
- isSigner: false,
1031
- });
1032
- }
1033
- }
1034
-
1035
- const remainingAccounts = [
1036
- ...oracleAccountMap.values(),
1037
- ...bankAccountMap.values(),
1038
- ...marketAccountMap.values(),
1039
- ];
1040
-
1041
- if (makerInfo) {
1042
- remainingAccounts.push({
1043
- pubkey: makerInfo.maker,
1044
- isWritable: true,
1045
- isSigner: false,
1046
- });
1047
- }
1048
-
1049
- const orderId = order.orderId;
1050
- const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
1051
-
1052
- return await this.program.instruction.fillOrder(orderId, makerOrderId, {
1053
- accounts: {
1054
- state: await this.getStatePublicKey(),
1055
- filler: fillerPublicKey,
1056
- user: userAccountPublicKey,
1057
- authority: this.wallet.publicKey,
1058
- },
1059
- remainingAccounts,
1060
- });
1061
- }
1062
-
1063
- public async triggerOrder(
1064
- userAccountPublicKey: PublicKey,
1065
- user: UserAccount,
1066
- order: Order
1067
- ): Promise<TransactionSignature> {
1068
- const { txSig } = await this.txSender.send(
1069
- wrapInTx(await this.getTriggerOrderIx(userAccountPublicKey, user, order)),
1070
- [],
1071
- this.opts
1072
- );
1073
- return txSig;
1074
- }
1075
-
1076
- public async getTriggerOrderIx(
1077
- userAccountPublicKey: PublicKey,
1078
- userAccount: UserAccount,
1079
- order: Order
1080
- ): Promise<TransactionInstruction> {
1081
- const fillerPublicKey = await this.getUserAccountPublicKey();
1082
-
1083
- const marketIndex = order.marketIndex;
1084
- const marketAccount = this.getMarketAccount(marketIndex);
1085
-
1086
- const oracleAccountMap = new Map<string, AccountMeta>();
1087
- const bankAccountMap = new Map<number, AccountMeta>();
1088
- const marketAccountMap = new Map<number, AccountMeta>();
1089
-
1090
- marketAccountMap.set(marketIndex.toNumber(), {
1091
- pubkey: marketAccount.pubkey,
1092
- isWritable: true,
1093
- isSigner: false,
1094
- });
1095
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1096
- pubkey: marketAccount.amm.oracle,
1097
- isWritable: false,
1098
- isSigner: false,
1099
- });
1100
-
1101
- for (const bankBalance of userAccount.bankBalances) {
1102
- if (!bankBalance.balance.eq(ZERO)) {
1103
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1104
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1105
- pubkey: bankAccount.pubkey,
1106
- isSigner: false,
1107
- isWritable: true,
1108
- });
1109
-
1110
- if (!bankAccount.oracle.equals(PublicKey.default)) {
1111
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1112
- pubkey: bankAccount.oracle,
1113
- isSigner: false,
1114
- isWritable: false,
1115
- });
1116
- }
1117
- }
1118
- }
1119
-
1120
- for (const position of userAccount.positions) {
1121
- if (
1122
- !positionIsAvailable(position) &&
1123
- !position.marketIndex.eq(order.marketIndex)
1124
- ) {
1125
- const market = this.getMarketAccount(position.marketIndex);
1126
- marketAccountMap.set(position.marketIndex.toNumber(), {
1127
- pubkey: market.pubkey,
1128
- isWritable: true,
1129
- isSigner: false,
1130
- });
1131
- oracleAccountMap.set(market.amm.oracle.toString(), {
1132
- pubkey: market.amm.oracle,
1133
- isWritable: false,
1134
- isSigner: false,
1135
- });
1136
- }
1137
- }
1138
-
1139
- const remainingAccounts = [
1140
- ...oracleAccountMap.values(),
1141
- ...bankAccountMap.values(),
1142
- ...marketAccountMap.values(),
1143
- ];
1144
-
1145
- const orderId = order.orderId;
1146
- return await this.program.instruction.triggerOrder(orderId, {
1147
- accounts: {
1148
- state: await this.getStatePublicKey(),
1149
- filler: fillerPublicKey,
1150
- user: userAccountPublicKey,
1151
- authority: this.wallet.publicKey,
1152
- },
1153
- remainingAccounts,
1154
- });
1155
- }
1156
-
1157
- public async placeAndTake(
1158
- orderParams: OptionalOrderParams,
1159
- makerInfo?: MakerInfo
1160
- ): Promise<TransactionSignature> {
1161
- const { txSig, slot } = await this.txSender.send(
1162
- wrapInTx(await this.getPlaceAndTakeIx(orderParams, makerInfo)),
1163
- [],
1164
- this.opts
1165
- );
1166
- this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
1167
- return txSig;
1168
- }
1169
-
1170
- public async getPlaceAndTakeIx(
1171
- orderParams: OptionalOrderParams,
1172
- makerInfo?: MakerInfo
1173
- ): Promise<TransactionInstruction> {
1174
- orderParams = this.getOrderParams(orderParams);
1175
- const userAccountPublicKey = await this.getUserAccountPublicKey();
1176
-
1177
- const remainingAccounts = this.getRemainingAccounts({
1178
- writableMarketIndex: orderParams.marketIndex,
1179
- writableBankIndex: QUOTE_ASSET_BANK_INDEX,
1180
- });
1181
-
1182
- let makerOrderId = null;
1183
- if (makerInfo) {
1184
- makerOrderId = makerInfo.order.orderId;
1185
- remainingAccounts.push({
1186
- pubkey: makerInfo.maker,
1187
- isSigner: false,
1188
- isWritable: true,
1189
- });
1190
- }
1191
-
1192
- return await this.program.instruction.placeAndTake(
1193
- orderParams,
1194
- makerOrderId,
1195
- {
1196
- accounts: {
1197
- state: await this.getStatePublicKey(),
1198
- user: userAccountPublicKey,
1199
- authority: this.wallet.publicKey,
1200
- },
1201
- remainingAccounts,
1202
- }
1203
- );
1204
- }
1205
-
1206
- public async placeAndMake(
1207
- orderParams: OptionalOrderParams,
1208
- takerInfo: TakerInfo
1209
- ): Promise<TransactionSignature> {
1210
- const { txSig, slot } = await this.txSender.send(
1211
- wrapInTx(await this.getPlaceAndMakeIx(orderParams, takerInfo)),
1212
- [],
1213
- this.opts
1214
- );
1215
-
1216
- this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
1217
-
1218
- return txSig;
1219
- }
1220
-
1221
- public async getPlaceAndMakeIx(
1222
- orderParams: OptionalOrderParams,
1223
- takerInfo: TakerInfo
1224
- ): Promise<TransactionInstruction> {
1225
- orderParams = this.getOrderParams(orderParams);
1226
- const userAccountPublicKey = await this.getUserAccountPublicKey();
1227
-
1228
- const remainingAccounts = this.getRemainingAccounts({
1229
- writableMarketIndex: orderParams.marketIndex,
1230
- writableBankIndex: QUOTE_ASSET_BANK_INDEX,
1231
- });
1232
-
1233
- const takerOrderId = takerInfo!.order!.orderId;
1234
- remainingAccounts.push({
1235
- pubkey: takerInfo.taker,
1236
- isSigner: false,
1237
- isWritable: true,
1238
- });
1239
-
1240
- return await this.program.instruction.placeAndMake(
1241
- orderParams,
1242
- takerOrderId,
1243
- {
1244
- accounts: {
1245
- state: await this.getStatePublicKey(),
1246
- user: userAccountPublicKey,
1247
- taker: takerInfo.taker,
1248
- authority: this.wallet.publicKey,
1249
- },
1250
- remainingAccounts,
1251
- }
1252
- );
1253
- }
1254
-
1255
- /**
1256
- * Close an entire position. If you want to reduce a position, use the {@link openPosition} method in the opposite direction of the current position.
1257
- * @param marketIndex
1258
- * @returns
1259
- */
1260
- public async closePosition(marketIndex: BN): Promise<TransactionSignature> {
1261
- const userPosition = this.getUser().getUserPosition(marketIndex);
1262
- if (!userPosition) {
1263
- throw Error(`No position in market ${marketIndex.toString()}`);
1264
- }
1265
-
1266
- return await this.placeAndTake({
1267
- orderType: OrderType.MARKET,
1268
- marketIndex,
1269
- direction: findDirectionToClose(userPosition),
1270
- baseAssetAmount: userPosition.baseAssetAmount,
1271
- reduceOnly: true,
1272
- });
1273
- }
1274
-
1275
- public async settlePNLs(
1276
- users: {
1277
- settleeUserAccountPublicKey: PublicKey;
1278
- settleeUserAccount: UserAccount;
1279
- }[],
1280
- marketIndex: BN
1281
- ): Promise<TransactionSignature> {
1282
- const ixs = [];
1283
- for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
1284
- ixs.push(
1285
- await this.settlePNLIx(
1286
- settleeUserAccountPublicKey,
1287
- settleeUserAccount,
1288
- marketIndex
1289
- )
1290
- );
1291
- }
1292
-
1293
- const tx = new Transaction().add(...ixs);
1294
-
1295
- const { txSig } = await this.txSender.send(tx, [], this.opts);
1296
- return txSig;
1297
- }
1298
-
1299
- public async settlePNL(
1300
- settleeUserAccountPublicKey: PublicKey,
1301
- settleeUserAccount: UserAccount,
1302
- marketIndex: BN
1303
- ): Promise<TransactionSignature> {
1304
- const { txSig } = await this.txSender.send(
1305
- wrapInTx(
1306
- await this.settlePNLIx(
1307
- settleeUserAccountPublicKey,
1308
- settleeUserAccount,
1309
- marketIndex
1310
- )
1311
- ),
1312
- [],
1313
- this.opts
1314
- );
1315
- return txSig;
1316
- }
1317
-
1318
- public async settlePNLIx(
1319
- settleeUserAccountPublicKey: PublicKey,
1320
- settleeUserAccount: UserAccount,
1321
- marketIndex: BN
1322
- ): Promise<TransactionInstruction> {
1323
- const marketAccountMap = new Map<number, AccountMeta>();
1324
- const oracleAccountMap = new Map<string, AccountMeta>();
1325
- const bankAccountMap = new Map<number, AccountMeta>();
1326
- for (const position of settleeUserAccount.positions) {
1327
- if (!positionIsAvailable(position)) {
1328
- const market = this.getMarketAccount(position.marketIndex);
1329
- marketAccountMap.set(position.marketIndex.toNumber(), {
1330
- pubkey: market.pubkey,
1331
- isWritable: true, // TODO
1332
- isSigner: false,
1333
- });
1334
- oracleAccountMap.set(market.amm.oracle.toString(), {
1335
- pubkey: market.amm.oracle,
1336
- isWritable: false,
1337
- isSigner: false,
1338
- });
1339
- }
1340
- }
1341
-
1342
- for (const userBankBalance of settleeUserAccount.bankBalances) {
1343
- if (!userBankBalance.balance.eq(QUOTE_ASSET_BANK_INDEX)) {
1344
- const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
1345
- bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
1346
- pubkey: bankAccount.pubkey,
1347
- isSigner: false,
1348
- isWritable: false,
1349
- });
1350
- if (!bankAccount.bankIndex.eq(ZERO)) {
1351
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1352
- pubkey: bankAccount.oracle,
1353
- isSigner: false,
1354
- isWritable: false,
1355
- });
1356
- }
1357
- }
1358
- }
1359
-
1360
- const marketAccount = this.getMarketAccount(marketIndex.toNumber());
1361
- marketAccountMap.set(marketIndex.toNumber(), {
1362
- pubkey: marketAccount.pubkey,
1363
- isSigner: false,
1364
- isWritable: true,
1365
- });
1366
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1367
- pubkey: marketAccount.amm.oracle,
1368
- isSigner: false,
1369
- isWritable: false,
1370
- });
1371
-
1372
- bankAccountMap.set(QUOTE_ASSET_BANK_INDEX.toNumber(), {
1373
- pubkey: this.getBankAccount(QUOTE_ASSET_BANK_INDEX).pubkey,
1374
- isSigner: false,
1375
- isWritable: true,
1376
- });
1377
-
1378
- const remainingAccounts = [
1379
- ...oracleAccountMap.values(),
1380
- ...bankAccountMap.values(),
1381
- ...marketAccountMap.values(),
1382
- ];
1383
-
1384
- return await this.program.instruction.settlePnl(marketIndex, {
1385
- accounts: {
1386
- state: await this.getStatePublicKey(),
1387
- authority: this.wallet.publicKey,
1388
- user: settleeUserAccountPublicKey,
1389
- },
1390
- remainingAccounts: remainingAccounts,
1391
- });
1392
- }
1393
-
1394
- public async liquidatePerp(
1395
- userAccountPublicKey: PublicKey,
1396
- userAccount: UserAccount,
1397
- marketIndex: BN,
1398
- maxBaseAssetAmount: BN
1399
- ): Promise<TransactionSignature> {
1400
- const { txSig } = await this.txSender.send(
1401
- wrapInTx(
1402
- await this.getLiquidatePerpIx(
1403
- userAccountPublicKey,
1404
- userAccount,
1405
- marketIndex,
1406
- maxBaseAssetAmount
1407
- )
1408
- ),
1409
- [],
1410
- this.opts
1411
- );
1412
- return txSig;
1413
- }
1414
-
1415
- public async getLiquidatePerpIx(
1416
- userAccountPublicKey: PublicKey,
1417
- userAccount: UserAccount,
1418
- marketIndex: BN,
1419
- maxBaseAssetAmount: BN
1420
- ): Promise<TransactionInstruction> {
1421
- const liquidatorPublicKey = await this.getUserAccountPublicKey();
1422
-
1423
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1424
- writableMarketIndex: marketIndex,
1425
- userAccount,
1426
- });
1427
-
1428
- return await this.program.instruction.liquidatePerp(
1429
- marketIndex,
1430
- maxBaseAssetAmount,
1431
- {
1432
- accounts: {
1433
- state: await this.getStatePublicKey(),
1434
- authority: this.wallet.publicKey,
1435
- user: userAccountPublicKey,
1436
- liquidator: liquidatorPublicKey,
1437
- },
1438
- remainingAccounts: remainingAccounts,
1439
- }
1440
- );
1441
- }
1442
-
1443
- public async liquidateBorrow(
1444
- userAccountPublicKey: PublicKey,
1445
- userAccount: UserAccount,
1446
- assetBankIndex: BN,
1447
- liabilityBankIndex: BN,
1448
- maxLiabilityTransfer: BN
1449
- ): Promise<TransactionSignature> {
1450
- const { txSig } = await this.txSender.send(
1451
- wrapInTx(
1452
- await this.getLiquidateBorrowIx(
1453
- userAccountPublicKey,
1454
- userAccount,
1455
- assetBankIndex,
1456
- liabilityBankIndex,
1457
- maxLiabilityTransfer
1458
- )
1459
- ),
1460
- [],
1461
- this.opts
1462
- );
1463
- return txSig;
1464
- }
1465
-
1466
- public async getLiquidateBorrowIx(
1467
- userAccountPublicKey: PublicKey,
1468
- userAccount: UserAccount,
1469
- assetBankIndex: BN,
1470
- liabilityBankIndex: BN,
1471
- maxLiabilityTransfer: BN
1472
- ): Promise<TransactionInstruction> {
1473
- const liquidatorPublicKey = await this.getUserAccountPublicKey();
1474
-
1475
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1476
- userAccount,
1477
- writableBankIndexes: [liabilityBankIndex, assetBankIndex],
1478
- });
1479
-
1480
- return await this.program.instruction.liquidateBorrow(
1481
- assetBankIndex,
1482
- liabilityBankIndex,
1483
- maxLiabilityTransfer,
1484
- {
1485
- accounts: {
1486
- state: await this.getStatePublicKey(),
1487
- authority: this.wallet.publicKey,
1488
- user: userAccountPublicKey,
1489
- liquidator: liquidatorPublicKey,
1490
- },
1491
- remainingAccounts: remainingAccounts,
1492
- }
1493
- );
1494
- }
1495
-
1496
- public async liquidateBorrowForPerpPnl(
1497
- userAccountPublicKey: PublicKey,
1498
- userAccount: UserAccount,
1499
- perpMarketIndex: BN,
1500
- liabilityBankIndex: BN,
1501
- maxLiabilityTransfer: BN
1502
- ): Promise<TransactionSignature> {
1503
- const { txSig } = await this.txSender.send(
1504
- wrapInTx(
1505
- await this.getLiquidateBorrowForPerpPnlIx(
1506
- userAccountPublicKey,
1507
- userAccount,
1508
- perpMarketIndex,
1509
- liabilityBankIndex,
1510
- maxLiabilityTransfer
1511
- )
1512
- ),
1513
- [],
1514
- this.opts
1515
- );
1516
- return txSig;
1517
- }
1518
-
1519
- public async getLiquidateBorrowForPerpPnlIx(
1520
- userAccountPublicKey: PublicKey,
1521
- userAccount: UserAccount,
1522
- perpMarketIndex: BN,
1523
- liabilityBankIndex: BN,
1524
- maxLiabilityTransfer: BN
1525
- ): Promise<TransactionInstruction> {
1526
- const liquidatorPublicKey = await this.getUserAccountPublicKey();
1527
-
1528
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1529
- userAccount,
1530
- writableMarketIndex: perpMarketIndex,
1531
- writableBankIndexes: [liabilityBankIndex],
1532
- });
1533
-
1534
- return await this.program.instruction.liquidateBorrowForPerpPnl(
1535
- perpMarketIndex,
1536
- liabilityBankIndex,
1537
- maxLiabilityTransfer,
1538
- {
1539
- accounts: {
1540
- state: await this.getStatePublicKey(),
1541
- authority: this.wallet.publicKey,
1542
- user: userAccountPublicKey,
1543
- liquidator: liquidatorPublicKey,
1544
- },
1545
- remainingAccounts: remainingAccounts,
1546
- }
1547
- );
1548
- }
1549
-
1550
- public async liquidatePerpPnlForDeposit(
1551
- userAccountPublicKey: PublicKey,
1552
- userAccount: UserAccount,
1553
- perpMarketIndex: BN,
1554
- assetBankIndex: BN,
1555
- maxPnlTransfer: BN
1556
- ): Promise<TransactionSignature> {
1557
- const { txSig } = await this.txSender.send(
1558
- wrapInTx(
1559
- await this.getLiquidatePerpPnlForDepositIx(
1560
- userAccountPublicKey,
1561
- userAccount,
1562
- perpMarketIndex,
1563
- assetBankIndex,
1564
- maxPnlTransfer
1565
- )
1566
- ),
1567
- [],
1568
- this.opts
1569
- );
1570
- return txSig;
1571
- }
1572
-
1573
- public async getLiquidatePerpPnlForDepositIx(
1574
- userAccountPublicKey: PublicKey,
1575
- userAccount: UserAccount,
1576
- perpMarketIndex: BN,
1577
- assetBankIndex: BN,
1578
- maxPnlTransfer: BN
1579
- ): Promise<TransactionInstruction> {
1580
- const liquidatorPublicKey = await this.getUserAccountPublicKey();
1581
-
1582
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1583
- userAccount,
1584
- writableMarketIndex: perpMarketIndex,
1585
- writableBankIndexes: [assetBankIndex],
1586
- });
1587
-
1588
- return await this.program.instruction.liquidatePerpPnlForDeposit(
1589
- perpMarketIndex,
1590
- assetBankIndex,
1591
- maxPnlTransfer,
1592
- {
1593
- accounts: {
1594
- state: await this.getStatePublicKey(),
1595
- authority: this.wallet.publicKey,
1596
- user: userAccountPublicKey,
1597
- liquidator: liquidatorPublicKey,
1598
- },
1599
- remainingAccounts: remainingAccounts,
1600
- }
1601
- );
1602
- }
1603
-
1604
- getRemainingAccountsForLiquidation(params: {
1605
- userAccount: UserAccount;
1606
- writableMarketIndex?: BN;
1607
- writableBankIndexes?: BN[];
1608
- }): AccountMeta[] {
1609
- const liquidateeUserAccount = params.userAccount;
1610
-
1611
- const oracleAccountMap = new Map<string, AccountMeta>();
1612
- const bankAccountMap = new Map<number, AccountMeta>();
1613
- const marketAccountMap = new Map<number, AccountMeta>();
1614
- for (const bankBalance of liquidateeUserAccount.bankBalances) {
1615
- if (!bankBalance.balance.eq(ZERO)) {
1616
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1617
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1618
- pubkey: bankAccount.pubkey,
1619
- isSigner: false,
1620
- isWritable: false,
1621
- });
1622
-
1623
- if (!bankAccount.oracle.equals(PublicKey.default)) {
1624
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1625
- pubkey: bankAccount.oracle,
1626
- isSigner: false,
1627
- isWritable: false,
1628
- });
1629
- }
1630
- }
1631
- }
1632
- for (const position of liquidateeUserAccount.positions) {
1633
- if (!positionIsAvailable(position)) {
1634
- const market = this.getMarketAccount(position.marketIndex);
1635
- marketAccountMap.set(position.marketIndex.toNumber(), {
1636
- pubkey: market.pubkey,
1637
- isWritable: false,
1638
- isSigner: false,
1639
- });
1640
- oracleAccountMap.set(market.amm.oracle.toString(), {
1641
- pubkey: market.amm.oracle,
1642
- isWritable: false,
1643
- isSigner: false,
1644
- });
1645
- }
1646
- }
1647
-
1648
- const userAccountAndSlot = this.getUserAccountAndSlot();
1649
- if (!userAccountAndSlot) {
1650
- throw Error(
1651
- 'No user account found. Most likely user account does not exist or failed to fetch account'
1652
- );
1653
- }
1654
- const { data: userAccount, slot: lastUserPositionsSlot } =
1655
- userAccountAndSlot;
1656
-
1657
- for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
1658
- // if cache has more recent slot than user positions account slot, add market to remaining accounts
1659
- // otherwise remove from slot
1660
- if (slot > lastUserPositionsSlot) {
1661
- const marketAccount = this.getMarketAccount(marketIndexNum);
1662
- marketAccountMap.set(marketIndexNum, {
1663
- pubkey: marketAccount.pubkey,
1664
- isSigner: false,
1665
- isWritable: false,
1666
- });
1667
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1668
- pubkey: marketAccount.amm.oracle,
1669
- isSigner: false,
1670
- isWritable: false,
1671
- });
1672
- } else {
1673
- this.marketLastSlotCache.delete(marketIndexNum);
1674
- }
1675
- }
1676
- for (const bankBalance of userAccount.bankBalances) {
1677
- if (!bankBalance.balance.eq(ZERO)) {
1678
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1679
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1680
- pubkey: bankAccount.pubkey,
1681
- isSigner: false,
1682
- isWritable: false,
1683
- });
1684
-
1685
- if (!bankAccount.oracle.equals(PublicKey.default)) {
1686
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1687
- pubkey: bankAccount.oracle,
1688
- isSigner: false,
1689
- isWritable: false,
1690
- });
1691
- }
1692
- }
1693
- }
1694
- for (const position of userAccount.positions) {
1695
- if (!positionIsAvailable(position)) {
1696
- const market = this.getMarketAccount(position.marketIndex);
1697
- marketAccountMap.set(position.marketIndex.toNumber(), {
1698
- pubkey: market.pubkey,
1699
- isWritable: false,
1700
- isSigner: false,
1701
- });
1702
- oracleAccountMap.set(market.amm.oracle.toString(), {
1703
- pubkey: market.amm.oracle,
1704
- isWritable: false,
1705
- isSigner: false,
1706
- });
1707
- }
1708
- }
1709
-
1710
- if (params.writableMarketIndex) {
1711
- const market = this.getMarketAccount(params.writableMarketIndex);
1712
- marketAccountMap.set(market.marketIndex.toNumber(), {
1713
- pubkey: market.pubkey,
1714
- isSigner: false,
1715
- isWritable: true,
1716
- });
1717
- oracleAccountMap.set(market.amm.oracle.toString(), {
1718
- pubkey: market.amm.oracle,
1719
- isSigner: false,
1720
- isWritable: false,
1721
- });
1722
- }
1723
-
1724
- if (params.writableBankIndexes) {
1725
- for (const writableBankIndex of params.writableBankIndexes) {
1726
- const bank = this.getBankAccount(writableBankIndex);
1727
- bankAccountMap.set(bank.bankIndex.toNumber(), {
1728
- pubkey: bank.pubkey,
1729
- isSigner: false,
1730
- isWritable: true,
1731
- });
1732
- if (!bank.oracle.equals(PublicKey.default)) {
1733
- oracleAccountMap.set(bank.oracle.toString(), {
1734
- pubkey: bank.oracle,
1735
- isSigner: false,
1736
- isWritable: false,
1737
- });
1738
- }
1739
- }
1740
- }
1741
-
1742
- return [
1743
- ...oracleAccountMap.values(),
1744
- ...bankAccountMap.values(),
1745
- ...marketAccountMap.values(),
1746
- ];
1747
- }
1748
-
1749
- public async updateFundingRate(
1750
- oracle: PublicKey,
1751
- marketIndex: BN
1752
- ): Promise<TransactionSignature> {
1753
- const { txSig } = await this.txSender.send(
1754
- wrapInTx(await this.getUpdateFundingRateIx(oracle, marketIndex)),
1755
- [],
1756
- this.opts
1757
- );
1758
- return txSig;
1759
- }
1760
-
1761
- public async getUpdateFundingRateIx(
1762
- oracle: PublicKey,
1763
- marketIndex: BN
1764
- ): Promise<TransactionInstruction> {
1765
- return await this.program.instruction.updateFundingRate(marketIndex, {
1766
- accounts: {
1767
- state: await this.getStatePublicKey(),
1768
- market: await getMarketPublicKey(this.program.programId, marketIndex),
1769
- oracle: oracle,
1770
- },
1771
- });
1772
- }
1773
-
1774
- public async settleFundingPayment(
1775
- userAccount: PublicKey
1776
- ): Promise<TransactionSignature> {
1777
- const { txSig } = await this.txSender.send(
1778
- wrapInTx(await this.getSettleFundingPaymentIx(userAccount)),
1779
- [],
1780
- this.opts
1781
- );
1782
- return txSig;
1783
- }
1784
-
1785
- public async getSettleFundingPaymentIx(
1786
- userAccount: PublicKey
1787
- ): Promise<TransactionInstruction> {
1788
- const user = (await this.program.account.user.fetch(
1789
- userAccount
1790
- )) as UserAccount;
1791
-
1792
- const userPositions = user.positions;
1793
-
1794
- const remainingAccounts = [];
1795
- for (const position of userPositions) {
1796
- if (!positionIsAvailable(position)) {
1797
- const marketPublicKey = await getMarketPublicKey(
1798
- this.program.programId,
1799
- position.marketIndex
1800
- );
1801
- remainingAccounts.push({
1802
- pubkey: marketPublicKey,
1803
- isWritable: false,
1804
- isSigner: false,
1805
- });
1806
- }
1807
- }
1808
-
1809
- return await this.program.instruction.settleFundingPayment({
1810
- accounts: {
1811
- state: await this.getStatePublicKey(),
1812
- user: userAccount,
1813
- },
1814
- remainingAccounts,
1815
- });
1816
- }
1817
-
1818
- public triggerEvent(eventName: keyof ClearingHouseAccountEvents, data?: any) {
1819
- this.eventEmitter.emit(eventName, data);
1820
- }
1821
-
1822
- public getOracleDataForMarket(marketIndex: BN): OraclePriceData {
1823
- const oracleKey = this.getMarketAccount(marketIndex).amm.oracle;
1824
- const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
1825
-
1826
- return oracleData;
1827
- }
1828
- }