@drift-labs/sdk 0.2.0-master.3 → 0.2.0-master.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -13
- package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/accounts/bulkUserSubscription.js +0 -1
- package/lib/accounts/fetch.d.ts +2 -1
- package/lib/accounts/fetch.js +9 -1
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +16 -16
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +31 -28
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +22 -11
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +17 -17
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +37 -35
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/marketAddresses.d.ts +1 -3
- package/lib/addresses/pda.d.ts +10 -4
- package/lib/addresses/pda.js +51 -14
- package/lib/admin.d.ts +34 -22
- package/lib/admin.js +182 -73
- package/lib/clearingHouse.d.ts +120 -42
- package/lib/clearingHouse.js +1505 -254
- package/lib/clearingHouseConfig.d.ts +4 -4
- package/lib/clearingHouseUser.d.ts +50 -38
- package/lib/clearingHouseUser.js +410 -190
- package/lib/clearingHouseUserStats.d.ts +18 -0
- package/lib/clearingHouseUserStats.js +49 -0
- package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
- package/lib/clearingHouseUserStatsConfig.js +2 -0
- package/lib/config.d.ts +7 -9
- package/lib/config.js +21 -21
- package/lib/constants/numericConstants.d.ts +18 -12
- package/lib/constants/numericConstants.js +28 -21
- package/lib/constants/perpMarkets.d.ts +18 -0
- package/lib/constants/{markets.js → perpMarkets.js} +7 -7
- package/lib/constants/spotMarkets.d.ts +19 -0
- package/lib/constants/spotMarkets.js +53 -0
- package/lib/dlob/DLOB.d.ts +73 -0
- package/lib/dlob/DLOB.js +553 -0
- package/lib/dlob/DLOBNode.d.ts +52 -0
- package/lib/dlob/DLOBNode.js +82 -0
- package/lib/dlob/NodeList.d.ts +26 -0
- package/lib/dlob/NodeList.js +138 -0
- package/lib/events/eventList.js +3 -0
- package/lib/events/eventSubscriber.d.ts +4 -2
- package/lib/events/eventSubscriber.js +16 -9
- package/lib/events/fetchLogs.d.ts +10 -1
- package/lib/events/fetchLogs.js +27 -7
- package/lib/events/pollingLogProvider.d.ts +2 -1
- package/lib/events/pollingLogProvider.js +6 -2
- package/lib/events/sort.js +8 -11
- package/lib/events/types.d.ts +7 -2
- package/lib/events/types.js +5 -0
- package/lib/examples/makeTradeExample.js +20 -8
- package/lib/factory/bigNum.d.ts +1 -0
- package/lib/factory/bigNum.js +34 -10
- package/lib/idl/clearing_house.json +4313 -1433
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +21 -6
- package/lib/index.js +25 -6
- package/lib/math/amm.d.ts +8 -5
- package/lib/math/amm.js +68 -46
- package/lib/math/auction.js +4 -1
- package/lib/math/conversion.js +1 -1
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +11 -10
- package/lib/math/insurance.d.ts +4 -0
- package/lib/math/insurance.js +27 -0
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +77 -0
- package/lib/math/market.d.ts +14 -9
- package/lib/math/market.js +69 -7
- package/lib/math/oracles.d.ts +4 -0
- package/lib/math/oracles.js +36 -8
- package/lib/math/orders.d.ts +6 -2
- package/lib/math/orders.js +78 -3
- package/lib/math/position.d.ts +21 -13
- package/lib/math/position.js +76 -36
- package/lib/math/repeg.js +14 -5
- package/lib/math/spotBalance.d.ts +22 -0
- package/lib/math/spotBalance.js +193 -0
- package/lib/math/spotMarket.d.ts +4 -0
- package/lib/math/spotMarket.js +8 -0
- package/lib/math/spotPosition.d.ts +6 -0
- package/lib/math/spotPosition.js +23 -0
- package/lib/math/trade.d.ts +10 -10
- package/lib/math/trade.js +22 -29
- package/lib/oracles/pythClient.js +1 -1
- package/lib/oracles/quoteAssetOracleClient.js +1 -1
- package/lib/oracles/switchboardClient.js +1 -1
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +12 -92
- package/lib/serum/serumSubscriber.d.ts +23 -0
- package/lib/serum/serumSubscriber.js +41 -0
- package/lib/serum/types.d.ts +11 -0
- package/lib/serum/types.js +2 -0
- package/lib/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.d.ts +1 -1
- package/lib/tx/retryTxSender.js +13 -4
- package/lib/tx/types.d.ts +1 -1
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +474 -123
- package/lib/types.js +99 -5
- package/lib/userMap/userMap.d.ts +25 -0
- package/lib/userMap/userMap.js +73 -0
- package/lib/userMap/userStatsMap.d.ts +19 -0
- package/lib/userMap/userStatsMap.js +68 -0
- package/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +9 -5
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +0 -1
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +46 -42
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +31 -11
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +64 -59
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.ts +1 -2
- package/src/addresses/pda.ts +88 -14
- package/src/admin.ts +333 -128
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +2464 -458
- package/src/clearingHouseConfig.ts +4 -3
- package/src/clearingHouseUser.ts +747 -291
- package/src/clearingHouseUserStats.ts +75 -0
- package/src/clearingHouseUserStatsConfig.ts +18 -0
- package/src/config.ts +30 -31
- package/src/constants/numericConstants.ts +41 -25
- package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
- package/src/constants/spotMarkets.ts +72 -0
- package/src/dlob/DLOB.ts +868 -0
- package/src/dlob/DLOBNode.ts +162 -0
- package/src/dlob/NodeList.ts +185 -0
- package/src/events/eventList.js +77 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/eventSubscriber.ts +20 -12
- package/src/events/fetchLogs.ts +35 -8
- package/src/events/pollingLogProvider.ts +10 -2
- package/src/events/sort.ts +11 -15
- package/src/events/types.ts +16 -1
- package/src/examples/makeTradeExample.js +157 -0
- package/src/examples/makeTradeExample.ts +32 -14
- package/src/factory/bigNum.ts +42 -13
- package/src/idl/clearing_house.json +4313 -1433
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.ts +21 -6
- package/src/math/amm.ts +136 -66
- package/src/math/auction.ts +5 -1
- package/src/math/conversion.ts +2 -2
- package/src/math/funding.ts +20 -18
- package/src/math/insurance.ts +35 -0
- package/src/math/margin.ts +127 -0
- package/src/math/market.ts +138 -12
- package/src/math/oracles.ts +63 -9
- package/src/math/orders.ts +138 -4
- package/src/math/position.ts +119 -58
- package/src/math/repeg.ts +16 -6
- package/src/math/spotBalance.ts +316 -0
- package/src/math/spotMarket.ts +9 -0
- package/src/math/spotPosition.ts +47 -0
- package/src/math/trade.ts +43 -49
- package/src/oracles/pythClient.ts +2 -2
- package/src/oracles/quoteAssetOracleClient.ts +2 -2
- package/src/oracles/switchboardClient.ts +2 -2
- package/src/orderParams.ts +24 -137
- package/src/serum/serumSubscriber.ts +80 -0
- package/src/serum/types.ts +13 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +16 -5
- package/src/tx/types.js +2 -0
- package/src/tx/types.ts +2 -1
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +477 -125
- package/src/userMap/userMap.ts +100 -0
- package/src/userMap/userStatsMap.ts +110 -0
- package/src/util/computeUnits.js +21 -11
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/tests/bn/test.ts +12 -3
- package/tests/dlob/helpers.ts +374 -0
- package/tests/dlob/test.ts +2865 -0
- package/lib/constants/banks.d.ts +0 -16
- package/lib/constants/banks.js +0 -34
- package/lib/constants/markets.d.ts +0 -19
- package/lib/math/bankBalance.d.ts +0 -9
- package/lib/math/bankBalance.js +0 -75
- package/lib/math/state.d.ts +0 -8
- package/lib/math/state.js +0 -15
- package/lib/orders.d.ts +0 -8
- package/lib/orders.js +0 -134
- package/src/constants/banks.ts +0 -43
- package/src/math/bankBalance.ts +0 -112
- package/src/math/state.ts +0 -14
- package/src/math/utils.js +0 -27
- package/src/math/utils.js.map +0 -1
- package/src/orders.ts +0 -244
- package/src/util/computeUnits.js.map +0 -1
package/lib/clearingHouse.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
63
|
-
|
|
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
|
-
((
|
|
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
|
-
|
|
75
|
-
|
|
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 {
|
|
79
|
-
|
|
80
|
-
|
|
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 (((
|
|
84
|
-
this.accountSubscriber = new pollingClearingHouseAccountSubscriber_1.PollingClearingHouseAccountSubscriber(this.program, config.accountSubscription.accountLoader,
|
|
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, (
|
|
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, (
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
183
|
+
getPerpMarketAccounts() {
|
|
152
184
|
return this.accountSubscriber
|
|
153
185
|
.getMarketAccountsAndSlots()
|
|
154
186
|
.map((value) => value.data);
|
|
155
187
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
188
|
+
getSpotMarketAccount(marketIndex) {
|
|
189
|
+
return this.accountSubscriber.getSpotMarketAccountAndSlot(marketIndex).data;
|
|
190
|
+
}
|
|
191
|
+
getSpotMarketAccounts() {
|
|
192
|
+
return this.accountSubscriber
|
|
193
|
+
.getSpotMarketAccountsAndSlots()
|
|
194
|
+
.map((value) => value.data);
|
|
159
195
|
}
|
|
160
|
-
|
|
161
|
-
return this.accountSubscriber.
|
|
162
|
-
.data;
|
|
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,96 @@ 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()
|
|
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
|
+
}
|
|
210
269
|
const nameBuffer = (0, userName_1.encodeName)(name);
|
|
211
270
|
const initializeUserAccountIx = await this.program.instruction.initializeUser(userId, nameBuffer, {
|
|
212
271
|
accounts: {
|
|
213
272
|
user: userAccountPublicKey,
|
|
273
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
214
274
|
authority: this.wallet.publicKey,
|
|
215
275
|
payer: this.wallet.publicKey,
|
|
216
276
|
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
217
277
|
systemProgram: anchor.web3.SystemProgram.programId,
|
|
218
278
|
state: await this.getStatePublicKey(),
|
|
219
279
|
},
|
|
280
|
+
remainingAccounts,
|
|
220
281
|
});
|
|
221
282
|
return [userAccountPublicKey, initializeUserAccountIx];
|
|
222
283
|
}
|
|
284
|
+
async getInitializeUserStatsIx() {
|
|
285
|
+
return await this.program.instruction.initializeUserStats({
|
|
286
|
+
accounts: {
|
|
287
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
288
|
+
authority: this.wallet.publicKey,
|
|
289
|
+
payer: this.wallet.publicKey,
|
|
290
|
+
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
291
|
+
systemProgram: anchor.web3.SystemProgram.programId,
|
|
292
|
+
state: await this.getStatePublicKey(),
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
async updateUserName(name, userId = 0) {
|
|
297
|
+
const nameBuffer = (0, userName_1.encodeName)(name);
|
|
298
|
+
return await this.program.rpc.updateUserName(userId, nameBuffer, {
|
|
299
|
+
accounts: {
|
|
300
|
+
user: await this.getUserAccountPublicKey(),
|
|
301
|
+
authority: this.wallet.publicKey,
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
async updateUserCustomMarginRatio(marginRatio, userId = 0) {
|
|
306
|
+
return await this.program.rpc.updateUserCustomMarginRatio(userId, marginRatio, {
|
|
307
|
+
accounts: {
|
|
308
|
+
user: await this.getUserAccountPublicKey(),
|
|
309
|
+
authority: this.wallet.publicKey,
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
async updateUserDelegate(delegate, userId = 0) {
|
|
314
|
+
return await this.program.rpc.updateUserDelegate(userId, delegate, {
|
|
315
|
+
accounts: {
|
|
316
|
+
user: await this.getUserAccountPublicKey(),
|
|
317
|
+
authority: this.wallet.publicKey,
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
async getUserAccountsForDelegate(delegate) {
|
|
322
|
+
const programAccounts = await this.program.account.user.all([
|
|
323
|
+
{
|
|
324
|
+
memcmp: {
|
|
325
|
+
offset: 40,
|
|
326
|
+
/** data to match, as base-58 encoded string and limited to less than 129 bytes */
|
|
327
|
+
bytes: bs58_1.default.encode(delegate.toBuffer()),
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
]);
|
|
331
|
+
return programAccounts.map((programAccount) => programAccount.account);
|
|
332
|
+
}
|
|
223
333
|
getUser(userId) {
|
|
224
334
|
userId = userId !== null && userId !== void 0 ? userId : this.activeUserId;
|
|
225
335
|
if (!this.users.has(userId)) {
|
|
@@ -230,6 +340,16 @@ class ClearingHouse {
|
|
|
230
340
|
getUsers() {
|
|
231
341
|
return [...this.users.values()];
|
|
232
342
|
}
|
|
343
|
+
getUserStats() {
|
|
344
|
+
return this.userStats;
|
|
345
|
+
}
|
|
346
|
+
getUserStatsAccountPublicKey() {
|
|
347
|
+
if (this.userStatsAccountPublicKey) {
|
|
348
|
+
return this.userStatsAccountPublicKey;
|
|
349
|
+
}
|
|
350
|
+
this.userStatsAccountPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, this.authority);
|
|
351
|
+
return this.userStatsAccountPublicKey;
|
|
352
|
+
}
|
|
233
353
|
async getUserAccountPublicKey() {
|
|
234
354
|
return this.getUser().userAccountPublicKey;
|
|
235
355
|
}
|
|
@@ -239,14 +359,13 @@ class ClearingHouse {
|
|
|
239
359
|
getUserAccountAndSlot(userId) {
|
|
240
360
|
return this.getUser(userId).getUserAccountAndSlot();
|
|
241
361
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return this.getUserAccount().bankBalances.find((bankBalance) => bankBalance.bankIndex.eq(bankIndexBN));
|
|
362
|
+
getSpotPosition(marketIndex) {
|
|
363
|
+
return this.getUserAccount().spotPositions.find((spotPosition) => spotPosition.marketIndex === marketIndex);
|
|
245
364
|
}
|
|
246
365
|
getQuoteAssetTokenAmount() {
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
return (0,
|
|
366
|
+
const spotMarket = this.getSpotMarketAccount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
367
|
+
const spotPosition = this.getSpotPosition(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
368
|
+
return (0, spotBalance_1.getTokenAmount)(spotPosition.balance, spotMarket, spotPosition.balanceType);
|
|
250
369
|
}
|
|
251
370
|
getRemainingAccounts(params) {
|
|
252
371
|
const userAccountAndSlot = this.getUserAccountAndSlot();
|
|
@@ -255,14 +374,14 @@ class ClearingHouse {
|
|
|
255
374
|
}
|
|
256
375
|
const { data: userAccount, slot: lastUserPositionsSlot } = userAccountAndSlot;
|
|
257
376
|
const oracleAccountMap = new Map();
|
|
258
|
-
const
|
|
259
|
-
const
|
|
377
|
+
const spotMarketAccountMap = new Map();
|
|
378
|
+
const perpMarketAccountMap = new Map();
|
|
260
379
|
for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
|
|
261
380
|
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
262
381
|
// otherwise remove from slot
|
|
263
382
|
if (slot > lastUserPositionsSlot) {
|
|
264
|
-
const marketAccount = this.
|
|
265
|
-
|
|
383
|
+
const marketAccount = this.getPerpMarketAccount(marketIndexNum);
|
|
384
|
+
perpMarketAccountMap.set(marketIndexNum, {
|
|
266
385
|
pubkey: marketAccount.pubkey,
|
|
267
386
|
isSigner: false,
|
|
268
387
|
isWritable: false,
|
|
@@ -277,15 +396,13 @@ class ClearingHouse {
|
|
|
277
396
|
this.marketLastSlotCache.delete(marketIndexNum);
|
|
278
397
|
}
|
|
279
398
|
}
|
|
280
|
-
for (const position of userAccount.
|
|
399
|
+
for (const position of userAccount.perpPositions) {
|
|
281
400
|
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
marketAccountMap.set(marketIndexNum, {
|
|
401
|
+
const marketAccount = this.getPerpMarketAccount(position.marketIndex);
|
|
402
|
+
perpMarketAccountMap.set(position.marketIndex, {
|
|
285
403
|
pubkey: marketAccount.pubkey,
|
|
286
404
|
isSigner: false,
|
|
287
|
-
|
|
288
|
-
isWritable: true,
|
|
405
|
+
isWritable: false,
|
|
289
406
|
});
|
|
290
407
|
oracleAccountMap.set(marketAccount.pubkey.toString(), {
|
|
291
408
|
pubkey: marketAccount.amm.oracle,
|
|
@@ -294,9 +411,22 @@ class ClearingHouse {
|
|
|
294
411
|
});
|
|
295
412
|
}
|
|
296
413
|
}
|
|
297
|
-
if (params.
|
|
298
|
-
const marketAccount = this.
|
|
299
|
-
|
|
414
|
+
if (params.readablePerpMarketIndex !== undefined) {
|
|
415
|
+
const marketAccount = this.getPerpMarketAccount(params.readablePerpMarketIndex);
|
|
416
|
+
perpMarketAccountMap.set(params.readablePerpMarketIndex, {
|
|
417
|
+
pubkey: marketAccount.pubkey,
|
|
418
|
+
isSigner: false,
|
|
419
|
+
isWritable: false,
|
|
420
|
+
});
|
|
421
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
422
|
+
pubkey: marketAccount.amm.oracle,
|
|
423
|
+
isSigner: false,
|
|
424
|
+
isWritable: false,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
if (params.writablePerpMarketIndex !== undefined) {
|
|
428
|
+
const marketAccount = this.getPerpMarketAccount(params.writablePerpMarketIndex);
|
|
429
|
+
perpMarketAccountMap.set(params.writablePerpMarketIndex, {
|
|
300
430
|
pubkey: marketAccount.pubkey,
|
|
301
431
|
isSigner: false,
|
|
302
432
|
isWritable: true,
|
|
@@ -307,33 +437,48 @@ class ClearingHouse {
|
|
|
307
437
|
isWritable: false,
|
|
308
438
|
});
|
|
309
439
|
}
|
|
310
|
-
for (const
|
|
311
|
-
if (!
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
pubkey:
|
|
440
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
441
|
+
if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
442
|
+
const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
443
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
444
|
+
pubkey: spotMarketAccount.pubkey,
|
|
315
445
|
isSigner: false,
|
|
316
446
|
isWritable: false,
|
|
317
447
|
});
|
|
318
|
-
if (
|
|
319
|
-
oracleAccountMap.set(
|
|
320
|
-
pubkey:
|
|
448
|
+
if (spotMarketAccount.marketIndex !== 0) {
|
|
449
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
450
|
+
pubkey: spotMarketAccount.oracle,
|
|
321
451
|
isSigner: false,
|
|
322
452
|
isWritable: false,
|
|
323
453
|
});
|
|
324
454
|
}
|
|
325
455
|
}
|
|
326
456
|
}
|
|
327
|
-
if (params.
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
pubkey:
|
|
457
|
+
if (params.readableSpotMarketIndex !== undefined) {
|
|
458
|
+
const spotMarketAccount = this.getSpotMarketAccount(params.readableSpotMarketIndex);
|
|
459
|
+
spotMarketAccountMap.set(params.readableSpotMarketIndex, {
|
|
460
|
+
pubkey: spotMarketAccount.pubkey,
|
|
461
|
+
isSigner: false,
|
|
462
|
+
isWritable: false,
|
|
463
|
+
});
|
|
464
|
+
if (spotMarketAccount.marketIndex !== 0) {
|
|
465
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
466
|
+
pubkey: spotMarketAccount.oracle,
|
|
467
|
+
isSigner: false,
|
|
468
|
+
isWritable: false,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
if (params.writableSpotMarketIndex !== undefined) {
|
|
473
|
+
const spotMarketAccount = this.getSpotMarketAccount(params.writableSpotMarketIndex);
|
|
474
|
+
spotMarketAccountMap.set(params.writableSpotMarketIndex, {
|
|
475
|
+
pubkey: spotMarketAccount.pubkey,
|
|
331
476
|
isSigner: false,
|
|
332
477
|
isWritable: true,
|
|
333
478
|
});
|
|
334
|
-
if (
|
|
335
|
-
oracleAccountMap.set(
|
|
336
|
-
pubkey:
|
|
479
|
+
if (spotMarketAccount.marketIndex !== 0) {
|
|
480
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
481
|
+
pubkey: spotMarketAccount.oracle,
|
|
337
482
|
isSigner: false,
|
|
338
483
|
isWritable: false,
|
|
339
484
|
});
|
|
@@ -341,8 +486,8 @@ class ClearingHouse {
|
|
|
341
486
|
}
|
|
342
487
|
return [
|
|
343
488
|
...oracleAccountMap.values(),
|
|
344
|
-
...
|
|
345
|
-
...
|
|
489
|
+
...spotMarketAccountMap.values(),
|
|
490
|
+
...perpMarketAccountMap.values(),
|
|
346
491
|
];
|
|
347
492
|
}
|
|
348
493
|
getOrder(orderId) {
|
|
@@ -354,38 +499,63 @@ class ClearingHouse {
|
|
|
354
499
|
var _a;
|
|
355
500
|
return (_a = this.getUserAccount()) === null || _a === void 0 ? void 0 : _a.orders.find((order) => order.userOrderId === userOrderId);
|
|
356
501
|
}
|
|
357
|
-
async deposit(amount,
|
|
358
|
-
const
|
|
359
|
-
const
|
|
360
|
-
const
|
|
502
|
+
async deposit(amount, marketIndex, collateralAccountPublicKey, userId, reduceOnly = false) {
|
|
503
|
+
const tx = new web3_js_1.Transaction();
|
|
504
|
+
const additionalSigners = [];
|
|
505
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
506
|
+
const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
|
|
507
|
+
const authority = this.authority;
|
|
508
|
+
const createWSOLTokenAccount = isSolMarket && collateralAccountPublicKey.equals(authority);
|
|
509
|
+
if (createWSOLTokenAccount) {
|
|
510
|
+
const { ixs, signers, pubkey } = await this.getWrappedSolAccountCreationIxs(amount, true);
|
|
511
|
+
collateralAccountPublicKey = pubkey;
|
|
512
|
+
ixs.forEach((ix) => {
|
|
513
|
+
tx.add(ix);
|
|
514
|
+
});
|
|
515
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
516
|
+
}
|
|
517
|
+
const depositCollateralIx = await this.getDepositInstruction(amount, marketIndex, collateralAccountPublicKey, userId, reduceOnly, true);
|
|
518
|
+
tx.add(depositCollateralIx);
|
|
519
|
+
// Close the wrapped sol account at the end of the transaction
|
|
520
|
+
if (createWSOLTokenAccount) {
|
|
521
|
+
tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, collateralAccountPublicKey, authority, authority, []));
|
|
522
|
+
}
|
|
523
|
+
const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
|
|
361
524
|
return txSig;
|
|
362
525
|
}
|
|
363
|
-
async getDepositInstruction(amount,
|
|
526
|
+
async getDepositInstruction(amount, marketIndex, userTokenAccount, userId, reduceOnly = false, userInitialized = true) {
|
|
364
527
|
const userAccountPublicKey = userId
|
|
365
|
-
? await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.
|
|
528
|
+
? await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.authority, userId)
|
|
366
529
|
: await this.getUserAccountPublicKey();
|
|
367
530
|
let remainingAccounts = [];
|
|
368
531
|
if (userInitialized) {
|
|
369
532
|
remainingAccounts = this.getRemainingAccounts({
|
|
370
|
-
|
|
533
|
+
writableSpotMarketIndex: marketIndex,
|
|
371
534
|
});
|
|
372
535
|
}
|
|
373
536
|
else {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
537
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
538
|
+
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
539
|
+
remainingAccounts.push({
|
|
540
|
+
pubkey: spotMarketAccount.oracle,
|
|
377
541
|
isSigner: false,
|
|
378
|
-
isWritable:
|
|
379
|
-
}
|
|
380
|
-
|
|
542
|
+
isWritable: false,
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
remainingAccounts.push({
|
|
546
|
+
pubkey: spotMarketAccount.pubkey,
|
|
547
|
+
isSigner: false,
|
|
548
|
+
isWritable: true,
|
|
549
|
+
});
|
|
381
550
|
}
|
|
382
|
-
const
|
|
383
|
-
return await this.program.instruction.deposit(
|
|
551
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
552
|
+
return await this.program.instruction.deposit(marketIndex, amount, reduceOnly, {
|
|
384
553
|
accounts: {
|
|
385
554
|
state: await this.getStatePublicKey(),
|
|
386
|
-
|
|
387
|
-
|
|
555
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
556
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
388
557
|
user: userAccountPublicKey,
|
|
558
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
389
559
|
userTokenAccount: userTokenAccount,
|
|
390
560
|
authority: this.wallet.publicKey,
|
|
391
561
|
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
@@ -393,55 +563,140 @@ class ClearingHouse {
|
|
|
393
563
|
remainingAccounts,
|
|
394
564
|
});
|
|
395
565
|
}
|
|
566
|
+
async checkIfAccountExists(account) {
|
|
567
|
+
try {
|
|
568
|
+
const accountInfo = await this.connection.getAccountInfo(account);
|
|
569
|
+
return accountInfo != null;
|
|
570
|
+
}
|
|
571
|
+
catch (e) {
|
|
572
|
+
// Doesn't already exist
|
|
573
|
+
return false;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
async getWrappedSolAccountCreationIxs(amount, isDeposit) {
|
|
577
|
+
const wrappedSolAccount = new web3_js_1.Keypair();
|
|
578
|
+
const result = {
|
|
579
|
+
ixs: [],
|
|
580
|
+
signers: [],
|
|
581
|
+
pubkey: wrappedSolAccount.publicKey,
|
|
582
|
+
};
|
|
583
|
+
const rentSpaceLamports = new anchor_1.BN(web3_js_1.LAMPORTS_PER_SOL / 100);
|
|
584
|
+
const lamports = isDeposit
|
|
585
|
+
? amount.add(rentSpaceLamports)
|
|
586
|
+
: rentSpaceLamports;
|
|
587
|
+
const authority = this.wallet.publicKey;
|
|
588
|
+
result.ixs.push(web3_js_1.SystemProgram.createAccount({
|
|
589
|
+
fromPubkey: authority,
|
|
590
|
+
newAccountPubkey: wrappedSolAccount.publicKey,
|
|
591
|
+
lamports: lamports.toNumber(),
|
|
592
|
+
space: 165,
|
|
593
|
+
programId: spl_token_1.TOKEN_PROGRAM_ID,
|
|
594
|
+
}));
|
|
595
|
+
result.ixs.push(spl_token_1.Token.createInitAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, spotMarkets_1.WRAPPED_SOL_MINT, wrappedSolAccount.publicKey, authority));
|
|
596
|
+
result.signers.push(wrappedSolAccount);
|
|
597
|
+
return result;
|
|
598
|
+
}
|
|
599
|
+
getAssociatedTokenAccountCreationIx(tokenMintAddress, associatedTokenAddress) {
|
|
600
|
+
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);
|
|
601
|
+
return createAssociatedAccountIx;
|
|
602
|
+
}
|
|
396
603
|
/**
|
|
397
604
|
* Creates the Clearing House User account for a user, and deposits some initial collateral
|
|
398
|
-
* @param userId
|
|
399
|
-
* @param name
|
|
400
605
|
* @param amount
|
|
401
606
|
* @param userTokenAccount
|
|
607
|
+
* @param marketIndex
|
|
608
|
+
* @param userId
|
|
609
|
+
* @param name
|
|
402
610
|
* @param fromUserId
|
|
403
611
|
* @returns
|
|
404
612
|
*/
|
|
405
|
-
async initializeUserAccountAndDepositCollateral(amount, userTokenAccount,
|
|
406
|
-
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
|
|
613
|
+
async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, userId = 0, name = userName_1.DEFAULT_USER_NAME, fromUserId, referrerInfo) {
|
|
614
|
+
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
|
|
615
|
+
const additionalSigners = [];
|
|
616
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
617
|
+
const isSolMarket = spotMarket.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
|
|
618
|
+
const tx = new web3_js_1.Transaction();
|
|
619
|
+
const authority = this.wallet.publicKey;
|
|
620
|
+
const createWSOLTokenAccount = isSolMarket && userTokenAccount.equals(authority);
|
|
621
|
+
if (createWSOLTokenAccount) {
|
|
622
|
+
const { ixs: startIxs, signers, pubkey, } = await this.getWrappedSolAccountCreationIxs(amount, true);
|
|
623
|
+
userTokenAccount = pubkey;
|
|
624
|
+
startIxs.forEach((ix) => {
|
|
625
|
+
tx.add(ix);
|
|
626
|
+
});
|
|
627
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
628
|
+
}
|
|
407
629
|
const depositCollateralIx = fromUserId != null
|
|
408
|
-
? await this.getTransferDepositIx(amount,
|
|
409
|
-
: await this.getDepositInstruction(amount,
|
|
410
|
-
|
|
411
|
-
.add(
|
|
412
|
-
|
|
413
|
-
|
|
630
|
+
? await this.getTransferDepositIx(amount, marketIndex, fromUserId, userId)
|
|
631
|
+
: await this.getDepositInstruction(amount, marketIndex, userTokenAccount, userId, false, false);
|
|
632
|
+
if (userId === 0) {
|
|
633
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
634
|
+
}
|
|
635
|
+
tx.add(initializeUserAccountIx).add(depositCollateralIx);
|
|
636
|
+
// Close the wrapped sol account at the end of the transaction
|
|
637
|
+
if (createWSOLTokenAccount) {
|
|
638
|
+
tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, userTokenAccount, authority, authority, []));
|
|
639
|
+
}
|
|
640
|
+
const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
|
|
414
641
|
return [txSig, userAccountPublicKey];
|
|
415
642
|
}
|
|
416
|
-
async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME,
|
|
417
|
-
const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await
|
|
418
|
-
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
|
|
419
|
-
const depositCollateralIx = await this.getDepositInstruction(amount,
|
|
420
|
-
const tx = new web3_js_1.Transaction()
|
|
421
|
-
|
|
422
|
-
.add(
|
|
423
|
-
|
|
424
|
-
|
|
643
|
+
async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME, marketIndex, tokenFaucet, amount, referrerInfo) {
|
|
644
|
+
const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
|
|
645
|
+
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
|
|
646
|
+
const depositCollateralIx = await this.getDepositInstruction(amount, marketIndex, associateTokenPublicKey, userId, false, false);
|
|
647
|
+
const tx = new web3_js_1.Transaction().add(createAssociatedAccountIx).add(mintToIx);
|
|
648
|
+
if (userId === 0) {
|
|
649
|
+
tx.add(await this.getInitializeUserStatsIx());
|
|
650
|
+
}
|
|
651
|
+
tx.add(initializeUserAccountIx).add(depositCollateralIx);
|
|
425
652
|
const txSig = await this.program.provider.sendAndConfirm(tx, []);
|
|
426
653
|
return [txSig, userAccountPublicKey];
|
|
427
654
|
}
|
|
428
|
-
async withdraw(amount,
|
|
429
|
-
const
|
|
655
|
+
async withdraw(amount, marketIndex, userTokenAccount, reduceOnly = false) {
|
|
656
|
+
const tx = new web3_js_1.Transaction();
|
|
657
|
+
const additionalSigners = [];
|
|
658
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
659
|
+
const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
|
|
660
|
+
const authority = this.wallet.publicKey;
|
|
661
|
+
const createWSOLTokenAccount = isSolMarket && userTokenAccount.equals(authority);
|
|
662
|
+
if (createWSOLTokenAccount) {
|
|
663
|
+
const { ixs, signers, pubkey } = await this.getWrappedSolAccountCreationIxs(amount, false);
|
|
664
|
+
userTokenAccount = pubkey;
|
|
665
|
+
ixs.forEach((ix) => {
|
|
666
|
+
tx.add(ix);
|
|
667
|
+
});
|
|
668
|
+
signers.forEach((signer) => additionalSigners.push(signer));
|
|
669
|
+
}
|
|
670
|
+
else {
|
|
671
|
+
const accountExists = await this.checkIfAccountExists(userTokenAccount);
|
|
672
|
+
if (!accountExists) {
|
|
673
|
+
const createAssociatedTokenAccountIx = this.getAssociatedTokenAccountCreationIx(spotMarketAccount.mint, userTokenAccount);
|
|
674
|
+
tx.add(createAssociatedTokenAccountIx);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
const withdrawCollateral = await this.getWithdrawIx(amount, spotMarketAccount.marketIndex, userTokenAccount, reduceOnly);
|
|
678
|
+
tx.add(withdrawCollateral);
|
|
679
|
+
// Close the wrapped sol account at the end of the transaction
|
|
680
|
+
if (createWSOLTokenAccount) {
|
|
681
|
+
tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, userTokenAccount, authority, authority, []));
|
|
682
|
+
}
|
|
683
|
+
const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
|
|
430
684
|
return txSig;
|
|
431
685
|
}
|
|
432
|
-
async getWithdrawIx(amount,
|
|
686
|
+
async getWithdrawIx(amount, marketIndex, userTokenAccount, reduceOnly = false) {
|
|
433
687
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
434
688
|
const remainingAccounts = this.getRemainingAccounts({
|
|
435
|
-
|
|
689
|
+
writableSpotMarketIndex: marketIndex,
|
|
436
690
|
});
|
|
437
|
-
const
|
|
438
|
-
return await this.program.instruction.withdraw(
|
|
691
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
692
|
+
return await this.program.instruction.withdraw(marketIndex, amount, reduceOnly, {
|
|
439
693
|
accounts: {
|
|
440
694
|
state: await this.getStatePublicKey(),
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
695
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
696
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
697
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
444
698
|
user: userAccountPublicKey,
|
|
699
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
445
700
|
userTokenAccount: userTokenAccount,
|
|
446
701
|
authority: this.wallet.publicKey,
|
|
447
702
|
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
@@ -449,55 +704,175 @@ class ClearingHouse {
|
|
|
449
704
|
remainingAccounts,
|
|
450
705
|
});
|
|
451
706
|
}
|
|
452
|
-
async transferDeposit(amount,
|
|
453
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTransferDepositIx(amount,
|
|
707
|
+
async transferDeposit(amount, marketIndex, fromUserId, toUserId) {
|
|
708
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTransferDepositIx(amount, marketIndex, fromUserId, toUserId)), [], this.opts);
|
|
454
709
|
return txSig;
|
|
455
710
|
}
|
|
456
|
-
async getTransferDepositIx(amount,
|
|
711
|
+
async getTransferDepositIx(amount, marketIndex, fromUserId, toUserId) {
|
|
457
712
|
const fromUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, fromUserId);
|
|
458
713
|
const toUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, toUserId);
|
|
459
714
|
const remainingAccounts = this.getRemainingAccounts({
|
|
460
|
-
|
|
715
|
+
writableSpotMarketIndex: marketIndex,
|
|
461
716
|
});
|
|
462
|
-
return await this.program.instruction.transferDeposit(
|
|
717
|
+
return await this.program.instruction.transferDeposit(marketIndex, amount, {
|
|
463
718
|
accounts: {
|
|
464
719
|
authority: this.wallet.publicKey,
|
|
465
720
|
fromUser,
|
|
466
721
|
toUser,
|
|
722
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
467
723
|
state: await this.getStatePublicKey(),
|
|
468
724
|
},
|
|
469
725
|
remainingAccounts,
|
|
470
726
|
});
|
|
471
727
|
}
|
|
472
|
-
async
|
|
473
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.
|
|
728
|
+
async updateSpotMarketCumulativeInterest(marketIndex) {
|
|
729
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.updateSpotMarketCumulativeInterestIx(marketIndex)), [], this.opts);
|
|
730
|
+
return txSig;
|
|
731
|
+
}
|
|
732
|
+
async updateSpotMarketCumulativeInterestIx(marketIndex) {
|
|
733
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
734
|
+
return await this.program.instruction.updateSpotMarketCumulativeInterest({
|
|
735
|
+
accounts: {
|
|
736
|
+
spotMarket: spotMarket.pubkey,
|
|
737
|
+
},
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
async settleLP(settleeUserAccountPublicKey, marketIndex) {
|
|
741
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.settleLPIx(settleeUserAccountPublicKey, marketIndex)), [], this.opts);
|
|
742
|
+
return txSig;
|
|
743
|
+
}
|
|
744
|
+
async settleLPIx(settleeUserAccountPublicKey, marketIndex) {
|
|
745
|
+
const settleeUserAccount = (await this.program.account.user.fetch(settleeUserAccountPublicKey));
|
|
746
|
+
const userPositions = settleeUserAccount.perpPositions;
|
|
747
|
+
const remainingAccounts = [];
|
|
748
|
+
let foundMarket = false;
|
|
749
|
+
for (const position of userPositions) {
|
|
750
|
+
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
751
|
+
const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, position.marketIndex);
|
|
752
|
+
remainingAccounts.push({
|
|
753
|
+
pubkey: marketPublicKey,
|
|
754
|
+
isWritable: true,
|
|
755
|
+
isSigner: false,
|
|
756
|
+
});
|
|
757
|
+
if (marketIndex === position.marketIndex) {
|
|
758
|
+
foundMarket = true;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (!foundMarket) {
|
|
763
|
+
console.log('Warning: lp is not in the market specified -- tx will likely fail');
|
|
764
|
+
}
|
|
765
|
+
return this.program.instruction.settleLp(marketIndex, {
|
|
766
|
+
accounts: {
|
|
767
|
+
state: await this.getStatePublicKey(),
|
|
768
|
+
user: settleeUserAccountPublicKey,
|
|
769
|
+
},
|
|
770
|
+
remainingAccounts: remainingAccounts,
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
async removeLiquidity(marketIndex, sharesToBurn) {
|
|
774
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getRemoveLiquidityIx(marketIndex, sharesToBurn)), [], this.opts);
|
|
775
|
+
return txSig;
|
|
776
|
+
}
|
|
777
|
+
async getRemoveLiquidityIx(marketIndex, sharesToBurn) {
|
|
778
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
779
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
780
|
+
writablePerpMarketIndex: marketIndex,
|
|
781
|
+
});
|
|
782
|
+
if (sharesToBurn == undefined) {
|
|
783
|
+
const userAccount = this.getUserAccount();
|
|
784
|
+
const perpPosition = userAccount.perpPositions.filter((position) => position.marketIndex === marketIndex)[0];
|
|
785
|
+
sharesToBurn = perpPosition.lpShares;
|
|
786
|
+
console.log('burning lp shares:', sharesToBurn.toString());
|
|
787
|
+
}
|
|
788
|
+
return this.program.instruction.removeLiquidity(sharesToBurn, marketIndex, {
|
|
789
|
+
accounts: {
|
|
790
|
+
state: await this.getStatePublicKey(),
|
|
791
|
+
user: userAccountPublicKey,
|
|
792
|
+
authority: this.wallet.publicKey,
|
|
793
|
+
},
|
|
794
|
+
remainingAccounts: remainingAccounts,
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
async addLiquidity(amount, marketIndex) {
|
|
798
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getAddLiquidityIx(amount, marketIndex)), [], this.opts);
|
|
799
|
+
this.marketLastSlotCache.set(marketIndex, slot);
|
|
474
800
|
return txSig;
|
|
475
801
|
}
|
|
476
|
-
async
|
|
477
|
-
const
|
|
478
|
-
|
|
802
|
+
async getAddLiquidityIx(amount, marketIndex) {
|
|
803
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
804
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
805
|
+
writablePerpMarketIndex: marketIndex,
|
|
806
|
+
});
|
|
807
|
+
return this.program.instruction.addLiquidity(amount, marketIndex, {
|
|
479
808
|
accounts: {
|
|
480
|
-
|
|
809
|
+
state: await this.getStatePublicKey(),
|
|
810
|
+
user: userAccountPublicKey,
|
|
811
|
+
authority: this.wallet.publicKey,
|
|
481
812
|
},
|
|
813
|
+
remainingAccounts: remainingAccounts,
|
|
482
814
|
});
|
|
483
815
|
}
|
|
484
816
|
async openPosition(direction, amount, marketIndex, limitPrice) {
|
|
485
|
-
return await this.placeAndTake(
|
|
817
|
+
return await this.placeAndTake({
|
|
818
|
+
orderType: types_1.OrderType.MARKET,
|
|
819
|
+
marketIndex,
|
|
820
|
+
direction,
|
|
821
|
+
baseAssetAmount: amount,
|
|
822
|
+
price: limitPrice,
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
async sendSignedTx(tx) {
|
|
826
|
+
const { txSig } = await this.txSender.send(tx, undefined, this.opts, true);
|
|
827
|
+
return txSig;
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* 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.
|
|
831
|
+
* @param orderParams
|
|
832
|
+
* @param userAccountPublicKey
|
|
833
|
+
* @param userAccount
|
|
834
|
+
* @returns
|
|
835
|
+
*/
|
|
836
|
+
async sendMarketOrderAndGetSignedFillTx(orderParams, userAccountPublicKey, userAccount) {
|
|
837
|
+
const marketIndex = orderParams.marketIndex;
|
|
838
|
+
const orderId = userAccount.nextOrderId;
|
|
839
|
+
const marketOrderTx = (0, utils_1.wrapInTx)(await this.getPlaceOrderIx(orderParams));
|
|
840
|
+
const fillTx = (0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, userAccount, {
|
|
841
|
+
orderId,
|
|
842
|
+
marketIndex,
|
|
843
|
+
}));
|
|
844
|
+
// Apply the latest blockhash to the txs so that we can sign before sending them
|
|
845
|
+
const currentBlockHash = (await this.connection.getLatestBlockhash('finalized')).blockhash;
|
|
846
|
+
marketOrderTx.recentBlockhash = currentBlockHash;
|
|
847
|
+
fillTx.recentBlockhash = currentBlockHash;
|
|
848
|
+
marketOrderTx.feePayer = userAccount.authority;
|
|
849
|
+
fillTx.feePayer = userAccount.authority;
|
|
850
|
+
const [signedMarketOrderTx, signedFillTx] = await this.provider.wallet.signAllTransactions([marketOrderTx, fillTx]);
|
|
851
|
+
const { txSig, slot } = await this.txSender.send(signedMarketOrderTx, [], this.opts, true);
|
|
852
|
+
this.marketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
853
|
+
return { txSig, signedFillTx };
|
|
486
854
|
}
|
|
487
855
|
async placeOrder(orderParams) {
|
|
488
856
|
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceOrderIx(orderParams)), [], this.opts);
|
|
489
|
-
this.marketLastSlotCache.set(orderParams.marketIndex
|
|
857
|
+
this.marketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
490
858
|
return txSig;
|
|
491
859
|
}
|
|
860
|
+
getOrderParams(optionalOrderParams, marketType) {
|
|
861
|
+
return Object.assign({}, types_1.DefaultOrderParams, optionalOrderParams, {
|
|
862
|
+
marketType,
|
|
863
|
+
});
|
|
864
|
+
}
|
|
492
865
|
async getPlaceOrderIx(orderParams) {
|
|
866
|
+
orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
|
|
493
867
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
494
868
|
const remainingAccounts = this.getRemainingAccounts({
|
|
495
|
-
|
|
869
|
+
readablePerpMarketIndex: orderParams.marketIndex,
|
|
496
870
|
});
|
|
497
871
|
return await this.program.instruction.placeOrder(orderParams, {
|
|
498
872
|
accounts: {
|
|
499
873
|
state: await this.getStatePublicKey(),
|
|
500
874
|
user: userAccountPublicKey,
|
|
875
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
501
876
|
authority: this.wallet.publicKey,
|
|
502
877
|
},
|
|
503
878
|
remainingAccounts,
|
|
@@ -509,13 +884,13 @@ class ClearingHouse {
|
|
|
509
884
|
}
|
|
510
885
|
async getUpdateAMMsIx(marketIndexes) {
|
|
511
886
|
for (let i = marketIndexes.length; i < 5; i++) {
|
|
512
|
-
marketIndexes.push(
|
|
887
|
+
marketIndexes.push(100);
|
|
513
888
|
}
|
|
514
889
|
const marketAccountInfos = [];
|
|
515
890
|
const oracleAccountInfos = [];
|
|
516
891
|
for (const marketIndex of marketIndexes) {
|
|
517
|
-
if (
|
|
518
|
-
const market = this.
|
|
892
|
+
if (marketIndex !== 100) {
|
|
893
|
+
const market = this.getPerpMarketAccount(marketIndex);
|
|
519
894
|
marketAccountInfos.push({
|
|
520
895
|
pubkey: market.pubkey,
|
|
521
896
|
isWritable: true,
|
|
@@ -537,6 +912,41 @@ class ClearingHouse {
|
|
|
537
912
|
remainingAccounts,
|
|
538
913
|
});
|
|
539
914
|
}
|
|
915
|
+
async settleExpiredMarket(marketIndex) {
|
|
916
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getSettleExpiredMarketIx(marketIndex)), [], this.opts);
|
|
917
|
+
return txSig;
|
|
918
|
+
}
|
|
919
|
+
async getSettleExpiredMarketIx(marketIndex) {
|
|
920
|
+
const marketAccountInfos = [];
|
|
921
|
+
const oracleAccountInfos = [];
|
|
922
|
+
const spotMarketAccountInfos = [];
|
|
923
|
+
const market = this.getPerpMarketAccount(marketIndex);
|
|
924
|
+
marketAccountInfos.push({
|
|
925
|
+
pubkey: market.pubkey,
|
|
926
|
+
isWritable: true,
|
|
927
|
+
isSigner: false,
|
|
928
|
+
});
|
|
929
|
+
oracleAccountInfos.push({
|
|
930
|
+
pubkey: market.amm.oracle,
|
|
931
|
+
isWritable: false,
|
|
932
|
+
isSigner: false,
|
|
933
|
+
});
|
|
934
|
+
spotMarketAccountInfos.push({
|
|
935
|
+
pubkey: this.getSpotMarketAccount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX).pubkey,
|
|
936
|
+
isSigner: false,
|
|
937
|
+
isWritable: true,
|
|
938
|
+
});
|
|
939
|
+
const remainingAccounts = oracleAccountInfos
|
|
940
|
+
.concat(spotMarketAccountInfos)
|
|
941
|
+
.concat(marketAccountInfos);
|
|
942
|
+
return await this.program.instruction.settleExpiredMarket(marketIndex, {
|
|
943
|
+
accounts: {
|
|
944
|
+
state: await this.getStatePublicKey(),
|
|
945
|
+
authority: this.wallet.publicKey,
|
|
946
|
+
},
|
|
947
|
+
remainingAccounts,
|
|
948
|
+
});
|
|
949
|
+
}
|
|
540
950
|
async cancelOrder(orderId) {
|
|
541
951
|
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getCancelOrderIx(orderId)), [], this.opts);
|
|
542
952
|
return txSig;
|
|
@@ -560,7 +970,7 @@ class ClearingHouse {
|
|
|
560
970
|
async getCancelOrderByUserIdIx(userOrderId) {
|
|
561
971
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
562
972
|
const order = this.getOrderByUserId(userOrderId);
|
|
563
|
-
const oracle = this.
|
|
973
|
+
const oracle = this.getPerpMarketAccount(order.marketIndex).amm.oracle;
|
|
564
974
|
const remainingAccounts = this.getRemainingAccounts({});
|
|
565
975
|
return await this.program.instruction.cancelOrderByUserId(userOrderId, {
|
|
566
976
|
accounts: {
|
|
@@ -572,58 +982,92 @@ class ClearingHouse {
|
|
|
572
982
|
remainingAccounts,
|
|
573
983
|
});
|
|
574
984
|
}
|
|
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);
|
|
985
|
+
async fillOrder(userAccountPublicKey, user, order, makerInfo, referrerInfo) {
|
|
986
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo, referrerInfo)), [], this.opts);
|
|
577
987
|
return txSig;
|
|
578
988
|
}
|
|
579
|
-
async getFillOrderIx(userAccountPublicKey, userAccount, order, makerInfo) {
|
|
989
|
+
async getFillOrderIx(userAccountPublicKey, userAccount, order, makerInfo, referrerInfo) {
|
|
990
|
+
const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
|
|
580
991
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
581
|
-
const
|
|
582
|
-
const
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
992
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
993
|
+
const marketIndex = order
|
|
994
|
+
? order.marketIndex
|
|
995
|
+
: userAccount.orders.find((order) => order.orderId.eq(userAccount.nextOrderId.sub(numericConstants_1.ONE))).marketIndex;
|
|
996
|
+
const marketAccount = this.getPerpMarketAccount(marketIndex);
|
|
997
|
+
const oracleAccountMap = new Map();
|
|
998
|
+
const spotMarketAccountMap = new Map();
|
|
999
|
+
const perpMarketAccountMap = new Map();
|
|
1000
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
1001
|
+
if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
1002
|
+
const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1003
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
1004
|
+
pubkey: spotMarketAccount.pubkey,
|
|
1005
|
+
isSigner: false,
|
|
1006
|
+
isWritable: false,
|
|
1007
|
+
});
|
|
1008
|
+
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1009
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
1010
|
+
pubkey: spotMarketAccount.oracle,
|
|
1011
|
+
isSigner: false,
|
|
1012
|
+
isWritable: false,
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
for (const position of userAccount.perpPositions) {
|
|
605
1018
|
if (!(0, position_1.positionIsAvailable)(position) &&
|
|
606
|
-
|
|
607
|
-
const market = this.
|
|
608
|
-
|
|
1019
|
+
position.marketIndex !== order.marketIndex) {
|
|
1020
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1021
|
+
perpMarketAccountMap.set(position.marketIndex, {
|
|
609
1022
|
pubkey: market.pubkey,
|
|
610
1023
|
isWritable: false,
|
|
611
1024
|
isSigner: false,
|
|
612
1025
|
});
|
|
613
|
-
|
|
1026
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
614
1027
|
pubkey: market.amm.oracle,
|
|
615
1028
|
isWritable: false,
|
|
616
1029
|
isSigner: false,
|
|
617
1030
|
});
|
|
618
1031
|
}
|
|
619
1032
|
}
|
|
620
|
-
|
|
1033
|
+
perpMarketAccountMap.set(marketIndex, {
|
|
1034
|
+
pubkey: marketAccount.pubkey,
|
|
1035
|
+
isWritable: true,
|
|
1036
|
+
isSigner: false,
|
|
1037
|
+
});
|
|
1038
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1039
|
+
pubkey: marketAccount.amm.oracle,
|
|
1040
|
+
isWritable: false,
|
|
1041
|
+
isSigner: false,
|
|
1042
|
+
});
|
|
1043
|
+
const remainingAccounts = [
|
|
1044
|
+
...oracleAccountMap.values(),
|
|
1045
|
+
...spotMarketAccountMap.values(),
|
|
1046
|
+
...perpMarketAccountMap.values(),
|
|
1047
|
+
];
|
|
621
1048
|
if (makerInfo) {
|
|
622
1049
|
remainingAccounts.push({
|
|
623
1050
|
pubkey: makerInfo.maker,
|
|
624
1051
|
isWritable: true,
|
|
625
1052
|
isSigner: false,
|
|
626
1053
|
});
|
|
1054
|
+
remainingAccounts.push({
|
|
1055
|
+
pubkey: makerInfo.makerStats,
|
|
1056
|
+
isWritable: true,
|
|
1057
|
+
isSigner: false,
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
if (referrerInfo) {
|
|
1061
|
+
remainingAccounts.push({
|
|
1062
|
+
pubkey: referrerInfo.referrer,
|
|
1063
|
+
isWritable: true,
|
|
1064
|
+
isSigner: false,
|
|
1065
|
+
});
|
|
1066
|
+
remainingAccounts.push({
|
|
1067
|
+
pubkey: referrerInfo.referrerStats,
|
|
1068
|
+
isWritable: true,
|
|
1069
|
+
isSigner: false,
|
|
1070
|
+
});
|
|
627
1071
|
}
|
|
628
1072
|
const orderId = order.orderId;
|
|
629
1073
|
const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
|
|
@@ -631,58 +1075,283 @@ class ClearingHouse {
|
|
|
631
1075
|
accounts: {
|
|
632
1076
|
state: await this.getStatePublicKey(),
|
|
633
1077
|
filler: fillerPublicKey,
|
|
1078
|
+
fillerStats: fillerStatsPublicKey,
|
|
634
1079
|
user: userAccountPublicKey,
|
|
1080
|
+
userStats: userStatsPublicKey,
|
|
635
1081
|
authority: this.wallet.publicKey,
|
|
636
1082
|
},
|
|
637
1083
|
remainingAccounts,
|
|
638
1084
|
});
|
|
639
1085
|
}
|
|
640
|
-
async
|
|
641
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.
|
|
1086
|
+
async placeSpotOrder(orderParams) {
|
|
1087
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceSpotOrderIx(orderParams)), [], this.opts);
|
|
642
1088
|
return txSig;
|
|
643
1089
|
}
|
|
644
|
-
async
|
|
645
|
-
|
|
646
|
-
const
|
|
647
|
-
const
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
1090
|
+
async getPlaceSpotOrderIx(orderParams) {
|
|
1091
|
+
orderParams = this.getOrderParams(orderParams, types_1.MarketType.SPOT);
|
|
1092
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1093
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1094
|
+
readableSpotMarketIndex: orderParams.marketIndex,
|
|
1095
|
+
});
|
|
1096
|
+
return await this.program.instruction.placeSpotOrder(orderParams, {
|
|
1097
|
+
accounts: {
|
|
1098
|
+
state: await this.getStatePublicKey(),
|
|
1099
|
+
user: userAccountPublicKey,
|
|
1100
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
1101
|
+
authority: this.wallet.publicKey,
|
|
653
1102
|
},
|
|
1103
|
+
remainingAccounts,
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
1106
|
+
async fillSpotOrder(userAccountPublicKey, user, order, fulfillmentConfig, makerInfo, referrerInfo) {
|
|
1107
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillSpotOrderIx(userAccountPublicKey, user, order, fulfillmentConfig, makerInfo, referrerInfo)), [], this.opts);
|
|
1108
|
+
return txSig;
|
|
1109
|
+
}
|
|
1110
|
+
async getFillSpotOrderIx(userAccountPublicKey, userAccount, order, fulfillmentConfig, makerInfo, referrerInfo) {
|
|
1111
|
+
const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
|
|
1112
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1113
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1114
|
+
const marketIndex = order
|
|
1115
|
+
? order.marketIndex
|
|
1116
|
+
: userAccount.orders.find((order) => order.orderId.eq(userAccount.nextOrderId.sub(numericConstants_1.ONE))).marketIndex;
|
|
1117
|
+
const oracleAccountMap = new Map();
|
|
1118
|
+
const spotMarketAccountMap = new Map();
|
|
1119
|
+
const perpMarketAccountMap = new Map();
|
|
1120
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
1121
|
+
if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
1122
|
+
const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1123
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
1124
|
+
pubkey: spotMarket.pubkey,
|
|
1125
|
+
isSigner: false,
|
|
1126
|
+
isWritable: false,
|
|
1127
|
+
});
|
|
1128
|
+
if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1129
|
+
oracleAccountMap.set(spotMarket.oracle.toString(), {
|
|
1130
|
+
pubkey: spotMarket.oracle,
|
|
1131
|
+
isSigner: false,
|
|
1132
|
+
isWritable: false,
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
for (const position of userAccount.perpPositions) {
|
|
1138
|
+
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
1139
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1140
|
+
perpMarketAccountMap.set(position.marketIndex, {
|
|
1141
|
+
pubkey: market.pubkey,
|
|
1142
|
+
isWritable: false,
|
|
1143
|
+
isSigner: false,
|
|
1144
|
+
});
|
|
1145
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1146
|
+
pubkey: market.amm.oracle,
|
|
1147
|
+
isWritable: false,
|
|
1148
|
+
isSigner: false,
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
1153
|
+
spotMarketAccountMap.set(marketIndex, {
|
|
1154
|
+
pubkey: spotMarketAccount.pubkey,
|
|
1155
|
+
isWritable: true,
|
|
1156
|
+
isSigner: false,
|
|
1157
|
+
});
|
|
1158
|
+
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1159
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
1160
|
+
pubkey: spotMarketAccount.oracle,
|
|
1161
|
+
isWritable: false,
|
|
1162
|
+
isSigner: false,
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
const quoteMarketAccount = this.getQuoteSpotMarketAccount();
|
|
1166
|
+
spotMarketAccountMap.set(quoteMarketAccount.marketIndex, {
|
|
1167
|
+
pubkey: quoteMarketAccount.pubkey,
|
|
1168
|
+
isWritable: true,
|
|
1169
|
+
isSigner: false,
|
|
1170
|
+
});
|
|
1171
|
+
const remainingAccounts = [
|
|
1172
|
+
...oracleAccountMap.values(),
|
|
1173
|
+
...spotMarketAccountMap.values(),
|
|
1174
|
+
...perpMarketAccountMap.values(),
|
|
654
1175
|
];
|
|
655
|
-
|
|
656
|
-
{
|
|
657
|
-
pubkey:
|
|
1176
|
+
if (makerInfo) {
|
|
1177
|
+
remainingAccounts.push({
|
|
1178
|
+
pubkey: makerInfo.maker,
|
|
658
1179
|
isWritable: true,
|
|
659
1180
|
isSigner: false,
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
1181
|
+
});
|
|
1182
|
+
remainingAccounts.push({
|
|
1183
|
+
pubkey: makerInfo.makerStats,
|
|
1184
|
+
isWritable: true,
|
|
1185
|
+
isSigner: false,
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
if (referrerInfo) {
|
|
1189
|
+
remainingAccounts.push({
|
|
1190
|
+
pubkey: referrerInfo.referrer,
|
|
1191
|
+
isWritable: true,
|
|
1192
|
+
isSigner: false,
|
|
1193
|
+
});
|
|
1194
|
+
remainingAccounts.push({
|
|
1195
|
+
pubkey: referrerInfo.referrerStats,
|
|
1196
|
+
isWritable: true,
|
|
1197
|
+
isSigner: false,
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
const orderId = order.orderId;
|
|
1201
|
+
const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
|
|
1202
|
+
if (fulfillmentConfig) {
|
|
1203
|
+
remainingAccounts.push({
|
|
1204
|
+
pubkey: fulfillmentConfig.pubkey,
|
|
1205
|
+
isWritable: false,
|
|
1206
|
+
isSigner: false,
|
|
1207
|
+
});
|
|
1208
|
+
remainingAccounts.push({
|
|
1209
|
+
pubkey: fulfillmentConfig.serumProgramId,
|
|
665
1210
|
isWritable: false,
|
|
666
1211
|
isSigner: false,
|
|
1212
|
+
});
|
|
1213
|
+
remainingAccounts.push({
|
|
1214
|
+
pubkey: fulfillmentConfig.serumMarket,
|
|
1215
|
+
isWritable: true,
|
|
1216
|
+
isSigner: false,
|
|
1217
|
+
});
|
|
1218
|
+
remainingAccounts.push({
|
|
1219
|
+
pubkey: fulfillmentConfig.serumRequestQueue,
|
|
1220
|
+
isWritable: true,
|
|
1221
|
+
isSigner: false,
|
|
1222
|
+
});
|
|
1223
|
+
remainingAccounts.push({
|
|
1224
|
+
pubkey: fulfillmentConfig.serumEventQueue,
|
|
1225
|
+
isWritable: true,
|
|
1226
|
+
isSigner: false,
|
|
1227
|
+
});
|
|
1228
|
+
remainingAccounts.push({
|
|
1229
|
+
pubkey: fulfillmentConfig.serumBids,
|
|
1230
|
+
isWritable: true,
|
|
1231
|
+
isSigner: false,
|
|
1232
|
+
});
|
|
1233
|
+
remainingAccounts.push({
|
|
1234
|
+
pubkey: fulfillmentConfig.serumAsks,
|
|
1235
|
+
isWritable: true,
|
|
1236
|
+
isSigner: false,
|
|
1237
|
+
});
|
|
1238
|
+
remainingAccounts.push({
|
|
1239
|
+
pubkey: fulfillmentConfig.serumBaseVault,
|
|
1240
|
+
isWritable: true,
|
|
1241
|
+
isSigner: false,
|
|
1242
|
+
});
|
|
1243
|
+
remainingAccounts.push({
|
|
1244
|
+
pubkey: fulfillmentConfig.serumQuoteVault,
|
|
1245
|
+
isWritable: true,
|
|
1246
|
+
isSigner: false,
|
|
1247
|
+
});
|
|
1248
|
+
remainingAccounts.push({
|
|
1249
|
+
pubkey: fulfillmentConfig.serumOpenOrders,
|
|
1250
|
+
isWritable: true,
|
|
1251
|
+
isSigner: false,
|
|
1252
|
+
});
|
|
1253
|
+
remainingAccounts.push({
|
|
1254
|
+
pubkey: (0, pda_1.getSerumSignerPublicKey)(fulfillmentConfig.serumProgramId, fulfillmentConfig.serumMarket, fulfillmentConfig.serumSignerNonce),
|
|
1255
|
+
isWritable: false,
|
|
1256
|
+
isSigner: false,
|
|
1257
|
+
});
|
|
1258
|
+
remainingAccounts.push({
|
|
1259
|
+
pubkey: this.getSignerPublicKey(),
|
|
1260
|
+
isWritable: false,
|
|
1261
|
+
isSigner: false,
|
|
1262
|
+
});
|
|
1263
|
+
remainingAccounts.push({
|
|
1264
|
+
pubkey: spl_token_1.TOKEN_PROGRAM_ID,
|
|
1265
|
+
isWritable: false,
|
|
1266
|
+
isSigner: false,
|
|
1267
|
+
});
|
|
1268
|
+
remainingAccounts.push({
|
|
1269
|
+
pubkey: spotMarketAccount.vault,
|
|
1270
|
+
isWritable: true,
|
|
1271
|
+
isSigner: false,
|
|
1272
|
+
});
|
|
1273
|
+
remainingAccounts.push({
|
|
1274
|
+
pubkey: quoteMarketAccount.vault,
|
|
1275
|
+
isWritable: true,
|
|
1276
|
+
isSigner: false,
|
|
1277
|
+
});
|
|
1278
|
+
remainingAccounts.push({
|
|
1279
|
+
pubkey: this.getStateAccount().srmVault,
|
|
1280
|
+
isWritable: false,
|
|
1281
|
+
isSigner: false,
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
return await this.program.instruction.fillSpotOrder(orderId, fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null, makerOrderId, {
|
|
1285
|
+
accounts: {
|
|
1286
|
+
state: await this.getStatePublicKey(),
|
|
1287
|
+
filler: fillerPublicKey,
|
|
1288
|
+
fillerStats: fillerStatsPublicKey,
|
|
1289
|
+
user: userAccountPublicKey,
|
|
1290
|
+
userStats: userStatsPublicKey,
|
|
1291
|
+
authority: this.wallet.publicKey,
|
|
667
1292
|
},
|
|
668
|
-
|
|
669
|
-
|
|
1293
|
+
remainingAccounts,
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
async triggerOrder(userAccountPublicKey, user, order) {
|
|
1297
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTriggerOrderIx(userAccountPublicKey, user, order)), [], this.opts);
|
|
1298
|
+
return txSig;
|
|
1299
|
+
}
|
|
1300
|
+
async getTriggerOrderIx(userAccountPublicKey, userAccount, order) {
|
|
1301
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1302
|
+
const marketIndex = order.marketIndex;
|
|
1303
|
+
const marketAccount = this.getPerpMarketAccount(marketIndex);
|
|
1304
|
+
const oracleAccountMap = new Map();
|
|
1305
|
+
const spotMarketAccountMap = new Map();
|
|
1306
|
+
const perpMarketAccountMap = new Map();
|
|
1307
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
1308
|
+
if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
1309
|
+
const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1310
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
1311
|
+
pubkey: spotMarketAccount.pubkey,
|
|
1312
|
+
isSigner: false,
|
|
1313
|
+
isWritable: false,
|
|
1314
|
+
});
|
|
1315
|
+
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1316
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
1317
|
+
pubkey: spotMarketAccount.oracle,
|
|
1318
|
+
isSigner: false,
|
|
1319
|
+
isWritable: false,
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
for (const position of userAccount.perpPositions) {
|
|
670
1325
|
if (!(0, position_1.positionIsAvailable)(position) &&
|
|
671
|
-
|
|
672
|
-
const market = this.
|
|
673
|
-
|
|
1326
|
+
position.marketIndex !== order.marketIndex) {
|
|
1327
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1328
|
+
perpMarketAccountMap.set(position.marketIndex, {
|
|
674
1329
|
pubkey: market.pubkey,
|
|
675
1330
|
isWritable: false,
|
|
676
1331
|
isSigner: false,
|
|
677
1332
|
});
|
|
678
|
-
|
|
1333
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
679
1334
|
pubkey: market.amm.oracle,
|
|
680
1335
|
isWritable: false,
|
|
681
1336
|
isSigner: false,
|
|
682
1337
|
});
|
|
683
1338
|
}
|
|
684
1339
|
}
|
|
685
|
-
|
|
1340
|
+
perpMarketAccountMap.set(marketIndex, {
|
|
1341
|
+
pubkey: marketAccount.pubkey,
|
|
1342
|
+
isWritable: true,
|
|
1343
|
+
isSigner: false,
|
|
1344
|
+
});
|
|
1345
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1346
|
+
pubkey: marketAccount.amm.oracle,
|
|
1347
|
+
isWritable: false,
|
|
1348
|
+
isSigner: false,
|
|
1349
|
+
});
|
|
1350
|
+
const remainingAccounts = [
|
|
1351
|
+
...oracleAccountMap.values(),
|
|
1352
|
+
...spotMarketAccountMap.values(),
|
|
1353
|
+
...perpMarketAccountMap.values(),
|
|
1354
|
+
];
|
|
686
1355
|
const orderId = order.orderId;
|
|
687
1356
|
return await this.program.instruction.triggerOrder(orderId, {
|
|
688
1357
|
accounts: {
|
|
@@ -694,16 +1363,94 @@ class ClearingHouse {
|
|
|
694
1363
|
remainingAccounts,
|
|
695
1364
|
});
|
|
696
1365
|
}
|
|
697
|
-
async
|
|
698
|
-
const { txSig
|
|
699
|
-
this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
|
|
1366
|
+
async triggerSpotOrder(userAccountPublicKey, user, order) {
|
|
1367
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTriggerSpotOrderIx(userAccountPublicKey, user, order)), [], this.opts);
|
|
700
1368
|
return txSig;
|
|
701
1369
|
}
|
|
702
|
-
async
|
|
1370
|
+
async getTriggerSpotOrderIx(userAccountPublicKey, userAccount, order) {
|
|
1371
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1372
|
+
const marketIndex = order.marketIndex;
|
|
1373
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
1374
|
+
const oracleAccountMap = new Map();
|
|
1375
|
+
const spotMarketAccountMap = new Map();
|
|
1376
|
+
const perpMarketAccountMap = new Map();
|
|
1377
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
1378
|
+
if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
1379
|
+
const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1380
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
1381
|
+
pubkey: spotMarketAccount.pubkey,
|
|
1382
|
+
isSigner: false,
|
|
1383
|
+
isWritable: false,
|
|
1384
|
+
});
|
|
1385
|
+
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1386
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
1387
|
+
pubkey: spotMarketAccount.oracle,
|
|
1388
|
+
isSigner: false,
|
|
1389
|
+
isWritable: false,
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
for (const position of userAccount.perpPositions) {
|
|
1395
|
+
if (!(0, position_1.positionIsAvailable)(position) &&
|
|
1396
|
+
position.marketIndex !== order.marketIndex) {
|
|
1397
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1398
|
+
perpMarketAccountMap.set(position.marketIndex, {
|
|
1399
|
+
pubkey: market.pubkey,
|
|
1400
|
+
isWritable: false,
|
|
1401
|
+
isSigner: false,
|
|
1402
|
+
});
|
|
1403
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1404
|
+
pubkey: market.amm.oracle,
|
|
1405
|
+
isWritable: false,
|
|
1406
|
+
isSigner: false,
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
const quoteSpotMarket = this.getQuoteSpotMarketAccount();
|
|
1411
|
+
spotMarketAccountMap.set(quoteSpotMarket.marketIndex, {
|
|
1412
|
+
pubkey: quoteSpotMarket.pubkey,
|
|
1413
|
+
isWritable: true,
|
|
1414
|
+
isSigner: false,
|
|
1415
|
+
});
|
|
1416
|
+
spotMarketAccountMap.set(marketIndex, {
|
|
1417
|
+
pubkey: spotMarketAccount.pubkey,
|
|
1418
|
+
isWritable: false,
|
|
1419
|
+
isSigner: false,
|
|
1420
|
+
});
|
|
1421
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
1422
|
+
pubkey: spotMarketAccount.oracle,
|
|
1423
|
+
isWritable: false,
|
|
1424
|
+
isSigner: false,
|
|
1425
|
+
});
|
|
1426
|
+
const remainingAccounts = [
|
|
1427
|
+
...oracleAccountMap.values(),
|
|
1428
|
+
...spotMarketAccountMap.values(),
|
|
1429
|
+
...perpMarketAccountMap.values(),
|
|
1430
|
+
];
|
|
1431
|
+
const orderId = order.orderId;
|
|
1432
|
+
return await this.program.instruction.triggerSpotOrder(orderId, {
|
|
1433
|
+
accounts: {
|
|
1434
|
+
state: await this.getStatePublicKey(),
|
|
1435
|
+
filler: fillerPublicKey,
|
|
1436
|
+
user: userAccountPublicKey,
|
|
1437
|
+
authority: this.wallet.publicKey,
|
|
1438
|
+
},
|
|
1439
|
+
remainingAccounts,
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
async placeAndTake(orderParams, makerInfo, referrerInfo) {
|
|
1443
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)), [], this.opts);
|
|
1444
|
+
this.marketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
1445
|
+
return txSig;
|
|
1446
|
+
}
|
|
1447
|
+
async getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo) {
|
|
1448
|
+
orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
|
|
1449
|
+
const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
|
|
703
1450
|
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
704
1451
|
const remainingAccounts = this.getRemainingAccounts({
|
|
705
|
-
|
|
706
|
-
|
|
1452
|
+
writablePerpMarketIndex: orderParams.marketIndex,
|
|
1453
|
+
writableSpotMarketIndex: numericConstants_1.QUOTE_SPOT_MARKET_INDEX,
|
|
707
1454
|
});
|
|
708
1455
|
let makerOrderId = null;
|
|
709
1456
|
if (makerInfo) {
|
|
@@ -713,11 +1460,68 @@ class ClearingHouse {
|
|
|
713
1460
|
isSigner: false,
|
|
714
1461
|
isWritable: true,
|
|
715
1462
|
});
|
|
1463
|
+
remainingAccounts.push({
|
|
1464
|
+
pubkey: makerInfo.makerStats,
|
|
1465
|
+
isSigner: false,
|
|
1466
|
+
isWritable: true,
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
if (referrerInfo) {
|
|
1470
|
+
remainingAccounts.push({
|
|
1471
|
+
pubkey: referrerInfo.referrer,
|
|
1472
|
+
isWritable: true,
|
|
1473
|
+
isSigner: false,
|
|
1474
|
+
});
|
|
1475
|
+
remainingAccounts.push({
|
|
1476
|
+
pubkey: referrerInfo.referrerStats,
|
|
1477
|
+
isWritable: true,
|
|
1478
|
+
isSigner: false,
|
|
1479
|
+
});
|
|
716
1480
|
}
|
|
717
1481
|
return await this.program.instruction.placeAndTake(orderParams, makerOrderId, {
|
|
718
1482
|
accounts: {
|
|
719
1483
|
state: await this.getStatePublicKey(),
|
|
720
1484
|
user: userAccountPublicKey,
|
|
1485
|
+
userStats: userStatsPublicKey,
|
|
1486
|
+
authority: this.wallet.publicKey,
|
|
1487
|
+
},
|
|
1488
|
+
remainingAccounts,
|
|
1489
|
+
});
|
|
1490
|
+
}
|
|
1491
|
+
async placeAndMake(orderParams, takerInfo, referrerInfo) {
|
|
1492
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo)), [], this.opts);
|
|
1493
|
+
this.marketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
1494
|
+
return txSig;
|
|
1495
|
+
}
|
|
1496
|
+
async getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo) {
|
|
1497
|
+
orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
|
|
1498
|
+
const userStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1499
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1500
|
+
// todo merge this with getRemainingAccounts
|
|
1501
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1502
|
+
counterPartyUserAccount: takerInfo.takerUserAccount,
|
|
1503
|
+
writablePerpMarketIndex: orderParams.marketIndex,
|
|
1504
|
+
});
|
|
1505
|
+
if (referrerInfo) {
|
|
1506
|
+
remainingAccounts.push({
|
|
1507
|
+
pubkey: referrerInfo.referrer,
|
|
1508
|
+
isWritable: true,
|
|
1509
|
+
isSigner: false,
|
|
1510
|
+
});
|
|
1511
|
+
remainingAccounts.push({
|
|
1512
|
+
pubkey: referrerInfo.referrerStats,
|
|
1513
|
+
isWritable: true,
|
|
1514
|
+
isSigner: false,
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
const takerOrderId = takerInfo.order.orderId;
|
|
1518
|
+
return await this.program.instruction.placeAndMake(orderParams, takerOrderId, {
|
|
1519
|
+
accounts: {
|
|
1520
|
+
state: await this.getStatePublicKey(),
|
|
1521
|
+
user: userAccountPublicKey,
|
|
1522
|
+
userStats: userStatsPublicKey,
|
|
1523
|
+
taker: takerInfo.taker,
|
|
1524
|
+
takerStats: takerInfo.takerStats,
|
|
721
1525
|
authority: this.wallet.publicKey,
|
|
722
1526
|
},
|
|
723
1527
|
remainingAccounts,
|
|
@@ -728,36 +1532,118 @@ class ClearingHouse {
|
|
|
728
1532
|
* @param marketIndex
|
|
729
1533
|
* @returns
|
|
730
1534
|
*/
|
|
731
|
-
async closePosition(marketIndex) {
|
|
1535
|
+
async closePosition(marketIndex, limitPrice) {
|
|
732
1536
|
const userPosition = this.getUser().getUserPosition(marketIndex);
|
|
733
1537
|
if (!userPosition) {
|
|
734
1538
|
throw Error(`No position in market ${marketIndex.toString()}`);
|
|
735
1539
|
}
|
|
736
|
-
return await this.placeAndTake(
|
|
1540
|
+
return await this.placeAndTake({
|
|
1541
|
+
orderType: types_1.OrderType.MARKET,
|
|
1542
|
+
marketIndex,
|
|
1543
|
+
direction: (0, position_1.findDirectionToClose)(userPosition),
|
|
1544
|
+
baseAssetAmount: userPosition.baseAssetAmount.abs(),
|
|
1545
|
+
reduceOnly: true,
|
|
1546
|
+
price: limitPrice,
|
|
1547
|
+
});
|
|
737
1548
|
}
|
|
738
1549
|
async settlePNLs(users, marketIndex) {
|
|
739
1550
|
const ixs = [];
|
|
740
1551
|
for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
|
|
741
1552
|
ixs.push(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex));
|
|
742
1553
|
}
|
|
743
|
-
const tx = new web3_js_1.Transaction()
|
|
1554
|
+
const tx = new web3_js_1.Transaction()
|
|
1555
|
+
.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
1556
|
+
units: 1000000,
|
|
1557
|
+
additionalFee: 0,
|
|
1558
|
+
}))
|
|
1559
|
+
.add(...ixs);
|
|
744
1560
|
const { txSig } = await this.txSender.send(tx, [], this.opts);
|
|
745
1561
|
return txSig;
|
|
746
1562
|
}
|
|
747
|
-
async settlePNL(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
|
|
748
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex)), [], this.opts);
|
|
1563
|
+
async settlePNL(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
|
|
1564
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex)), [], this.opts);
|
|
1565
|
+
return txSig;
|
|
1566
|
+
}
|
|
1567
|
+
async settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
|
|
1568
|
+
const perpMarketAccountMap = new Map();
|
|
1569
|
+
const oracleAccountMap = new Map();
|
|
1570
|
+
const spotMarketAccountMap = new Map();
|
|
1571
|
+
for (const position of settleeUserAccount.perpPositions) {
|
|
1572
|
+
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
1573
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1574
|
+
perpMarketAccountMap.set(position.marketIndex, {
|
|
1575
|
+
pubkey: market.pubkey,
|
|
1576
|
+
isWritable: false,
|
|
1577
|
+
isSigner: false,
|
|
1578
|
+
});
|
|
1579
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1580
|
+
pubkey: market.amm.oracle,
|
|
1581
|
+
isWritable: false,
|
|
1582
|
+
isSigner: false,
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
for (const spotPosition of settleeUserAccount.spotPositions) {
|
|
1587
|
+
if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
1588
|
+
const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1589
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
1590
|
+
pubkey: spotMarketAccount.pubkey,
|
|
1591
|
+
isSigner: false,
|
|
1592
|
+
isWritable: false,
|
|
1593
|
+
});
|
|
1594
|
+
if (spotMarketAccount.marketIndex !== 0) {
|
|
1595
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
1596
|
+
pubkey: spotMarketAccount.oracle,
|
|
1597
|
+
isSigner: false,
|
|
1598
|
+
isWritable: false,
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
const marketAccount = this.getPerpMarketAccount(marketIndex);
|
|
1604
|
+
perpMarketAccountMap.set(marketIndex, {
|
|
1605
|
+
pubkey: marketAccount.pubkey,
|
|
1606
|
+
isSigner: false,
|
|
1607
|
+
isWritable: true,
|
|
1608
|
+
});
|
|
1609
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1610
|
+
pubkey: marketAccount.amm.oracle,
|
|
1611
|
+
isSigner: false,
|
|
1612
|
+
isWritable: false,
|
|
1613
|
+
});
|
|
1614
|
+
spotMarketAccountMap.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, {
|
|
1615
|
+
pubkey: this.getSpotMarketAccount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX).pubkey,
|
|
1616
|
+
isSigner: false,
|
|
1617
|
+
isWritable: true,
|
|
1618
|
+
});
|
|
1619
|
+
const remainingAccounts = [
|
|
1620
|
+
...oracleAccountMap.values(),
|
|
1621
|
+
...spotMarketAccountMap.values(),
|
|
1622
|
+
...perpMarketAccountMap.values(),
|
|
1623
|
+
];
|
|
1624
|
+
return await this.program.instruction.settlePnl(marketIndex, {
|
|
1625
|
+
accounts: {
|
|
1626
|
+
state: await this.getStatePublicKey(),
|
|
1627
|
+
authority: this.wallet.publicKey,
|
|
1628
|
+
user: settleeUserAccountPublicKey,
|
|
1629
|
+
},
|
|
1630
|
+
remainingAccounts: remainingAccounts,
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
async settleExpiredPosition(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
|
|
1634
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getSettleExpiredPositionIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex)), [], this.opts);
|
|
749
1635
|
return txSig;
|
|
750
1636
|
}
|
|
751
|
-
async
|
|
1637
|
+
async getSettleExpiredPositionIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
|
|
752
1638
|
const marketAccountMap = new Map();
|
|
753
1639
|
const oracleAccountMap = new Map();
|
|
754
|
-
const
|
|
755
|
-
for (const position of settleeUserAccount.
|
|
1640
|
+
const spotMarketAccountMap = new Map();
|
|
1641
|
+
for (const position of settleeUserAccount.perpPositions) {
|
|
756
1642
|
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
757
|
-
const market = this.
|
|
758
|
-
marketAccountMap.set(position.marketIndex
|
|
1643
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1644
|
+
marketAccountMap.set(position.marketIndex, {
|
|
759
1645
|
pubkey: market.pubkey,
|
|
760
|
-
isWritable:
|
|
1646
|
+
isWritable: false,
|
|
761
1647
|
isSigner: false,
|
|
762
1648
|
});
|
|
763
1649
|
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
@@ -767,15 +1653,15 @@ class ClearingHouse {
|
|
|
767
1653
|
});
|
|
768
1654
|
}
|
|
769
1655
|
}
|
|
770
|
-
for (const userBankBalance of settleeUserAccount.
|
|
771
|
-
if (!userBankBalance.balance.eq(numericConstants_1.
|
|
772
|
-
const bankAccount = this.
|
|
773
|
-
|
|
1656
|
+
for (const userBankBalance of settleeUserAccount.spotPositions) {
|
|
1657
|
+
if (!userBankBalance.balance.eq(numericConstants_1.ZERO)) {
|
|
1658
|
+
const bankAccount = this.getSpotMarketAccount(userBankBalance.marketIndex);
|
|
1659
|
+
spotMarketAccountMap.set(userBankBalance.marketIndex, {
|
|
774
1660
|
pubkey: bankAccount.pubkey,
|
|
775
1661
|
isSigner: false,
|
|
776
1662
|
isWritable: false,
|
|
777
1663
|
});
|
|
778
|
-
if (
|
|
1664
|
+
if (bankAccount.marketIndex !== 0) {
|
|
779
1665
|
oracleAccountMap.set(bankAccount.oracle.toString(), {
|
|
780
1666
|
pubkey: bankAccount.oracle,
|
|
781
1667
|
isSigner: false,
|
|
@@ -784,8 +1670,8 @@ class ClearingHouse {
|
|
|
784
1670
|
}
|
|
785
1671
|
}
|
|
786
1672
|
}
|
|
787
|
-
const marketAccount = this.
|
|
788
|
-
marketAccountMap.set(marketIndex
|
|
1673
|
+
const marketAccount = this.getPerpMarketAccount(marketIndex);
|
|
1674
|
+
marketAccountMap.set(marketIndex, {
|
|
789
1675
|
pubkey: marketAccount.pubkey,
|
|
790
1676
|
isSigner: false,
|
|
791
1677
|
isWritable: true,
|
|
@@ -795,17 +1681,17 @@ class ClearingHouse {
|
|
|
795
1681
|
isSigner: false,
|
|
796
1682
|
isWritable: false,
|
|
797
1683
|
});
|
|
798
|
-
|
|
799
|
-
pubkey: this.
|
|
1684
|
+
spotMarketAccountMap.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, {
|
|
1685
|
+
pubkey: this.getSpotMarketAccount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX).pubkey,
|
|
800
1686
|
isSigner: false,
|
|
801
1687
|
isWritable: true,
|
|
802
1688
|
});
|
|
803
1689
|
const remainingAccounts = [
|
|
804
1690
|
...oracleAccountMap.values(),
|
|
805
|
-
...
|
|
1691
|
+
...spotMarketAccountMap.values(),
|
|
806
1692
|
...marketAccountMap.values(),
|
|
807
1693
|
];
|
|
808
|
-
return await this.program.instruction.
|
|
1694
|
+
return await this.program.instruction.settleExpiredPosition(marketIndex, {
|
|
809
1695
|
accounts: {
|
|
810
1696
|
state: await this.getStatePublicKey(),
|
|
811
1697
|
authority: this.wallet.publicKey,
|
|
@@ -814,54 +1700,275 @@ class ClearingHouse {
|
|
|
814
1700
|
remainingAccounts: remainingAccounts,
|
|
815
1701
|
});
|
|
816
1702
|
}
|
|
817
|
-
async
|
|
818
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.
|
|
1703
|
+
async liquidatePerp(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
|
|
1704
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount)), [], this.opts);
|
|
1705
|
+
this.marketLastSlotCache.set(marketIndex, slot);
|
|
819
1706
|
return txSig;
|
|
820
1707
|
}
|
|
821
|
-
async
|
|
822
|
-
const
|
|
823
|
-
const
|
|
824
|
-
const
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
1708
|
+
async getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
|
|
1709
|
+
const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
|
|
1710
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1711
|
+
const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1712
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1713
|
+
writablePerpMarketIndex: marketIndex,
|
|
1714
|
+
counterPartyUserAccount: userAccount,
|
|
1715
|
+
});
|
|
1716
|
+
return await this.program.instruction.liquidatePerp(marketIndex, maxBaseAssetAmount, {
|
|
1717
|
+
accounts: {
|
|
1718
|
+
state: await this.getStatePublicKey(),
|
|
1719
|
+
authority: this.wallet.publicKey,
|
|
1720
|
+
user: userAccountPublicKey,
|
|
1721
|
+
userStats: userStatsPublicKey,
|
|
1722
|
+
liquidator: liquidatorPublicKey,
|
|
1723
|
+
liquidatorStats: liquidatorStatsPublicKey,
|
|
829
1724
|
},
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
1725
|
+
remainingAccounts: remainingAccounts,
|
|
1726
|
+
});
|
|
1727
|
+
}
|
|
1728
|
+
async liquidateBorrow(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
|
|
1729
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateBorrowIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer)), [], this.opts);
|
|
1730
|
+
return txSig;
|
|
1731
|
+
}
|
|
1732
|
+
async getLiquidateBorrowIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
|
|
1733
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1734
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1735
|
+
counterPartyUserAccount: userAccount,
|
|
1736
|
+
writableSpotMarketIndexes: [liabilityMarketIndex, assetMarketIndex],
|
|
1737
|
+
});
|
|
1738
|
+
return await this.program.instruction.liquidateBorrow(assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer, {
|
|
1739
|
+
accounts: {
|
|
1740
|
+
state: await this.getStatePublicKey(),
|
|
1741
|
+
authority: this.wallet.publicKey,
|
|
1742
|
+
user: userAccountPublicKey,
|
|
1743
|
+
liquidator: liquidatorPublicKey,
|
|
1744
|
+
},
|
|
1745
|
+
remainingAccounts: remainingAccounts,
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
async liquidateBorrowForPerpPnl(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
|
|
1749
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer)), [], this.opts);
|
|
1750
|
+
this.marketLastSlotCache.set(perpMarketIndex, slot);
|
|
1751
|
+
return txSig;
|
|
1752
|
+
}
|
|
1753
|
+
async getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
|
|
1754
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1755
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1756
|
+
counterPartyUserAccount: userAccount,
|
|
1757
|
+
writablePerpMarketIndex: perpMarketIndex,
|
|
1758
|
+
writableSpotMarketIndexes: [liabilityMarketIndex],
|
|
1759
|
+
});
|
|
1760
|
+
return await this.program.instruction.liquidateBorrowForPerpPnl(perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer, {
|
|
1761
|
+
accounts: {
|
|
1762
|
+
state: await this.getStatePublicKey(),
|
|
1763
|
+
authority: this.wallet.publicKey,
|
|
1764
|
+
user: userAccountPublicKey,
|
|
1765
|
+
liquidator: liquidatorPublicKey,
|
|
1766
|
+
},
|
|
1767
|
+
remainingAccounts: remainingAccounts,
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1770
|
+
async liquidatePerpPnlForDeposit(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer) {
|
|
1771
|
+
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer)), [], this.opts);
|
|
1772
|
+
this.marketLastSlotCache.set(perpMarketIndex, slot);
|
|
1773
|
+
return txSig;
|
|
1774
|
+
}
|
|
1775
|
+
async getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer) {
|
|
1776
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1777
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1778
|
+
counterPartyUserAccount: userAccount,
|
|
1779
|
+
writablePerpMarketIndex: perpMarketIndex,
|
|
1780
|
+
writableSpotMarketIndexes: [assetMarketIndex],
|
|
1781
|
+
});
|
|
1782
|
+
return await this.program.instruction.liquidatePerpPnlForDeposit(perpMarketIndex, assetMarketIndex, maxPnlTransfer, {
|
|
1783
|
+
accounts: {
|
|
1784
|
+
state: await this.getStatePublicKey(),
|
|
1785
|
+
authority: this.wallet.publicKey,
|
|
1786
|
+
user: userAccountPublicKey,
|
|
1787
|
+
liquidator: liquidatorPublicKey,
|
|
1788
|
+
},
|
|
1789
|
+
remainingAccounts: remainingAccounts,
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
async resolvePerpBankruptcy(userAccountPublicKey, userAccount, marketIndex) {
|
|
1793
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolvePerpBankruptcyIx(userAccountPublicKey, userAccount, marketIndex)), [], this.opts);
|
|
1794
|
+
return txSig;
|
|
1795
|
+
}
|
|
1796
|
+
async getResolvePerpBankruptcyIx(userAccountPublicKey, userAccount, marketIndex) {
|
|
1797
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1798
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1799
|
+
writablePerpMarketIndex: marketIndex,
|
|
1800
|
+
writableSpotMarketIndexes: [numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
|
|
1801
|
+
counterPartyUserAccount: userAccount,
|
|
1802
|
+
});
|
|
1803
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
1804
|
+
return await this.program.instruction.resolvePerpBankruptcy(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, marketIndex, {
|
|
1805
|
+
accounts: {
|
|
1806
|
+
state: await this.getStatePublicKey(),
|
|
1807
|
+
authority: this.wallet.publicKey,
|
|
1808
|
+
user: userAccountPublicKey,
|
|
1809
|
+
liquidator: liquidatorPublicKey,
|
|
1810
|
+
spotMarketVault: spotMarket.vault,
|
|
1811
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
1812
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
1813
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
1814
|
+
},
|
|
1815
|
+
remainingAccounts: remainingAccounts,
|
|
1816
|
+
});
|
|
1817
|
+
}
|
|
1818
|
+
async resolveBorrowBankruptcy(userAccountPublicKey, userAccount, marketIndex) {
|
|
1819
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolveBorrowBankruptcyIx(userAccountPublicKey, userAccount, marketIndex)), [], this.opts);
|
|
1820
|
+
return txSig;
|
|
1821
|
+
}
|
|
1822
|
+
async getResolveBorrowBankruptcyIx(userAccountPublicKey, userAccount, marketIndex) {
|
|
1823
|
+
const liquidatorPublicKey = await this.getUserAccountPublicKey();
|
|
1824
|
+
const remainingAccounts = this.getRemainingAccountsWithCounterparty({
|
|
1825
|
+
writableSpotMarketIndexes: [marketIndex],
|
|
1826
|
+
counterPartyUserAccount: userAccount,
|
|
1827
|
+
});
|
|
1828
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
1829
|
+
return await this.program.instruction.resolveBorrowBankruptcy(marketIndex, {
|
|
1830
|
+
accounts: {
|
|
1831
|
+
state: await this.getStatePublicKey(),
|
|
1832
|
+
authority: this.wallet.publicKey,
|
|
1833
|
+
user: userAccountPublicKey,
|
|
1834
|
+
liquidator: liquidatorPublicKey,
|
|
1835
|
+
spotMarketVault: spotMarket.vault,
|
|
1836
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
1837
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
1838
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
1839
|
+
},
|
|
1840
|
+
remainingAccounts: remainingAccounts,
|
|
1841
|
+
});
|
|
1842
|
+
}
|
|
1843
|
+
getRemainingAccountsWithCounterparty(params) {
|
|
1844
|
+
const counterPartyUserAccount = params.counterPartyUserAccount;
|
|
1845
|
+
const oracleAccountMap = new Map();
|
|
1846
|
+
const spotMarketAccountMap = new Map();
|
|
1847
|
+
const marketAccountMap = new Map();
|
|
1848
|
+
for (const spotPosition of counterPartyUserAccount.spotPositions) {
|
|
1849
|
+
if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
1850
|
+
const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1851
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
1852
|
+
pubkey: spotMarket.pubkey,
|
|
1853
|
+
isSigner: false,
|
|
1854
|
+
isWritable: false,
|
|
1855
|
+
});
|
|
1856
|
+
if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1857
|
+
oracleAccountMap.set(spotMarket.oracle.toString(), {
|
|
1858
|
+
pubkey: spotMarket.oracle,
|
|
1859
|
+
isSigner: false,
|
|
1860
|
+
isWritable: false,
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
for (const position of counterPartyUserAccount.perpPositions) {
|
|
834
1866
|
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
835
|
-
const market = this.
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
isWritable: true,
|
|
1867
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1868
|
+
marketAccountMap.set(position.marketIndex, {
|
|
1869
|
+
pubkey: market.pubkey,
|
|
1870
|
+
isWritable: false,
|
|
840
1871
|
isSigner: false,
|
|
841
1872
|
});
|
|
842
|
-
|
|
1873
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
843
1874
|
pubkey: market.amm.oracle,
|
|
844
1875
|
isWritable: false,
|
|
845
1876
|
isSigner: false,
|
|
846
1877
|
});
|
|
847
1878
|
}
|
|
848
1879
|
}
|
|
849
|
-
const
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
1880
|
+
const userAccountAndSlot = this.getUserAccountAndSlot();
|
|
1881
|
+
if (!userAccountAndSlot) {
|
|
1882
|
+
throw Error('No user account found. Most likely user account does not exist or failed to fetch account');
|
|
1883
|
+
}
|
|
1884
|
+
const { data: userAccount, slot: lastUserPositionsSlot } = userAccountAndSlot;
|
|
1885
|
+
for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
|
|
1886
|
+
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
1887
|
+
// otherwise remove from slot
|
|
1888
|
+
if (slot > lastUserPositionsSlot) {
|
|
1889
|
+
const marketAccount = this.getPerpMarketAccount(marketIndexNum);
|
|
1890
|
+
marketAccountMap.set(marketIndexNum, {
|
|
1891
|
+
pubkey: marketAccount.pubkey,
|
|
1892
|
+
isSigner: false,
|
|
1893
|
+
isWritable: false,
|
|
1894
|
+
});
|
|
1895
|
+
oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
|
|
1896
|
+
pubkey: marketAccount.amm.oracle,
|
|
1897
|
+
isSigner: false,
|
|
1898
|
+
isWritable: false,
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
else {
|
|
1902
|
+
this.marketLastSlotCache.delete(marketIndexNum);
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
for (const spotPosition of userAccount.spotPositions) {
|
|
1906
|
+
if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
1907
|
+
const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1908
|
+
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
1909
|
+
pubkey: spotMarket.pubkey,
|
|
1910
|
+
isSigner: false,
|
|
1911
|
+
isWritable: false,
|
|
1912
|
+
});
|
|
1913
|
+
if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1914
|
+
oracleAccountMap.set(spotMarket.oracle.toString(), {
|
|
1915
|
+
pubkey: spotMarket.oracle,
|
|
1916
|
+
isSigner: false,
|
|
1917
|
+
isWritable: false,
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
for (const position of userAccount.perpPositions) {
|
|
1923
|
+
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
1924
|
+
const market = this.getPerpMarketAccount(position.marketIndex);
|
|
1925
|
+
marketAccountMap.set(position.marketIndex, {
|
|
1926
|
+
pubkey: market.pubkey,
|
|
1927
|
+
isWritable: false,
|
|
1928
|
+
isSigner: false,
|
|
1929
|
+
});
|
|
1930
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1931
|
+
pubkey: market.amm.oracle,
|
|
1932
|
+
isWritable: false,
|
|
1933
|
+
isSigner: false,
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
if (params.writablePerpMarketIndex !== undefined) {
|
|
1938
|
+
const market = this.getPerpMarketAccount(params.writablePerpMarketIndex);
|
|
1939
|
+
marketAccountMap.set(market.marketIndex, {
|
|
1940
|
+
pubkey: market.pubkey,
|
|
1941
|
+
isSigner: false,
|
|
1942
|
+
isWritable: true,
|
|
1943
|
+
});
|
|
1944
|
+
oracleAccountMap.set(market.amm.oracle.toString(), {
|
|
1945
|
+
pubkey: market.amm.oracle,
|
|
1946
|
+
isSigner: false,
|
|
1947
|
+
isWritable: false,
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
if (params.writableSpotMarketIndexes !== undefined) {
|
|
1951
|
+
for (const writableSpotMarketIndex of params.writableSpotMarketIndexes) {
|
|
1952
|
+
const spotMarketAccount = this.getSpotMarketAccount(writableSpotMarketIndex);
|
|
1953
|
+
spotMarketAccountMap.set(spotMarketAccount.marketIndex, {
|
|
1954
|
+
pubkey: spotMarketAccount.pubkey,
|
|
1955
|
+
isSigner: false,
|
|
1956
|
+
isWritable: true,
|
|
1957
|
+
});
|
|
1958
|
+
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
1959
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
1960
|
+
pubkey: spotMarketAccount.oracle,
|
|
1961
|
+
isSigner: false,
|
|
1962
|
+
isWritable: false,
|
|
1963
|
+
});
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
return [
|
|
1968
|
+
...oracleAccountMap.values(),
|
|
1969
|
+
...spotMarketAccountMap.values(),
|
|
1970
|
+
...marketAccountMap.values(),
|
|
1971
|
+
];
|
|
865
1972
|
}
|
|
866
1973
|
async updateFundingRate(oracle, marketIndex) {
|
|
867
1974
|
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateFundingRateIx(oracle, marketIndex)), [], this.opts);
|
|
@@ -882,7 +1989,7 @@ class ClearingHouse {
|
|
|
882
1989
|
}
|
|
883
1990
|
async getSettleFundingPaymentIx(userAccount) {
|
|
884
1991
|
const user = (await this.program.account.user.fetch(userAccount));
|
|
885
|
-
const userPositions = user.
|
|
1992
|
+
const userPositions = user.perpPositions;
|
|
886
1993
|
const remainingAccounts = [];
|
|
887
1994
|
for (const position of userPositions) {
|
|
888
1995
|
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
@@ -906,9 +2013,153 @@ class ClearingHouse {
|
|
|
906
2013
|
this.eventEmitter.emit(eventName, data);
|
|
907
2014
|
}
|
|
908
2015
|
getOracleDataForMarket(marketIndex) {
|
|
909
|
-
const oracleKey = this.
|
|
2016
|
+
const oracleKey = this.getPerpMarketAccount(marketIndex).amm.oracle;
|
|
2017
|
+
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
2018
|
+
return oracleData;
|
|
2019
|
+
}
|
|
2020
|
+
getOracleDataForSpotMarket(marketIndex) {
|
|
2021
|
+
const oracleKey = this.getSpotMarketAccount(marketIndex).oracle;
|
|
910
2022
|
const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
|
|
911
2023
|
return oracleData;
|
|
912
2024
|
}
|
|
2025
|
+
async initializeInsuranceFundStake(marketIndex) {
|
|
2026
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getInitializeInsuranceFundStakeIx(marketIndex)), [], this.opts);
|
|
2027
|
+
return txSig;
|
|
2028
|
+
}
|
|
2029
|
+
async getInitializeInsuranceFundStakeIx(marketIndex) {
|
|
2030
|
+
const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
|
|
2031
|
+
return await this.program.instruction.initializeInsuranceFundStake(marketIndex, {
|
|
2032
|
+
accounts: {
|
|
2033
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2034
|
+
spotMarket: this.getSpotMarketAccount(marketIndex).pubkey,
|
|
2035
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2036
|
+
authority: this.wallet.publicKey,
|
|
2037
|
+
payer: this.wallet.publicKey,
|
|
2038
|
+
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
|
2039
|
+
systemProgram: anchor.web3.SystemProgram.programId,
|
|
2040
|
+
state: await this.getStatePublicKey(),
|
|
2041
|
+
},
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
async addInsuranceFundStake(marketIndex, amount, collateralAccountPublicKey) {
|
|
2045
|
+
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
2046
|
+
const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
|
|
2047
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2048
|
+
writableSpotMarketIndex: marketIndex,
|
|
2049
|
+
});
|
|
2050
|
+
return await this.program.rpc.addInsuranceFundStake(marketIndex, amount, {
|
|
2051
|
+
accounts: {
|
|
2052
|
+
state: await this.getStatePublicKey(),
|
|
2053
|
+
spotMarket: spotMarket.pubkey,
|
|
2054
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2055
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2056
|
+
authority: this.wallet.publicKey,
|
|
2057
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
2058
|
+
userTokenAccount: collateralAccountPublicKey,
|
|
2059
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
2060
|
+
},
|
|
2061
|
+
remainingAccounts,
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
2064
|
+
async requestRemoveInsuranceFundStake(marketIndex, amount) {
|
|
2065
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2066
|
+
const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
|
|
2067
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2068
|
+
writableSpotMarketIndex: marketIndex,
|
|
2069
|
+
});
|
|
2070
|
+
return await this.program.rpc.requestRemoveInsuranceFundStake(marketIndex, amount, {
|
|
2071
|
+
accounts: {
|
|
2072
|
+
state: await this.getStatePublicKey(),
|
|
2073
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2074
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2075
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2076
|
+
authority: this.wallet.publicKey,
|
|
2077
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2078
|
+
// userTokenAccount: collateralAccountPublicKey,
|
|
2079
|
+
// tokenProgram: TOKEN_PROGRAM_ID,
|
|
2080
|
+
},
|
|
2081
|
+
remainingAccounts,
|
|
2082
|
+
});
|
|
2083
|
+
}
|
|
2084
|
+
async cancelRequestRemoveInsuranceFundStake(marketIndex) {
|
|
2085
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2086
|
+
const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
|
|
2087
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2088
|
+
writableSpotMarketIndex: marketIndex,
|
|
2089
|
+
});
|
|
2090
|
+
return await this.program.rpc.cancelRequestRemoveInsuranceFundStake(marketIndex, {
|
|
2091
|
+
accounts: {
|
|
2092
|
+
state: await this.getStatePublicKey(),
|
|
2093
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2094
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2095
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2096
|
+
authority: this.wallet.publicKey,
|
|
2097
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2098
|
+
// userTokenAccount: collateralAccountPublicKey,
|
|
2099
|
+
// tokenProgram: TOKEN_PROGRAM_ID,
|
|
2100
|
+
},
|
|
2101
|
+
remainingAccounts,
|
|
2102
|
+
});
|
|
2103
|
+
}
|
|
2104
|
+
async removeInsuranceFundStake(marketIndex, collateralAccountPublicKey) {
|
|
2105
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2106
|
+
const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
|
|
2107
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2108
|
+
writableSpotMarketIndex: marketIndex,
|
|
2109
|
+
});
|
|
2110
|
+
return await this.program.rpc.removeInsuranceFundStake(marketIndex, {
|
|
2111
|
+
accounts: {
|
|
2112
|
+
state: await this.getStatePublicKey(),
|
|
2113
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2114
|
+
insuranceFundStake: ifStakeAccountPublicKey,
|
|
2115
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2116
|
+
authority: this.wallet.publicKey,
|
|
2117
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2118
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2119
|
+
userTokenAccount: collateralAccountPublicKey,
|
|
2120
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
2121
|
+
},
|
|
2122
|
+
remainingAccounts,
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
async settleRevenueToInsuranceFund(marketIndex) {
|
|
2126
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
2127
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2128
|
+
writableSpotMarketIndex: marketIndex,
|
|
2129
|
+
});
|
|
2130
|
+
return await this.program.rpc.settleRevenueToInsuranceFund(marketIndex, {
|
|
2131
|
+
accounts: {
|
|
2132
|
+
state: await this.getStatePublicKey(),
|
|
2133
|
+
spotMarket: spotMarketAccount.pubkey,
|
|
2134
|
+
spotMarketVault: spotMarketAccount.vault,
|
|
2135
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2136
|
+
insuranceFundVault: spotMarketAccount.insuranceFundVault,
|
|
2137
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
2138
|
+
},
|
|
2139
|
+
remainingAccounts,
|
|
2140
|
+
});
|
|
2141
|
+
}
|
|
2142
|
+
async resolvePerpPnlDeficit(spotMarketIndex, perpMarketIndex) {
|
|
2143
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolvePerpPnlDeficitIx(spotMarketIndex, perpMarketIndex)), [], this.opts);
|
|
2144
|
+
return txSig;
|
|
2145
|
+
}
|
|
2146
|
+
async getResolvePerpPnlDeficitIx(spotMarketIndex, perpMarketIndex) {
|
|
2147
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2148
|
+
writablePerpMarketIndex: perpMarketIndex,
|
|
2149
|
+
writableSpotMarketIndex: spotMarketIndex,
|
|
2150
|
+
});
|
|
2151
|
+
const spotMarket = this.getSpotMarketAccount(spotMarketIndex);
|
|
2152
|
+
return await this.program.instruction.resolvePerpPnlDeficit(spotMarketIndex, perpMarketIndex, {
|
|
2153
|
+
accounts: {
|
|
2154
|
+
state: await this.getStatePublicKey(),
|
|
2155
|
+
authority: this.wallet.publicKey,
|
|
2156
|
+
spotMarketVault: spotMarket.vault,
|
|
2157
|
+
insuranceFundVault: spotMarket.insuranceFundVault,
|
|
2158
|
+
clearingHouseSigner: this.getSignerPublicKey(),
|
|
2159
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
2160
|
+
},
|
|
2161
|
+
remainingAccounts: remainingAccounts,
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
913
2164
|
}
|
|
914
2165
|
exports.ClearingHouse = ClearingHouse;
|