@drift-labs/sdk 0.2.0-master.3 → 0.2.0-master.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/README.md +13 -13
  2. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  3. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  4. package/lib/accounts/bulkUserSubscription.js +0 -1
  5. package/lib/accounts/fetch.d.ts +2 -1
  6. package/lib/accounts/fetch.js +9 -1
  7. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +16 -16
  8. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +31 -28
  9. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  10. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  11. package/lib/accounts/types.d.ts +22 -11
  12. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +17 -17
  13. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +37 -35
  14. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  15. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  16. package/lib/addresses/marketAddresses.d.ts +1 -3
  17. package/lib/addresses/pda.d.ts +10 -4
  18. package/lib/addresses/pda.js +51 -14
  19. package/lib/admin.d.ts +42 -26
  20. package/lib/admin.js +228 -81
  21. package/lib/clearingHouse.d.ts +130 -49
  22. package/lib/clearingHouse.js +1256 -367
  23. package/lib/clearingHouseConfig.d.ts +4 -4
  24. package/lib/clearingHouseUser.d.ts +51 -39
  25. package/lib/clearingHouseUser.js +408 -191
  26. package/lib/clearingHouseUserStats.d.ts +18 -0
  27. package/lib/clearingHouseUserStats.js +49 -0
  28. package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
  29. package/lib/clearingHouseUserStatsConfig.js +2 -0
  30. package/lib/config.d.ts +7 -9
  31. package/lib/config.js +21 -21
  32. package/lib/constants/numericConstants.d.ts +25 -12
  33. package/lib/constants/numericConstants.js +35 -21
  34. package/lib/constants/perpMarkets.d.ts +18 -0
  35. package/lib/constants/{markets.js → perpMarkets.js} +7 -7
  36. package/lib/constants/spotMarkets.d.ts +19 -0
  37. package/lib/constants/spotMarkets.js +53 -0
  38. package/lib/dlob/DLOB.d.ts +74 -0
  39. package/lib/dlob/DLOB.js +595 -0
  40. package/lib/dlob/DLOBNode.d.ts +54 -0
  41. package/lib/dlob/DLOBNode.js +85 -0
  42. package/lib/dlob/NodeList.d.ts +26 -0
  43. package/lib/dlob/NodeList.js +139 -0
  44. package/lib/events/eventList.js +3 -0
  45. package/lib/events/eventSubscriber.d.ts +4 -2
  46. package/lib/events/eventSubscriber.js +16 -9
  47. package/lib/events/fetchLogs.d.ts +10 -1
  48. package/lib/events/fetchLogs.js +27 -7
  49. package/lib/events/pollingLogProvider.d.ts +2 -1
  50. package/lib/events/pollingLogProvider.js +6 -2
  51. package/lib/events/sort.js +8 -11
  52. package/lib/events/types.d.ts +8 -2
  53. package/lib/events/types.js +6 -0
  54. package/lib/examples/makeTradeExample.js +20 -8
  55. package/lib/factory/bigNum.d.ts +2 -0
  56. package/lib/factory/bigNum.js +48 -10
  57. package/lib/idl/clearing_house.json +4889 -1529
  58. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  59. package/lib/index.d.ts +21 -6
  60. package/lib/index.js +25 -6
  61. package/lib/math/amm.d.ts +9 -6
  62. package/lib/math/amm.js +91 -66
  63. package/lib/math/auction.js +4 -1
  64. package/lib/math/conversion.js +1 -1
  65. package/lib/math/funding.d.ts +6 -6
  66. package/lib/math/funding.js +11 -10
  67. package/lib/math/insurance.d.ts +4 -0
  68. package/lib/math/insurance.js +27 -0
  69. package/lib/math/margin.d.ts +11 -0
  70. package/lib/math/margin.js +77 -0
  71. package/lib/math/market.d.ts +14 -9
  72. package/lib/math/market.js +72 -10
  73. package/lib/math/oracles.d.ts +4 -0
  74. package/lib/math/oracles.js +36 -8
  75. package/lib/math/orders.d.ts +6 -2
  76. package/lib/math/orders.js +78 -3
  77. package/lib/math/position.d.ts +21 -13
  78. package/lib/math/position.js +76 -36
  79. package/lib/math/repeg.js +14 -5
  80. package/lib/math/spotBalance.d.ts +22 -0
  81. package/lib/math/spotBalance.js +192 -0
  82. package/lib/math/spotMarket.d.ts +4 -0
  83. package/lib/math/spotMarket.js +8 -0
  84. package/lib/math/spotPosition.d.ts +6 -0
  85. package/lib/math/spotPosition.js +23 -0
  86. package/lib/math/trade.d.ts +10 -10
  87. package/lib/math/trade.js +32 -39
  88. package/lib/oracles/pythClient.js +1 -1
  89. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  90. package/lib/oracles/switchboardClient.js +1 -1
  91. package/lib/orderParams.d.ts +14 -5
  92. package/lib/orderParams.js +12 -92
  93. package/lib/serum/serumSubscriber.d.ts +23 -0
  94. package/lib/serum/serumSubscriber.js +41 -0
  95. package/lib/serum/types.d.ts +11 -0
  96. package/lib/serum/types.js +2 -0
  97. package/lib/slot/SlotSubscriber.d.ts +7 -0
  98. package/lib/slot/SlotSubscriber.js +3 -0
  99. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  100. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  101. package/lib/tx/retryTxSender.d.ts +1 -1
  102. package/lib/tx/retryTxSender.js +13 -4
  103. package/lib/tx/types.d.ts +1 -1
  104. package/lib/tx/utils.js +1 -1
  105. package/lib/types.d.ts +566 -138
  106. package/lib/types.js +129 -5
  107. package/lib/userMap/userMap.d.ts +25 -0
  108. package/lib/userMap/userMap.js +73 -0
  109. package/lib/userMap/userStatsMap.d.ts +19 -0
  110. package/lib/userMap/userStatsMap.js +68 -0
  111. package/lib/util/computeUnits.js +1 -1
  112. package/lib/util/getTokenAddress.d.ts +2 -0
  113. package/lib/util/getTokenAddress.js +9 -0
  114. package/package.json +12 -6
  115. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  116. package/src/accounts/bulkUserSubscription.ts +0 -1
  117. package/src/accounts/fetch.ts +27 -2
  118. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +46 -42
  119. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  120. package/src/accounts/types.ts +31 -11
  121. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +64 -59
  122. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  123. package/src/addresses/marketAddresses.ts +1 -2
  124. package/src/addresses/pda.ts +88 -14
  125. package/src/admin.ts +452 -147
  126. package/src/assert/assert.js +9 -0
  127. package/src/clearingHouse.ts +2066 -467
  128. package/src/clearingHouseConfig.ts +4 -3
  129. package/src/clearingHouseUser.ts +747 -294
  130. package/src/clearingHouseUserStats.ts +75 -0
  131. package/src/clearingHouseUserStatsConfig.ts +18 -0
  132. package/src/config.ts +30 -31
  133. package/src/constants/numericConstants.ts +48 -25
  134. package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
  135. package/src/constants/spotMarkets.ts +73 -0
  136. package/src/dlob/DLOB.ts +953 -0
  137. package/src/dlob/DLOBNode.ts +167 -0
  138. package/src/dlob/NodeList.ts +189 -0
  139. package/src/events/eventList.js +77 -0
  140. package/src/events/eventList.ts +3 -0
  141. package/src/events/eventSubscriber.ts +20 -12
  142. package/src/events/fetchLogs.ts +35 -8
  143. package/src/events/pollingLogProvider.ts +10 -2
  144. package/src/events/sort.ts +11 -15
  145. package/src/events/types.ts +19 -1
  146. package/src/examples/makeTradeExample.js +157 -0
  147. package/src/examples/makeTradeExample.ts +32 -14
  148. package/src/factory/bigNum.ts +65 -13
  149. package/src/idl/clearing_house.json +4889 -1529
  150. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  151. package/src/index.ts +21 -6
  152. package/src/math/amm.ts +171 -88
  153. package/src/math/auction.ts +5 -1
  154. package/src/math/conversion.ts +2 -2
  155. package/src/math/funding.ts +20 -18
  156. package/src/math/insurance.ts +35 -0
  157. package/src/math/margin.ts +127 -0
  158. package/src/math/market.ts +145 -14
  159. package/src/math/oracles.ts +63 -9
  160. package/src/math/orders.ts +138 -4
  161. package/src/math/position.ts +119 -58
  162. package/src/math/repeg.ts +16 -6
  163. package/src/math/spotBalance.ts +319 -0
  164. package/src/math/spotMarket.ts +9 -0
  165. package/src/math/spotPosition.ts +47 -0
  166. package/src/math/trade.ts +53 -59
  167. package/src/oracles/pythClient.ts +2 -2
  168. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  169. package/src/oracles/switchboardClient.ts +2 -2
  170. package/src/orderParams.ts +24 -137
  171. package/src/serum/serumSubscriber.ts +80 -0
  172. package/src/serum/types.ts +13 -0
  173. package/src/slot/SlotSubscriber.ts +11 -1
  174. package/src/token/index.js +38 -0
  175. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  176. package/src/tx/retryTxSender.ts +16 -5
  177. package/src/tx/types.js +2 -0
  178. package/src/tx/types.ts +2 -1
  179. package/src/tx/utils.js +17 -0
  180. package/src/tx/utils.ts +1 -1
  181. package/src/types.ts +533 -140
  182. package/src/userMap/userMap.ts +100 -0
  183. package/src/userMap/userStatsMap.ts +110 -0
  184. package/src/util/computeUnits.js +21 -11
  185. package/src/util/computeUnits.ts +1 -1
  186. package/src/util/getTokenAddress.js +9 -0
  187. package/src/util/getTokenAddress.ts +18 -0
  188. package/src/util/promiseTimeout.js +14 -0
  189. package/src/util/tps.js +27 -0
  190. package/tests/bn/test.ts +24 -10
  191. package/tests/dlob/helpers.ts +397 -0
  192. package/tests/dlob/test.ts +3688 -0
  193. package/lib/constants/banks.d.ts +0 -16
  194. package/lib/constants/banks.js +0 -34
  195. package/lib/constants/markets.d.ts +0 -19
  196. package/lib/math/bankBalance.d.ts +0 -9
  197. package/lib/math/bankBalance.js +0 -75
  198. package/lib/math/state.d.ts +0 -8
  199. package/lib/math/state.js +0 -15
  200. package/lib/orders.d.ts +0 -8
  201. package/lib/orders.js +0 -134
  202. package/src/constants/banks.ts +0 -43
  203. package/src/math/bankBalance.ts +0 -112
  204. package/src/math/state.ts +0 -14
  205. package/src/math/utils.js +0 -27
  206. package/src/math/utils.js.map +0 -1
  207. package/src/orders.ts +0 -244
  208. package/src/util/computeUnits.js.map +0 -1
@@ -28,7 +28,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.ClearingHouse = void 0;
30
30
  const anchor_1 = require("@project-serum/anchor");
31
+ const bs58_1 = __importDefault(require("bs58"));
31
32
  const spl_token_1 = require("@solana/spl-token");
33
+ const types_1 = require("./types");
32
34
  const anchor = __importStar(require("@project-serum/anchor"));
33
35
  const clearing_house_json_1 = __importDefault(require("./idl/clearing_house.json"));
34
36
  const web3_js_1 = require("@solana/web3.js");
@@ -36,21 +38,23 @@ const pda_1 = require("./addresses/pda");
36
38
  const utils_1 = require("./tx/utils");
37
39
  const numericConstants_1 = require("./constants/numericConstants");
38
40
  const position_1 = require("./math/position");
39
- const bankBalance_1 = require("./math/bankBalance");
41
+ const spotBalance_1 = require("./math/spotBalance");
40
42
  const userName_1 = require("./userName");
41
43
  const pollingClearingHouseAccountSubscriber_1 = require("./accounts/pollingClearingHouseAccountSubscriber");
42
44
  const webSocketClearingHouseAccountSubscriber_1 = require("./accounts/webSocketClearingHouseAccountSubscriber");
43
45
  const retryTxSender_1 = require("./tx/retryTxSender");
44
46
  const clearingHouseUser_1 = require("./clearingHouseUser");
45
- const orderParams_1 = require("./orderParams");
46
47
  const config_1 = require("./config");
48
+ const spotMarkets_1 = require("./constants/spotMarkets");
49
+ const clearingHouseUserStats_1 = require("./clearingHouseUserStats");
50
+ const spotPosition_1 = require("./math/spotPosition");
47
51
  /**
48
52
  * # ClearingHouse
49
53
  * 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.
50
54
  */
