Skip to content

Commit 2b4fe27

Browse files
authored
Reinforce coinGecko ID validation logic in validate.ts (#1329)
1 parent 9030ded commit 2b4fe27

File tree

1 file changed

+100
-39
lines changed

1 file changed

+100
-39
lines changed

src/validate.ts

Lines changed: 100 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -120,28 +120,12 @@ export const validateCosmosChainInfo = async (
120120
await checkRestConnectivity(chainInfo.chainId, chainInfo.rest);
121121
}
122122

123-
// check coinGecko vaild
124-
const coinGeckoIds = new Set<string>();
125-
for (const currency of chainInfo.currencies) {
126-
if (currency.coinGeckoId) {
127-
coinGeckoIds.add(currency.coinGeckoId);
128-
}
129-
}
130-
131-
for (const currency of chainInfo.feeCurrencies) {
132-
if (currency.coinGeckoId) {
133-
coinGeckoIds.add(currency.coinGeckoId);
134-
}
135-
}
136-
137-
if (chainInfo.stakeCurrency?.coinGeckoId) {
138-
coinGeckoIds.add(chainInfo.stakeCurrency.coinGeckoId);
139-
}
140-
141-
await checkCoinGeckoIds(...Array.from(coinGeckoIds));
142-
143123
checkIsTestnet(chainInfo);
144124

125+
validateCoinGeckoIds(chainInfo); // check coinGeckoId inputs vaild
126+
const coinGeckoIds = collectCoinGeckoIds(chainInfo);
127+
await checkCoinGeckoIdsAvailable(...Array.from(coinGeckoIds)); // check coinGeckoIds available in Coin Gecko
128+
145129
return chainInfo;
146130
};
147131

@@ -240,25 +224,11 @@ export const validateEvmChainInfo = async (
240224

241225
await checkEvmRpcConnectivity(chainInfo.evm.chainId, chainInfo.rpc);
242226

243-
// check coinGecko vaild
244-
const coinGeckoIds = new Set<string>();
245-
for (const currency of chainInfo.currencies) {
246-
if (currency.coinGeckoId) {
247-
coinGeckoIds.add(currency.coinGeckoId);
248-
}
249-
}
250-
251-
for (const currency of chainInfo.feeCurrencies) {
252-
if (currency.coinGeckoId) {
253-
coinGeckoIds.add(currency.coinGeckoId);
254-
}
255-
}
256-
257-
if (chainInfo.stakeCurrency?.coinGeckoId) {
258-
coinGeckoIds.add(chainInfo.stakeCurrency.coinGeckoId);
259-
}
227+
checkIsTestnet(chainInfo);
260228

261-
await checkCoinGeckoIds(...Array.from(coinGeckoIds));
229+
validateCoinGeckoIds(chainInfo); // check coinGeckoId inputs vaild
230+
const coinGeckoIds = collectCoinGeckoIds(chainInfo);
231+
await checkCoinGeckoIdsAvailable(...Array.from(coinGeckoIds)); // check coinGeckoIds available in Coin Gecko
262232

263233
return chainInfo;
264234
};
@@ -272,7 +242,7 @@ export const checkImageSize = (path: string) => {
272242
}
273243
};
274244

275-
const checkCoinGeckoIds = async (...coinGeckoIds: string[]) => {
245+
const checkCoinGeckoIdsAvailable = async (...coinGeckoIds: string[]) => {
276246
const priceURL =
277247
process.env.PRICE_URL || "https://api.coingecko.com/api/v3/simple/price";
278248
const response = await fetch(
@@ -396,3 +366,94 @@ export const checkIsTestnet = (chainInfo: ChainInfo) => {
396366

397367
return true;
398368
};
369+
370+
export const collectCoinGeckoIds = (chainInfo: ChainInfo): Set<string> => {
371+
const coinGeckoIds = new Set<string>();
372+
373+
for (const currency of chainInfo.currencies) {
374+
if (currency.coinGeckoId) {
375+
coinGeckoIds.add(currency.coinGeckoId);
376+
}
377+
}
378+
379+
for (const currency of chainInfo.feeCurrencies) {
380+
if (currency.coinGeckoId) {
381+
coinGeckoIds.add(currency.coinGeckoId);
382+
}
383+
}
384+
385+
if (chainInfo.stakeCurrency?.coinGeckoId) {
386+
coinGeckoIds.add(chainInfo.stakeCurrency.coinGeckoId);
387+
}
388+
389+
return coinGeckoIds;
390+
};
391+
392+
export const validateCoinGeckoIds = (chainInfo: ChainInfo): void => {
393+
const throwError = {
394+
missingCoinGeckoId: (coinMinimalDenom: string) => {
395+
throw new Error(
396+
`Provide coinGeckoId for the currency "${coinMinimalDenom}" in the "currencies", "feeCurrencies", and "stakeCurrency" fields all together`,
397+
);
398+
},
399+
testnetHavingCoinGeckoId: () => {
400+
throw new Error("Testnet chain should not have coinGeckoId");
401+
},
402+
};
403+
404+
for (const currency of chainInfo.currencies) {
405+
if (currency.coinGeckoId && chainInfo.isTestnet) {
406+
throwError.testnetHavingCoinGeckoId();
407+
}
408+
409+
if (
410+
!currency.coinGeckoId &&
411+
((chainInfo.stakeCurrency?.coinMinimalDenom ===
412+
currency.coinMinimalDenom &&
413+
!!chainInfo.stakeCurrency?.coinGeckoId) ||
414+
chainInfo.feeCurrencies.some(
415+
(c) =>
416+
c.coinMinimalDenom === currency.coinMinimalDenom && !!c.coinGeckoId,
417+
))
418+
) {
419+
throwError.missingCoinGeckoId(currency.coinMinimalDenom);
420+
}
421+
}
422+
423+
for (const currency of chainInfo.feeCurrencies) {
424+
if (currency.coinGeckoId && chainInfo.isTestnet) {
425+
throwError.testnetHavingCoinGeckoId();
426+
}
427+
428+
if (
429+
!currency.coinGeckoId &&
430+
((chainInfo.stakeCurrency?.coinMinimalDenom ===
431+
currency.coinMinimalDenom &&
432+
!!chainInfo.stakeCurrency?.coinGeckoId) ||
433+
chainInfo.currencies.some(
434+
(c) =>
435+
c.coinMinimalDenom === currency.coinMinimalDenom && !!c.coinGeckoId,
436+
))
437+
) {
438+
throwError.missingCoinGeckoId(currency.coinMinimalDenom);
439+
}
440+
}
441+
442+
if (chainInfo.stakeCurrency) {
443+
if (chainInfo.stakeCurrency.coinGeckoId && chainInfo.isTestnet) {
444+
throwError.testnetHavingCoinGeckoId();
445+
}
446+
447+
if (
448+
[...chainInfo.currencies, ...chainInfo.feeCurrencies].some(
449+
(c) =>
450+
c.coinMinimalDenom === chainInfo.stakeCurrency?.coinMinimalDenom &&
451+
!!c.coinGeckoId,
452+
)
453+
) {
454+
throwError.missingCoinGeckoId(
455+
chainInfo.stakeCurrency.coinMinimalDenom ?? "",
456+
);
457+
}
458+
}
459+
};

0 commit comments

Comments
 (0)