@drift-labs/sdk 0.2.0-master.3 → 0.2.0-master.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -13
- package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
- package/lib/accounts/bulkUserStatsSubscription.js +21 -0
- package/lib/accounts/bulkUserSubscription.js +0 -1
- package/lib/accounts/fetch.d.ts +2 -1
- package/lib/accounts/fetch.js +9 -1
- package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +16 -16
- package/lib/accounts/pollingClearingHouseAccountSubscriber.js +31 -28
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
- package/lib/accounts/types.d.ts +22 -11
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +17 -17
- package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +37 -35
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
- package/lib/addresses/marketAddresses.d.ts +1 -3
- package/lib/addresses/pda.d.ts +10 -4
- package/lib/addresses/pda.js +51 -14
- package/lib/admin.d.ts +42 -26
- package/lib/admin.js +228 -81
- package/lib/clearingHouse.d.ts +130 -49
- package/lib/clearingHouse.js +1256 -367
- package/lib/clearingHouseConfig.d.ts +4 -4
- package/lib/clearingHouseUser.d.ts +51 -39
- package/lib/clearingHouseUser.js +408 -191
- package/lib/clearingHouseUserStats.d.ts +18 -0
- package/lib/clearingHouseUserStats.js +49 -0
- package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
- package/lib/clearingHouseUserStatsConfig.js +2 -0
- package/lib/config.d.ts +7 -9
- package/lib/config.js +21 -21
- package/lib/constants/numericConstants.d.ts +25 -12
- package/lib/constants/numericConstants.js +35 -21
- package/lib/constants/perpMarkets.d.ts +18 -0
- package/lib/constants/{markets.js → perpMarkets.js} +7 -7
- package/lib/constants/spotMarkets.d.ts +19 -0
- package/lib/constants/spotMarkets.js +53 -0
- package/lib/dlob/DLOB.d.ts +74 -0
- package/lib/dlob/DLOB.js +595 -0
- package/lib/dlob/DLOBNode.d.ts +54 -0
- package/lib/dlob/DLOBNode.js +85 -0
- package/lib/dlob/NodeList.d.ts +26 -0
- package/lib/dlob/NodeList.js +139 -0
- package/lib/events/eventList.js +3 -0
- package/lib/events/eventSubscriber.d.ts +4 -2
- package/lib/events/eventSubscriber.js +16 -9
- package/lib/events/fetchLogs.d.ts +10 -1
- package/lib/events/fetchLogs.js +27 -7
- package/lib/events/pollingLogProvider.d.ts +2 -1
- package/lib/events/pollingLogProvider.js +6 -2
- package/lib/events/sort.js +8 -11
- package/lib/events/types.d.ts +8 -2
- package/lib/events/types.js +6 -0
- package/lib/examples/makeTradeExample.js +20 -8
- package/lib/factory/bigNum.d.ts +2 -0
- package/lib/factory/bigNum.js +48 -10
- package/lib/idl/clearing_house.json +4889 -1529
- package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/lib/index.d.ts +21 -6
- package/lib/index.js +25 -6
- package/lib/math/amm.d.ts +9 -6
- package/lib/math/amm.js +91 -66
- package/lib/math/auction.js +4 -1
- package/lib/math/conversion.js +1 -1
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.js +11 -10
- package/lib/math/insurance.d.ts +4 -0
- package/lib/math/insurance.js +27 -0
- package/lib/math/margin.d.ts +11 -0
- package/lib/math/margin.js +77 -0
- package/lib/math/market.d.ts +14 -9
- package/lib/math/market.js +72 -10
- package/lib/math/oracles.d.ts +4 -0
- package/lib/math/oracles.js +36 -8
- package/lib/math/orders.d.ts +6 -2
- package/lib/math/orders.js +78 -3
- package/lib/math/position.d.ts +21 -13
- package/lib/math/position.js +76 -36
- package/lib/math/repeg.js +14 -5
- package/lib/math/spotBalance.d.ts +22 -0
- package/lib/math/spotBalance.js +192 -0
- package/lib/math/spotMarket.d.ts +4 -0
- package/lib/math/spotMarket.js +8 -0
- package/lib/math/spotPosition.d.ts +6 -0
- package/lib/math/spotPosition.js +23 -0
- package/lib/math/trade.d.ts +10 -10
- package/lib/math/trade.js +32 -39
- package/lib/oracles/pythClient.js +1 -1
- package/lib/oracles/quoteAssetOracleClient.js +1 -1
- package/lib/oracles/switchboardClient.js +1 -1
- package/lib/orderParams.d.ts +14 -5
- package/lib/orderParams.js +12 -92
- package/lib/serum/serumSubscriber.d.ts +23 -0
- package/lib/serum/serumSubscriber.js +41 -0
- package/lib/serum/types.d.ts +11 -0
- package/lib/serum/types.js +2 -0
- package/lib/slot/SlotSubscriber.d.ts +7 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
- package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
- package/lib/tx/retryTxSender.d.ts +1 -1
- package/lib/tx/retryTxSender.js +13 -4
- package/lib/tx/types.d.ts +1 -1
- package/lib/tx/utils.js +1 -1
- package/lib/types.d.ts +566 -138
- package/lib/types.js +129 -5
- package/lib/userMap/userMap.d.ts +25 -0
- package/lib/userMap/userMap.js +73 -0
- package/lib/userMap/userStatsMap.d.ts +19 -0
- package/lib/userMap/userStatsMap.js +68 -0
- package/lib/util/computeUnits.js +1 -1
- package/lib/util/getTokenAddress.d.ts +2 -0
- package/lib/util/getTokenAddress.js +9 -0
- package/package.json +12 -6
- package/src/accounts/bulkUserStatsSubscription.ts +33 -0
- package/src/accounts/bulkUserSubscription.ts +0 -1
- package/src/accounts/fetch.ts +27 -2
- package/src/accounts/pollingClearingHouseAccountSubscriber.ts +46 -42
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
- package/src/accounts/types.ts +31 -11
- package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +64 -59
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
- package/src/addresses/marketAddresses.ts +1 -2
- package/src/addresses/pda.ts +88 -14
- package/src/admin.ts +452 -147
- package/src/assert/assert.js +9 -0
- package/src/clearingHouse.ts +2066 -467
- package/src/clearingHouseConfig.ts +4 -3
- package/src/clearingHouseUser.ts +747 -294
- package/src/clearingHouseUserStats.ts +75 -0
- package/src/clearingHouseUserStatsConfig.ts +18 -0
- package/src/config.ts +30 -31
- package/src/constants/numericConstants.ts +48 -25
- package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
- package/src/constants/spotMarkets.ts +73 -0
- package/src/dlob/DLOB.ts +953 -0
- package/src/dlob/DLOBNode.ts +167 -0
- package/src/dlob/NodeList.ts +189 -0
- package/src/events/eventList.js +77 -0
- package/src/events/eventList.ts +3 -0
- package/src/events/eventSubscriber.ts +20 -12
- package/src/events/fetchLogs.ts +35 -8
- package/src/events/pollingLogProvider.ts +10 -2
- package/src/events/sort.ts +11 -15
- package/src/events/types.ts +19 -1
- package/src/examples/makeTradeExample.js +157 -0
- package/src/examples/makeTradeExample.ts +32 -14
- package/src/factory/bigNum.ts +65 -13
- package/src/idl/clearing_house.json +4889 -1529
- package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
- package/src/index.ts +21 -6
- package/src/math/amm.ts +171 -88
- package/src/math/auction.ts +5 -1
- package/src/math/conversion.ts +2 -2
- package/src/math/funding.ts +20 -18
- package/src/math/insurance.ts +35 -0
- package/src/math/margin.ts +127 -0
- package/src/math/market.ts +145 -14
- package/src/math/oracles.ts +63 -9
- package/src/math/orders.ts +138 -4
- package/src/math/position.ts +119 -58
- package/src/math/repeg.ts +16 -6
- package/src/math/spotBalance.ts +319 -0
- package/src/math/spotMarket.ts +9 -0
- package/src/math/spotPosition.ts +47 -0
- package/src/math/trade.ts +53 -59
- package/src/oracles/pythClient.ts +2 -2
- package/src/oracles/quoteAssetOracleClient.ts +2 -2
- package/src/oracles/switchboardClient.ts +2 -2
- package/src/orderParams.ts +24 -137
- package/src/serum/serumSubscriber.ts +80 -0
- package/src/serum/types.ts +13 -0
- package/src/slot/SlotSubscriber.ts +11 -1
- package/src/token/index.js +38 -0
- package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
- package/src/tx/retryTxSender.ts +16 -5
- package/src/tx/types.js +2 -0
- package/src/tx/types.ts +2 -1
- package/src/tx/utils.js +17 -0
- package/src/tx/utils.ts +1 -1
- package/src/types.ts +533 -140
- package/src/userMap/userMap.ts +100 -0
- package/src/userMap/userStatsMap.ts +110 -0
- package/src/util/computeUnits.js +21 -11
- package/src/util/computeUnits.ts +1 -1
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/getTokenAddress.ts +18 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/tests/bn/test.ts +24 -10
- package/tests/dlob/helpers.ts +397 -0
- package/tests/dlob/test.ts +3688 -0
- package/lib/constants/banks.d.ts +0 -16
- package/lib/constants/banks.js +0 -34
- package/lib/constants/markets.d.ts +0 -19
- package/lib/math/bankBalance.d.ts +0 -9
- package/lib/math/bankBalance.js +0 -75
- package/lib/math/state.d.ts +0 -8
- package/lib/math/state.js +0 -15
- package/lib/orders.d.ts +0 -8
- package/lib/orders.js +0 -134
- package/src/constants/banks.ts +0 -43
- package/src/math/bankBalance.ts +0 -112
- package/src/math/state.ts +0 -14
- package/src/math/utils.js +0 -27
- package/src/math/utils.js.map +0 -1
- package/src/orders.ts +0 -244
- package/src/util/computeUnits.js.map +0 -1
package/README.md
CHANGED
|
@@ -54,13 +54,13 @@ a BigNum: 10,500,000, with precision 10^6, is equal to 10.5 because 10,500,000 /
|
|
|
54
54
|
|
|
55
55
|
The Drift SDK uses some common precisions, which are available as constants to import from the SDK.
|
|
56
56
|
|
|
57
|
-
| Precision Name
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
57
|
+
| Precision Name | Value |
|
|
58
|
+
| --------------------- | ----- |
|
|
59
|
+
| FUNDING_RATE_BUFFER | 10^3 |
|
|
60
|
+
| QUOTE_PRECISION | 10^6 |
|
|
61
|
+
| PEG_PRECISION | 10^6 |
|
|
62
|
+
| PRICE_PRECISION | 10^6 |
|
|
63
|
+
| AMM_RESERVE_PRECISION | 10^9 |
|
|
64
64
|
|
|
65
65
|
**Important Note for BigNum division**
|
|
66
66
|
|
|
@@ -88,7 +88,7 @@ import { BN, Provider } from '@project-serum/anchor';
|
|
|
88
88
|
import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
89
89
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
90
90
|
import {
|
|
91
|
-
|
|
91
|
+
calculateReservePrice,
|
|
92
92
|
ClearingHouse,
|
|
93
93
|
ClearingHouseUser,
|
|
94
94
|
initialize,
|
|
@@ -96,9 +96,9 @@ import {
|
|
|
96
96
|
PositionDirection,
|
|
97
97
|
convertToNumber,
|
|
98
98
|
calculateTradeSlippage,
|
|
99
|
-
|
|
99
|
+
PRICE_PRECISION,
|
|
100
100
|
QUOTE_PRECISION,
|
|
101
|
-
Wallet
|
|
101
|
+
Wallet,
|
|
102
102
|
} from '@drift-labs/sdk';
|
|
103
103
|
|
|
104
104
|
export const getTokenAddress = (
|
|
@@ -177,11 +177,11 @@ const main = async () => {
|
|
|
177
177
|
(market) => market.baseAssetSymbol === 'SOL'
|
|
178
178
|
);
|
|
179
179
|
|
|
180
|
-
const currentMarketPrice =
|
|
180
|
+
const currentMarketPrice = calculateReservePrice(
|
|
181
181
|
clearingHouse.getMarket(solMarketInfo.marketIndex)
|
|
182
182
|
);
|
|
183
183
|
|
|
184
|
-
const formattedPrice = convertToNumber(currentMarketPrice,
|
|
184
|
+
const formattedPrice = convertToNumber(currentMarketPrice, PRICE_PRECISION);
|
|
185
185
|
|
|
186
186
|
console.log(`Current Market Price is $${formattedPrice}`);
|
|
187
187
|
|
|
@@ -194,7 +194,7 @@ const main = async () => {
|
|
|
194
194
|
new BN(5000).mul(QUOTE_PRECISION),
|
|
195
195
|
solMarketAccount
|
|
196
196
|
)[0],
|
|
197
|
-
|
|
197
|
+
PRICE_PRECISION
|
|
198
198
|
);
|
|
199
199
|
|
|
200
200
|
console.log(
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ClearingHouseUserStats } from '../clearingHouseUserStats';
|
|
2
|
+
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
3
|
+
/**
|
|
4
|
+
* @param userStats
|
|
5
|
+
* @param accountLoader
|
|
6
|
+
*/
|
|
7
|
+
export declare function bulkPollingUserStatsSubscribe(userStats: ClearingHouseUserStats[], accountLoader: BulkAccountLoader): Promise<void>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bulkPollingUserStatsSubscribe = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @param userStats
|
|
6
|
+
* @param accountLoader
|
|
7
|
+
*/
|
|
8
|
+
async function bulkPollingUserStatsSubscribe(userStats, accountLoader) {
|
|
9
|
+
if (userStats.length === 0) {
|
|
10
|
+
await accountLoader.load();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
await Promise.all(userStats.map((userStat) => {
|
|
14
|
+
return userStat.accountSubscriber.addToAccountLoader();
|
|
15
|
+
}));
|
|
16
|
+
await accountLoader.load();
|
|
17
|
+
await Promise.all(userStats.map(async (userStat) => {
|
|
18
|
+
return userStat.subscribe();
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
exports.bulkPollingUserStatsSubscribe = bulkPollingUserStatsSubscribe;
|
|
@@ -11,7 +11,6 @@ async function bulkPollingUserSubscribe(users, accountLoader) {
|
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
13
|
await Promise.all(users.map((user) => {
|
|
14
|
-
// Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
|
|
15
14
|
return user.accountSubscriber.addToAccountLoader();
|
|
16
15
|
}));
|
|
17
16
|
await accountLoader.load();
|
package/lib/accounts/fetch.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
2
|
-
import { UserAccount } from '../types';
|
|
2
|
+
import { UserAccount, UserStatsAccount } from '../types';
|
|
3
3
|
import { Program } from '@project-serum/anchor';
|
|
4
4
|
export declare function fetchUserAccounts(connection: Connection, program: Program, authority: PublicKey, limit?: number): Promise<(UserAccount | undefined)[]>;
|
|
5
|
+
export declare function fetchUserStatsAccount(connection: Connection, program: Program, authority: PublicKey): Promise<UserStatsAccount | undefined>;
|
package/lib/accounts/fetch.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchUserAccounts = void 0;
|
|
3
|
+
exports.fetchUserStatsAccount = exports.fetchUserAccounts = void 0;
|
|
4
4
|
const pda_1 = require("../addresses/pda");
|
|
5
5
|
async function fetchUserAccounts(connection, program, authority, limit = 8) {
|
|
6
6
|
const userAccountPublicKeys = new Array();
|
|
@@ -16,3 +16,11 @@ async function fetchUserAccounts(connection, program, authority, limit = 8) {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
exports.fetchUserAccounts = fetchUserAccounts;
|
|
19
|
+
async function fetchUserStatsAccount(connection, program, authority) {
|
|
20
|
+
const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(program.programId, authority);
|
|
21
|
+
const accountInfo = await connection.getAccountInfo(userStatsPublicKey, 'confirmed');
|
|
22
|
+
return accountInfo
|
|
23
|
+
? program.account.user.coder.accounts.decode('UserStats', accountInfo.data)
|
|
24
|
+
: undefined;
|
|
25
|
+
}
|
|
26
|
+
exports.fetchUserStatsAccount = fetchUserStatsAccount;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
/// <reference types="bn.js" />
|
|
2
1
|
/// <reference types="node" />
|
|
3
2
|
import { DataAndSlot, AccountToPoll, ClearingHouseAccountEvents, ClearingHouseAccountSubscriber, OraclesToPoll } from './types';
|
|
4
|
-
import {
|
|
3
|
+
import { Program } from '@project-serum/anchor';
|
|
5
4
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
6
5
|
import { EventEmitter } from 'events';
|
|
7
|
-
import {
|
|
6
|
+
import { SpotMarketAccount, PerpMarketAccount, StateAccount, UserAccount } from '../types';
|
|
8
7
|
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
9
8
|
import { PublicKey } from '@solana/web3.js';
|
|
10
9
|
import { OracleInfo, OraclePriceData } from '../oracles/types';
|
|
@@ -12,8 +11,8 @@ import { OracleClientCache } from '../oracles/oracleClientCache';
|
|
|
12
11
|
export declare class PollingClearingHouseAccountSubscriber implements ClearingHouseAccountSubscriber {
|
|
13
12
|
isSubscribed: boolean;
|
|
14
13
|
program: Program;
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
perpMarketIndexes: number[];
|
|
15
|
+
spotMarketIndexes: number[];
|
|
17
16
|
oracleInfos: OracleInfo[];
|
|
18
17
|
oracleClientCache: OracleClientCache;
|
|
19
18
|
eventEmitter: StrictEventEmitter<EventEmitter, ClearingHouseAccountEvents>;
|
|
@@ -22,20 +21,20 @@ export declare class PollingClearingHouseAccountSubscriber implements ClearingHo
|
|
|
22
21
|
oraclesToPoll: Map<string, OraclesToPoll>;
|
|
23
22
|
errorCallbackId?: string;
|
|
24
23
|
state?: DataAndSlot<StateAccount>;
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
perpMarket: Map<number, DataAndSlot<PerpMarketAccount>>;
|
|
25
|
+
spotMarket: Map<number, DataAndSlot<SpotMarketAccount>>;
|
|
27
26
|
oracles: Map<string, DataAndSlot<OraclePriceData>>;
|
|
28
27
|
user?: DataAndSlot<UserAccount>;
|
|
29
28
|
private isSubscribing;
|
|
30
29
|
private subscriptionPromise;
|
|
31
30
|
private subscriptionPromiseResolver;
|
|
32
|
-
constructor(program: Program, accountLoader: BulkAccountLoader,
|
|
31
|
+
constructor(program: Program, accountLoader: BulkAccountLoader, perpMarketIndexes: number[], spotMarketIndexes: number[], oracleInfos: OracleInfo[]);
|
|
33
32
|
subscribe(): Promise<boolean>;
|
|
34
33
|
updateAccountsToPoll(): Promise<void>;
|
|
35
34
|
updateMarketAccountsToPoll(): Promise<boolean>;
|
|
36
|
-
addMarketAccountToPoll(marketIndex:
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
addMarketAccountToPoll(marketIndex: number): Promise<boolean>;
|
|
36
|
+
updateSpotMarketAccountsToPoll(): Promise<boolean>;
|
|
37
|
+
addSpotMarketAccountToPoll(marketIndex: number): Promise<boolean>;
|
|
39
38
|
updateOraclesToPoll(): boolean;
|
|
40
39
|
addOracleToPoll(oracleInfo: OracleInfo): boolean;
|
|
41
40
|
getClearingHouseAccounts(): Promise<ClearingHouseAccounts>;
|
|
@@ -45,14 +44,15 @@ export declare class PollingClearingHouseAccountSubscriber implements ClearingHo
|
|
|
45
44
|
fetch(): Promise<void>;
|
|
46
45
|
didSubscriptionSucceed(): boolean;
|
|
47
46
|
unsubscribe(): Promise<void>;
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
addSpotMarket(marketIndex: number): Promise<boolean>;
|
|
48
|
+
addPerpMarket(marketIndex: number): Promise<boolean>;
|
|
50
49
|
addOracle(oracleInfo: OracleInfo): Promise<boolean>;
|
|
51
50
|
assertIsSubscribed(): void;
|
|
52
51
|
getStateAccountAndSlot(): DataAndSlot<StateAccount>;
|
|
53
|
-
getMarketAccountAndSlot(marketIndex:
|
|
54
|
-
getMarketAccountsAndSlots(): DataAndSlot<
|
|
55
|
-
|
|
52
|
+
getMarketAccountAndSlot(marketIndex: number): DataAndSlot<PerpMarketAccount> | undefined;
|
|
53
|
+
getMarketAccountsAndSlots(): DataAndSlot<PerpMarketAccount>[];
|
|
54
|
+
getSpotMarketAccountAndSlot(marketIndex: number): DataAndSlot<SpotMarketAccount> | undefined;
|
|
55
|
+
getSpotMarketAccountsAndSlots(): DataAndSlot<SpotMarketAccount>[];
|
|
56
56
|
getOraclePriceDataAndSlot(oraclePublicKey: PublicKey): DataAndSlot<OraclePriceData> | undefined;
|
|
57
57
|
}
|
|
58
58
|
declare type ClearingHouseAccounts = {
|
|
@@ -9,20 +9,20 @@ const web3_js_1 = require("@solana/web3.js");
|
|
|
9
9
|
const oracleClientCache_1 = require("../oracles/oracleClientCache");
|
|
10
10
|
const quoteAssetOracleClient_1 = require("../oracles/quoteAssetOracleClient");
|
|
11
11
|
class PollingClearingHouseAccountSubscriber {
|
|
12
|
-
constructor(program, accountLoader,
|
|
12
|
+
constructor(program, accountLoader, perpMarketIndexes, spotMarketIndexes, oracleInfos) {
|
|
13
13
|
this.oracleClientCache = new oracleClientCache_1.OracleClientCache();
|
|
14
14
|
this.accountsToPoll = new Map();
|
|
15
15
|
this.oraclesToPoll = new Map();
|
|
16
|
-
this.
|
|
17
|
-
this.
|
|
16
|
+
this.perpMarket = new Map();
|
|
17
|
+
this.spotMarket = new Map();
|
|
18
18
|
this.oracles = new Map();
|
|
19
19
|
this.isSubscribing = false;
|
|
20
20
|
this.isSubscribed = false;
|
|
21
21
|
this.program = program;
|
|
22
22
|
this.eventEmitter = new events_1.EventEmitter();
|
|
23
23
|
this.accountLoader = accountLoader;
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
24
|
+
this.perpMarketIndexes = perpMarketIndexes;
|
|
25
|
+
this.spotMarketIndexes = spotMarketIndexes;
|
|
26
26
|
this.oracleInfos = oracleInfos;
|
|
27
27
|
}
|
|
28
28
|
async subscribe() {
|
|
@@ -65,10 +65,10 @@ class PollingClearingHouseAccountSubscriber {
|
|
|
65
65
|
eventType: 'stateAccountUpdate',
|
|
66
66
|
});
|
|
67
67
|
await this.updateMarketAccountsToPoll();
|
|
68
|
-
await this.
|
|
68
|
+
await this.updateSpotMarketAccountsToPoll();
|
|
69
69
|
}
|
|
70
70
|
async updateMarketAccountsToPoll() {
|
|
71
|
-
for (const marketIndex of this.
|
|
71
|
+
for (const marketIndex of this.perpMarketIndexes) {
|
|
72
72
|
await this.addMarketAccountToPoll(marketIndex);
|
|
73
73
|
}
|
|
74
74
|
return true;
|
|
@@ -76,26 +76,26 @@ class PollingClearingHouseAccountSubscriber {
|
|
|
76
76
|
async addMarketAccountToPoll(marketIndex) {
|
|
77
77
|
const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, marketIndex);
|
|
78
78
|
this.accountsToPoll.set(marketPublicKey.toString(), {
|
|
79
|
-
key: '
|
|
79
|
+
key: 'perpMarket',
|
|
80
80
|
publicKey: marketPublicKey,
|
|
81
|
-
eventType: '
|
|
82
|
-
mapKey: marketIndex
|
|
81
|
+
eventType: 'perpMarketAccountUpdate',
|
|
82
|
+
mapKey: marketIndex,
|
|
83
83
|
});
|
|
84
84
|
return true;
|
|
85
85
|
}
|
|
86
|
-
async
|
|
87
|
-
for (const
|
|
88
|
-
await this.
|
|
86
|
+
async updateSpotMarketAccountsToPoll() {
|
|
87
|
+
for (const marketIndex of this.spotMarketIndexes) {
|
|
88
|
+
await this.addSpotMarketAccountToPoll(marketIndex);
|
|
89
89
|
}
|
|
90
90
|
return true;
|
|
91
91
|
}
|
|
92
|
-
async
|
|
93
|
-
const
|
|
94
|
-
this.accountsToPoll.set(
|
|
95
|
-
key: '
|
|
96
|
-
publicKey:
|
|
97
|
-
eventType: '
|
|
98
|
-
mapKey:
|
|
92
|
+
async addSpotMarketAccountToPoll(marketIndex) {
|
|
93
|
+
const marketPublicKey = await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, marketIndex);
|
|
94
|
+
this.accountsToPoll.set(marketPublicKey.toString(), {
|
|
95
|
+
key: 'spotMarket',
|
|
96
|
+
publicKey: marketPublicKey,
|
|
97
|
+
eventType: 'spotMarketAccountUpdate',
|
|
98
|
+
mapKey: marketIndex,
|
|
99
99
|
});
|
|
100
100
|
return true;
|
|
101
101
|
}
|
|
@@ -223,13 +223,13 @@ class PollingClearingHouseAccountSubscriber {
|
|
|
223
223
|
this.oraclesToPoll.clear();
|
|
224
224
|
this.isSubscribed = false;
|
|
225
225
|
}
|
|
226
|
-
async
|
|
227
|
-
await this.
|
|
228
|
-
const accountToPoll = this.accountsToPoll.get(
|
|
226
|
+
async addSpotMarket(marketIndex) {
|
|
227
|
+
await this.addSpotMarketAccountToPoll(marketIndex);
|
|
228
|
+
const accountToPoll = this.accountsToPoll.get(marketIndex.toString());
|
|
229
229
|
this.addAccountToAccountLoader(accountToPoll);
|
|
230
230
|
return true;
|
|
231
231
|
}
|
|
232
|
-
async
|
|
232
|
+
async addPerpMarket(marketIndex) {
|
|
233
233
|
await this.addMarketAccountToPoll(marketIndex);
|
|
234
234
|
const accountToPoll = this.accountsToPoll.get(marketIndex.toString());
|
|
235
235
|
this.addAccountToAccountLoader(accountToPoll);
|
|
@@ -254,13 +254,16 @@ class PollingClearingHouseAccountSubscriber {
|
|
|
254
254
|
return this.state;
|
|
255
255
|
}
|
|
256
256
|
getMarketAccountAndSlot(marketIndex) {
|
|
257
|
-
return this.
|
|
257
|
+
return this.perpMarket.get(marketIndex);
|
|
258
258
|
}
|
|
259
259
|
getMarketAccountsAndSlots() {
|
|
260
|
-
return Array.from(this.
|
|
260
|
+
return Array.from(this.perpMarket.values());
|
|
261
|
+
}
|
|
262
|
+
getSpotMarketAccountAndSlot(marketIndex) {
|
|
263
|
+
return this.spotMarket.get(marketIndex);
|
|
261
264
|
}
|
|
262
|
-
|
|
263
|
-
return this.
|
|
265
|
+
getSpotMarketAccountsAndSlots() {
|
|
266
|
+
return Array.from(this.spotMarket.values());
|
|
264
267
|
}
|
|
265
268
|
getOraclePriceDataAndSlot(oraclePublicKey) {
|
|
266
269
|
this.assertIsSubscribed();
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { DataAndSlot, AccountToPoll, UserStatsAccountSubscriber, UserStatsAccountEvents } from './types';
|
|
3
|
+
import { Program } from '@project-serum/anchor';
|
|
4
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
import { PublicKey } from '@solana/web3.js';
|
|
7
|
+
import { UserStatsAccount } from '../types';
|
|
8
|
+
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
9
|
+
export declare class PollingUserStatsAccountSubscriber implements UserStatsAccountSubscriber {
|
|
10
|
+
isSubscribed: boolean;
|
|
11
|
+
program: Program;
|
|
12
|
+
eventEmitter: StrictEventEmitter<EventEmitter, UserStatsAccountEvents>;
|
|
13
|
+
userStatsAccountPublicKey: PublicKey;
|
|
14
|
+
accountLoader: BulkAccountLoader;
|
|
15
|
+
accountsToPoll: Map<string, AccountToPoll>;
|
|
16
|
+
errorCallbackId?: string;
|
|
17
|
+
userStats?: DataAndSlot<UserStatsAccount>;
|
|
18
|
+
constructor(program: Program, userStatsAccountPublicKey: PublicKey, accountLoader: BulkAccountLoader);
|
|
19
|
+
subscribe(): Promise<boolean>;
|
|
20
|
+
addToAccountLoader(): Promise<void>;
|
|
21
|
+
fetchIfUnloaded(): Promise<void>;
|
|
22
|
+
fetch(): Promise<void>;
|
|
23
|
+
didSubscriptionSucceed(): boolean;
|
|
24
|
+
unsubscribe(): Promise<void>;
|
|
25
|
+
assertIsSubscribed(): void;
|
|
26
|
+
getUserStatsAccountAndSlot(): DataAndSlot<UserStatsAccount>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PollingUserStatsAccountSubscriber = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const events_1 = require("events");
|
|
6
|
+
const utils_1 = require("./utils");
|
|
7
|
+
class PollingUserStatsAccountSubscriber {
|
|
8
|
+
constructor(program, userStatsAccountPublicKey, accountLoader) {
|
|
9
|
+
this.accountsToPoll = new Map();
|
|
10
|
+
this.isSubscribed = false;
|
|
11
|
+
this.program = program;
|
|
12
|
+
this.accountLoader = accountLoader;
|
|
13
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
14
|
+
this.userStatsAccountPublicKey = userStatsAccountPublicKey;
|
|
15
|
+
}
|
|
16
|
+
async subscribe() {
|
|
17
|
+
if (this.isSubscribed) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
await this.addToAccountLoader();
|
|
21
|
+
let subscriptionSucceeded = false;
|
|
22
|
+
let retries = 0;
|
|
23
|
+
while (!subscriptionSucceeded && retries < 5) {
|
|
24
|
+
await this.fetchIfUnloaded();
|
|
25
|
+
subscriptionSucceeded = this.didSubscriptionSucceed();
|
|
26
|
+
retries++;
|
|
27
|
+
}
|
|
28
|
+
if (subscriptionSucceeded) {
|
|
29
|
+
this.eventEmitter.emit('update');
|
|
30
|
+
}
|
|
31
|
+
this.isSubscribed = subscriptionSucceeded;
|
|
32
|
+
return subscriptionSucceeded;
|
|
33
|
+
}
|
|
34
|
+
async addToAccountLoader() {
|
|
35
|
+
if (this.accountsToPoll.size > 0) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.accountsToPoll.set(this.userStatsAccountPublicKey.toString(), {
|
|
39
|
+
key: 'userStats',
|
|
40
|
+
publicKey: this.userStatsAccountPublicKey,
|
|
41
|
+
eventType: 'userStatsAccountUpdate',
|
|
42
|
+
});
|
|
43
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
44
|
+
accountToPoll.callbackId = this.accountLoader.addAccount(accountToPoll.publicKey, (buffer, slot) => {
|
|
45
|
+
if (!buffer) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const account = this.program.account[accountToPoll.key].coder.accounts.decode((0, utils_1.capitalize)(accountToPoll.key), buffer);
|
|
49
|
+
this[accountToPoll.key] = { data: account, slot };
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
this.eventEmitter.emit(accountToPoll.eventType, account);
|
|
52
|
+
this.eventEmitter.emit('update');
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
this.errorCallbackId = this.accountLoader.addErrorCallbacks((error) => {
|
|
56
|
+
this.eventEmitter.emit('error', error);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async fetchIfUnloaded() {
|
|
60
|
+
let shouldFetch = false;
|
|
61
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
62
|
+
if (this[accountToPoll.key] === undefined) {
|
|
63
|
+
shouldFetch = true;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (shouldFetch) {
|
|
68
|
+
await this.fetch();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async fetch() {
|
|
72
|
+
await this.accountLoader.load();
|
|
73
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
74
|
+
const { buffer, slot } = this.accountLoader.getBufferAndSlot(accountToPoll.publicKey);
|
|
75
|
+
if (buffer) {
|
|
76
|
+
const account = this.program.account[accountToPoll.key].coder.accounts.decode((0, utils_1.capitalize)(accountToPoll.key), buffer);
|
|
77
|
+
this[accountToPoll.key] = { data: account, slot };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
didSubscriptionSucceed() {
|
|
82
|
+
let success = true;
|
|
83
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
84
|
+
if (!this[accountToPoll.key]) {
|
|
85
|
+
success = false;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return success;
|
|
90
|
+
}
|
|
91
|
+
async unsubscribe() {
|
|
92
|
+
if (!this.isSubscribed) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
96
|
+
this.accountLoader.removeAccount(accountToPoll.publicKey, accountToPoll.callbackId);
|
|
97
|
+
}
|
|
98
|
+
this.accountLoader.removeErrorCallbacks(this.errorCallbackId);
|
|
99
|
+
this.errorCallbackId = undefined;
|
|
100
|
+
this.accountsToPoll.clear();
|
|
101
|
+
this.isSubscribed = false;
|
|
102
|
+
}
|
|
103
|
+
assertIsSubscribed() {
|
|
104
|
+
if (!this.isSubscribed) {
|
|
105
|
+
throw new types_1.NotSubscribedError('You must call `subscribe` before using this function');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
getUserStatsAccountAndSlot() {
|
|
109
|
+
this.assertIsSubscribed();
|
|
110
|
+
return this.userStats;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.PollingUserStatsAccountSubscriber = PollingUserStatsAccountSubscriber;
|
package/lib/accounts/types.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
|
|
3
|
-
/// <reference types="node" />
|
|
4
|
-
import { BankAccount, MarketAccount, OracleSource, StateAccount, UserAccount } from '../types';
|
|
2
|
+
import { SpotMarketAccount, PerpMarketAccount, OracleSource, StateAccount, UserAccount, UserStatsAccount } from '../types';
|
|
5
3
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
6
4
|
import { EventEmitter } from 'events';
|
|
7
5
|
import { PublicKey } from '@solana/web3.js';
|
|
8
6
|
import { AccountInfo } from '@solana/spl-token';
|
|
9
7
|
import { OracleInfo, OraclePriceData } from '..';
|
|
10
|
-
import { BN } from '@project-serum/anchor';
|
|
11
8
|
export interface AccountSubscriber<T> {
|
|
12
9
|
dataAndSlot?: DataAndSlot<T>;
|
|
13
10
|
subscribe(onChange: (data: T) => void): Promise<void>;
|
|
@@ -19,8 +16,8 @@ export declare class NotSubscribedError extends Error {
|
|
|
19
16
|
}
|
|
20
17
|
export interface ClearingHouseAccountEvents {
|
|
21
18
|
stateAccountUpdate: (payload: StateAccount) => void;
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
perpMarketAccountUpdate: (payload: PerpMarketAccount) => void;
|
|
20
|
+
spotMarketAccountUpdate: (payload: SpotMarketAccount) => void;
|
|
24
21
|
oraclePriceUpdate: (publicKey: PublicKey, data: OraclePriceData) => void;
|
|
25
22
|
userAccountUpdate: (payload: UserAccount) => void;
|
|
26
23
|
update: void;
|
|
@@ -32,13 +29,14 @@ export interface ClearingHouseAccountSubscriber {
|
|
|
32
29
|
subscribe(): Promise<boolean>;
|
|
33
30
|
fetch(): Promise<void>;
|
|
34
31
|
unsubscribe(): Promise<void>;
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
addPerpMarket(marketIndex: number): Promise<boolean>;
|
|
33
|
+
addSpotMarket(marketIndex: number): Promise<boolean>;
|
|
37
34
|
addOracle(oracleInfo: OracleInfo): Promise<boolean>;
|
|
38
35
|
getStateAccountAndSlot(): DataAndSlot<StateAccount>;
|
|
39
|
-
getMarketAccountAndSlot(marketIndex:
|
|
40
|
-
getMarketAccountsAndSlots(): DataAndSlot<
|
|
41
|
-
|
|
36
|
+
getMarketAccountAndSlot(marketIndex: number): DataAndSlot<PerpMarketAccount> | undefined;
|
|
37
|
+
getMarketAccountsAndSlots(): DataAndSlot<PerpMarketAccount>[];
|
|
38
|
+
getSpotMarketAccountAndSlot(marketIndex: number): DataAndSlot<SpotMarketAccount> | undefined;
|
|
39
|
+
getSpotMarketAccountsAndSlots(): DataAndSlot<SpotMarketAccount>[];
|
|
42
40
|
getOraclePriceDataAndSlot(oraclePublicKey: PublicKey): DataAndSlot<OraclePriceData> | undefined;
|
|
43
41
|
}
|
|
44
42
|
export interface UserAccountEvents {
|
|
@@ -100,3 +98,16 @@ export declare type DataAndSlot<T> = {
|
|
|
100
98
|
data: T;
|
|
101
99
|
slot: number;
|
|
102
100
|
};
|
|
101
|
+
export interface UserStatsAccountEvents {
|
|
102
|
+
userStatsAccountUpdate: (payload: UserStatsAccount) => void;
|
|
103
|
+
update: void;
|
|
104
|
+
error: (e: Error) => void;
|
|
105
|
+
}
|
|
106
|
+
export interface UserStatsAccountSubscriber {
|
|
107
|
+
eventEmitter: StrictEventEmitter<EventEmitter, UserStatsAccountEvents>;
|
|
108
|
+
isSubscribed: boolean;
|
|
109
|
+
subscribe(): Promise<boolean>;
|
|
110
|
+
fetch(): Promise<void>;
|
|
111
|
+
unsubscribe(): Promise<void>;
|
|
112
|
+
getUserStatsAccountAndSlot(): DataAndSlot<UserStatsAccount>;
|
|
113
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
/// <reference types="bn.js" />
|
|
2
1
|
/// <reference types="node" />
|
|
3
2
|
import { ClearingHouseAccountSubscriber, ClearingHouseAccountEvents, DataAndSlot } from './types';
|
|
4
3
|
import { AccountSubscriber } from './types';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { SpotMarketAccount, PerpMarketAccount, StateAccount } from '../types';
|
|
5
|
+
import { Program } from '@project-serum/anchor';
|
|
7
6
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
8
7
|
import { EventEmitter } from 'events';
|
|
9
8
|
import { PublicKey } from '@solana/web3.js';
|
|
@@ -12,38 +11,39 @@ import { OracleClientCache } from '../oracles/oracleClientCache';
|
|
|
12
11
|
export declare class WebSocketClearingHouseAccountSubscriber implements ClearingHouseAccountSubscriber {
|
|
13
12
|
isSubscribed: boolean;
|
|
14
13
|
program: Program;
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
perpMarketIndexes: number[];
|
|
15
|
+
spotMarketIndexes: number[];
|
|
17
16
|
oracleInfos: OracleInfo[];
|
|
18
17
|
oracleClientCache: OracleClientCache;
|
|
19
18
|
eventEmitter: StrictEventEmitter<EventEmitter, ClearingHouseAccountEvents>;
|
|
20
19
|
stateAccountSubscriber?: AccountSubscriber<StateAccount>;
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
perpMarketAccountSubscribers: Map<number, AccountSubscriber<PerpMarketAccount>>;
|
|
21
|
+
spotMarketAccountSubscribers: Map<number, AccountSubscriber<SpotMarketAccount>>;
|
|
23
22
|
oracleSubscribers: Map<string, AccountSubscriber<OraclePriceData>>;
|
|
24
23
|
private isSubscribing;
|
|
25
24
|
private subscriptionPromise;
|
|
26
25
|
private subscriptionPromiseResolver;
|
|
27
|
-
constructor(program: Program,
|
|
26
|
+
constructor(program: Program, perpMarketIndexes: number[], spotMarketIndexes: number[], oracleInfos: OracleInfo[]);
|
|
28
27
|
subscribe(): Promise<boolean>;
|
|
29
28
|
subscribeToMarketAccounts(): Promise<boolean>;
|
|
30
|
-
subscribeToMarketAccount(marketIndex:
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
subscribeToMarketAccount(marketIndex: number): Promise<boolean>;
|
|
30
|
+
subscribeToSpotMarketAccounts(): Promise<boolean>;
|
|
31
|
+
subscribeToSpotMarketAccount(marketIndex: number): Promise<boolean>;
|
|
33
32
|
subscribeToOracles(): Promise<boolean>;
|
|
34
33
|
subscribeToOracle(oracleInfo: OracleInfo): Promise<boolean>;
|
|
35
34
|
unsubscribeFromMarketAccounts(): Promise<void>;
|
|
36
|
-
|
|
35
|
+
unsubscribeFromSpotMarketAccounts(): Promise<void>;
|
|
37
36
|
unsubscribeFromOracles(): Promise<void>;
|
|
38
37
|
fetch(): Promise<void>;
|
|
39
38
|
unsubscribe(): Promise<void>;
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
addSpotMarket(marketIndex: number): Promise<boolean>;
|
|
40
|
+
addPerpMarket(marketIndex: number): Promise<boolean>;
|
|
42
41
|
addOracle(oracleInfo: OracleInfo): Promise<boolean>;
|
|
43
42
|
assertIsSubscribed(): void;
|
|
44
43
|
getStateAccountAndSlot(): DataAndSlot<StateAccount>;
|
|
45
|
-
getMarketAccountAndSlot(marketIndex:
|
|
46
|
-
getMarketAccountsAndSlots(): DataAndSlot<
|
|
47
|
-
|
|
44
|
+
getMarketAccountAndSlot(marketIndex: number): DataAndSlot<PerpMarketAccount> | undefined;
|
|
45
|
+
getMarketAccountsAndSlots(): DataAndSlot<PerpMarketAccount>[];
|
|
46
|
+
getSpotMarketAccountAndSlot(marketIndex: number): DataAndSlot<SpotMarketAccount> | undefined;
|
|
47
|
+
getSpotMarketAccountsAndSlots(): DataAndSlot<SpotMarketAccount>[];
|
|
48
48
|
getOraclePriceDataAndSlot(oraclePublicKey: PublicKey): DataAndSlot<OraclePriceData> | undefined;
|
|
49
49
|
}
|