@drift-labs/sdk 0.1.36-master.7 → 0.2.0-master.10

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 (254) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +6 -6
  2. package/lib/accounts/bulkAccountLoader.js +81 -95
  3. package/lib/accounts/bulkUserSubscription.js +13 -57
  4. package/lib/accounts/fetch.d.ts +4 -0
  5. package/lib/accounts/fetch.js +18 -0
  6. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +34 -38
  7. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +224 -224
  8. package/lib/accounts/pollingOracleSubscriber.d.ts +3 -3
  9. package/lib/accounts/pollingOracleSubscriber.js +37 -49
  10. package/lib/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
  11. package/lib/accounts/pollingTokenAccountSubscriber.js +35 -50
  12. package/lib/accounts/pollingUserAccountSubscriber.d.ts +7 -13
  13. package/lib/accounts/pollingUserAccountSubscriber.js +71 -134
  14. package/lib/accounts/types.d.ts +34 -41
  15. package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -4
  16. package/lib/accounts/webSocketAccountSubscriber.js +39 -35
  17. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +33 -28
  18. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +153 -185
  19. package/lib/accounts/webSocketUserAccountSubscriber.d.ts +5 -11
  20. package/lib/accounts/webSocketUserAccountSubscriber.js +22 -67
  21. package/lib/addresses/marketAddresses.d.ts +4 -0
  22. package/lib/addresses/marketAddresses.js +15 -0
  23. package/lib/addresses/pda.d.ts +12 -0
  24. package/lib/addresses/pda.js +83 -0
  25. package/lib/admin.d.ts +12 -18
  26. package/lib/admin.js +398 -558
  27. package/lib/clearingHouse.d.ts +83 -109
  28. package/lib/clearingHouse.js +832 -893
  29. package/lib/clearingHouseConfig.d.ts +34 -0
  30. package/lib/clearingHouseConfig.js +2 -0
  31. package/lib/clearingHouseUser.d.ts +19 -22
  32. package/lib/clearingHouseUser.js +155 -141
  33. package/lib/clearingHouseUserConfig.d.ts +14 -0
  34. package/lib/clearingHouseUserConfig.js +2 -0
  35. package/lib/config.d.ts +12 -0
  36. package/lib/config.js +35 -4
  37. package/lib/constants/banks.d.ts +16 -0
  38. package/lib/constants/banks.js +41 -0
  39. package/lib/constants/markets.d.ts +8 -3
  40. package/lib/constants/markets.js +13 -206
  41. package/lib/constants/numericConstants.d.ts +17 -0
  42. package/lib/constants/numericConstants.js +23 -6
  43. package/lib/events/eventList.d.ts +22 -0
  44. package/lib/events/eventList.js +77 -0
  45. package/lib/events/eventSubscriber.d.ts +34 -0
  46. package/lib/events/eventSubscriber.js +126 -0
  47. package/lib/events/fetchLogs.d.ts +13 -0
  48. package/lib/events/fetchLogs.js +39 -0
  49. package/lib/events/pollingLogProvider.d.ts +15 -0
  50. package/lib/events/pollingLogProvider.js +53 -0
  51. package/lib/events/sort.d.ts +2 -0
  52. package/lib/events/sort.js +44 -0
  53. package/lib/events/txEventCache.d.ts +24 -0
  54. package/lib/events/txEventCache.js +71 -0
  55. package/lib/events/types.d.ts +49 -0
  56. package/lib/events/types.js +20 -0
  57. package/lib/events/webSocketLogProvider.d.ts +12 -0
  58. package/lib/events/webSocketLogProvider.js +30 -0
  59. package/lib/examples/makeTradeExample.js +26 -27
  60. package/lib/factory/bigNum.d.ts +118 -0
  61. package/lib/factory/bigNum.js +364 -0
  62. package/lib/factory/oracleClient.d.ts +1 -2
  63. package/lib/factory/oracleClient.js +6 -2
  64. package/lib/idl/clearing_house.json +2258 -2774
  65. package/lib/index.d.ts +14 -5
  66. package/lib/index.js +18 -5
  67. package/lib/math/amm.d.ts +24 -29
  68. package/lib/math/amm.js +209 -176
  69. package/lib/math/auction.d.ts +5 -0
  70. package/lib/math/auction.js +42 -0
  71. package/lib/math/bankBalance.d.ts +9 -0
  72. package/lib/math/bankBalance.js +75 -0
  73. package/lib/math/conversion.d.ts +0 -1
  74. package/lib/math/conversion.js +1 -5
  75. package/lib/math/funding.d.ts +6 -6
  76. package/lib/math/funding.js +158 -175
  77. package/lib/math/market.d.ts +6 -6
  78. package/lib/math/market.js +10 -9
  79. package/lib/math/orders.d.ts +6 -1
  80. package/lib/math/orders.js +38 -1
  81. package/lib/math/position.d.ts +7 -5
  82. package/lib/math/position.js +29 -27
  83. package/lib/math/repeg.d.ts +22 -0
  84. package/lib/math/repeg.js +128 -0
  85. package/lib/math/trade.d.ts +5 -4
  86. package/lib/math/trade.js +29 -24
  87. package/lib/mockUSDCFaucet.js +87 -116
  88. package/lib/oracles/oracleClientCache.d.ts +8 -0
  89. package/lib/oracles/oracleClientCache.js +19 -0
  90. package/lib/oracles/pythClient.d.ts +3 -5
  91. package/lib/oracles/pythClient.js +12 -31
  92. package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
  93. package/lib/oracles/quoteAssetOracleClient.js +21 -0
  94. package/lib/oracles/switchboardClient.d.ts +3 -5
  95. package/lib/oracles/switchboardClient.js +29 -50
  96. package/lib/oracles/types.d.ts +6 -1
  97. package/lib/orderParams.d.ts +14 -5
  98. package/lib/orderParams.js +8 -96
  99. package/lib/orders.d.ts +6 -7
  100. package/lib/orders.js +11 -89
  101. package/lib/slot/SlotSubscriber.d.ts +19 -0
  102. package/lib/slot/SlotSubscriber.js +26 -0
  103. package/lib/tx/retryTxSender.d.ts +2 -2
  104. package/lib/tx/retryTxSender.js +108 -123
  105. package/lib/tx/types.d.ts +5 -1
  106. package/lib/tx/utils.d.ts +1 -1
  107. package/lib/tx/utils.js +11 -2
  108. package/lib/types.d.ts +180 -110
  109. package/lib/types.js +54 -1
  110. package/lib/userName.d.ts +4 -0
  111. package/lib/userName.js +20 -0
  112. package/lib/util/computeUnits.js +10 -21
  113. package/lib/util/tps.js +11 -22
  114. package/lib/wallet.js +7 -20
  115. package/package.json +11 -4
  116. package/src/accounts/bulkAccountLoader.js +197 -0
  117. package/src/accounts/bulkAccountLoader.ts +21 -15
  118. package/src/accounts/bulkUserSubscription.js +33 -0
  119. package/src/accounts/bulkUserSubscription.ts +1 -45
  120. package/src/accounts/fetch.js +29 -0
  121. package/src/accounts/fetch.ts +33 -0
  122. package/src/accounts/pollingClearingHouseAccountSubscriber.js +311 -0
  123. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
  124. package/src/accounts/pollingOracleSubscriber.js +93 -0
  125. package/src/accounts/pollingOracleSubscriber.ts +16 -8
  126. package/src/accounts/pollingTokenAccountSubscriber.js +90 -0
  127. package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
  128. package/src/accounts/pollingUserAccountSubscriber.js +132 -0
  129. package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
  130. package/src/accounts/types.js +10 -0
  131. package/src/accounts/types.ts +41 -70
  132. package/src/accounts/utils.js +7 -0
  133. package/src/accounts/webSocketAccountSubscriber.js +93 -0
  134. package/src/accounts/webSocketAccountSubscriber.ts +33 -16
  135. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +233 -0
  136. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
  137. package/src/accounts/webSocketUserAccountSubscriber.js +62 -0
  138. package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
  139. package/src/addresses/marketAddresses.js +26 -0
  140. package/src/addresses/marketAddresses.ts +18 -0
  141. package/{lib/addresses.js → src/addresses/pda.js} +45 -34
  142. package/src/addresses/pda.ts +118 -0
  143. package/src/admin.ts +247 -336
  144. package/src/assert/assert.js +9 -0
  145. package/src/clearingHouse.ts +1023 -1026
  146. package/src/clearingHouseConfig.ts +37 -0
  147. package/src/clearingHouseUser.ts +275 -185
  148. package/src/clearingHouseUserConfig.ts +18 -0
  149. package/src/config.ts +54 -1
  150. package/src/constants/banks.ts +50 -0
  151. package/src/constants/markets.ts +16 -207
  152. package/src/constants/numericConstants.ts +34 -5
  153. package/src/events/eventList.js +77 -0
  154. package/src/events/eventList.ts +94 -0
  155. package/src/events/eventSubscriber.js +139 -0
  156. package/src/events/eventSubscriber.ts +194 -0
  157. package/src/events/fetchLogs.js +50 -0
  158. package/src/events/fetchLogs.ts +80 -0
  159. package/src/events/pollingLogProvider.js +64 -0
  160. package/src/events/pollingLogProvider.ts +79 -0
  161. package/src/events/sort.js +44 -0
  162. package/src/events/sort.ts +65 -0
  163. package/src/events/txEventCache.js +71 -0
  164. package/src/events/txEventCache.ts +74 -0
  165. package/src/events/types.js +20 -0
  166. package/src/events/types.ts +98 -0
  167. package/src/events/webSocketLogProvider.js +41 -0
  168. package/src/events/webSocketLogProvider.ts +38 -0
  169. package/src/examples/makeTradeExample.js +80 -0
  170. package/src/examples/makeTradeExample.ts +20 -11
  171. package/src/factory/bigNum.js +364 -0
  172. package/src/factory/bigNum.ts +524 -0
  173. package/src/factory/oracleClient.js +20 -0
  174. package/src/factory/oracleClient.ts +7 -4
  175. package/src/idl/clearing_house.json +2258 -2774
  176. package/src/index.js +69 -0
  177. package/src/index.ts +14 -5
  178. package/src/math/amm.js +369 -0
  179. package/src/math/amm.ts +382 -243
  180. package/src/math/auction.js +42 -0
  181. package/src/math/auction.ts +43 -0
  182. package/src/math/bankBalance.js +75 -0
  183. package/src/math/bankBalance.ts +112 -0
  184. package/src/math/conversion.js +11 -0
  185. package/src/math/conversion.ts +1 -11
  186. package/src/math/funding.js +248 -0
  187. package/src/math/funding.ts +12 -9
  188. package/src/math/market.js +57 -0
  189. package/src/math/market.ts +37 -30
  190. package/src/math/oracles.js +26 -0
  191. package/src/math/orders.js +110 -0
  192. package/src/math/orders.ts +43 -1
  193. package/src/math/position.js +140 -0
  194. package/src/math/position.ts +52 -35
  195. package/src/math/repeg.js +128 -0
  196. package/src/math/repeg.ts +176 -0
  197. package/src/math/state.js +15 -0
  198. package/src/math/trade.js +253 -0
  199. package/src/math/trade.ts +55 -47
  200. package/src/math/utils.js +26 -0
  201. package/src/math/utils.js.map +1 -0
  202. package/src/mockUSDCFaucet.js +171 -0
  203. package/src/oracles/oracleClientCache.js +19 -0
  204. package/src/oracles/oracleClientCache.ts +20 -0
  205. package/src/oracles/pythClient.js +46 -0
  206. package/src/oracles/pythClient.ts +4 -11
  207. package/src/oracles/quoteAssetOracleClient.js +32 -0
  208. package/src/oracles/quoteAssetOracleClient.ts +25 -0
  209. package/src/oracles/switchboardClient.js +69 -0
  210. package/src/oracles/switchboardClient.ts +11 -24
  211. package/src/oracles/types.js +2 -0
  212. package/src/oracles/types.ts +7 -1
  213. package/src/orderParams.js +20 -0
  214. package/src/orderParams.ts +20 -141
  215. package/src/orders.js +134 -0
  216. package/src/orders.ts +25 -134
  217. package/src/slot/SlotSubscriber.js +39 -0
  218. package/src/slot/SlotSubscriber.ts +42 -0
  219. package/src/token/index.js +38 -0
  220. package/src/tx/retryTxSender.js +188 -0
  221. package/src/tx/retryTxSender.ts +6 -4
  222. package/src/tx/types.js +2 -0
  223. package/src/tx/types.ts +6 -1
  224. package/src/tx/utils.js +17 -0
  225. package/src/tx/utils.ts +22 -3
  226. package/src/types.js +114 -0
  227. package/src/types.ts +176 -124
  228. package/src/userName.js +20 -0
  229. package/src/userName.ts +20 -0
  230. package/src/util/promiseTimeout.js +14 -0
  231. package/src/util/tps.js +27 -0
  232. package/src/wallet.js +35 -0
  233. package/tests/bn/test.ts +255 -0
  234. package/tsconfig.json +12 -12
  235. package/lib/addresses.d.ts +0 -10
  236. package/lib/constants/accounts.d.ts +0 -15
  237. package/lib/constants/accounts.js +0 -18
  238. package/lib/factory/clearingHouse.d.ts +0 -35
  239. package/lib/factory/clearingHouse.js +0 -81
  240. package/lib/factory/clearingHouseUser.d.ts +0 -19
  241. package/lib/factory/clearingHouseUser.js +0 -34
  242. package/lib/math/insuranceFund.d.ts +0 -15
  243. package/lib/math/insuranceFund.js +0 -33
  244. package/lib/settlement.d.ts +0 -4
  245. package/lib/settlement.js +0 -10
  246. package/lib/tx/defaultTxSender.d.ts +0 -8
  247. package/lib/tx/defaultTxSender.js +0 -12
  248. package/src/addresses.ts +0 -82
  249. package/src/constants/accounts.ts +0 -26
  250. package/src/factory/clearingHouse.ts +0 -173
  251. package/src/factory/clearingHouseUser.ts +0 -73
  252. package/src/math/insuranceFund.ts +0 -29
  253. package/src/settlement.ts +0 -9
  254. package/src/tx/defaultTxSender.ts +0 -24
