@drift-labs/sdk 2.96.0-beta.2 → 2.96.0-beta.20
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 +1 -0
- package/VERSION +1 -1
- package/bun.lockb +0 -0
- package/lib/accounts/pollingDriftClientAccountSubscriber.d.ts +5 -3
- package/lib/accounts/pollingDriftClientAccountSubscriber.js +24 -1
- package/lib/accounts/types.d.ts +5 -8
- package/lib/accounts/types.js +7 -1
- package/lib/accounts/utils.d.ts +7 -0
- package/lib/accounts/utils.js +33 -1
- package/lib/accounts/webSocketAccountSubscriber.d.ts +1 -1
- package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +8 -7
- package/lib/accounts/webSocketDriftClientAccountSubscriber.js +24 -1
- package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +1 -1
- package/lib/config.d.ts +5 -1
- package/lib/config.js +9 -1
- package/lib/constants/perpMarkets.js +21 -0
- package/lib/constants/spotMarkets.js +12 -1
- package/lib/driftClient.d.ts +44 -9
- package/lib/driftClient.js +181 -61
- package/lib/driftClientConfig.d.ts +2 -6
- package/lib/events/eventSubscriber.js +9 -8
- package/lib/events/types.js +1 -5
- package/lib/idl/drift.json +169 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/math/margin.d.ts +16 -1
- package/lib/math/margin.js +67 -1
- package/lib/orderParams.js +8 -8
- package/lib/orderSubscriber/OrderSubscriber.d.ts +1 -2
- package/lib/orderSubscriber/OrderSubscriber.js +4 -19
- package/lib/orderSubscriber/types.d.ts +0 -9
- package/lib/tokenFaucet.js +2 -1
- package/lib/tx/baseTxSender.js +2 -2
- package/lib/tx/fastSingleTxSender.js +2 -2
- package/lib/tx/forwardOnlyTxSender.js +2 -2
- package/lib/tx/retryTxSender.js +2 -2
- package/lib/tx/txHandler.js +10 -7
- package/lib/tx/whileValidTxSender.d.ts +2 -4
- package/lib/tx/whileValidTxSender.js +16 -17
- package/lib/types.d.ts +21 -1
- package/lib/types.js +6 -1
- package/lib/user.d.ts +4 -1
- package/lib/user.js +13 -13
- package/lib/userConfig.d.ts +1 -6
- package/lib/userMap/userMap.js +0 -14
- package/lib/userMap/userMapConfig.d.ts +0 -7
- package/lib/userStatsConfig.d.ts +0 -6
- package/lib/util/TransactionConfirmationManager.d.ts +14 -0
- package/lib/util/TransactionConfirmationManager.js +96 -0
- package/package.json +4 -5
- package/src/accounts/pollingDriftClientAccountSubscriber.ts +41 -5
- package/src/accounts/types.ts +6 -9
- package/src/accounts/utils.ts +42 -0
- package/src/accounts/webSocketAccountSubscriber.ts +1 -1
- package/src/accounts/webSocketDriftClientAccountSubscriber.ts +43 -8
- package/src/accounts/webSocketProgramAccountSubscriber.ts +1 -1
- package/src/config.ts +15 -1
- package/src/constants/perpMarkets.ts +22 -0
- package/src/constants/spotMarkets.ts +14 -1
- package/src/driftClient.ts +423 -91
- package/src/driftClientConfig.ts +2 -7
- package/src/events/eventSubscriber.ts +18 -11
- package/src/events/types.ts +1 -5
- package/src/idl/drift.json +169 -1
- package/src/index.ts +1 -0
- package/src/math/margin.ts +137 -1
- package/src/orderParams.ts +20 -12
- package/src/orderSubscriber/OrderSubscriber.ts +1 -15
- package/src/orderSubscriber/types.ts +0 -10
- package/src/tokenFaucet.ts +2 -2
- package/src/tx/baseTxSender.ts +2 -2
- package/src/tx/fastSingleTxSender.ts +2 -2
- package/src/tx/forwardOnlyTxSender.ts +2 -2
- package/src/tx/retryTxSender.ts +2 -2
- package/src/tx/txHandler.ts +8 -2
- package/src/tx/whileValidTxSender.ts +23 -26
- package/src/types.ts +30 -1
- package/src/user.ts +35 -13
- package/src/userConfig.ts +1 -7
- package/src/userMap/userMap.ts +1 -17
- package/src/userMap/userMapConfig.ts +0 -8
- package/src/userStatsConfig.ts +0 -7
- package/src/util/TransactionConfirmationManager.ts +155 -0
- package/tests/ci/idl.ts +12 -3
- package/tests/ci/verifyConstants.ts +13 -0
- package/tests/tx/TransactionConfirmationManager.test.ts +286 -0
- package/lib/accounts/grpcAccountSubscriber.d.ts +0 -16
- package/lib/accounts/grpcAccountSubscriber.js +0 -155
- package/lib/accounts/grpcDriftClientAccountSubscriber.d.ts +0 -13
- package/lib/accounts/grpcDriftClientAccountSubscriber.js +0 -96
- package/lib/accounts/grpcInsuranceFundStakeAccountSubscriber.d.ts +0 -10
- package/lib/accounts/grpcInsuranceFundStakeAccountSubscriber.js +0 -30
- package/lib/accounts/grpcProgramAccountSubscriber.d.ts +0 -19
- package/lib/accounts/grpcProgramAccountSubscriber.js +0 -161
- package/lib/accounts/grpcUserAccountSubscriber.d.ts +0 -10
- package/lib/accounts/grpcUserAccountSubscriber.js +0 -28
- package/lib/accounts/grpcUserStatsAccountSubscriber.d.ts +0 -10
- package/lib/accounts/grpcUserStatsAccountSubscriber.js +0 -28
- package/lib/orderSubscriber/grpcSubscription.d.ts +0 -25
- package/lib/orderSubscriber/grpcSubscription.js +0 -68
- package/lib/userMap/grpcSubscription.d.ts +0 -26
- package/lib/userMap/grpcSubscription.js +0 -42
- package/src/accounts/grpcAccountSubscriber.ts +0 -158
- package/src/accounts/grpcDriftClientAccountSubscriber.ts +0 -196
- package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -62
- package/src/accounts/grpcProgramAccountSubscriber.ts +0 -181
- package/src/accounts/grpcUserAccountSubscriber.ts +0 -48
- package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -51
- package/src/orderSubscriber/grpcSubscription.ts +0 -126
- package/src/userMap/grpcSubscription.ts +0 -83
|
@@ -4,11 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.WhileValidTxSender = void 0;
|
|
7
|
-
const
|
|
7
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
8
8
|
const baseTxSender_1 = require("./baseTxSender");
|
|
9
9
|
const bs58_1 = __importDefault(require("bs58"));
|
|
10
|
+
const config_1 = require("../config");
|
|
10
11
|
const DEFAULT_RETRY = 2000;
|
|
11
|
-
const VALID_BLOCK_HEIGHT_OFFSET = -150; // This is a bit of weirdness but the lastValidBlockHeight value returned from connection.getLatestBlockhash is always 300 blocks ahead of the current block, even though the transaction actually expires after 150 blocks. This accounts for that so that we can at least accuractely estimate the transaction expiry.
|
|
12
12
|
class WhileValidTxSender extends baseTxSender_1.BaseTxSender {
|
|
13
13
|
async checkAndSetUseBlockHeightOffset() {
|
|
14
14
|
this.connection.getVersion().then((version) => {
|
|
@@ -29,7 +29,7 @@ class WhileValidTxSender extends baseTxSender_1.BaseTxSender {
|
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
-
constructor({ connection, wallet, opts = { ...
|
|
32
|
+
constructor({ connection, wallet, opts = { ...config_1.DEFAULT_CONFIRMATION_OPTS, maxRetries: 0 }, retrySleep = DEFAULT_RETRY, additionalConnections = new Array(), additionalTxSenderCallbacks = [], txHandler, trackTxLandRate, txLandRateLookbackWindowMinutes, landRateToFeeFunc, }) {
|
|
33
33
|
super({
|
|
34
34
|
connection,
|
|
35
35
|
wallet,
|
|
@@ -45,7 +45,6 @@ class WhileValidTxSender extends baseTxSender_1.BaseTxSender {
|
|
|
45
45
|
this.untilValid = new Map();
|
|
46
46
|
this.useBlockHeightOffset = true;
|
|
47
47
|
this.retrySleep = retrySleep;
|
|
48
|
-
this.blockhashCommitment = blockhashCommitment;
|
|
49
48
|
this.checkAndSetUseBlockHeightOffset();
|
|
50
49
|
}
|
|
51
50
|
async sleep(reference) {
|
|
@@ -69,7 +68,7 @@ class WhileValidTxSender extends baseTxSender_1.BaseTxSender {
|
|
|
69
68
|
latestBlockhash = tx.SIGNATURE_BLOCK_AND_EXPIRY;
|
|
70
69
|
}
|
|
71
70
|
// handle subclass-specific side effects
|
|
72
|
-
const txSig = bs58_1.default.encode(((_a = signedTx.signatures[0]) === null || _a === void 0 ? void 0 : _a.signature)
|
|
71
|
+
const txSig = bs58_1.default.encode((signedTx === null || signedTx === void 0 ? void 0 : signedTx.signature) || ((_a = signedTx.signatures[0]) === null || _a === void 0 ? void 0 : _a.signature));
|
|
73
72
|
this.untilValid.set(txSig, latestBlockhash);
|
|
74
73
|
return signedTx;
|
|
75
74
|
}
|
|
@@ -104,11 +103,13 @@ class WhileValidTxSender extends baseTxSender_1.BaseTxSender {
|
|
|
104
103
|
}
|
|
105
104
|
const txSig = bs58_1.default.encode(signedTx.signatures[0]);
|
|
106
105
|
this.untilValid.set(txSig, latestBlockhash);
|
|
106
|
+
console.debug(`preflight_commitment`, `sending_tx_with_preflight_commitment::${opts === null || opts === void 0 ? void 0 : opts.preflightCommitment}`);
|
|
107
107
|
return this.sendRawTransaction(signedTx.serialize(), opts);
|
|
108
108
|
}
|
|
109
109
|
async sendRawTransaction(rawTransaction, opts) {
|
|
110
|
-
var _a, _b;
|
|
110
|
+
var _a, _b, _c;
|
|
111
111
|
const startTime = this.getTimestamp();
|
|
112
|
+
console.debug(`preflight_commitment`, `sending_tx_with_preflight_commitment::${opts === null || opts === void 0 ? void 0 : opts.preflightCommitment}`);
|
|
112
113
|
const txid = await this.connection.sendRawTransaction(rawTransaction, opts);
|
|
113
114
|
(_a = this.txSigCache) === null || _a === void 0 ? void 0 : _a.set(txid, false);
|
|
114
115
|
this.sendToAdditionalConnections(rawTransaction, opts);
|
|
@@ -138,19 +139,17 @@ class WhileValidTxSender extends baseTxSender_1.BaseTxSender {
|
|
|
138
139
|
})();
|
|
139
140
|
let slot;
|
|
140
141
|
try {
|
|
141
|
-
const
|
|
142
|
-
const result = await this.connection.confirmTransaction({
|
|
143
|
-
signature: txid,
|
|
144
|
-
blockhash,
|
|
145
|
-
lastValidBlockHeight: this.useBlockHeightOffset
|
|
146
|
-
? lastValidBlockHeight + VALID_BLOCK_HEIGHT_OFFSET
|
|
147
|
-
: lastValidBlockHeight,
|
|
148
|
-
}, opts === null || opts === void 0 ? void 0 : opts.commitment);
|
|
149
|
-
if (!result) {
|
|
150
|
-
throw new Error(`Couldn't get signature status for txid: ${txid}`);
|
|
151
|
-
}
|
|
142
|
+
const result = await this.confirmTransaction(txid, opts.commitment);
|
|
152
143
|
(_b = this.txSigCache) === null || _b === void 0 ? void 0 : _b.set(txid, true);
|
|
153
144
|
await this.checkConfirmationResultForError(txid, result.value);
|
|
145
|
+
if ((_c = result === null || result === void 0 ? void 0 : result.value) === null || _c === void 0 ? void 0 : _c.err) {
|
|
146
|
+
// Fallback error handling if there's a problem reporting the error in checkConfirmationResultForError
|
|
147
|
+
throw new web3_js_1.SendTransactionError({
|
|
148
|
+
action: 'send',
|
|
149
|
+
signature: txid,
|
|
150
|
+
transactionMessage: `Transaction Failed`,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
154
153
|
slot = result.context.slot;
|
|
155
154
|
// eslint-disable-next-line no-useless-catch
|
|
156
155
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
|
-
import { PublicKey, Transaction, VersionedTransaction } from '@solana/web3.js';
|
|
2
|
+
import { Keypair, PublicKey, Transaction, VersionedTransaction } from '@solana/web3.js';
|
|
3
3
|
import { BN } from '.';
|
|
4
4
|
export type MappedRecord<A extends Record<string, unknown>, B> = {
|
|
5
5
|
[K in keyof A]: B;
|
|
@@ -1096,6 +1096,20 @@ export declare class ModifyOrderPolicy {
|
|
|
1096
1096
|
};
|
|
1097
1097
|
}
|
|
1098
1098
|
export declare const DefaultOrderParams: OrderParams;
|
|
1099
|
+
export type SwiftServerMessage = {
|
|
1100
|
+
slot: BN;
|
|
1101
|
+
swiftOrderSignature: Uint8Array;
|
|
1102
|
+
};
|
|
1103
|
+
export type SwiftOrderParamsMessage = {
|
|
1104
|
+
swiftOrderParams: OptionalOrderParams;
|
|
1105
|
+
expectedOrderId: number;
|
|
1106
|
+
takeProfitOrderParams: SwiftTriggerOrderParams | null;
|
|
1107
|
+
stopLossOrderParams: SwiftTriggerOrderParams | null;
|
|
1108
|
+
};
|
|
1109
|
+
export type SwiftTriggerOrderParams = {
|
|
1110
|
+
triggerPrice: BN;
|
|
1111
|
+
baseAssetAmount: BN;
|
|
1112
|
+
};
|
|
1099
1113
|
export type MakerInfo = {
|
|
1100
1114
|
maker: PublicKey;
|
|
1101
1115
|
makerStats: PublicKey;
|
|
@@ -1112,6 +1126,10 @@ export type ReferrerInfo = {
|
|
|
1112
1126
|
referrer: PublicKey;
|
|
1113
1127
|
referrerStats: PublicKey;
|
|
1114
1128
|
};
|
|
1129
|
+
export declare enum PlaceAndTakeOrderSuccessCondition {
|
|
1130
|
+
PartialFill = 1,
|
|
1131
|
+
FullFill = 2
|
|
1132
|
+
}
|
|
1115
1133
|
type ExactType<T> = Pick<T, keyof T>;
|
|
1116
1134
|
export type BaseTxParams = ExactType<{
|
|
1117
1135
|
computeUnits?: number;
|
|
@@ -1137,11 +1155,13 @@ export interface IWallet {
|
|
|
1137
1155
|
signTransaction(tx: Transaction): Promise<Transaction>;
|
|
1138
1156
|
signAllTransactions(txs: Transaction[]): Promise<Transaction[]>;
|
|
1139
1157
|
publicKey: PublicKey;
|
|
1158
|
+
payer?: Keypair;
|
|
1140
1159
|
}
|
|
1141
1160
|
export interface IVersionedWallet {
|
|
1142
1161
|
signVersionedTransaction(tx: VersionedTransaction): Promise<VersionedTransaction>;
|
|
1143
1162
|
signAllVersionedTransactions(txs: VersionedTransaction[]): Promise<VersionedTransaction[]>;
|
|
1144
1163
|
publicKey: PublicKey;
|
|
1164
|
+
payer?: Keypair;
|
|
1145
1165
|
}
|
|
1146
1166
|
export type FeeStructure = {
|
|
1147
1167
|
feeTiers: FeeTier[];
|
package/lib/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SwapReduceOnly = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.ExchangeStatus = void 0;
|
|
3
|
+
exports.SwapReduceOnly = exports.PlaceAndTakeOrderSuccessCondition = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.ExchangeStatus = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
5
|
// # Utility Types / Enums / Constants
|
|
6
6
|
var ExchangeStatus;
|
|
@@ -325,6 +325,11 @@ exports.DefaultOrderParams = {
|
|
|
325
325
|
auctionStartPrice: null,
|
|
326
326
|
auctionEndPrice: null,
|
|
327
327
|
};
|
|
328
|
+
var PlaceAndTakeOrderSuccessCondition;
|
|
329
|
+
(function (PlaceAndTakeOrderSuccessCondition) {
|
|
330
|
+
PlaceAndTakeOrderSuccessCondition[PlaceAndTakeOrderSuccessCondition["PartialFill"] = 1] = "PartialFill";
|
|
331
|
+
PlaceAndTakeOrderSuccessCondition[PlaceAndTakeOrderSuccessCondition["FullFill"] = 2] = "FullFill";
|
|
332
|
+
})(PlaceAndTakeOrderSuccessCondition = exports.PlaceAndTakeOrderSuccessCondition || (exports.PlaceAndTakeOrderSuccessCondition = {}));
|
|
328
333
|
class SwapReduceOnly {
|
|
329
334
|
}
|
|
330
335
|
exports.SwapReduceOnly = SwapReduceOnly;
|
package/lib/user.d.ts
CHANGED
|
@@ -265,9 +265,10 @@ export declare class User {
|
|
|
265
265
|
* @param estimatedEntryPrice
|
|
266
266
|
* @param marginCategory // allow Initial to be passed in if we are trying to calculate price for DLP de-risking
|
|
267
267
|
* @param includeOpenOrders
|
|
268
|
+
* @param offsetCollateral // allows calculating the liquidation price after this offset collateral is added to the user's account (e.g. : what will the liquidation price be for this position AFTER I deposit $x worth of collateral)
|
|
268
269
|
* @returns Precision : PRICE_PRECISION
|
|
269
270
|
*/
|
|
270
|
-
liquidationPrice(marketIndex: number, positionBaseSizeChange?: BN, estimatedEntryPrice?: BN, marginCategory?: MarginCategory, includeOpenOrders?: boolean): BN;
|
|
271
|
+
liquidationPrice(marketIndex: number, positionBaseSizeChange?: BN, estimatedEntryPrice?: BN, marginCategory?: MarginCategory, includeOpenOrders?: boolean, offsetCollateral?: BN): BN;
|
|
271
272
|
calculateEntriesEffectOnFreeCollateral(market: PerpMarketAccount, oraclePrice: BN, perpPosition: PerpPosition, positionBaseSizeChange: BN, estimatedEntryPrice: BN, includeOpenOrders: boolean): BN;
|
|
272
273
|
calculateFreeCollateralDeltaForPerp(market: PerpMarketAccount, perpPosition: PerpPosition, positionBaseSizeChange: BN, oraclePrice: BN, marginCategory?: MarginCategory, includeOpenOrders?: boolean): BN | undefined;
|
|
273
274
|
calculateFreeCollateralDeltaForSpot(market: SpotMarketAccount, signedTokenAmount: BN, marginCategory?: MarginCategory): BN;
|
|
@@ -278,6 +279,8 @@ export declare class User {
|
|
|
278
279
|
* @returns : Precision PRICE_PRECISION
|
|
279
280
|
*/
|
|
280
281
|
liquidationPriceAfterClose(positionMarketIndex: number, closeQuoteAmount: BN, estimatedEntryPrice?: BN): BN;
|
|
282
|
+
getMarginUSDCRequiredForTrade(targetMarketIndex: number, baseSize: BN): BN;
|
|
283
|
+
getCollateralDepositRequiredForTrade(targetMarketIndex: number, baseSize: BN, collateralIndex: number): BN;
|
|
281
284
|
/**
|
|
282
285
|
* Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
|
|
283
286
|
*
|
package/lib/user.js
CHANGED
|
@@ -15,7 +15,6 @@ const oracles_1 = require("./math/oracles");
|
|
|
15
15
|
const tiers_1 = require("./math/tiers");
|
|
16
16
|
const strictOraclePrice_1 = require("./oracles/strictOraclePrice");
|
|
17
17
|
const fuel_1 = require("./math/fuel");
|
|
18
|
-
const grpcUserAccountSubscriber_1 = require("./accounts/grpcUserAccountSubscriber");
|
|
19
18
|
class User {
|
|
20
19
|
get isSubscribed() {
|
|
21
20
|
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
@@ -24,7 +23,7 @@ class User {
|
|
|
24
23
|
this._isSubscribed = val;
|
|
25
24
|
}
|
|
26
25
|
constructor(config) {
|
|
27
|
-
var _a, _b, _c, _d, _e
|
|
26
|
+
var _a, _b, _c, _d, _e;
|
|
28
27
|
this._isSubscribed = false;
|
|
29
28
|
this.driftClient = config.driftClient;
|
|
30
29
|
this.userAccountPublicKey = config.userAccountPublicKey;
|
|
@@ -34,17 +33,11 @@ class User {
|
|
|
34
33
|
else if (((_b = config.accountSubscription) === null || _b === void 0 ? void 0 : _b.type) === 'custom') {
|
|
35
34
|
this.accountSubscriber = config.accountSubscription.userAccountSubscriber;
|
|
36
35
|
}
|
|
37
|
-
else if (((_c = config.accountSubscription) === null || _c === void 0 ? void 0 : _c.type) === 'grpc') {
|
|
38
|
-
this.accountSubscriber = new grpcUserAccountSubscriber_1.grpcUserAccountSubscriber(config.accountSubscription.configs, config.driftClient.program, config.userAccountPublicKey, {
|
|
39
|
-
resubTimeoutMs: (_d = config.accountSubscription) === null || _d === void 0 ? void 0 : _d.resubTimeoutMs,
|
|
40
|
-
logResubMessages: (_e = config.accountSubscription) === null || _e === void 0 ? void 0 : _e.logResubMessages,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
36
|
else {
|
|
44
37
|
this.accountSubscriber = new webSocketUserAccountSubscriber_1.WebSocketUserAccountSubscriber(config.driftClient.program, config.userAccountPublicKey, {
|
|
45
|
-
resubTimeoutMs: (
|
|
46
|
-
logResubMessages: (
|
|
47
|
-
}, (
|
|
38
|
+
resubTimeoutMs: (_c = config.accountSubscription) === null || _c === void 0 ? void 0 : _c.resubTimeoutMs,
|
|
39
|
+
logResubMessages: (_d = config.accountSubscription) === null || _d === void 0 ? void 0 : _d.logResubMessages,
|
|
40
|
+
}, (_e = config.accountSubscription) === null || _e === void 0 ? void 0 : _e.commitment);
|
|
48
41
|
}
|
|
49
42
|
this.eventEmitter = this.accountSubscriber.eventEmitter;
|
|
50
43
|
}
|
|
@@ -1209,12 +1202,13 @@ class User {
|
|
|
1209
1202
|
* @param estimatedEntryPrice
|
|
1210
1203
|
* @param marginCategory // allow Initial to be passed in if we are trying to calculate price for DLP de-risking
|
|
1211
1204
|
* @param includeOpenOrders
|
|
1205
|
+
* @param offsetCollateral // allows calculating the liquidation price after this offset collateral is added to the user's account (e.g. : what will the liquidation price be for this position AFTER I deposit $x worth of collateral)
|
|
1212
1206
|
* @returns Precision : PRICE_PRECISION
|
|
1213
1207
|
*/
|
|
1214
|
-
liquidationPrice(marketIndex, positionBaseSizeChange = numericConstants_1.ZERO, estimatedEntryPrice = numericConstants_1.ZERO, marginCategory = 'Maintenance', includeOpenOrders = false) {
|
|
1208
|
+
liquidationPrice(marketIndex, positionBaseSizeChange = numericConstants_1.ZERO, estimatedEntryPrice = numericConstants_1.ZERO, marginCategory = 'Maintenance', includeOpenOrders = false, offsetCollateral = numericConstants_1.ZERO) {
|
|
1215
1209
|
const totalCollateral = this.getTotalCollateral(marginCategory);
|
|
1216
1210
|
const marginRequirement = this.getMarginRequirement(marginCategory, undefined, false, includeOpenOrders);
|
|
1217
|
-
let freeCollateral = _1.BN.max(numericConstants_1.ZERO, totalCollateral.sub(marginRequirement));
|
|
1211
|
+
let freeCollateral = _1.BN.max(numericConstants_1.ZERO, totalCollateral.sub(marginRequirement)).add(offsetCollateral);
|
|
1218
1212
|
const oracle = this.driftClient.getPerpMarketAccount(marketIndex).amm.oracle;
|
|
1219
1213
|
const oraclePrice = this.driftClient.getOracleDataForPerpMarket(marketIndex).price;
|
|
1220
1214
|
const market = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
@@ -1374,6 +1368,12 @@ class User {
|
|
|
1374
1368
|
.neg();
|
|
1375
1369
|
return this.liquidationPrice(positionMarketIndex, closeBaseAmount, estimatedEntryPrice);
|
|
1376
1370
|
}
|
|
1371
|
+
getMarginUSDCRequiredForTrade(targetMarketIndex, baseSize) {
|
|
1372
|
+
return (0, margin_1.calculateMarginUSDCRequiredForTrade)(this.driftClient, targetMarketIndex, baseSize, this.getUserAccount().maxMarginRatio);
|
|
1373
|
+
}
|
|
1374
|
+
getCollateralDepositRequiredForTrade(targetMarketIndex, baseSize, collateralIndex) {
|
|
1375
|
+
return (0, margin_1.calculateCollateralDepositRequiredForTrade)(this.driftClient, targetMarketIndex, baseSize, collateralIndex, this.getUserAccount().maxMarginRatio);
|
|
1376
|
+
}
|
|
1377
1377
|
/**
|
|
1378
1378
|
* Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
|
|
1379
1379
|
*
|
package/lib/userConfig.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DriftClient } from './driftClient';
|
|
2
2
|
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
3
3
|
import { BulkAccountLoader } from './accounts/bulkAccountLoader';
|
|
4
|
-
import {
|
|
4
|
+
import { UserAccountSubscriber } from './accounts/types';
|
|
5
5
|
export type UserConfig = {
|
|
6
6
|
accountSubscription?: UserSubscriptionConfig;
|
|
7
7
|
driftClient: DriftClient;
|
|
@@ -18,9 +18,4 @@ export type UserSubscriptionConfig = {
|
|
|
18
18
|
} | {
|
|
19
19
|
type: 'custom';
|
|
20
20
|
userAccountSubscriber: UserAccountSubscriber;
|
|
21
|
-
} | {
|
|
22
|
-
type: 'grpc';
|
|
23
|
-
resubTimeoutMs?: number;
|
|
24
|
-
logResubMessages?: boolean;
|
|
25
|
-
configs: GrpcConfigs;
|
|
26
21
|
};
|
package/lib/userMap/userMap.js
CHANGED
|
@@ -9,7 +9,6 @@ const memcmp_1 = require("../memcmp");
|
|
|
9
9
|
const WebsocketSubscription_1 = require("./WebsocketSubscription");
|
|
10
10
|
const PollingSubscription_1 = require("./PollingSubscription");
|
|
11
11
|
const user_1 = require("../decode/user");
|
|
12
|
-
const grpcSubscription_1 = require("./grpcSubscription");
|
|
13
12
|
const MAX_USER_ACCOUNT_SIZE_BYTES = 4376;
|
|
14
13
|
class UserMap {
|
|
15
14
|
/**
|
|
@@ -53,19 +52,6 @@ class UserMap {
|
|
|
53
52
|
skipInitialLoad: config.skipInitialLoad,
|
|
54
53
|
});
|
|
55
54
|
}
|
|
56
|
-
else if (config.subscriptionConfig.type === 'grpc') {
|
|
57
|
-
this.subscription = new grpcSubscription_1.grpcSubscription({
|
|
58
|
-
configs: config.subscriptionConfig.configs,
|
|
59
|
-
userMap: this,
|
|
60
|
-
commitment: this.commitment,
|
|
61
|
-
resubOpts: {
|
|
62
|
-
resubTimeoutMs: config.subscriptionConfig.resubTimeoutMs,
|
|
63
|
-
logResubMessages: config.subscriptionConfig.logResubMessages,
|
|
64
|
-
},
|
|
65
|
-
skipInitialLoad: config.skipInitialLoad,
|
|
66
|
-
decodeFn,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
55
|
else {
|
|
70
56
|
this.subscription = new WebsocketSubscription_1.WebsocketSubscription({
|
|
71
57
|
userMap: this,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Commitment, Connection } from '@solana/web3.js';
|
|
2
2
|
import { DriftClient } from '../driftClient';
|
|
3
|
-
import { GrpcConfigs } from '../accounts/types';
|
|
4
3
|
export type UserAccountFilterCriteria = {
|
|
5
4
|
hasOpenOrders: boolean;
|
|
6
5
|
};
|
|
@@ -18,12 +17,6 @@ export type UserMapConfig = {
|
|
|
18
17
|
type: 'polling';
|
|
19
18
|
frequency: number;
|
|
20
19
|
commitment?: Commitment;
|
|
21
|
-
} | {
|
|
22
|
-
type: 'grpc';
|
|
23
|
-
configs: GrpcConfigs;
|
|
24
|
-
resubTimeoutMs?: number;
|
|
25
|
-
logResubMessages?: boolean;
|
|
26
|
-
commitment?: Commitment;
|
|
27
20
|
} | {
|
|
28
21
|
type: 'websocket';
|
|
29
22
|
resubTimeoutMs?: number;
|
package/lib/userStatsConfig.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { DriftClient } from './driftClient';
|
|
2
2
|
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
3
3
|
import { BulkAccountLoader } from './accounts/bulkAccountLoader';
|
|
4
|
-
import { GrpcConfigs } from './accounts/types';
|
|
5
4
|
export type UserStatsConfig = {
|
|
6
5
|
accountSubscription?: UserStatsSubscriptionConfig;
|
|
7
6
|
driftClient: DriftClient;
|
|
@@ -17,9 +16,4 @@ export type UserStatsSubscriptionConfig = {
|
|
|
17
16
|
accountLoader: BulkAccountLoader;
|
|
18
17
|
} | {
|
|
19
18
|
type: 'custom';
|
|
20
|
-
} | {
|
|
21
|
-
type: 'grpc';
|
|
22
|
-
resubTimeoutMs?: number;
|
|
23
|
-
logResubMessages?: boolean;
|
|
24
|
-
configs: GrpcConfigs;
|
|
25
19
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Connection, SignatureStatus, TransactionConfirmationStatus } from '@solana/web3.js';
|
|
2
|
+
/**
|
|
3
|
+
* Class to await for transaction confirmations in an optimised manner. It tracks a shared list of all pending transactions and fetches them in bulk in a shared RPC request whenever they have an "overlapping" polling interval. E.g. tx1 with an interval of 200ms and tx2 with an interval of 300ms (if sent at the same time) will be fetched together at at 600ms, 1200ms, 1800ms, etc.
|
|
4
|
+
*/
|
|
5
|
+
export declare class TransactionConfirmationManager {
|
|
6
|
+
private connection;
|
|
7
|
+
private pendingConfirmations;
|
|
8
|
+
private intervalId;
|
|
9
|
+
constructor(connection: Connection);
|
|
10
|
+
confirmTransaction(txSig: string, desiredConfirmationStatus?: TransactionConfirmationStatus, timeout?: number, pollInterval?: number, searchTransactionHistory?: boolean): Promise<SignatureStatus>;
|
|
11
|
+
private startConfirmationLoop;
|
|
12
|
+
private checkPendingConfirmations;
|
|
13
|
+
private checkTransactionStatuses;
|
|
14
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransactionConfirmationManager = void 0;
|
|
4
|
+
const config_1 = require("../config");
|
|
5
|
+
const confirmationStatusValues = {
|
|
6
|
+
processed: 0,
|
|
7
|
+
confirmed: 1,
|
|
8
|
+
finalized: 2,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Class to await for transaction confirmations in an optimised manner. It tracks a shared list of all pending transactions and fetches them in bulk in a shared RPC request whenever they have an "overlapping" polling interval. E.g. tx1 with an interval of 200ms and tx2 with an interval of 300ms (if sent at the same time) will be fetched together at at 600ms, 1200ms, 1800ms, etc.
|
|
12
|
+
*/
|
|
13
|
+
class TransactionConfirmationManager {
|
|
14
|
+
constructor(connection) {
|
|
15
|
+
this.pendingConfirmations = new Map();
|
|
16
|
+
this.intervalId = null;
|
|
17
|
+
this.connection = connection;
|
|
18
|
+
}
|
|
19
|
+
async confirmTransaction(txSig, desiredConfirmationStatus = config_1.DEFAULT_CONFIRMATION_OPTS.commitment, timeout = 30000, pollInterval = 1000, searchTransactionHistory = false) {
|
|
20
|
+
// Interval must be > 400ms and a multiple of 100ms
|
|
21
|
+
if (pollInterval < 400 || pollInterval % 100 !== 0) {
|
|
22
|
+
throw new Error('Transaction confirmation polling interval must be at least 400ms and a multiple of 100ms');
|
|
23
|
+
}
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
this.pendingConfirmations.set(txSig, {
|
|
26
|
+
txSig,
|
|
27
|
+
desiredConfirmationStatus,
|
|
28
|
+
timeout,
|
|
29
|
+
pollInterval,
|
|
30
|
+
searchTransactionHistory,
|
|
31
|
+
startTime: Date.now(),
|
|
32
|
+
resolve,
|
|
33
|
+
reject,
|
|
34
|
+
});
|
|
35
|
+
if (!this.intervalId) {
|
|
36
|
+
this.startConfirmationLoop();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
startConfirmationLoop() {
|
|
41
|
+
this.intervalId = setInterval(() => this.checkPendingConfirmations(), 100);
|
|
42
|
+
}
|
|
43
|
+
async checkPendingConfirmations() {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
const transactionsToCheck = [];
|
|
46
|
+
for (const [txSig, request] of this.pendingConfirmations.entries()) {
|
|
47
|
+
if (now - request.startTime >= request.timeout) {
|
|
48
|
+
request.reject(new Error(`Transaction confirmation timeout after ${request.timeout}ms`));
|
|
49
|
+
this.pendingConfirmations.delete(txSig);
|
|
50
|
+
}
|
|
51
|
+
else if ((now - request.startTime) % request.pollInterval < 100) {
|
|
52
|
+
transactionsToCheck.push(request);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (transactionsToCheck.length > 0) {
|
|
56
|
+
await this.checkTransactionStatuses(transactionsToCheck);
|
|
57
|
+
}
|
|
58
|
+
if (this.pendingConfirmations.size === 0 && this.intervalId) {
|
|
59
|
+
clearInterval(this.intervalId);
|
|
60
|
+
this.intervalId = null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async checkTransactionStatuses(requests) {
|
|
64
|
+
const txSigs = requests.map((request) => request.txSig);
|
|
65
|
+
const { value: statuses } = await this.connection.getSignatureStatuses(txSigs, {
|
|
66
|
+
searchTransactionHistory: requests.some((req) => req.searchTransactionHistory),
|
|
67
|
+
});
|
|
68
|
+
if (!statuses || statuses.length !== txSigs.length) {
|
|
69
|
+
throw new Error('Failed to get signature statuses');
|
|
70
|
+
}
|
|
71
|
+
for (let i = 0; i < statuses.length; i++) {
|
|
72
|
+
const status = statuses[i];
|
|
73
|
+
const request = requests[i];
|
|
74
|
+
if (status === null) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (status.err) {
|
|
78
|
+
request.reject(new Error(`Transaction failed: ${JSON.stringify(status.err)}`));
|
|
79
|
+
this.pendingConfirmations.delete(request.txSig);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (confirmationStatusValues[status.confirmationStatus] === undefined ||
|
|
83
|
+
confirmationStatusValues[request.desiredConfirmationStatus] ===
|
|
84
|
+
undefined) {
|
|
85
|
+
throw new Error(`Invalid confirmation status when awaiting confirmation: ${status.confirmationStatus}`);
|
|
86
|
+
}
|
|
87
|
+
if (status.confirmationStatus &&
|
|
88
|
+
confirmationStatusValues[status.confirmationStatus] >=
|
|
89
|
+
confirmationStatusValues[request.desiredConfirmationStatus]) {
|
|
90
|
+
request.resolve(status);
|
|
91
|
+
this.pendingConfirmations.delete(request.txSig);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.TransactionConfirmationManager = TransactionConfirmationManager;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.96.0-beta.
|
|
3
|
+
"version": "2.96.0-beta.20",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -37,16 +37,14 @@
|
|
|
37
37
|
"@coral-xyz/anchor": "0.28.0",
|
|
38
38
|
"@coral-xyz/anchor-30": "npm:@coral-xyz/anchor@0.30.1",
|
|
39
39
|
"@ellipsis-labs/phoenix-sdk": "^1.4.2",
|
|
40
|
-
"@
|
|
41
|
-
"@openbook-dex/openbook-v2": "^0.2.10",
|
|
40
|
+
"@openbook-dex/openbook-v2": "0.2.10",
|
|
42
41
|
"@project-serum/serum": "^0.13.38",
|
|
43
42
|
"@pythnetwork/client": "2.5.3",
|
|
44
43
|
"@pythnetwork/price-service-sdk": "^1.7.1",
|
|
45
44
|
"@pythnetwork/pyth-solana-receiver": "^0.7.0",
|
|
46
45
|
"@solana/spl-token": "0.3.7",
|
|
47
46
|
"@solana/web3.js": "1.92.3",
|
|
48
|
-
"@switchboard-xyz/on-demand": "1.2.
|
|
49
|
-
"@triton-one/yellowstone-grpc": "^0.6.0",
|
|
47
|
+
"@switchboard-xyz/on-demand": "1.2.42",
|
|
50
48
|
"anchor-bankrun": "^0.3.0",
|
|
51
49
|
"node-cache": "^5.1.2",
|
|
52
50
|
"rpc-websockets": "7.5.1",
|
|
@@ -58,6 +56,7 @@
|
|
|
58
56
|
"devDependencies": {
|
|
59
57
|
"@types/big.js": "^6.2.0",
|
|
60
58
|
"@types/bn.js": "^5.1.3",
|
|
59
|
+
"@types/bs58": "^4.0.4",
|
|
61
60
|
"@types/chai": "^4.3.1",
|
|
62
61
|
"@types/jest": "^28.1.3",
|
|
63
62
|
"@types/mocha": "^9.1.1",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
DataAndSlot,
|
|
3
2
|
AccountToPoll,
|
|
3
|
+
DataAndSlot,
|
|
4
|
+
DelistedMarketSetting,
|
|
4
5
|
DriftClientAccountEvents,
|
|
5
6
|
DriftClientAccountSubscriber,
|
|
6
7
|
NotSubscribedError,
|
|
@@ -10,18 +11,18 @@ import { Program } from '@coral-xyz/anchor';
|
|
|
10
11
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
11
12
|
import { EventEmitter } from 'events';
|
|
12
13
|
import {
|
|
13
|
-
SpotMarketAccount,
|
|
14
14
|
PerpMarketAccount,
|
|
15
|
+
SpotMarketAccount,
|
|
15
16
|
StateAccount,
|
|
16
17
|
UserAccount,
|
|
17
18
|
} from '../types';
|
|
18
19
|
import {
|
|
19
20
|
getDriftStateAccountPublicKey,
|
|
20
|
-
getSpotMarketPublicKey,
|
|
21
21
|
getPerpMarketPublicKey,
|
|
22
|
+
getSpotMarketPublicKey,
|
|
22
23
|
} from '../addresses/pda';
|
|
23
24
|
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
24
|
-
import { capitalize } from './utils';
|
|
25
|
+
import { capitalize, findDelistedPerpMarketsAndOracles } from './utils';
|
|
25
26
|
import { PublicKey } from '@solana/web3.js';
|
|
26
27
|
import { OracleInfo, OraclePriceData } from '../oracles/types';
|
|
27
28
|
import { OracleClientCache } from '../oracles/oracleClientCache';
|
|
@@ -58,6 +59,7 @@ export class PollingDriftClientAccountSubscriber
|
|
|
58
59
|
spotOracleStringMap = new Map<number, string>();
|
|
59
60
|
oracles = new Map<string, DataAndSlot<OraclePriceData>>();
|
|
60
61
|
user?: DataAndSlot<UserAccount>;
|
|
62
|
+
delistedMarketSetting: DelistedMarketSetting;
|
|
61
63
|
|
|
62
64
|
private isSubscribing = false;
|
|
63
65
|
private subscriptionPromise: Promise<boolean>;
|
|
@@ -69,7 +71,8 @@ export class PollingDriftClientAccountSubscriber
|
|
|
69
71
|
perpMarketIndexes: number[],
|
|
70
72
|
spotMarketIndexes: number[],
|
|
71
73
|
oracleInfos: OracleInfo[],
|
|
72
|
-
shouldFindAllMarketsAndOracles: boolean
|
|
74
|
+
shouldFindAllMarketsAndOracles: boolean,
|
|
75
|
+
delistedMarketSetting: DelistedMarketSetting
|
|
73
76
|
) {
|
|
74
77
|
this.isSubscribed = false;
|
|
75
78
|
this.program = program;
|
|
@@ -79,6 +82,7 @@ export class PollingDriftClientAccountSubscriber
|
|
|
79
82
|
this.spotMarketIndexes = spotMarketIndexes;
|
|
80
83
|
this.oracleInfos = oracleInfos;
|
|
81
84
|
this.shouldFindAllMarketsAndOracles = shouldFindAllMarketsAndOracles;
|
|
85
|
+
this.delistedMarketSetting = delistedMarketSetting;
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
public async subscribe(): Promise<boolean> {
|
|
@@ -120,6 +124,8 @@ export class PollingDriftClientAccountSubscriber
|
|
|
120
124
|
this.eventEmitter.emit('update');
|
|
121
125
|
}
|
|
122
126
|
|
|
127
|
+
this.handleDelistedMarkets();
|
|
128
|
+
|
|
123
129
|
await Promise.all([this.setPerpOracleMap(), this.setSpotOracleMap()]);
|
|
124
130
|
|
|
125
131
|
this.isSubscribing = false;
|
|
@@ -500,6 +506,36 @@ export class PollingDriftClientAccountSubscriber
|
|
|
500
506
|
await Promise.all(oraclePromises);
|
|
501
507
|
}
|
|
502
508
|
|
|
509
|
+
handleDelistedMarkets(): void {
|
|
510
|
+
if (this.delistedMarketSetting === DelistedMarketSetting.Subscribe) {
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const { perpMarketIndexes, oracles } = findDelistedPerpMarketsAndOracles(
|
|
515
|
+
this.getMarketAccountsAndSlots(),
|
|
516
|
+
this.getSpotMarketAccountsAndSlots()
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
for (const perpMarketIndex of perpMarketIndexes) {
|
|
520
|
+
const perpMarketPubkey = this.perpMarket.get(perpMarketIndex).data.pubkey;
|
|
521
|
+
const callbackId = this.accountsToPoll.get(
|
|
522
|
+
perpMarketPubkey.toBase58()
|
|
523
|
+
).callbackId;
|
|
524
|
+
this.accountLoader.removeAccount(perpMarketPubkey, callbackId);
|
|
525
|
+
if (this.delistedMarketSetting === DelistedMarketSetting.Discard) {
|
|
526
|
+
this.perpMarket.delete(perpMarketIndex);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
for (const oracle of oracles) {
|
|
531
|
+
const callbackId = this.oraclesToPoll.get(oracle.toBase58()).callbackId;
|
|
532
|
+
this.accountLoader.removeAccount(oracle, callbackId);
|
|
533
|
+
if (this.delistedMarketSetting === DelistedMarketSetting.Discard) {
|
|
534
|
+
this.oracles.delete(oracle.toBase58());
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
503
539
|
assertIsSubscribed(): void {
|
|
504
540
|
if (!this.isSubscribed) {
|
|
505
541
|
throw new NotSubscribedError(
|
package/src/accounts/types.ts
CHANGED
|
@@ -12,8 +12,6 @@ import { EventEmitter } from 'events';
|
|
|
12
12
|
import { Context, PublicKey } from '@solana/web3.js';
|
|
13
13
|
import { Account } from '@solana/spl-token';
|
|
14
14
|
import { OracleInfo, OraclePriceData } from '..';
|
|
15
|
-
import { CommitmentLevel } from '@triton-one/yellowstone-grpc';
|
|
16
|
-
import { ChannelOptions } from '@grpc/grpc-js';
|
|
17
15
|
|
|
18
16
|
export interface AccountSubscriber<T> {
|
|
19
17
|
dataAndSlot?: DataAndSlot<T>;
|
|
@@ -86,6 +84,12 @@ export interface DriftClientAccountSubscriber {
|
|
|
86
84
|
updateAccountLoaderPollingFrequency?: (pollingFrequency: number) => void;
|
|
87
85
|
}
|
|
88
86
|
|
|
87
|
+
export enum DelistedMarketSetting {
|
|
88
|
+
Unsubscribe,
|
|
89
|
+
Subscribe,
|
|
90
|
+
Discard,
|
|
91
|
+
}
|
|
92
|
+
|
|
89
93
|
export interface UserAccountEvents {
|
|
90
94
|
userAccountUpdate: (payload: UserAccount) => void;
|
|
91
95
|
update: void;
|
|
@@ -203,10 +207,3 @@ export interface UserStatsAccountSubscriber {
|
|
|
203
207
|
|
|
204
208
|
getUserStatsAccountAndSlot(): DataAndSlot<UserStatsAccount>;
|
|
205
209
|
}
|
|
206
|
-
|
|
207
|
-
export type GrpcConfigs = {
|
|
208
|
-
endpoint: string;
|
|
209
|
-
token: string;
|
|
210
|
-
commitmentLevel?: CommitmentLevel;
|
|
211
|
-
channelOptions?: ChannelOptions;
|
|
212
|
-
};
|
package/src/accounts/utils.ts
CHANGED
|
@@ -1,3 +1,45 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { DataAndSlot } from './types';
|
|
3
|
+
import { isVariant, PerpMarketAccount, SpotMarketAccount } from '../types';
|
|
4
|
+
|
|
1
5
|
export function capitalize(value: string): string {
|
|
2
6
|
return value[0].toUpperCase() + value.slice(1);
|
|
3
7
|
}
|
|
8
|
+
|
|
9
|
+
export function findDelistedPerpMarketsAndOracles(
|
|
10
|
+
perpMarkets: DataAndSlot<PerpMarketAccount>[],
|
|
11
|
+
spotMarkets: DataAndSlot<SpotMarketAccount>[]
|
|
12
|
+
): { perpMarketIndexes: number[]; oracles: PublicKey[] } {
|
|
13
|
+
const delistedPerpMarketIndexes = [];
|
|
14
|
+
const delistedOracles = [];
|
|
15
|
+
for (const perpMarket of perpMarkets) {
|
|
16
|
+
if (!perpMarket.data) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (isVariant(perpMarket.data.status, 'delisted')) {
|
|
21
|
+
delistedPerpMarketIndexes.push(perpMarket.data.marketIndex);
|
|
22
|
+
delistedOracles.push(perpMarket.data.amm.oracle);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// make sure oracle isn't used by spot market
|
|
27
|
+
const filteredDelistedOracles = [];
|
|
28
|
+
for (const delistedOracle of delistedOracles) {
|
|
29
|
+
for (const spotMarket of spotMarkets) {
|
|
30
|
+
if (!spotMarket.data) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (spotMarket.data.oracle.equals(delistedOracle)) {
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
filteredDelistedOracles.push(delistedOracle);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
perpMarketIndexes: delistedPerpMarketIndexes,
|
|
43
|
+
oracles: filteredDelistedOracles,
|
|
44
|
+
};
|
|
45
|
+
}
|