51
55
  class ClearingHouse {
52
56
  constructor(config) {
53
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
57
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
54
58
  this.users = new Map();
55
59
  this._isSubscribed = false;
56
60
  this.marketLastSlotCache = new Map();
@@ -59,10 +63,11 @@ class ClearingHouse {
59
63
  this.opts = config.opts || anchor_1.AnchorProvider.defaultOptions();
60
64
  this.provider = new anchor_1.AnchorProvider(config.connection, config.wallet, this.opts);
61
65
  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];
66
+ this.authority = (_a = config.authority) !== null && _a !== void 0 ? _a : this.wallet.publicKey;
67
+ const userIds = (_b = config.userIds) !== null && _b !== void 0 ? _b : [0];
68
+ this.activeUserId = (_c = config.activeUserId) !== null && _c !== void 0 ? _c : userIds[0];
64
69
  this.userAccountSubscriptionConfig =
65
- ((_c = config.accountSubscription) === null || _c === void 0 ? void 0 : _c.type) === 'polling'
70
+ ((_d = config.accountSubscription) === null || _d === void 0 ? void 0 : _d.type) === 'polling'
66
71
  ? {
67
72
  type: 'polling',
68
73
  accountLoader: config.accountSubscription.accountLoader,
@@ -71,23 +76,34 @@ class ClearingHouse {
71
76
  type: 'websocket',
72
77
  };
73
78
  this.createUsers(userIds, this.userAccountSubscriptionConfig);
74
- let marketIndexes = config.marketIndexes;
75
- let bankIndexes = config.bankIndexes;
79
+ if (config.userStats) {
80
+ this.userStats = new clearingHouseUserStats_1.ClearingHouseUserStats({
81
+ clearingHouse: this,
82
+ userStatsAccountPublicKey: (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, this.authority),
83
+ accountSubscription: this.userAccountSubscriptionConfig,
84
+ });
85
+ }
86
+ let perpMarketIndexes = config.perpMarketIndexes;
87
+ let spotMarketIndexes = config.spotMarketIndexes;
76
88
  let oracleInfos = config.oracleInfos;
77
89
  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;
90
+ const { perpMarketIndexes: envPerpMarketIndexes, spotMarketIndexes: envSpotMarketIndexes, oracleInfos: envOralceInfos, } = (0, config_1.getMarketsAndOraclesForSubscription)(config.env);
91
+ perpMarketIndexes = perpMarketIndexes
92
+ ? perpMarketIndexes
93
+ : envPerpMarketIndexes;
94
+ spotMarketIndexes = spotMarketIndexes
95
+ ? spotMarketIndexes
96
+ : envSpotMarketIndexes;
81
97
  oracleInfos = oracleInfos ? oracleInfos : envOralceInfos;
82
98
  }
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 : []);
99
+ if (((_e = config.accountSubscription) === null || _e === void 0 ? void 0 : _e.type) === 'polling') {
100
+ this.accountSubscriber = new pollingClearingHouseAccountSubscriber_1.PollingClearingHouseAccountSubscriber(this.program, config.accountSubscription.accountLoader, perpMarketIndexes !== null && perpMarketIndexes !== void 0 ? perpMarketIndexes : [], spotMarketIndexes !== null && spotMarketIndexes !== void 0 ? spotMarketIndexes : [], oracleInfos !== null && oracleInfos !== void 0 ? oracleInfos : []);
85
101
  }
86
102
  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 : []);
103
+ this.accountSubscriber = new webSocketClearingHouseAccountSubscriber_1.WebSocketClearingHouseAccountSubscriber(this.program, (_f = config.perpMarketIndexes) !== null && _f !== void 0 ? _f : [], (_g = config.spotMarketIndexes) !== null && _g !== void 0 ? _g : [], (_h = config.oracleInfos) !== null && _h !== void 0 ? _h : []);
88
104
  }
89
105
  this.eventEmitter = this.accountSubscriber.eventEmitter;
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);
106
+ this.txSender = new retryTxSender_1.RetryTxSender(this.provider, (_j = config.txSenderConfig) === null || _j === void 0 ? void 0 : _j.timeout, (_k = config.txSenderConfig) === null || _k === void 0 ? void 0 : _k.retrySleep, (_l = config.txSenderConfig) === null || _l === void 0 ? void 0 : _l.additionalConnections);
91
107
  }
92
108
  get isSubscribed() {
93
109
  return this._isSubscribed && this.accountSubscriber.isSubscribed;
@@ -102,7 +118,7 @@ class ClearingHouse {
102
118
  }
103
119
  }
104
120
  createUser(userId, accountSubscriptionConfig) {
105
- const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, userId);
121
+ const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.authority, userId);
106
122
  return new clearingHouseUser_1.ClearingHouseUser({
107
123
  clearingHouse: this,
108
124
  userAccountPublicKey,
@@ -111,6 +127,9 @@ class ClearingHouse {
111
127
  }
112
128
  async subscribe() {
113
129
  const subscribePromises = this.subscribeUsers().concat(this.accountSubscriber.subscribe());
130
+ if (this.userStats !== undefined) {
131
+ subscribePromises.concat(this.userStats.subscribe());
132
+ }
114
133
  this.isSubscribed = (await Promise.all(subscribePromises)).reduce((success, prevSuccess) => success && prevSuccess);
115
134
  return this.isSubscribed;
116
135
  }
@@ -121,12 +140,19 @@ class ClearingHouse {
121
140
  * Forces the accountSubscriber to fetch account updates from rpc
122
141
  */
123
142
  async fetchAccounts() {
124
- await Promise.all([...this.users.values()]
143
+ const promises = [...this.users.values()]
125
144
  .map((user) => user.fetchAccounts())
126
- .concat(this.accountSubscriber.fetch()));
145
+ .concat(this.accountSubscriber.fetch());
146
+ if (this.userStats) {
147
+ promises.concat(this.userStats.fetchAccounts());
148
+ }
149
+ await Promise.all(promises);
127
150
  }
128
151
  async unsubscribe() {
129
152
  const unsubscribePromises = this.unsubscribeUsers().concat(this.accountSubscriber.unsubscribe());
153
+ if (this.userStats !== undefined) {
154
+ unsubscribePromises.concat(this.userStats.unsubscribe());
155
+ }
130
156
  await Promise.all(unsubscribePromises);
131
157
  this.isSubscribed = false;
132
158
  }
@@ -140,30 +166,43 @@ class ClearingHouse {
140
166
  this.statePublicKey = await (0, pda_1.getClearingHouseStateAccountPublicKey)(this.program.programId);
141
167
  return this.statePublicKey;
142
168
  }
169
+ getSignerPublicKey() {
170
+ if (this.signerPublicKey) {
171
+ return this.signerPublicKey;
172
+ }
173
+ this.signerPublicKey = (0, pda_1.getClearingHouseSignerPublicKey)(this.program.programId);
174
+ return this.signerPublicKey;
175
+ }
143
176
  getStateAccount() {
144
177
  return this.accountSubscriber.getStateAccountAndSlot().data;
145
178
  }
146
- getMarketAccount(marketIndex) {
179
+ getPerpMarketAccount(marketIndex) {
147
180
  var _a;
148
- marketIndex = marketIndex instanceof anchor_1.BN ? marketIndex : new anchor_1.BN(marketIndex);
149
181
  return (_a = this.accountSubscriber.getMarketAccountAndSlot(marketIndex)) === null || _a === void 0 ? void 0 : _a.data;
150
182
  }
151
- getMarketAccounts() {
183
+ getPerpMarketAccounts() {
152
184
  return this.accountSubscriber
153
185
  .getMarketAccountsAndSlots()
154
186
  .map((value) => value.data);
155
187
  }
156
- getBankAccount(bankIndex) {
157
- bankIndex = bankIndex instanceof anchor_1.BN ? bankIndex : new anchor_1.BN(bankIndex);
158
- return this.accountSubscriber.getBankAccountAndSlot(bankIndex).data;
188
+ getSpotMarketAccount(marketIndex) {
189
+ return this.accountSubscriber.getSpotMarketAccountAndSlot(marketIndex).data;
159
190
  }
160
- getQuoteAssetBankAccount() {
161
- return this.accountSubscriber.getBankAccountAndSlot(numericConstants_1.QUOTE_ASSET_BANK_INDEX)
162
- .data;
191
+ getSpotMarketAccounts() {
192
+ return this.accountSubscriber
193
+ .getSpotMarketAccountsAndSlots()
194
+ .map((value) => value.data);
195
+ }
196
+ getQuoteSpotMarketAccount() {
197
+ return this.accountSubscriber.getSpotMarketAccountAndSlot(numericConstants_1.QUOTE_SPOT_MARKET_INDEX).data;
163
198
  }
164
199
  getOraclePriceDataAndSlot(oraclePublicKey) {
165
200
  return this.accountSubscriber.getOraclePriceDataAndSlot(oraclePublicKey);
166
201
  }
202
+ async getSerumV3FulfillmentConfig(serumMarket) {
203
+ const address = await (0, pda_1.getSerumFulfillmentConfigPublicKey)(this.program.programId, serumMarket);
204
+ return (await this.program.account.serumV3FulfillmentConfig.fetch(address));
205
+ }
167
206
  /**
168
207
  * Update the wallet to use for clearing house transactions and linked user account
169
208
  * @param newWallet
@@ -178,6 +217,7 @@ class ClearingHouse {
178
217
  this.wallet = newWallet;
179
218
  this.provider = newProvider;
180
219
  this.program = newProgram;
220
+ this.authority = newWallet.publicKey;
181
221
  if (this.isSubscribed) {
182
222
  await Promise.all(this.unsubscribeUsers());
183
223
  }
@@ -187,6 +227,7 @@ class ClearingHouse {
187
227
  await Promise.all(this.subscribeUsers());
188
228
  }
189
229
  this.activeUserId = activeUserId;
230
+ this.userStatsAccountPublicKey = undefined;
190
231
  }
191
232
  async switchActiveUser(userId) {
192
233
  this.activeUserId = userId;
@@ -199,27 +240,120 @@ class ClearingHouse {
199
240
  await user.subscribe();
200
241
  this.users.set(userId, user);
201
242
  }
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);
243
+ async initializeUserAccount(userId = 0, name = userName_1.DEFAULT_USER_NAME, referrerInfo) {
244
+ const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
245
+ const tx = new web3_js_1.Transaction();
246
+ if (userId === 0) {
247
+ // not the safest assumption, can explicitly check if user stats account exists if it causes problems
248
+ tx.add(await this.getInitializeUserStatsIx());
249
+ }
250
+ tx.add(initializeUserAccountIx);
205
251
  const { txSig } = await this.txSender.send(tx, [], this.opts);
206
252
  return [txSig, userAccountPublicKey];
207
253
  }
208
- async getInitializeUserInstructions(userId = 0, name = userName_1.DEFAULT_USER_NAME) {
254
+ async getInitializeUserInstructions(userId = 0, name = userName_1.DEFAULT_USER_NAME, referrerInfo) {
209
255
  const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, userId);
256
+ const remainingAccounts = new Array();
257
+ if (referrerInfo !== undefined) {
258
+ remainingAccounts.push({
259
+ pubkey: referrerInfo.referrer,
260
+ isWritable: true,
261
+ isSigner: false,
262
+ });
263
+ remainingAccounts.push({
264
+ pubkey: referrerInfo.referrerStats,
265
+ isWritable: true,
266
+ isSigner: false,
267
+ });
268
+ }
269
+ const state = this.getStateAccount();
270
+ if (!state.whitelistMint.equals(web3_js_1.PublicKey.default)) {
271
+ const associatedTokenPublicKey = await spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, state.whitelistMint, this.wallet.publicKey);
272
+ remainingAccounts.push({
273
+ pubkey: associatedTokenPublicKey,
274
+ isWritable: false,
275
+ isSigner: false,
276
+ });
277
+ }
210
278
  const nameBuffer = (0, userName_1.encodeName)(name);
211
279
  const initializeUserAccountIx = await this.program.instruction.initializeUser(userId, nameBuffer, {
212
280
  accounts: {
213
281
  user: userAccountPublicKey,
282
+ userStats: this.getUserStatsAccountPublicKey(),
214
283
  authority: this.wallet.publicKey,
215
284
  payer: this.wallet.publicKey,
216
285
  rent: anchor.web3.SYSVAR_RENT_PUBKEY,
217
286
  systemProgram: anchor.web3.SystemProgram.programId,
218
287
  state: await this.getStatePublicKey(),
219
288
  },
289
+ remainingAccounts,
220
290
  });
221
291
  return [userAccountPublicKey, initializeUserAccountIx];
222
292
  }
293
+ async getInitializeUserStatsIx() {
294
+ return await this.program.instruction.initializeUserStats({
295
+ accounts: {
296
+ userStats: this.getUserStatsAccountPublicKey(),
297
+ authority: this.wallet.publicKey,
298
+ payer: this.wallet.publicKey,
299
+ rent: anchor.web3.SYSVAR_RENT_PUBKEY,
300
+ systemProgram: anchor.web3.SystemProgram.programId,
301
+ state: await this.getStatePublicKey(),
302
+ },
303
+ });
304
+ }
305
+ async updateUserName(name, userId = 0) {
306
+ const nameBuffer = (0, userName_1.encodeName)(name);
307
+ return await this.program.rpc.updateUserName(userId, nameBuffer, {
308
+ accounts: {
309
+ user: await this.getUserAccountPublicKey(),
310
+ authority: this.wallet.publicKey,
311
+ },
312
+ });
313
+ }
314
+ async updateUserCustomMarginRatio(marginRatio, userId = 0) {
315
+ return await this.program.rpc.updateUserCustomMarginRatio(userId, marginRatio, {
316
+ accounts: {
317
+ user: await this.getUserAccountPublicKey(),
318
+ authority: this.wallet.publicKey,
319
+ },
320
+ });
321
+ }
322
+ async updateUserDelegate(delegate, userId = 0) {
323
+ return await this.program.rpc.updateUserDelegate(userId, delegate, {
324
+ accounts: {
325
+ user: await this.getUserAccountPublicKey(),
326
+ authority: this.wallet.publicKey,
327
+ },
328
+ });
329
+ }
330
+ async getUserAccountsForDelegate(delegate) {
331
+ const programAccounts = await this.program.account.user.all([
332
+ {
333
+ memcmp: {
334
+ offset: 40,
335
+ /** data to match, as base-58 encoded string and limited to less than 129 bytes */
336
+ bytes: bs58_1.default.encode(delegate.toBuffer()),
337
+ },
338
+ },
339
+ ]);
340
+ return programAccounts.map((programAccount) => programAccount.account);
341
+ }
342
+ async deleteUser(userId = 0) {
343
+ var _a;
344
+ const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, userId);
345
+ const txSig = await this.program.rpc.deleteUser({
346
+ accounts: {
347
+ user: userAccountPublicKey,
348
+ userStats: this.getUserStatsAccountPublicKey(),
349
+ authority: this.wallet.publicKey,
350
+ state: await this.getStatePublicKey(),
351
+ },
352
+ });
353
+ await ((_a = this.users.get(userId)) === null || _a === void 0 ? void 0 : _a.unsubscribe());
354
+ this.users.delete(userId);
355
+ return txSig;
356
+ }
223
357
  getUser(userId) {
224
358
  userId = userId !== null && userId !== void 0 ? userId : this.activeUserId;
225
359
  if (!this.users.has(userId)) {
@@ -230,6 +364,16 @@ class ClearingHouse {
230
364
  getUsers() {
231
365
  return [...this.users.values()];
232
366
  }
367
+ getUserStats() {
368
+ return this.userStats;
369
+ }
370
+ getUserStatsAccountPublicKey() {
371
+ if (this.userStatsAccountPublicKey) {
372
+ return this.userStatsAccountPublicKey;
373
+ }
374
+ this.userStatsAccountPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, this.authority);
375
+ return this.userStatsAccountPublicKey;
376
+ }
233
377
  async getUserAccountPublicKey() {
234
378
  return this.getUser().userAccountPublicKey;
235
379
  }
@@ -239,153 +383,208 @@ class ClearingHouse {
239
383
  getUserAccountAndSlot(userId) {
240
384
  return this.getUser(userId).getUserAccountAndSlot();
241
385
  }
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));
386
+ getSpotPosition(marketIndex) {
387
+ return this.getUserAccount().spotPositions.find((spotPosition) => spotPosition.marketIndex === marketIndex);
245
388
  }
246
389
  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);
390
+ const spotMarket = this.getSpotMarketAccount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
391
+ const spotPosition = this.getSpotPosition(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
392
+ return (0, spotBalance_1.getTokenAmount)(spotPosition.balance, spotMarket, spotPosition.balanceType);
250
393
  }
251
394
  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,
267
- isSigner: false,
268
- isWritable: false,
269
- });
270
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
271
- pubkey: marketAccount.amm.oracle,
272
- isSigner: false,
273
- isWritable: false,
274
- });
275
- }
276
- else {
277
- this.marketLastSlotCache.delete(marketIndexNum);
395
+ var _a;
396
+ const { oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap } = this.getRemainingAccountMapsForUsers(params.userAccounts);
397
+ if (params.useMarketLastSlotCache) {
398
+ const lastUserPositionsSlot = (_a = this.getUserAccountAndSlot()) === null || _a === void 0 ? void 0 : _a.slot;
399
+ for (const [marketIndex, slot] of this.marketLastSlotCache.entries()) {
400
+ // if cache has more recent slot than user positions account slot, add market to remaining accounts
401
+ // otherwise remove from slot
402
+ if (slot > lastUserPositionsSlot) {
403
+ const marketAccount = this.getPerpMarketAccount(marketIndex);
404
+ perpMarketAccountMap.set(marketIndex, {
405
+ pubkey: marketAccount.pubkey,
406
+ isSigner: false,
407
+ isWritable: false,
408
+ });
409
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
410
+ pubkey: marketAccount.amm.oracle,
411
+ isSigner: false,
412
+ isWritable: false,
413
+ });
414
+ }
415
+ else {
416
+ this.marketLastSlotCache.delete(marketIndex);
417
+ }
278
418
  }
