@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
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { grpcUserAccountSubscriber } from '../src/accounts/grpcUserAccountSubscriber';
|
|
2
|
-
import { grpcMultiUserAccountSubscriber } from '../src/accounts/grpcMultiUserAccountSubscriber';
|
|
3
|
-
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
4
|
-
import { VELOCITY_PROGRAM_ID } from '../src';
|
|
5
|
-
import { CommitmentLevel } from '@triton-one/yellowstone-grpc';
|
|
6
|
-
import { AnchorProvider, Idl, Program } from '@coral-xyz/anchor';
|
|
7
|
-
import velocityIDL from '../src/idl/velocity.json';
|
|
8
|
-
import assert from 'assert';
|
|
9
|
-
import { Wallet } from '../src';
|
|
10
|
-
|
|
11
|
-
const GRPC_ENDPOINT = process.env.GRPC_ENDPOINT;
|
|
12
|
-
const TOKEN = process.env.TOKEN;
|
|
13
|
-
const RPC_ENDPOINT = process.env.RPC_ENDPOINT;
|
|
14
|
-
|
|
15
|
-
const USER_ACCOUNT_PUBKEYS = [
|
|
16
|
-
// Add user account public keys here, e.g.:
|
|
17
|
-
// new PublicKey('...')
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
async function testGrpcUserAccountSubscriberV1VsV2() {
|
|
21
|
-
console.log('🚀 Initializing User Account Subscriber V1 vs V2 Test...');
|
|
22
|
-
|
|
23
|
-
if (USER_ACCOUNT_PUBKEYS.length === 0) {
|
|
24
|
-
console.error(
|
|
25
|
-
'❌ No user account public keys provided. Please add some to USER_ACCOUNT_PUBKEYS array.'
|
|
26
|
-
);
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const connection = new Connection(RPC_ENDPOINT);
|
|
31
|
-
const wallet = new Wallet(new Keypair());
|
|
32
|
-
|
|
33
|
-
const programId = new PublicKey(VELOCITY_PROGRAM_ID);
|
|
34
|
-
const provider = new AnchorProvider(
|
|
35
|
-
connection,
|
|
36
|
-
// @ts-ignore
|
|
37
|
-
wallet,
|
|
38
|
-
{
|
|
39
|
-
commitment: 'processed',
|
|
40
|
-
}
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
const program = new Program(velocityIDL as Idl, programId, provider);
|
|
44
|
-
|
|
45
|
-
const grpcConfigs = {
|
|
46
|
-
endpoint: GRPC_ENDPOINT,
|
|
47
|
-
token: TOKEN,
|
|
48
|
-
commitmentLevel: CommitmentLevel.PROCESSED,
|
|
49
|
-
channelOptions: {
|
|
50
|
-
grpcKeepAliveTimeout: 1_000,
|
|
51
|
-
grpcTcpKeepalive: 10_000,
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
console.log(`📊 Testing ${USER_ACCOUNT_PUBKEYS.length} user accounts...`);
|
|
56
|
-
|
|
57
|
-
// V1: Create individual subscribers for each user account
|
|
58
|
-
const v1Subscribers = USER_ACCOUNT_PUBKEYS.map(
|
|
59
|
-
(pubkey) =>
|
|
60
|
-
new grpcUserAccountSubscriber(grpcConfigs, program, pubkey, {
|
|
61
|
-
logResubMessages: true,
|
|
62
|
-
})
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// V2: Create a single multi-subscriber and get per-user interfaces
|
|
66
|
-
const v2MultiSubscriber = new grpcMultiUserAccountSubscriber(
|
|
67
|
-
program,
|
|
68
|
-
grpcConfigs,
|
|
69
|
-
{ logResubMessages: true }
|
|
70
|
-
);
|
|
71
|
-
const v2Subscribers = USER_ACCOUNT_PUBKEYS.map((pubkey) =>
|
|
72
|
-
v2MultiSubscriber.forUser(pubkey)
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
// Subscribe all V1 subscribers
|
|
76
|
-
console.log('🔗 Subscribing V1 subscribers...');
|
|
77
|
-
await Promise.all(v1Subscribers.map((sub) => sub.subscribe()));
|
|
78
|
-
console.log('✅ V1 subscribers ready');
|
|
79
|
-
|
|
80
|
-
// Subscribe all V2 subscribers
|
|
81
|
-
console.log('🔗 Subscribing V2 subscribers...');
|
|
82
|
-
await v2MultiSubscriber.subscribe();
|
|
83
|
-
console.log('✅ V2 subscribers ready');
|
|
84
|
-
|
|
85
|
-
const compare = () => {
|
|
86
|
-
try {
|
|
87
|
-
let passedTests = 0;
|
|
88
|
-
let totalTests = 0;
|
|
89
|
-
|
|
90
|
-
// Test each user account
|
|
91
|
-
for (let i = 0; i < USER_ACCOUNT_PUBKEYS.length; i++) {
|
|
92
|
-
const pubkey = USER_ACCOUNT_PUBKEYS[i];
|
|
93
|
-
const v1Sub = v1Subscribers[i];
|
|
94
|
-
const v2Sub = v2Subscribers[i];
|
|
95
|
-
|
|
96
|
-
totalTests++;
|
|
97
|
-
|
|
98
|
-
// 1. Test isSubscribed
|
|
99
|
-
assert.strictEqual(
|
|
100
|
-
v1Sub.isSubscribed,
|
|
101
|
-
v2Sub.isSubscribed,
|
|
102
|
-
`User ${pubkey.toBase58()}: isSubscribed should match`
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
// 2. Test getUserAccountAndSlot
|
|
106
|
-
const v1Data = v1Sub.getUserAccountAndSlot();
|
|
107
|
-
const v2Data = v2Sub.getUserAccountAndSlot();
|
|
108
|
-
|
|
109
|
-
// Compare the user account data
|
|
110
|
-
assert.deepStrictEqual(
|
|
111
|
-
v1Data.data,
|
|
112
|
-
v2Data.data,
|
|
113
|
-
`User ${pubkey.toBase58()}: account data should match`
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
// Slots might differ slightly due to timing, but let's check if they're close
|
|
117
|
-
const slotDiff = Math.abs(v1Data.slot - v2Data.slot);
|
|
118
|
-
if (slotDiff > 10) {
|
|
119
|
-
console.warn(
|
|
120
|
-
`⚠️ User ${pubkey.toBase58()}: slot difference is ${slotDiff} (v1: ${
|
|
121
|
-
v1Data.slot
|
|
122
|
-
}, v2: ${v2Data.slot})`
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
passedTests++;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
console.log(
|
|
130
|
-
`✅ All comparisons passed (${passedTests}/${totalTests} user accounts)`
|
|
131
|
-
);
|
|
132
|
-
} catch (error) {
|
|
133
|
-
console.error('❌ Comparison failed:', error);
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
// Run initial comparison
|
|
138
|
-
compare();
|
|
139
|
-
|
|
140
|
-
// Run comparison every second to verify live updates
|
|
141
|
-
const interval = setInterval(compare, 1000);
|
|
142
|
-
|
|
143
|
-
const cleanup = async () => {
|
|
144
|
-
clearInterval(interval);
|
|
145
|
-
console.log('🧹 Cleaning up...');
|
|
146
|
-
await Promise.all([
|
|
147
|
-
...v1Subscribers.map((sub) => sub.unsubscribe()),
|
|
148
|
-
...v2Subscribers.map((sub) => sub.unsubscribe()),
|
|
149
|
-
]);
|
|
150
|
-
console.log('✅ Cleanup complete');
|
|
151
|
-
process.exit(0);
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
process.on('SIGINT', cleanup);
|
|
155
|
-
process.on('SIGTERM', cleanup);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
testGrpcUserAccountSubscriberV1VsV2().catch(console.error);
|
package/scripts/postbuild.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// scripts/postbuild.js
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const yargs = require('yargs/yargs');
|
|
5
|
-
const { hideBin } = require('yargs/helpers');
|
|
6
|
-
|
|
7
|
-
const forceEnv = yargs(hideBin(process.argv))
|
|
8
|
-
.option('force-env', {
|
|
9
|
-
type: 'string',
|
|
10
|
-
description: 'Specify environment to force (node or browser)',
|
|
11
|
-
choices: ['node', 'browser']
|
|
12
|
-
})
|
|
13
|
-
.argv?.forceEnv;
|
|
14
|
-
|
|
15
|
-
const isomorphicPackages = ['grpc', 'anchor', 'anchor29'];
|
|
16
|
-
const environments = ['node', 'browser'];
|
|
17
|
-
|
|
18
|
-
environments.forEach((environment) => {
|
|
19
|
-
console.log(`Running ${environment} environment postbuild script`);
|
|
20
|
-
console.log(``);
|
|
21
|
-
|
|
22
|
-
isomorphicPackages.forEach((package) => {
|
|
23
|
-
|
|
24
|
-
// We want to overwrite the base isomorphic files (the "target" files) with the concrete implementation code and definition files (the "source" files).
|
|
25
|
-
|
|
26
|
-
const isomorphicFolderPath = path.join(
|
|
27
|
-
__dirname,
|
|
28
|
-
'..',
|
|
29
|
-
'lib',
|
|
30
|
-
environment,
|
|
31
|
-
'isomorphic'
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
const targetEnv = forceEnv ? forceEnv : environment;
|
|
35
|
-
|
|
36
|
-
const filesToSwap = [
|
|
37
|
-
{
|
|
38
|
-
source: `${package}.${targetEnv}.js`,
|
|
39
|
-
target: `${package}.js`,
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
source: `${package}.${targetEnv}.d.ts`,
|
|
43
|
-
target: `${package}.d.ts`,
|
|
44
|
-
},
|
|
45
|
-
];
|
|
46
|
-
|
|
47
|
-
for (const file of filesToSwap) {
|
|
48
|
-
const sourcePath = path.join(
|
|
49
|
-
isomorphicFolderPath,
|
|
50
|
-
file.source
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
const targetPath = path.join(
|
|
54
|
-
isomorphicFolderPath,
|
|
55
|
-
file.target
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
const sourceContent = fs.readFileSync(sourcePath, 'utf8');
|
|
60
|
-
fs.writeFileSync(targetPath, sourceContent);
|
|
61
|
-
} catch (error) {
|
|
62
|
-
console.error(
|
|
63
|
-
`Error processing isomophic package : ${package} :: ${error.message}`
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Delete other environment files for safety
|
|
69
|
-
environments.forEach((otherEnvironment) => {
|
|
70
|
-
if (otherEnvironment === targetEnv) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const otherTargetFiles = [
|
|
75
|
-
`${package}.${otherEnvironment}.js`,
|
|
76
|
-
`${package}.${otherEnvironment}.d.ts`,
|
|
77
|
-
];
|
|
78
|
-
|
|
79
|
-
for (const otherTargetFile of otherTargetFiles) {
|
|
80
|
-
const otherTargetPath = path.join(
|
|
81
|
-
__dirname,
|
|
82
|
-
'..',
|
|
83
|
-
'lib',
|
|
84
|
-
environment,
|
|
85
|
-
'isomorphic',
|
|
86
|
-
otherTargetFile
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
if (fs.existsSync(otherTargetPath)) {
|
|
90
|
-
fs.unlinkSync(otherTargetPath);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
});
|
|
@@ -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
|
-
});
|