11import { DriftClient } from '../src/driftClient' ;
22import { grpcDriftClientAccountSubscriberV2 } from '../src/accounts/grpcDriftClientAccountSubscriberV2' ;
3+ import { grpcDriftClientAccountSubscriber } from '../src/accounts/grpcDriftClientAccountSubscriber' ;
34import { Connection , Keypair , PublicKey } from '@solana/web3.js' ;
45import { DriftClientConfig } from '../src/driftClientConfig' ;
56import {
6- decodeName ,
77 DRIFT_PROGRAM_ID ,
88 PerpMarketAccount ,
9+ SpotMarketAccount ,
910 Wallet ,
11+ OracleInfo ,
1012} from '../src' ;
1113import { CommitmentLevel } from '@triton-one/yellowstone-grpc' ;
1214import dotenv from 'dotenv' ;
@@ -21,8 +23,8 @@ import driftIDL from '../src/idl/drift.json';
2123const GRPC_ENDPOINT = process . env . GRPC_ENDPOINT ;
2224const TOKEN = process . env . TOKEN ;
2325
24- async function initializeGrpcDriftClientV2 ( ) {
25- const connection = new Connection ( 'https://api.mainnet-beta.solana.com ' ) ;
26+ async function initializeGrpcDriftClientV2VersusV1 ( ) {
27+ const connection = new Connection ( '' ) ;
2628 const wallet = new Wallet ( new Keypair ( ) ) ;
2729 dotenv . config ( { path : '../' } ) ;
2830
@@ -38,177 +40,136 @@ async function initializeGrpcDriftClientV2() {
3840
3941 const program = new Program ( driftIDL as Idl , programId , provider ) ;
4042
41- const perpMarketProgramAccounts =
42- ( await program . account . perpMarket . all ( ) ) as ProgramAccount < PerpMarketAccount > [ ] ;
43- const solPerpMarket = perpMarketProgramAccounts . find (
44- ( account ) => account . account . marketIndex === 0
45- ) ;
46- const solOracleInfo = {
47- publicKey : solPerpMarket . account . amm . oracle ,
48- source : solPerpMarket . account . amm . oracleSource ,
49- } ;
50- const ethPerpMarket = perpMarketProgramAccounts . find (
51- ( account ) => account . account . marketIndex === 2
52- ) ;
53- const ethOracleInfo = {
54- publicKey : ethPerpMarket . account . amm . oracle ,
55- source : ethPerpMarket . account . amm . oracleSource ,
56- } ;
57- const btcPerpMarket = perpMarketProgramAccounts . find (
58- ( account ) => account . account . marketIndex === 1
59- ) ;
60- const btcOracleInfo = {
61- publicKey : btcPerpMarket . account . amm . oracle ,
62- source : btcPerpMarket . account . amm . oracleSource ,
43+ const perpMarketIndexes = [ 4 ] ;
44+ const spotMarketIndexes = [ 32 ] ;
45+
46+ const perpMarketProgramAccounts = (
47+ await program . account . perpMarket . all ( )
48+ ) . filter ( ( a ) =>
49+ perpMarketIndexes . includes ( a . account . marketIndex as number )
50+ ) as ProgramAccount < PerpMarketAccount > [ ] ;
51+ const spotMarketProgramAccounts = (
52+ await program . account . spotMarket . all ( )
53+ ) . filter ( ( a ) =>
54+ spotMarketIndexes . includes ( a . account . marketIndex as number )
55+ ) as ProgramAccount < SpotMarketAccount > [ ] ;
56+
57+ // const perpMarketIndexes = perpMarketProgramAccounts.map(
58+ // (a) => a.account.marketIndex
59+ // );
60+ // const spotMarketIndexes = spotMarketProgramAccounts.map(
61+ // (a) => a.account.marketIndex
62+ // );
63+ // const oracleInfos = [
64+ // {
65+ // publicKey: new PublicKey('BERaNi6cpEresbq6HC1EQGaB1H1UjvEo4NGnmYSSJof4'),
66+ // source: OracleSource.PYTH_LAZER,
67+ // },
68+ // {
69+ // publicKey: new PublicKey('BERaNi6cpEresbq6HC1EQGaB1H1UjvEo4NGnmYSSJof4'),
70+ // source: OracleSource.PYTH_LAZER_1M,
71+ // },
72+ // ];
73+
74+ const seen = new Set < string > ( ) ;
75+ const oracleInfos : OracleInfo [ ] = [ ] ;
76+ for ( const acct of perpMarketProgramAccounts ) {
77+ const key = `${ acct . account . amm . oracle . toBase58 ( ) } -${ Object . keys (
78+ acct . account . amm . oracleSource ?? { }
79+ ) ?. [ 0 ] } `;
80+ if ( ! seen . has ( key ) ) {
81+ seen . add ( key ) ;
82+ oracleInfos . push ( {
83+ publicKey : acct . account . amm . oracle ,
84+ source : acct . account . amm . oracleSource ,
85+ } ) ;
86+ }
87+ }
88+ for ( const acct of spotMarketProgramAccounts ) {
89+ const key = `${ acct . account . oracle . toBase58 ( ) } -${ Object . keys (
90+ acct . account . oracleSource ?? { }
91+ ) ?. [ 0 ] } `;
92+ if ( ! seen . has ( key ) ) {
93+ seen . add ( key ) ;
94+ oracleInfos . push ( {
95+ publicKey : acct . account . oracle ,
96+ source : acct . account . oracleSource ,
97+ } ) ;
98+ }
99+ }
100+
101+ const baseAccountSubscription = {
102+ type : 'grpc' as const ,
103+ grpcConfigs : {
104+ endpoint : GRPC_ENDPOINT ,
105+ token : TOKEN ,
106+ commitmentLevel : 'confirmed' as unknown as CommitmentLevel ,
107+ channelOptions : {
108+ 'grpc.keepalive_time_ms' : 10_000 ,
109+ 'grpc.keepalive_timeout_ms' : 1_000 ,
110+ 'grpc.keepalive_permit_without_calls' : 1 ,
111+ } ,
112+ } ,
63113 } ;
64114
65- const config : DriftClientConfig = {
115+ const configV2 : DriftClientConfig = {
66116 connection,
67117 wallet,
68118 programID : new PublicKey ( DRIFT_PROGRAM_ID ) ,
69119 accountSubscription : {
70- type : 'grpc' ,
71- grpcConfigs : {
72- endpoint : GRPC_ENDPOINT ,
73- token : TOKEN ,
74- commitmentLevel : 'confirmed' as unknown as CommitmentLevel ,
75- channelOptions : {
76- 'grpc.keepalive_time_ms' : 10_000 ,
77- 'grpc.keepalive_timeout_ms' : 1_000 ,
78- 'grpc.keepalive_permit_without_calls' : 1 ,
79- } ,
80- } ,
120+ ...baseAccountSubscription ,
81121 driftClientAccountSubscriber : grpcDriftClientAccountSubscriberV2 ,
82122 } ,
83- perpMarketIndexes : [ 0 , 1 , 2 ] ,
84- spotMarketIndexes : [ 0 , 1 , 2 ] ,
85- oracleInfos : [ solOracleInfo , ethOracleInfo , btcOracleInfo ] ,
123+ perpMarketIndexes,
124+ spotMarketIndexes,
125+ oracleInfos,
86126 } ;
87127
88- const driftClient = new DriftClient ( config ) ;
89-
90- let perpMarketUpdateCount = 0 ;
91- let spotMarketUpdateCount = 0 ;
92- let oraclePriceUpdateCount = 0 ;
93- let userAccountUpdateCount = 0 ;
94-
95- const updatePromise = new Promise < void > ( ( resolve ) => {
96- driftClient . accountSubscriber . eventEmitter . on (
97- 'perpMarketAccountUpdate' ,
98- ( data ) => {
99- console . log (
100- 'Perp market account update:' ,
101- decodeName ( data . name ) ,
102- 'mmOracleSequenceId:' ,
103- data . amm . mmOracleSequenceId . toString ( )
104- ) ;
105- // const perpMarketData = driftClient.getPerpMarketAccount(
106- // data.marketIndex
107- // );
108- // console.log(
109- // 'Perp market data market index:',
110- // perpMarketData?.marketIndex
111- // );
112- // const oracle = driftClient.getOracleDataForPerpMarket(data.marketIndex);
113- // const mmOracle = driftClient.getMMOracleDataForPerpMarket(
114- // data.marketIndex
115- // );
116- // console.log('Perp oracle price:', oracle.price.toString());
117- // console.log('Perp MM oracle price:', mmOracle.price.toString());
118- // console.log(
119- // 'Perp MM oracle sequence id:',
120- // perpMarketData?.amm?.mmOracleSequenceId?.toString()
121- // );
122- perpMarketUpdateCount ++ ;
123- if (
124- perpMarketUpdateCount >= 10 &&
125- spotMarketUpdateCount >= 10 &&
126- oraclePriceUpdateCount >= 10 &&
127- userAccountUpdateCount >= 2
128- ) {
129- resolve ( ) ;
130- }
131- }
132- ) ;
133-
134- driftClient . accountSubscriber . eventEmitter . on (
135- 'spotMarketAccountUpdate' ,
136- ( data ) => {
137- console . log ( 'Spot market account update:' , decodeName ( data . name ) ) ;
138- const spotMarketData = driftClient . getSpotMarketAccount (
139- data . marketIndex
140- ) ;
141- console . log (
142- 'Spot market data market index:' ,
143- spotMarketData ?. marketIndex
144- ) ;
145- const oracle = driftClient . getOracleDataForSpotMarket ( data . marketIndex ) ;
146- console . log ( 'Spot oracle price:' , oracle . price . toString ( ) ) ;
147- spotMarketUpdateCount ++ ;
148- if (
149- perpMarketUpdateCount >= 10 &&
150- spotMarketUpdateCount >= 10 &&
151- oraclePriceUpdateCount >= 10 &&
152- userAccountUpdateCount >= 2
153- ) {
154- resolve ( ) ;
155- }
156- }
157- ) ;
158-
159- driftClient . accountSubscriber . eventEmitter . on (
160- 'oraclePriceUpdate' ,
161- ( data ) => {
162- console . log ( 'Oracle price update:' , data . toBase58 ( ) ) ;
163- oraclePriceUpdateCount ++ ;
164- if (
165- perpMarketUpdateCount >= 10 &&
166- spotMarketUpdateCount >= 10 &&
167- oraclePriceUpdateCount >= 10 &&
168- userAccountUpdateCount >= 2
169- ) {
170- resolve ( ) ;
171- }
172- }
173- ) ;
174-
175- driftClient . accountSubscriber . eventEmitter . on (
176- 'userAccountUpdate' ,
177- ( data ) => {
178- console . log ( 'User account update:' , decodeName ( data . name ) ) ;
179- userAccountUpdateCount ++ ;
180- if (
181- perpMarketUpdateCount >= 10 &&
182- spotMarketUpdateCount >= 10 &&
183- oraclePriceUpdateCount >= 10 &&
184- userAccountUpdateCount >= 2
185- ) {
186- resolve ( ) ;
187- }
188- }
189- ) ;
190- } ) ;
191-
192- await driftClient . subscribe ( ) ;
193- console . log ( 'DriftClient initialized and listening for updates.' ) ;
194-
195- for ( const marketIndex of config . perpMarketIndexes ) {
196- const oracle = driftClient . getOracleDataForPerpMarket ( marketIndex ) ;
197- const mmOracle = driftClient . getMMOracleDataForPerpMarket ( marketIndex ) ;
198- console . log ( 'Initial perp oracle price:' , oracle . price . toString ( ) ) ;
199- console . log ( 'Initial perp MM oracle price:' , mmOracle . price . toString ( ) ) ;
200- }
128+ const configV1 : DriftClientConfig = {
129+ connection,
130+ wallet,
131+ programID : new PublicKey ( DRIFT_PROGRAM_ID ) ,
132+ accountSubscription : {
133+ ...baseAccountSubscription ,
134+ driftClientAccountSubscriber : grpcDriftClientAccountSubscriber ,
135+ } ,
136+ perpMarketIndexes,
137+ spotMarketIndexes,
138+ oracleInfos,
139+ } ;
201140
202- for ( const marketIndex of config . spotMarketIndexes ) {
203- const oracle = driftClient . getOracleDataForSpotMarket ( marketIndex ) ;
204- console . log ( 'Initial spot oracle price:' , oracle . price . toString ( ) ) ;
205- }
141+ const clientV2 = new DriftClient ( configV2 ) ;
142+ const clientV1 = new DriftClient ( configV1 ) ;
143+
144+ await Promise . all ( [ clientV1 . subscribe ( ) , clientV2 . subscribe ( ) ] ) ;
145+ const compare = ( ) => {
146+ for ( const idx of perpMarketIndexes ) {
147+ const p1 = clientV1 . getOracleDataForPerpMarket ( idx ) . price ;
148+ const p2 = clientV2 . getOracleDataForPerpMarket ( idx ) . price ;
149+ console . log (
150+ `perp mkt ${ idx } | v1 ${ p1 . toString ( ) } | v2 ${ p2 . toString ( ) } `
151+ ) ;
152+ }
153+ for ( const idx of spotMarketIndexes ) {
154+ const s1 = clientV1 . getOracleDataForSpotMarket ( idx ) . price ;
155+ const s2 = clientV2 . getOracleDataForSpotMarket ( idx ) . price ;
156+ console . log (
157+ `spot mkt ${ idx } | v1 ${ s1 . toString ( ) } | v2 ${ s2 . toString ( ) } `
158+ ) ;
159+ }
160+ } ;
161+
162+ compare ( ) ;
163+ const interval = setInterval ( compare , 1000 ) ;
206164
207- const stateAccount = driftClient . getStateAccount ( ) ;
208- console . log ( 'Initial state account:' , stateAccount . toString ( ) ) ;
165+ const cleanup = async ( ) => {
166+ clearInterval ( interval ) ;
167+ await Promise . all ( [ clientV1 . unsubscribe ( ) , clientV2 . unsubscribe ( ) ] ) ;
168+ process . exit ( 0 ) ;
169+ } ;
209170
210- await updatePromise ;
211- console . log ( 'Received required number of updates.' ) ;
171+ process . on ( 'SIGINT' , cleanup ) ;
172+ process . on ( 'SIGTERM' , cleanup ) ;
212173}
213174
214- initializeGrpcDriftClientV2 ( ) . catch ( console . error ) ;
175+ initializeGrpcDriftClientV2VersusV1 ( ) . catch ( console . error ) ;
0 commit comments