279
419
  }
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, {
420
+ if (params.readablePerpMarketIndex !== undefined) {
421
+ const marketAccount = this.getPerpMarketAccount(params.readablePerpMarketIndex);
422
+ perpMarketAccountMap.set(params.readablePerpMarketIndex, {
423
+ pubkey: marketAccount.pubkey,
424
+ isSigner: false,
425
+ isWritable: false,
426
+ });
427
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
428
+ pubkey: marketAccount.amm.oracle,
429
+ isSigner: false,
430
+ isWritable: false,
431
+ });
432
+ }
433
+ if (params.writablePerpMarketIndexes !== undefined) {
434
+ for (const writablePerpMarketIndex of params.writablePerpMarketIndexes) {
435
+ const marketAccount = this.getPerpMarketAccount(writablePerpMarketIndex);
436
+ perpMarketAccountMap.set(writablePerpMarketIndex, {
285
437
  pubkey: marketAccount.pubkey,
286
438
  isSigner: false,
287
- // isWritable: false, // TODO
288
439
  isWritable: true,
289
440
  });
290
- oracleAccountMap.set(marketAccount.pubkey.toString(), {
441
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
291
442
  pubkey: marketAccount.amm.oracle,
292
443
  isSigner: false,
293
444
  isWritable: false,
294
445
  });
295
446
  }
296
447
  }
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,
303
- });
304
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
305
- pubkey: marketAccount.amm.oracle,
448
+ if (params.readableSpotMarketIndex !== undefined) {
449
+ const spotMarketAccount = this.getSpotMarketAccount(params.readableSpotMarketIndex);
450
+ spotMarketAccountMap.set(params.readableSpotMarketIndex, {
451
+ pubkey: spotMarketAccount.pubkey,
306
452
  isSigner: false,
307
453
  isWritable: false,
308
454
  });
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,
455
+ if (spotMarketAccount.marketIndex !== 0) {
456
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
457
+ pubkey: spotMarketAccount.oracle,
315
458
  isSigner: false,
316
459
  isWritable: false,
317
460
  });
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
- }
325
461
  }
326
462
  }
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,
333
- });
334
- if (!bankAccount.bankIndex.eq(numericConstants_1.ZERO)) {
335
- oracleAccountMap.set(bankAccount.oracle.toString(), {
336
- pubkey: bankAccount.oracle,
463
+ if (params.writableSpotMarketIndexes !== undefined) {
464
+ for (const writableSpotMarketIndex of params.writableSpotMarketIndexes) {
465
+ const spotMarketAccount = this.getSpotMarketAccount(writableSpotMarketIndex);
466
+ spotMarketAccountMap.set(spotMarketAccount.marketIndex, {
467
+ pubkey: spotMarketAccount.pubkey,
337
468
  isSigner: false,
338
- isWritable: false,
469
+ isWritable: true,
339
470
  });
471
+ if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
472
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
473
+ pubkey: spotMarketAccount.oracle,
474
+ isSigner: false,
475
+ isWritable: false,
476
+ });
477
+ }
340
478
  }
341
479
  }
342
480
  return [
343
481
  ...oracleAccountMap.values(),
344
- ...bankAccountMap.values(),
345
- ...marketAccountMap.values(),
482
+ ...spotMarketAccountMap.values(),
483
+ ...perpMarketAccountMap.values(),
346
484
  ];
347
485
  }
486
+ getRemainingAccountMapsForUsers(userAccounts) {
487
+ const oracleAccountMap = new Map();
488
+ const spotMarketAccountMap = new Map();
489
+ const perpMarketAccountMap = new Map();
490
+ for (const userAccount of userAccounts) {
491
+ for (const spotPosition of userAccount.spotPositions) {
492
+ if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
493
+ const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
494
+ spotMarketAccountMap.set(spotPosition.marketIndex, {
495
+ pubkey: spotMarket.pubkey,
496
+ isSigner: false,
497
+ isWritable: false,
498
+ });
499
+ if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
500
+ oracleAccountMap.set(spotMarket.oracle.toString(), {
501
+ pubkey: spotMarket.oracle,
502
+ isSigner: false,
503
+ isWritable: false,
504
+ });
505
+ }
506
+ }
507
+ }
508
+ for (const position of userAccount.perpPositions) {
509
+ if (!(0, position_1.positionIsAvailable)(position)) {
510
+ const market = this.getPerpMarketAccount(position.marketIndex);
511
+ perpMarketAccountMap.set(position.marketIndex, {
512
+ pubkey: market.pubkey,
513
+ isWritable: false,
514
+ isSigner: false,
515
+ });
516
+ oracleAccountMap.set(market.amm.oracle.toString(), {
517
+ pubkey: market.amm.oracle,
518
+ isWritable: false,
519
+ isSigner: false,
520
+ });
521
+ }
522
+ }
523
+ }
524
+ return {
525
+ oracleAccountMap,
526
+ spotMarketAccountMap,
527
+ perpMarketAccountMap,
528
+ };
529
+ }
348
530
  getOrder(orderId) {
349
531
  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));
532
+ return (_a = this.getUserAccount()) === null || _a === void 0 ? void 0 : _a.orders.find((order) => order.orderId === orderId);
352
533
  }
353
534
  getOrderByUserId(userOrderId) {
354
535
  var _a;
355
536
  return (_a = this.getUserAccount()) === null || _a === void 0 ? void 0 : _a.orders.find((order) => order.userOrderId === userOrderId);
356
537
  }
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);
538
+ async deposit(amount, marketIndex, collateralAccountPublicKey, userId, reduceOnly = false) {
539
+ const tx = new web3_js_1.Transaction();
540
+ const additionalSigners = [];
541
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
542
+ const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
543
+ const authority = this.authority;
544
+ const createWSOLTokenAccount = isSolMarket && collateralAccountPublicKey.equals(authority);
545
+ if (createWSOLTokenAccount) {
546
+ const { ixs, signers, pubkey } = await this.getWrappedSolAccountCreationIxs(amount, true);
547
+ collateralAccountPublicKey = pubkey;
548
+ ixs.forEach((ix) => {
549
+ tx.add(ix);
550
+ });
551
+ signers.forEach((signer) => additionalSigners.push(signer));
552
+ }
553
+ const depositCollateralIx = await this.getDepositInstruction(amount, marketIndex, collateralAccountPublicKey, userId, reduceOnly, true);
554
+ tx.add(depositCollateralIx);
555
+ // Close the wrapped sol account at the end of the transaction
556
+ if (createWSOLTokenAccount) {
557
+ tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, collateralAccountPublicKey, authority, authority, []));
558
+ }
559
+ const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
361
560
  return txSig;
362
561
  }
363
- async getDepositInstruction(amount, bankIndex, userTokenAccount, userId, reduceOnly = false, userInitialized = true) {
562
+ async getDepositInstruction(amount, marketIndex, userTokenAccount, userId, reduceOnly = false, userInitialized = true) {
364
563
  const userAccountPublicKey = userId
365
- ? await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, userId)
564
+ ? await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, userId)
366
565
  : await this.getUserAccountPublicKey();
367
566
  let remainingAccounts = [];
368
567
  if (userInitialized) {
369
568
  remainingAccounts = this.getRemainingAccounts({
370
- writableBankIndex: bankIndex,
569
+ userAccounts: [this.getUserAccount()],
570
+ useMarketLastSlotCache: true,
571
+ writableSpotMarketIndexes: [marketIndex],
371
572
  });
372
573
  }
373
574
  else {
374
- remainingAccounts = [
375
- {
376
- pubkey: this.getBankAccount(bankIndex).pubkey,
377
- isSigner: false,
378
- isWritable: true,
379
- },
380
- ];
575
+ remainingAccounts = this.getRemainingAccounts({
576
+ userAccounts: [],
577
+ writableSpotMarketIndexes: [marketIndex],
578
+ });
381
579
  }
