@drift-labs/sdk 2.96.0-beta.0 → 2.96.0-beta.10
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/VERSION +1 -1
- package/lib/constants/perpMarkets.js +10 -0
- package/lib/constants/spotMarkets.js +2 -1
- package/lib/driftClient.d.ts +42 -2
- package/lib/driftClient.js +125 -7
- package/lib/events/eventSubscriber.d.ts +7 -0
- package/lib/events/eventSubscriber.js +69 -31
- package/lib/events/eventsServerLogProvider.d.ts +21 -0
- package/lib/events/eventsServerLogProvider.js +121 -0
- package/lib/events/pollingLogProvider.js +1 -1
- package/lib/events/types.d.ts +12 -5
- package/lib/events/types.js +5 -1
- package/lib/events/webSocketLogProvider.js +2 -2
- package/lib/idl/drift.json +104 -0
- package/lib/math/margin.d.ts +16 -1
- package/lib/math/margin.js +67 -1
- package/lib/orderParams.js +8 -8
- package/lib/types.d.ts +10 -1
- package/lib/user.d.ts +4 -1
- package/lib/user.js +9 -2
- package/package.json +2 -2
- package/src/constants/perpMarkets.ts +10 -0
- package/src/constants/spotMarkets.ts +3 -1
- package/src/driftClient.ts +309 -11
- package/src/events/eventSubscriber.ts +132 -54
- package/src/events/eventsServerLogProvider.ts +152 -0
- package/src/events/pollingLogProvider.ts +1 -1
- package/src/events/types.ts +29 -6
- package/src/events/webSocketLogProvider.ts +4 -4
- package/src/idl/drift.json +104 -0
- package/src/math/margin.ts +137 -1
- package/src/orderParams.ts +20 -12
- package/src/types.ts +16 -1
- package/src/user.ts +35 -2
- package/tests/ci/idl.ts +12 -3
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.96.0-beta.
|
|
1
|
+
2.96.0-beta.10
|
|
@@ -778,6 +778,16 @@ exports.MainnetPerpMarkets = [
|
|
|
778
778
|
oracleSource: __1.OracleSource.PYTH_PULL,
|
|
779
779
|
pythFeedId: '0x8963217838ab4cf5cadc172203c1f0b763fbaa45f346d8ee50ba994bbcac3026',
|
|
780
780
|
},
|
|
781
|
+
{
|
|
782
|
+
fullName: 'LANDO-F1-SGP-WIN-BET',
|
|
783
|
+
category: ['Prediction', 'Sports'],
|
|
784
|
+
symbol: 'LANDO-F1-SGP-WIN-BET',
|
|
785
|
+
baseAssetSymbol: 'LANDO-F1-SGP-WIN',
|
|
786
|
+
marketIndex: 43,
|
|
787
|
+
oracle: new web3_js_1.PublicKey('DpJz7rjTJLxxnuqrqZTUjMWtnaMFAEfZUv5ATdb9HTh1'),
|
|
788
|
+
launchTs: 1726646453000,
|
|
789
|
+
oracleSource: __1.OracleSource.Prelaunch,
|
|
790
|
+
},
|
|
781
791
|
];
|
|
782
792
|
exports.PerpMarkets = {
|
|
783
793
|
devnet: exports.DevnetPerpMarkets,
|
|
@@ -94,7 +94,7 @@ exports.MainnetSpotMarkets = [
|
|
|
94
94
|
precision: new __1.BN(10).pow(numericConstants_1.EIGHT),
|
|
95
95
|
precisionExp: numericConstants_1.EIGHT,
|
|
96
96
|
serumMarket: new web3_js_1.PublicKey('3BAKsQd3RuhZKES2DGysMhjBdwjZYKYmxRqnSMtZ4KSN'),
|
|
97
|
-
pythFeedId: '
|
|
97
|
+
pythFeedId: '0xc9d8b075a5c69303365ae23633d4e085199bf5c520a3b90fed1322a0342ffc33',
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
symbol: 'wETH',
|
|
@@ -280,6 +280,7 @@ exports.MainnetSpotMarkets = [
|
|
|
280
280
|
precision: new __1.BN(10).pow(numericConstants_1.SIX),
|
|
281
281
|
precisionExp: numericConstants_1.SIX,
|
|
282
282
|
launchTs: 1719415157000,
|
|
283
|
+
pythFeedId: '0xc811abc82b4bad1f9bd711a2773ccaa935b03ecef974236942cec5e0eb845a3a',
|
|
283
284
|
},
|
|
284
285
|
{
|
|
285
286
|
symbol: 'POPCAT',
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/// <reference types="node" />
|
|
4
4
|
import { AnchorProvider, BN, Program, ProgramAccount } from '@coral-xyz/anchor';
|
|
5
5
|
import { Idl as Idl30, Program as Program30 } from '@coral-xyz/anchor-30';
|
|
6
|
-
import { StateAccount, IWallet, PositionDirection, UserAccount, PerpMarketAccount, OrderParams, Order, SpotMarketAccount, SpotPosition, MakerInfo, TakerInfo, OptionalOrderParams, ReferrerInfo, MarketType, TxParams, SerumV3FulfillmentConfigAccount, ReferrerNameAccount, OrderTriggerCondition, PerpMarketExtendedInfo, UserStatsAccount, PhoenixV1FulfillmentConfigAccount, ModifyOrderPolicy, SwapReduceOnly, SettlePnlMode, SignedTxData, MappedRecord, OpenbookV2FulfillmentConfigAccount } from './types';
|
|
6
|
+
import { StateAccount, IWallet, PositionDirection, UserAccount, PerpMarketAccount, OrderParams, Order, SpotMarketAccount, SpotPosition, MakerInfo, TakerInfo, OptionalOrderParams, ReferrerInfo, MarketType, TxParams, SerumV3FulfillmentConfigAccount, ReferrerNameAccount, OrderTriggerCondition, PerpMarketExtendedInfo, UserStatsAccount, PhoenixV1FulfillmentConfigAccount, ModifyOrderPolicy, SwapReduceOnly, SettlePnlMode, SignedTxData, MappedRecord, OpenbookV2FulfillmentConfigAccount, SwiftOrderParamsMessage } from './types';
|
|
7
7
|
import * as anchor from '@coral-xyz/anchor';
|
|
8
8
|
import { Connection, PublicKey, TransactionSignature, ConfirmOptions, Transaction, TransactionInstruction, AccountMeta, Signer, AddressLookupTableAccount, TransactionVersion, VersionedTransaction, BlockhashWithExpiryBlockHeight } from '@solana/web3.js';
|
|
9
9
|
import { TokenFaucet } from './tokenFaucet';
|
|
@@ -239,6 +239,7 @@ export declare class DriftClient {
|
|
|
239
239
|
*/
|
|
240
240
|
getAssociatedTokenAccount(marketIndex: number, useNative?: boolean, tokenProgram?: anchor.web3.PublicKey): Promise<PublicKey>;
|
|
241
241
|
createAssociatedTokenAccountIdempotentInstruction(account: PublicKey, payer: PublicKey, owner: PublicKey, mint: PublicKey, tokenProgram?: anchor.web3.PublicKey): TransactionInstruction;
|
|
242
|
+
getDepositTxnIx(amount: BN, marketIndex: number, associatedTokenAccount: PublicKey, subAccountId?: number, reduceOnly?: boolean): Promise<TransactionInstruction[]>;
|
|
242
243
|
createDepositTxn(amount: BN, marketIndex: number, associatedTokenAccount: PublicKey, subAccountId?: number, reduceOnly?: boolean, txParams?: TxParams): Promise<VersionedTransaction | Transaction>;
|
|
243
244
|
/**
|
|
244
245
|
* Deposit funds into the given spot market
|
|
@@ -261,6 +262,10 @@ export declare class DriftClient {
|
|
|
261
262
|
getTokenProgramForSpotMarket(spotMarketAccount: SpotMarketAccount): PublicKey;
|
|
262
263
|
addTokenMintToRemainingAccounts(spotMarketAccount: SpotMarketAccount, remainingAccounts: AccountMeta[]): void;
|
|
263
264
|
getAssociatedTokenAccountCreationIx(tokenMintAddress: PublicKey, associatedTokenAddress: PublicKey, tokenProgram: PublicKey): anchor.web3.TransactionInstruction;
|
|
265
|
+
createInitializeUserAccountAndDepositCollateralIxs(amount: BN, userTokenAccount: PublicKey, marketIndex?: number, subAccountId?: number, name?: string, fromSubAccountId?: number, referrerInfo?: ReferrerInfo, donateAmount?: BN, customMaxMarginRatio?: number): Promise<{
|
|
266
|
+
ixs: TransactionInstruction[];
|
|
267
|
+
userAccountPublicKey: PublicKey;
|
|
268
|
+
}>;
|
|
264
269
|
createInitializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, marketIndex?: number, subAccountId?: number, name?: string, fromSubAccountId?: number, referrerInfo?: ReferrerInfo, donateAmount?: BN, txParams?: TxParams, customMaxMarginRatio?: number): Promise<[Transaction | VersionedTransaction, PublicKey]>;
|
|
265
270
|
/**
|
|
266
271
|
* Creates the User account for a user, and deposits some initial collateral
|
|
@@ -340,7 +345,10 @@ export declare class DriftClient {
|
|
|
340
345
|
signedSettlePnlTx?: Transaction;
|
|
341
346
|
}>;
|
|
342
347
|
placePerpOrder(orderParams: OptionalOrderParams, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
|
|
343
|
-
getPlacePerpOrderIx(orderParams: OptionalOrderParams, subAccountId?: number
|
|
348
|
+
getPlacePerpOrderIx(orderParams: OptionalOrderParams, subAccountId?: number, depositToTradeArgs?: {
|
|
349
|
+
isMakingNewAccount: boolean;
|
|
350
|
+
depositMarketIndex: number;
|
|
351
|
+
}): Promise<TransactionInstruction>;
|
|
344
352
|
updateAMMs(marketIndexes: number[], txParams?: TxParams): Promise<TransactionSignature>;
|
|
345
353
|
getUpdateAMMsIx(marketIndexes: number[]): Promise<TransactionInstruction>;
|
|
346
354
|
settleExpiredMarket(marketIndex: number, txParams?: TxParams): Promise<TransactionSignature>;
|
|
@@ -497,6 +505,38 @@ export declare class DriftClient {
|
|
|
497
505
|
getPlaceAndTakePerpOrderIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, subAccountId?: number): Promise<TransactionInstruction>;
|
|
498
506
|
placeAndMakePerpOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
|
|
499
507
|
getPlaceAndMakePerpOrderIx(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo, subAccountId?: number): Promise<TransactionInstruction>;
|
|
508
|
+
signTakerOrderParams(orderParamsMessage: SwiftOrderParamsMessage): Promise<Buffer>;
|
|
509
|
+
getEncodedSwiftOrderParamsMessage(orderParamsMessage: SwiftOrderParamsMessage): Buffer;
|
|
510
|
+
decodeSwiftTakerOrderParamsMessage(encodedMessage: Buffer): SwiftOrderParamsMessage;
|
|
511
|
+
signMessage(message: Uint8Array): Promise<Buffer>;
|
|
512
|
+
assembleSwiftServerMessage(message: Buffer, signature: Buffer, takerPubkey: PublicKey, marketIndex: number, marketType: MarketType, slot: number | BN): {
|
|
513
|
+
message: string;
|
|
514
|
+
signature: string;
|
|
515
|
+
taker_pubkey: string;
|
|
516
|
+
market_index: number;
|
|
517
|
+
market_type: 'perp' | 'spot';
|
|
518
|
+
slot: BN;
|
|
519
|
+
};
|
|
520
|
+
placeSwiftTakerOrder(takerOrderParamsMessage: Buffer, takerSignature: Buffer, marketIndex: number, takerInfo: {
|
|
521
|
+
taker: PublicKey;
|
|
522
|
+
takerStats: PublicKey;
|
|
523
|
+
takerUserAccount: UserAccount;
|
|
524
|
+
}, txParams?: TxParams): Promise<TransactionSignature>;
|
|
525
|
+
getPlaceSwiftTakerPerpOrderIx(takerOrderParamsMessage: Buffer, takerSignature: Buffer, marketIndex: number, takerInfo: {
|
|
526
|
+
taker: PublicKey;
|
|
527
|
+
takerStats: PublicKey;
|
|
528
|
+
takerUserAccount: UserAccount;
|
|
529
|
+
}): Promise<TransactionInstruction[]>;
|
|
530
|
+
placeAndMakeSwiftPerpOrder(encodedTakerOrderParamsMessage: Buffer, takerSignature: Buffer, takerExpectedOrderId: number, takerInfo: {
|
|
531
|
+
taker: PublicKey;
|
|
532
|
+
takerStats: PublicKey;
|
|
533
|
+
takerUserAccount: UserAccount;
|
|
534
|
+
}, orderParams: OptionalOrderParams, referrerInfo?: ReferrerInfo, txParams?: TxParams, subAccountId?: number): Promise<TransactionSignature>;
|
|
535
|
+
getPlaceAndMakeSwiftPerpOrderIxs(encodedTakerOrderParamsMessage: Buffer, takerSignature: Buffer, takerExpectedOrderId: number, takerInfo: {
|
|
536
|
+
taker: PublicKey;
|
|
537
|
+
takerStats: PublicKey;
|
|
538
|
+
takerUserAccount: UserAccount;
|
|
539
|
+
}, orderParams: OptionalOrderParams, referrerInfo?: ReferrerInfo, subAccountId?: number): Promise<TransactionInstruction[]>;
|
|
500
540
|
preparePlaceAndTakeSpotOrder(orderParams: OptionalOrderParams, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams, subAccountId?: number): Promise<{
|
|
501
541
|
placeAndTakeSpotOrderTx: anchor.web3.Transaction | anchor.web3.VersionedTransaction;
|
|
502
542
|
}>;
|
package/lib/driftClient.js
CHANGED
|
@@ -68,6 +68,7 @@ const utils_2 = require("./tx/utils");
|
|
|
68
68
|
const pyth_solana_receiver_json_1 = __importDefault(require("./idl/pyth_solana_receiver.json"));
|
|
69
69
|
const on_demand_1 = require("@switchboard-xyz/on-demand");
|
|
70
70
|
const switchboard_on_demand_30_json_1 = __importDefault(require("./idl/switchboard_on_demand_30.json"));
|
|
71
|
+
const ed = __importStar(require("@noble/ed25519"));
|
|
71
72
|
/**
|
|
72
73
|
* # DriftClient
|
|
73
74
|
* 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.
|
|
@@ -109,6 +110,7 @@ class DriftClient {
|
|
|
109
110
|
this.txHandler =
|
|
110
111
|
(_m = config === null || config === void 0 ? void 0 : config.txHandler) !== null && _m !== void 0 ? _m : new txHandler_1.TxHandler({
|
|
111
112
|
connection: this.connection,
|
|
113
|
+
// @ts-ignore
|
|
112
114
|
wallet: this.provider.wallet,
|
|
113
115
|
confirmationOptions: this.opts,
|
|
114
116
|
opts: {
|
|
@@ -1118,7 +1120,7 @@ class DriftClient {
|
|
|
1118
1120
|
data: Buffer.from([0x1]),
|
|
1119
1121
|
});
|
|
1120
1122
|
}
|
|
1121
|
-
async
|
|
1123
|
+
async getDepositTxnIx(amount, marketIndex, associatedTokenAccount, subAccountId, reduceOnly = false) {
|
|
1122
1124
|
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
1123
1125
|
const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
|
|
1124
1126
|
const signerAuthority = this.wallet.publicKey;
|
|
@@ -1135,6 +1137,10 @@ class DriftClient {
|
|
|
1135
1137
|
if (createWSOLTokenAccount) {
|
|
1136
1138
|
instructions.push((0, spl_token_1.createCloseAccountInstruction)(associatedTokenAccount, signerAuthority, signerAuthority, []));
|
|
1137
1139
|
}
|
|
1140
|
+
return instructions;
|
|
1141
|
+
}
|
|
1142
|
+
async createDepositTxn(amount, marketIndex, associatedTokenAccount, subAccountId, reduceOnly = false, txParams) {
|
|
1143
|
+
const instructions = await this.getDepositTxnIx(amount, marketIndex, associatedTokenAccount, subAccountId, reduceOnly);
|
|
1138
1144
|
txParams = { ...(txParams !== null && txParams !== void 0 ? txParams : this.txParams), computeUnits: 600000 };
|
|
1139
1145
|
const tx = await this.buildTransaction(instructions, txParams);
|
|
1140
1146
|
return tx;
|
|
@@ -1242,7 +1248,7 @@ class DriftClient {
|
|
|
1242
1248
|
getAssociatedTokenAccountCreationIx(tokenMintAddress, associatedTokenAddress, tokenProgram) {
|
|
1243
1249
|
return (0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, associatedTokenAddress, this.wallet.publicKey, tokenMintAddress, tokenProgram);
|
|
1244
1250
|
}
|
|
1245
|
-
async
|
|
1251
|
+
async createInitializeUserAccountAndDepositCollateralIxs(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name, fromSubAccountId, referrerInfo, donateAmount, customMaxMarginRatio) {
|
|
1246
1252
|
const ixs = [];
|
|
1247
1253
|
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
|
|
1248
1254
|
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
@@ -1288,6 +1294,13 @@ class DriftClient {
|
|
|
1288
1294
|
if (createWSOLTokenAccount) {
|
|
1289
1295
|
ixs.push((0, spl_token_1.createCloseAccountInstruction)(wsolTokenAccount, authority, authority, []));
|
|
1290
1296
|
}
|
|
1297
|
+
return {
|
|
1298
|
+
ixs,
|
|
1299
|
+
userAccountPublicKey,
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
async createInitializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name, fromSubAccountId, referrerInfo, donateAmount, txParams, customMaxMarginRatio) {
|
|
1303
|
+
const { ixs, userAccountPublicKey } = await this.createInitializeUserAccountAndDepositCollateralIxs(amount, userTokenAccount, marketIndex, subAccountId, name, fromSubAccountId, referrerInfo, donateAmount, customMaxMarginRatio);
|
|
1291
1304
|
const tx = await this.buildTransaction(ixs, txParams);
|
|
1292
1305
|
return [tx, userAccountPublicKey];
|
|
1293
1306
|
}
|
|
@@ -1663,13 +1676,21 @@ class DriftClient {
|
|
|
1663
1676
|
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
1664
1677
|
return txSig;
|
|
1665
1678
|
}
|
|
1666
|
-
async getPlacePerpOrderIx(orderParams, subAccountId) {
|
|
1679
|
+
async getPlacePerpOrderIx(orderParams, subAccountId, depositToTradeArgs) {
|
|
1667
1680
|
orderParams = (0, orderParams_1.getOrderParams)(orderParams, { marketType: types_1.MarketType.PERP });
|
|
1668
|
-
const
|
|
1681
|
+
const isDepositToTradeTx = depositToTradeArgs !== undefined;
|
|
1682
|
+
const user = isDepositToTradeTx
|
|
1683
|
+
? (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.authority, subAccountId)
|
|
1684
|
+
: await this.getUserAccountPublicKey(subAccountId);
|
|
1669
1685
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1670
|
-
userAccounts:
|
|
1671
|
-
|
|
1686
|
+
userAccounts: (depositToTradeArgs === null || depositToTradeArgs === void 0 ? void 0 : depositToTradeArgs.isMakingNewAccount)
|
|
1687
|
+
? []
|
|
1688
|
+
: [this.getUserAccount(subAccountId)],
|
|
1689
|
+
useMarketLastSlotCache: false,
|
|
1672
1690
|
readablePerpMarketIndex: orderParams.marketIndex,
|
|
1691
|
+
readableSpotMarketIndexes: isDepositToTradeTx
|
|
1692
|
+
? [depositToTradeArgs === null || depositToTradeArgs === void 0 ? void 0 : depositToTradeArgs.depositMarketIndex]
|
|
1693
|
+
: undefined,
|
|
1673
1694
|
});
|
|
1674
1695
|
return await this.program.instruction.placePerpOrder(orderParams, {
|
|
1675
1696
|
accounts: {
|
|
@@ -2781,7 +2802,9 @@ class DriftClient {
|
|
|
2781
2802
|
if (!txsToSign) {
|
|
2782
2803
|
return null;
|
|
2783
2804
|
}
|
|
2784
|
-
const signedTxs = (await this.txHandler.getSignedTransactionMap(txsToSign,
|
|
2805
|
+
const signedTxs = (await this.txHandler.getSignedTransactionMap(txsToSign,
|
|
2806
|
+
// @ts-ignore
|
|
2807
|
+
this.provider.wallet)).signedTxMap;
|
|
2785
2808
|
const { txSig, slot } = await this.sendTransaction(signedTxs.placeAndTakeTx, [], this.opts, true);
|
|
2786
2809
|
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2787
2810
|
return {
|
|
@@ -2888,6 +2911,101 @@ class DriftClient {
|
|
|
2888
2911
|
remainingAccounts,
|
|
2889
2912
|
});
|
|
2890
2913
|
}
|
|
2914
|
+
async signTakerOrderParams(orderParamsMessage) {
|
|
2915
|
+
const takerOrderParamsMessage = Uint8Array.from(this.getEncodedSwiftOrderParamsMessage(orderParamsMessage));
|
|
2916
|
+
return await this.signMessage(takerOrderParamsMessage);
|
|
2917
|
+
}
|
|
2918
|
+
getEncodedSwiftOrderParamsMessage(orderParamsMessage) {
|
|
2919
|
+
return this.program.coder.types.encode('SwiftOrderParamsMessage', orderParamsMessage);
|
|
2920
|
+
}
|
|
2921
|
+
decodeSwiftTakerOrderParamsMessage(encodedMessage) {
|
|
2922
|
+
return this.program.coder.types.decode('SwiftOrderParamsMessage', encodedMessage);
|
|
2923
|
+
}
|
|
2924
|
+
async signMessage(message) {
|
|
2925
|
+
return Buffer.from(await ed.sign(message, this.wallet.payer.secretKey.slice(0, 32)));
|
|
2926
|
+
}
|
|
2927
|
+
assembleSwiftServerMessage(message, signature, takerPubkey, marketIndex, marketType, slot) {
|
|
2928
|
+
return {
|
|
2929
|
+
message: message.toString('base64'),
|
|
2930
|
+
signature: signature.toString('base64'),
|
|
2931
|
+
taker_pubkey: takerPubkey.toBase58(),
|
|
2932
|
+
market_index: marketIndex,
|
|
2933
|
+
market_type: (0, types_1.isVariant)(marketType, 'perp') ? 'perp' : 'spot',
|
|
2934
|
+
slot: typeof slot === 'number' ? new anchor_1.BN(slot) : slot,
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
async placeSwiftTakerOrder(takerOrderParamsMessage, takerSignature, marketIndex, takerInfo, txParams) {
|
|
2938
|
+
const ixs = await this.getPlaceSwiftTakerPerpOrderIx(takerOrderParamsMessage, takerSignature, marketIndex, takerInfo);
|
|
2939
|
+
const { txSig } = await this.sendTransaction(await this.buildTransaction(ixs, txParams), [], this.opts);
|
|
2940
|
+
return txSig;
|
|
2941
|
+
}
|
|
2942
|
+
async getPlaceSwiftTakerPerpOrderIx(takerOrderParamsMessage, takerSignature, marketIndex, takerInfo) {
|
|
2943
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2944
|
+
userAccounts: [takerInfo.takerUserAccount],
|
|
2945
|
+
useMarketLastSlotCache: true,
|
|
2946
|
+
readablePerpMarketIndex: marketIndex,
|
|
2947
|
+
});
|
|
2948
|
+
const signatureIx = web3_js_1.Ed25519Program.createInstructionWithPublicKey({
|
|
2949
|
+
publicKey: takerInfo.takerUserAccount.authority.toBytes(),
|
|
2950
|
+
signature: Uint8Array.from(takerSignature),
|
|
2951
|
+
message: Uint8Array.from(takerOrderParamsMessage),
|
|
2952
|
+
});
|
|
2953
|
+
const placeTakerSwiftPerpOrderIx = await this.program.instruction.placeSwiftTakerOrder(takerOrderParamsMessage, takerSignature, {
|
|
2954
|
+
accounts: {
|
|
2955
|
+
state: await this.getStatePublicKey(),
|
|
2956
|
+
user: takerInfo.taker,
|
|
2957
|
+
userStats: takerInfo.takerStats,
|
|
2958
|
+
authority: this.wallet.publicKey,
|
|
2959
|
+
ixSysvar: web3_js_1.SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
2960
|
+
},
|
|
2961
|
+
remainingAccounts,
|
|
2962
|
+
});
|
|
2963
|
+
return [signatureIx, placeTakerSwiftPerpOrderIx];
|
|
2964
|
+
}
|
|
2965
|
+
async placeAndMakeSwiftPerpOrder(encodedTakerOrderParamsMessage, takerSignature, takerExpectedOrderId, takerInfo, orderParams, referrerInfo, txParams, subAccountId) {
|
|
2966
|
+
const ixs = await this.getPlaceAndMakeSwiftPerpOrderIxs(encodedTakerOrderParamsMessage, takerSignature, takerExpectedOrderId, takerInfo, orderParams, referrerInfo, subAccountId);
|
|
2967
|
+
const { txSig, slot } = await this.sendTransaction(await this.buildTransaction(ixs, txParams), [], this.opts);
|
|
2968
|
+
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
2969
|
+
return txSig;
|
|
2970
|
+
}
|
|
2971
|
+
async getPlaceAndMakeSwiftPerpOrderIxs(encodedTakerOrderParamsMessage, takerSignature, takerExpectedOrderId, takerInfo, orderParams, referrerInfo, subAccountId) {
|
|
2972
|
+
const [signatureIx, placeTakerSwiftPerpOrderIx] = await this.getPlaceSwiftTakerPerpOrderIx(encodedTakerOrderParamsMessage, takerSignature, orderParams.marketIndex, takerInfo);
|
|
2973
|
+
orderParams = (0, orderParams_1.getOrderParams)(orderParams, { marketType: types_1.MarketType.PERP });
|
|
2974
|
+
const userStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
2975
|
+
const user = await this.getUserAccountPublicKey(subAccountId);
|
|
2976
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2977
|
+
userAccounts: [
|
|
2978
|
+
this.getUserAccount(subAccountId),
|
|
2979
|
+
takerInfo.takerUserAccount,
|
|
2980
|
+
],
|
|
2981
|
+
useMarketLastSlotCache: true,
|
|
2982
|
+
writablePerpMarketIndexes: [orderParams.marketIndex],
|
|
2983
|
+
});
|
|
2984
|
+
if (referrerInfo) {
|
|
2985
|
+
remainingAccounts.push({
|
|
2986
|
+
pubkey: referrerInfo.referrer,
|
|
2987
|
+
isWritable: true,
|
|
2988
|
+
isSigner: false,
|
|
2989
|
+
});
|
|
2990
|
+
remainingAccounts.push({
|
|
2991
|
+
pubkey: referrerInfo.referrerStats,
|
|
2992
|
+
isWritable: true,
|
|
2993
|
+
isSigner: false,
|
|
2994
|
+
});
|
|
2995
|
+
}
|
|
2996
|
+
const placeAndMakeIx = await this.program.instruction.placeAndMakePerpOrder(orderParams, takerExpectedOrderId, {
|
|
2997
|
+
accounts: {
|
|
2998
|
+
state: await this.getStatePublicKey(),
|
|
2999
|
+
user,
|
|
3000
|
+
userStats: userStatsPublicKey,
|
|
3001
|
+
taker: takerInfo.taker,
|
|
3002
|
+
takerStats: takerInfo.takerStats,
|
|
3003
|
+
authority: this.wallet.publicKey,
|
|
3004
|
+
},
|
|
3005
|
+
remainingAccounts,
|
|
3006
|
+
});
|
|
3007
|
+
return [signatureIx, placeTakerSwiftPerpOrderIx, placeAndMakeIx];
|
|
3008
|
+
}
|
|
2891
3009
|
async preparePlaceAndTakeSpotOrder(orderParams, fulfillmentConfig, makerInfo, referrerInfo, txParams, subAccountId) {
|
|
2892
3010
|
const tx = await this.buildTransaction(await this.getPlaceAndTakeSpotOrderIx(orderParams, fulfillmentConfig, makerInfo, referrerInfo, subAccountId), txParams);
|
|
2893
3011
|
return {
|
|
@@ -15,12 +15,19 @@ export declare class EventSubscriber {
|
|
|
15
15
|
private awaitTxPromises;
|
|
16
16
|
private awaitTxResolver;
|
|
17
17
|
private logProvider;
|
|
18
|
+
private currentProviderType;
|
|
18
19
|
eventEmitter: StrictEventEmitter<EventEmitter, EventSubscriberEvents>;
|
|
19
20
|
private lastSeenSlot;
|
|
20
21
|
private lastSeenBlockTime;
|
|
21
22
|
lastSeenTxSig: string;
|
|
22
23
|
constructor(connection: Connection, program: Program, options?: EventSubscriptionOptions);
|
|
24
|
+
private initializeLogProvider;
|
|
23
25
|
private populateInitialEventListMap;
|
|
26
|
+
/**
|
|
27
|
+
* Implements fallback logic for reconnecting to LogProvider. Currently terminates at polling,
|
|
28
|
+
* could be improved to try the original type again after some cooldown.
|
|
29
|
+
*/
|
|
30
|
+
private updateFallbackProviderType;
|
|
24
31
|
subscribe(): Promise<boolean>;
|
|
25
32
|
private handleTxLogs;
|
|
26
33
|
fetchPreviousTx(fetchMax?: boolean): Promise<void>;
|
|
@@ -10,6 +10,7 @@ const webSocketLogProvider_1 = require("./webSocketLogProvider");
|
|
|
10
10
|
const events_1 = require("events");
|
|
11
11
|
const sort_1 = require("./sort");
|
|
12
12
|
const parse_1 = require("./parse");
|
|
13
|
+
const eventsServerLogProvider_1 = require("./eventsServerLogProvider");
|
|
13
14
|
class EventSubscriber {
|
|
14
15
|
constructor(connection, program, options = types_1.DefaultEventSubscriptionOptions) {
|
|
15
16
|
var _a;
|
|
@@ -23,15 +24,37 @@ class EventSubscriber {
|
|
|
23
24
|
this.txEventCache = new txEventCache_1.TxEventCache(this.options.maxTx);
|
|
24
25
|
this.eventListMap = new Map();
|
|
25
26
|
this.eventEmitter = new events_1.EventEmitter();
|
|
26
|
-
|
|
27
|
+
this.currentProviderType = this.options.logProviderConfig.type;
|
|
28
|
+
this.initializeLogProvider();
|
|
29
|
+
}
|
|
30
|
+
initializeLogProvider(subscribe = false) {
|
|
31
|
+
const logProviderConfig = this.options.logProviderConfig;
|
|
32
|
+
if (this.currentProviderType === 'websocket') {
|
|
27
33
|
this.logProvider = new webSocketLogProvider_1.WebSocketLogProvider(
|
|
28
34
|
// @ts-ignore
|
|
29
35
|
this.connection, this.address, this.options.commitment, this.options.logProviderConfig.resubTimeoutMs);
|
|
30
36
|
}
|
|
31
|
-
else {
|
|
37
|
+
else if (this.currentProviderType === 'polling') {
|
|
38
|
+
const frequency = 'frequency' in logProviderConfig
|
|
39
|
+
? logProviderConfig.frequency
|
|
40
|
+
: logProviderConfig.fallbackFrequency;
|
|
41
|
+
const batchSize = 'batchSize' in logProviderConfig
|
|
42
|
+
? logProviderConfig.batchSize
|
|
43
|
+
: logProviderConfig.fallbackBatchSize;
|
|
32
44
|
this.logProvider = new pollingLogProvider_1.PollingLogProvider(
|
|
33
45
|
// @ts-ignore
|
|
34
|
-
this.connection, this.address, options.commitment,
|
|
46
|
+
this.connection, this.address, this.options.commitment, frequency, batchSize);
|
|
47
|
+
}
|
|
48
|
+
else if (this.currentProviderType === 'events-server') {
|
|
49
|
+
this.logProvider = new eventsServerLogProvider_1.EventsServerLogProvider(logProviderConfig.url, this.options.eventTypes, this.options.address ? this.options.address.toString() : undefined);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
throw new Error(`Invalid log provider type: ${this.currentProviderType}`);
|
|
53
|
+
}
|
|
54
|
+
if (subscribe) {
|
|
55
|
+
this.logProvider.subscribe((txSig, slot, logs, mostRecentBlockTime, txSigIndex) => {
|
|
56
|
+
this.handleTxLogs(txSig, slot, logs, mostRecentBlockTime, this.currentProviderType === 'events-server', txSigIndex);
|
|
57
|
+
}, true);
|
|
35
58
|
}
|
|
36
59
|
}
|
|
37
60
|
populateInitialEventListMap() {
|
|
@@ -39,37 +62,51 @@ class EventSubscriber {
|
|
|
39
62
|
this.eventListMap.set(eventType, new eventList_1.EventList(eventType, this.options.maxEventsPerType, (0, sort_1.getSortFn)(this.options.orderBy, this.options.orderDir), this.options.orderDir));
|
|
40
63
|
}
|
|
41
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Implements fallback logic for reconnecting to LogProvider. Currently terminates at polling,
|
|
67
|
+
* could be improved to try the original type again after some cooldown.
|
|
68
|
+
*/
|
|
69
|
+
updateFallbackProviderType(reconnectAttempts, maxReconnectAttempts) {
|
|
70
|
+
if (reconnectAttempts < maxReconnectAttempts) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
let nextProviderType = this.currentProviderType;
|
|
74
|
+
if (this.currentProviderType === 'events-server') {
|
|
75
|
+
nextProviderType = 'websocket';
|
|
76
|
+
}
|
|
77
|
+
else if (this.currentProviderType === 'websocket') {
|
|
78
|
+
nextProviderType = 'polling';
|
|
79
|
+
}
|
|
80
|
+
else if (this.currentProviderType === 'polling') {
|
|
81
|
+
nextProviderType = 'polling';
|
|
82
|
+
}
|
|
83
|
+
console.log(`EventSubscriber: Failing over providerType ${this.currentProviderType} to ${nextProviderType}`);
|
|
84
|
+
this.currentProviderType = nextProviderType;
|
|
85
|
+
}
|
|
42
86
|
async subscribe() {
|
|
43
87
|
try {
|
|
44
88
|
if (this.logProvider.isSubscribed()) {
|
|
45
89
|
return true;
|
|
46
90
|
}
|
|
47
91
|
this.populateInitialEventListMap();
|
|
48
|
-
if (this.options.logProviderConfig.type === 'websocket'
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
this.logProvider.subscribe((txSig, slot, logs, mostRecentBlockTime) => {
|
|
63
|
-
this.handleTxLogs(txSig, slot, logs, mostRecentBlockTime);
|
|
64
|
-
}, true);
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
}
|
|
92
|
+
if (this.options.logProviderConfig.type === 'websocket' ||
|
|
93
|
+
this.options.logProviderConfig.type === 'events-server') {
|
|
94
|
+
const logProviderConfig = this.options
|
|
95
|
+
.logProviderConfig;
|
|
96
|
+
if (this.logProvider.eventEmitter) {
|
|
97
|
+
this.logProvider.eventEmitter.on('reconnect', async (reconnectAttempts) => {
|
|
98
|
+
if (reconnectAttempts > logProviderConfig.maxReconnectAttempts) {
|
|
99
|
+
console.log(`EventSubscriber: Reconnect attempts ${reconnectAttempts}/${logProviderConfig.maxReconnectAttempts}, reconnecting...`);
|
|
100
|
+
this.logProvider.eventEmitter.removeAllListeners('reconnect');
|
|
101
|
+
await this.unsubscribe();
|
|
102
|
+
this.updateFallbackProviderType(reconnectAttempts, logProviderConfig.maxReconnectAttempts);
|
|
103
|
+
this.initializeLogProvider(true);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
69
106
|
}
|
|
70
107
|
}
|
|
71
|
-
this.logProvider.subscribe((txSig, slot, logs, mostRecentBlockTime) => {
|
|
72
|
-
this.handleTxLogs(txSig, slot, logs, mostRecentBlockTime);
|
|
108
|
+
this.logProvider.subscribe((txSig, slot, logs, mostRecentBlockTime, txSigIndex) => {
|
|
109
|
+
this.handleTxLogs(txSig, slot, logs, mostRecentBlockTime, this.currentProviderType === 'events-server', txSigIndex);
|
|
73
110
|
}, true);
|
|
74
111
|
return true;
|
|
75
112
|
}
|
|
@@ -79,11 +116,11 @@ class EventSubscriber {
|
|
|
79
116
|
return false;
|
|
80
117
|
}
|
|
81
118
|
}
|
|
82
|
-
handleTxLogs(txSig, slot, logs, mostRecentBlockTime) {
|
|
83
|
-
if (this.txEventCache.has(txSig)) {
|
|
119
|
+
handleTxLogs(txSig, slot, logs, mostRecentBlockTime, fromEventsServer = false, txSigIndex = undefined) {
|
|
120
|
+
if (!fromEventsServer && this.txEventCache.has(txSig)) {
|
|
84
121
|
return;
|
|
85
122
|
}
|
|
86
|
-
const wrappedEvents = this.parseEventsFromLogs(txSig, slot, logs);
|
|
123
|
+
const wrappedEvents = this.parseEventsFromLogs(txSig, slot, logs, txSigIndex);
|
|
87
124
|
for (const wrappedEvent of wrappedEvents) {
|
|
88
125
|
this.eventListMap.get(wrappedEvent.eventType).insert(wrappedEvent);
|
|
89
126
|
}
|
|
@@ -134,7 +171,7 @@ class EventSubscriber {
|
|
|
134
171
|
this.awaitTxResolver.clear();
|
|
135
172
|
return await this.logProvider.unsubscribe(true);
|
|
136
173
|
}
|
|
137
|
-
parseEventsFromLogs(txSig, slot, logs) {
|
|
174
|
+
parseEventsFromLogs(txSig, slot, logs, txSigIndex) {
|
|
138
175
|
const records = [];
|
|
139
176
|
// @ts-ignore
|
|
140
177
|
const events = (0, parse_1.parseLogs)(this.program, logs);
|
|
@@ -146,7 +183,8 @@ class EventSubscriber {
|
|
|
146
183
|
event.data.txSig = txSig;
|
|
147
184
|
event.data.slot = slot;
|
|
148
185
|
event.data.eventType = event.name;
|
|
149
|
-
event.data.txSigIndex =
|
|
186
|
+
event.data.txSigIndex =
|
|
187
|
+
txSigIndex !== undefined ? txSigIndex : runningEventIndex;
|
|
150
188
|
records.push(event.data);
|
|
151
189
|
}
|
|
152
190
|
runningEventIndex++;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { logProviderCallback, EventType, LogProvider } from './types';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
export declare class EventsServerLogProvider implements LogProvider {
|
|
5
|
+
private readonly url;
|
|
6
|
+
private readonly eventTypes;
|
|
7
|
+
private readonly userAccount?;
|
|
8
|
+
private ws?;
|
|
9
|
+
private callback?;
|
|
10
|
+
private isUnsubscribing;
|
|
11
|
+
private externalUnsubscribe;
|
|
12
|
+
private lastHeartbeat;
|
|
13
|
+
private timeoutId?;
|
|
14
|
+
private reconnectAttempts;
|
|
15
|
+
eventEmitter?: EventEmitter;
|
|
16
|
+
constructor(url: string, eventTypes: EventType[], userAccount?: string);
|
|
17
|
+
isSubscribed(): boolean;
|
|
18
|
+
subscribe(callback: logProviderCallback): Promise<boolean>;
|
|
19
|
+
unsubscribe(external?: boolean): Promise<boolean>;
|
|
20
|
+
private setTimeout;
|
|
21
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventsServerLogProvider = void 0;
|
|
4
|
+
const events_1 = require("events");
|
|
5
|
+
// browser support
|
|
6
|
+
let WebSocketImpl;
|
|
7
|
+
if (typeof window !== 'undefined' && window.WebSocket) {
|
|
8
|
+
WebSocketImpl = window.WebSocket;
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
WebSocketImpl = require('ws');
|
|
12
|
+
}
|
|
13
|
+
const EVENT_SERVER_HEARTBEAT_INTERVAL_MS = 5000;
|
|
14
|
+
const ALLOWED_MISSED_HEARTBEATS = 3;
|
|
15
|
+
class EventsServerLogProvider {
|
|
16
|
+
constructor(url, eventTypes, userAccount) {
|
|
17
|
+
this.url = url;
|
|
18
|
+
this.eventTypes = eventTypes;
|
|
19
|
+
this.userAccount = userAccount;
|
|
20
|
+
this.isUnsubscribing = false;
|
|
21
|
+
this.externalUnsubscribe = false;
|
|
22
|
+
this.lastHeartbeat = 0;
|
|
23
|
+
this.reconnectAttempts = 0;
|
|
24
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
25
|
+
}
|
|
26
|
+
isSubscribed() {
|
|
27
|
+
return this.ws !== undefined;
|
|
28
|
+
}
|
|
29
|
+
async subscribe(callback) {
|
|
30
|
+
if (this.ws !== undefined) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
this.ws = new WebSocketImpl(this.url);
|
|
34
|
+
this.callback = callback;
|
|
35
|
+
this.ws.addEventListener('open', () => {
|
|
36
|
+
for (const channel of this.eventTypes) {
|
|
37
|
+
const subscribeMessage = {
|
|
38
|
+
type: 'subscribe',
|
|
39
|
+
channel: channel,
|
|
40
|
+
};
|
|
41
|
+
if (this.userAccount) {
|
|
42
|
+
subscribeMessage['user'] = this.userAccount;
|
|
43
|
+
}
|
|
44
|
+
this.ws.send(JSON.stringify(subscribeMessage));
|
|
45
|
+
}
|
|
46
|
+
this.reconnectAttempts = 0;
|
|
47
|
+
});
|
|
48
|
+
this.ws.addEventListener('message', (data) => {
|
|
49
|
+
try {
|
|
50
|
+
if (!this.isUnsubscribing) {
|
|
51
|
+
clearTimeout(this.timeoutId);
|
|
52
|
+
this.setTimeout();
|
|
53
|
+
if (this.reconnectAttempts > 0) {
|
|
54
|
+
console.log('eventsServerLogProvider: Resetting reconnect attempts to 0');
|
|
55
|
+
}
|
|
56
|
+
this.reconnectAttempts = 0;
|
|
57
|
+
}
|
|
58
|
+
const parsedData = JSON.parse(data.data.toString());
|
|
59
|
+
if (parsedData.channel === 'heartbeat') {
|
|
60
|
+
this.lastHeartbeat = Date.now();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (parsedData.message !== undefined) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const event = JSON.parse(parsedData.data);
|
|
67
|
+
this.callback(event.txSig, event.slot, [
|
|
68
|
+
'Program dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH invoke [1]',
|
|
69
|
+
event.rawLog,
|
|
70
|
+
'Program dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH success',
|
|
71
|
+
], undefined, event.txSigIndex);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error('Error parsing message:', error);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
this.ws.addEventListener('close', () => {
|
|
78
|
+
console.log('eventsServerLogProvider: WebSocket closed');
|
|
79
|
+
});
|
|
80
|
+
this.ws.addEventListener('error', (error) => {
|
|
81
|
+
console.error('eventsServerLogProvider: WebSocket error:', error);
|
|
82
|
+
});
|
|
83
|
+
this.setTimeout();
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
async unsubscribe(external = false) {
|
|
87
|
+
this.isUnsubscribing = true;
|
|
88
|
+
this.externalUnsubscribe = external;
|
|
89
|
+
if (this.timeoutId) {
|
|
90
|
+
clearInterval(this.timeoutId);
|
|
91
|
+
this.timeoutId = undefined;
|
|
92
|
+
}
|
|
93
|
+
if (this.ws !== undefined) {
|
|
94
|
+
this.ws.close();
|
|
95
|
+
this.ws = undefined;
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this.isUnsubscribing = false;
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
setTimeout() {
|
|
104
|
+
this.timeoutId = setTimeout(async () => {
|
|
105
|
+
if (this.isUnsubscribing || this.externalUnsubscribe) {
|
|
106
|
+
// If we are in the process of unsubscribing, do not attempt to resubscribe
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const timeSinceLastHeartbeat = Date.now() - this.lastHeartbeat;
|
|
110
|
+
if (timeSinceLastHeartbeat >
|
|
111
|
+
EVENT_SERVER_HEARTBEAT_INTERVAL_MS * ALLOWED_MISSED_HEARTBEATS) {
|
|
112
|
+
console.log(`eventServerLogProvider: No heartbeat in ${timeSinceLastHeartbeat}ms, resubscribing on attempt ${this.reconnectAttempts + 1}`);
|
|
113
|
+
await this.unsubscribe();
|
|
114
|
+
this.reconnectAttempts++;
|
|
115
|
+
this.eventEmitter.emit('reconnect', this.reconnectAttempts);
|
|
116
|
+
this.subscribe(this.callback);
|
|
117
|
+
}
|
|
118
|
+
}, EVENT_SERVER_HEARTBEAT_INTERVAL_MS * 2);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.EventsServerLogProvider = EventsServerLogProvider;
|
|
@@ -30,7 +30,7 @@ class PollingLogProvider {
|
|
|
30
30
|
this.firstFetch = false;
|
|
31
31
|
const { mostRecentTx, transactionLogs } = response;
|
|
32
32
|
for (const { txSig, slot, logs } of transactionLogs) {
|
|
33
|
-
callback(txSig, slot, logs, response.mostRecentBlockTime);
|
|
33
|
+
callback(txSig, slot, logs, response.mostRecentBlockTime, undefined);
|
|
34
34
|
}
|
|
35
35
|
this.mostRecentSeenTx = mostRecentTx;
|
|
36
36
|
}
|