@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,284 +0,0 @@
|
|
|
1
|
-
import { VelocityClient } from '../src/velocityClient';
|
|
2
|
-
import { grpcVelocityClientAccountSubscriberV2 } from '../src/accounts/grpcVelocityClientAccountSubscriberV2';
|
|
3
|
-
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
4
|
-
import { VelocityClientConfig } from '../src/velocityClientConfig';
|
|
5
|
-
import {
|
|
6
|
-
VELOCITY_PROGRAM_ID,
|
|
7
|
-
PerpMarketAccount,
|
|
8
|
-
SpotMarketAccount,
|
|
9
|
-
Wallet,
|
|
10
|
-
OracleInfo,
|
|
11
|
-
decodeName,
|
|
12
|
-
} from '../src';
|
|
13
|
-
import { CommitmentLevel } from '@triton-one/yellowstone-grpc';
|
|
14
|
-
import dotenv from 'dotenv';
|
|
15
|
-
import {
|
|
16
|
-
AnchorProvider,
|
|
17
|
-
Idl,
|
|
18
|
-
Program,
|
|
19
|
-
ProgramAccount,
|
|
20
|
-
} from '@coral-xyz/anchor';
|
|
21
|
-
import velocityIDL from '../src/idl/velocity.json';
|
|
22
|
-
import { grpcMultiUserAccountSubscriber } from '../src/accounts/grpcMultiUserAccountSubscriber';
|
|
23
|
-
|
|
24
|
-
const GRPC_ENDPOINT = process.env.GRPC_ENDPOINT;
|
|
25
|
-
const TOKEN = process.env.TOKEN;
|
|
26
|
-
const RPC_ENDPOINT = process.env.RPC_ENDPOINT;
|
|
27
|
-
|
|
28
|
-
async function initializeSingleGrpcClient() {
|
|
29
|
-
console.log('🚀 Initializing single gRPC Velocity Client...');
|
|
30
|
-
|
|
31
|
-
const connection = new Connection(RPC_ENDPOINT);
|
|
32
|
-
const wallet = new Wallet(new Keypair());
|
|
33
|
-
dotenv.config({ path: '../' });
|
|
34
|
-
|
|
35
|
-
const programId = new PublicKey(VELOCITY_PROGRAM_ID);
|
|
36
|
-
const provider = new AnchorProvider(
|
|
37
|
-
connection,
|
|
38
|
-
// @ts-ignore
|
|
39
|
-
wallet,
|
|
40
|
-
{
|
|
41
|
-
commitment: 'processed',
|
|
42
|
-
}
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const program = new Program(velocityIDL as Idl, programId, provider);
|
|
46
|
-
|
|
47
|
-
// Get perp market accounts
|
|
48
|
-
const allPerpMarketProgramAccounts =
|
|
49
|
-
(await program.account.perpMarket.all()) as ProgramAccount<PerpMarketAccount>[];
|
|
50
|
-
const perpMarketProgramAccounts = allPerpMarketProgramAccounts.filter((val) =>
|
|
51
|
-
[46].includes(val.account.marketIndex)
|
|
52
|
-
);
|
|
53
|
-
const perpMarketIndexes = perpMarketProgramAccounts.map(
|
|
54
|
-
(val) => val.account.marketIndex
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
// Get spot market accounts
|
|
58
|
-
const allSpotMarketProgramAccounts =
|
|
59
|
-
(await program.account.spotMarket.all()) as ProgramAccount<SpotMarketAccount>[];
|
|
60
|
-
const spotMarketProgramAccounts = allSpotMarketProgramAccounts.filter((val) =>
|
|
61
|
-
[0].includes(val.account.marketIndex)
|
|
62
|
-
);
|
|
63
|
-
const spotMarketIndexes = spotMarketProgramAccounts.map(
|
|
64
|
-
(val) => val.account.marketIndex
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
// Get oracle infos
|
|
68
|
-
const seen = new Set<string>();
|
|
69
|
-
const oracleInfos: OracleInfo[] = [];
|
|
70
|
-
for (const acct of perpMarketProgramAccounts) {
|
|
71
|
-
const key = `${acct.account.amm.oracle.toBase58()}-${
|
|
72
|
-
Object.keys(acct.account.amm.oracleSource)[0]
|
|
73
|
-
}`;
|
|
74
|
-
if (!seen.has(key)) {
|
|
75
|
-
seen.add(key);
|
|
76
|
-
oracleInfos.push({
|
|
77
|
-
publicKey: acct.account.amm.oracle,
|
|
78
|
-
source: acct.account.amm.oracleSource,
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
for (const acct of spotMarketProgramAccounts) {
|
|
83
|
-
const key = `${acct.account.oracle.toBase58()}-${
|
|
84
|
-
Object.keys(acct.account.oracleSource)[0]
|
|
85
|
-
}`;
|
|
86
|
-
if (!seen.has(key)) {
|
|
87
|
-
seen.add(key);
|
|
88
|
-
oracleInfos.push({
|
|
89
|
-
publicKey: acct.account.oracle,
|
|
90
|
-
source: acct.account.oracleSource,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
console.log(
|
|
96
|
-
`📊 Markets: ${perpMarketIndexes.length} perp, ${spotMarketIndexes.length} spot`
|
|
97
|
-
);
|
|
98
|
-
console.log(`🔮 Oracles: ${oracleInfos.length}`);
|
|
99
|
-
|
|
100
|
-
const grpcConfigs = {
|
|
101
|
-
endpoint: GRPC_ENDPOINT,
|
|
102
|
-
token: TOKEN,
|
|
103
|
-
commitmentLevel: CommitmentLevel.PROCESSED,
|
|
104
|
-
channelOptions: {
|
|
105
|
-
grpcKeepAliveTimeout: 1_000,
|
|
106
|
-
grpcTcpKeepalive: 10_000,
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const multiUserSubsciber = new grpcMultiUserAccountSubscriber(
|
|
111
|
-
program,
|
|
112
|
-
grpcConfigs
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
const baseAccountSubscription = {
|
|
116
|
-
type: 'grpc' as const,
|
|
117
|
-
grpcConfigs,
|
|
118
|
-
grpcMultiUserAccountSubscriber: multiUserSubsciber,
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
const config: VelocityClientConfig = {
|
|
122
|
-
connection,
|
|
123
|
-
wallet,
|
|
124
|
-
programID: new PublicKey(VELOCITY_PROGRAM_ID),
|
|
125
|
-
accountSubscription: {
|
|
126
|
-
...baseAccountSubscription,
|
|
127
|
-
velocityClientAccountSubscriber: grpcVelocityClientAccountSubscriberV2,
|
|
128
|
-
},
|
|
129
|
-
perpMarketIndexes,
|
|
130
|
-
spotMarketIndexes,
|
|
131
|
-
oracleInfos,
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const client = new VelocityClient(config);
|
|
135
|
-
|
|
136
|
-
// Set up event listeners
|
|
137
|
-
const eventCounts = {
|
|
138
|
-
stateAccountUpdate: 0,
|
|
139
|
-
perpMarketAccountUpdate: 0,
|
|
140
|
-
spotMarketAccountUpdate: 0,
|
|
141
|
-
oraclePriceUpdate: 0,
|
|
142
|
-
update: 0,
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
console.log('🎧 Setting up event listeners...');
|
|
146
|
-
|
|
147
|
-
client.eventEmitter.on('stateAccountUpdate', (_data) => {
|
|
148
|
-
eventCounts.stateAccountUpdate++;
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
client.eventEmitter.on('perpMarketAccountUpdate', (_data) => {
|
|
152
|
-
eventCounts.perpMarketAccountUpdate++;
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
client.eventEmitter.on('spotMarketAccountUpdate', (_data) => {
|
|
156
|
-
eventCounts.spotMarketAccountUpdate++;
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
client.eventEmitter.on('oraclePriceUpdate', (_publicKey, _source, _data) => {
|
|
160
|
-
eventCounts.oraclePriceUpdate++;
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
client.accountSubscriber.eventEmitter.on('update', () => {
|
|
164
|
-
eventCounts.update++;
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// Subscribe
|
|
168
|
-
console.log('🔗 Subscribing to accounts...');
|
|
169
|
-
await client.subscribe();
|
|
170
|
-
|
|
171
|
-
console.log('✅ Client subscribed successfully!');
|
|
172
|
-
console.log(
|
|
173
|
-
'🚀 Starting high-load testing (50 reads/sec per perp market)...'
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
// High-frequency load testing - 50 reads per second per perp market
|
|
177
|
-
const loadTestInterval = setInterval(async () => {
|
|
178
|
-
try {
|
|
179
|
-
// Test getPerpMarketAccount for each perp market (50 times per second per market)
|
|
180
|
-
for (const marketIndex of perpMarketIndexes) {
|
|
181
|
-
const perpMarketAccount = client.getPerpMarketAccount(marketIndex);
|
|
182
|
-
if (!perpMarketAccount) {
|
|
183
|
-
console.log(`Perp market ${marketIndex} not found`);
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
console.log(
|
|
187
|
-
'perpMarketAccount name: ',
|
|
188
|
-
decodeName(perpMarketAccount.name)
|
|
189
|
-
);
|
|
190
|
-
console.log(
|
|
191
|
-
'perpMarketAccount data: ',
|
|
192
|
-
JSON.stringify({
|
|
193
|
-
marketIndex: perpMarketAccount.marketIndex,
|
|
194
|
-
name: decodeName(perpMarketAccount.name),
|
|
195
|
-
baseAssetReserve: perpMarketAccount.amm.baseAssetReserve.toString(),
|
|
196
|
-
quoteAssetReserve:
|
|
197
|
-
perpMarketAccount.amm.quoteAssetReserve.toString(),
|
|
198
|
-
})
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Test getMMOracleDataForPerpMarket for each perp market (50 times per second per market)
|
|
203
|
-
for (const marketIndex of perpMarketIndexes) {
|
|
204
|
-
try {
|
|
205
|
-
const oracleData = client.getMMOracleDataForPerpMarket(marketIndex);
|
|
206
|
-
console.log('oracleData price: ', oracleData.price.toString());
|
|
207
|
-
console.log(
|
|
208
|
-
'oracleData: ',
|
|
209
|
-
JSON.stringify({
|
|
210
|
-
price: oracleData.price.toString(),
|
|
211
|
-
confidence: oracleData.confidence?.toString(),
|
|
212
|
-
slot: oracleData.slot?.toString(),
|
|
213
|
-
})
|
|
214
|
-
);
|
|
215
|
-
} catch (error) {
|
|
216
|
-
// Ignore errors for load testing
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
for (const marketIndex of perpMarketIndexes) {
|
|
221
|
-
try {
|
|
222
|
-
const { data, slot } =
|
|
223
|
-
client.accountSubscriber.getMarketAccountAndSlot(marketIndex);
|
|
224
|
-
if (!data) {
|
|
225
|
-
console.log(
|
|
226
|
-
`Perp market getMarketAccountAndSlot ${marketIndex} not found`
|
|
227
|
-
);
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
console.log(
|
|
231
|
-
'marketAccountAndSlot: ',
|
|
232
|
-
JSON.stringify({
|
|
233
|
-
marketIndex: data.marketIndex,
|
|
234
|
-
name: decodeName(data.name),
|
|
235
|
-
slot: slot?.toString(),
|
|
236
|
-
baseAssetReserve: data.amm.baseAssetReserve.toString(),
|
|
237
|
-
quoteAssetReserve: data.amm.quoteAssetReserve.toString(),
|
|
238
|
-
})
|
|
239
|
-
);
|
|
240
|
-
} catch (error) {
|
|
241
|
-
console.error(
|
|
242
|
-
`Error getting market account and slot for market ${marketIndex}:`,
|
|
243
|
-
error
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
} catch (error) {
|
|
248
|
-
console.error('Load test error:', error);
|
|
249
|
-
}
|
|
250
|
-
}, 20); // 50 times per second = 1000ms / 50 = 20ms interval
|
|
251
|
-
|
|
252
|
-
// Log periodic stats
|
|
253
|
-
const statsInterval = setInterval(() => {
|
|
254
|
-
console.log('\n📈 Event Counts:', eventCounts);
|
|
255
|
-
console.log(`⏱️ Client subscribed: ${client.isSubscribed}`);
|
|
256
|
-
console.log(
|
|
257
|
-
`🔗 Account subscriber subscribed: ${client.accountSubscriber.isSubscribed}`
|
|
258
|
-
);
|
|
259
|
-
console.log(
|
|
260
|
-
`🔥 Load: ${perpMarketIndexes.length * 50 * 2} reads/sec (${
|
|
261
|
-
perpMarketIndexes.length
|
|
262
|
-
} markets × 50 getPerpMarketAccount + 50 getMMOracleDataForPerpMarket)`
|
|
263
|
-
);
|
|
264
|
-
}, 5000);
|
|
265
|
-
|
|
266
|
-
// Handle shutdown signals - just exit without cleanup since they never unsubscribe
|
|
267
|
-
process.on('SIGINT', () => {
|
|
268
|
-
console.log('\n🛑 Shutting down...');
|
|
269
|
-
clearInterval(loadTestInterval);
|
|
270
|
-
clearInterval(statsInterval);
|
|
271
|
-
process.exit(0);
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
process.on('SIGTERM', () => {
|
|
275
|
-
console.log('\n🛑 Shutting down...');
|
|
276
|
-
clearInterval(loadTestInterval);
|
|
277
|
-
clearInterval(statsInterval);
|
|
278
|
-
process.exit(0);
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
return client;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
initializeSingleGrpcClient().catch(console.error);
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
2
|
-
import dotenv from 'dotenv';
|
|
3
|
-
import {
|
|
4
|
-
AnchorProvider,
|
|
5
|
-
Idl,
|
|
6
|
-
Program,
|
|
7
|
-
ProgramAccount,
|
|
8
|
-
} from '@coral-xyz/anchor';
|
|
9
|
-
import velocityIDL from '../src/idl/velocity.json';
|
|
10
|
-
import {
|
|
11
|
-
VELOCITY_PROGRAM_ID,
|
|
12
|
-
PerpMarketAccount,
|
|
13
|
-
SpotMarketAccount,
|
|
14
|
-
OracleInfo,
|
|
15
|
-
Wallet,
|
|
16
|
-
ZERO,
|
|
17
|
-
} from '../src';
|
|
18
|
-
import { VelocityClient } from '../src/velocityClient';
|
|
19
|
-
import { VelocityClientConfig } from '../src/velocityClientConfig';
|
|
20
|
-
|
|
21
|
-
function isStatusOpen(status: any) {
|
|
22
|
-
return !!status && 'open' in status;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function isPerpMarketType(marketType: any) {
|
|
26
|
-
return !!marketType && 'perp' in marketType;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function main() {
|
|
30
|
-
dotenv.config({ path: '../' });
|
|
31
|
-
|
|
32
|
-
const RPC_ENDPOINT = process.env.RPC_ENDPOINT;
|
|
33
|
-
if (!RPC_ENDPOINT) throw new Error('RPC_ENDPOINT env var required');
|
|
34
|
-
|
|
35
|
-
// Load wallet
|
|
36
|
-
// For safety this creates a new ephemeral wallet unless PRIVATE_KEY is provided (base58 array)
|
|
37
|
-
let keypair: Keypair;
|
|
38
|
-
const pk = process.env.PRIVATE_KEY;
|
|
39
|
-
if (pk) {
|
|
40
|
-
const secret = Uint8Array.from(JSON.parse(pk));
|
|
41
|
-
keypair = Keypair.fromSecretKey(secret);
|
|
42
|
-
} else {
|
|
43
|
-
keypair = new Keypair();
|
|
44
|
-
console.warn(
|
|
45
|
-
'Using ephemeral keypair. Provide PRIVATE_KEY for real withdrawals.'
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
const wallet = new Wallet(keypair);
|
|
49
|
-
|
|
50
|
-
// Connection and program for market discovery
|
|
51
|
-
const connection = new Connection(RPC_ENDPOINT);
|
|
52
|
-
const provider = new AnchorProvider(connection, wallet as any, {
|
|
53
|
-
commitment: 'processed',
|
|
54
|
-
});
|
|
55
|
-
const programId = new PublicKey(VELOCITY_PROGRAM_ID);
|
|
56
|
-
const program = new Program(velocityIDL as Idl, programId, provider);
|
|
57
|
-
|
|
58
|
-
// Discover markets and oracles (like the example test script)
|
|
59
|
-
const allPerpMarketProgramAccounts =
|
|
60
|
-
(await program.account.perpMarket.all()) as ProgramAccount<PerpMarketAccount>[];
|
|
61
|
-
const perpMarketIndexes = allPerpMarketProgramAccounts.map(
|
|
62
|
-
(val) => val.account.marketIndex
|
|
63
|
-
);
|
|
64
|
-
const allSpotMarketProgramAccounts =
|
|
65
|
-
(await program.account.spotMarket.all()) as ProgramAccount<SpotMarketAccount>[];
|
|
66
|
-
const spotMarketIndexes = allSpotMarketProgramAccounts.map(
|
|
67
|
-
(val) => val.account.marketIndex
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
const seen = new Set<string>();
|
|
71
|
-
const oracleInfos: OracleInfo[] = [];
|
|
72
|
-
for (const acct of allPerpMarketProgramAccounts) {
|
|
73
|
-
const key = `${acct.account.amm.oracle.toBase58()}-${
|
|
74
|
-
Object.keys(acct.account.amm.oracleSource)[0]
|
|
75
|
-
}`;
|
|
76
|
-
if (!seen.has(key)) {
|
|
77
|
-
seen.add(key);
|
|
78
|
-
oracleInfos.push({
|
|
79
|
-
publicKey: acct.account.amm.oracle,
|
|
80
|
-
source: acct.account.amm.oracleSource,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
for (const acct of allSpotMarketProgramAccounts) {
|
|
85
|
-
const key = `${acct.account.oracle.toBase58()}-${
|
|
86
|
-
Object.keys(acct.account.oracleSource)[0]
|
|
87
|
-
}`;
|
|
88
|
-
if (!seen.has(key)) {
|
|
89
|
-
seen.add(key);
|
|
90
|
-
oracleInfos.push({
|
|
91
|
-
publicKey: acct.account.oracle,
|
|
92
|
-
source: acct.account.oracleSource,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Build VelocityClient with websocket subscription (lightweight)
|
|
98
|
-
const clientConfig: VelocityClientConfig = {
|
|
99
|
-
connection,
|
|
100
|
-
wallet,
|
|
101
|
-
programID: programId,
|
|
102
|
-
accountSubscription: {
|
|
103
|
-
type: 'websocket',
|
|
104
|
-
commitment: 'processed',
|
|
105
|
-
},
|
|
106
|
-
perpMarketIndexes,
|
|
107
|
-
spotMarketIndexes,
|
|
108
|
-
oracleInfos,
|
|
109
|
-
env: 'devnet',
|
|
110
|
-
};
|
|
111
|
-
const client = new VelocityClient(clientConfig);
|
|
112
|
-
await client.subscribe();
|
|
113
|
-
|
|
114
|
-
// Ensure user exists and is subscribed
|
|
115
|
-
const user = client.getUser();
|
|
116
|
-
await user.subscribe();
|
|
117
|
-
|
|
118
|
-
const userAccount = user.getUserAccount();
|
|
119
|
-
const openOrders = user.getOpenOrders();
|
|
120
|
-
|
|
121
|
-
const marketsWithOpenOrders = new Set<number>();
|
|
122
|
-
for (const o of openOrders ?? []) {
|
|
123
|
-
if (isStatusOpen(o.status) && isPerpMarketType(o.marketType)) {
|
|
124
|
-
marketsWithOpenOrders.add(o.marketIndex);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const withdrawTargets = userAccount.perpPositions.filter((pos) => {
|
|
129
|
-
const isZeroBase = pos.baseAssetAmount.eq(ZERO);
|
|
130
|
-
const hasIso = pos.isolatedPositionScaledBalance.gt(ZERO);
|
|
131
|
-
const hasOpenOrders = marketsWithOpenOrders.has(pos.marketIndex);
|
|
132
|
-
return isZeroBase && hasIso && !hasOpenOrders;
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
console.log(
|
|
136
|
-
`Found ${withdrawTargets.length} isolated perp positions to withdraw`
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
for (const pos of withdrawTargets) {
|
|
140
|
-
try {
|
|
141
|
-
const amount = client.getIsolatedPerpPositionTokenAmount(pos.marketIndex);
|
|
142
|
-
if (amount.lte(ZERO)) continue;
|
|
143
|
-
|
|
144
|
-
const perpMarketAccount = client.getPerpMarketAccount(pos.marketIndex);
|
|
145
|
-
const quoteAta = await client.getAssociatedTokenAccount(
|
|
146
|
-
perpMarketAccount.quoteSpotMarketIndex
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
const ixs = await client.getWithdrawFromIsolatedPerpPositionIxsBundle(
|
|
150
|
-
amount,
|
|
151
|
-
pos.marketIndex,
|
|
152
|
-
0,
|
|
153
|
-
quoteAta,
|
|
154
|
-
true
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
const tx = await client.buildTransaction(ixs);
|
|
158
|
-
const { txSig } = await client.sendTransaction(tx);
|
|
159
|
-
console.log(
|
|
160
|
-
`Withdrew isolated deposit for perp market ${pos.marketIndex}: ${txSig}`
|
|
161
|
-
);
|
|
162
|
-
} catch (e) {
|
|
163
|
-
console.error(`Failed to withdraw for market ${pos.marketIndex}:`, e);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
await user.unsubscribe();
|
|
168
|
-
await client.unsubscribe();
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
main().catch((e) => {
|
|
172
|
-
console.error(e);
|
|
173
|
-
process.exit(1);
|
|
174
|
-
});
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
# WebSocketAccountSubscriberV2
|
|
2
|
-
|
|
3
|
-
This is a new implementation of the WebSocket account subscriber that utilizes the [gill](https://www.npmjs.com/package/gill) library for improved RPC and WebSocket functionality.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The `WebSocketAccountSubscriberV2` class provides the same interface as the original `WebSocketAccountSubscriber` but uses gill's modern TypeScript client library for Solana blockchain interactions.
|
|
8
|
-
|
|
9
|
-
## Usage
|
|
10
|
-
|
|
11
|
-
The usage is identical to the original `WebSocketAccountSubscriber`:
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
import { WebSocketAccountSubscriberV2 } from './accounts/webSocketAccountSubscriberV2';
|
|
15
|
-
|
|
16
|
-
const subscriber = new WebSocketAccountSubscriberV2(
|
|
17
|
-
'userAccount', // account name
|
|
18
|
-
program, // Anchor program instance
|
|
19
|
-
userAccountPublicKey, // PublicKey of the account to subscribe to
|
|
20
|
-
decodeBuffer, // optional custom decode function
|
|
21
|
-
resubOpts, // optional resubscription options
|
|
22
|
-
commitment // optional commitment level
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
// Subscribe to account changes
|
|
26
|
-
await subscriber.subscribe((data) => {
|
|
27
|
-
console.log('Account updated:', data);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
// Unsubscribe when done
|
|
31
|
-
await subscriber.unsubscribe();
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Polling Instead of Resubscribing
|
|
35
|
-
|
|
36
|
-
For accounts that rarely update (like long-tail markets), you can use polling instead of resubscribing to reduce resource usage:
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
const resubOpts = {
|
|
40
|
-
resubTimeoutMs: 30000, // 30 seconds
|
|
41
|
-
logResubMessages: true,
|
|
42
|
-
usePollingInsteadOfResub: true, // Enable polling mode
|
|
43
|
-
pollingIntervalMs: 30000, // Poll every 30 seconds (optional, defaults to 30000)
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const subscriber = new WebSocketAccountSubscriberV2(
|
|
47
|
-
'perpMarket', // account name
|
|
48
|
-
program,
|
|
49
|
-
marketPublicKey,
|
|
50
|
-
undefined, // decodeBuffer
|
|
51
|
-
resubOpts
|
|
52
|
-
);
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
**How it works:**
|
|
56
|
-
1. Initially subscribes to WebSocket updates
|
|
57
|
-
2. If no WebSocket data is received for `resubTimeoutMs` (30s), switches to websocket+polling mode if `usePollingInsteadOfResub` is specified true, else just resubscribes(unsub, sub).
|
|
58
|
-
3. Polls every `pollingIntervalMs` (alongside websocket connection) to check for updates by:
|
|
59
|
-
- Storing current account buffer state
|
|
60
|
-
- Fetching latest account data
|
|
61
|
-
- Comparing buffers to detect any missed updates
|
|
62
|
-
4. If polling detects new data (indicating missed WebSocket events):
|
|
63
|
-
- Immediately stops polling
|
|
64
|
-
- Resubscribes to WebSocket to restore real-time updates
|
|
65
|
-
- This helps recover from degraded WebSocket connections
|
|
66
|
-
5. If a WebSocket event is received while polling:
|
|
67
|
-
- Polling is automatically stopped
|
|
68
|
-
- System continues with normal WebSocket updates
|
|
69
|
-
6. This approach provides:
|
|
70
|
-
- Efficient handling of rarely-updated accounts
|
|
71
|
-
- Automatic recovery from WebSocket connection issues
|
|
72
|
-
- Seamless fallback between polling and WebSocket modes
|
|
73
|
-
|
|
74
|
-
## Implementation Details
|
|
75
|
-
|
|
76
|
-
### Gill Integration
|
|
77
|
-
|
|
78
|
-
The implementation uses gill's `createSolanaClient` function to create RPC and WebSocket clients:
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
import { createSolanaClient } from 'gill';
|
|
82
|
-
|
|
83
|
-
const { rpc, rpcSubscriptions } = createSolanaClient({
|
|
84
|
-
urlOrMoniker: rpcUrl, // or "mainnet", "devnet", etc.
|
|
85
|
-
});
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Key Differences from Original
|
|
89
|
-
|
|
90
|
-
1. **RPC Client**: Uses gill's `rpc` client for account fetching
|
|
91
|
-
2. **WebSocket Subscriptions**: Uses gill's `rpcSubscriptions` for real-time updates
|
|
92
|
-
3. **Address Handling**: Converts `PublicKey` to gill's `Address` type for compatibility
|
|
93
|
-
4. **Response Formatting**: Converts gill responses to match the expected `AccountInfo<Buffer>` format
|
|
94
|
-
5. **Abort Signal**: Utilizes AbortSignal nodejs/web class to shutdown websocket connection synchronously
|
|
95
|
-
6. **Polling Mode**: Optional polling mechanism for accounts that rarely update
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# WebSocketProgramAccountSubscriberV2
|
|
2
|
-
|
|
3
|
-
This is a new implementation of the WebSocket program account subscriber that utilizes the [gill](https://www.npmjs.com/package/gill) library for improved RPC and WebSocket functionality, with additional smart polling logic for specific accounts.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The `WebSocketProgramAccountSubscriberV2` class provides the same interface as the original `WebSocketProgramAccountSubscriber` but uses gill's modern TypeScript client library for Solana blockchain interactions. Additionally, it implements smart polling logic for accounts that don't update frequently (like long-tail markets) to prevent missing updates.
|
|
8
|
-
|
|
9
|
-
## Key Features
|
|
10
|
-
|
|
11
|
-
1. **Gill Integration**: Uses gill's `createSolanaClient` for RPC and WebSocket functionality
|
|
12
|
-
2. **Smart Polling**: Optional polling for specific accounts that don't update frequently
|
|
13
|
-
3. **Missed Update Detection**: Automatically detects when updates are missed and resubscribes
|
|
14
|
-
4. **Configurable Polling**: 30-second default polling interval, customizable per instance
|
|
15
|
-
|
|
16
|
-
## Usage
|
|
17
|
-
|
|
18
|
-
The usage is similar to the original `WebSocketProgramAccountSubscriber` with additional options:
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
import { WebSocketProgramAccountSubscriberV2 } from './accounts/webSocketProgramAccountSubscriberV2';
|
|
22
|
-
|
|
23
|
-
// Create subscriber with optional accounts to poll
|
|
24
|
-
const subscriber = new WebSocketProgramAccountSubscriberV2(
|
|
25
|
-
'perpMarket', // account name
|
|
26
|
-
'perpMarket', // account discriminator
|
|
27
|
-
program, // Anchor program instance
|
|
28
|
-
decodeBuffer, // decode function
|
|
29
|
-
{ filters: [] }, // options
|
|
30
|
-
resubOpts, // optional resubscription options
|
|
31
|
-
[longTailMarket1, longTailMarket2] // optional list of accounts to poll
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
// Subscribe to program account changes
|
|
35
|
-
await subscriber.subscribe((accountId, data, context, buffer) => {
|
|
36
|
-
console.log('Account updated:', accountId.toBase58(), data);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// Add more accounts to poll dynamically
|
|
40
|
-
subscriber.addAccountToPoll(newMarketPublicKey);
|
|
41
|
-
|
|
42
|
-
// Remove accounts from polling
|
|
43
|
-
subscriber.removeAccountFromPoll(oldMarketPublicKey);
|
|
44
|
-
|
|
45
|
-
// Change polling interval
|
|
46
|
-
subscriber.setPollingInterval(60000); // 60 seconds
|
|
47
|
-
|
|
48
|
-
// Unsubscribe when done
|
|
49
|
-
await subscriber.unsubscribe();
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Implementation Details
|
|
53
|
-
|
|
54
|
-
### Gill Integration
|
|
55
|
-
|
|
56
|
-
The implementation uses gill's `createSolanaClient` function to create RPC and WebSocket clients:
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
import { createSolanaClient } from 'gill';
|
|
60
|
-
|
|
61
|
-
const { rpc, rpcSubscriptions } = createSolanaClient({
|
|
62
|
-
urlOrMoniker: rpcUrl, // or "mainnet", "devnet", etc.
|
|
63
|
-
});
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### Smart Polling Logic
|
|
67
|
-
|
|
68
|
-
1. **Account Selection**: Only accounts in the `accountsToMonitor` set are monitored
|
|
69
|
-
2. **Monitoring Period**: Default 30 seconds before starting to poll an account
|
|
70
|
-
3. **WebSocket Tracking**: Tracks the last WebSocket notification time for each account
|
|
71
|
-
4. **Conditional Polling**: Only starts polling if no WebSocket notification received in 30 seconds
|
|
72
|
-
5. **Batch Polling**: Uses `getMultipleAccounts` to poll all accounts in a single RPC call
|
|
73
|
-
6. **Dynamic Polling**: Stops polling individual accounts when WebSocket notifications are received
|
|
74
|
-
7. **Missed Update Detection**: Compares current slot and buffer with cached data
|
|
75
|
-
8. **Automatic Resubscription**: If a missed update is detected, the entire subscription is resubscribed
|
|
76
|
-
|
|
77
|
-
### Key Differences from Original
|
|
78
|
-
|
|
79
|
-
1. **RPC Client**: Uses gill's `rpc` client for account fetching
|
|
80
|
-
2. **WebSocket Subscriptions**: Uses gill's `rpcSubscriptions` for real-time updates
|
|
81
|
-
3. **Address Handling**: Converts `PublicKey` to gill's `Address` type for compatibility
|
|
82
|
-
4. **Response Formatting**: Converts gill responses to match the expected `AccountInfo<Buffer>` format
|
|
83
|
-
5. **Abort Signal**: Utilizes AbortSignal nodejs/web class to shutdown websocket connection synchronously
|
|
84
|
-
6. **Smart Polling**: Implements polling logic for specific accounts to prevent missed updates
|
|
85
|
-
|
|
86
|
-
## Configuration Options
|
|
87
|
-
|
|
88
|
-
### Constructor Parameters
|
|
89
|
-
|
|
90
|
-
- `subscriptionName`: Name for logging purposes
|
|
91
|
-
- `accountDiscriminator`: Account discriminator for decoding
|
|
92
|
-
- `program`: Anchor program instance
|
|
93
|
-
- `decodeBufferFn`: Function to decode account data
|
|
94
|
-
- `options`: Subscription options (filters, commitment)
|
|
95
|
-
- `resubOpts`: Resubscription options
|
|
96
|
-
- `accountsToPoll`: Optional array of PublicKeys to poll
|
|
97
|
-
|
|
98
|
-
### Polling Configuration
|
|
99
|
-
|
|
100
|
-
- **Default Monitoring Period**: 30 seconds before starting to poll
|
|
101
|
-
- **WebSocket Tracking**: Records timestamp of last WebSocket notification per account
|
|
102
|
-
- **Conditional Polling**: Only polls accounts that haven't received WebSocket updates recently
|
|
103
|
-
- **Batch Polling**: Uses `getMultipleAccounts` for efficient polling of multiple accounts
|
|
104
|
-
- **Dynamic Management**: Automatically starts/stops polling based on WebSocket activity
|
|
105
|
-
- **Detection Logic**: Compares slot numbers and buffer contents
|
|
106
|
-
- **Resubscription**: Triggers when missed updates are detected
|
|
107
|
-
- **Logging**: Optional logging of polling events
|
|
108
|
-
|
|
109
|
-
## Current Limitations
|
|
110
|
-
|
|
111
|
-
1. **Gill API Compatibility**: Some type mismatches exist with the current gill version
|
|
112
|
-
2. **Account Key Handling**: The account key extraction from gill notifications needs refinement
|
|
113
|
-
3. **Encoding Types**: Some encoding type comparisons need to be resolved
|
|
114
|
-
|
|
115
|
-
## Future Improvements
|
|
116
|
-
|
|
117
|
-
1. **Better Gill Integration**: Resolve remaining type compatibility issues
|
|
118
|
-
2. **Enhanced Logging**: More detailed logging for debugging
|
|
119
|
-
3. **Performance Optimization**: Optimize polling frequency based on account activity
|
|
120
|
-
4. **Batch Polling**: Poll multiple accounts in a single RPC call
|
|
121
|
-
|
|
122
|
-
## Migration from V1
|
|
123
|
-
|
|
124
|
-
The V2 implementation maintains the same interface as V1, making migration straightforward:
|
|
125
|
-
|
|
126
|
-
```typescript
|
|
127
|
-
// V1
|
|
128
|
-
const subscriber = new WebSocketProgramAccountSubscriber(...);
|
|
129
|
-
|
|
130
|
-
// V2 (same interface)
|
|
131
|
-
const subscriber = new WebSocketProgramAccountSubscriberV2(...);
|
|
132
|
-
|
|
133
|
-
// V2 with polling (new feature)
|
|
134
|
-
const subscriber = new WebSocketProgramAccountSubscriberV2(..., accountsToPoll);
|
|
135
|
-
```
|