382
- const bank = this.getBankAccount(bankIndex);
383
- return await this.program.instruction.deposit(bankIndex, amount, reduceOnly, {
580
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
581
+ return await this.program.instruction.deposit(marketIndex, amount, reduceOnly, {
384
582
  accounts: {
385
583
  state: await this.getStatePublicKey(),
386
- bank: bank.pubkey,
387
- bankVault: bank.vault,
584
+ spotMarket: spotMarketAccount.pubkey,
585
+ spotMarketVault: spotMarketAccount.vault,
388
586
  user: userAccountPublicKey,
587
+ userStats: this.getUserStatsAccountPublicKey(),
389
588
  userTokenAccount: userTokenAccount,
390
589
  authority: this.wallet.publicKey,
391
590
  tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
@@ -393,55 +592,142 @@ class ClearingHouse {
393
592
  remainingAccounts,
394
593
  });
395
594
  }
595
+ async checkIfAccountExists(account) {
596
+ try {
597
+ const accountInfo = await this.connection.getAccountInfo(account);
598
+ return accountInfo != null;
599
+ }
600
+ catch (e) {
601
+ // Doesn't already exist
602
+ return false;
603
+ }
604
+ }
605
+ async getWrappedSolAccountCreationIxs(amount, isDeposit) {
606
+ const wrappedSolAccount = new web3_js_1.Keypair();
607
+ const result = {
608
+ ixs: [],
609
+ signers: [],
610
+ pubkey: wrappedSolAccount.publicKey,
611
+ };
612
+ const rentSpaceLamports = new anchor_1.BN(web3_js_1.LAMPORTS_PER_SOL / 100);
613
+ const lamports = isDeposit
614
+ ? amount.add(rentSpaceLamports)
615
+ : rentSpaceLamports;
616
+ const authority = this.wallet.publicKey;
617
+ result.ixs.push(web3_js_1.SystemProgram.createAccount({
618
+ fromPubkey: authority,
619
+ newAccountPubkey: wrappedSolAccount.publicKey,
620
+ lamports: lamports.toNumber(),
621
+ space: 165,
622
+ programId: spl_token_1.TOKEN_PROGRAM_ID,
623
+ }));
624
+ result.ixs.push(spl_token_1.Token.createInitAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, spotMarkets_1.WRAPPED_SOL_MINT, wrappedSolAccount.publicKey, authority));
625
+ result.signers.push(wrappedSolAccount);
626
+ return result;
627
+ }
628
+ getAssociatedTokenAccountCreationIx(tokenMintAddress, associatedTokenAddress) {
629
+ const createAssociatedAccountIx = spl_token_1.Token.createAssociatedTokenAccountInstruction(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, tokenMintAddress, associatedTokenAddress, this.wallet.publicKey, this.wallet.publicKey);
630
+ return createAssociatedAccountIx;
631
+ }
396
632
  /**
397
633
  * Creates the Clearing House User account for a user, and deposits some initial collateral
398
- * @param userId
399
- * @param name
400
634
  * @param amount
401
635
  * @param userTokenAccount
636
+ * @param marketIndex
637
+ * @param userId
638
+ * @param name
402
639
  * @param fromUserId
403
640
  * @returns
404
641
  */
405
- async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, bankIndex = new anchor_1.BN(0), userId = 0, name = userName_1.DEFAULT_USER_NAME, fromUserId) {
406
- const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
642
+ async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, userId = 0, name = userName_1.DEFAULT_USER_NAME, fromUserId, referrerInfo) {
643
+ const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
644
+ const additionalSigners = [];
645
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
646
+ const isSolMarket = spotMarket.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
647
+ const tx = new web3_js_1.Transaction();
648
+ const authority = this.wallet.publicKey;
649
+ const createWSOLTokenAccount = isSolMarket && userTokenAccount.equals(authority);
650
+ if (createWSOLTokenAccount) {
651
+ const { ixs: startIxs, signers, pubkey, } = await this.getWrappedSolAccountCreationIxs(amount, true);
652
+ userTokenAccount = pubkey;
653
+ startIxs.forEach((ix) => {
654
+ tx.add(ix);
655
+ });
656
+ signers.forEach((signer) => additionalSigners.push(signer));
657
+ }
407
658
  const depositCollateralIx = fromUserId != null
408
- ? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
409
- : await this.getDepositInstruction(amount, bankIndex, userTokenAccount, userId, false, false);
410
- const tx = new web3_js_1.Transaction()
411
- .add(initializeUserAccountIx)
412
- .add(depositCollateralIx);
413
- const { txSig } = await this.txSender.send(tx, []);
659
+ ? await this.getTransferDepositIx(amount, marketIndex, fromUserId, userId)
660
+ : await this.getDepositInstruction(amount, marketIndex, userTokenAccount, userId, false, false);
661
+ if (userId === 0) {
662
+ tx.add(await this.getInitializeUserStatsIx());
663
+ }
664
+ tx.add(initializeUserAccountIx).add(depositCollateralIx);
665
+ // Close the wrapped sol account at the end of the transaction
666
+ if (createWSOLTokenAccount) {
667
+ tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, userTokenAccount, authority, authority, []));
668
+ }
669
+ const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
414
670
  return [txSig, userAccountPublicKey];
415
671
  }
416
- async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME, mockUSDCFaucet, amount) {
417
- const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await mockUSDCFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
418
- const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
419
- const depositCollateralIx = await this.getDepositInstruction(amount, new anchor_1.BN(0), associateTokenPublicKey, userId, false, false);
420
- const tx = new web3_js_1.Transaction()
421
- .add(createAssociatedAccountIx)
422
- .add(mintToIx)
423
- .add(initializeUserAccountIx)
424
- .add(depositCollateralIx);
672
+ async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME, marketIndex, tokenFaucet, amount, referrerInfo) {
673
+ const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
674
+ const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
675
+ const depositCollateralIx = await this.getDepositInstruction(amount, marketIndex, associateTokenPublicKey, userId, false, false);
676
+ const tx = new web3_js_1.Transaction().add(createAssociatedAccountIx).add(mintToIx);
677
+ if (userId === 0) {
678
+ tx.add(await this.getInitializeUserStatsIx());
679
+ }
680
+ tx.add(initializeUserAccountIx).add(depositCollateralIx);
425
681
  const txSig = await this.program.provider.sendAndConfirm(tx, []);
426
682
  return [txSig, userAccountPublicKey];
427
683
  }
428
- async withdraw(amount, bankIndex, userTokenAccount, reduceOnly = false) {
429
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getWithdrawIx(amount, bankIndex, userTokenAccount, reduceOnly)), [], this.opts);
684
+ async withdraw(amount, marketIndex, userTokenAccount, reduceOnly = false) {
685
+ const tx = new web3_js_1.Transaction();
686
+ const additionalSigners = [];
687
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
688
+ const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
689
+ const authority = this.wallet.publicKey;
690
+ const createWSOLTokenAccount = isSolMarket && userTokenAccount.equals(authority);
691
+ if (createWSOLTokenAccount) {
692
+ const { ixs, signers, pubkey } = await this.getWrappedSolAccountCreationIxs(amount, false);
693
+ userTokenAccount = pubkey;
694
+ ixs.forEach((ix) => {
695
+ tx.add(ix);
696
+ });
697
+ signers.forEach((signer) => additionalSigners.push(signer));
698
+ }
699
+ else {
700
+ const accountExists = await this.checkIfAccountExists(userTokenAccount);
701
+ if (!accountExists) {
702
+ const createAssociatedTokenAccountIx = this.getAssociatedTokenAccountCreationIx(spotMarketAccount.mint, userTokenAccount);
703
+ tx.add(createAssociatedTokenAccountIx);
704
+ }
705
+ }
706
+ const withdrawCollateral = await this.getWithdrawIx(amount, spotMarketAccount.marketIndex, userTokenAccount, reduceOnly);
707
+ tx.add(withdrawCollateral);
708
+ // Close the wrapped sol account at the end of the transaction
709
+ if (createWSOLTokenAccount) {
710
+ tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, userTokenAccount, authority, authority, []));
711
+ }
712
+ const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
430
713
  return txSig;
431
714
  }
432
- async getWithdrawIx(amount, bankIndex, userTokenAccount, reduceOnly = false) {
715
+ async getWithdrawIx(amount, marketIndex, userTokenAccount, reduceOnly = false) {
433
716
  const userAccountPublicKey = await this.getUserAccountPublicKey();
434
717
  const remainingAccounts = this.getRemainingAccounts({
435
- writableBankIndex: bankIndex,
718
+ userAccounts: [this.getUserAccount()],
719
+ useMarketLastSlotCache: true,
720
+ writableSpotMarketIndexes: [marketIndex],
436
721
  });
437
- const bank = this.getBankAccount(bankIndex);
438
- return await this.program.instruction.withdraw(bankIndex, amount, reduceOnly, {
722
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
723
+ return await this.program.instruction.withdraw(marketIndex, amount, reduceOnly, {
439
724
  accounts: {
440
725
  state: await this.getStatePublicKey(),
441
- bank: bank.pubkey,
442
- bankVault: bank.vault,
443
- bankVaultAuthority: bank.vaultAuthority,
726
+ spotMarket: spotMarketAccount.pubkey,
727
+ spotMarketVault: spotMarketAccount.vault,
728
+ clearingHouseSigner: this.getSignerPublicKey(),
444
729
  user: userAccountPublicKey,
730
+ userStats: this.getUserStatsAccountPublicKey(),
445
731
  userTokenAccount: userTokenAccount,
446
732
  authority: this.wallet.publicKey,
447
733
  tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
@@ -449,55 +735,181 @@ class ClearingHouse {
449
735
  remainingAccounts,
450
736
  });
451
737
  }
452
- async transferDeposit(amount, bankIndex, fromUserId, toUserId) {
453
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTransferDepositIx(amount, bankIndex, fromUserId, toUserId)), [], this.opts);
738
+ async transferDeposit(amount, marketIndex, fromUserId, toUserId) {
739
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTransferDepositIx(amount, marketIndex, fromUserId, toUserId)), [], this.opts);
454
740
  return txSig;
455
741
  }
456
- async getTransferDepositIx(amount, bankIndex, fromUserId, toUserId) {
742
+ async getTransferDepositIx(amount, marketIndex, fromUserId, toUserId) {
457
743
  const fromUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, fromUserId);
458
744
  const toUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, toUserId);
459
- const remainingAccounts = this.getRemainingAccounts({
460
- writableBankIndex: bankIndex,
461
- });
462
- return await this.program.instruction.transferDeposit(bankIndex, amount, {
745
+ let remainingAccounts;
746
+ if (this.users.has(fromUserId)) {
747
+ remainingAccounts = this.getRemainingAccounts({
748
+ userAccounts: [this.users.get(fromUserId).getUserAccount()],
749
+ useMarketLastSlotCache: true,
750
+ writableSpotMarketIndexes: [marketIndex],
751
+ });
752
+ }
753
+ else {
754
+ const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.authority, fromUserId);
755
+ const fromUserAccount = (await this.program.account.user.fetch(userAccountPublicKey));
756
+ remainingAccounts = this.getRemainingAccounts({
757
+ userAccounts: [fromUserAccount],
758
+ useMarketLastSlotCache: true,
759
+ writableSpotMarketIndexes: [marketIndex],
760
+ });
761
+ }
762
+ return await this.program.instruction.transferDeposit(marketIndex, amount, {
463
763
  accounts: {
464
764
  authority: this.wallet.publicKey,
465
765
  fromUser,
466
766
  toUser,
767
+ userStats: this.getUserStatsAccountPublicKey(),
467
768
  state: await this.getStatePublicKey(),
468
769
  },
469
770
  remainingAccounts,
470
771
  });
471
772
  }
472
- async updateBankCumulativeInterest(bankIndex) {
473
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.updateBankCumulativeInterestIx(bankIndex)), [], this.opts);
773
+ async updateSpotMarketCumulativeInterest(marketIndex) {
774
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.updateSpotMarketCumulativeInterestIx(marketIndex)), [], this.opts);
775
+ return txSig;
776
+ }
777
+ async updateSpotMarketCumulativeInterestIx(marketIndex) {
778
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
779
+ return await this.program.instruction.updateSpotMarketCumulativeInterest({
780
+ accounts: {
781
+ state: await this.getStatePublicKey(),
782
+ spotMarket: spotMarket.pubkey,
783
+ },
784
+ });
785
+ }
786
+ async settleLP(settleeUserAccountPublicKey, marketIndex) {
787
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.settleLPIx(settleeUserAccountPublicKey, marketIndex)), [], this.opts);
788
+ return txSig;
789
+ }
790
+ async settleLPIx(settleeUserAccountPublicKey, marketIndex) {
791
+ const settleeUserAccount = (await this.program.account.user.fetch(settleeUserAccountPublicKey));
792
+ const remainingAccounts = this.getRemainingAccounts({
793
+ userAccounts: [settleeUserAccount],
794
+ writablePerpMarketIndexes: [marketIndex],
795
+ });
796
+ return this.program.instruction.settleLp(marketIndex, {
797
+ accounts: {
798
+ state: await this.getStatePublicKey(),
799
+ user: settleeUserAccountPublicKey,
800
+ },
801
+ remainingAccounts: remainingAccounts,
802
+ });
803
+ }
804
+ async removeLiquidity(marketIndex, sharesToBurn) {
805
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getRemoveLiquidityIx(marketIndex, sharesToBurn)), [], this.opts);
806
+ return txSig;
807
+ }
808
+ async getRemoveLiquidityIx(marketIndex, sharesToBurn) {
809
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
810
+ const remainingAccounts = this.getRemainingAccounts({
811
+ userAccounts: [this.getUserAccount()],
812
+ useMarketLastSlotCache: true,
813
+ writablePerpMarketIndexes: [marketIndex],
814
+ });
815
+ if (sharesToBurn == undefined) {
816
+ const userAccount = this.getUserAccount();
817
+ const perpPosition = userAccount.perpPositions.filter((position) => position.marketIndex === marketIndex)[0];
818
+ sharesToBurn = perpPosition.lpShares;
819
+ console.log('burning lp shares:', sharesToBurn.toString());
820
+ }
821
+ return this.program.instruction.removeLiquidity(sharesToBurn, marketIndex, {
822
+ accounts: {
823
+ state: await this.getStatePublicKey(),
824
+ user: userAccountPublicKey,
825
+ authority: this.wallet.publicKey,
826
+ },
827
+ remainingAccounts: remainingAccounts,
828
+ });
829
+ }
830
+ async addLiquidity(amount, marketIndex) {
831
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getAddLiquidityIx(amount, marketIndex)), [], this.opts);
832
+ this.marketLastSlotCache.set(marketIndex, slot);
474
833
  return txSig;
