Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion indexer/src/cache/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@

import { ResolverContext } from '../kadena-server/config/apollo-server-config';
import NodeCache from 'node-cache';
import { HASH_RATE_AND_TOTAL_DIFFICULTY_KEY, NETWORK_STATISTICS_KEY, NODE_INFO_KEY } from './keys';
import {
COUNTERS_OF_EACH_CHAIN_KEY,
HASH_RATE_AND_TOTAL_DIFFICULTY_KEY,
NETWORK_STATISTICS_KEY,
NODE_INFO_KEY,
} from './keys';
import { HashRateAndTotalDifficulty } from '../kadena-server/repository/application/network-repository';

/**
Expand Down Expand Up @@ -108,6 +113,22 @@ export default async function initCache(context: ResolverContext) {
}
}

/**
* Fetches and caches information about the blockchain node
*
* This includes node version, connectivity status, and other
* node-specific information that helps monitor the node's health.
*/

async function getCountersOfEachChain() {
try {
const counters = await networkRepository.getCountersOfEachChain();
MEMORY_CACHE.set(COUNTERS_OF_EACH_CHAIN_KEY, counters);
} catch (err) {
console.error('[ERROR][CACHE][CONN_TIMEOUT] Failed to get counters of each chain', err);
}
}

// Initialize the hash rate cache with a default value
// The -1 value indicates that real data hasn't been loaded yet
MEMORY_CACHE.set(HASH_RATE_AND_TOTAL_DIFFICULTY_KEY, {
Expand All @@ -124,6 +145,7 @@ export default async function initCache(context: ResolverContext) {
await getNetworkStatistics();
await getNodeInfo();
await getHashRateAndTotalDifficulty();
await getCountersOfEachChain();
};

// Populate cache with initial data
Expand Down
6 changes: 6 additions & 0 deletions indexer/src/cache/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ export const NETWORK_STATISTICS_KEY = 'NETWORK_STATISTICS_KEY';
* Used to store and retrieve information about the blockchain node
*/
export const NODE_INFO_KEY = 'NODE_INFO_KEY';

/**
* Key for caching counters of each chain data
* Used to store and retrieve information about the numbers of entities in each chain
*/
export const COUNTERS_OF_EACH_CHAIN_KEY = 'COUNTERS_OF_EACH_CHAIN_KEY';
29 changes: 29 additions & 0 deletions indexer/src/kadena-server/config/graphql-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ export type ContinuationPayload = {
step?: Maybe<Scalars['Int']['output']>;
};

export type CountersOfEachChain = {
__typename?: 'CountersOfEachChain';
blocksCount: Scalars['Int']['output'];
chainId: Scalars['String']['output'];
totalGasUsed: Scalars['String']['output'];
transactionCount: Scalars['Int']['output'];
};

/** DEX metrics including TVL, volume, and pool count */
export type DexMetrics = {
__typename?: 'DexMetrics';
Expand Down Expand Up @@ -394,6 +402,7 @@ export type NetworkInfo = {
apiVersion: Scalars['String']['output'];
/** The number of circulating coins. */
coinsInCirculation: Scalars['Float']['output'];
countersOfEachChain: Array<CountersOfEachChain>;
genesisHeights: Array<GenesisHeight>;
/** The network hash rate. */
networkHashRate: Scalars['Float']['output'];
Expand Down Expand Up @@ -1551,6 +1560,7 @@ export type ResolversTypes = {
Boolean: ResolverTypeWrapper<Scalars['Boolean']['output']>;
ChartDataPoint: ResolverTypeWrapper<ChartDataPoint>;
ContinuationPayload: ResolverTypeWrapper<ContinuationPayload>;
CountersOfEachChain: ResolverTypeWrapper<CountersOfEachChain>;
DateTime: ResolverTypeWrapper<Scalars['DateTime']['output']>;
Decimal: ResolverTypeWrapper<Scalars['Decimal']['output']>;
DexMetrics: ResolverTypeWrapper<DexMetrics>;
Expand Down Expand Up @@ -1846,6 +1856,7 @@ export type ResolversParentTypes = {
Boolean: Scalars['Boolean']['output'];
ChartDataPoint: ChartDataPoint;
ContinuationPayload: ContinuationPayload;
CountersOfEachChain: CountersOfEachChain;
DateTime: Scalars['DateTime']['output'];
Decimal: Scalars['Decimal']['output'];
DexMetrics: DexMetrics;
Expand Down Expand Up @@ -2196,6 +2207,18 @@ export type ContinuationPayloadResolvers<
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};

export type CountersOfEachChainResolvers<
ContextType = any,
ParentType extends
ResolversParentTypes['CountersOfEachChain'] = ResolversParentTypes['CountersOfEachChain'],
> = {
blocksCount?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
chainId?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
totalGasUsed?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
transactionCount?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};

export interface DateTimeScalarConfig
extends GraphQLScalarTypeConfig<ResolversTypes['DateTime'], any> {
name: 'DateTime';
Expand Down Expand Up @@ -2509,6 +2532,11 @@ export type NetworkInfoResolvers<
> = {
apiVersion?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
coinsInCirculation?: Resolver<ResolversTypes['Float'], ParentType, ContextType>;
countersOfEachChain?: Resolver<
Array<ResolversTypes['CountersOfEachChain']>,
ParentType,
ContextType
>;
genesisHeights?: Resolver<Array<ResolversTypes['GenesisHeight']>, ParentType, ContextType>;
networkHashRate?: Resolver<ResolversTypes['Float'], ParentType, ContextType>;
networkHost?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
Expand Down Expand Up @@ -3537,6 +3565,7 @@ export type Resolvers<ContextType = any> = {
BlockTransactionsConnectionEdge?: BlockTransactionsConnectionEdgeResolvers<ContextType>;
ChartDataPoint?: ChartDataPointResolvers<ContextType>;
ContinuationPayload?: ContinuationPayloadResolvers<ContextType>;
CountersOfEachChain?: CountersOfEachChainResolvers<ContextType>;
DateTime?: GraphQLScalarType;
Decimal?: GraphQLScalarType;
DexMetrics?: DexMetricsResolvers<ContextType>;
Expand Down
8 changes: 8 additions & 0 deletions indexer/src/kadena-server/config/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,14 @@ type NetworkInfo {
nodePackageVersion: String!
nodeServiceDate: DateTime
nodeLatestBehaviorHeight: Int!
countersOfEachChain: [CountersOfEachChain!]! @complexity(value: 1)
}

type CountersOfEachChain {
chainId: String!
blocksCount: Int!
transactionCount: Int!
totalGasUsed: String!
}

type GenesisHeight {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,18 @@ export interface GetNodeInfo {
nodeLatestBehaviorHeight: number;
}

type AllInfo = NetworkStatistics & HashRateAndTotalDifficulty & GetNodeInfo;
export interface CountersOfEachChain {
chainId: string;
blocksCount: number;
transactionCount: number;
totalGasUsed: string;
}

type AllInfo = NetworkStatistics &
HashRateAndTotalDifficulty &
GetNodeInfo & {
countersOfEachChain: CountersOfEachChain[];
};

export type CurrentChainHeights = Record<string, number>;

Expand All @@ -31,4 +42,5 @@ export default interface NetworkRepository {
getNodeInfo(): Promise<GetNodeInfo>;
getAllInfo(): Promise<AllInfo>;
getCurrentChainHeights(): Promise<CurrentChainHeights>;
getCountersOfEachChain(): Promise<CountersOfEachChain[]>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { Op } from 'sequelize';
import BlockModel from '../../../../models/block';
import NetworkRepository, {
CountersOfEachChain,
CurrentChainHeights,
GetNodeInfo,
HashRateAndTotalDifficulty,
Expand All @@ -25,7 +26,11 @@ import { rootPgPool } from '../../../../config/database';
import { nodeInfoValidator } from '../schema-validator/node-info-validator';
import { getRequiredEnvString } from '../../../../utils/helpers';
import { MEMORY_CACHE } from '../../../../cache/init';
import { HASH_RATE_AND_TOTAL_DIFFICULTY_KEY, NETWORK_STATISTICS_KEY } from '../../../../cache/keys';
import {
COUNTERS_OF_EACH_CHAIN_KEY,
HASH_RATE_AND_TOTAL_DIFFICULTY_KEY,
NETWORK_STATISTICS_KEY,
} from '../../../../cache/keys';
import { getCirculationNumber } from '../../../../utils/coin-circulation';

// Configuration values from environment variables
Expand Down Expand Up @@ -232,6 +237,27 @@ export default class NetworkDbRepository implements NetworkRepository {
return output;
}

async getCountersOfEachChain(): Promise<CountersOfEachChain[]> {
const countersQuery = `
SELECT "chainId", "canonicalBlocks", "canonicalTransactions", "totalGasUsed"
FROM "Counters"
ORDER BY "chainId"
`;

const { rows } = await rootPgPool.query(countersQuery);

const output = rows.map(row => {
return {
chainId: row.chainId,
blocksCount: row.canonicalBlocks,
transactionCount: row.canonicalTransactions,
totalGasUsed: row.totalGasUsed,
};
});

return output;
}

/**
* Retrieves all network information from cache
*
Expand All @@ -247,7 +273,15 @@ export default class NetworkDbRepository implements NetworkRepository {
const HashRateAndTotalDifficulty = MEMORY_CACHE.get(
HASH_RATE_AND_TOTAL_DIFFICULTY_KEY,
) as HashRateAndTotalDifficulty;
const countersOfEachChain = MEMORY_CACHE.get(
COUNTERS_OF_EACH_CHAIN_KEY,
) as CountersOfEachChain[];

return { ...nodeInfo, ...networkStatistics, ...HashRateAndTotalDifficulty };
return {
...nodeInfo,
...networkStatistics,
...HashRateAndTotalDifficulty,
countersOfEachChain,
};
}
}