@velocity-exchange/sdk 0.4.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/lib/browser/adminClient.d.ts +52 -0
- package/lib/browser/adminClient.js +97 -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 +191 -15
- package/lib/browser/idl/velocity.json +192 -16
- package/lib/browser/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/browser/orderSubscriber/OrderSubscriber.js +10 -4
- package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
- package/lib/browser/types.d.ts +6 -0
- package/lib/browser/user.d.ts +20 -3
- package/lib/browser/user.js +52 -4
- package/lib/browser/velocityClient.d.ts +46 -10
- package/lib/browser/velocityClient.js +107 -35
- package/lib/node/adminClient.d.ts +52 -0
- package/lib/node/adminClient.d.ts.map +1 -1
- package/lib/node/adminClient.js +97 -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 +191 -15
- package/lib/node/idl/velocity.d.ts.map +1 -1
- package/lib/node/idl/velocity.json +192 -16
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
- package/lib/node/orderSubscriber/OrderSubscriber.js +10 -4
- package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
- package/lib/node/pyth/pythLazerSubscriber.js +37 -27
- package/lib/node/types.d.ts +6 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/user.d.ts +20 -3
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +52 -4
- 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
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Channel,
|
|
3
|
-
PriceFeedProperty,
|
|
4
|
-
PythLazerClient,
|
|
5
|
-
} from '@pythnetwork/pyth-lazer-sdk';
|
|
6
|
-
import { VelocityEnv } from '../config';
|
|
7
|
-
import { PerpMarkets } from '../constants/perpMarkets';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Configuration for a group of Pyth Lazer price feeds.
|
|
11
|
-
*/
|
|
12
|
-
export type PythLazerPriceFeedArray = {
|
|
13
|
-
/** Optional channel for update frequency (e.g., 'fixed_rate@200ms') */
|
|
14
|
-
channel?: Channel;
|
|
15
|
-
/** Array of Pyth Lazer price feed IDs to subscribe to */
|
|
16
|
-
priceFeedIds: number[];
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
type FeedSymbolInfo = {
|
|
20
|
-
name: string;
|
|
21
|
-
state: string;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Manages subscriptions to Pyth Lazer price feeds and provides access to real-time price data.
|
|
26
|
-
* Automatically filters out non-stable feeds and handles reconnection logic.
|
|
27
|
-
*/
|
|
28
|
-
export class PythLazerSubscriber {
|
|
29
|
-
private static readonly SYMBOLS_API_URL =
|
|
30
|
-
'https://history.pyth-lazer.dourolabs.app/history/v1/symbols';
|
|
31
|
-
private symbolsCache: Map<number, FeedSymbolInfo> | null = null;
|
|
32
|
-
private pythLazerClient?: PythLazerClient;
|
|
33
|
-
feedIdChunkToPriceMessage: Map<string, string> = new Map();
|
|
34
|
-
feedIdToPrice: Map<number, number> = new Map();
|
|
35
|
-
feedIdHashToFeedIds: Map<string, number[]> = new Map();
|
|
36
|
-
subscriptionIdsToFeedIdsHash: Map<number, string> = new Map();
|
|
37
|
-
allSubscribedIds: number[] = [];
|
|
38
|
-
|
|
39
|
-
timeoutId?: NodeJS.Timeout;
|
|
40
|
-
receivingData = false;
|
|
41
|
-
isUnsubscribing = false;
|
|
42
|
-
|
|
43
|
-
marketIndextoPriceFeedIdChunk: Map<number, number[]> = new Map();
|
|
44
|
-
marketIndextoPriceFeedId: Map<number, number> = new Map();
|
|
45
|
-
|
|
46
|
-
private readonly feedProperties: PriceFeedProperty[];
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Creates a new PythLazerSubscriber instance.
|
|
50
|
-
* @param endpoints - Array of WebSocket endpoint URLs for Pyth Lazer
|
|
51
|
-
* @param token - Authentication token for Pyth Lazer API
|
|
52
|
-
* @param priceFeedArrays - Array of price feed configurations to subscribe to
|
|
53
|
-
* @param env - Velocity environment (mainnet-beta, devnet, etc.)
|
|
54
|
-
* @param resubTimeoutMs - Milliseconds to wait before resubscribing on data timeout
|
|
55
|
-
* @param sdkLogging - Whether to log Pyth SDK logs to the console. This is very noisy but could be useful for debugging.
|
|
56
|
-
* @param feedProperties - Price feed properties to request. Must include both 'price' and 'exponent' (required for getPriceFromMarketIndex). Defaults to ['price', 'bestAskPrice', 'bestBidPrice', 'exponent']. Stored by copy so caller mutation does not affect this instance.
|
|
57
|
-
*/
|
|
58
|
-
constructor(
|
|
59
|
-
private endpoints: string[],
|
|
60
|
-
private token: string,
|
|
61
|
-
private priceFeedArrays: PythLazerPriceFeedArray[],
|
|
62
|
-
env: VelocityEnv = 'devnet',
|
|
63
|
-
private resubTimeoutMs: number = 2000,
|
|
64
|
-
private sdkLogging: boolean = false,
|
|
65
|
-
feedProperties: PriceFeedProperty[] = [
|
|
66
|
-
'price',
|
|
67
|
-
'bestAskPrice',
|
|
68
|
-
'bestBidPrice',
|
|
69
|
-
'exponent',
|
|
70
|
-
'feedUpdateTimestamp',
|
|
71
|
-
]
|
|
72
|
-
) {
|
|
73
|
-
this.feedProperties = [...feedProperties];
|
|
74
|
-
if (
|
|
75
|
-
!this.feedProperties.includes('price') ||
|
|
76
|
-
!this.feedProperties.includes('exponent')
|
|
77
|
-
) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
"feedProperties must include both 'price' and 'exponent' for getPriceFromMarketIndex to work"
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
const markets = PerpMarkets[env].filter(
|
|
83
|
-
(market) => market.pythLazerId !== undefined
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
this.allSubscribedIds = this.priceFeedArrays
|
|
87
|
-
.map((array) => array.priceFeedIds)
|
|
88
|
-
.flat();
|
|
89
|
-
|
|
90
|
-
for (const priceFeedIds of priceFeedArrays) {
|
|
91
|
-
const filteredMarkets = markets.filter((market) =>
|
|
92
|
-
priceFeedIds.priceFeedIds.includes(market.pythLazerId!)
|
|
93
|
-
);
|
|
94
|
-
for (const market of filteredMarkets) {
|
|
95
|
-
this.marketIndextoPriceFeedIdChunk.set(
|
|
96
|
-
market.marketIndex,
|
|
97
|
-
priceFeedIds.priceFeedIds
|
|
98
|
-
);
|
|
99
|
-
this.marketIndextoPriceFeedId.set(
|
|
100
|
-
market.marketIndex,
|
|
101
|
-
market.pythLazerId!
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
private async fetchSymbolsIfNeeded(): Promise<void> {
|
|
108
|
-
if (this.symbolsCache !== null) return;
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
const response = await fetch(PythLazerSubscriber.SYMBOLS_API_URL);
|
|
112
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
113
|
-
const symbols = await response.json();
|
|
114
|
-
|
|
115
|
-
this.symbolsCache = new Map();
|
|
116
|
-
for (const symbol of symbols) {
|
|
117
|
-
this.symbolsCache.set(symbol.pyth_lazer_id, {
|
|
118
|
-
name: symbol.name,
|
|
119
|
-
state: symbol.state,
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
} catch (error) {
|
|
123
|
-
console.warn(
|
|
124
|
-
`Failed to fetch Pyth Lazer symbols, proceeding with all feeds: ${error}`
|
|
125
|
-
);
|
|
126
|
-
this.symbolsCache = new Map(); // Empty map = no filtering
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
private filterStableFeeds(feedIds: number[]): number[] {
|
|
131
|
-
if (this.symbolsCache === null || this.symbolsCache.size === 0) {
|
|
132
|
-
return feedIds; // No filtering if cache unavailable
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return feedIds.filter((feedId) => {
|
|
136
|
-
const info = this.symbolsCache!.get(feedId);
|
|
137
|
-
if (!info) {
|
|
138
|
-
console.warn(
|
|
139
|
-
`Feed ID ${feedId} not found in symbols API, including anyway`
|
|
140
|
-
);
|
|
141
|
-
return true;
|
|
142
|
-
}
|
|
143
|
-
if (info.state !== 'stable') {
|
|
144
|
-
console.warn(
|
|
145
|
-
`Removing feed ID ${feedId} (${info.name}) - state is "${info.state}", not "stable"`
|
|
146
|
-
);
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
return true;
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Subscribes to Pyth Lazer price feeds. Automatically filters out non-stable feeds
|
|
155
|
-
* and establishes WebSocket connections for real-time price updates.
|
|
156
|
-
*/
|
|
157
|
-
async subscribe() {
|
|
158
|
-
await this.fetchSymbolsIfNeeded();
|
|
159
|
-
|
|
160
|
-
this.pythLazerClient = await PythLazerClient.create({
|
|
161
|
-
token: this.token,
|
|
162
|
-
logger: this.sdkLogging ? console : undefined,
|
|
163
|
-
webSocketPoolConfig: {
|
|
164
|
-
urls: this.endpoints,
|
|
165
|
-
numConnections: 4, // Optionally specify number of parallel redundant connections to reduce the chance of dropped messages. The connections will round-robin across the provided URLs. Default is 4.
|
|
166
|
-
onError: (error) => {
|
|
167
|
-
console.error('⛔️ PythLazerClient error:', error.message);
|
|
168
|
-
},
|
|
169
|
-
onWebSocketError: (error) => {
|
|
170
|
-
console.error('⛔️ WebSocket error:', error.message);
|
|
171
|
-
},
|
|
172
|
-
onWebSocketPoolError: (error) => {
|
|
173
|
-
console.error('⛔️ WebSocket pool error:', error.message);
|
|
174
|
-
},
|
|
175
|
-
// Optional configuration for resilient WebSocket connections
|
|
176
|
-
rwsConfig: {
|
|
177
|
-
heartbeatTimeoutDurationMs: 5000, // Optional heartbeat timeout duration in milliseconds
|
|
178
|
-
maxRetryDelayMs: 1000, // Optional maximum retry delay in milliseconds
|
|
179
|
-
logAfterRetryCount: 10, // Optional log after how many retries
|
|
180
|
-
},
|
|
181
|
-
},
|
|
182
|
-
});
|
|
183
|
-
// Reset allSubscribedIds to rebuild with only stable feeds
|
|
184
|
-
this.allSubscribedIds = [];
|
|
185
|
-
|
|
186
|
-
let subscriptionId = 1;
|
|
187
|
-
for (const priceFeedArray of this.priceFeedArrays) {
|
|
188
|
-
const filteredFeedIds = this.filterStableFeeds(
|
|
189
|
-
priceFeedArray.priceFeedIds
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
if (filteredFeedIds.length === 0) {
|
|
193
|
-
console.warn(
|
|
194
|
-
`All feeds filtered out for subscription ${subscriptionId}, skipping`
|
|
195
|
-
);
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Update allSubscribedIds with only stable feeds
|
|
200
|
-
this.allSubscribedIds.push(...filteredFeedIds);
|
|
201
|
-
|
|
202
|
-
const feedIdsHash = this.hash(filteredFeedIds);
|
|
203
|
-
this.feedIdHashToFeedIds.set(feedIdsHash, filteredFeedIds);
|
|
204
|
-
this.subscriptionIdsToFeedIdsHash.set(subscriptionId, feedIdsHash);
|
|
205
|
-
|
|
206
|
-
// Update marketIndextoPriceFeedIdChunk to use filtered feeds
|
|
207
|
-
for (const [
|
|
208
|
-
marketIndex,
|
|
209
|
-
chunk,
|
|
210
|
-
] of this.marketIndextoPriceFeedIdChunk.entries()) {
|
|
211
|
-
if (this.hash(chunk) === this.hash(priceFeedArray.priceFeedIds)) {
|
|
212
|
-
this.marketIndextoPriceFeedIdChunk.set(marketIndex, filteredFeedIds);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Remove entries from marketIndextoPriceFeedId for filtered-out feeds
|
|
217
|
-
for (const [
|
|
218
|
-
marketIndex,
|
|
219
|
-
feedId,
|
|
220
|
-
] of this.marketIndextoPriceFeedId.entries()) {
|
|
221
|
-
if (
|
|
222
|
-
!filteredFeedIds.includes(feedId) &&
|
|
223
|
-
priceFeedArray.priceFeedIds.includes(feedId)
|
|
224
|
-
) {
|
|
225
|
-
this.marketIndextoPriceFeedId.delete(marketIndex);
|
|
226
|
-
this.marketIndextoPriceFeedIdChunk.delete(marketIndex);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
this.pythLazerClient.addMessageListener((message) => {
|
|
231
|
-
this.receivingData = true;
|
|
232
|
-
clearTimeout(this.timeoutId);
|
|
233
|
-
switch (message.type) {
|
|
234
|
-
case 'json': {
|
|
235
|
-
if (message.value.type == 'streamUpdated') {
|
|
236
|
-
if (message.value.solana?.data) {
|
|
237
|
-
this.feedIdChunkToPriceMessage.set(
|
|
238
|
-
this.subscriptionIdsToFeedIdsHash.get(
|
|
239
|
-
message.value.subscriptionId
|
|
240
|
-
)!,
|
|
241
|
-
message.value.solana.data
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
if (message.value.parsed?.priceFeeds) {
|
|
245
|
-
for (const priceFeed of message.value.parsed.priceFeeds) {
|
|
246
|
-
const price =
|
|
247
|
-
Number(priceFeed.price!) *
|
|
248
|
-
Math.pow(10, Number(priceFeed.exponent!));
|
|
249
|
-
this.feedIdToPrice.set(priceFeed.priceFeedId, price);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
default: {
|
|
256
|
-
break;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
this.setTimeout();
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
this.pythLazerClient.send({
|
|
263
|
-
type: 'subscribe',
|
|
264
|
-
subscriptionId,
|
|
265
|
-
priceFeedIds: filteredFeedIds,
|
|
266
|
-
properties: this.feedProperties,
|
|
267
|
-
formats: ['solana'],
|
|
268
|
-
deliveryFormat: 'json',
|
|
269
|
-
channel: priceFeedArray.channel ?? ('fixed_rate@200ms' as Channel),
|
|
270
|
-
jsonBinaryEncoding: 'hex',
|
|
271
|
-
});
|
|
272
|
-
subscriptionId++;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
this.receivingData = true;
|
|
276
|
-
this.setTimeout();
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
protected setTimeout(): void {
|
|
280
|
-
this.timeoutId = setTimeout(async () => {
|
|
281
|
-
if (this.isUnsubscribing) {
|
|
282
|
-
// If we are in the process of unsubscribing, do not attempt to resubscribe
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (this.receivingData) {
|
|
287
|
-
console.log(`No ws data from pyth lazer client resubscribing`);
|
|
288
|
-
await this.unsubscribe();
|
|
289
|
-
this.receivingData = false;
|
|
290
|
-
await this.subscribe();
|
|
291
|
-
}
|
|
292
|
-
}, this.resubTimeoutMs);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Unsubscribes from all Pyth Lazer price feeds and closes WebSocket connections.
|
|
297
|
-
*/
|
|
298
|
-
async unsubscribe() {
|
|
299
|
-
this.isUnsubscribing = true;
|
|
300
|
-
this.pythLazerClient?.shutdown();
|
|
301
|
-
this.pythLazerClient = undefined;
|
|
302
|
-
clearTimeout(this.timeoutId);
|
|
303
|
-
this.timeoutId = undefined;
|
|
304
|
-
this.isUnsubscribing = false;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
hash(arr: number[]): string {
|
|
308
|
-
return 'h:' + arr.join('|');
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Retrieves the latest Solana-format price message for a group of feed IDs.
|
|
313
|
-
* @param feedIds - Array of price feed IDs
|
|
314
|
-
* @returns Hex-encoded price message data, or undefined if not available
|
|
315
|
-
*/
|
|
316
|
-
async getLatestPriceMessage(feedIds: number[]): Promise<string | undefined> {
|
|
317
|
-
return this.feedIdChunkToPriceMessage.get(this.hash(feedIds));
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Retrieves the latest Solana-format price message for a specific market.
|
|
322
|
-
* @param marketIndex - The market index to get price data for
|
|
323
|
-
* @returns Hex-encoded price message data, or undefined if not found
|
|
324
|
-
*/
|
|
325
|
-
async getLatestPriceMessageForMarketIndex(
|
|
326
|
-
marketIndex: number
|
|
327
|
-
): Promise<string | undefined> {
|
|
328
|
-
const feedIds = this.marketIndextoPriceFeedIdChunk.get(marketIndex);
|
|
329
|
-
if (!feedIds) {
|
|
330
|
-
return undefined;
|
|
331
|
-
}
|
|
332
|
-
return await this.getLatestPriceMessage(feedIds);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Gets the array of price feed IDs associated with a market index.
|
|
337
|
-
* @param marketIndex - The market index to look up
|
|
338
|
-
* @returns Array of price feed IDs, or empty array if not found
|
|
339
|
-
*/
|
|
340
|
-
getPriceFeedIdsFromMarketIndex(marketIndex: number): number[] {
|
|
341
|
-
return this.marketIndextoPriceFeedIdChunk.get(marketIndex) || [];
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Gets the array of price feed IDs from a subscription hash.
|
|
346
|
-
* @param hash - The subscription hash
|
|
347
|
-
* @returns Array of price feed IDs, or empty array if not found
|
|
348
|
-
*/
|
|
349
|
-
getPriceFeedIdsFromHash(hash: string): number[] {
|
|
350
|
-
return this.feedIdHashToFeedIds.get(hash) || [];
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Gets the current parsed price for a specific market index.
|
|
355
|
-
* @param marketIndex - The market index to get the price for
|
|
356
|
-
* @returns The price as a number, or undefined if not available
|
|
357
|
-
*/
|
|
358
|
-
getPriceFromMarketIndex(marketIndex: number): number | undefined {
|
|
359
|
-
const feedId = this.marketIndextoPriceFeedId.get(marketIndex);
|
|
360
|
-
if (feedId === undefined) {
|
|
361
|
-
return undefined;
|
|
362
|
-
}
|
|
363
|
-
return this.feedIdToPrice.get(feedId);
|
|
364
|
-
}
|
|
365
|
-
}
|