475
834
  }
476
- async updateBankCumulativeInterestIx(bankIndex) {
477
- const bank = this.getBankAccount(bankIndex);
478
- return await this.program.instruction.updateBankCumulativeInterest({
835
+ async getAddLiquidityIx(amount, marketIndex) {
836
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
837
+ const remainingAccounts = this.getRemainingAccounts({
838
+ userAccounts: [this.getUserAccount()],
839
+ useMarketLastSlotCache: true,
840
+ writablePerpMarketIndexes: [marketIndex],
841
+ });
842
+ return this.program.instruction.addLiquidity(amount, marketIndex, {
479
843
  accounts: {
480
- bank: bank.pubkey,
844
+ state: await this.getStatePublicKey(),
845
+ user: userAccountPublicKey,
846
+ authority: this.wallet.publicKey,
481
847
  },
848
+ remainingAccounts: remainingAccounts,
482
849
  });
483
850
  }
484
851
  async openPosition(direction, amount, marketIndex, limitPrice) {
485
- return await this.placeAndTake((0, orderParams_1.getMarketOrderParams)(marketIndex, direction, numericConstants_1.ZERO, amount, false, limitPrice));
852
+ return await this.placeAndTake({
853
+ orderType: types_1.OrderType.MARKET,
854
+ marketIndex,
855
+ direction,
856
+ baseAssetAmount: amount,
857
+ price: limitPrice,
858
+ });
859
+ }
860
+ async sendSignedTx(tx) {
861
+ const { txSig } = await this.txSender.send(tx, undefined, this.opts, true);
862
+ return txSig;
863
+ }
864
+ /**
865
+ * Sends a market order and returns a signed tx which can fill the order against the vamm, which the caller can use to fill their own order if required.
866
+ * @param orderParams
867
+ * @param userAccountPublicKey
868
+ * @param userAccount
869
+ * @returns
870
+ */
871
+ async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount) {
872
+ const marketIndex = orderParams.marketIndex;
873
+ const orderId = userAccount.nextOrderId;
874
+ const marketOrderTx = (0, utils_1.wrapInTx)(await this.getPlaceOrderIx(orderParams));
875
+ const fillTx = (0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, userAccount, {
876
+ orderId,
877
+ marketIndex,
878
+ }));
879
+ // Apply the latest blockhash to the txs so that we can sign before sending them
880
+ const currentBlockHash = (await this.connection.getLatestBlockhash('finalized')).blockhash;
881
+ marketOrderTx.recentBlockhash = currentBlockHash;
882
+ fillTx.recentBlockhash = currentBlockHash;
883
+ marketOrderTx.feePayer = userAccount.authority;
884
+ fillTx.feePayer = userAccount.authority;
885
+ const [signedMarketOrderTx, signedFillTx] = await this.provider.wallet.signAllTransactions([marketOrderTx, fillTx]);
886
+ const { txSig, slot } = await this.txSender.send(signedMarketOrderTx, [], this.opts, true);
887
+ this.marketLastSlotCache.set(orderParams.marketIndex, slot);
888
+ return { txSig, signedFillTx };
486
889
  }
487
890
  async placeOrder(orderParams) {
488
891
  const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceOrderIx(orderParams)), [], this.opts);
489
- this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
892
+ this.marketLastSlotCache.set(orderParams.marketIndex, slot);
490
893
  return txSig;
491
894
  }
