Skip to content

Commit 9137745

Browse files
committed
refactor: use functional instead of procedural for getConfig
1 parent b03718e commit 9137745

File tree

1 file changed

+95
-85
lines changed

1 file changed

+95
-85
lines changed

governance/xc_admin/packages/xc_admin_common/src/programs/core/core_functions.ts

Lines changed: 95 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)