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