@@ -130,101 +130,111 @@ export function getConfig(params: GetConfigParams): RawConfig {
130130 if ( params . programType !== ProgramType . PYTH_CORE ) {
131131 throw new Error ( "Invalid program type for Core getConfig" ) ;
132132 }
133+
133134 const accounts = params . accounts ;
134- const priceRawConfigs : { [ key : string ] : PriceRawConfig } = { } ;
135- const rawConfig : RawConfig = { mappingAccounts : [ ] } ;
136135
137- // Make a copy of the accounts array to modify
138- const allPythAccounts = [ ...accounts ] ;
139-
140- /// First pass, price accounts
141- let i = 0 ;
142- while ( i < allPythAccounts . length ) {
143- const base = parseBaseData ( allPythAccounts [ i ] . account . data ) ;
144- switch ( base ?. type ) {
145- case AccountType . Price :
146- const parsed = parsePriceData ( allPythAccounts [ i ] . account . data ) ;
147- priceRawConfigs [ allPythAccounts [ i ] . pubkey . toBase58 ( ) ] = {
148- next : parsed . nextPriceAccountKey ,
149- address : allPythAccounts [ i ] . pubkey ,
150- publishers : parsed . priceComponents . map ( ( x ) => {
151- return x . publisher ! ;
152- } ) ,
153- expo : parsed . exponent ,
154- minPub : parsed . minPublishers ,
155- maxLatency : parsed . maxLatency ,
156- } ;
157- allPythAccounts [ i ] = allPythAccounts [ allPythAccounts . length - 1 ] ;
158- allPythAccounts . pop ( ) ;
159- break ;
160- default :
161- i += 1 ;
162- }
163- }
136+ // First pass: Extract price accounts
137+ const priceRawConfigs = Object . fromEntries (
138+ accounts
139+ . filter (
140+ ( account ) =>
141+ parseBaseData ( account . account . data ) ?. type === AccountType . Price ,
142+ )
143+ . map ( ( account ) => {
144+ const parsed = parsePriceData ( account . account . data ) ;
145+ return [
146+ account . pubkey . toBase58 ( ) ,
147+ {
148+ next : parsed . nextPriceAccountKey ,
149+ address : account . pubkey ,
150+ publishers : parsed . priceComponents . map ( ( x ) => x . publisher ! ) ,
151+ expo : parsed . exponent ,
152+ minPub : parsed . minPublishers ,
153+ maxLatency : parsed . maxLatency ,
154+ } ,
155+ ] ;
156+ } ) ,
157+ ) ;
158+
159+ // Second pass: Extract product accounts and link to price accounts
160+ const productRawConfigs = Object . fromEntries (
161+ accounts
162+ . filter (
163+ ( account ) =>
164+ parseBaseData ( account . account . data ) ?. type === AccountType . Product ,
165+ )
166+ . map ( ( account ) => {
167+ const parsed = parseProductData ( account . account . data ) ;
168+ const priceAccounts : PriceRawConfig [ ] = [ ] ;
164169
165- /// Second pass, product accounts
166- i = 0 ;
167- const productRawConfigs : { [ key : string ] : ProductRawConfig } = { } ;
168- while ( i < allPythAccounts . length ) {
169- const base = parseBaseData ( allPythAccounts [ i ] . account . data ) ;
170- switch ( base ?. type ) {
171- case AccountType . Product :
172- const parsed = parseProductData ( allPythAccounts [ i ] . account . data ) ;
170+ // Follow the linked list of price accounts
173171 if ( parsed . priceAccountKey ) {
174172 let priceAccountKey : string | undefined =
175173 parsed . priceAccountKey . toBase58 ( ) ;
176- const priceAccounts = [ ] ;
177- while ( priceAccountKey ) {
178- const toAdd : PriceRawConfig = priceRawConfigs [ priceAccountKey ] ;
179- priceAccounts . push ( toAdd ) ;
180- delete priceRawConfigs [ priceAccountKey ] ;
181- priceAccountKey = toAdd . next ? toAdd . next . toBase58 ( ) : undefined ;
174+ const processedPriceKeys = new Set < string > ( ) ;
175+
176+ while (
177+ priceAccountKey &&
178+ ! processedPriceKeys . has ( priceAccountKey ) &&
179+ priceRawConfigs [ priceAccountKey ]
180+ ) {
181+ processedPriceKeys . add ( priceAccountKey ) ;
182+ const priceConfig : PriceRawConfig =
183+ priceRawConfigs [ priceAccountKey ] ;
184+ priceAccounts . push ( priceConfig ) ;
185+ priceAccountKey = priceConfig . next
186+ ? priceConfig . next . toBase58 ( )
187+ : undefined ;
182188 }
183- productRawConfigs [ allPythAccounts [ i ] . pubkey . toBase58 ( ) ] = {
189+ }
190+
191+ return [
192+ account . pubkey . toBase58 ( ) ,
193+ {
184194 priceAccounts,
185195 metadata : parsed . product ,
186- address : allPythAccounts [ i ] . pubkey ,
187- } ;
188- }
189- allPythAccounts [ i ] = allPythAccounts [ allPythAccounts . length - 1 ] ;
190- allPythAccounts . pop ( ) ;
191- break ;
192- default :
193- i += 1 ;
194- }
195- }
196+ address : account . pubkey ,
197+ } ,
198+ ] ;
199+ } ) ,
200+ ) ;
196201
197- /// Third pass, mapping accounts
198- i = 0 ;
199- while ( i < allPythAccounts . length ) {
200- const base = parseBaseData ( allPythAccounts [ i ] . account . data ) ;
201- switch ( base ?. type ) {
202- case AccountType . Mapping :
203- const parsed = parseMappingData ( allPythAccounts [ i ] . account . data ) ;
204- rawConfig . mappingAccounts . push ( {
205- next : parsed . nextMappingAccount ,
206- address : allPythAccounts [ i ] . pubkey ,
207- products : parsed . productAccountKeys
208- . filter ( ( key ) => productRawConfigs [ key . toBase58 ( ) ] )
209- . map ( ( key ) => {
210- const toAdd = productRawConfigs [ key . toBase58 ( ) ] ;
211- delete productRawConfigs [ key . toBase58 ( ) ] ;
212- return toAdd ;
213- } ) ,
214- } ) ;
215- allPythAccounts [ i ] = allPythAccounts [ allPythAccounts . length - 1 ] ;
216- allPythAccounts . pop ( ) ;
217- break ;
218- case AccountType . Permission :
219- rawConfig . permissionAccount = parsePermissionData (
220- allPythAccounts [ i ] . account . data ,
221- ) ;
222- allPythAccounts [ i ] = allPythAccounts [ allPythAccounts . length - 1 ] ;
223- allPythAccounts . pop ( ) ;
224- break ;
225- default :
226- i += 1 ;
227- }
202+ // Third pass: Extract mapping accounts and permission data
203+ const rawConfig : RawConfig = { mappingAccounts : [ ] } ;
204+
205+ // Process mapping accounts
206+ const mappingAccounts = accounts
207+ . filter (
208+ ( account ) =>
209+ parseBaseData ( account . account . data ) ?. type === AccountType . Mapping ,
210+ )
211+ . map ( ( account ) => {
212+ const parsed = parseMappingData ( account . account . data ) ;
213+ return {
214+ next : parsed . nextMappingAccount ,
215+ address : account . pubkey ,
216+ products : parsed . productAccountKeys
217+ . filter ( ( key ) => productRawConfigs [ key . toBase58 ( ) ] )
218+ . map ( ( key ) => {
219+ const product = productRawConfigs [ key . toBase58 ( ) ] ;
220+ delete productRawConfigs [ key . toBase58 ( ) ] ;
221+ return product ;
222+ } ) ,
223+ } ;
224+ } ) ;
225+
226+ rawConfig . mappingAccounts = mappingAccounts ;
227+
228+ // Find permission account if it exists
229+ const permissionAccount = accounts . find (
230+ ( account ) =>
231+ parseBaseData ( account . account . data ) ?. type === AccountType . Permission ,
232+ ) ;
233+
234+ if ( permissionAccount ) {
235+ rawConfig . permissionAccount = parsePermissionData (
236+ permissionAccount . account . data ,
237+ ) ;
228238 }
229239
230240 return rawConfig ;
0 commit comments