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