@@ -22,15 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
35
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
27
  };
@@ -38,33 +29,65 @@ Object.defineProperty(exports, "__esModule", { value: true });
38
29
  exports.ClearingHouse = void 0;
39
30
  const anchor_1 = require("@project-serum/anchor");
40
31
  const spl_token_1 = require("@solana/spl-token");
32
+ const types_1 = require("./types");
41
33
  const anchor = __importStar(require("@project-serum/anchor"));
42
34
  const clearing_house_json_1 = __importDefault(require("./idl/clearing_house.json"));
43
35
  const web3_js_1 = require("@solana/web3.js");
44
- const addresses_1 = require("./addresses");
36
+ const pda_1 = require("./addresses/pda");
45
37
  const utils_1 = require("./tx/utils");
46
- const clearingHouse_1 = require("./factory/clearingHouse");
47
38
  const numericConstants_1 = require("./constants/numericConstants");
48
- const bulkAccountLoader_1 = require("./accounts/bulkAccountLoader");
49
- const clearingHouseUser_1 = require("./factory/clearingHouseUser");
50
- const bulkUserSubscription_1 = require("./accounts/bulkUserSubscription");
39
+ const position_1 = require("./math/position");
40
+ const bankBalance_1 = require("./math/bankBalance");
41
+ const userName_1 = require("./userName");
42
+ const pollingClearingHouseAccountSubscriber_1 = require("./accounts/pollingClearingHouseAccountSubscriber");
43
+ const webSocketClearingHouseAccountSubscriber_1 = require("./accounts/webSocketClearingHouseAccountSubscriber");
44
+ const retryTxSender_1 = require("./tx/retryTxSender");
45
+ const clearingHouseUser_1 = require("./clearingHouseUser");
46
+ const config_1 = require("./config");
51
47
  /**
52
48
  * # ClearingHouse
53
49
  * 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.
54
- *
55
- * 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.
56
- * 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}
57
50
  */