895
+ getOrderParams(optionalOrderParams, marketType) {
896
+ return Object.assign({}, types_1.DefaultOrderParams, optionalOrderParams, {
897
+ marketType,
898
+ });
899
+ }
492
900
  async getPlaceOrderIx(orderParams) {
901
+ orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
493
902
  const userAccountPublicKey = await this.getUserAccountPublicKey();
494
903
  const remainingAccounts = this.getRemainingAccounts({
495
- writableMarketIndex: orderParams.marketIndex,
904
+ userAccounts: [this.getUserAccount()],
905
+ useMarketLastSlotCache: true,
906
+ readablePerpMarketIndex: orderParams.marketIndex,
496
907
  });
497
908
  return await this.program.instruction.placeOrder(orderParams, {
498
909
  accounts: {
499
910
  state: await this.getStatePublicKey(),
500
911
  user: userAccountPublicKey,
912
+ userStats: this.getUserStatsAccountPublicKey(),
501
913
  authority: this.wallet.publicKey,
502
914
  },
503
915
  remainingAccounts,
@@ -509,13 +921,13 @@ class ClearingHouse {
509
921
  }
510
922
  async getUpdateAMMsIx(marketIndexes) {
511
923
  for (let i = marketIndexes.length; i < 5; i++) {
512
- marketIndexes.push(new anchor_1.BN(100));
924
+ marketIndexes.push(100);
513
925
  }
514
926
  const marketAccountInfos = [];
515
927
  const oracleAccountInfos = [];
516
928
  for (const marketIndex of marketIndexes) {
517
- if (!marketIndex.eq(new anchor_1.BN(100))) {
518
- const market = this.getMarketAccount(marketIndex);
929
+ if (marketIndex !== 100) {
930
+ const market = this.getPerpMarketAccount(marketIndex);
519
931
  marketAccountInfos.push({
520
932
  pubkey: market.pubkey,
521
933
  isWritable: true,
@@ -537,13 +949,51 @@ class ClearingHouse {
537
949
  remainingAccounts,
538
950
  });
539
951
  }
952
+ async settleExpiredMarket(marketIndex) {
953
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getSettleExpiredMarketIx(marketIndex)), [], this.opts);
954
+ return txSig;
955
+ }
956
+ async getSettleExpiredMarketIx(marketIndex) {
957
+ const marketAccountInfos = [];
958
+ const oracleAccountInfos = [];
959
+ const spotMarketAccountInfos = [];
960
+ const market = this.getPerpMarketAccount(marketIndex);
961
+ marketAccountInfos.push({
962
+ pubkey: market.pubkey,
963
+ isWritable: true,
964
+ isSigner: false,
965
+ });
966
+ oracleAccountInfos.push({
967
+ pubkey: market.amm.oracle,
968
+ isWritable: false,
969
+ isSigner: false,
970
+ });
971
+ spotMarketAccountInfos.push({
972
+ pubkey: this.getSpotMarketAccount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX).pubkey,
973
+ isSigner: false,
974
+ isWritable: true,
975
+ });
976
+ const remainingAccounts = oracleAccountInfos
977
+ .concat(spotMarketAccountInfos)
978
+ .concat(marketAccountInfos);
979
+ return await this.program.instruction.settleExpiredMarket(marketIndex, {
980
+ accounts: {
981
+ state: await this.getStatePublicKey(),
982
+ authority: this.wallet.publicKey,
983
+ },
984
+ remainingAccounts,
985
+ });
986
+ }
540
987
  async cancelOrder(orderId) {
541
988
  const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getCancelOrderIx(orderId)), [], this.opts);
542
989
  return txSig;
543
990
  }
544
991
  async getCancelOrderIx(orderId) {
545
992
  const userAccountPublicKey = await this.getUserAccountPublicKey();
546
- const remainingAccounts = this.getRemainingAccounts({});
993
+ const remainingAccounts = this.getRemainingAccounts({
994
+ userAccounts: [this.getUserAccount()],
995
+ useMarketLastSlotCache: true,
996
+ });
547
997
  return await this.program.instruction.cancelOrder(orderId !== null && orderId !== void 0 ? orderId : null, {
548
998
  accounts: {
549
999
  state: await this.getStatePublicKey(),
@@ -560,8 +1010,11 @@ class ClearingHouse {
560
1010
  async getCancelOrderByUserIdIx(userOrderId) {
561
1011
  const userAccountPublicKey = await this.getUserAccountPublicKey();
562
1012
  const order = this.getOrderByUserId(userOrderId);
563
- const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
564
- const remainingAccounts = this.getRemainingAccounts({});
1013
+ const oracle = this.getPerpMarketAccount(order.marketIndex).amm.oracle;
1014
+ const remainingAccounts = this.getRemainingAccounts({
1015
+ userAccounts: [this.getUserAccount()],
1016
+ useMarketLastSlotCache: true,
1017
+ });
565
1018
  return await this.program.instruction.cancelOrderByUserId(userOrderId, {
566
1019
  accounts: {
567
1020
  state: await this.getStatePublicKey(),
@@ -572,55 +1025,45 @@ class ClearingHouse {
572
1025
  remainingAccounts,
573
1026
  });
574
1027
  }
575
- async fillOrder(userAccountPublicKey, user, order, makerInfo) {
576
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)), [], this.opts);
1028
+ async fillOrder(userAccountPublicKey, user, order, makerInfo, referrerInfo) {
1029
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo, referrerInfo)), [], this.opts);
577
1030
  return txSig;
578
1031
  }
579
- async getFillOrderIx(userAccountPublicKey, userAccount, order, makerInfo) {
1032
+ async getFillOrderIx(userAccountPublicKey, userAccount, order, makerInfo, referrerInfo) {
1033
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
580
1034
  const fillerPublicKey = await this.getUserAccountPublicKey();
581
- const marketIndex = order.marketIndex;
582
- const marketAccount = this.getMarketAccount(marketIndex);
583
- const bankAccountInfos = [
584
- {
585
- pubkey: this.getQuoteAssetBankAccount().pubkey,
586
- isSigner: false,
587
- isWritable: true,
588
- },
589
- ];
590
- const marketAccountInfos = [
591
- {
592
- pubkey: marketAccount.pubkey,
1035
+ const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
1036
+ const marketIndex = order
1037
+ ? order.marketIndex
1038
+ : userAccount.orders.find((order) => order.orderId === userAccount.nextOrderId - 1).marketIndex;
1039
+ const userAccounts = [userAccount];
1040
+ if (makerInfo !== undefined) {
1041
+ userAccounts.push(makerInfo.makerUserAccount);
1042
+ }
1043
+ const remainingAccounts = this.getRemainingAccounts({
1044
+ userAccounts,
1045
+ writablePerpMarketIndexes: [marketIndex],
1046
+ });
1047
+ if (makerInfo) {
1048
+ remainingAccounts.push({
1049
+ pubkey: makerInfo.maker,
593
1050
  isWritable: true,
594
1051
  isSigner: false,
595
- },
596
- ];
597
- const oracleAccountInfos = [
598
- {
599
- pubkey: marketAccount.amm.oracle,
600
- isWritable: false,
1052
+ });
1053
+ remainingAccounts.push({
1054
+ pubkey: makerInfo.makerStats,
1055
+ isWritable: true,
601
1056
  isSigner: false,
602
- },
603
- ];
604
- for (const position of userAccount.positions) {
605
- if (!(0, position_1.positionIsAvailable)(position) &&
606
- !position.marketIndex.eq(order.marketIndex)) {
607
- const market = this.getMarketAccount(position.marketIndex);
608
- marketAccountInfos.push({
609
- pubkey: market.pubkey,
610
- isWritable: false,
611
- isSigner: false,
612
- });
613
- oracleAccountInfos.push({
614
- pubkey: market.amm.oracle,
615
- isWritable: false,
616
- isSigner: false,
617
- });
618
- }
1057
+ });
619
1058
  }
620
- const remainingAccounts = oracleAccountInfos.concat(bankAccountInfos.concat(marketAccountInfos));
621
- if (makerInfo) {
1059
+ if (referrerInfo) {
622
1060
  remainingAccounts.push({
623
- pubkey: makerInfo.maker,
1061
+ pubkey: referrerInfo.referrer,
1062
+ isWritable: true,
1063
+ isSigner: false,
1064
+ });
1065
+ remainingAccounts.push({
1066
+ pubkey: referrerInfo.referrerStats,
624
1067
  isWritable: true,
625
1068
  isSigner: false,
626
1069
  });
@@ -631,58 +1074,195 @@ class ClearingHouse {
631
1074
  accounts: {
632
1075
  state: await this.getStatePublicKey(),
633
1076
  filler: fillerPublicKey,
1077
+ fillerStats: fillerStatsPublicKey,
634
1078
  user: userAccountPublicKey,
1079
+ userStats: userStatsPublicKey,
635
1080
  authority: this.wallet.publicKey,
636
1081
  },
637
1082
  remainingAccounts,
638
1083
  });
639
1084
  }
640
- async triggerOrder(userAccountPublicKey, user, order) {
641
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTriggerOrderIx(userAccountPublicKey, user, order)), [], this.opts);
1085
+ async placeSpotOrder(orderParams) {
1086
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceSpotOrderIx(orderParams)), [], this.opts);
642
1087
  return txSig;
643
1088
  }
644
- async getTriggerOrderIx(userAccountPublicKey, userAccount, order) {
1089
+ async getPlaceSpotOrderIx(orderParams) {
1090
+ orderParams = this.getOrderParams(orderParams, types_1.MarketType.SPOT);
1091
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
1092
+ const remainingAccounts = this.getRemainingAccounts({
1093
+ userAccounts: [this.getUserAccount()],
1094
+ useMarketLastSlotCache: true,
1095
+ readableSpotMarketIndex: orderParams.marketIndex,
1096
+ });
1097
+ return await this.program.instruction.placeSpotOrder(orderParams, {
1098
+ accounts: {
1099
+ state: await this.getStatePublicKey(),
1100
+ user: userAccountPublicKey,
1101
+ userStats: this.getUserStatsAccountPublicKey(),
1102
+ authority: this.wallet.publicKey,
1103
+ },
1104
+ remainingAccounts,
1105
+ });
1106
+ }
1107
+ async fillSpotOrder(userAccountPublicKey, user, order, fulfillmentConfig, makerInfo, referrerInfo) {
1108
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillSpotOrderIx(userAccountPublicKey, user, order, fulfillmentConfig, makerInfo, referrerInfo)), [], this.opts);
1109
+ return txSig;
1110
+ }
1111
+ async getFillSpotOrderIx(userAccountPublicKey, userAccount, order, fulfillmentConfig, makerInfo, referrerInfo) {
1112
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
645
1113
  const fillerPublicKey = await this.getUserAccountPublicKey();
646
- const marketIndex = order.marketIndex;
647
- const marketAccount = this.getMarketAccount(marketIndex);
648
- const bankAccountInfos = [
649
- {
650
- pubkey: this.getQuoteAssetBankAccount().pubkey,
1114
+ const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
1115
+ const marketIndex = order
1116
+ ? order.marketIndex
1117
+ : userAccount.orders.find((order) => order.orderId === userAccount.nextOrderId - 1).marketIndex;
1118
+ const userAccounts = [userAccount];
1119
+ if (makerInfo !== undefined) {
1120
+ userAccounts.push(makerInfo.makerUserAccount);
1121
+ }
1122
+ const remainingAccounts = this.getRemainingAccounts({
1123
+ userAccounts,
1124
+ writableSpotMarketIndexes: [marketIndex, numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
1125
+ });
1126
+ if (makerInfo) {
1127
+ remainingAccounts.push({
1128
+ pubkey: makerInfo.maker,
1129
+ isWritable: true,
651
1130
  isSigner: false,
1131
+ });
1132
+ remainingAccounts.push({
1133
+ pubkey: makerInfo.makerStats,
652
1134
  isWritable: true,
653
- },
654
- ];
655
- const marketAccountInfos = [
656
- {
657
- pubkey: marketAccount.pubkey,
1135
+ isSigner: false,
1136
+ });
1137
+ }
1138
+ if (referrerInfo) {
1139
+ remainingAccounts.push({
1140
+ pubkey: referrerInfo.referrer,
658
1141
  isWritable: true,
659
1142
  isSigner: false,
660
- },
661
- ];
662
- const oracleAccountInfos = [
663
- {
664
- pubkey: marketAccount.amm.oracle,
1143
+ });
1144
+ remainingAccounts.push({
1145
+ pubkey: referrerInfo.referrerStats,
1146
+ isWritable: true,
1147
+ isSigner: false,
1148
+ });
1149
+ }
1150
+ const orderId = order.orderId;
1151
+ const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
1152
+ if (fulfillmentConfig) {
1153
+ remainingAccounts.push({
1154
+ pubkey: fulfillmentConfig.pubkey,
1155
+ isWritable: false,
1156
+ isSigner: false,
1157
+ });
1158
+ remainingAccounts.push({
1159
+ pubkey: fulfillmentConfig.serumProgramId,
1160
+ isWritable: false,
1161
+ isSigner: false,
1162
+ });
1163
+ remainingAccounts.push({
1164
+ pubkey: fulfillmentConfig.serumMarket,
1165
+ isWritable: true,
1166
+ isSigner: false,
1167
+ });
1168
+ remainingAccounts.push({
1169
+ pubkey: fulfillmentConfig.serumRequestQueue,
1170
+ isWritable: true,
1171
+ isSigner: false,
1172
+ });
1173
+ remainingAccounts.push({
1174
+ pubkey: fulfillmentConfig.serumEventQueue,
1175
+ isWritable: true,
1176
+ isSigner: false,
1177
+ });
1178
+ remainingAccounts.push({
1179
+ pubkey: fulfillmentConfig.serumBids,
1180
+ isWritable: true,
1181
+ isSigner: false,
1182
+ });
1183
+ remainingAccounts.push({
1184
+ pubkey: fulfillmentConfig.serumAsks,
1185
+ isWritable: true,
1186
+ isSigner: false,
1187
+ });
1188
+ remainingAccounts.push({
1189
+ pubkey: fulfillmentConfig.serumBaseVault,
1190
+ isWritable: true,
1191
+ isSigner: false,
1192
+ });
1193
+ remainingAccounts.push({
1194
+ pubkey: fulfillmentConfig.serumQuoteVault,
1195
+ isWritable: true,
1196
+ isSigner: false,
1197
+ });
1198
+ remainingAccounts.push({
1199
+ pubkey: fulfillmentConfig.serumOpenOrders,
1200
+ isWritable: true,
1201
+ isSigner: false,
1202
+ });
1203
+ remainingAccounts.push({
1204
+ pubkey: (0, pda_1.getSerumSignerPublicKey)(fulfillmentConfig.serumProgramId, fulfillmentConfig.serumMarket, fulfillmentConfig.serumSignerNonce),
1205
+ isWritable: false,
1206
+ isSigner: false,
1207
+ });
1208
+ remainingAccounts.push({
1209
+ pubkey: this.getSignerPublicKey(),
1210
+ isWritable: false,
1211
+ isSigner: false,
1212
+ });
1213
+ remainingAccounts.push({
1214
+ pubkey: spl_token_1.TOKEN_PROGRAM_ID,
1215
+ isWritable: false,
1216
+ isSigner: false,
1217
+ });
1218
+ remainingAccounts.push({
1219
+ pubkey: this.getSpotMarketAccount(marketIndex).vault,
1220
+ isWritable: true,
1221
+ isSigner: false,
1222
+ });
1223
+ remainingAccounts.push({
1224
+ pubkey: this.getQuoteSpotMarketAccount().vault,
1225
+ isWritable: true,
1226
+ isSigner: false,
1227
+ });
1228
+ remainingAccounts.push({
1229
+ pubkey: this.getStateAccount().srmVault,
665
1230
  isWritable: false,
666
1231
  isSigner: false,
1232
+ });
1233
+ }
1234
+ return await this.program.instruction.fillSpotOrder(orderId, fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null, makerOrderId, {
1235
+ accounts: {
1236
+ state: await this.getStatePublicKey(),
1237
+ filler: fillerPublicKey,
1238
+ fillerStats: fillerStatsPublicKey,
1239
+ user: userAccountPublicKey,
1240
+ userStats: userStatsPublicKey,
1241
+ authority: this.wallet.publicKey,
667
1242
  },
668
- ];
669
- for (const position of userAccount.positions) {
670
- if (!(0, position_1.positionIsAvailable)(position) &&
671
- !position.marketIndex.eq(order.marketIndex)) {
672
- const market = this.getMarketAccount(position.marketIndex);
673
- marketAccountInfos.push({
674
- pubkey: market.pubkey,
675
- isWritable: false,
676
- isSigner: false,
677
- });
678
- oracleAccountInfos.push({
679
- pubkey: market.amm.oracle,
680
- isWritable: false,
681
- isSigner: false,
682
- });
683
- }
1243
+ remainingAccounts,
1244
+ });
1245
+ }
1246
+ async triggerOrder(userAccountPublicKey, user, order) {
1247
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTriggerOrderIx(userAccountPublicKey, user, order)), [], this.opts);
1248
+ return txSig;
1249
+ }
1250
+ async getTriggerOrderIx(userAccountPublicKey, userAccount, order) {
1251
+ const fillerPublicKey = await this.getUserAccountPublicKey();
1252
+ let remainingAccountsParams;
1253
+ if ((0, types_1.isVariant)(order.marketType, 'perp')) {
1254
+ remainingAccountsParams = {
1255
+ userAccounts: [userAccount],
1256
+ writablePerpMarketIndexes: [order.marketIndex],
1257
+ };
1258
+ }
1259
+ else {
1260
+ remainingAccountsParams = {
1261
+ userAccounts: [userAccount],
1262
+ writableSpotMarketIndexes: [order.marketIndex, numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
1263
+ };
684
1264
  }
685
- const remainingAccounts = oracleAccountInfos.concat(bankAccountInfos.concat(marketAccountInfos));
1265
+ const remainingAccounts = this.getRemainingAccounts(remainingAccountsParams);
686
1266
  const orderId = order.orderId;
687
1267
  return await this.program.instruction.triggerOrder(orderId, {
688
1268
  accounts: {
@@ -694,16 +1274,23 @@ class ClearingHouse {
694
1274
  remainingAccounts,
695
1275
  });
696
1276
  }
697
- async placeAndTake(orderParams, makerInfo) {
698
- const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeIx(orderParams, makerInfo)), [], this.opts);
699
- this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
1277
+ async placeAndTake(orderParams, makerInfo, referrerInfo) {
1278
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)), [], this.opts);
1279
+ this.marketLastSlotCache.set(orderParams.marketIndex, slot);
700
1280
  return txSig;
701
1281
  }
702
- async getPlaceAndTakeIx(orderParams, makerInfo) {
1282
+ async getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo) {
1283
+ orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
1284
+ const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
703
1285
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1286
+ const userAccounts = [this.getUserAccount()];
1287
+ if (makerInfo !== undefined) {
1288
+ userAccounts.push(makerInfo.makerUserAccount);
1289
+ }
704
1290
  const remainingAccounts = this.getRemainingAccounts({
705
- writableMarketIndex: orderParams.marketIndex,
706
- writableBankIndex: numericConstants_1.QUOTE_ASSET_BANK_INDEX,
1291
+ userAccounts,
1292
+ useMarketLastSlotCache: true,
1293
+ writablePerpMarketIndexes: [orderParams.marketIndex],
707
1294
  });
708
1295
  let makerOrderId = null;
709
1296
  if (makerInfo) {
@@ -713,11 +1300,68 @@ class ClearingHouse {
713
1300
  isSigner: false,
714
1301
  isWritable: true,
715
1302
  });
1303
+ remainingAccounts.push({
1304
+ pubkey: makerInfo.makerStats,
1305
+ isSigner: false,
1306
+ isWritable: true,
1307
+ });
1308
+ }
1309
+ if (referrerInfo) {
1310
+ remainingAccounts.push({
1311
+ pubkey: referrerInfo.referrer,
1312
+ isWritable: true,
1313
+ isSigner: false,
1314
+ });
1315
+ remainingAccounts.push({
1316
+ pubkey: referrerInfo.referrerStats,
1317
+ isWritable: true,
1318
+ isSigner: false,
1319
+ });
716
1320
  }
717
1321
  return await this.program.instruction.placeAndTake(orderParams, makerOrderId, {
718
1322
  accounts: {
719
1323
  state: await this.getStatePublicKey(),
720
1324
  user: userAccountPublicKey,
1325
+ userStats: userStatsPublicKey,
1326
+ authority: this.wallet.publicKey,
1327
+ },
1328
+ remainingAccounts,
1329
+ });
1330
+ }
1331
+ async placeAndMake(orderParams, takerInfo, referrerInfo) {
1332
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo)), [], this.opts);
1333
+ this.marketLastSlotCache.set(orderParams.marketIndex, slot);
1334
+ return txSig;
1335
+ }
1336
+ async getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo) {
1337
+ orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
1338
+ const userStatsPublicKey = this.getUserStatsAccountPublicKey();
1339
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
1340
+ const remainingAccounts = this.getRemainingAccounts({
1341
+ userAccounts: [this.getUserAccount(), takerInfo.takerUserAccount],
1342
+ useMarketLastSlotCache: true,
1343
+ writablePerpMarketIndexes: [orderParams.marketIndex],
1344
+ });
1345
+ if (referrerInfo) {
1346
+ remainingAccounts.push({
1347
+ pubkey: referrerInfo.referrer,
1348
+ isWritable: true,
1349
+ isSigner: false,
1350
+ });
1351
+ remainingAccounts.push({
1352
+ pubkey: referrerInfo.referrerStats,
1353
+ isWritable: true,
1354
+ isSigner: false,
1355
+ });
1356
+ }
1357
+ const takerOrderId = takerInfo.order.orderId;
1358
+ return await this.program.instruction.placeAndMake(orderParams, takerOrderId, {
1359
+ accounts: {
1360
+ state: await this.getStatePublicKey(),
1361
+ user: userAccountPublicKey,
1362
+ userStats: userStatsPublicKey,
1363
+ taker: takerInfo.taker,
1364
+ takerStats: takerInfo.takerStats,
721
1365
  authority: this.wallet.publicKey,
722
1366
  },
723
1367
  remainingAccounts,
@@ -728,19 +1372,31 @@ class ClearingHouse {
728
1372
  * @param marketIndex
729
1373
  * @returns
730
1374
  */
731
- async closePosition(marketIndex) {
1375
+ async closePosition(marketIndex, limitPrice) {
732
1376
  const userPosition = this.getUser().getUserPosition(marketIndex);
733
1377
  if (!userPosition) {
734
1378
  throw Error(`No position in market ${marketIndex.toString()}`);
735
1379
  }
736
- return await this.placeAndTake((0, orderParams_1.getMarketOrderParams)(marketIndex, (0, position_1.findDirectionToClose)(userPosition), numericConstants_1.ZERO, userPosition.baseAssetAmount, true, undefined));
1380
+ return await this.placeAndTake({
1381
+ orderType: types_1.OrderType.MARKET,
1382
+ marketIndex,
1383
+ direction: (0, position_1.findDirectionToClose)(userPosition),
1384
+ baseAssetAmount: userPosition.baseAssetAmount.abs(),
1385
+ reduceOnly: true,
1386
+ price: limitPrice,
1387
+ });
737
1388
  }
738
1389
  async settlePNLs(users, marketIndex) {
739
1390
  const ixs = [];
740
1391
  for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
741
1392
  ixs.push(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex));
742
1393
  }
743
- const tx = new web3_js_1.Transaction().add(...ixs);
1394
+ const tx = new web3_js_1.Transaction()
1395
+ .add(web3_js_1.ComputeBudgetProgram.requestUnits({
1396
+ units: 1000000,
1397
+ additionalFee: 0,
1398
+ }))
1399
+ .add(...ixs);
744
1400
  const { txSig } = await this.txSender.send(tx, [], this.opts);
745
1401
  return txSig;
746
1402
  }
@@ -749,63 +1405,31 @@ class ClearingHouse {
749
1405
  return txSig;
750
1406
  }
751
1407
  async settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
752
- const marketAccountMap = new Map();
753
- const oracleAccountMap = new Map();
754
- const bankAccountMap = new Map();
755
- for (const position of settleeUserAccount.positions) {
756
- if (!(0, position_1.positionIsAvailable)(position)) {
757
- const market = this.getMarketAccount(position.marketIndex);
758
- marketAccountMap.set(position.marketIndex.toNumber(), {
759
- pubkey: market.pubkey,
760
- isWritable: true,
761
- isSigner: false,
762
- });
763
- oracleAccountMap.set(market.amm.oracle.toString(), {
764
- pubkey: market.amm.oracle,
765
- isWritable: false,
766
- isSigner: false,
767
- });
768
- }
769
- }
770
- for (const userBankBalance of settleeUserAccount.bankBalances) {
771
- if (!userBankBalance.balance.eq(numericConstants_1.QUOTE_ASSET_BANK_INDEX)) {
772
- const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
773
- bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
774
- pubkey: bankAccount.pubkey,
775
- isSigner: false,
776
- isWritable: false,
777
- });
778
- if (!bankAccount.bankIndex.eq(numericConstants_1.ZERO)) {
779
- oracleAccountMap.set(bankAccount.oracle.toString(), {
780
- pubkey: bankAccount.oracle,
781
- isSigner: false,
782
- isWritable: false,
783
- });
784
- }
785
- }
786
- }
787
- const marketAccount = this.getMarketAccount(marketIndex.toNumber());
788
- marketAccountMap.set(marketIndex.toNumber(), {
789
- pubkey: marketAccount.pubkey,
790
- isSigner: false,
791
- isWritable: true,
1408
+ const remainingAccounts = this.getRemainingAccounts({
1409
+ userAccounts: [settleeUserAccount],
1410
+ writablePerpMarketIndexes: [marketIndex],
1411
+ writableSpotMarketIndexes: [numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
792
1412
  });
793
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
794
- pubkey: marketAccount.amm.oracle,
795
- isSigner: false,
796
- isWritable: false,
1413
+ return await this.program.instruction.settlePnl(marketIndex, {
1414
+ accounts: {
1415
+ state: await this.getStatePublicKey(),
1416
+ authority: this.wallet.publicKey,
1417
+ user: settleeUserAccountPublicKey,
1418
+ },
1419
+ remainingAccounts: remainingAccounts,
797
1420
  });
798
- bankAccountMap.set(numericConstants_1.QUOTE_ASSET_BANK_INDEX.toNumber(), {
799
- pubkey: this.getBankAccount(numericConstants_1.QUOTE_ASSET_BANK_INDEX).pubkey,
800
- isSigner: false,
801
- isWritable: true,
1421
+ }
1422
+ async settleExpiredPosition(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
1423
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getSettleExpiredPositionIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex)), [], this.opts);
1424
+ return txSig;
1425
+ }
1426
+ async getSettleExpiredPositionIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
1427
+ const remainingAccounts = this.getRemainingAccounts({
1428
+ userAccounts: [settleeUserAccount],
1429
+ writablePerpMarketIndexes: [marketIndex],
1430
+ writableSpotMarketIndexes: [numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
802
1431
  });
803
- const remainingAccounts = [
804
- ...oracleAccountMap.values(),
805
- ...bankAccountMap.values(),
806
- ...marketAccountMap.values(),
807
- ];
808
- return await this.program.instruction.settlePnl(marketIndex, {
1432
+ return await this.program.instruction.settleExpiredPosition(marketIndex, {
809
1433
  accounts: {
810
1434
  state: await this.getStatePublicKey(),
811
1435
  authority: this.wallet.publicKey,
@@ -814,50 +1438,163 @@ class ClearingHouse {
814
1438
  remainingAccounts: remainingAccounts,
815
1439
  });
816
1440
  }
817
- async liquidate(liquidateeUserAccountPublicKey) {
818
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateIx(liquidateeUserAccountPublicKey)), [], this.opts);
1441
+ async liquidatePerp(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
1442
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount)), [], this.opts);
1443
+ this.marketLastSlotCache.set(marketIndex, slot);
819
1444
  return txSig;
820
1445
  }
821
- async getLiquidateIx(liquidateeUserAccountPublicKey) {
822
- const userAccountPublicKey = await this.getUserAccountPublicKey();
823
- const liquidateeUserAccount = (await this.program.account.user.fetch(liquidateeUserAccountPublicKey));
824
- const bankAccountInfos = [
825
- {
826
- pubkey: this.getQuoteAssetBankAccount().pubkey,
827
- isSigner: false,
828
- isWritable: true,
1446
+ async getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
1447
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1448
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
1449
+ const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
1450
+ const remainingAccounts = this.getRemainingAccounts({
1451
+ userAccounts: [this.getUserAccount(), userAccount],
1452
+ useMarketLastSlotCache: true,
1453
+ writablePerpMarketIndexes: [marketIndex],
1454
+ });
1455
+ return await this.program.instruction.liquidatePerp(marketIndex, maxBaseAssetAmount, {
1456
+ accounts: {
1457
+ state: await this.getStatePublicKey(),
1458
+ authority: this.wallet.publicKey,
1459
+ user: userAccountPublicKey,
1460
+ userStats: userStatsPublicKey,
1461
+ liquidator: liquidatorPublicKey,
1462
+ liquidatorStats: liquidatorStatsPublicKey,
829
1463
  },
830
- ];
831
- const marketAccountInfos = [];
832
- const oracleAccountInfos = [];
833
- for (const position of liquidateeUserAccount.positions) {
834
- if (!(0, position_1.positionIsAvailable)(position)) {
835
- const market = this.getMarketAccount(position.marketIndex);
836
- const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, position.marketIndex);
837
- marketAccountInfos.push({
838
- pubkey: marketPublicKey,
839
- isWritable: true,
840
- isSigner: false,
841
- });
842
- oracleAccountInfos.push({
843
- pubkey: market.amm.oracle,
844
- isWritable: false,
845
- isSigner: false,
846
- });
847
- }
848
- }
849
- const remainingAccounts = oracleAccountInfos.concat(bankAccountInfos.concat(marketAccountInfos));
850
- const state = this.getStateAccount();
851
- const quoteAssetBankAccount = this.getQuoteAssetBankAccount();
852
- return await this.program.instruction.liquidate({
1464
+ remainingAccounts: remainingAccounts,
1465
+ });
1466
+ }
1467
+ async liquidateSpot(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1468
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateSpotIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer)), [], this.opts);
1469
+ return txSig;
1470
+ }
1471
+ async getLiquidateSpotIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1472
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1473
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
1474
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1475
+ const remainingAccounts = this.getRemainingAccounts({
1476
+ userAccounts: [this.getUserAccount(), userAccount],
1477
+ useMarketLastSlotCache: true,
1478
+ writableSpotMarketIndexes: [liabilityMarketIndex, assetMarketIndex],
1479
+ });
1480
+ return await this.program.instruction.liquidateSpot(assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer, {
853
1481
  accounts: {
854
1482
  state: await this.getStatePublicKey(),
855
1483
  authority: this.wallet.publicKey,
856
- user: liquidateeUserAccountPublicKey,
857
- liquidator: userAccountPublicKey,
858
- bankVault: quoteAssetBankAccount.vault,
859
- bankVaultAuthority: quoteAssetBankAccount.vaultAuthority,
860
- insuranceVault: state.insuranceVault,
1484
+ user: userAccountPublicKey,
1485
+ userStats: userStatsPublicKey,
1486
+ liquidator: liquidatorPublicKey,
1487
+ liquidatorStats: liquidatorStatsPublicKey,
1488
+ },
1489
+ remainingAccounts: remainingAccounts,
1490
+ });
1491
+ }
1492
+ async liquidateBorrowForPerpPnl(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1493
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer)), [], this.opts);
1494
+ this.marketLastSlotCache.set(perpMarketIndex, slot);
1495
+ return txSig;
1496
+ }
1497
+ async getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1498
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1499
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
1500
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1501
+ const remainingAccounts = this.getRemainingAccounts({
1502
+ userAccounts: [this.getUserAccount(), userAccount],
1503
+ writablePerpMarketIndexes: [perpMarketIndex],
1504
+ writableSpotMarketIndexes: [liabilityMarketIndex],
1505
+ });
1506
+ return await this.program.instruction.liquidateBorrowForPerpPnl(perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer, {
1507
+ accounts: {
1508
+ state: await this.getStatePublicKey(),
1509
+ authority: this.wallet.publicKey,
1510
+ user: userAccountPublicKey,
1511
+ userStats: userStatsPublicKey,
1512
+ liquidator: liquidatorPublicKey,
1513
+ liquidatorStats: liquidatorStatsPublicKey,
1514
+ },
1515
+ remainingAccounts: remainingAccounts,
1516
+ });
1517
+ }
1518
+ async liquidatePerpPnlForDeposit(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer) {
1519
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer)), [], this.opts);
1520
+ this.marketLastSlotCache.set(perpMarketIndex, slot);
1521
+ return txSig;
1522
+ }
1523
+ async getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer) {
1524
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1525
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
1526
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1527
+ const remainingAccounts = this.getRemainingAccounts({
1528
+ userAccounts: [this.getUserAccount(), userAccount],
1529
+ writablePerpMarketIndexes: [perpMarketIndex],
1530
+ writableSpotMarketIndexes: [assetMarketIndex],
1531
+ });
1532
+ return await this.program.instruction.liquidatePerpPnlForDeposit(perpMarketIndex, assetMarketIndex, maxPnlTransfer, {
1533
+ accounts: {
1534
+ state: await this.getStatePublicKey(),
1535
+ authority: this.wallet.publicKey,
1536
+ user: userAccountPublicKey,
1537
+ userStats: userStatsPublicKey,
1538
+ liquidator: liquidatorPublicKey,
1539
+ liquidatorStats: liquidatorStatsPublicKey,
1540
+ },
1541
+ remainingAccounts: remainingAccounts,
1542
+ });
1543
+ }
1544
+ async resolvePerpBankruptcy(userAccountPublicKey, userAccount, marketIndex) {
1545
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolvePerpBankruptcyIx(userAccountPublicKey, userAccount, marketIndex)), [], this.opts);
1546
+ return txSig;
1547
+ }
1548
+ async getResolvePerpBankruptcyIx(userAccountPublicKey, userAccount, marketIndex) {
1549
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1550
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
1551
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1552
+ const remainingAccounts = this.getRemainingAccounts({
1553
+ userAccounts: [this.getUserAccount(), userAccount],
1554
+ writablePerpMarketIndexes: [marketIndex],
1555
+ writableSpotMarketIndexes: [numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
1556
+ });
1557
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
1558
+ return await this.program.instruction.resolvePerpBankruptcy(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, marketIndex, {
1559
+ accounts: {
1560
+ state: await this.getStatePublicKey(),
1561
+ authority: this.wallet.publicKey,
1562
+ user: userAccountPublicKey,
1563
+ userStats: userStatsPublicKey,
1564
+ liquidator: liquidatorPublicKey,
1565
+ liquidatorStats: liquidatorStatsPublicKey,
1566
+ spotMarketVault: spotMarket.vault,
1567
+ insuranceFundVault: spotMarket.insuranceFundVault,
1568
+ clearingHouseSigner: this.getSignerPublicKey(),
1569
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1570
+ },
1571
+ remainingAccounts: remainingAccounts,
1572
+ });
1573
+ }
1574
+ async resolveSpotBankruptcy(userAccountPublicKey, userAccount, marketIndex) {
1575
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolveSpotBankruptcyIx(userAccountPublicKey, userAccount, marketIndex)), [], this.opts);
1576
+ return txSig;
1577
+ }
1578
+ async getResolveSpotBankruptcyIx(userAccountPublicKey, userAccount, marketIndex) {
1579
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1580
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
1581
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1582
+ const remainingAccounts = this.getRemainingAccounts({
1583
+ userAccounts: [this.getUserAccount(), userAccount],
1584
+ writableSpotMarketIndexes: [marketIndex],
1585
+ });
1586
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
1587
+ return await this.program.instruction.resolveSpotBankruptcy(marketIndex, {
1588
+ accounts: {
1589
+ state: await this.getStatePublicKey(),
1590
+ authority: this.wallet.publicKey,
1591
+ user: userAccountPublicKey,
1592
+ userStats: userStatsPublicKey,
1593
+ liquidatorStats: liquidatorStatsPublicKey,
1594
+ liquidator: liquidatorPublicKey,
1595
+ spotMarketVault: spotMarket.vault,
1596
+ insuranceFundVault: spotMarket.insuranceFundVault,
1597
+ clearingHouseSigner: this.getSignerPublicKey(),
861
1598
  tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
862
1599
  },
863
1600
  remainingAccounts: remainingAccounts,
@@ -876,28 +1613,26 @@ class ClearingHouse {
876
1613
  },
877
1614
  });
878
1615
  }
