diff --git a/apps/api/src/services/external/apiNodeService.ts b/apps/api/src/services/external/apiNodeService.ts index 97a5ca811..5088b7487 100644 --- a/apps/api/src/services/external/apiNodeService.ts +++ b/apps/api/src/services/external/apiNodeService.ts @@ -6,6 +6,8 @@ import fetch from "node-fetch"; import { Op } from "sequelize"; import { cacheKeys, cacheResponse } from "@src/caching/helpers"; +import { getSentry } from "@src/core/providers/sentry.provider"; +import { LoggerService } from "@src/core/services/logger/logger.service"; import { getTransactionByAddress } from "@src/services/db/transactionsService"; import { CosmosGovProposalResponse, @@ -32,64 +34,61 @@ import { getDeploymentRelatedMessages } from "../db/deploymentService"; import { getProviderList } from "../db/providerStatusService"; export async function getChainStats() { + const createLoggingExecutor = (logger: LoggerService) => async (cb: () => Promise, defaultValue?: T): Promise => { + try { + return await cb(); + } catch (error) { + logger.error({ event: `Failed to fetch ${cb.name}`, error }); + getSentry().captureException(error); + return defaultValue; + } + } + + const logger = new LoggerService() + const runOrLog = createLoggingExecutor(logger) + const result = await cacheResponse( 60 * 5, // 5 minutes cacheKeys.getChainStats, async () => { - let bondedTokens; - let totalSupply; - let communityPool; - let inflation; - let communityTax; - - try { + const bondedTokens = await runOrLog(async () => { const bondedTokensQuery = await axios.get( `${apiNodeUrl}/cosmos/staking/v1beta1/pool` ); - bondedTokens = parseInt(bondedTokensQuery.data.pool.bonded_tokens); - } catch (error) { - console.error("Failed to fetch bonded tokens:", error); - } + return parseInt(bondedTokensQuery.data.pool.bonded_tokens); + }) - try { + const totalSupply = await runOrLog(async () => { const supplyQuery = await axios.get( `${apiNodeUrl}/cosmos/bank/v1beta1/supply?pagination.limit=1000` ); - totalSupply = parseInt( + return parseInt( supplyQuery.data.supply.find((x) => x.denom === "uakt")?.amount || "0" ); - } catch (error) { - console.error("Failed to fetch total supply:", error); - } + }) - try { + const communityPool = await runOrLog(async () => { const communityPoolQuery = await axios.get( `${apiNodeUrl}/cosmos/distribution/v1beta1/community_pool` ); - communityPool = parseFloat( + return parseFloat( communityPoolQuery.data.pool.find((x) => x.denom === "uakt")?.amount || "0" ); - } catch (error) { - console.error("Failed to fetch community pool:", error); - } + }) - try { + const inflation = await runOrLog(async () => { const inflationQuery = await axios.get( `${apiNodeUrl}/cosmos/mint/v1beta1/inflation` ); - inflation = parseFloat(inflationQuery.data.inflation || "0"); - } catch (error) { - console.error("Failed to fetch inflation:", error); - } + return parseFloat(inflationQuery.data.inflation || "0"); + }) - try { + const communityTax = await runOrLog(async () => { const distributionQuery = await axios.get( `${apiNodeUrl}/cosmos/distribution/v1beta1/params` ); - communityTax = parseFloat(distributionQuery.data.params.community_tax || "0"); - } catch (error) { - console.error("Failed to fetch distribution params:", error); - } + return parseFloat(distributionQuery.data.params.community_tax || "0"); + }) return { communityPool, @@ -102,18 +101,19 @@ export async function getChainStats() { true ); + let stakingAPR; + if (result.bondedTokens && result.inflation && result.communityTax && result.totalSupply) { + if (result.bondedTokens > 0) { + stakingAPR = result.inflation * (1 - result.communityTax) * result.totalSupply / result.bondedTokens + } + } + return { bondedTokens: result.bondedTokens, totalSupply: result.totalSupply, communityPool: result.communityPool, inflation: result.inflation, - stakingAPR: - result.bondedTokens && result.inflation && result.communityTax && result.totalSupply - ? (result.bondedTokens > 0 - ? (result.inflation * (1 - result.communityTax)) / - (result.bondedTokens / result.totalSupply) - : null) - : undefined, + stakingAPR: stakingAPR, }; }