58
51
  class ClearingHouse {
59
- constructor(connection, wallet, program, accountSubscriber, txSender, opts) {
52
+ constructor(config) {
53
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
54
+ this.users = new Map();
60
55
  this._isSubscribed = false;
61
- this.connection = connection;
62
- this.wallet = wallet;
63
- this.opts = opts;
64
- this.program = program;
65
- this.accountSubscriber = accountSubscriber;
56
+ this.marketLastSlotCache = new Map();
57
+ this.connection = config.connection;
58
+ this.wallet = config.wallet;
59
+ this.opts = config.opts || anchor_1.AnchorProvider.defaultOptions();
60
+ this.provider = new anchor_1.AnchorProvider(config.connection, config.wallet, this.opts);
61
+ this.program = new anchor_1.Program(clearing_house_json_1.default, config.programID, this.provider);
62
+ const userIds = (_a = config.userIds) !== null && _a !== void 0 ? _a : [0];
63
+ this.activeUserId = (_b = config.activeUserId) !== null && _b !== void 0 ? _b : userIds[0];
64
+ this.userAccountSubscriptionConfig =
65
+ ((_c = config.accountSubscription) === null || _c === void 0 ? void 0 : _c.type) === 'polling'
66
+ ? {
67
+ type: 'polling',
68
+ accountLoader: config.accountSubscription.accountLoader,
69
+ }
70
+ : {
71
+ type: 'websocket',
72
+ };
73
+ this.createUsers(userIds, this.userAccountSubscriptionConfig);
74
+ let marketIndexes = config.marketIndexes;
75
+ let bankIndexes = config.bankIndexes;
76
+ let oracleInfos = config.oracleInfos;
77
+ if (config.env) {
78
+ const { marketIndexes: envMarketIndexes, bankIndexes: envBankIndexes, oracleInfos: envOralceInfos, } = (0, config_1.getMarketsBanksAndOraclesForSubscription)(config.env);
79
+ marketIndexes = marketIndexes ? marketIndexes : envMarketIndexes;
80
+ bankIndexes = bankIndexes ? bankIndexes : envBankIndexes;
81
+ oracleInfos = oracleInfos ? oracleInfos : envOralceInfos;
82
+ }
83
+ if (((_d = config.accountSubscription) === null || _d === void 0 ? void 0 : _d.type) === 'polling') {
84
+ this.accountSubscriber = new pollingClearingHouseAccountSubscriber_1.PollingClearingHouseAccountSubscriber(this.program, config.accountSubscription.accountLoader, marketIndexes !== null && marketIndexes !== void 0 ? marketIndexes : [], bankIndexes !== null && bankIndexes !== void 0 ? bankIndexes : [], oracleInfos !== null && oracleInfos !== void 0 ? oracleInfos : []);
85
+ }
86
+ else {
87
+ this.accountSubscriber = new webSocketClearingHouseAccountSubscriber_1.WebSocketClearingHouseAccountSubscriber(this.program, (_e = config.marketIndexes) !== null && _e !== void 0 ? _e : [], (_f = config.bankIndexes) !== null && _f !== void 0 ? _f : [], (_g = config.oracleInfos) !== null && _g !== void 0 ? _g : []);
88
+ }
66
89
  this.eventEmitter = this.accountSubscriber.eventEmitter;
67
- this.txSender = txSender;
90
+ this.txSender = new retryTxSender_1.RetryTxSender(this.provider, (_h = config.txSenderConfig) === null || _h === void 0 ? void 0 : _h.timeout, (_j = config.txSenderConfig) === null || _j === void 0 ? void 0 : _j.retrySleep, (_k = config.txSenderConfig) === null || _k === void 0 ? void 0 : _k.additionalConnections);
68
91
  }
69
92
  get isSubscribed() {
70
93
  return this._isSubscribed && this.accountSubscriber.isSubscribed;
@@ -72,128 +95,82 @@ class ClearingHouse {
72
95
  set isSubscribed(val) {
73
96
  this._isSubscribed = val;
74
97
  }
75
- /**
76
- * @deprecated You should use the getClearingHouse factory method instead
77
- * @param connection
78
- * @param wallet
79
- * @param clearingHouseProgramId
80
- * @param opts
81
- * @returns
82
- */
83
- static from(connection, wallet, clearingHouseProgramId, opts = anchor_1.AnchorProvider.defaultOptions()) {
84
- const config = (0, clearingHouse_1.getWebSocketClearingHouseConfig)(connection, wallet, clearingHouseProgramId, opts);
85
- return (0, clearingHouse_1.getClearingHouse)(config);
98
+ createUsers(userIds, accountSubscriptionConfig) {
99
+ for (const userId of userIds) {
100
+ const user = this.createUser(userId, accountSubscriptionConfig);
101
+ this.users.set(userId, user);
102
+ }
86
103
  }
87
- /**
88
- *
89
- * @param optionalSubscriptions - Optional extra accounts to subcribe to. Always subscribes to base clearing house state and market account state by default. You should only subscribe to optional extra accounts if required, to avoid overloading your RPC.
90
- * @returns Promise<boolean> : SubscriptionSuccess
91
- */
92
- subscribe(optionalSubscriptions) {
93
- return __awaiter(this, void 0, void 0, function* () {
94
- this.isSubscribed = yield this.accountSubscriber.subscribe(optionalSubscriptions);
95
- return this.isSubscribed;
104
+ createUser(userId, accountSubscriptionConfig) {
105
+ const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, userId);
106
+ return new clearingHouseUser_1.ClearingHouseUser({
107
+ clearingHouse: this,
108
+ userAccountPublicKey,
109
+ accountSubscription: accountSubscriptionConfig,
96
110
  });
97
111
  }
98
- /**
99
- * Shorthand function to subscribe to all available Clearing House State Accounts
100
- * @returns Promise<boolean> : SubscriptionSuccess
101
- */
102
- subscribeToAll() {
103
- return __awaiter(this, void 0, void 0, function* () {
104
- return this.subscribe([
105
- 'curveHistoryAccount',
106
- 'depositHistoryAccount',
107
- 'fundingPaymentHistoryAccount',
108
- 'fundingRateHistoryAccount',
109
- 'liquidationHistoryAccount',
110
- 'tradeHistoryAccount',
111
- 'orderHistoryAccount',
112
- ]);
113
- });
112
+ async subscribe() {
113
+ const subscribePromises = this.subscribeUsers().concat(this.accountSubscriber.subscribe());
114
+ this.isSubscribed = (await Promise.all(subscribePromises)).reduce((success, prevSuccess) => success && prevSuccess);
115
+ return this.isSubscribed;
114
116
  }
115
- /**
116
- * Forces the accountSubscriber to fetch account updates from rpc
117
- */
118
- fetchAccounts() {
119
- return __awaiter(this, void 0, void 0, function* () {
120
- yield this.accountSubscriber.fetch();
121
- });
117
+ subscribeUsers() {
118
+ return [...this.users.values()].map((user) => user.subscribe());
122
119
  }
123
120
  /**
124
- * Unsubscribe from all currently subscribed state accounts
121
+ * Forces the accountSubscriber to fetch account updates from rpc
125
122
  */
126
- unsubscribe() {
127
- return __awaiter(this, void 0, void 0, function* () {
128
- yield this.accountSubscriber.unsubscribe();
129
- this.isSubscribed = false;
130
- });
123
+ async fetchAccounts() {
124
+ await Promise.all([...this.users.values()]
125
+ .map((user) => user.fetchAccounts())
126
+ .concat(this.accountSubscriber.fetch()));
131
127
  }
132
- getStatePublicKey() {
133
- return __awaiter(this, void 0, void 0, function* () {
134
- if (this.statePublicKey) {
135
- return this.statePublicKey;
136
- }
137
- this.statePublicKey = yield (0, addresses_1.getClearingHouseStateAccountPublicKey)(this.program.programId);
138
- return this.statePublicKey;
139
- });
140
- }
141
- getStateAccount() {
142
- return this.accountSubscriber.getStateAccount();
128
+ async unsubscribe() {
129
+ const unsubscribePromises = this.unsubscribeUsers().concat(this.accountSubscriber.unsubscribe());
130
+ await Promise.all(unsubscribePromises);
131
+ this.isSubscribed = false;
143
132
  }
144
- getSettlementAccount() {
145
- return __awaiter(this, void 0, void 0, function* () {
146
- // @ts-ignore
147
- return yield this.program.account.settlementState.fetch(yield (0, addresses_1.getSettlementStatePublicKey)(this.program.programId));
148
- });
133
+ unsubscribeUsers() {
134
+ return [...this.users.values()].map((user) => user.unsubscribe());
149
135
  }
150
- getMarketsAccount() {
151
- return this.accountSubscriber.getMarketsAccount();
152
- }
153
- getMarket(marketIndex) {
154
- if (marketIndex instanceof anchor_1.BN) {
155
- marketIndex = marketIndex.toNumber();
136
+ async getStatePublicKey() {
137
+ if (this.statePublicKey) {
138
+ return this.statePublicKey;
156
139
  }
157
- return this.getMarketsAccount().markets[marketIndex];
158
- }
159
- getFundingPaymentHistoryAccount() {
160
- return this.accountSubscriber.getFundingPaymentHistoryAccount();
161
- }
162
- getFundingRateHistoryAccount() {
163
- return this.accountSubscriber.getFundingRateHistoryAccount();
140
+ this.statePublicKey = await (0, pda_1.getClearingHouseStateAccountPublicKey)(this.program.programId);
141
+ return this.statePublicKey;
164
142
  }
165
- getTradeHistoryAccount() {
166
- return this.accountSubscriber.getTradeHistoryAccount();
167
- }
168
- getLiquidationHistoryAccount() {
169
- return this.accountSubscriber.getLiquidationHistoryAccount();
143
+ getStateAccount() {
144
+ return this.accountSubscriber.getStateAccountAndSlot().data;
170
145
  }
171
- getDepositHistoryAccount() {
172
- return this.accountSubscriber.getDepositHistoryAccount();
146
+ getMarketAccount(marketIndex) {
147
+ var _a;
148
+ marketIndex = marketIndex instanceof anchor_1.BN ? marketIndex : new anchor_1.BN(marketIndex);
149
+ return (_a = this.accountSubscriber.getMarketAccountAndSlot(marketIndex)) === null || _a === void 0 ? void 0 : _a.data;
173
150
  }
174
- getCurveHistoryAccount() {
175
- return this.accountSubscriber.getCurveHistoryAccount();
151
+ getMarketAccounts() {
152
+ return this.accountSubscriber
153
+ .getMarketAccountsAndSlots()
154
+ .map((value) => value.data);
176
155
  }
177
- getOrderHistoryAccount() {
178
- return this.accountSubscriber.getOrderHistoryAccount();
156
+ getBankAccount(bankIndex) {
157
+ bankIndex = bankIndex instanceof anchor_1.BN ? bankIndex : new anchor_1.BN(bankIndex);
158
+ return this.accountSubscriber.getBankAccountAndSlot(bankIndex).data;
179
159
  }
180
- getOrderStatePublicKey() {
181
- return __awaiter(this, void 0, void 0, function* () {
182
- if (this.orderStatePublicKey) {
183
- return this.orderStatePublicKey;
184
- }
185
- this.orderStatePublicKey = yield (0, addresses_1.getOrderStateAccountPublicKey)(this.program.programId);
186
- return this.orderStatePublicKey;
187
- });
160
+ getQuoteAssetBankAccount() {
161
+ return this.accountSubscriber.getBankAccountAndSlot(numericConstants_1.QUOTE_ASSET_BANK_INDEX)
162
+ .data;
188
163
  }
189
- getOrderStateAccount() {
190
- return this.accountSubscriber.getOrderStateAccount();
164
+ getOraclePriceDataAndSlot(oraclePublicKey) {
165
+ return this.accountSubscriber.getOraclePriceDataAndSlot(oraclePublicKey);
191
166
  }
192
167
  /**
193
168
  * Update the wallet to use for clearing house transactions and linked user account
194
169
  * @param newWallet
170
+ * @param userIds
171
+ * @param activeUserId
195
172
  */
196
- updateWallet(newWallet) {
173
+ async updateWallet(newWallet, userIds = [0], activeUserId = 0) {
197
174
  const newProvider = new anchor_1.AnchorProvider(this.connection, newWallet, this.opts);
198
175
  const newProgram = new anchor_1.Program(clearing_house_json_1.default, this.program.programId, newProvider);
199
176
  // Update provider for txSender with new wallet details
@@ -201,852 +178,814 @@ class ClearingHouse {
201
178
  this.wallet = newWallet;
202
179
  this.provider = newProvider;
203
180
  this.program = newProgram;
204
- this.userAccountPublicKey = undefined;
205
- this.userAccount = undefined;
206
- this.userOrdersAccountPublicKey = undefined;
207
- this.userOrdersExist = undefined;
208
- }
209
- initializeUserAccount() {
210
- return __awaiter(this, void 0, void 0, function* () {
211
- const [userPositionsAccount, userAccountPublicKey, initializeUserAccountIx, initializeUserOrdersAccountIx,] = yield this.getInitializeUserInstructions();
212
- const tx = new web3_js_1.Transaction()
213
- .add(initializeUserAccountIx)
214
- .add(initializeUserOrdersAccountIx);
215
- const txSig = yield this.txSender.send(tx, [userPositionsAccount], this.opts);
216
- return [txSig, userAccountPublicKey];
217
- });
218
- }
219
- getInitializeUserInstructions() {
220
- return __awaiter(this, void 0, void 0, function* () {
221
- const [userAccountPublicKey, userAccountNonce] = yield (0, addresses_1.getUserAccountPublicKeyAndNonce)(this.program.programId, this.wallet.publicKey);
222
- const remainingAccounts = [];
223
- const optionalAccounts = {
224
- whitelistToken: false,
225
- };
226
- const state = this.getStateAccount();
227
- if (state.whitelistMint) {
228
- optionalAccounts.whitelistToken = true;
229
- const associatedTokenPublicKey = yield spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, state.whitelistMint, this.wallet.publicKey);
230
- remainingAccounts.push({
231
- pubkey: associatedTokenPublicKey,
232
- isWritable: false,
233
- isSigner: false,
234
- });
235
- }
236
- const userPositions = new web3_js_1.Keypair();
237
- const initializeUserAccountIx = yield this.program.instruction.initializeUser(userAccountNonce, optionalAccounts, {
238
- accounts: {
239
- user: userAccountPublicKey,
240
- authority: this.wallet.publicKey,
241
- rent: anchor.web3.SYSVAR_RENT_PUBKEY,
242
- systemProgram: anchor.web3.SystemProgram.programId,
243
- userPositions: userPositions.publicKey,
244
- state: yield this.getStatePublicKey(),
245
- },
246
- remainingAccounts: remainingAccounts,
247
- });
248
- const initializeUserOrdersAccountIx = yield this.getInitializeUserOrdersInstruction(userAccountPublicKey);
249
- return [
250
- userPositions,
251
- userAccountPublicKey,
252
- initializeUserAccountIx,
253
- initializeUserOrdersAccountIx,
254
- ];
255
- });
256
- }
257
- getInitializeUserOrdersInstruction(userAccountPublicKey) {
258
- return __awaiter(this, void 0, void 0, function* () {
259
- if (!userAccountPublicKey) {
260
- userAccountPublicKey = yield this.getUserAccountPublicKey();
261
- }
262
- const [userOrdersAccountPublicKey, userOrdersAccountNonce] = yield (0, addresses_1.getUserOrdersAccountPublicKeyAndNonce)(this.program.programId, userAccountPublicKey);
263
- return yield this.program.instruction.initializeUserOrders(userOrdersAccountNonce, {
264
- accounts: {
265
- user: userAccountPublicKey,
266
- authority: this.wallet.publicKey,
267
- rent: anchor.web3.SYSVAR_RENT_PUBKEY,
268
- systemProgram: anchor.web3.SystemProgram.programId,
269
- userOrders: userOrdersAccountPublicKey,
270
- state: yield this.getStatePublicKey(),
271
- },
272
- });
273
- });
274
- }
275
- /**
276
- * Get the address for the Clearing House User's account. NOT the user's wallet address.
277
- * @returns
278
- */
279
- getUserAccountPublicKey() {
280
- return __awaiter(this, void 0, void 0, function* () {
281
- if (this.userAccountPublicKey) {
282
- return this.userAccountPublicKey;
283
- }
284
- this.userAccountPublicKey = yield (0, addresses_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey);
285
- return this.userAccountPublicKey;
286
- });
287
- }
288
- getUserAccount() {
289
- return __awaiter(this, void 0, void 0, function* () {
290
- if (this.userAccount) {
291
- return this.userAccount;
292
- }
293
- this.userAccount = (yield this.program.account.user.fetch(yield this.getUserAccountPublicKey()));
294
- return this.userAccount;
295
- });
296
- }
297
- /**
298
- * Get the address for the Clearing House User Order's account. NOT the user's wallet address.
299
- * @returns
300
- */
301
- getUserOrdersAccountPublicKey() {
302
- return __awaiter(this, void 0, void 0, function* () {
303
- if (this.userOrdersAccountPublicKey) {
304
- return this.userOrdersAccountPublicKey;
305
- }
306
- this.userOrdersAccountPublicKey = yield (0, addresses_1.getUserOrdersAccountPublicKey)(this.program.programId, yield this.getUserAccountPublicKey());
307
- return this.userOrdersAccountPublicKey;
308
- });
181
+ if (this.isSubscribed) {
182
+ await Promise.all(this.unsubscribeUsers());
183
+ }
184
+ this.users.clear();
185
+ this.createUsers(userIds, this.userAccountSubscriptionConfig);
186
+ if (this.isSubscribed) {
187
+ await Promise.all(this.subscribeUsers());
188
+ }
189
+ this.activeUserId = activeUserId;
309
190
  }
310
- userOrdersAccountExists() {
311
- return __awaiter(this, void 0, void 0, function* () {
312
- if (this.userOrdersExist) {
313
- return this.userOrdersExist;
314
- }
315
- const userOrdersAccountRPCResponse = yield this.connection.getParsedAccountInfo(yield this.getUserOrdersAccountPublicKey());
316
- this.userOrdersExist = userOrdersAccountRPCResponse.value !== null;
317
- return this.userOrdersExist;
318
- });
191
+ async switchActiveUser(userId) {
192
+ this.activeUserId = userId;
319
193
  }
320
- depositCollateral(amount, collateralAccountPublicKey, userPositionsAccountPublicKey) {
321
- return __awaiter(this, void 0, void 0, function* () {
322
- const depositCollateralIx = yield this.getDepositCollateralInstruction(amount, collateralAccountPublicKey, userPositionsAccountPublicKey);
323
- const tx = new web3_js_1.Transaction().add(depositCollateralIx);
324
- return yield this.txSender.send(tx);
325
- });
194
+ async addUser(userId) {
195
+ if (this.users.has(userId)) {
196
+ return;
197
+ }
198
+ const user = this.createUser(userId, this.userAccountSubscriptionConfig);
199
+ await user.subscribe();
200
+ this.users.set(userId, user);
201
+ }
202
+ async initializeUserAccount(userId = 0, name = userName_1.DEFAULT_USER_NAME) {
203
+ const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
204
+ const tx = new web3_js_1.Transaction().add(initializeUserAccountIx);
205
+ const { txSig } = await this.txSender.send(tx, [], this.opts);
206
+ return [txSig, userAccountPublicKey];
207
+ }
208
+ async getInitializeUserInstructions(userId = 0, name = userName_1.DEFAULT_USER_NAME) {
209
+ const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, userId);
210
+ const nameBuffer = (0, userName_1.encodeName)(name);
211
+ const initializeUserAccountIx = await this.program.instruction.initializeUser(userId, nameBuffer, {
212
+ accounts: {
213
+ user: userAccountPublicKey,
214
+ authority: this.wallet.publicKey,
215
+ payer: this.wallet.publicKey,
216
+ rent: anchor.web3.SYSVAR_RENT_PUBKEY,
217
+ systemProgram: anchor.web3.SystemProgram.programId,
218
+ state: await this.getStatePublicKey(),
219
+ },
220
+ });
221
+ return [userAccountPublicKey, initializeUserAccountIx];
222
+ }
223
+ getUser(userId) {
224
+ userId = userId !== null && userId !== void 0 ? userId : this.activeUserId;
225
+ if (!this.users.has(userId)) {
226
+ throw new Error(`Clearing House has no user for user id ${userId}`);
227
+ }
228
+ return this.users.get(userId);
326
229
  }
327
- getDepositCollateralInstruction(amount, collateralAccountPublicKey, userPositionsAccountPublicKey) {
328
- return __awaiter(this, void 0, void 0, function* () {
329
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
330
- if (!userPositionsAccountPublicKey) {
331
- userPositionsAccountPublicKey = (yield this.getUserAccount()).positions;
332
- }
333
- const state = this.getStateAccount();
334
- return yield this.program.instruction.depositCollateral(amount, {
335
- accounts: {
336
- state: yield this.getStatePublicKey(),
337
- user: userAccountPublicKey,
338
- collateralVault: state.collateralVault,
339
- userCollateralAccount: collateralAccountPublicKey,
340
- authority: this.wallet.publicKey,
341
- tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
342
- markets: state.markets,
343
- fundingPaymentHistory: state.fundingPaymentHistory,
344
- depositHistory: state.depositHistory,
345
- userPositions: userPositionsAccountPublicKey,
346
- },
347
- });
348
- });
230
+ getUsers() {
231
+ return [...this.users.values()];
349
232
  }
350
- /**
351
- * Creates the Clearing House User account for a user, and deposits some initial collateral
352
- * @param amount
353
- * @param collateralAccountPublicKey
354
- * @returns
355
- */
356
- initializeUserAccountAndDepositCollateral(amount, collateralAccountPublicKey) {
357
- return __awaiter(this, void 0, void 0, function* () {
358
- const [userPositionsAccount, userAccountPublicKey, initializeUserAccountIx, initializeUserOrdersAccountIx,] = yield this.getInitializeUserInstructions();
359
- const depositCollateralIx = yield this.getDepositCollateralInstruction(amount, collateralAccountPublicKey, userPositionsAccount.publicKey);
360
- const tx = new web3_js_1.Transaction()
361
- .add(initializeUserAccountIx)
362
- .add(initializeUserOrdersAccountIx)
363
- .add(depositCollateralIx);
364
- const txSig = yield this.txSender.send(tx, [userPositionsAccount]);
365
- return [txSig, userAccountPublicKey];
366
- });
233
+ async getUserAccountPublicKey() {
234
+ return this.getUser().userAccountPublicKey;
367
235
  }
368
- initializeUserAccountForDevnet(mockUSDCFaucet, amount) {
369
- return __awaiter(this, void 0, void 0, function* () {
370
- const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = yield mockUSDCFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
371
- const [userPositionsAccount, userAccountPublicKey, initializeUserAccountIx, initializeUserOrdersAccountIx,] = yield this.getInitializeUserInstructions();
372
- const depositCollateralIx = yield this.getDepositCollateralInstruction(amount, associateTokenPublicKey, userPositionsAccount.publicKey);
373
- const tx = new web3_js_1.Transaction()
374
- .add(createAssociatedAccountIx)
375
- .add(mintToIx)
376
- .add(initializeUserAccountIx)
377
- .add(initializeUserOrdersAccountIx)
378
- .add(depositCollateralIx);
379
- const txSig = yield this.program.provider.sendAndConfirm(tx, [
380
- userPositionsAccount,
381
- ]);
382
- return [txSig, userAccountPublicKey];
383
- });
236
+ getUserAccount(userId) {
237
+ return this.getUser(userId).getUserAccount();
384
238
  }
385
- withdrawCollateral(amount, collateralAccountPublicKey) {
386
- return __awaiter(this, void 0, void 0, function* () {
387
- return this.txSender.send((0, utils_1.wrapInTx)(yield this.getWithdrawCollateralIx(amount, collateralAccountPublicKey)), [], this.opts);
388
- });
239
+ getUserAccountAndSlot(userId) {
240
+ return this.getUser(userId).getUserAccountAndSlot();
389
241
  }
390
- getWithdrawCollateralIx(amount, collateralAccountPublicKey) {
391
- return __awaiter(this, void 0, void 0, function* () {
392
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
393
- const user = yield this.program.account.user.fetch(userAccountPublicKey);
394
- const state = this.getStateAccount();
395
- return yield this.program.instruction.withdrawCollateral(amount, {
396
- accounts: {
397
- state: yield this.getStatePublicKey(),
398
- user: userAccountPublicKey,
399
- collateralVault: state.collateralVault,
400
- collateralVaultAuthority: state.collateralVaultAuthority,
401
- insuranceVault: state.insuranceVault,
402
- insuranceVaultAuthority: state.insuranceVaultAuthority,
403
- userCollateralAccount: collateralAccountPublicKey,
404
- authority: this.wallet.publicKey,
405
- tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
406
- markets: state.markets,
407
- userPositions: user.positions,
408
- fundingPaymentHistory: state.fundingPaymentHistory,
409
- depositHistory: state.depositHistory,
410
- },
411
- });
412
- });
242
+ getUserBankBalance(bankIndex) {
243
+ const bankIndexBN = bankIndex instanceof anchor_1.BN ? bankIndex : new anchor_1.BN(bankIndex);
244
+ return this.getUserAccount().bankBalances.find((bankBalance) => bankBalance.bankIndex.eq(bankIndexBN));
413
245
  }
414
- openPosition(direction, amount, marketIndex, limitPrice, discountToken, referrer) {
415
- return __awaiter(this, void 0, void 0, function* () {
416
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getOpenPositionIx(direction, amount, marketIndex, limitPrice, discountToken, referrer)), [], this.opts);
417
- });
246
+ getQuoteAssetTokenAmount() {
247
+ const bank = this.getBankAccount(numericConstants_1.QUOTE_ASSET_BANK_INDEX);
248
+ const userBankBalance = this.getUserBankBalance(numericConstants_1.QUOTE_ASSET_BANK_INDEX);
249
+ return (0, bankBalance_1.getTokenAmount)(userBankBalance.balance, bank, userBankBalance.balanceType);
418
250
  }
419
- getOpenPositionIx(direction, amount, marketIndex, limitPrice, discountToken, referrer) {
420
- return __awaiter(this, void 0, void 0, function* () {
421
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
422
- const userAccount = yield this.getUserAccount();
423
- if (limitPrice == undefined) {
424
- limitPrice = new anchor_1.BN(0); // no limit
425
- }
426
- const optionalAccounts = {
427
- discountToken: false,
428
- referrer: false,
429
- };
430
- const remainingAccounts = [];
431
- if (discountToken) {
432
- optionalAccounts.discountToken = true;
433
- remainingAccounts.push({
434
- pubkey: discountToken,
435
- isWritable: false,
251
+ getRemainingAccounts(params) {
252
+ const userAccountAndSlot = this.getUserAccountAndSlot();
253
+ if (!userAccountAndSlot) {
254
+ throw Error('No user account found. Most likely user account does not exist or failed to fetch account');
255
+ }
256
+ const { data: userAccount, slot: lastUserPositionsSlot } = userAccountAndSlot;
257
+ const oracleAccountMap = new Map();
258
+ const bankAccountMap = new Map();
259
+ const marketAccountMap = new Map();
260
+ for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
261
+ // if cache has more recent slot than user positions account slot, add market to remaining accounts
262
+ // otherwise remove from slot
263
+ if (slot > lastUserPositionsSlot) {
264
+ const marketAccount = this.getMarketAccount(marketIndexNum);
265
+ marketAccountMap.set(marketIndexNum, {
266
+ pubkey: marketAccount.pubkey,
436
267
  isSigner: false,
268
+ isWritable: false,
437
269
  });
438
- }
439
- if (referrer) {
440
- optionalAccounts.referrer = true;
441
- remainingAccounts.push({
442
- pubkey: referrer,
443
- isWritable: true,
270
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
271
+ pubkey: marketAccount.amm.oracle,
444
272
  isSigner: false,
273
+ isWritable: false,
445
274
  });
446
275
  }
447
- const priceOracle = this.getMarketsAccount().markets[marketIndex.toNumber()].amm.oracle;
448
- const state = this.getStateAccount();
449
- return yield this.program.instruction.openPosition(direction, amount, marketIndex, limitPrice, optionalAccounts, {
450
- accounts: {
451
- state: yield this.getStatePublicKey(),
452
- user: userAccountPublicKey,
453
- authority: this.wallet.publicKey,
454
- markets: state.markets,
455
- userPositions: userAccount.positions,
456
- tradeHistory: state.tradeHistory,
457
- fundingPaymentHistory: state.fundingPaymentHistory,
458
- fundingRateHistory: state.fundingRateHistory,
459
- oracle: priceOracle,
460
- },
461
- remainingAccounts: remainingAccounts,
462
- });
463
- });
464
- }
465
- initializeUserOrdersThenPlaceOrder(orderParams, discountToken, referrer) {
466
- return __awaiter(this, void 0, void 0, function* () {
467
- const instructions = [];
468
- const userOrdersAccountExists = yield this.userOrdersAccountExists();
469
- if (!userOrdersAccountExists) {
470
- instructions.push(yield this.getInitializeUserOrdersInstruction());
276
+ else {
277
+ this.marketLastSlotCache.delete(marketIndexNum);
471
278
  }
472
- instructions.push(yield this.getPlaceOrderIx(orderParams, discountToken, referrer));
473
- const tx = new web3_js_1.Transaction();
474
- for (const instruction of instructions) {
475
- tx.add(instruction);
476
- }
477
- return yield this.txSender.send(tx, [], this.opts);
478
- });
479
- }
480
- placeOrder(orderParams, discountToken, referrer) {
481
- return __awaiter(this, void 0, void 0, function* () {
482
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getPlaceOrderIx(orderParams, discountToken, referrer)), [], this.opts);
483
- });
484
- }
485
- getPlaceOrderIx(orderParams, discountToken, referrer) {
486
- return __awaiter(this, void 0, void 0, function* () {
487
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
488
- const userAccount = yield this.getUserAccount();
489
- const priceOracle = this.getMarketsAccount().markets[orderParams.marketIndex.toNumber()].amm
490
- .oracle;
491
- const remainingAccounts = [];
492
- if (orderParams.optionalAccounts.discountToken) {
493
- if (!discountToken) {
494
- throw Error('Optional accounts specified discount token but no discount token present');
495
- }
496
- remainingAccounts.push({
497
- pubkey: discountToken,
498
- isWritable: false,
279
+ }
280
+ for (const position of userAccount.positions) {
281
+ if (!(0, position_1.positionIsAvailable)(position)) {
282
+ const marketIndexNum = position.marketIndex.toNumber();
283
+ const marketAccount = this.getMarketAccount(marketIndexNum);
284
+ marketAccountMap.set(marketIndexNum, {
285
+ pubkey: marketAccount.pubkey,
499
286
  isSigner: false,
287
+ // isWritable: false, // TODO
288
+ isWritable: true,
500
289
  });
501
- }
502
- if (orderParams.optionalAccounts.referrer) {
503
- if (!referrer) {
504
- throw Error('Optional accounts specified referrer but no referrer present');
505
- }
506
- remainingAccounts.push({
507
- pubkey: referrer,
508
- isWritable: false,
290
+ oracleAccountMap.set(marketAccount.pubkey.toString(), {
291
+ pubkey: marketAccount.amm.oracle,
509
292
  isSigner: false,
510
- });
511
- }
512
- if (!orderParams.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
513
- remainingAccounts.push({
514
- pubkey: priceOracle,
515
293
  isWritable: false,
516
- isSigner: false,
517
294
  });
518
295
  }
519
- const state = this.getStateAccount();
520
- const orderState = this.getOrderStateAccount();
521
- return yield this.program.instruction.placeOrder(orderParams, {
522
- accounts: {
523
- state: yield this.getStatePublicKey(),
524
- user: userAccountPublicKey,
525
- authority: this.wallet.publicKey,
526
- markets: state.markets,
527
- userOrders: yield this.getUserOrdersAccountPublicKey(),
528
- userPositions: userAccount.positions,
529
- fundingPaymentHistory: state.fundingPaymentHistory,
530
- fundingRateHistory: state.fundingRateHistory,
531
- orderState: yield this.getOrderStatePublicKey(),
532
- orderHistory: orderState.orderHistory,
533
- },
534
- remainingAccounts,
296
+ }
297
+ if (params.writableMarketIndex) {
298
+ const marketAccount = this.getMarketAccount(params.writableMarketIndex.toNumber());
299
+ marketAccountMap.set(params.writableMarketIndex.toNumber(), {
300
+ pubkey: marketAccount.pubkey,
301
+ isSigner: false,
302
+ isWritable: true,
535
303
  });
536
- });
537
- }
538
- expireOrders(userAccountPublicKey, userOrdersAccountPublicKey) {
539
- return __awaiter(this, void 0, void 0, function* () {
540
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getExpireOrdersIx(userAccountPublicKey, userOrdersAccountPublicKey)), [], this.opts);
541
- });
542
- }
543
- getExpireOrdersIx(userAccountPublicKey, userOrdersAccountPublicKey) {
544
- return __awaiter(this, void 0, void 0, function* () {
545
- const fillerPublicKey = yield this.getUserAccountPublicKey();
546
- const userAccount = yield this.program.account.user.fetch(userAccountPublicKey);
547
- const orderState = this.getOrderStateAccount();
548
- return yield this.program.instruction.expireOrders({
549
- accounts: {
550
- state: yield this.getStatePublicKey(),
551
- filler: fillerPublicKey,
552
- user: userAccountPublicKey,
553
- authority: this.wallet.publicKey,
554
- userPositions: userAccount.positions,
555
- userOrders: userOrdersAccountPublicKey,
556
- orderState: yield this.getOrderStatePublicKey(),
557
- orderHistory: orderState.orderHistory,
558
- },
304
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
305
+ pubkey: marketAccount.amm.oracle,
306
+ isSigner: false,
307
+ isWritable: false,
559
308
  });
560
- });
561
- }
562
- cancelOrder(orderId, oracle) {
563
- return __awaiter(this, void 0, void 0, function* () {
564
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getCancelOrderIx(orderId, oracle)), [], this.opts);
565
- });
566
- }
567
- getCancelOrderIx(orderId, oracle) {
568
- return __awaiter(this, void 0, void 0, function* () {
569
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
570
- const userAccount = yield this.getUserAccount();
571
- const state = this.getStateAccount();
572
- const orderState = this.getOrderStateAccount();
573
- const remainingAccounts = [];
574
- if (oracle) {
575
- remainingAccounts.push({
576
- pubkey: oracle,
577
- isWritable: false,
309
+ }
310
+ for (const userBankBalance of userAccount.bankBalances) {
311
+ if (!userBankBalance.balance.eq(numericConstants_1.ZERO)) {
312
+ const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
313
+ bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
314
+ pubkey: bankAccount.pubkey,
578
315
  isSigner: false,
316
+ isWritable: false,
579
317
  });
318
+ if (!bankAccount.bankIndex.eq(numericConstants_1.ZERO)) {
319
+ oracleAccountMap.set(bankAccount.oracle.toString(), {
320
+ pubkey: bankAccount.oracle,
321
+ isSigner: false,
322
+ isWritable: false,
323
+ });
324
+ }
580
325
  }
581
- return yield this.program.instruction.cancelOrder(orderId, {
582
- accounts: {
583
- state: yield this.getStatePublicKey(),
584
- user: userAccountPublicKey,
585
- authority: this.wallet.publicKey,
586
- markets: state.markets,
587
- userOrders: yield this.getUserOrdersAccountPublicKey(),
588
- userPositions: userAccount.positions,
589
- fundingPaymentHistory: state.fundingPaymentHistory,
590
- fundingRateHistory: state.fundingRateHistory,
591
- orderState: yield this.getOrderStatePublicKey(),
592
- orderHistory: orderState.orderHistory,
593
- },
594
- remainingAccounts,
326
+ }
327
+ if (params.writableBankIndex) {
328
+ const bankAccount = this.getBankAccount(params.writableBankIndex);
329
+ bankAccountMap.set(params.writableBankIndex.toNumber(), {
330
+ pubkey: bankAccount.pubkey,
331
+ isSigner: false,
332
+ isWritable: true,
595
333
  });
596
- });
597
- }
598
- cancelOrderByUserId(userOrderId, oracle) {
599
- return __awaiter(this, void 0, void 0, function* () {
600
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getCancelOrderByUserIdIx(userOrderId, oracle)), [], this.opts);
601
- });
602
- }
603
- getCancelOrderByUserIdIx(userOrderId, oracle) {
604
- return __awaiter(this, void 0, void 0, function* () {
605
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
606
- const userAccount = yield this.getUserAccount();
607
- const state = this.getStateAccount();
608
- const orderState = this.getOrderStateAccount();
609
- const remainingAccounts = [];
610
- if (oracle) {
611
- remainingAccounts.push({
612
- pubkey: oracle,
613
- isWritable: false,
334
+ if (!bankAccount.bankIndex.eq(numericConstants_1.ZERO)) {
335
+ oracleAccountMap.set(bankAccount.oracle.toString(), {
336
+ pubkey: bankAccount.oracle,
614
337
  isSigner: false,
338
+ isWritable: false,
615
339
  });
616
340
  }
617
- return yield this.program.instruction.cancelOrderByUserId(userOrderId, {
618
- accounts: {
619
- state: yield this.getStatePublicKey(),
620
- user: userAccountPublicKey,
621
- authority: this.wallet.publicKey,
622
- markets: state.markets,
623
- userOrders: yield this.getUserOrdersAccountPublicKey(),
624
- userPositions: userAccount.positions,
625
- fundingPaymentHistory: state.fundingPaymentHistory,
626
- fundingRateHistory: state.fundingRateHistory,
627
- orderState: yield this.getOrderStatePublicKey(),
628
- orderHistory: orderState.orderHistory,
629
- },
630
- remainingAccounts,
341
+ }
342
+ return [
343
+ ...oracleAccountMap.values(),
344
+ ...bankAccountMap.values(),
345
+ ...marketAccountMap.values(),
346
+ ];
347
+ }
348
+ getOrder(orderId) {
349
+ var _a;
350
+ const orderIdBN = orderId instanceof anchor_1.BN ? orderId : new anchor_1.BN(orderId);
351
+ return (_a = this.getUserAccount()) === null || _a === void 0 ? void 0 : _a.orders.find((order) => order.orderId.eq(orderIdBN));
352
+ }
353
+ getOrderByUserId(userOrderId) {
354
+ var _a;
355
+ return (_a = this.getUserAccount()) === null || _a === void 0 ? void 0 : _a.orders.find((order) => order.userOrderId === userOrderId);
356
+ }
357
+ async deposit(amount, bankIndex, collateralAccountPublicKey, userId, reduceOnly = false) {
358
+ const depositCollateralIx = await this.getDepositInstruction(amount, bankIndex, collateralAccountPublicKey, userId, reduceOnly, true);
359
+ const tx = new web3_js_1.Transaction().add(depositCollateralIx);
360
+ const { txSig } = await this.txSender.send(tx);
361
+ return txSig;
362
+ }
363
+ async getDepositInstruction(amount, bankIndex, userTokenAccount, userId, reduceOnly = false, userInitialized = true) {
364
+ const userAccountPublicKey = userId
365
+ ? await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, userId)
366
+ : await this.getUserAccountPublicKey();
367
+ let remainingAccounts = [];
368
+ if (userInitialized) {
369
+ remainingAccounts = this.getRemainingAccounts({
370
+ writableBankIndex: bankIndex,
631
371
  });
632
- });
633
- }
634
- cancelAllOrders(oracles, bestEffort) {
635
- return __awaiter(this, void 0, void 0, function* () {
636
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getCancelAllOrdersIx(oracles, bestEffort)), [], this.opts);
637
- });
638
- }
639
- getCancelAllOrdersIx(oracles, bestEffort) {
640
- return __awaiter(this, void 0, void 0, function* () {
641
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
642
- const userAccount = yield this.getUserAccount();
643
- const state = this.getStateAccount();
644
- const orderState = this.getOrderStateAccount();
645
- const remainingAccounts = [];
646
- for (const oracle of oracles) {
372
+ }
373
+ else {
374
+ const bankAccount = this.getBankAccount(bankIndex);
375
+ if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
647
376
  remainingAccounts.push({
648
- pubkey: oracle,
649
- isWritable: false,
377
+ pubkey: bankAccount.oracle,
650
378
  isSigner: false,
379
+ isWritable: false,
651
380
  });
652
381
  }
653
- return yield this.program.instruction.cancelAllOrders(bestEffort, {
654
- accounts: {
655
- state: yield this.getStatePublicKey(),
656
- user: userAccountPublicKey,
657
- authority: this.wallet.publicKey,
658
- markets: state.markets,
659
- userOrders: yield this.getUserOrdersAccountPublicKey(),
660
- userPositions: userAccount.positions,
661
- fundingPaymentHistory: state.fundingPaymentHistory,
662
- fundingRateHistory: state.fundingRateHistory,
663
- orderState: yield this.getOrderStatePublicKey(),
664
- orderHistory: orderState.orderHistory,
665
- },
666
- remainingAccounts,
382
+ remainingAccounts.push({
383
+ pubkey: bankAccount.pubkey,
384
+ isSigner: false,
385
+ isWritable: true,
667
386
  });
387
+ }
388
+ const bank = this.getBankAccount(bankIndex);
389
+ return await this.program.instruction.deposit(bankIndex, amount, reduceOnly, {
390
+ accounts: {
391
+ state: await this.getStatePublicKey(),
392
+ bank: bank.pubkey,
393
+ bankVault: bank.vault,
394
+ user: userAccountPublicKey,
395
+ userTokenAccount: userTokenAccount,
396
+ authority: this.wallet.publicKey,
397
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
398
+ },
399
+ remainingAccounts,
668
400
  });
669
401
  }
670
- cancelOrdersByMarketAndSide(oracles, bestEffort, marketIndexOnly, directionOnly) {
671
- return __awaiter(this, void 0, void 0, function* () {
672
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getCancelOrdersByMarketAndSideIx(oracles, bestEffort, marketIndexOnly, directionOnly)), [], this.opts);
673
- });
674
- }
675
- getCancelOrdersByMarketAndSideIx(oracles, bestEffort, marketIndexOnly, directionOnly) {
676
- return __awaiter(this, void 0, void 0, function* () {
677
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
678
- const userAccount = yield this.getUserAccount();
679
- const state = this.getStateAccount();
680
- const orderState = this.getOrderStateAccount();
681
- const remainingAccounts = [];
682
- for (const oracle of oracles) {
683
- remainingAccounts.push({
684
- pubkey: oracle,
402
+ /**
403
+ * Creates the Clearing House User account for a user, and deposits some initial collateral
404
+ * @param userId
405
+ * @param name
406
+ * @param amount
407
+ * @param userTokenAccount
408
+ * @param fromUserId
409
+ * @returns
410
+ */
411
+ async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, bankIndex = new anchor_1.BN(0), userId = 0, name = userName_1.DEFAULT_USER_NAME, fromUserId) {
412
+ const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
413
+ const depositCollateralIx = fromUserId != null
414
+ ? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
415
+ : await this.getDepositInstruction(amount, bankIndex, userTokenAccount, userId, false, false);
416
+ const tx = new web3_js_1.Transaction()
417
+ .add(initializeUserAccountIx)
418
+ .add(depositCollateralIx);
419
+ const { txSig } = await this.txSender.send(tx, []);
420
+ return [txSig, userAccountPublicKey];
421
+ }
422
+ async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME, mockUSDCFaucet, amount) {
423
+ const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await mockUSDCFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
424
+ const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
425
+ const depositCollateralIx = await this.getDepositInstruction(amount, new anchor_1.BN(0), associateTokenPublicKey, userId, false, false);
426
+ const tx = new web3_js_1.Transaction()
427
+ .add(createAssociatedAccountIx)
428
+ .add(mintToIx)
429
+ .add(initializeUserAccountIx)
430
+ .add(depositCollateralIx);
431
+ const txSig = await this.program.provider.sendAndConfirm(tx, []);
432
+ return [txSig, userAccountPublicKey];
433
+ }
434
+ async withdraw(amount, bankIndex, userTokenAccount, reduceOnly = false) {
435
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getWithdrawIx(amount, bankIndex, userTokenAccount, reduceOnly)), [], this.opts);
436
+ return txSig;
437
+ }
438
+ async getWithdrawIx(amount, bankIndex, userTokenAccount, reduceOnly = false) {
439
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
440
+ const remainingAccounts = this.getRemainingAccounts({
441
+ writableBankIndex: bankIndex,
442
+ });
443
+ const bank = this.getBankAccount(bankIndex);
444
+ return await this.program.instruction.withdraw(bankIndex, amount, reduceOnly, {
445
+ accounts: {
446
+ state: await this.getStatePublicKey(),
447
+ bank: bank.pubkey,
448
+ bankVault: bank.vault,
449
+ bankVaultAuthority: bank.vaultAuthority,
450
+ user: userAccountPublicKey,
451
+ userTokenAccount: userTokenAccount,
452
+ authority: this.wallet.publicKey,
453
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
454
+ },
455
+ remainingAccounts,
456
+ });
457
+ }
458
+ async transferDeposit(amount, bankIndex, fromUserId, toUserId) {
459
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTransferDepositIx(amount, bankIndex, fromUserId, toUserId)), [], this.opts);
460
+ return txSig;
461
+ }
462
+ async getTransferDepositIx(amount, bankIndex, fromUserId, toUserId) {
463
+ const fromUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, fromUserId);
464
+ const toUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, toUserId);
465
+ const remainingAccounts = this.getRemainingAccounts({
466
+ writableBankIndex: bankIndex,
467
+ });
468
+ return await this.program.instruction.transferDeposit(bankIndex, amount, {
469
+ accounts: {
470
+ authority: this.wallet.publicKey,
471
+ fromUser,
472
+ toUser,
473
+ state: await this.getStatePublicKey(),
474
+ },
475
+ remainingAccounts,
476
+ });
477
+ }
478
+ async updateBankCumulativeInterest(bankIndex) {
479
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.updateBankCumulativeInterestIx(bankIndex)), [], this.opts);
480
+ return txSig;
481
+ }
482
+ async updateBankCumulativeInterestIx(bankIndex) {
483
+ const bank = this.getBankAccount(bankIndex);
484
+ return await this.program.instruction.updateBankCumulativeInterest({
485
+ accounts: {
486
+ bank: bank.pubkey,
487
+ },
488
+ });
489
+ }
490
+ async openPosition(direction, amount, marketIndex, limitPrice) {
491
+ return await this.placeAndTake({
492
+ orderType: types_1.OrderType.MARKET,
493
+ marketIndex,
494
+ direction,
495
+ baseAssetAmount: amount,
496
+ price: limitPrice,
497
+ });
498
+ }
499
+ async placeOrder(orderParams) {
500
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceOrderIx(orderParams)), [], this.opts);
501
+ this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
502
+ return txSig;
503
+ }
504
+ getOrderParams(optionalOrderParams) {
505
+ return Object.assign({}, types_1.DefaultOrderParams, optionalOrderParams);
506
+ }
507
+ async getPlaceOrderIx(orderParams) {
508
+ orderParams = this.getOrderParams(orderParams);
509
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
510
+ const remainingAccounts = this.getRemainingAccounts({
511
+ writableMarketIndex: orderParams.marketIndex,
512
+ });
513
+ return await this.program.instruction.placeOrder(orderParams, {
514
+ accounts: {
515
+ state: await this.getStatePublicKey(),
516
+ user: userAccountPublicKey,
517
+ authority: this.wallet.publicKey,
518
+ },
519
+ remainingAccounts,
520
+ });
521
+ }
522
+ async updateAMMs(marketIndexes) {
523
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateAMMsIx(marketIndexes)), [], this.opts);
524
+ return txSig;
525
+ }
526
+ async getUpdateAMMsIx(marketIndexes) {
527
+ for (let i = marketIndexes.length; i < 5; i++) {
528
+ marketIndexes.push(new anchor_1.BN(100));
529
+ }
530
+ const marketAccountInfos = [];
531
+ const oracleAccountInfos = [];
532
+ for (const marketIndex of marketIndexes) {
533
+ if (!marketIndex.eq(new anchor_1.BN(100))) {
534
+ const market = this.getMarketAccount(marketIndex);
535
+ marketAccountInfos.push({
536
+ pubkey: market.pubkey,
537
+ isWritable: true,
538
+ isSigner: false,
539
+ });
540
+ oracleAccountInfos.push({
541
+ pubkey: market.amm.oracle,
685
542
  isWritable: false,
686
543
  isSigner: false,
687
544
  });
688
545
  }
689
- return yield this.program.instruction.cancelOrdersByMarketAndSide(bestEffort, marketIndexOnly, directionOnly, {
690
- accounts: {
691
- state: yield this.getStatePublicKey(),
692
- user: userAccountPublicKey,
693
- authority: this.wallet.publicKey,
694
- markets: state.markets,
695
- userOrders: yield this.getUserOrdersAccountPublicKey(),
696
- userPositions: userAccount.positions,
697
- fundingPaymentHistory: state.fundingPaymentHistory,
698
- fundingRateHistory: state.fundingRateHistory,
699
- orderState: yield this.getOrderStatePublicKey(),
700
- orderHistory: orderState.orderHistory,
701
- },
702
- remainingAccounts,
703
- });
704
- });
705
- }
706
- fillOrder(userAccountPublicKey, userOrdersAccountPublicKey, order) {
707
- return __awaiter(this, void 0, void 0, function* () {
708
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getFillOrderIx(userAccountPublicKey, userOrdersAccountPublicKey, order)), [], this.opts);
709
- });
710
- }
711
- getFillOrderIx(userAccountPublicKey, userOrdersAccountPublicKey, order) {
712
- return __awaiter(this, void 0, void 0, function* () {
713
- const fillerPublicKey = yield this.getUserAccountPublicKey();
714
- const userAccount = yield this.program.account.user.fetch(userAccountPublicKey);
715
- const marketIndex = order.marketIndex;
716
- const oracle = this.getMarket(marketIndex).amm.oracle;
717
- const state = this.getStateAccount();
718
- const orderState = this.getOrderStateAccount();
719
- const remainingAccounts = [];
720
- if (!order.referrer.equals(web3_js_1.PublicKey.default)) {
721
- remainingAccounts.push({
722
- pubkey: order.referrer,
723
- isWritable: true,
546
+ }
547
+ const remainingAccounts = oracleAccountInfos.concat(marketAccountInfos);
548
+ return await this.program.instruction.updateAmms(marketIndexes, {
549
+ accounts: {
550
+ state: await this.getStatePublicKey(),
551
+ authority: this.wallet.publicKey,
552
+ },
553
+ remainingAccounts,
554
+ });
555
+ }
556
+ async cancelOrder(orderId) {
557
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getCancelOrderIx(orderId)), [], this.opts);
558
+ return txSig;
559
+ }
560
+ async getCancelOrderIx(orderId) {
561
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
562
+ const remainingAccounts = this.getRemainingAccounts({});
563
+ return await this.program.instruction.cancelOrder(orderId !== null && orderId !== void 0 ? orderId : null, {
564
+ accounts: {
565
+ state: await this.getStatePublicKey(),
566
+ user: userAccountPublicKey,
567
+ authority: this.wallet.publicKey,
568
+ },
569
+ remainingAccounts,
570
+ });
571
+ }
572
+ async cancelOrderByUserId(userOrderId) {
573
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getCancelOrderByUserIdIx(userOrderId)), [], this.opts);
574
+ return txSig;
575
+ }
576
+ async getCancelOrderByUserIdIx(userOrderId) {
577
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
578
+ const order = this.getOrderByUserId(userOrderId);
579
+ const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
580
+ const remainingAccounts = this.getRemainingAccounts({});
581
+ return await this.program.instruction.cancelOrderByUserId(userOrderId, {
582
+ accounts: {
583
+ state: await this.getStatePublicKey(),
584
+ user: userAccountPublicKey,
585
+ authority: this.wallet.publicKey,
586
+ oracle,
587
+ },
588
+ remainingAccounts,
589
+ });
590
+ }
591
+ async fillOrder(userAccountPublicKey, user, order, makerInfo) {
592
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)), [], this.opts);
593
+ return txSig;
594
+ }
595
+ async getFillOrderIx(userAccountPublicKey, userAccount, order, makerInfo) {
596
+ const fillerPublicKey = await this.getUserAccountPublicKey();
597
+ const marketIndex = order.marketIndex;
598
+ const marketAccount = this.getMarketAccount(marketIndex);
599
+ const oracleAccountMap = new Map();
600
+ const bankAccountMap = new Map();
601
+ const marketAccountMap = new Map();
602
+ marketAccountMap.set(marketIndex.toNumber(), {
603
+ pubkey: marketAccount.pubkey,
604
+ isWritable: true,
605
+ isSigner: false,
606
+ });
607
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
608
+ pubkey: marketAccount.amm.oracle,
609
+ isWritable: false,
610
+ isSigner: false,
611
+ });
612
+ for (const bankBalance of userAccount.bankBalances) {
613
+ if (!bankBalance.balance.eq(numericConstants_1.ZERO)) {
614
+ const bankAccount = this.getBankAccount(bankBalance.bankIndex);
615
+ bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
616
+ pubkey: bankAccount.pubkey,
724
617
  isSigner: false,
618
+ isWritable: true,
725
619
  });
726
- }
727
- const orderId = order.orderId;
728
- return yield this.program.instruction.fillOrder(orderId, {
729
- accounts: {
730
- state: yield this.getStatePublicKey(),
731
- filler: fillerPublicKey,
732
- user: userAccountPublicKey,
733
- authority: this.wallet.publicKey,
734
- markets: state.markets,
735
- userPositions: userAccount.positions,
736
- userOrders: userOrdersAccountPublicKey,
737
- tradeHistory: state.tradeHistory,
738
- fundingPaymentHistory: state.fundingPaymentHistory,
739
- fundingRateHistory: state.fundingRateHistory,
740
- orderState: yield this.getOrderStatePublicKey(),
741
- orderHistory: orderState.orderHistory,
742
- extendedCurveHistory: state.extendedCurveHistory,
743
- oracle: oracle,
744
- },
745
- remainingAccounts,
746
- });
747
- });
748
- }
749
- initializeUserOrdersThenPlaceAndFillOrder(orderParams, discountToken, referrer) {
750
- return __awaiter(this, void 0, void 0, function* () {
751
- const instructions = [];
752
- const userOrdersAccountExists = yield this.userOrdersAccountExists();
753
- if (!userOrdersAccountExists) {
754
- instructions.push(yield this.getInitializeUserOrdersInstruction());
755
- }
756
- instructions.push(yield this.getPlaceAndFillOrderIx(orderParams, discountToken, referrer));
757
- const tx = new web3_js_1.Transaction();
758
- for (const instruction of instructions) {
759
- tx.add(instruction);
760
- }
761
- return yield this.txSender.send(tx, [], this.opts);
762
- });
763
- }
764
- placeAndFillOrder(orderParams, discountToken, referrer) {
765
- return __awaiter(this, void 0, void 0, function* () {
766
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getPlaceAndFillOrderIx(orderParams, discountToken, referrer)), [], this.opts);
767
- });
768
- }
769
- getPlaceAndFillOrderIx(orderParams, discountToken, referrer) {
770
- return __awaiter(this, void 0, void 0, function* () {
771
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
772
- const userAccount = yield this.getUserAccount();
773
- const priceOracle = this.getMarketsAccount().markets[orderParams.marketIndex.toNumber()].amm
774
- .oracle;
775
- const remainingAccounts = [];
776
- if (orderParams.optionalAccounts.discountToken) {
777
- if (!discountToken) {
778
- throw Error('Optional accounts specified discount token but no discount token present');
620
+ if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
621
+ oracleAccountMap.set(bankAccount.oracle.toString(), {
622
+ pubkey: bankAccount.oracle,
623
+ isSigner: false,
624
+ isWritable: false,
625
+ });
779
626
  }
780
- remainingAccounts.push({
781
- pubkey: discountToken,
627
+ }
628
+ }
629
+ for (const position of userAccount.positions) {
630
+ if (!(0, position_1.positionIsAvailable)(position) &&
631
+ !position.marketIndex.eq(order.marketIndex)) {
632
+ const market = this.getMarketAccount(position.marketIndex);
633
+ marketAccountMap.set(position.marketIndex.toNumber(), {
634
+ pubkey: market.pubkey,
635
+ isWritable: true,
636
+ isSigner: false,
637
+ });
638
+ oracleAccountMap.set(market.amm.oracle.toString(), {
639
+ pubkey: market.amm.oracle,
782
640
  isWritable: false,
783
641
  isSigner: false,
784
642
  });
785
643
  }
786
- if (orderParams.optionalAccounts.referrer) {
787
- if (!referrer) {
788
- throw Error('Optional accounts specified referrer but no referrer present');
644
+ }
645
+ const remainingAccounts = [
646
+ ...oracleAccountMap.values(),
647
+ ...bankAccountMap.values(),
648
+ ...marketAccountMap.values(),
649
+ ];
650
+ if (makerInfo) {
651
+ remainingAccounts.push({
652
+ pubkey: makerInfo.maker,
653
+ isWritable: true,
654
+ isSigner: false,
655
+ });
656
+ }
657
+ const orderId = order.orderId;
658
+ const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
659
+ return await this.program.instruction.fillOrder(orderId, makerOrderId, {
660
+ accounts: {
661
+ state: await this.getStatePublicKey(),
662
+ filler: fillerPublicKey,
663
+ user: userAccountPublicKey,
664
+ authority: this.wallet.publicKey,
665
+ },
666
+ remainingAccounts,
667
+ });
668
+ }
669
+ async triggerOrder(userAccountPublicKey, user, order) {
670
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTriggerOrderIx(userAccountPublicKey, user, order)), [], this.opts);
671
+ return txSig;
672
+ }
673
+ async getTriggerOrderIx(userAccountPublicKey, userAccount, order) {
674
+ const fillerPublicKey = await this.getUserAccountPublicKey();
675
+ const marketIndex = order.marketIndex;
676
+ const marketAccount = this.getMarketAccount(marketIndex);
677
+ const oracleAccountMap = new Map();
678
+ const bankAccountMap = new Map();
679
+ const marketAccountMap = new Map();
680
+ marketAccountMap.set(marketIndex.toNumber(), {
681
+ pubkey: marketAccount.pubkey,
682
+ isWritable: true,
683
+ isSigner: false,
684
+ });
685
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
686
+ pubkey: marketAccount.amm.oracle,
687
+ isWritable: false,
688
+ isSigner: false,
689
+ });
690
+ for (const bankBalance of userAccount.bankBalances) {
691
+ if (!bankBalance.balance.eq(numericConstants_1.ZERO)) {
692
+ const bankAccount = this.getBankAccount(bankBalance.bankIndex);
693
+ bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
694
+ pubkey: bankAccount.pubkey,
695
+ isSigner: false,
696
+ isWritable: true,
697
+ });
698
+ if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
699
+ oracleAccountMap.set(bankAccount.oracle.toString(), {
700
+ pubkey: bankAccount.oracle,
701
+ isSigner: false,
702
+ isWritable: false,
703
+ });
789
704
  }
790
- remainingAccounts.push({
791
- pubkey: referrer,
705
+ }
706
+ }
707
+ for (const position of userAccount.positions) {
708
+ if (!(0, position_1.positionIsAvailable)(position) &&
709
+ !position.marketIndex.eq(order.marketIndex)) {
710
+ const market = this.getMarketAccount(position.marketIndex);
711
+ marketAccountMap.set(position.marketIndex.toNumber(), {
712
+ pubkey: market.pubkey,
792
713
  isWritable: true,
793
714
  isSigner: false,
794
715
  });
716
+ oracleAccountMap.set(market.amm.oracle.toString(), {
717
+ pubkey: market.amm.oracle,
718
+ isWritable: false,
719
+ isSigner: false,
720
+ });
795
721
  }
796
- const state = this.getStateAccount();
797
- const orderState = this.getOrderStateAccount();
798
- return yield this.program.instruction.placeAndFillOrder(orderParams, {
799
- accounts: {
800
- state: yield this.getStatePublicKey(),
801
- user: userAccountPublicKey,
802
- authority: this.wallet.publicKey,
803
- markets: state.markets,
804
- userOrders: yield this.getUserOrdersAccountPublicKey(),
805
- userPositions: userAccount.positions,
806
- tradeHistory: state.tradeHistory,
807
- fundingPaymentHistory: state.fundingPaymentHistory,
808
- fundingRateHistory: state.fundingRateHistory,
809
- orderState: yield this.getOrderStatePublicKey(),
810
- orderHistory: orderState.orderHistory,
811
- extendedCurveHistory: state.extendedCurveHistory,
812
- oracle: priceOracle,
813
- },
814
- remainingAccounts,
722
+ }
723
+ const remainingAccounts = [
724
+ ...oracleAccountMap.values(),
725
+ ...bankAccountMap.values(),
726
+ ...marketAccountMap.values(),
727
+ ];
728
+ const orderId = order.orderId;
729
+ return await this.program.instruction.triggerOrder(orderId, {
730
+ accounts: {
731
+ state: await this.getStatePublicKey(),
732
+ filler: fillerPublicKey,
733
+ user: userAccountPublicKey,
734
+ authority: this.wallet.publicKey,
735
+ },
736
+ remainingAccounts,
737
+ });
738
+ }
739
+ async placeAndTake(orderParams, makerInfo) {
740
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeIx(orderParams, makerInfo)), [], this.opts);
741
+ this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
742
+ return txSig;
743
+ }
744
+ async getPlaceAndTakeIx(orderParams, makerInfo) {
745
+ orderParams = this.getOrderParams(orderParams);
746
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
747
+ const remainingAccounts = this.getRemainingAccounts({
748
+ writableMarketIndex: orderParams.marketIndex,
749
+ writableBankIndex: numericConstants_1.QUOTE_ASSET_BANK_INDEX,
750
+ });
751
+ let makerOrderId = null;
752
+ if (makerInfo) {
753
+ makerOrderId = makerInfo.order.orderId;
754
+ remainingAccounts.push({
755
+ pubkey: makerInfo.maker,
756
+ isSigner: false,
757
+ isWritable: true,
815
758
  });
759
+ }
760
+ return await this.program.instruction.placeAndTake(orderParams, makerOrderId, {
761
+ accounts: {
762
+ state: await this.getStatePublicKey(),
763
+ user: userAccountPublicKey,
764
+ authority: this.wallet.publicKey,
765
+ },
766
+ remainingAccounts,
767
+ });
768
+ }
769
+ async placeAndMake(orderParams, takerInfo) {
770
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndMakeIx(orderParams, takerInfo)), [], this.opts);
771
+ this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
772
+ return txSig;
773
+ }
774
+ async getPlaceAndMakeIx(orderParams, takerInfo) {
775
+ orderParams = this.getOrderParams(orderParams);
776
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
777
+ const remainingAccounts = this.getRemainingAccounts({
778
+ writableMarketIndex: orderParams.marketIndex,
779
+ writableBankIndex: numericConstants_1.QUOTE_ASSET_BANK_INDEX,
780
+ });
781
+ const takerOrderId = takerInfo.order.orderId;
782
+ remainingAccounts.push({
783
+ pubkey: takerInfo.taker,
784
+ isSigner: false,
785
+ isWritable: true,
786
+ });
787
+ return await this.program.instruction.placeAndMake(orderParams, takerOrderId, {
788
+ accounts: {
789
+ state: await this.getStatePublicKey(),
790
+ user: userAccountPublicKey,
791
+ taker: takerInfo.taker,
792
+ authority: this.wallet.publicKey,
793
+ },
794
+ remainingAccounts,
816
795
  });
817
796
  }
818
797
  /**
819
798
  * Close an entire position. If you want to reduce a position, use the {@link openPosition} method in the opposite direction of the current position.
820
799
  * @param marketIndex
821
- * @param discountToken
822
- * @param referrer
823
800
  * @returns
824
801
  */
825
- closePosition(marketIndex, discountToken, referrer) {
826
- return __awaiter(this, void 0, void 0, function* () {
827
- return yield this.txSender.send((0, utils_1.wrapInTx)(yield this.getClosePositionIx(marketIndex, discountToken, referrer)), [], this.opts);
828
- });
829
- }
830
- getClosePositionIx(marketIndex, discountToken, referrer) {
831
- return __awaiter(this, void 0, void 0, function* () {
832
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
833
- const userAccount = yield this.getUserAccount();
834
- const priceOracle = this.getMarketsAccount().markets[marketIndex.toNumber()].amm.oracle;
835
- const optionalAccounts = {
836
- discountToken: false,
837
- referrer: false,
838
- };
839
- const remainingAccounts = [];
840
- if (discountToken) {
841
- optionalAccounts.discountToken = true;
842
- remainingAccounts.push({
843
- pubkey: discountToken,
802
+ async closePosition(marketIndex) {
803
+ const userPosition = this.getUser().getUserPosition(marketIndex);
804
+ if (!userPosition) {
805
+ throw Error(`No position in market ${marketIndex.toString()}`);
806
+ }
807
+ return await this.placeAndTake({
808
+ orderType: types_1.OrderType.MARKET,
809
+ marketIndex,
810
+ direction: (0, position_1.findDirectionToClose)(userPosition),
811
+ baseAssetAmount: userPosition.baseAssetAmount,
812
+ reduceOnly: true,
813
+ });
814
+ }
815
+ async settlePNLs(users, marketIndex) {
816
+ const ixs = [];
817
+ for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
818
+ ixs.push(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex));
819
+ }
820
+ const tx = new web3_js_1.Transaction().add(...ixs);
821
+ const { txSig } = await this.txSender.send(tx, [], this.opts);
822
+ return txSig;
823
+ }
824
+ async settlePNL(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
825
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex)), [], this.opts);
826
+ return txSig;
827
+ }
828
+ async settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
829
+ const marketAccountMap = new Map();
830
+ const oracleAccountMap = new Map();
831
+ const bankAccountMap = new Map();
832
+ for (const position of settleeUserAccount.positions) {
833
+ if (!(0, position_1.positionIsAvailable)(position)) {
834
+ const market = this.getMarketAccount(position.marketIndex);
835
+ marketAccountMap.set(position.marketIndex.toNumber(), {
836
+ pubkey: market.pubkey,
837
+ isWritable: true,
838
+ isSigner: false,
839
+ });
840
+ oracleAccountMap.set(market.amm.oracle.toString(), {
841
+ pubkey: market.amm.oracle,
844
842
  isWritable: false,
845
843
  isSigner: false,
846
844
  });
847
845
  }
848
- if (referrer) {
849
- optionalAccounts.referrer = true;
850
- remainingAccounts.push({
851
- pubkey: referrer,
852
- isWritable: true,
846
+ }
847
+ for (const userBankBalance of settleeUserAccount.bankBalances) {
848
+ if (!userBankBalance.balance.eq(numericConstants_1.QUOTE_ASSET_BANK_INDEX)) {
849
+ const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
850
+ bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
851
+ pubkey: bankAccount.pubkey,
853
852
  isSigner: false,
853
+ isWritable: false,
854
854
  });
855
- }
856
- const state = this.getStateAccount();
857
- return yield this.program.instruction.closePosition(marketIndex, optionalAccounts, {
858
- accounts: {
859
- state: yield this.getStatePublicKey(),
860
- user: userAccountPublicKey,
861
- authority: this.wallet.publicKey,
862
- markets: state.markets,
863
- userPositions: userAccount.positions,
864
- tradeHistory: state.tradeHistory,
865
- fundingPaymentHistory: state.fundingPaymentHistory,
866
- fundingRateHistory: state.fundingRateHistory,
867
- oracle: priceOracle,
868
- },
869
- remainingAccounts: remainingAccounts,
870
- });
871
- });
872
- }
873
- closeAllPositions(userPositionsAccount, discountToken, referrer) {
874
- return __awaiter(this, void 0, void 0, function* () {
875
- const ixs = [];
876
- for (const userPosition of userPositionsAccount.positions) {
877
- if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
878
- continue;
879
- }
880
- ixs.push(yield this.getClosePositionIx(userPosition.marketIndex, discountToken, referrer));
881
- }
882
- const tx = new web3_js_1.Transaction().add(...ixs);
883
- return this.txSender.send(tx, [], this.opts);
884
- });
885
- }
886
- liquidate(liquidateeUserAccountPublicKey) {
887
- return __awaiter(this, void 0, void 0, function* () {
888
- return this.txSender.send((0, utils_1.wrapInTx)(yield this.getLiquidateIx(liquidateeUserAccountPublicKey)), [], this.opts);
889
- });
890
- }
891
- getLiquidateIx(liquidateeUserAccountPublicKey) {
892
- return __awaiter(this, void 0, void 0, function* () {
893
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
894
- const liquidateeUserAccount = yield this.program.account.user.fetch(liquidateeUserAccountPublicKey);
895
- const liquidateePositions = yield this.program.account.userPositions.fetch(liquidateeUserAccount.positions);
896
- const markets = this.getMarketsAccount();
897
- const remainingAccounts = [];
898
- for (const position of liquidateePositions.positions) {
899
- if (!position.baseAssetAmount.eq(new anchor_1.BN(0))) {
900
- const market = markets.markets[position.marketIndex.toNumber()];
901
- remainingAccounts.push({
902
- pubkey: market.amm.oracle,
903
- isWritable: false,
855
+ if (!bankAccount.bankIndex.eq(numericConstants_1.ZERO)) {
856
+ oracleAccountMap.set(bankAccount.oracle.toString(), {
857
+ pubkey: bankAccount.oracle,
904
858
  isSigner: false,
859
+ isWritable: false,
905
860
  });
906
861
  }
907
862
  }
908
- const state = this.getStateAccount();
909
- return yield this.program.instruction.liquidate({
910
- accounts: {
911
- state: yield this.getStatePublicKey(),
912
- authority: this.wallet.publicKey,
913
- user: liquidateeUserAccountPublicKey,
914
- liquidator: userAccountPublicKey,
915
- collateralVault: state.collateralVault,
916
- collateralVaultAuthority: state.collateralVaultAuthority,
917
- insuranceVault: state.insuranceVault,
918
- insuranceVaultAuthority: state.insuranceVaultAuthority,
919
- tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
920
- markets: state.markets,
921
- userPositions: liquidateeUserAccount.positions,
922
- tradeHistory: state.tradeHistory,
923
- liquidationHistory: state.liquidationHistory,
924
- fundingPaymentHistory: state.fundingPaymentHistory,
925
- },
926
- remainingAccounts: remainingAccounts,
927
- });
928
- });
929
- }
930
- updateFundingRate(oracle, marketIndex) {
931
- return __awaiter(this, void 0, void 0, function* () {
932
- return this.txSender.send((0, utils_1.wrapInTx)(yield this.getUpdateFundingRateIx(oracle, marketIndex)), [], this.opts);
933
- });
934
- }
935
- getUpdateFundingRateIx(oracle, marketIndex) {
936
- return __awaiter(this, void 0, void 0, function* () {
937
- const state = this.getStateAccount();
938
- return yield this.program.instruction.updateFundingRate(marketIndex, {
939
- accounts: {
940
- state: yield this.getStatePublicKey(),
941
- markets: state.markets,
942
- oracle: oracle,
943
- fundingRateHistory: state.fundingRateHistory,
944
- },
945
- });
946
- });
947
- }
948
- settleFundingPayment(userAccount, userPositionsAccount) {
949
- return __awaiter(this, void 0, void 0, function* () {
950
- return this.txSender.send((0, utils_1.wrapInTx)(yield this.getSettleFundingPaymentIx(userAccount, userPositionsAccount)), [], this.opts);
951
- });
952
- }
953
- getSettleFundingPaymentIx(userAccount, userPositionsAccount) {
954
- return __awaiter(this, void 0, void 0, function* () {
955
- const state = this.getStateAccount();
956
- return yield this.program.instruction.settleFundingPayment({
957
- accounts: {
958
- state: yield this.getStatePublicKey(),
959
- markets: state.markets,
960
- user: userAccount,
961
- userPositions: userPositionsAccount,
962
- fundingPaymentHistory: state.fundingPaymentHistory,
963
- },
964
- });
863
+ }
864
+ const marketAccount = this.getMarketAccount(marketIndex.toNumber());
865
+ marketAccountMap.set(marketIndex.toNumber(), {
866
+ pubkey: marketAccount.pubkey,
867
+ isSigner: false,
868
+ isWritable: true,
869
+ });
870
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
871
+ pubkey: marketAccount.amm.oracle,
872
+ isSigner: false,
873
+ isWritable: false,
874
+ });
875
+ bankAccountMap.set(numericConstants_1.QUOTE_ASSET_BANK_INDEX.toNumber(), {
876
+ pubkey: this.getBankAccount(numericConstants_1.QUOTE_ASSET_BANK_INDEX).pubkey,
877
+ isSigner: false,
878
+ isWritable: true,
879
+ });
880
+ const remainingAccounts = [
881
+ ...oracleAccountMap.values(),
882
+ ...bankAccountMap.values(),
883
+ ...marketAccountMap.values(),
884
+ ];
885
+ return await this.program.instruction.settlePnl(marketIndex, {
886
+ accounts: {
887
+ state: await this.getStatePublicKey(),
888
+ authority: this.wallet.publicKey,
889
+ user: settleeUserAccountPublicKey,
890
+ },
891
+ remainingAccounts: remainingAccounts,
892
+ });
893
+ }
894
+ async liquidate(liquidateeUserAccountPublicKey) {
895
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateIx(liquidateeUserAccountPublicKey)), [], this.opts);
896
+ return txSig;
897
+ }
898
+ async getLiquidateIx(liquidateeUserAccountPublicKey) {
899
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
900
+ const liquidateeUserAccount = (await this.program.account.user.fetch(liquidateeUserAccountPublicKey));
901
+ const bankAccountInfos = [
902
+ {
903
+ pubkey: this.getQuoteAssetBankAccount().pubkey,
904
+ isSigner: false,
905
+ isWritable: true,
906
+ },
907
+ ];
908
+ const marketAccountInfos = [];
909
+ const oracleAccountInfos = [];
910
+ for (const position of liquidateeUserAccount.positions) {
911
+ if (!(0, position_1.positionIsAvailable)(position)) {
912
+ const market = this.getMarketAccount(position.marketIndex);
913
+ const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, position.marketIndex);
914
+ marketAccountInfos.push({
915
+ pubkey: marketPublicKey,
916
+ isWritable: true,
917
+ isSigner: false,
918
+ });
919
+ oracleAccountInfos.push({
920
+ pubkey: market.amm.oracle,
921
+ isWritable: false,
922
+ isSigner: false,
923
+ });
924
+ }
925
+ }
926
+ const remainingAccounts = oracleAccountInfos.concat(bankAccountInfos.concat(marketAccountInfos));
927
+ const state = this.getStateAccount();
928
+ const quoteAssetBankAccount = this.getQuoteAssetBankAccount();
929
+ return await this.program.instruction.liquidate({
930
+ accounts: {
931
+ state: await this.getStatePublicKey(),
932
+ authority: this.wallet.publicKey,
933
+ user: liquidateeUserAccountPublicKey,
934
+ liquidator: userAccountPublicKey,
935
+ bankVault: quoteAssetBankAccount.vault,
936
+ bankVaultAuthority: quoteAssetBankAccount.vaultAuthority,
937
+ insuranceVault: state.insuranceVault,
938
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
939
+ },
940
+ remainingAccounts: remainingAccounts,
941
+ });
942
+ }
943
+ async updateFundingRate(oracle, marketIndex) {
944
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateFundingRateIx(oracle, marketIndex)), [], this.opts);
945
+ return txSig;
946
+ }
947
+ async getUpdateFundingRateIx(oracle, marketIndex) {
948
+ return await this.program.instruction.updateFundingRate(marketIndex, {
949
+ accounts: {
950
+ state: await this.getStatePublicKey(),
951
+ market: await (0, pda_1.getMarketPublicKey)(this.program.programId, marketIndex),
952
+ oracle: oracle,
953
+ },
954
+ });
955
+ }
956
+ async settleFundingPayment(userAccount) {
957
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getSettleFundingPaymentIx(userAccount)), [], this.opts);
958
+ return txSig;
959
+ }
960
+ async getSettleFundingPaymentIx(userAccount) {
961
+ const user = (await this.program.account.user.fetch(userAccount));
962
+ const userPositions = user.positions;
963
+ const remainingAccounts = [];
964
+ for (const position of userPositions) {
965
+ if (!(0, position_1.positionIsAvailable)(position)) {
966
+ const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, position.marketIndex);
967
+ remainingAccounts.push({
968
+ pubkey: marketPublicKey,
969
+ isWritable: false,
970
+ isSigner: false,
971
+ });
972
+ }
973
+ }
974
+ return await this.program.instruction.settleFundingPayment({
975
+ accounts: {
976
+ state: await this.getStatePublicKey(),
977
+ user: userAccount,
978
+ },
979
+ remainingAccounts,
965
980
  });
966
981
  }
967
982
  triggerEvent(eventName, data) {
968
983
  this.eventEmitter.emit(eventName, data);
969
984
  }
970
- settlePositionAndClaimCollateral(collateralAccountPublicKey) {
971
- return __awaiter(this, void 0, void 0, function* () {
972
- const settlePositionIx = yield this.getSettlePositionIx();
973
- const claimCollateralIx = yield this.getClaimCollateralIx(collateralAccountPublicKey);
974
- const tx = new web3_js_1.Transaction().add(settlePositionIx).add(claimCollateralIx);
975
- return this.txSender.send(tx, [], this.opts);
976
- });
977
- }
978
- getSettlePositionIx() {
979
- return __awaiter(this, void 0, void 0, function* () {
980
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
981
- const user = yield this.program.account.user.fetch(userAccountPublicKey);
982
- const state = this.getStateAccount();
983
- const settlementState = yield (0, addresses_1.getSettlementStatePublicKey)(this.program.programId);
984
- return yield this.program.instruction.settlePosition({
985
- accounts: {
986
- state: yield this.getStatePublicKey(),
987
- user: userAccountPublicKey,
988
- markets: state.markets,
989
- authority: this.wallet.publicKey,
990
- userPositions: user.positions,
991
- settlementState,
992
- fundingPaymentHistory: state.fundingPaymentHistory,
993
- },
994
- });
995
- });
996
- }
997
- getClaimCollateralIx(collateralAccountPublicKey) {
998
- return __awaiter(this, void 0, void 0, function* () {
999
- const userAccountPublicKey = yield this.getUserAccountPublicKey();
1000
- const state = this.getStateAccount();
1001
- const settlementState = yield (0, addresses_1.getSettlementStatePublicKey)(this.program.programId);
1002
- return yield this.program.instruction.claimCollateral({
1003
- accounts: {
1004
- state: yield this.getStatePublicKey(),
1005
- user: userAccountPublicKey,
1006
- collateralVault: state.collateralVault,
1007
- collateralVaultAuthority: state.collateralVaultAuthority,
1008
- userCollateralAccount: collateralAccountPublicKey,
1009
- authority: this.wallet.publicKey,
1010
- tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1011
- settlementState,
1012
- },
1013
- });
1014
- });
1015
- }
1016
- getTotalSettlementSize() {
1017
- return __awaiter(this, void 0, void 0, function* () {
1018
- const accountLoader = new bulkAccountLoader_1.BulkAccountLoader(this.connection, 'processed', 50000);
1019
- const clearingHouse = (0, clearingHouse_1.getClearingHouse)((0, clearingHouse_1.getPollingClearingHouseConfig)(this.connection, this.wallet, this.program.programId, accountLoader));
1020
- console.log('loading all users');
1021
- const programUserAccounts = (yield this.program.account.user.all());
1022
- const userArray = [];
1023
- for (const programUserAccount of programUserAccounts) {
1024
- const user = (0, clearingHouseUser_1.getClearingHouseUser)((0, clearingHouseUser_1.getPollingClearingHouseUserConfig)(clearingHouse, programUserAccount.account.authority, accountLoader));
1025
- userArray.push(user);
1026
- }
1027
- console.log('subscribing all users');
1028
- yield (0, bulkUserSubscription_1.bulkPollingUserSubscribe)(userArray, accountLoader);
1029
- console.log('calculating settlement size');
1030
- const settlementSize = userArray.reduce((collateralToBeSettled, user) => {
1031
- return collateralToBeSettled.add(user.getUserAccount().forgoPositionSettlement === 0
1032
- ? user.getSettledPositionValue()
1033
- : numericConstants_1.ZERO);
1034
- }, numericConstants_1.ZERO);
1035
- for (const user of userArray) {
1036
- yield user.unsubscribe();
1037
- }
1038
- return settlementSize;
1039
- });
1040
- }
1041
- updateUserForgoSettlement() {
1042
- return __awaiter(this, void 0, void 0, function* () {
1043
- return yield this.program.rpc.updateUserForgoSettlement({
1044
- accounts: {
1045
- authority: this.wallet.publicKey,
1046
- user: yield this.getUserAccountPublicKey(),
1047
- },
1048
- });
1049
- });
985
+ getOracleDataForMarket(marketIndex) {
986
+ const oracleKey = this.getMarketAccount(marketIndex).amm.oracle;
987
+ const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
988
+ return oracleData;
1050
989
  }
1051
990
  }
1052
991
  exports.ClearingHouse = ClearingHouse;