879
- async settleFundingPayment(userAccount) {
880
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getSettleFundingPaymentIx(userAccount)), [], this.opts);
1616
+ async settleFundingPayment(userAccountPublicKey) {
1617
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getSettleFundingPaymentIx(userAccountPublicKey)), [], this.opts);
881
1618
  return txSig;
882
1619
  }
883
- async getSettleFundingPaymentIx(userAccount) {
884
- const user = (await this.program.account.user.fetch(userAccount));
885
- const userPositions = user.positions;
886
- const remainingAccounts = [];
887
- for (const position of userPositions) {
1620
+ async getSettleFundingPaymentIx(userAccountPublicKey) {
1621
+ const userAccount = (await this.program.account.user.fetch(userAccountPublicKey));
1622
+ const writablePerpMarketIndexes = [];
1623
+ for (const position of userAccount.perpPositions) {
888
1624
  if (!(0, position_1.positionIsAvailable)(position)) {
889
- const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, position.marketIndex);
890
- remainingAccounts.push({
891
- pubkey: marketPublicKey,
892
- isWritable: false,
893
- isSigner: false,
894
- });
1625
+ writablePerpMarketIndexes.push(position.marketIndex);
895
1626
  }
896
1627
  }
1628
+ const remainingAccounts = this.getRemainingAccounts({
1629
+ userAccounts: [userAccount],
1630
+ writablePerpMarketIndexes,
1631
+ });
897
1632
  return await this.program.instruction.settleFundingPayment({
898
1633
  accounts: {
899
1634
  state: await this.getStatePublicKey(),
900
- user: userAccount,
1635
+ user: userAccountPublicKey,
901
1636
  },
902
1637
  remainingAccounts,
903
1638
  });
@@ -906,9 +1641,163 @@ class ClearingHouse {
906
1641
  this.eventEmitter.emit(eventName, data);
907
1642
  }
908
1643
  getOracleDataForMarket(marketIndex) {
909
- const oracleKey = this.getMarketAccount(marketIndex).amm.oracle;
1644
+ const oracleKey = this.getPerpMarketAccount(marketIndex).amm.oracle;
1645
+ const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
1646
+ return oracleData;
1647
+ }
1648
+ getOracleDataForSpotMarket(marketIndex) {
1649
+ const oracleKey = this.getSpotMarketAccount(marketIndex).oracle;
910
1650
  const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
911
1651
  return oracleData;
912
1652
  }
1653
+ async initializeInsuranceFundStake(marketIndex) {
1654
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getInitializeInsuranceFundStakeIx(marketIndex)), [], this.opts);
1655
+ return txSig;
1656
+ }
1657
+ async getInitializeInsuranceFundStakeIx(marketIndex) {
1658
+ const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
1659
+ return await this.program.instruction.initializeInsuranceFundStake(marketIndex, {
1660
+ accounts: {
1661
+ insuranceFundStake: ifStakeAccountPublicKey,
1662
+ spotMarket: this.getSpotMarketAccount(marketIndex).pubkey,
1663
+ userStats: this.getUserStatsAccountPublicKey(),
1664
+ authority: this.wallet.publicKey,
1665
+ payer: this.wallet.publicKey,
1666
+ rent: anchor.web3.SYSVAR_RENT_PUBKEY,
1667
+ systemProgram: anchor.web3.SystemProgram.programId,
1668
+ state: await this.getStatePublicKey(),
1669
+ },
1670
+ });
1671
+ }
1672
+ async addInsuranceFundStake(marketIndex, amount, collateralAccountPublicKey) {
1673
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
1674
+ const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
1675
+ const remainingAccounts = this.getRemainingAccounts({
1676
+ userAccounts: [this.getUserAccount()],
1677
+ useMarketLastSlotCache: true,
1678
+ writableSpotMarketIndexes: [marketIndex],
1679
+ });
1680
+ return await this.program.rpc.addInsuranceFundStake(marketIndex, amount, {
1681
+ accounts: {
1682
+ state: await this.getStatePublicKey(),
1683
+ spotMarket: spotMarket.pubkey,
1684
+ insuranceFundStake: ifStakeAccountPublicKey,
1685
+ userStats: this.getUserStatsAccountPublicKey(),
1686
+ authority: this.wallet.publicKey,
1687
+ spotMarketVault: spotMarket.vault,
1688
+ insuranceFundVault: spotMarket.insuranceFundVault,
1689
+ clearingHouseSigner: this.getSignerPublicKey(),
1690
+ userTokenAccount: collateralAccountPublicKey,
1691
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1692
+ },
1693
+ remainingAccounts,
1694
+ });
1695
+ }
1696
+ async requestRemoveInsuranceFundStake(marketIndex, amount) {
1697
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1698
+ const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
1699
+ const remainingAccounts = this.getRemainingAccounts({
1700
+ userAccounts: [this.getUserAccount()],
1701
+ useMarketLastSlotCache: true,
1702
+ writableSpotMarketIndexes: [marketIndex],
1703
+ });
1704
+ return await this.program.rpc.requestRemoveInsuranceFundStake(marketIndex, amount, {
1705
+ accounts: {
1706
+ state: await this.getStatePublicKey(),
1707
+ spotMarket: spotMarketAccount.pubkey,
1708
+ insuranceFundStake: ifStakeAccountPublicKey,
1709
+ userStats: this.getUserStatsAccountPublicKey(),
1710
+ authority: this.wallet.publicKey,
1711
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
1712
+ },
1713
+ remainingAccounts,
1714
+ });
1715
+ }
1716
+ async cancelRequestRemoveInsuranceFundStake(marketIndex) {
1717
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1718
+ const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
1719
+ const remainingAccounts = this.getRemainingAccounts({
1720
+ userAccounts: [this.getUserAccount()],
1721
+ useMarketLastSlotCache: true,
1722
+ writableSpotMarketIndexes: [marketIndex],
1723
+ });
1724
+ return await this.program.rpc.cancelRequestRemoveInsuranceFundStake(marketIndex, {
1725
+ accounts: {
1726
+ state: await this.getStatePublicKey(),
1727
+ spotMarket: spotMarketAccount.pubkey,
1728
+ insuranceFundStake: ifStakeAccountPublicKey,
1729
+ userStats: this.getUserStatsAccountPublicKey(),
1730
+ authority: this.wallet.publicKey,
1731
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
1732
+ },
1733
+ remainingAccounts,
1734
+ });
1735
+ }
1736
+ async removeInsuranceFundStake(marketIndex, collateralAccountPublicKey) {
1737
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1738
+ const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
1739
+ const remainingAccounts = this.getRemainingAccounts({
1740
+ userAccounts: [this.getUserAccount()],
1741
+ useMarketLastSlotCache: true,
1742
+ writableSpotMarketIndexes: [marketIndex],
1743
+ });
1744
+ return await this.program.rpc.removeInsuranceFundStake(marketIndex, {
1745
+ accounts: {
1746
+ state: await this.getStatePublicKey(),
1747
+ spotMarket: spotMarketAccount.pubkey,
1748
+ insuranceFundStake: ifStakeAccountPublicKey,
1749
+ userStats: this.getUserStatsAccountPublicKey(),
1750
+ authority: this.wallet.publicKey,
1751
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
1752
+ clearingHouseSigner: this.getSignerPublicKey(),
1753
+ userTokenAccount: collateralAccountPublicKey,
1754
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1755
+ },
1756
+ remainingAccounts,
1757
+ });
1758
+ }
1759
+ async settleRevenueToInsuranceFund(marketIndex) {
1760
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1761
+ const remainingAccounts = this.getRemainingAccounts({
1762
+ userAccounts: [this.getUserAccount()],
1763
+ useMarketLastSlotCache: true,
1764
+ writableSpotMarketIndexes: [marketIndex],
1765
+ });
1766
+ return await this.program.rpc.settleRevenueToInsuranceFund(marketIndex, {
1767
+ accounts: {
1768
+ state: await this.getStatePublicKey(),
1769
+ spotMarket: spotMarketAccount.pubkey,
1770
+ spotMarketVault: spotMarketAccount.vault,
1771
+ clearingHouseSigner: this.getSignerPublicKey(),
1772
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
1773
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1774
+ },
1775
+ remainingAccounts,
1776
+ });
1777
+ }
1778
+ async resolvePerpPnlDeficit(spotMarketIndex, perpMarketIndex) {
1779
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolvePerpPnlDeficitIx(spotMarketIndex, perpMarketIndex)), [], this.opts);
1780
+ return txSig;
1781
+ }
1782
+ async getResolvePerpPnlDeficitIx(spotMarketIndex, perpMarketIndex) {
1783
+ const remainingAccounts = this.getRemainingAccounts({
1784
+ userAccounts: [this.getUserAccount()],
1785
+ useMarketLastSlotCache: true,
1786
+ writablePerpMarketIndexes: [perpMarketIndex],
1787
+ writableSpotMarketIndexes: [spotMarketIndex],
1788
+ });
1789
+ const spotMarket = this.getSpotMarketAccount(spotMarketIndex);
1790
+ return await this.program.instruction.resolvePerpPnlDeficit(spotMarketIndex, perpMarketIndex, {
1791
+ accounts: {
1792
+ state: await this.getStatePublicKey(),
1793
+ authority: this.wallet.publicKey,
1794
+ spotMarketVault: spotMarket.vault,
1795
+ insuranceFundVault: spotMarket.insuranceFundVault,
1796
+ clearingHouseSigner: this.getSignerPublicKey(),
1797
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
1798
+ },
1799
+ remainingAccounts: remainingAccounts,
1800
+ });
1801
+ }
913
1802
  }
914
1803
  exports.ClearingHouse = ClearingHouse;