@velocity-exchange/sdk 0.4.0 → 0.6.0
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 +3 -3
- package/lib/browser/adminClient.d.ts +35 -0
- package/lib/browser/adminClient.js +65 -0
- package/lib/browser/config.js +6 -7
- package/lib/browser/constants/numericConstants.d.ts +1 -1
- package/lib/browser/constants/numericConstants.js +1 -1
- package/lib/browser/decode/user.js +5 -1
- package/lib/browser/idl/velocity.d.ts +146 -3
- package/lib/browser/idl/velocity.json +147 -4
- package/lib/browser/orderSubscriber/OrderSubscriber.js +3 -0
- package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
- package/lib/browser/types.d.ts +4 -0
- package/lib/browser/user.d.ts +15 -0
- package/lib/browser/user.js +37 -1
- package/lib/browser/velocityClient.d.ts +46 -10
- package/lib/browser/velocityClient.js +107 -35
- package/lib/node/adminClient.d.ts +35 -0
- package/lib/node/adminClient.d.ts.map +1 -1
- package/lib/node/adminClient.js +65 -0
- package/lib/node/config.d.ts.map +1 -1
- package/lib/node/config.js +6 -7
- package/lib/node/constants/numericConstants.d.ts +1 -1
- package/lib/node/constants/numericConstants.d.ts.map +1 -1
- package/lib/node/constants/numericConstants.js +1 -1
- package/lib/node/decode/user.d.ts.map +1 -1
- package/lib/node/decode/user.js +5 -1
- package/lib/node/idl/velocity.d.ts +146 -3
- package/lib/node/idl/velocity.d.ts.map +1 -1
- package/lib/node/idl/velocity.json +147 -4
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
- package/lib/node/orderSubscriber/OrderSubscriber.js +3 -0
- package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
- package/lib/node/pyth/pythLazerSubscriber.js +37 -27
- package/lib/node/types.d.ts +4 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/user.d.ts +15 -0
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +37 -1
- package/lib/node/velocityClient.d.ts +46 -10
- package/lib/node/velocityClient.d.ts.map +1 -1
- package/lib/node/velocityClient.js +107 -35
- package/package.json +7 -3
- package/.prettierignore +0 -1
- package/CHANGELOG.md +0 -132
- package/build-browser.js +0 -58
- package/bunfig.toml +0 -3
- package/esbuild-shims.js +0 -12
- package/scripts/deposit-isolated-positions.ts +0 -110
- package/scripts/find-flagged-users.ts +0 -213
- package/scripts/grpc-client-test-comparison.ts +0 -372
- package/scripts/grpc-multiuser-client-test-comparison.ts +0 -158
- package/scripts/postbuild.js +0 -95
- package/scripts/single-grpc-client-test.ts +0 -284
- package/scripts/withdraw-isolated-positions.ts +0 -174
- package/src/accounts/README_WebSocketAccountSubscriberV2.md +0 -95
- package/src/accounts/README_WebSocketProgramAccountSubscriberV2.md +0 -135
- package/src/accounts/basicUserAccountSubscriber.ts +0 -79
- package/src/accounts/basicUserStatsAccountSubscriber.ts +0 -87
- package/src/accounts/bulkAccountLoader.ts +0 -358
- package/src/accounts/bulkUserStatsSubscription.ts +0 -40
- package/src/accounts/bulkUserSubscription.ts +0 -39
- package/src/accounts/customizedCadenceBulkAccountLoader.ts +0 -250
- package/src/accounts/fetch.ts +0 -200
- package/src/accounts/grpcAccountSubscriber.ts +0 -225
- package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -73
- package/src/accounts/grpcMultiAccountSubscriber.ts +0 -566
- package/src/accounts/grpcMultiUserAccountSubscriber.ts +0 -328
- package/src/accounts/grpcProgramAccountSubscriber.ts +0 -264
- package/src/accounts/grpcUserAccountSubscriber.ts +0 -63
- package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -65
- package/src/accounts/grpcVelocityClientAccountSubscriber.ts +0 -257
- package/src/accounts/grpcVelocityClientAccountSubscriberV2.ts +0 -941
- package/src/accounts/laserProgramAccountSubscriber.ts +0 -266
- package/src/accounts/oneShotUserAccountSubscriber.ts +0 -88
- package/src/accounts/oneShotUserStatsAccountSubscriber.ts +0 -94
- package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +0 -223
- package/src/accounts/pollingOracleAccountSubscriber.ts +0 -151
- package/src/accounts/pollingTokenAccountSubscriber.ts +0 -147
- package/src/accounts/pollingUserAccountSubscriber.ts +0 -198
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +0 -180
- package/src/accounts/pollingVelocityClientAccountSubscriber.ts +0 -774
- package/src/accounts/testBulkAccountLoader.ts +0 -59
- package/src/accounts/types.ts +0 -428
- package/src/accounts/utils.ts +0 -90
- package/src/accounts/webSocketAccountSubscriber.ts +0 -304
- package/src/accounts/webSocketAccountSubscriberV2.ts +0 -536
- package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +0 -171
- package/src/accounts/webSocketProgramAccountSubscriber.ts +0 -244
- package/src/accounts/webSocketProgramAccountSubscriberV2.ts +0 -1048
- package/src/accounts/webSocketProgramAccountsSubscriberV2.ts +0 -1042
- package/src/accounts/webSocketUserAccountSubscriber.ts +0 -139
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +0 -131
- package/src/accounts/webSocketVelocityClientAccountSubscriber.ts +0 -865
- package/src/accounts/webSocketVelocityClientAccountSubscriberV2.ts +0 -897
- package/src/accounts/websocketProgramUserAccountSubscriber.ts +0 -127
- package/src/addresses/marketAddresses.ts +0 -28
- package/src/addresses/pda.ts +0 -620
- package/src/adminClient.ts +0 -8136
- package/src/assert/assert.ts +0 -5
- package/src/auctionSubscriber/auctionSubscriber.ts +0 -86
- package/src/auctionSubscriber/auctionSubscriberGrpc.ts +0 -99
- package/src/auctionSubscriber/index.ts +0 -9
- package/src/auctionSubscriber/types.ts +0 -30
- package/src/bankrun/bankrunConnection.ts +0 -630
- package/src/blockhashSubscriber/BlockhashSubscriber.ts +0 -160
- package/src/blockhashSubscriber/index.ts +0 -6
- package/src/blockhashSubscriber/types.ts +0 -13
- package/src/clock/clockSubscriber.ts +0 -146
- package/src/config.ts +0 -312
- package/src/constants/index.ts +0 -9
- package/src/constants/numericConstants.ts +0 -194
- package/src/constants/perpMarkets.ts +0 -127
- package/src/constants/spotMarkets.ts +0 -104
- package/src/constants/txConstants.ts +0 -2
- package/src/constituentMap/constituentMap.ts +0 -305
- package/src/constituentMap/pollingConstituentAccountSubscriber.ts +0 -99
- package/src/constituentMap/webSocketConstituentAccountSubscriber.ts +0 -121
- package/src/core/VelocityCore.ts +0 -606
- package/src/core/index.ts +0 -12
- package/src/core/instructions/deposit.ts +0 -64
- package/src/core/instructions/fill.ts +0 -51
- package/src/core/instructions/funding.ts +0 -33
- package/src/core/instructions/liquidation.ts +0 -55
- package/src/core/instructions/orders.ts +0 -84
- package/src/core/instructions/perpOrders.ts +0 -312
- package/src/core/instructions/settlement.ts +0 -40
- package/src/core/instructions/trigger.ts +0 -41
- package/src/core/instructions/withdraw.ts +0 -65
- package/src/core/remainingAccounts.ts +0 -320
- package/src/core/signedMsg.ts +0 -109
- package/src/decode/customCoder.ts +0 -148
- package/src/decode/user.ts +0 -401
- package/src/dlob/DLOB.ts +0 -2793
- package/src/dlob/DLOBNode.ts +0 -305
- package/src/dlob/DLOBSubscriber.ts +0 -269
- package/src/dlob/NodeList.ts +0 -244
- package/src/dlob/orderBookLevels.ts +0 -695
- package/src/dlob/types.ts +0 -37
- package/src/events/eventList.ts +0 -114
- package/src/events/eventSubscriber.ts +0 -521
- package/src/events/eventsServerLogProvider.ts +0 -189
- package/src/events/fetchLogs.ts +0 -219
- package/src/events/parse.ts +0 -271
- package/src/events/pollingLogProvider.ts +0 -113
- package/src/events/sort.ts +0 -51
- package/src/events/txEventCache.ts +0 -92
- package/src/events/types.ts +0 -337
- package/src/events/webSocketLogProvider.ts +0 -152
- package/src/factory/bigNum.ts +0 -709
- package/src/factory/oracleClient.ts +0 -73
- package/src/idl/pyth.json +0 -142
- package/src/idl/pyth.ts +0 -97
- package/src/idl/pyth_solana_receiver.json +0 -628
- package/src/idl/token_faucet.json +0 -229
- package/src/idl/token_faucet.ts +0 -197
- package/src/idl/velocity.json +0 -23974
- package/src/idl/velocity.ts +0 -23980
- package/src/index.ts +0 -150
- package/src/indicative-quotes/indicativeQuotesSender.ts +0 -233
- package/src/isomorphic/README.md +0 -19
- package/src/isomorphic/anchor.browser.ts +0 -44
- package/src/isomorphic/anchor.node.ts +0 -1
- package/src/isomorphic/anchor.ts +0 -1
- package/src/isomorphic/anchor29.browser.ts +0 -24
- package/src/isomorphic/anchor29.node.ts +0 -1
- package/src/isomorphic/anchor29.ts +0 -1
- package/src/isomorphic/grpc.browser.ts +0 -4
- package/src/isomorphic/grpc.node.ts +0 -130
- package/src/isomorphic/grpc.ts +0 -1
- package/src/jupiter/jupiterClient.ts +0 -502
- package/src/keypair.ts +0 -32
- package/src/margin/README.md +0 -138
- package/src/marginCalculation.ts +0 -407
- package/src/marinade/idl/idl.json +0 -1962
- package/src/marinade/index.ts +0 -73
- package/src/marinade/types.ts +0 -3925
- package/src/math/amm.ts +0 -1758
- package/src/math/auction.ts +0 -480
- package/src/math/bankruptcy.ts +0 -138
- package/src/math/builder.ts +0 -130
- package/src/math/conversion.ts +0 -45
- package/src/math/exchangeStatus.ts +0 -261
- package/src/math/funding.ts +0 -498
- package/src/math/insurance.ts +0 -171
- package/src/math/liquidation.ts +0 -433
- package/src/math/margin.ts +0 -327
- package/src/math/market.ts +0 -487
- package/src/math/oracles.ts +0 -477
- package/src/math/orders.ts +0 -500
- package/src/math/position.ts +0 -381
- package/src/math/repeg.ts +0 -223
- package/src/math/spotBalance.ts +0 -996
- package/src/math/spotMarket.ts +0 -115
- package/src/math/spotPosition.ts +0 -263
- package/src/math/state.ts +0 -71
- package/src/math/superStake.ts +0 -602
- package/src/math/tiers.ts +0 -73
- package/src/math/trade.ts +0 -879
- package/src/math/utils.ts +0 -183
- package/src/memcmp.ts +0 -279
- package/src/oracles/oracleClientCache.ts +0 -41
- package/src/oracles/oracleId.ts +0 -99
- package/src/oracles/prelaunchOracleClient.ts +0 -63
- package/src/oracles/pythClient.ts +0 -125
- package/src/oracles/pythLazerClient.ts +0 -141
- package/src/oracles/quoteAssetOracleClient.ts +0 -43
- package/src/oracles/strictOraclePrice.ts +0 -40
- package/src/oracles/types.ts +0 -82
- package/src/oracles/utils.ts +0 -45
- package/src/orderParams.ts +0 -117
- package/src/orderSubscriber/OrderSubscriber.ts +0 -378
- package/src/orderSubscriber/PollingSubscription.ts +0 -50
- package/src/orderSubscriber/WebsocketSubscription.ts +0 -137
- package/src/orderSubscriber/grpcSubscription.ts +0 -155
- package/src/orderSubscriber/index.ts +0 -7
- package/src/orderSubscriber/types.ts +0 -64
- package/src/priorityFee/averageOverSlotsStrategy.ts +0 -17
- package/src/priorityFee/averageStrategy.ts +0 -13
- package/src/priorityFee/ewmaStrategy.ts +0 -51
- package/src/priorityFee/heliusPriorityFeeMethod.ts +0 -68
- package/src/priorityFee/index.ts +0 -16
- package/src/priorityFee/maxOverSlotsStrategy.ts +0 -18
- package/src/priorityFee/maxStrategy.ts +0 -8
- package/src/priorityFee/priorityFeeSubscriber.ts +0 -328
- package/src/priorityFee/priorityFeeSubscriberMap.ts +0 -134
- package/src/priorityFee/solanaPriorityFeeMethod.ts +0 -46
- package/src/priorityFee/types.ts +0 -82
- package/src/priorityFee/velocityPriorityFeeMethod.ts +0 -53
- package/src/pyth/constants.ts +0 -9
- package/src/pyth/index.ts +0 -15
- package/src/pyth/pythLazerSubscriber.ts +0 -365
- package/src/pyth/types.ts +0 -4451
- package/src/pyth/utils.ts +0 -13
- package/src/slot/SlotSubscriber.ts +0 -126
- package/src/slot/SlothashSubscriber.ts +0 -163
- package/src/swap/UnifiedSwapClient.ts +0 -315
- package/src/swift/grpcSignedMsgUserAccountSubscriber.ts +0 -81
- package/src/swift/index.ts +0 -10
- package/src/swift/signedMsgUserAccountSubscriber.ts +0 -251
- package/src/swift/swiftOrderSubscriber.ts +0 -351
- package/src/testClient.ts +0 -42
- package/src/titan/titanClient.ts +0 -438
- package/src/token/index.ts +0 -13
- package/src/tokenFaucet.ts +0 -296
- package/src/tx/baseTxSender.ts +0 -651
- package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +0 -31
- package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +0 -105
- package/src/tx/blockhashFetcher/types.ts +0 -9
- package/src/tx/fastSingleTxSender.ts +0 -200
- package/src/tx/forwardOnlyTxSender.ts +0 -193
- package/src/tx/priorityFeeCalculator.ts +0 -117
- package/src/tx/reportTransactionError.ts +0 -176
- package/src/tx/retryTxSender.ts +0 -177
- package/src/tx/txHandler.ts +0 -1009
- package/src/tx/txParamProcessor.ts +0 -225
- package/src/tx/types.ts +0 -117
- package/src/tx/utils.ts +0 -133
- package/src/tx/whileValidTxSender.ts +0 -377
- package/src/types.ts +0 -2575
- package/src/user.ts +0 -5316
- package/src/userConfig.ts +0 -38
- package/src/userMap/PollingSubscription.ts +0 -61
- package/src/userMap/WebsocketSubscription.ts +0 -93
- package/src/userMap/grpcSubscription.ts +0 -93
- package/src/userMap/referrerMap.ts +0 -360
- package/src/userMap/revenueShareEscrowMap.ts +0 -342
- package/src/userMap/userMap.ts +0 -784
- package/src/userMap/userMapConfig.ts +0 -82
- package/src/userMap/userStatsMap.ts +0 -393
- package/src/userName.ts +0 -37
- package/src/userStats.ts +0 -159
- package/src/userStatsConfig.ts +0 -35
- package/src/util/TransactionConfirmationManager.ts +0 -333
- package/src/util/chainClock.ts +0 -65
- package/src/util/computeUnits.ts +0 -101
- package/src/util/digest.ts +0 -33
- package/src/util/ed25519Utils.ts +0 -95
- package/src/util/promiseTimeout.ts +0 -23
- package/src/velocityClient.ts +0 -14802
- package/src/velocityClientConfig.ts +0 -119
- package/src/wallet.ts +0 -91
- package/tests/VelocityCore/builder_escrow.test.ts +0 -121
- package/tests/VelocityCore/decode.test.ts +0 -16
- package/tests/VelocityCore/fill_trigger.test.ts +0 -73
- package/tests/VelocityCore/instructions.test.ts +0 -46
- package/tests/VelocityCore/pdas.test.ts +0 -30
- package/tests/VelocityCore/perp_orders.test.ts +0 -205
- package/tests/VelocityCore/remainingAccounts.test.ts +0 -72
- package/tests/VelocityCore/settlement_liquidation.test.ts +0 -69
- package/tests/accounts/customizedCadenceBulkAccountLoader.test.ts +0 -211
- package/tests/amm/test.ts +0 -2402
- package/tests/auctions/test.ts +0 -81
- package/tests/bn/test.ts +0 -355
- package/tests/builder/builderFee.test.ts +0 -42
- package/tests/ci/verifyConstants.ts +0 -393
- package/tests/decode/test.ts +0 -262
- package/tests/decode/userAccountBufferStrings.ts +0 -102
- package/tests/dlob/helpers.ts +0 -748
- package/tests/dlob/test.ts +0 -6969
- package/tests/dlob/tickSizeStandardization.ts +0 -545
- package/tests/events/parseLogsForCuUsage.ts +0 -139
- package/tests/exchangeStatus/test.ts +0 -45
- package/tests/insurance/test.ts +0 -40
- package/tests/liquidation/test.ts +0 -125
- package/tests/oracles/mmOracleGate.test.ts +0 -379
- package/tests/oracles/pythPegSnap.test.ts +0 -76
- package/tests/sdkParity/enumParity.test.ts +0 -84
- package/tests/sdkParity/marginCategoryFill.test.ts +0 -143
- package/tests/sdkParity/memcmpOffsets.test.ts +0 -139
- package/tests/spot/test.ts +0 -281
- package/tests/tx/TransactionConfirmationManager.test.ts +0 -312
- package/tests/tx/cachedBlockhashFetcher.test.ts +0 -96
- package/tests/tx/priorityFeeCalculator.ts +0 -77
- package/tests/tx/priorityFeeStrategy.ts +0 -95
- package/tests/user/bankruptcy.ts +0 -165
- package/tests/user/feeAndWithdrawLimits.ts +0 -284
- package/tests/user/getMarginCalculation.ts +0 -586
- package/tests/user/helpers.ts +0 -184
- package/tests/user/liquidations.ts +0 -129
- package/tests/user/marginCalculations.test.ts +0 -321
- package/tests/user/test.ts +0 -833
- package/tsconfig.browser.json +0 -18
- package/tsconfig.json +0 -36
package/src/dlob/types.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { DLOB } from './DLOB';
|
|
2
|
-
import { VelocityClient } from '../velocityClient';
|
|
3
|
-
|
|
4
|
-
/** Configuration for constructing a `DLOBSubscriber`. */
|
|
5
|
-
export type DLOBSubscriptionConfig = {
|
|
6
|
-
/** Client used to resolve market accounts/oracle data for `getL2`/`getL3`. Required — the constructor throws if omitted. */
|
|
7
|
-
velocityClient?: VelocityClient;
|
|
8
|
-
/** Provides the `DLOB` snapshot to poll, e.g. built from a `UserMap`. */
|
|
9
|
-
dlobSource: DLOBSource;
|
|
10
|
-
/** Provides the current slot used both to request the next `DLOB` snapshot and to price orders when serving `getL2`/`getL3`. */
|
|
11
|
-
slotSource: SlotSource;
|
|
12
|
-
/** Polling interval in milliseconds between calls to `dlobSource.getDLOB`. */
|
|
13
|
-
updateFrequency: number;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/** Events emitted by `DLOBSubscriber`'s `eventEmitter`. */
|
|
17
|
-
export interface DLOBSubscriberEvents {
|
|
18
|
-
/** Fired after each successful periodic `DLOB` refresh, with the newly fetched `DLOB`. */
|
|
19
|
-
update: (dlob: DLOB) => void;
|
|
20
|
-
/** Fired if a periodic refresh's `dlobSource.getDLOB` call throws. */
|
|
21
|
-
error: (e: Error) => void;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** Supplies a fresh `DLOB` snapshot on demand, e.g. built from a `UserMap` of on-chain user accounts. */
|
|
25
|
-
export interface DLOBSource {
|
|
26
|
-
/**
|
|
27
|
-
* @param slot slot to build/tag the returned `DLOB` snapshot at
|
|
28
|
-
* @returns a promise resolving to a populated `DLOB`
|
|
29
|
-
*/
|
|
30
|
-
getDLOB(slot: number): Promise<DLOB>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** Supplies the current slot, e.g. backed by a `SlotSubscriber`. */
|
|
34
|
-
export interface SlotSource {
|
|
35
|
-
/** @returns the most recently observed slot. */
|
|
36
|
-
getSlot(): number;
|
|
37
|
-
}
|
package/src/events/eventList.ts
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EventType,
|
|
3
|
-
EventMap,
|
|
4
|
-
EventSubscriptionOrderDirection,
|
|
5
|
-
SortFn,
|
|
6
|
-
} from './types';
|
|
7
|
-
|
|
8
|
-
class Node<Type extends EventType, Event extends EventMap[Type]> {
|
|
9
|
-
constructor(
|
|
10
|
-
public event: Event,
|
|
11
|
-
public next?: Node<Type, Event>,
|
|
12
|
-
public prev?: Node<Type, Event>
|
|
13
|
-
) {}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Fixed-capacity, sorted doubly-linked list of decoded events for a single
|
|
18
|
-
* `EventType`, used internally by `EventSubscriber` to retain the most
|
|
19
|
-
* recent `maxSize` events per type in the configured order.
|
|
20
|
-
*/
|
|
21
|
-
export class EventList<Type extends EventType> {
|
|
22
|
-
size = 0;
|
|
23
|
-
head?: Node<Type, EventMap[Type]>;
|
|
24
|
-
tail?: Node<Type, EventMap[Type]>;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @param eventType The `EventType` this list holds.
|
|
28
|
-
* @param maxSize Max events retained; once exceeded, the tail (least-recent per `sortFn`/`orderDirection`) is evicted.
|
|
29
|
-
* @param sortFn Comparator determining insertion order (see `getSortFn`).
|
|
30
|
-
* @param orderDirection Whether `'less than'` per `sortFn` sorts toward the head (`'asc'`) or tail (`'desc'`).
|
|
31
|
-
*/
|
|
32
|
-
public constructor(
|
|
33
|
-
public eventType: Type,
|
|
34
|
-
public maxSize: number,
|
|
35
|
-
private sortFn: SortFn,
|
|
36
|
-
private orderDirection: EventSubscriptionOrderDirection
|
|
37
|
-
) {}
|
|
38
|
-
|
|
39
|
-
/** Inserts `event` in sorted position (per `sortFn`/`orderDirection`), evicting the tail if this pushes the list over `maxSize`. */
|
|
40
|
-
public insert(event: EventMap[Type]): void {
|
|
41
|
-
this.size++;
|
|
42
|
-
const newNode = new Node(event);
|
|
43
|
-
if (this.head === undefined) {
|
|
44
|
-
this.head = this.tail = newNode;
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (
|
|
49
|
-
this.sortFn(this.head.event, newNode.event) ===
|
|
50
|
-
(this.orderDirection === 'asc' ? 'less than' : 'greater than')
|
|
51
|
-
) {
|
|
52
|
-
this.head.prev = newNode;
|
|
53
|
-
newNode.next = this.head;
|
|
54
|
-
this.head = newNode;
|
|
55
|
-
} else {
|
|
56
|
-
let currentNode = this.head;
|
|
57
|
-
while (
|
|
58
|
-
currentNode.next !== undefined &&
|
|
59
|
-
this.sortFn(currentNode.next.event, newNode.event) !==
|
|
60
|
-
(this.orderDirection === 'asc' ? 'less than' : 'greater than')
|
|
61
|
-
) {
|
|
62
|
-
currentNode = currentNode.next;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
newNode.next = currentNode.next;
|
|
66
|
-
if (newNode.next !== undefined) {
|
|
67
|
-
newNode.next.prev = newNode;
|
|
68
|
-
} else {
|
|
69
|
-
this.tail = newNode;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
currentNode.next = newNode;
|
|
73
|
-
newNode.prev = currentNode;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (this.size > this.maxSize) {
|
|
77
|
-
this.detach();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** Removes the tail node (the least-recent event per the list's order) and decrements `size`. No-ops on an empty list. */
|
|
82
|
-
detach(): void {
|
|
83
|
-
const node = this.tail;
|
|
84
|
-
if (node === undefined) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
if (node.prev !== undefined) {
|
|
88
|
-
node.prev.next = node.next;
|
|
89
|
-
} else {
|
|
90
|
-
this.head = node.next;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (node.next !== undefined) {
|
|
94
|
-
node.next.prev = node.prev;
|
|
95
|
-
} else {
|
|
96
|
-
this.tail = node.prev;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
this.size--;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/** Materializes the list into a plain array, in current sort order. Allocates a new array — prefer iterating the list directly for hot paths. */
|
|
103
|
-
toArray(): EventMap[Type][] {
|
|
104
|
-
return Array.from(this);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
*[Symbol.iterator]() {
|
|
108
|
-
let node = this.head;
|
|
109
|
-
while (node) {
|
|
110
|
-
yield node.event;
|
|
111
|
-
node = node.next;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
@@ -1,521 +0,0 @@
|
|
|
1
|
-
// EventSubscriber — see the class doc below for behavior. This module also
|
|
2
|
-
// wires together the LogProvider implementations (websocket/polling/events-server);
|
|
3
|
-
// see `events/types.ts` for the full event type union and `events/parse.ts` for log parsing.
|
|
4
|
-
import { Connection, PublicKey, TransactionSignature } from '@solana/web3.js';
|
|
5
|
-
import { Program } from '../isomorphic/anchor';
|
|
6
|
-
import {
|
|
7
|
-
DefaultEventSubscriptionOptions,
|
|
8
|
-
EventSubscriptionOptions,
|
|
9
|
-
EventType,
|
|
10
|
-
WrappedEvents,
|
|
11
|
-
EventMap,
|
|
12
|
-
LogProvider,
|
|
13
|
-
EventSubscriberEvents,
|
|
14
|
-
WebSocketLogProviderConfig,
|
|
15
|
-
EventsServerLogProviderConfig,
|
|
16
|
-
LogProviderType,
|
|
17
|
-
StreamingLogProviderConfig,
|
|
18
|
-
PollingLogProviderConfig,
|
|
19
|
-
LogProviderConfig,
|
|
20
|
-
} from './types';
|
|
21
|
-
import { TxEventCache } from './txEventCache';
|
|
22
|
-
import { EventList } from './eventList';
|
|
23
|
-
import { PollingLogProvider } from './pollingLogProvider';
|
|
24
|
-
import { fetchLogs } from './fetchLogs';
|
|
25
|
-
import { WebSocketLogProvider } from './webSocketLogProvider';
|
|
26
|
-
import { EventEmitter } from 'events';
|
|
27
|
-
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
28
|
-
import { getSortFn } from './sort';
|
|
29
|
-
import { parseLogs } from './parse';
|
|
30
|
-
import { EventsServerLogProvider } from './eventsServerLogProvider';
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* EventSubscriber — streams and decodes Velocity program events from
|
|
34
|
-
* transaction logs (all records emitted via `emit!` from `state/events.rs`:
|
|
35
|
-
* `DepositRecord`, `OrderActionRecord`, `LiquidationRecord`,
|
|
36
|
-
* `FundingPaymentRecord`, etc. — see `EventMap` for the full set), via a
|
|
37
|
-
* pluggable `LogProvider` (websocket, polling, or the Velocity events server),
|
|
38
|
-
* and surfaces them both through per-type `EventList`s and a `'newEvent'`
|
|
39
|
-
* `eventEmitter`.
|
|
40
|
-
*
|
|
41
|
-
* Ordering and dedup: each decoded event is tagged with `slot` and a
|
|
42
|
-
* `txSigIndex` (its position among decoded events within the same
|
|
43
|
-
* transaction); the per-event-type `EventList`s use these to sort either by
|
|
44
|
-
* blockchain order (slot, then `txSigIndex`) or by client arrival order, per
|
|
45
|
-
* `EventSubscriptionOptions.orderBy`. Whole transactions are deduped by
|
|
46
|
-
* signature via an internal LRU (`TxEventCache`, sized by `options.maxTx`):
|
|
47
|
-
* a transaction already in the cache is skipped entirely on a subsequent
|
|
48
|
-
* delivery from the *same* log provider, which protects against a
|
|
49
|
-
* websocket/polling provider redelivering the same tx. Events pushed by the
|
|
50
|
-
* events-server provider bypass this cache (it dedups upstream and supplies
|
|
51
|
-
* an authoritative `txSigIndex`). Event names are also normalized from the
|
|
52
|
-
* `@coral-xyz/anchor` 0.32+ camelCase IDL form back to the PascalCase used by
|
|
53
|
-
* `EventType`/`EventMap` before being matched against the subscribed types.
|
|
54
|
-
*/
|
|
55
|
-
export class EventSubscriber {
|
|
56
|
-
private address: PublicKey;
|
|
57
|
-
private eventListMap: Map<EventType, EventList<EventType>>;
|
|
58
|
-
/** Case-insensitive lookup from decoded (camelCase) IDL event names to subscribed `EventType` keys. */
|
|
59
|
-
private eventTypeByLowercaseName = new Map<string, EventType>();
|
|
60
|
-
private txEventCache: TxEventCache;
|
|
61
|
-
private awaitTxPromises = new Map<string, Promise<void>>();
|
|
62
|
-
private awaitTxResolver = new Map<string, () => void>();
|
|
63
|
-
private _logProvider?: LogProvider;
|
|
64
|
-
private _currentProviderType: LogProviderType;
|
|
65
|
-
public eventEmitter: StrictEventEmitter<EventEmitter, EventSubscriberEvents>;
|
|
66
|
-
private lastSeenSlot: number | undefined;
|
|
67
|
-
private lastSeenBlockTime: number | undefined;
|
|
68
|
-
public lastSeenTxSig: string | undefined;
|
|
69
|
-
|
|
70
|
-
private get logProvider(): LogProvider {
|
|
71
|
-
if (!this._logProvider) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
'EventSubscriber: logProvider accessed before initializeLogProvider()'
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
return this._logProvider;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* @param connection RPC connection used by the polling/websocket log providers and by `fetchPreviousTx`.
|
|
81
|
-
* @param program Anchor `Program` whose IDL coder decodes event logs (see `parse.ts`).
|
|
82
|
-
* @param options Subscription options; merged over `DefaultEventSubscriptionOptions` so any field left unset uses the default.
|
|
83
|
-
*/
|
|
84
|
-
public constructor(
|
|
85
|
-
private connection: Connection,
|
|
86
|
-
private program: Program,
|
|
87
|
-
private options: EventSubscriptionOptions = DefaultEventSubscriptionOptions
|
|
88
|
-
) {
|
|
89
|
-
this.options = Object.assign({}, DefaultEventSubscriptionOptions, options);
|
|
90
|
-
this.address = this.options.address ?? program.programId;
|
|
91
|
-
this.txEventCache = new TxEventCache(this.options.maxTx);
|
|
92
|
-
this.eventListMap = new Map<EventType, EventList<EventType>>();
|
|
93
|
-
this.eventEmitter = new EventEmitter();
|
|
94
|
-
|
|
95
|
-
this._currentProviderType = this.getLogProviderConfig().type;
|
|
96
|
-
this.initializeLogProvider();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private getLogProviderConfig(): LogProviderConfig {
|
|
100
|
-
if (this.options.logProviderConfig === undefined) {
|
|
101
|
-
throw new Error('EventSubscriber: logProviderConfig is not set');
|
|
102
|
-
}
|
|
103
|
-
return this.options.logProviderConfig;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
private getEventTypes(): EventType[] {
|
|
107
|
-
if (this.options.eventTypes === undefined) {
|
|
108
|
-
throw new Error('EventSubscriber: eventTypes is not set');
|
|
109
|
-
}
|
|
110
|
-
return this.options.eventTypes;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** The `LogProviderType` currently in use. May differ from the configured type after a fallback failover (see `updateFallbackProviderType`). */
|
|
114
|
-
get currentProviderType() {
|
|
115
|
-
return this._currentProviderType;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
private initializeLogProvider(subscribe = false) {
|
|
119
|
-
const logProviderConfig = this.getLogProviderConfig();
|
|
120
|
-
|
|
121
|
-
if (this._currentProviderType === 'websocket') {
|
|
122
|
-
this._logProvider = new WebSocketLogProvider(
|
|
123
|
-
// @ts-ignore
|
|
124
|
-
this.connection,
|
|
125
|
-
this.address,
|
|
126
|
-
this.options.commitment ?? 'confirmed',
|
|
127
|
-
(logProviderConfig as WebSocketLogProviderConfig).resubTimeoutMs
|
|
128
|
-
);
|
|
129
|
-
} else if (this._currentProviderType === 'polling') {
|
|
130
|
-
const frequency =
|
|
131
|
-
'frequency' in logProviderConfig
|
|
132
|
-
? (logProviderConfig as PollingLogProviderConfig).frequency
|
|
133
|
-
: (logProviderConfig as StreamingLogProviderConfig).fallbackFrequency;
|
|
134
|
-
const batchSize =
|
|
135
|
-
'batchSize' in logProviderConfig
|
|
136
|
-
? (logProviderConfig as PollingLogProviderConfig).batchSize
|
|
137
|
-
: (logProviderConfig as StreamingLogProviderConfig).fallbackBatchSize;
|
|
138
|
-
|
|
139
|
-
this._logProvider = new PollingLogProvider(
|
|
140
|
-
// @ts-ignore
|
|
141
|
-
this.connection,
|
|
142
|
-
this.address,
|
|
143
|
-
this.options.commitment ?? 'confirmed',
|
|
144
|
-
frequency,
|
|
145
|
-
batchSize
|
|
146
|
-
);
|
|
147
|
-
} else if (this._currentProviderType === 'events-server') {
|
|
148
|
-
this._logProvider = new EventsServerLogProvider(
|
|
149
|
-
(logProviderConfig as EventsServerLogProviderConfig).url,
|
|
150
|
-
this.getEventTypes(),
|
|
151
|
-
this.options.address ? this.options.address.toString() : undefined
|
|
152
|
-
);
|
|
153
|
-
} else {
|
|
154
|
-
throw new Error(
|
|
155
|
-
`Invalid log provider type: ${this._currentProviderType}`
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (subscribe) {
|
|
160
|
-
this.logProvider.subscribe(
|
|
161
|
-
(txSig, slot, logs, mostRecentBlockTime, txSigIndex) => {
|
|
162
|
-
this.handleTxLogs(
|
|
163
|
-
txSig,
|
|
164
|
-
slot,
|
|
165
|
-
logs,
|
|
166
|
-
mostRecentBlockTime,
|
|
167
|
-
this._currentProviderType === 'events-server',
|
|
168
|
-
txSigIndex
|
|
169
|
-
);
|
|
170
|
-
},
|
|
171
|
-
true
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
private populateInitialEventListMap() {
|
|
177
|
-
const maxEventsPerType = this.options.maxEventsPerType;
|
|
178
|
-
const orderBy = this.options.orderBy;
|
|
179
|
-
const orderDir = this.options.orderDir;
|
|
180
|
-
if (
|
|
181
|
-
maxEventsPerType === undefined ||
|
|
182
|
-
orderBy === undefined ||
|
|
183
|
-
orderDir === undefined
|
|
184
|
-
) {
|
|
185
|
-
throw new Error(
|
|
186
|
-
'EventSubscriber: maxEventsPerType, orderBy and orderDir must be set'
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
for (const eventType of this.getEventTypes()) {
|
|
190
|
-
this.eventListMap.set(
|
|
191
|
-
eventType,
|
|
192
|
-
new EventList(
|
|
193
|
-
eventType,
|
|
194
|
-
maxEventsPerType,
|
|
195
|
-
getSortFn(orderBy, orderDir),
|
|
196
|
-
orderDir
|
|
197
|
-
)
|
|
198
|
-
);
|
|
199
|
-
this.eventTypeByLowercaseName.set(eventType.toLowerCase(), eventType);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Implements fallback logic for reconnecting to LogProvider. Currently terminates at polling,
|
|
205
|
-
* could be improved to try the original type again after some cooldown.
|
|
206
|
-
*/
|
|
207
|
-
private updateFallbackProviderType(
|
|
208
|
-
reconnectAttempts: number,
|
|
209
|
-
maxReconnectAttempts: number
|
|
210
|
-
) {
|
|
211
|
-
if (reconnectAttempts < maxReconnectAttempts) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
let nextProviderType = this._currentProviderType;
|
|
216
|
-
if (this._currentProviderType === 'events-server') {
|
|
217
|
-
nextProviderType = 'websocket';
|
|
218
|
-
} else if (this._currentProviderType === 'websocket') {
|
|
219
|
-
nextProviderType = 'polling';
|
|
220
|
-
} else if (this._currentProviderType === 'polling') {
|
|
221
|
-
nextProviderType = 'polling';
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
console.log(
|
|
225
|
-
`EventSubscriber: Failing over providerType ${this._currentProviderType} to ${nextProviderType}`
|
|
226
|
-
);
|
|
227
|
-
this._currentProviderType = nextProviderType;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Starts streaming events via the configured `LogProvider`. Idempotent —
|
|
232
|
-
* returns `true` immediately if already subscribed. (Re)initializes the
|
|
233
|
-
* per-event-type `EventList`s, so any events retained from a prior
|
|
234
|
-
* subscribe/unsubscribe cycle are discarded. For streaming providers
|
|
235
|
-
* (websocket, events-server), also wires up automatic failover: if the
|
|
236
|
-
* provider emits more than `maxReconnectAttempts` (default `Infinity`,
|
|
237
|
-
* i.e. never) reconnect attempts, the subscriber tears down and
|
|
238
|
-
* reinitializes with the next provider in the fallback chain
|
|
239
|
-
* (events-server → websocket → polling; polling has no further fallback).
|
|
240
|
-
* Does not itself backfill history — call `fetchPreviousTx` for that.
|
|
241
|
-
* @returns `true` once subscribed, or `false` if an error occurred while starting the subscription (logged to console, not thrown).
|
|
242
|
-
*/
|
|
243
|
-
public async subscribe(): Promise<boolean> {
|
|
244
|
-
try {
|
|
245
|
-
if (this.logProvider.isSubscribed()) {
|
|
246
|
-
return true;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
this.populateInitialEventListMap();
|
|
250
|
-
|
|
251
|
-
if (
|
|
252
|
-
this.getLogProviderConfig().type === 'websocket' ||
|
|
253
|
-
this.getLogProviderConfig().type === 'events-server'
|
|
254
|
-
) {
|
|
255
|
-
const logProviderConfig =
|
|
256
|
-
this.getLogProviderConfig() as StreamingLogProviderConfig;
|
|
257
|
-
// `maxReconnectAttempts` is optional; when unset the original
|
|
258
|
-
// `reconnectAttempts > undefined` comparison was always false, so
|
|
259
|
-
// fall back to Infinity to preserve that never-trigger behavior.
|
|
260
|
-
const maxReconnectAttempts =
|
|
261
|
-
logProviderConfig.maxReconnectAttempts ?? Infinity;
|
|
262
|
-
|
|
263
|
-
const eventEmitter = this.logProvider.eventEmitter;
|
|
264
|
-
if (eventEmitter) {
|
|
265
|
-
eventEmitter.on('reconnect', async (reconnectAttempts) => {
|
|
266
|
-
if (reconnectAttempts > maxReconnectAttempts) {
|
|
267
|
-
console.log(
|
|
268
|
-
`EventSubscriber: Reconnect attempts ${reconnectAttempts}/${maxReconnectAttempts}, reconnecting...`
|
|
269
|
-
);
|
|
270
|
-
eventEmitter.removeAllListeners('reconnect');
|
|
271
|
-
await this.unsubscribe();
|
|
272
|
-
this.updateFallbackProviderType(
|
|
273
|
-
reconnectAttempts,
|
|
274
|
-
maxReconnectAttempts
|
|
275
|
-
);
|
|
276
|
-
this.initializeLogProvider(true);
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
this.logProvider.subscribe(
|
|
282
|
-
(txSig, slot, logs, mostRecentBlockTime, txSigIndex) => {
|
|
283
|
-
this.handleTxLogs(
|
|
284
|
-
txSig,
|
|
285
|
-
slot,
|
|
286
|
-
logs,
|
|
287
|
-
mostRecentBlockTime,
|
|
288
|
-
this._currentProviderType === 'events-server',
|
|
289
|
-
txSigIndex
|
|
290
|
-
);
|
|
291
|
-
},
|
|
292
|
-
true
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
return true;
|
|
296
|
-
} catch (e) {
|
|
297
|
-
console.error('Error fetching previous txs in event subscriber');
|
|
298
|
-
console.error(e);
|
|
299
|
-
return false;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
private handleTxLogs(
|
|
304
|
-
txSig: TransactionSignature,
|
|
305
|
-
slot: number,
|
|
306
|
-
logs: string[],
|
|
307
|
-
mostRecentBlockTime: number | undefined,
|
|
308
|
-
fromEventsServer = false,
|
|
309
|
-
txSigIndex: number | undefined = undefined
|
|
310
|
-
): void {
|
|
311
|
-
if (!fromEventsServer && this.txEventCache.has(txSig)) {
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const wrappedEvents = this.parseEventsFromLogs(
|
|
316
|
-
txSig,
|
|
317
|
-
slot,
|
|
318
|
-
logs,
|
|
319
|
-
txSigIndex
|
|
320
|
-
);
|
|
321
|
-
|
|
322
|
-
for (const wrappedEvent of wrappedEvents) {
|
|
323
|
-
const eventList = this.eventListMap.get(wrappedEvent.eventType);
|
|
324
|
-
if (eventList === undefined) {
|
|
325
|
-
throw new Error(
|
|
326
|
-
`EventSubscriber: no EventList for eventType ${wrappedEvent.eventType}`
|
|
327
|
-
);
|
|
328
|
-
}
|
|
329
|
-
eventList.insert(wrappedEvent);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// dont emit event till we've added all the events to the eventListMap
|
|
333
|
-
for (const wrappedEvent of wrappedEvents) {
|
|
334
|
-
this.eventEmitter.emit('newEvent', wrappedEvent);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (this.awaitTxPromises.has(txSig)) {
|
|
338
|
-
this.awaitTxPromises.delete(txSig);
|
|
339
|
-
const resolver = this.awaitTxResolver.get(txSig);
|
|
340
|
-
if (resolver !== undefined) {
|
|
341
|
-
resolver();
|
|
342
|
-
}
|
|
343
|
-
this.awaitTxResolver.delete(txSig);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
if (!this.lastSeenSlot || slot > this.lastSeenSlot) {
|
|
347
|
-
this.lastSeenTxSig = txSig;
|
|
348
|
-
this.lastSeenSlot = slot;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
if (
|
|
352
|
-
this.lastSeenBlockTime === undefined ||
|
|
353
|
-
(mostRecentBlockTime !== undefined &&
|
|
354
|
-
mostRecentBlockTime > this.lastSeenBlockTime)
|
|
355
|
-
) {
|
|
356
|
-
this.lastSeenBlockTime = mostRecentBlockTime;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
this.txEventCache.add(txSig, wrappedEvents);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Backfills historical events by walking transactions for `address` via
|
|
364
|
-
* `getSignaturesForAddress`/`getTransaction`, newest-first, until either
|
|
365
|
-
* `options.untilTx` is reached or `options.maxTx` transactions have been
|
|
366
|
-
* fetched. Each fetched transaction is decoded and inserted into the
|
|
367
|
-
* event lists exactly like a live update, so `newEvent` fires for
|
|
368
|
-
* backfilled events too. No-ops if neither `untilTx` is set nor
|
|
369
|
-
* `fetchMax` is true — the subscriber does not backfill by default.
|
|
370
|
-
* @param fetchMax If true, backfill up to `maxTx` transactions even without an `untilTx` cutoff.
|
|
371
|
-
*/
|
|
372
|
-
public async fetchPreviousTx(fetchMax?: boolean): Promise<void> {
|
|
373
|
-
if (!this.options.untilTx && !fetchMax) {
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
let txFetched = 0;
|
|
378
|
-
let beforeTx: TransactionSignature | undefined = undefined;
|
|
379
|
-
const untilTx: TransactionSignature | undefined = this.options.untilTx;
|
|
380
|
-
const maxTx = this.options.maxTx;
|
|
381
|
-
if (maxTx === undefined) {
|
|
382
|
-
throw new Error('EventSubscriber: maxTx is not set');
|
|
383
|
-
}
|
|
384
|
-
while (txFetched < maxTx) {
|
|
385
|
-
const response = await fetchLogs(
|
|
386
|
-
// @ts-ignore
|
|
387
|
-
this.connection,
|
|
388
|
-
this.address,
|
|
389
|
-
this.options.commitment === 'finalized' ? 'finalized' : 'confirmed',
|
|
390
|
-
beforeTx,
|
|
391
|
-
untilTx
|
|
392
|
-
);
|
|
393
|
-
|
|
394
|
-
if (response === undefined) {
|
|
395
|
-
break;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
txFetched += response.transactionLogs.length;
|
|
399
|
-
beforeTx = response.earliestTx;
|
|
400
|
-
|
|
401
|
-
for (const { txSig, slot, logs } of response.transactionLogs) {
|
|
402
|
-
this.handleTxLogs(txSig, slot, logs, response.mostRecentBlockTime);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Stops the log provider and clears all in-memory state: the per-event-type
|
|
409
|
-
* `EventList`s, the `TxEventCache`, and any pending `awaitTx` promises
|
|
410
|
-
* (which are left unresolved/unrejected — callers awaiting a tx signature
|
|
411
|
-
* across an unsubscribe will hang).
|
|
412
|
-
* @returns Whatever the underlying `LogProvider.unsubscribe` returns.
|
|
413
|
-
*/
|
|
414
|
-
public async unsubscribe(): Promise<boolean> {
|
|
415
|
-
this.eventListMap.clear();
|
|
416
|
-
this.txEventCache.clear();
|
|
417
|
-
this.awaitTxPromises.clear();
|
|
418
|
-
this.awaitTxResolver.clear();
|
|
419
|
-
|
|
420
|
-
return await this.logProvider.unsubscribe(true);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
private parseEventsFromLogs(
|
|
424
|
-
txSig: TransactionSignature,
|
|
425
|
-
slot: number,
|
|
426
|
-
logs: string[],
|
|
427
|
-
txSigIndex: number | undefined
|
|
428
|
-
): WrappedEvents {
|
|
429
|
-
const records = [];
|
|
430
|
-
// @ts-ignore
|
|
431
|
-
const events = parseLogs(this.program, logs);
|
|
432
|
-
let runningEventIndex = 0;
|
|
433
|
-
for (const event of events) {
|
|
434
|
-
// @coral-xyz/anchor 0.32+ converts IDL names to camelCase; match
|
|
435
|
-
// case-insensitively so names with leading acronyms (LPSwapRecord →
|
|
436
|
-
// lpSwapRecord) still resolve to their PascalCase EventType keys.
|
|
437
|
-
const eventType = this.eventTypeByLowercaseName.get(
|
|
438
|
-
event.name.toLowerCase()
|
|
439
|
-
);
|
|
440
|
-
if (eventType) {
|
|
441
|
-
event.data.txSig = txSig;
|
|
442
|
-
event.data.slot = slot;
|
|
443
|
-
event.data.eventType = eventType;
|
|
444
|
-
event.data.txSigIndex =
|
|
445
|
-
txSigIndex !== undefined ? txSigIndex : runningEventIndex;
|
|
446
|
-
records.push(event.data);
|
|
447
|
-
}
|
|
448
|
-
runningEventIndex++;
|
|
449
|
-
}
|
|
450
|
-
return records;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* Resolves once the subscriber has observed and decoded events for `txSig`
|
|
455
|
-
* (immediately if it's already in the `TxEventCache`). Useful for waiting
|
|
456
|
-
* on the events of a transaction the caller just sent, before reading them
|
|
457
|
-
* via `getEventsByTx`. Never rejects; a transaction that never arrives
|
|
458
|
-
* (e.g. it failed, or the subscriber isn't subscribed) leaves the returned
|
|
459
|
-
* promise pending forever.
|
|
460
|
-
* @param txSig Signature to wait for.
|
|
461
|
-
* @returns A promise that resolves (with no value) once that transaction's events have been processed.
|
|
462
|
-
*/
|
|
463
|
-
public awaitTx(txSig: TransactionSignature): Promise<void> {
|
|
464
|
-
const existingPromise = this.awaitTxPromises.get(txSig);
|
|
465
|
-
if (existingPromise !== undefined) {
|
|
466
|
-
return existingPromise;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
if (this.txEventCache.has(txSig)) {
|
|
470
|
-
return Promise.resolve();
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
const promise = new Promise<void>((resolve) => {
|
|
474
|
-
this.awaitTxResolver.set(txSig, resolve);
|
|
475
|
-
});
|
|
476
|
-
this.awaitTxPromises.set(txSig, promise);
|
|
477
|
-
return promise;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
/**
|
|
481
|
-
* Returns the live `EventList` for `eventType` — the ordered, size-bounded
|
|
482
|
-
* (`maxEventsPerType`) linked list the subscriber inserts new events into.
|
|
483
|
-
* Prefer this over `getEventsArray` to iterate without copying.
|
|
484
|
-
* @param eventType Event type to look up; must be one of `options.eventTypes` (subscribed types).
|
|
485
|
-
* @returns The `EventList` for that type, or `undefined` if `eventType` was never subscribed (list not yet populated by `subscribe()`).
|
|
486
|
-
*/
|
|
487
|
-
public getEventList<Type extends keyof EventMap>(
|
|
488
|
-
eventType: Type
|
|
489
|
-
): EventList<Type> | undefined {
|
|
490
|
-
return this.eventListMap.get(eventType) as EventList<Type> | undefined;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
/**
|
|
494
|
-
* This requires the EventList be cast to an array, which requires reallocation of memory.
|
|
495
|
-
* Would bias to using getEventList over getEvents
|
|
496
|
-
*
|
|
497
|
-
* @param eventType Event type to snapshot.
|
|
498
|
-
* @returns All currently retained events of that type, in the `EventList`'s sort order (see `EventSubscriptionOptions.orderBy`/`orderDir`).
|
|
499
|
-
* @throws If `eventType` has no `EventList` (i.e. it isn't in `options.eventTypes`).
|
|
500
|
-
*/
|
|
501
|
-
public getEventsArray<Type extends EventType>(
|
|
502
|
-
eventType: Type
|
|
503
|
-
): EventMap[Type][] {
|
|
504
|
-
const eventList = this.eventListMap.get(eventType);
|
|
505
|
-
if (eventList === undefined) {
|
|
506
|
-
throw new Error(
|
|
507
|
-
`EventSubscriber: no EventList for eventType ${eventType}`
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
return eventList.toArray() as EventMap[Type][];
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
/**
|
|
514
|
-
* Looks up the decoded events previously observed for a transaction.
|
|
515
|
-
* @param txSig Transaction signature to look up.
|
|
516
|
-
* @returns The wrapped events emitted by that transaction, or `undefined` if the transaction has aged out of the `TxEventCache` (bounded by `options.maxTx`) or was never observed.
|
|
517
|
-
*/
|
|
518
|
-
public getEventsByTx(txSig: TransactionSignature): WrappedEvents | undefined {
|
|
519
|
-
return this.txEventCache.get(txSig);
|
|
520
|
-
}
|
|
521
|
-
}
|