@@ -130,101 +130,111 @@ export function getConfig(params: GetConfigParams): RawConfig {
130
130
if ( params . programType !== ProgramType . PYTH_CORE ) {
131
131
throw new Error ( "Invalid program type for Core getConfig" ) ;
132
132
}
133
+
133
134
const accounts = params . accounts ;
134
- const priceRawConfigs : { [ key : string ] : PriceRawConfig } = { } ;
135
- const rawConfig : RawConfig = { mappingAccounts : [ ] } ;
136
135
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 [ ] = [ ] ;
164
169
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
173
171
if ( parsed . priceAccountKey ) {
174
172
let priceAccountKey : string | undefined =
175
173
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 ;
182
188
}
183
- productRawConfigs [ allPythAccounts [ i ] . pubkey . toBase58 ( ) ] = {
189
+ }
190
+
191
+ return [
192
+ account . pubkey . toBase58 ( ) ,
193
+ {
184
194
priceAccounts,
185
195
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
+ ) ;
196
201
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
+ ) ;
228
238
}
229
239
230
240
return rawConfig ;
0 commit comments