From 0e169ef5186df314f64cf7127d49351dd2535008 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 12:52:46 +0800 Subject: [PATCH 01/11] feat: generate graphql metadata --- src/__generated__/gql.ts | 9 + src/__generated__/graphql.ts | 750 +++++++++++++++++++++++++++++++++++ 2 files changed, 759 insertions(+) diff --git a/src/__generated__/gql.ts b/src/__generated__/gql.ts index 30178bb..9685f86 100644 --- a/src/__generated__/gql.ts +++ b/src/__generated__/gql.ts @@ -21,6 +21,7 @@ type Documents = { '\n query GetRecentBlocks(\n $limit: Int\n $offset: Int\n $orderBy: [BlockOrderByInput!]\n ) {\n blocks(limit: $limit, offset: $offset, orderBy: $orderBy) {\n id\n hash\n height\n reward\n timestamp\n }\n }\n ': typeof types.GetRecentBlocksDocument; '\n query GetBlockById($height: Int!, $hash: String!, $limit: Int!) {\n blocks(where: { height_eq: $height, OR: { hash_eq: $hash } }) {\n id\n hash\n height\n reward\n timestamp\n }\n miners: minerRewards(\n where: {\n block: { height_eq: $height }\n OR: { block: { hash_eq: $hash } }\n }\n ) {\n miner {\n id\n }\n }\n transactions: transfersConnection(\n orderBy: timestamp_DESC\n first: $limit\n where: {\n extrinsicHash_isNull: false\n AND: {\n block: { height_eq: $height }\n OR: { block: { hash_eq: $hash } }\n }\n }\n ) {\n edges {\n node {\n fee\n extrinsicHash\n block {\n height\n }\n amount\n timestamp\n from {\n id\n }\n to {\n id\n }\n }\n }\n\n totalCount\n }\n reversibleTransactions: reversibleTransfersConnection(\n orderBy: timestamp_DESC\n first: $limit\n where: {\n block: { height_eq: $height }\n OR: { block: { hash_eq: $hash } }\n }\n ) {\n edges {\n node {\n extrinsicHash\n timestamp\n status\n amount\n block {\n height\n }\n from {\n id\n }\n to {\n id\n }\n }\n }\n\n totalCount\n }\n }\n ': typeof types.GetBlockByIdDocument; '\n query GetStatus(\n $beginningDate: DateTime!\n $todayDate: DateTime!\n $endDate: DateTime!\n ) {\n transactions: transfersConnection(\n orderBy: id_ASC\n where: { extrinsicHash_isNull: false }\n ) {\n totalCount\n }\n reversibleTransactions: reversibleTransfersConnection(orderBy: id_ASC) {\n totalCount\n }\n status: squidStatus {\n hash\n height\n finalizedHeight\n finalizedHash\n }\n minedBlocks24Hours: blocksConnection(\n orderBy: id_ASC\n where: { timestamp_gte: $todayDate, timestamp_lte: $endDate }\n ) {\n totalCount\n }\n allActiveAccounts: accountsConnection(\n orderBy: id_ASC\n where: {\n transfersFrom_some: {\n timestamp_gte: $beginningDate\n timestamp_lte: $endDate\n }\n }\n ) {\n totalCount\n }\n allDepositAccounts: accountsConnection(\n orderBy: id_ASC\n where: {\n transfersTo_some: {\n timestamp_gte: $beginningDate\n timestamp_lte: $endDate\n }\n }\n ) {\n totalCount\n }\n }\n ': typeof types.GetStatusDocument; + '\n query GetMinerLeaderboard($limit: Int, $offset: Int) {\n leaderboardEntries: minerStats(\n limit: $limit\n offset: $offset\n orderBy: totalMinedBlocks_DESC\n ) {\n id\n totalMinedBlocks\n totalRewards\n }\n meta: minerStatsConnection(orderBy: id_ASC) {\n totalCount\n }\n }\n ': typeof types.GetMinerLeaderboardDocument; '\n query GetMinerRewards(\n $limit: Int\n $offset: Int\n $orderBy: [MinerRewardOrderByInput!]\n $where: MinerRewardWhereInput\n ) {\n minerRewards(\n limit: $limit\n offset: $offset\n orderBy: $orderBy\n where: $where\n ) {\n block {\n height\n hash\n }\n reward\n miner {\n id\n }\n timestamp\n }\n meta: minerRewardsConnection(orderBy: id_ASC, where: $where) {\n totalCount\n }\n }\n ': typeof types.GetMinerRewardsDocument; '\n query GetRecentMinerRewards(\n $limit: Int\n $offset: Int\n $orderBy: [MinerRewardOrderByInput!]\n $where: MinerRewardWhereInput\n ) {\n minerRewards(\n limit: $limit\n offset: $offset\n orderBy: $orderBy\n where: $where\n ) {\n block {\n height\n hash\n }\n reward\n miner {\n id\n }\n timestamp\n }\n }\n ': typeof types.GetRecentMinerRewardsDocument; '\n query GetMinerRewardsStats($startDate: DateTime!, $endDate: DateTime!) {\n last24Hour: minerRewardsConnection(\n orderBy: id_ASC\n where: { timestamp_gte: $startDate, timestamp_lte: $endDate }\n ) {\n totalCount\n }\n allTime: minerRewardsConnection(orderBy: id_ASC) {\n totalCount\n }\n }\n ': typeof types.GetMinerRewardsStatsDocument; @@ -51,6 +52,8 @@ const documents: Documents = { types.GetBlockByIdDocument, '\n query GetStatus(\n $beginningDate: DateTime!\n $todayDate: DateTime!\n $endDate: DateTime!\n ) {\n transactions: transfersConnection(\n orderBy: id_ASC\n where: { extrinsicHash_isNull: false }\n ) {\n totalCount\n }\n reversibleTransactions: reversibleTransfersConnection(orderBy: id_ASC) {\n totalCount\n }\n status: squidStatus {\n hash\n height\n finalizedHeight\n finalizedHash\n }\n minedBlocks24Hours: blocksConnection(\n orderBy: id_ASC\n where: { timestamp_gte: $todayDate, timestamp_lte: $endDate }\n ) {\n totalCount\n }\n allActiveAccounts: accountsConnection(\n orderBy: id_ASC\n where: {\n transfersFrom_some: {\n timestamp_gte: $beginningDate\n timestamp_lte: $endDate\n }\n }\n ) {\n totalCount\n }\n allDepositAccounts: accountsConnection(\n orderBy: id_ASC\n where: {\n transfersTo_some: {\n timestamp_gte: $beginningDate\n timestamp_lte: $endDate\n }\n }\n ) {\n totalCount\n }\n }\n ': types.GetStatusDocument, + '\n query GetMinerLeaderboard($limit: Int, $offset: Int) {\n leaderboardEntries: minerStats(\n limit: $limit\n offset: $offset\n orderBy: totalMinedBlocks_DESC\n ) {\n id\n totalMinedBlocks\n totalRewards\n }\n meta: minerStatsConnection(orderBy: id_ASC) {\n totalCount\n }\n }\n ': + types.GetMinerLeaderboardDocument, '\n query GetMinerRewards(\n $limit: Int\n $offset: Int\n $orderBy: [MinerRewardOrderByInput!]\n $where: MinerRewardWhereInput\n ) {\n minerRewards(\n limit: $limit\n offset: $offset\n orderBy: $orderBy\n where: $where\n ) {\n block {\n height\n hash\n }\n reward\n miner {\n id\n }\n timestamp\n }\n meta: minerRewardsConnection(orderBy: id_ASC, where: $where) {\n totalCount\n }\n }\n ': types.GetMinerRewardsDocument, '\n query GetRecentMinerRewards(\n $limit: Int\n $offset: Int\n $orderBy: [MinerRewardOrderByInput!]\n $where: MinerRewardWhereInput\n ) {\n minerRewards(\n limit: $limit\n offset: $offset\n orderBy: $orderBy\n where: $where\n ) {\n block {\n height\n hash\n }\n reward\n miner {\n id\n }\n timestamp\n }\n }\n ': @@ -137,6 +140,12 @@ export function gql( export function gql( source: '\n query GetStatus(\n $beginningDate: DateTime!\n $todayDate: DateTime!\n $endDate: DateTime!\n ) {\n transactions: transfersConnection(\n orderBy: id_ASC\n where: { extrinsicHash_isNull: false }\n ) {\n totalCount\n }\n reversibleTransactions: reversibleTransfersConnection(orderBy: id_ASC) {\n totalCount\n }\n status: squidStatus {\n hash\n height\n finalizedHeight\n finalizedHash\n }\n minedBlocks24Hours: blocksConnection(\n orderBy: id_ASC\n where: { timestamp_gte: $todayDate, timestamp_lte: $endDate }\n ) {\n totalCount\n }\n allActiveAccounts: accountsConnection(\n orderBy: id_ASC\n where: {\n transfersFrom_some: {\n timestamp_gte: $beginningDate\n timestamp_lte: $endDate\n }\n }\n ) {\n totalCount\n }\n allDepositAccounts: accountsConnection(\n orderBy: id_ASC\n where: {\n transfersTo_some: {\n timestamp_gte: $beginningDate\n timestamp_lte: $endDate\n }\n }\n ) {\n totalCount\n }\n }\n ' ): (typeof documents)['\n query GetStatus(\n $beginningDate: DateTime!\n $todayDate: DateTime!\n $endDate: DateTime!\n ) {\n transactions: transfersConnection(\n orderBy: id_ASC\n where: { extrinsicHash_isNull: false }\n ) {\n totalCount\n }\n reversibleTransactions: reversibleTransfersConnection(orderBy: id_ASC) {\n totalCount\n }\n status: squidStatus {\n hash\n height\n finalizedHeight\n finalizedHash\n }\n minedBlocks24Hours: blocksConnection(\n orderBy: id_ASC\n where: { timestamp_gte: $todayDate, timestamp_lte: $endDate }\n ) {\n totalCount\n }\n allActiveAccounts: accountsConnection(\n orderBy: id_ASC\n where: {\n transfersFrom_some: {\n timestamp_gte: $beginningDate\n timestamp_lte: $endDate\n }\n }\n ) {\n totalCount\n }\n allDepositAccounts: accountsConnection(\n orderBy: id_ASC\n where: {\n transfersTo_some: {\n timestamp_gte: $beginningDate\n timestamp_lte: $endDate\n }\n }\n ) {\n totalCount\n }\n }\n ']; +/** + * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function gql( + source: '\n query GetMinerLeaderboard($limit: Int, $offset: Int) {\n leaderboardEntries: minerStats(\n limit: $limit\n offset: $offset\n orderBy: totalMinedBlocks_DESC\n ) {\n id\n totalMinedBlocks\n totalRewards\n }\n meta: minerStatsConnection(orderBy: id_ASC) {\n totalCount\n }\n }\n ' +): (typeof documents)['\n query GetMinerLeaderboard($limit: Int, $offset: Int) {\n leaderboardEntries: minerStats(\n limit: $limit\n offset: $offset\n orderBy: totalMinedBlocks_DESC\n ) {\n id\n totalMinedBlocks\n totalRewards\n }\n meta: minerStatsConnection(orderBy: id_ASC) {\n totalCount\n }\n }\n ']; /** * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/src/__generated__/graphql.ts b/src/__generated__/graphql.ts index 7179331..7546531 100644 --- a/src/__generated__/graphql.ts +++ b/src/__generated__/graphql.ts @@ -542,11 +542,266 @@ export type BlocksConnection = { totalCount: Scalars['Int']['output']; }; +export type ErrorEvent = { + __typename?: 'ErrorEvent'; + block: Block; + errorDocs?: Maybe; + errorModule?: Maybe; + errorName?: Maybe; + errorType: Scalars['String']['output']; + event?: Maybe; + extrinsicHash?: Maybe; + id: Scalars['String']['output']; + timestamp: Scalars['DateTime']['output']; +}; + +export type ErrorEventEdge = { + __typename?: 'ErrorEventEdge'; + cursor: Scalars['String']['output']; + node: ErrorEvent; +}; + +export enum ErrorEventOrderByInput { + BlockHashAsc = 'block_hash_ASC', + BlockHashAscNullsFirst = 'block_hash_ASC_NULLS_FIRST', + BlockHashAscNullsLast = 'block_hash_ASC_NULLS_LAST', + BlockHashDesc = 'block_hash_DESC', + BlockHashDescNullsFirst = 'block_hash_DESC_NULLS_FIRST', + BlockHashDescNullsLast = 'block_hash_DESC_NULLS_LAST', + BlockHeightAsc = 'block_height_ASC', + BlockHeightAscNullsFirst = 'block_height_ASC_NULLS_FIRST', + BlockHeightAscNullsLast = 'block_height_ASC_NULLS_LAST', + BlockHeightDesc = 'block_height_DESC', + BlockHeightDescNullsFirst = 'block_height_DESC_NULLS_FIRST', + BlockHeightDescNullsLast = 'block_height_DESC_NULLS_LAST', + BlockIdAsc = 'block_id_ASC', + BlockIdAscNullsFirst = 'block_id_ASC_NULLS_FIRST', + BlockIdAscNullsLast = 'block_id_ASC_NULLS_LAST', + BlockIdDesc = 'block_id_DESC', + BlockIdDescNullsFirst = 'block_id_DESC_NULLS_FIRST', + BlockIdDescNullsLast = 'block_id_DESC_NULLS_LAST', + BlockRewardAsc = 'block_reward_ASC', + BlockRewardAscNullsFirst = 'block_reward_ASC_NULLS_FIRST', + BlockRewardAscNullsLast = 'block_reward_ASC_NULLS_LAST', + BlockRewardDesc = 'block_reward_DESC', + BlockRewardDescNullsFirst = 'block_reward_DESC_NULLS_FIRST', + BlockRewardDescNullsLast = 'block_reward_DESC_NULLS_LAST', + BlockTimestampAsc = 'block_timestamp_ASC', + BlockTimestampAscNullsFirst = 'block_timestamp_ASC_NULLS_FIRST', + BlockTimestampAscNullsLast = 'block_timestamp_ASC_NULLS_LAST', + BlockTimestampDesc = 'block_timestamp_DESC', + BlockTimestampDescNullsFirst = 'block_timestamp_DESC_NULLS_FIRST', + BlockTimestampDescNullsLast = 'block_timestamp_DESC_NULLS_LAST', + ErrorDocsAsc = 'errorDocs_ASC', + ErrorDocsAscNullsFirst = 'errorDocs_ASC_NULLS_FIRST', + ErrorDocsAscNullsLast = 'errorDocs_ASC_NULLS_LAST', + ErrorDocsDesc = 'errorDocs_DESC', + ErrorDocsDescNullsFirst = 'errorDocs_DESC_NULLS_FIRST', + ErrorDocsDescNullsLast = 'errorDocs_DESC_NULLS_LAST', + ErrorModuleAsc = 'errorModule_ASC', + ErrorModuleAscNullsFirst = 'errorModule_ASC_NULLS_FIRST', + ErrorModuleAscNullsLast = 'errorModule_ASC_NULLS_LAST', + ErrorModuleDesc = 'errorModule_DESC', + ErrorModuleDescNullsFirst = 'errorModule_DESC_NULLS_FIRST', + ErrorModuleDescNullsLast = 'errorModule_DESC_NULLS_LAST', + ErrorNameAsc = 'errorName_ASC', + ErrorNameAscNullsFirst = 'errorName_ASC_NULLS_FIRST', + ErrorNameAscNullsLast = 'errorName_ASC_NULLS_LAST', + ErrorNameDesc = 'errorName_DESC', + ErrorNameDescNullsFirst = 'errorName_DESC_NULLS_FIRST', + ErrorNameDescNullsLast = 'errorName_DESC_NULLS_LAST', + ErrorTypeAsc = 'errorType_ASC', + ErrorTypeAscNullsFirst = 'errorType_ASC_NULLS_FIRST', + ErrorTypeAscNullsLast = 'errorType_ASC_NULLS_LAST', + ErrorTypeDesc = 'errorType_DESC', + ErrorTypeDescNullsFirst = 'errorType_DESC_NULLS_FIRST', + ErrorTypeDescNullsLast = 'errorType_DESC_NULLS_LAST', + EventExtrinsicHashAsc = 'event_extrinsicHash_ASC', + EventExtrinsicHashAscNullsFirst = 'event_extrinsicHash_ASC_NULLS_FIRST', + EventExtrinsicHashAscNullsLast = 'event_extrinsicHash_ASC_NULLS_LAST', + EventExtrinsicHashDesc = 'event_extrinsicHash_DESC', + EventExtrinsicHashDescNullsFirst = 'event_extrinsicHash_DESC_NULLS_FIRST', + EventExtrinsicHashDescNullsLast = 'event_extrinsicHash_DESC_NULLS_LAST', + EventIdAsc = 'event_id_ASC', + EventIdAscNullsFirst = 'event_id_ASC_NULLS_FIRST', + EventIdAscNullsLast = 'event_id_ASC_NULLS_LAST', + EventIdDesc = 'event_id_DESC', + EventIdDescNullsFirst = 'event_id_DESC_NULLS_FIRST', + EventIdDescNullsLast = 'event_id_DESC_NULLS_LAST', + EventIsScheduledAsc = 'event_isScheduled_ASC', + EventIsScheduledAscNullsFirst = 'event_isScheduled_ASC_NULLS_FIRST', + EventIsScheduledAscNullsLast = 'event_isScheduled_ASC_NULLS_LAST', + EventIsScheduledDesc = 'event_isScheduled_DESC', + EventIsScheduledDescNullsFirst = 'event_isScheduled_DESC_NULLS_FIRST', + EventIsScheduledDescNullsLast = 'event_isScheduled_DESC_NULLS_LAST', + EventTimestampAsc = 'event_timestamp_ASC', + EventTimestampAscNullsFirst = 'event_timestamp_ASC_NULLS_FIRST', + EventTimestampAscNullsLast = 'event_timestamp_ASC_NULLS_LAST', + EventTimestampDesc = 'event_timestamp_DESC', + EventTimestampDescNullsFirst = 'event_timestamp_DESC_NULLS_FIRST', + EventTimestampDescNullsLast = 'event_timestamp_DESC_NULLS_LAST', + EventTypeAsc = 'event_type_ASC', + EventTypeAscNullsFirst = 'event_type_ASC_NULLS_FIRST', + EventTypeAscNullsLast = 'event_type_ASC_NULLS_LAST', + EventTypeDesc = 'event_type_DESC', + EventTypeDescNullsFirst = 'event_type_DESC_NULLS_FIRST', + EventTypeDescNullsLast = 'event_type_DESC_NULLS_LAST', + ExtrinsicHashAsc = 'extrinsicHash_ASC', + ExtrinsicHashAscNullsFirst = 'extrinsicHash_ASC_NULLS_FIRST', + ExtrinsicHashAscNullsLast = 'extrinsicHash_ASC_NULLS_LAST', + ExtrinsicHashDesc = 'extrinsicHash_DESC', + ExtrinsicHashDescNullsFirst = 'extrinsicHash_DESC_NULLS_FIRST', + ExtrinsicHashDescNullsLast = 'extrinsicHash_DESC_NULLS_LAST', + IdAsc = 'id_ASC', + IdAscNullsFirst = 'id_ASC_NULLS_FIRST', + IdAscNullsLast = 'id_ASC_NULLS_LAST', + IdDesc = 'id_DESC', + IdDescNullsFirst = 'id_DESC_NULLS_FIRST', + IdDescNullsLast = 'id_DESC_NULLS_LAST', + TimestampAsc = 'timestamp_ASC', + TimestampAscNullsFirst = 'timestamp_ASC_NULLS_FIRST', + TimestampAscNullsLast = 'timestamp_ASC_NULLS_LAST', + TimestampDesc = 'timestamp_DESC', + TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', + TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST' +} + +export type ErrorEventWhereInput = { + AND?: InputMaybe>; + OR?: InputMaybe>; + block?: InputMaybe; + block_isNull?: InputMaybe; + errorDocs_contains?: InputMaybe; + errorDocs_containsInsensitive?: InputMaybe; + errorDocs_endsWith?: InputMaybe; + errorDocs_eq?: InputMaybe; + errorDocs_gt?: InputMaybe; + errorDocs_gte?: InputMaybe; + errorDocs_in?: InputMaybe>; + errorDocs_isNull?: InputMaybe; + errorDocs_lt?: InputMaybe; + errorDocs_lte?: InputMaybe; + errorDocs_not_contains?: InputMaybe; + errorDocs_not_containsInsensitive?: InputMaybe; + errorDocs_not_endsWith?: InputMaybe; + errorDocs_not_eq?: InputMaybe; + errorDocs_not_in?: InputMaybe>; + errorDocs_not_startsWith?: InputMaybe; + errorDocs_startsWith?: InputMaybe; + errorModule_contains?: InputMaybe; + errorModule_containsInsensitive?: InputMaybe; + errorModule_endsWith?: InputMaybe; + errorModule_eq?: InputMaybe; + errorModule_gt?: InputMaybe; + errorModule_gte?: InputMaybe; + errorModule_in?: InputMaybe>; + errorModule_isNull?: InputMaybe; + errorModule_lt?: InputMaybe; + errorModule_lte?: InputMaybe; + errorModule_not_contains?: InputMaybe; + errorModule_not_containsInsensitive?: InputMaybe; + errorModule_not_endsWith?: InputMaybe; + errorModule_not_eq?: InputMaybe; + errorModule_not_in?: InputMaybe>; + errorModule_not_startsWith?: InputMaybe; + errorModule_startsWith?: InputMaybe; + errorName_contains?: InputMaybe; + errorName_containsInsensitive?: InputMaybe; + errorName_endsWith?: InputMaybe; + errorName_eq?: InputMaybe; + errorName_gt?: InputMaybe; + errorName_gte?: InputMaybe; + errorName_in?: InputMaybe>; + errorName_isNull?: InputMaybe; + errorName_lt?: InputMaybe; + errorName_lte?: InputMaybe; + errorName_not_contains?: InputMaybe; + errorName_not_containsInsensitive?: InputMaybe; + errorName_not_endsWith?: InputMaybe; + errorName_not_eq?: InputMaybe; + errorName_not_in?: InputMaybe>; + errorName_not_startsWith?: InputMaybe; + errorName_startsWith?: InputMaybe; + errorType_contains?: InputMaybe; + errorType_containsInsensitive?: InputMaybe; + errorType_endsWith?: InputMaybe; + errorType_eq?: InputMaybe; + errorType_gt?: InputMaybe; + errorType_gte?: InputMaybe; + errorType_in?: InputMaybe>; + errorType_isNull?: InputMaybe; + errorType_lt?: InputMaybe; + errorType_lte?: InputMaybe; + errorType_not_contains?: InputMaybe; + errorType_not_containsInsensitive?: InputMaybe; + errorType_not_endsWith?: InputMaybe; + errorType_not_eq?: InputMaybe; + errorType_not_in?: InputMaybe>; + errorType_not_startsWith?: InputMaybe; + errorType_startsWith?: InputMaybe; + event?: InputMaybe; + event_isNull?: InputMaybe; + extrinsicHash_contains?: InputMaybe; + extrinsicHash_containsInsensitive?: InputMaybe; + extrinsicHash_endsWith?: InputMaybe; + extrinsicHash_eq?: InputMaybe; + extrinsicHash_gt?: InputMaybe; + extrinsicHash_gte?: InputMaybe; + extrinsicHash_in?: InputMaybe>; + extrinsicHash_isNull?: InputMaybe; + extrinsicHash_lt?: InputMaybe; + extrinsicHash_lte?: InputMaybe; + extrinsicHash_not_contains?: InputMaybe; + extrinsicHash_not_containsInsensitive?: InputMaybe< + Scalars['String']['input'] + >; + extrinsicHash_not_endsWith?: InputMaybe; + extrinsicHash_not_eq?: InputMaybe; + extrinsicHash_not_in?: InputMaybe>; + extrinsicHash_not_startsWith?: InputMaybe; + extrinsicHash_startsWith?: InputMaybe; + id_contains?: InputMaybe; + id_containsInsensitive?: InputMaybe; + id_endsWith?: InputMaybe; + id_eq?: InputMaybe; + id_gt?: InputMaybe; + id_gte?: InputMaybe; + id_in?: InputMaybe>; + id_isNull?: InputMaybe; + id_lt?: InputMaybe; + id_lte?: InputMaybe; + id_not_contains?: InputMaybe; + id_not_containsInsensitive?: InputMaybe; + id_not_endsWith?: InputMaybe; + id_not_eq?: InputMaybe; + id_not_in?: InputMaybe>; + id_not_startsWith?: InputMaybe; + id_startsWith?: InputMaybe; + timestamp_eq?: InputMaybe; + timestamp_gt?: InputMaybe; + timestamp_gte?: InputMaybe; + timestamp_in?: InputMaybe>; + timestamp_isNull?: InputMaybe; + timestamp_lt?: InputMaybe; + timestamp_lte?: InputMaybe; + timestamp_not_eq?: InputMaybe; + timestamp_not_in?: InputMaybe>; +}; + +export type ErrorEventsConnection = { + __typename?: 'ErrorEventsConnection'; + edges: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + export type Event = { __typename?: 'Event'; balanceEvent?: Maybe; block: Block; + errorEvent?: Maybe; extrinsicHash?: Maybe; + highSecuritySet?: Maybe; id: Scalars['String']['output']; isScheduled: Scalars['Boolean']['output']; minerReward?: Maybe; @@ -611,12 +866,78 @@ export enum EventOrderByInput { BlockTimestampDesc = 'block_timestamp_DESC', BlockTimestampDescNullsFirst = 'block_timestamp_DESC_NULLS_FIRST', BlockTimestampDescNullsLast = 'block_timestamp_DESC_NULLS_LAST', + ErrorEventErrorDocsAsc = 'errorEvent_errorDocs_ASC', + ErrorEventErrorDocsAscNullsFirst = 'errorEvent_errorDocs_ASC_NULLS_FIRST', + ErrorEventErrorDocsAscNullsLast = 'errorEvent_errorDocs_ASC_NULLS_LAST', + ErrorEventErrorDocsDesc = 'errorEvent_errorDocs_DESC', + ErrorEventErrorDocsDescNullsFirst = 'errorEvent_errorDocs_DESC_NULLS_FIRST', + ErrorEventErrorDocsDescNullsLast = 'errorEvent_errorDocs_DESC_NULLS_LAST', + ErrorEventErrorModuleAsc = 'errorEvent_errorModule_ASC', + ErrorEventErrorModuleAscNullsFirst = 'errorEvent_errorModule_ASC_NULLS_FIRST', + ErrorEventErrorModuleAscNullsLast = 'errorEvent_errorModule_ASC_NULLS_LAST', + ErrorEventErrorModuleDesc = 'errorEvent_errorModule_DESC', + ErrorEventErrorModuleDescNullsFirst = 'errorEvent_errorModule_DESC_NULLS_FIRST', + ErrorEventErrorModuleDescNullsLast = 'errorEvent_errorModule_DESC_NULLS_LAST', + ErrorEventErrorNameAsc = 'errorEvent_errorName_ASC', + ErrorEventErrorNameAscNullsFirst = 'errorEvent_errorName_ASC_NULLS_FIRST', + ErrorEventErrorNameAscNullsLast = 'errorEvent_errorName_ASC_NULLS_LAST', + ErrorEventErrorNameDesc = 'errorEvent_errorName_DESC', + ErrorEventErrorNameDescNullsFirst = 'errorEvent_errorName_DESC_NULLS_FIRST', + ErrorEventErrorNameDescNullsLast = 'errorEvent_errorName_DESC_NULLS_LAST', + ErrorEventErrorTypeAsc = 'errorEvent_errorType_ASC', + ErrorEventErrorTypeAscNullsFirst = 'errorEvent_errorType_ASC_NULLS_FIRST', + ErrorEventErrorTypeAscNullsLast = 'errorEvent_errorType_ASC_NULLS_LAST', + ErrorEventErrorTypeDesc = 'errorEvent_errorType_DESC', + ErrorEventErrorTypeDescNullsFirst = 'errorEvent_errorType_DESC_NULLS_FIRST', + ErrorEventErrorTypeDescNullsLast = 'errorEvent_errorType_DESC_NULLS_LAST', + ErrorEventExtrinsicHashAsc = 'errorEvent_extrinsicHash_ASC', + ErrorEventExtrinsicHashAscNullsFirst = 'errorEvent_extrinsicHash_ASC_NULLS_FIRST', + ErrorEventExtrinsicHashAscNullsLast = 'errorEvent_extrinsicHash_ASC_NULLS_LAST', + ErrorEventExtrinsicHashDesc = 'errorEvent_extrinsicHash_DESC', + ErrorEventExtrinsicHashDescNullsFirst = 'errorEvent_extrinsicHash_DESC_NULLS_FIRST', + ErrorEventExtrinsicHashDescNullsLast = 'errorEvent_extrinsicHash_DESC_NULLS_LAST', + ErrorEventIdAsc = 'errorEvent_id_ASC', + ErrorEventIdAscNullsFirst = 'errorEvent_id_ASC_NULLS_FIRST', + ErrorEventIdAscNullsLast = 'errorEvent_id_ASC_NULLS_LAST', + ErrorEventIdDesc = 'errorEvent_id_DESC', + ErrorEventIdDescNullsFirst = 'errorEvent_id_DESC_NULLS_FIRST', + ErrorEventIdDescNullsLast = 'errorEvent_id_DESC_NULLS_LAST', + ErrorEventTimestampAsc = 'errorEvent_timestamp_ASC', + ErrorEventTimestampAscNullsFirst = 'errorEvent_timestamp_ASC_NULLS_FIRST', + ErrorEventTimestampAscNullsLast = 'errorEvent_timestamp_ASC_NULLS_LAST', + ErrorEventTimestampDesc = 'errorEvent_timestamp_DESC', + ErrorEventTimestampDescNullsFirst = 'errorEvent_timestamp_DESC_NULLS_FIRST', + ErrorEventTimestampDescNullsLast = 'errorEvent_timestamp_DESC_NULLS_LAST', ExtrinsicHashAsc = 'extrinsicHash_ASC', ExtrinsicHashAscNullsFirst = 'extrinsicHash_ASC_NULLS_FIRST', ExtrinsicHashAscNullsLast = 'extrinsicHash_ASC_NULLS_LAST', ExtrinsicHashDesc = 'extrinsicHash_DESC', ExtrinsicHashDescNullsFirst = 'extrinsicHash_DESC_NULLS_FIRST', ExtrinsicHashDescNullsLast = 'extrinsicHash_DESC_NULLS_LAST', + HighSecuritySetDelayAsc = 'highSecuritySet_delay_ASC', + HighSecuritySetDelayAscNullsFirst = 'highSecuritySet_delay_ASC_NULLS_FIRST', + HighSecuritySetDelayAscNullsLast = 'highSecuritySet_delay_ASC_NULLS_LAST', + HighSecuritySetDelayDesc = 'highSecuritySet_delay_DESC', + HighSecuritySetDelayDescNullsFirst = 'highSecuritySet_delay_DESC_NULLS_FIRST', + HighSecuritySetDelayDescNullsLast = 'highSecuritySet_delay_DESC_NULLS_LAST', + HighSecuritySetExtrinsicHashAsc = 'highSecuritySet_extrinsicHash_ASC', + HighSecuritySetExtrinsicHashAscNullsFirst = 'highSecuritySet_extrinsicHash_ASC_NULLS_FIRST', + HighSecuritySetExtrinsicHashAscNullsLast = 'highSecuritySet_extrinsicHash_ASC_NULLS_LAST', + HighSecuritySetExtrinsicHashDesc = 'highSecuritySet_extrinsicHash_DESC', + HighSecuritySetExtrinsicHashDescNullsFirst = 'highSecuritySet_extrinsicHash_DESC_NULLS_FIRST', + HighSecuritySetExtrinsicHashDescNullsLast = 'highSecuritySet_extrinsicHash_DESC_NULLS_LAST', + HighSecuritySetIdAsc = 'highSecuritySet_id_ASC', + HighSecuritySetIdAscNullsFirst = 'highSecuritySet_id_ASC_NULLS_FIRST', + HighSecuritySetIdAscNullsLast = 'highSecuritySet_id_ASC_NULLS_LAST', + HighSecuritySetIdDesc = 'highSecuritySet_id_DESC', + HighSecuritySetIdDescNullsFirst = 'highSecuritySet_id_DESC_NULLS_FIRST', + HighSecuritySetIdDescNullsLast = 'highSecuritySet_id_DESC_NULLS_LAST', + HighSecuritySetTimestampAsc = 'highSecuritySet_timestamp_ASC', + HighSecuritySetTimestampAscNullsFirst = 'highSecuritySet_timestamp_ASC_NULLS_FIRST', + HighSecuritySetTimestampAscNullsLast = 'highSecuritySet_timestamp_ASC_NULLS_LAST', + HighSecuritySetTimestampDesc = 'highSecuritySet_timestamp_DESC', + HighSecuritySetTimestampDescNullsFirst = 'highSecuritySet_timestamp_DESC_NULLS_FIRST', + HighSecuritySetTimestampDescNullsLast = 'highSecuritySet_timestamp_DESC_NULLS_LAST', IdAsc = 'id_ASC', IdAscNullsFirst = 'id_ASC_NULLS_FIRST', IdAscNullsLast = 'id_ASC_NULLS_LAST', @@ -741,6 +1062,8 @@ export enum EventOrderByInput { export enum EventType { Balance = 'BALANCE', + Error = 'ERROR', + HighSecuritySet = 'HIGH_SECURITY_SET', MinerReward = 'MINER_REWARD', ReversibleTransfer = 'REVERSIBLE_TRANSFER', Transfer = 'TRANSFER' @@ -753,6 +1076,8 @@ export type EventWhereInput = { balanceEvent_isNull?: InputMaybe; block?: InputMaybe; block_isNull?: InputMaybe; + errorEvent?: InputMaybe; + errorEvent_isNull?: InputMaybe; extrinsicHash_contains?: InputMaybe; extrinsicHash_containsInsensitive?: InputMaybe; extrinsicHash_endsWith?: InputMaybe; @@ -772,6 +1097,8 @@ export type EventWhereInput = { extrinsicHash_not_in?: InputMaybe>; extrinsicHash_not_startsWith?: InputMaybe; extrinsicHash_startsWith?: InputMaybe; + highSecuritySet?: InputMaybe; + highSecuritySet_isNull?: InputMaybe; id_contains?: InputMaybe; id_containsInsensitive?: InputMaybe; id_endsWith?: InputMaybe; @@ -821,6 +1148,245 @@ export type EventsConnection = { totalCount: Scalars['Int']['output']; }; +export type HighSecuritySet = { + __typename?: 'HighSecuritySet'; + block: Block; + delay: Scalars['BigInt']['output']; + event?: Maybe; + extrinsicHash?: Maybe; + id: Scalars['String']['output']; + interceptor: Account; + timestamp: Scalars['DateTime']['output']; + who: Account; +}; + +export type HighSecuritySetEdge = { + __typename?: 'HighSecuritySetEdge'; + cursor: Scalars['String']['output']; + node: HighSecuritySet; +}; + +export enum HighSecuritySetOrderByInput { + BlockHashAsc = 'block_hash_ASC', + BlockHashAscNullsFirst = 'block_hash_ASC_NULLS_FIRST', + BlockHashAscNullsLast = 'block_hash_ASC_NULLS_LAST', + BlockHashDesc = 'block_hash_DESC', + BlockHashDescNullsFirst = 'block_hash_DESC_NULLS_FIRST', + BlockHashDescNullsLast = 'block_hash_DESC_NULLS_LAST', + BlockHeightAsc = 'block_height_ASC', + BlockHeightAscNullsFirst = 'block_height_ASC_NULLS_FIRST', + BlockHeightAscNullsLast = 'block_height_ASC_NULLS_LAST', + BlockHeightDesc = 'block_height_DESC', + BlockHeightDescNullsFirst = 'block_height_DESC_NULLS_FIRST', + BlockHeightDescNullsLast = 'block_height_DESC_NULLS_LAST', + BlockIdAsc = 'block_id_ASC', + BlockIdAscNullsFirst = 'block_id_ASC_NULLS_FIRST', + BlockIdAscNullsLast = 'block_id_ASC_NULLS_LAST', + BlockIdDesc = 'block_id_DESC', + BlockIdDescNullsFirst = 'block_id_DESC_NULLS_FIRST', + BlockIdDescNullsLast = 'block_id_DESC_NULLS_LAST', + BlockRewardAsc = 'block_reward_ASC', + BlockRewardAscNullsFirst = 'block_reward_ASC_NULLS_FIRST', + BlockRewardAscNullsLast = 'block_reward_ASC_NULLS_LAST', + BlockRewardDesc = 'block_reward_DESC', + BlockRewardDescNullsFirst = 'block_reward_DESC_NULLS_FIRST', + BlockRewardDescNullsLast = 'block_reward_DESC_NULLS_LAST', + BlockTimestampAsc = 'block_timestamp_ASC', + BlockTimestampAscNullsFirst = 'block_timestamp_ASC_NULLS_FIRST', + BlockTimestampAscNullsLast = 'block_timestamp_ASC_NULLS_LAST', + BlockTimestampDesc = 'block_timestamp_DESC', + BlockTimestampDescNullsFirst = 'block_timestamp_DESC_NULLS_FIRST', + BlockTimestampDescNullsLast = 'block_timestamp_DESC_NULLS_LAST', + DelayAsc = 'delay_ASC', + DelayAscNullsFirst = 'delay_ASC_NULLS_FIRST', + DelayAscNullsLast = 'delay_ASC_NULLS_LAST', + DelayDesc = 'delay_DESC', + DelayDescNullsFirst = 'delay_DESC_NULLS_FIRST', + DelayDescNullsLast = 'delay_DESC_NULLS_LAST', + EventExtrinsicHashAsc = 'event_extrinsicHash_ASC', + EventExtrinsicHashAscNullsFirst = 'event_extrinsicHash_ASC_NULLS_FIRST', + EventExtrinsicHashAscNullsLast = 'event_extrinsicHash_ASC_NULLS_LAST', + EventExtrinsicHashDesc = 'event_extrinsicHash_DESC', + EventExtrinsicHashDescNullsFirst = 'event_extrinsicHash_DESC_NULLS_FIRST', + EventExtrinsicHashDescNullsLast = 'event_extrinsicHash_DESC_NULLS_LAST', + EventIdAsc = 'event_id_ASC', + EventIdAscNullsFirst = 'event_id_ASC_NULLS_FIRST', + EventIdAscNullsLast = 'event_id_ASC_NULLS_LAST', + EventIdDesc = 'event_id_DESC', + EventIdDescNullsFirst = 'event_id_DESC_NULLS_FIRST', + EventIdDescNullsLast = 'event_id_DESC_NULLS_LAST', + EventIsScheduledAsc = 'event_isScheduled_ASC', + EventIsScheduledAscNullsFirst = 'event_isScheduled_ASC_NULLS_FIRST', + EventIsScheduledAscNullsLast = 'event_isScheduled_ASC_NULLS_LAST', + EventIsScheduledDesc = 'event_isScheduled_DESC', + EventIsScheduledDescNullsFirst = 'event_isScheduled_DESC_NULLS_FIRST', + EventIsScheduledDescNullsLast = 'event_isScheduled_DESC_NULLS_LAST', + EventTimestampAsc = 'event_timestamp_ASC', + EventTimestampAscNullsFirst = 'event_timestamp_ASC_NULLS_FIRST', + EventTimestampAscNullsLast = 'event_timestamp_ASC_NULLS_LAST', + EventTimestampDesc = 'event_timestamp_DESC', + EventTimestampDescNullsFirst = 'event_timestamp_DESC_NULLS_FIRST', + EventTimestampDescNullsLast = 'event_timestamp_DESC_NULLS_LAST', + EventTypeAsc = 'event_type_ASC', + EventTypeAscNullsFirst = 'event_type_ASC_NULLS_FIRST', + EventTypeAscNullsLast = 'event_type_ASC_NULLS_LAST', + EventTypeDesc = 'event_type_DESC', + EventTypeDescNullsFirst = 'event_type_DESC_NULLS_FIRST', + EventTypeDescNullsLast = 'event_type_DESC_NULLS_LAST', + ExtrinsicHashAsc = 'extrinsicHash_ASC', + ExtrinsicHashAscNullsFirst = 'extrinsicHash_ASC_NULLS_FIRST', + ExtrinsicHashAscNullsLast = 'extrinsicHash_ASC_NULLS_LAST', + ExtrinsicHashDesc = 'extrinsicHash_DESC', + ExtrinsicHashDescNullsFirst = 'extrinsicHash_DESC_NULLS_FIRST', + ExtrinsicHashDescNullsLast = 'extrinsicHash_DESC_NULLS_LAST', + IdAsc = 'id_ASC', + IdAscNullsFirst = 'id_ASC_NULLS_FIRST', + IdAscNullsLast = 'id_ASC_NULLS_LAST', + IdDesc = 'id_DESC', + IdDescNullsFirst = 'id_DESC_NULLS_FIRST', + IdDescNullsLast = 'id_DESC_NULLS_LAST', + InterceptorFreeAsc = 'interceptor_free_ASC', + InterceptorFreeAscNullsFirst = 'interceptor_free_ASC_NULLS_FIRST', + InterceptorFreeAscNullsLast = 'interceptor_free_ASC_NULLS_LAST', + InterceptorFreeDesc = 'interceptor_free_DESC', + InterceptorFreeDescNullsFirst = 'interceptor_free_DESC_NULLS_FIRST', + InterceptorFreeDescNullsLast = 'interceptor_free_DESC_NULLS_LAST', + InterceptorFrozenAsc = 'interceptor_frozen_ASC', + InterceptorFrozenAscNullsFirst = 'interceptor_frozen_ASC_NULLS_FIRST', + InterceptorFrozenAscNullsLast = 'interceptor_frozen_ASC_NULLS_LAST', + InterceptorFrozenDesc = 'interceptor_frozen_DESC', + InterceptorFrozenDescNullsFirst = 'interceptor_frozen_DESC_NULLS_FIRST', + InterceptorFrozenDescNullsLast = 'interceptor_frozen_DESC_NULLS_LAST', + InterceptorIdAsc = 'interceptor_id_ASC', + InterceptorIdAscNullsFirst = 'interceptor_id_ASC_NULLS_FIRST', + InterceptorIdAscNullsLast = 'interceptor_id_ASC_NULLS_LAST', + InterceptorIdDesc = 'interceptor_id_DESC', + InterceptorIdDescNullsFirst = 'interceptor_id_DESC_NULLS_FIRST', + InterceptorIdDescNullsLast = 'interceptor_id_DESC_NULLS_LAST', + InterceptorLastUpdatedAsc = 'interceptor_lastUpdated_ASC', + InterceptorLastUpdatedAscNullsFirst = 'interceptor_lastUpdated_ASC_NULLS_FIRST', + InterceptorLastUpdatedAscNullsLast = 'interceptor_lastUpdated_ASC_NULLS_LAST', + InterceptorLastUpdatedDesc = 'interceptor_lastUpdated_DESC', + InterceptorLastUpdatedDescNullsFirst = 'interceptor_lastUpdated_DESC_NULLS_FIRST', + InterceptorLastUpdatedDescNullsLast = 'interceptor_lastUpdated_DESC_NULLS_LAST', + InterceptorReservedAsc = 'interceptor_reserved_ASC', + InterceptorReservedAscNullsFirst = 'interceptor_reserved_ASC_NULLS_FIRST', + InterceptorReservedAscNullsLast = 'interceptor_reserved_ASC_NULLS_LAST', + InterceptorReservedDesc = 'interceptor_reserved_DESC', + InterceptorReservedDescNullsFirst = 'interceptor_reserved_DESC_NULLS_FIRST', + InterceptorReservedDescNullsLast = 'interceptor_reserved_DESC_NULLS_LAST', + TimestampAsc = 'timestamp_ASC', + TimestampAscNullsFirst = 'timestamp_ASC_NULLS_FIRST', + TimestampAscNullsLast = 'timestamp_ASC_NULLS_LAST', + TimestampDesc = 'timestamp_DESC', + TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', + TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST', + WhoFreeAsc = 'who_free_ASC', + WhoFreeAscNullsFirst = 'who_free_ASC_NULLS_FIRST', + WhoFreeAscNullsLast = 'who_free_ASC_NULLS_LAST', + WhoFreeDesc = 'who_free_DESC', + WhoFreeDescNullsFirst = 'who_free_DESC_NULLS_FIRST', + WhoFreeDescNullsLast = 'who_free_DESC_NULLS_LAST', + WhoFrozenAsc = 'who_frozen_ASC', + WhoFrozenAscNullsFirst = 'who_frozen_ASC_NULLS_FIRST', + WhoFrozenAscNullsLast = 'who_frozen_ASC_NULLS_LAST', + WhoFrozenDesc = 'who_frozen_DESC', + WhoFrozenDescNullsFirst = 'who_frozen_DESC_NULLS_FIRST', + WhoFrozenDescNullsLast = 'who_frozen_DESC_NULLS_LAST', + WhoIdAsc = 'who_id_ASC', + WhoIdAscNullsFirst = 'who_id_ASC_NULLS_FIRST', + WhoIdAscNullsLast = 'who_id_ASC_NULLS_LAST', + WhoIdDesc = 'who_id_DESC', + WhoIdDescNullsFirst = 'who_id_DESC_NULLS_FIRST', + WhoIdDescNullsLast = 'who_id_DESC_NULLS_LAST', + WhoLastUpdatedAsc = 'who_lastUpdated_ASC', + WhoLastUpdatedAscNullsFirst = 'who_lastUpdated_ASC_NULLS_FIRST', + WhoLastUpdatedAscNullsLast = 'who_lastUpdated_ASC_NULLS_LAST', + WhoLastUpdatedDesc = 'who_lastUpdated_DESC', + WhoLastUpdatedDescNullsFirst = 'who_lastUpdated_DESC_NULLS_FIRST', + WhoLastUpdatedDescNullsLast = 'who_lastUpdated_DESC_NULLS_LAST', + WhoReservedAsc = 'who_reserved_ASC', + WhoReservedAscNullsFirst = 'who_reserved_ASC_NULLS_FIRST', + WhoReservedAscNullsLast = 'who_reserved_ASC_NULLS_LAST', + WhoReservedDesc = 'who_reserved_DESC', + WhoReservedDescNullsFirst = 'who_reserved_DESC_NULLS_FIRST', + WhoReservedDescNullsLast = 'who_reserved_DESC_NULLS_LAST' +} + +export type HighSecuritySetWhereInput = { + AND?: InputMaybe>; + OR?: InputMaybe>; + block?: InputMaybe; + block_isNull?: InputMaybe; + delay_eq?: InputMaybe; + delay_gt?: InputMaybe; + delay_gte?: InputMaybe; + delay_in?: InputMaybe>; + delay_isNull?: InputMaybe; + delay_lt?: InputMaybe; + delay_lte?: InputMaybe; + delay_not_eq?: InputMaybe; + delay_not_in?: InputMaybe>; + event?: InputMaybe; + event_isNull?: InputMaybe; + extrinsicHash_contains?: InputMaybe; + extrinsicHash_containsInsensitive?: InputMaybe; + extrinsicHash_endsWith?: InputMaybe; + extrinsicHash_eq?: InputMaybe; + extrinsicHash_gt?: InputMaybe; + extrinsicHash_gte?: InputMaybe; + extrinsicHash_in?: InputMaybe>; + extrinsicHash_isNull?: InputMaybe; + extrinsicHash_lt?: InputMaybe; + extrinsicHash_lte?: InputMaybe; + extrinsicHash_not_contains?: InputMaybe; + extrinsicHash_not_containsInsensitive?: InputMaybe< + Scalars['String']['input'] + >; + extrinsicHash_not_endsWith?: InputMaybe; + extrinsicHash_not_eq?: InputMaybe; + extrinsicHash_not_in?: InputMaybe>; + extrinsicHash_not_startsWith?: InputMaybe; + extrinsicHash_startsWith?: InputMaybe; + id_contains?: InputMaybe; + id_containsInsensitive?: InputMaybe; + id_endsWith?: InputMaybe; + id_eq?: InputMaybe; + id_gt?: InputMaybe; + id_gte?: InputMaybe; + id_in?: InputMaybe>; + id_isNull?: InputMaybe; + id_lt?: InputMaybe; + id_lte?: InputMaybe; + id_not_contains?: InputMaybe; + id_not_containsInsensitive?: InputMaybe; + id_not_endsWith?: InputMaybe; + id_not_eq?: InputMaybe; + id_not_in?: InputMaybe>; + id_not_startsWith?: InputMaybe; + id_startsWith?: InputMaybe; + interceptor?: InputMaybe; + interceptor_isNull?: InputMaybe; + timestamp_eq?: InputMaybe; + timestamp_gt?: InputMaybe; + timestamp_gte?: InputMaybe; + timestamp_in?: InputMaybe>; + timestamp_isNull?: InputMaybe; + timestamp_lt?: InputMaybe; + timestamp_lte?: InputMaybe; + timestamp_not_eq?: InputMaybe; + timestamp_not_in?: InputMaybe>; + who?: InputMaybe; + who_isNull?: InputMaybe; +}; + +export type HighSecuritySetsConnection = { + __typename?: 'HighSecuritySetsConnection'; + edges: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + export type MinerReward = { __typename?: 'MinerReward'; block: Block; @@ -1102,9 +1668,15 @@ export type Query = { blockById?: Maybe; blocks: Array; blocksConnection: BlocksConnection; + errorEventById?: Maybe; + errorEvents: Array; + errorEventsConnection: ErrorEventsConnection; eventById?: Maybe; events: Array; eventsConnection: EventsConnection; + highSecuritySetById?: Maybe; + highSecuritySets: Array; + highSecuritySetsConnection: HighSecuritySetsConnection; minerRewardById?: Maybe; minerRewards: Array; minerRewardsConnection: MinerRewardsConnection; @@ -1174,6 +1746,24 @@ export type QueryBlocksConnectionArgs = { where?: InputMaybe; }; +export type QueryErrorEventByIdArgs = { + id: Scalars['String']['input']; +}; + +export type QueryErrorEventsArgs = { + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + +export type QueryErrorEventsConnectionArgs = { + after?: InputMaybe; + first?: InputMaybe; + orderBy: Array; + where?: InputMaybe; +}; + export type QueryEventByIdArgs = { id: Scalars['String']['input']; }; @@ -1192,6 +1782,24 @@ export type QueryEventsConnectionArgs = { where?: InputMaybe; }; +export type QueryHighSecuritySetByIdArgs = { + id: Scalars['String']['input']; +}; + +export type QueryHighSecuritySetsArgs = { + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + +export type QueryHighSecuritySetsConnectionArgs = { + after?: InputMaybe; + first?: InputMaybe; + orderBy: Array; + where?: InputMaybe; +}; + export type QueryMinerRewardByIdArgs = { id: Scalars['String']['input']; }; @@ -1268,6 +1876,7 @@ export type ReversibleTransfer = { __typename?: 'ReversibleTransfer'; amount: Scalars['BigInt']['output']; block: Block; + cancelledBy?: Maybe; event?: Maybe; executedTransfer?: Maybe; extrinsicHash?: Maybe; @@ -1324,6 +1933,36 @@ export enum ReversibleTransferOrderByInput { BlockTimestampDesc = 'block_timestamp_DESC', BlockTimestampDescNullsFirst = 'block_timestamp_DESC_NULLS_FIRST', BlockTimestampDescNullsLast = 'block_timestamp_DESC_NULLS_LAST', + CancelledByFreeAsc = 'cancelledBy_free_ASC', + CancelledByFreeAscNullsFirst = 'cancelledBy_free_ASC_NULLS_FIRST', + CancelledByFreeAscNullsLast = 'cancelledBy_free_ASC_NULLS_LAST', + CancelledByFreeDesc = 'cancelledBy_free_DESC', + CancelledByFreeDescNullsFirst = 'cancelledBy_free_DESC_NULLS_FIRST', + CancelledByFreeDescNullsLast = 'cancelledBy_free_DESC_NULLS_LAST', + CancelledByFrozenAsc = 'cancelledBy_frozen_ASC', + CancelledByFrozenAscNullsFirst = 'cancelledBy_frozen_ASC_NULLS_FIRST', + CancelledByFrozenAscNullsLast = 'cancelledBy_frozen_ASC_NULLS_LAST', + CancelledByFrozenDesc = 'cancelledBy_frozen_DESC', + CancelledByFrozenDescNullsFirst = 'cancelledBy_frozen_DESC_NULLS_FIRST', + CancelledByFrozenDescNullsLast = 'cancelledBy_frozen_DESC_NULLS_LAST', + CancelledByIdAsc = 'cancelledBy_id_ASC', + CancelledByIdAscNullsFirst = 'cancelledBy_id_ASC_NULLS_FIRST', + CancelledByIdAscNullsLast = 'cancelledBy_id_ASC_NULLS_LAST', + CancelledByIdDesc = 'cancelledBy_id_DESC', + CancelledByIdDescNullsFirst = 'cancelledBy_id_DESC_NULLS_FIRST', + CancelledByIdDescNullsLast = 'cancelledBy_id_DESC_NULLS_LAST', + CancelledByLastUpdatedAsc = 'cancelledBy_lastUpdated_ASC', + CancelledByLastUpdatedAscNullsFirst = 'cancelledBy_lastUpdated_ASC_NULLS_FIRST', + CancelledByLastUpdatedAscNullsLast = 'cancelledBy_lastUpdated_ASC_NULLS_LAST', + CancelledByLastUpdatedDesc = 'cancelledBy_lastUpdated_DESC', + CancelledByLastUpdatedDescNullsFirst = 'cancelledBy_lastUpdated_DESC_NULLS_FIRST', + CancelledByLastUpdatedDescNullsLast = 'cancelledBy_lastUpdated_DESC_NULLS_LAST', + CancelledByReservedAsc = 'cancelledBy_reserved_ASC', + CancelledByReservedAscNullsFirst = 'cancelledBy_reserved_ASC_NULLS_FIRST', + CancelledByReservedAscNullsLast = 'cancelledBy_reserved_ASC_NULLS_LAST', + CancelledByReservedDesc = 'cancelledBy_reserved_DESC', + CancelledByReservedDescNullsFirst = 'cancelledBy_reserved_DESC_NULLS_FIRST', + CancelledByReservedDescNullsLast = 'cancelledBy_reserved_DESC_NULLS_LAST', EventExtrinsicHashAsc = 'event_extrinsicHash_ASC', EventExtrinsicHashAscNullsFirst = 'event_extrinsicHash_ASC_NULLS_FIRST', EventExtrinsicHashAscNullsLast = 'event_extrinsicHash_ASC_NULLS_LAST', @@ -1508,6 +2147,8 @@ export type ReversibleTransferWhereInput = { amount_not_in?: InputMaybe>; block?: InputMaybe; block_isNull?: InputMaybe; + cancelledBy?: InputMaybe; + cancelledBy_isNull?: InputMaybe; event?: InputMaybe; event_isNull?: InputMaybe; executedTransfer?: InputMaybe; @@ -2141,6 +2782,22 @@ export type GetStatusQuery = { allDepositAccounts: { __typename?: 'AccountsConnection'; totalCount: number }; }; +export type GetMinerLeaderboardQueryVariables = Exact<{ + limit?: InputMaybe; + offset?: InputMaybe; +}>; + +export type GetMinerLeaderboardQuery = { + __typename?: 'Query'; + leaderboardEntries: Array<{ + __typename?: 'MinerStats'; + id: string; + totalMinedBlocks: number; + totalRewards: any; + }>; + meta: { __typename?: 'MinerStatsConnection'; totalCount: number }; +}; + export type GetMinerRewardsQueryVariables = Exact<{ limit?: InputMaybe; offset?: InputMaybe; @@ -4147,6 +4804,99 @@ export const GetStatusDocument = { } ] } as unknown as DocumentNode; +export const GetMinerLeaderboardDocument = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'query', + name: { kind: 'Name', value: 'GetMinerLeaderboard' }, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { kind: 'Name', value: 'limit' } + }, + type: { kind: 'NamedType', name: { kind: 'Name', value: 'Int' } } + }, + { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { kind: 'Name', value: 'offset' } + }, + type: { kind: 'NamedType', name: { kind: 'Name', value: 'Int' } } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + alias: { kind: 'Name', value: 'leaderboardEntries' }, + name: { kind: 'Name', value: 'minerStats' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'limit' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'limit' } + } + }, + { + kind: 'Argument', + name: { kind: 'Name', value: 'offset' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'offset' } + } + }, + { + kind: 'Argument', + name: { kind: 'Name', value: 'orderBy' }, + value: { kind: 'EnumValue', value: 'totalMinedBlocks_DESC' } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: 'id' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'totalMinedBlocks' } + }, + { kind: 'Field', name: { kind: 'Name', value: 'totalRewards' } } + ] + } + }, + { + kind: 'Field', + alias: { kind: 'Name', value: 'meta' }, + name: { kind: 'Name', value: 'minerStatsConnection' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'orderBy' }, + value: { kind: 'EnumValue', value: 'id_ASC' } + } + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: 'totalCount' } } + ] + } + } + ] + } + } + ] +} as unknown as DocumentNode< + GetMinerLeaderboardQuery, + GetMinerLeaderboardQueryVariables +>; export const GetMinerRewardsDocument = { kind: 'Document', definitions: [ From 2513301807f0b5abbd15dd5c60f1254d9afcb1b4 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 12:53:05 +0800 Subject: [PATCH 02/11] feat: add high security set schema and api --- src/api/high-security-sets.tsx | 186 ++++++++++++++++++ .../query-sorts/high-security-sets.ts | 41 ++++ src/constants/query-sorts/index.ts | 1 + src/schemas/high-security-set.ts | 35 ++++ src/schemas/index.ts | 1 + 5 files changed, 264 insertions(+) create mode 100644 src/api/high-security-sets.tsx create mode 100644 src/constants/query-sorts/high-security-sets.ts create mode 100644 src/schemas/high-security-set.ts diff --git a/src/api/high-security-sets.tsx b/src/api/high-security-sets.tsx new file mode 100644 index 0000000..d57aa74 --- /dev/null +++ b/src/api/high-security-sets.tsx @@ -0,0 +1,186 @@ +import type { QueryHookOptions } from '@apollo/client'; +import { gql, useQuery } from '@apollo/client'; +import { endOfToday } from 'date-fns/endOfToday'; +import { startOfToday } from 'date-fns/startOfToday'; + +import type { HighSecuritySetWhereInput } from '@/__generated__/graphql'; +import { QUERY_DEFAULT_LIMIT } from '@/constants/query-default-limit'; +import { QUERY_RECENT_LIMIT } from '@/constants/query-recent-limit'; +import type { HighSecuritySetSorts } from '@/constants/query-sorts'; +import { HIGH_SECURITY_SET_SORTS } from '@/constants/query-sorts'; +import type { + HighSecuritySetListResponse, + HighSecuritySetResponse, + HighSecuritySetsStatsResponse, + RecentHighSecuritySetsResponse +} from '@/schemas'; +import type { PaginatedQueryVariables } from '@/types/query'; + +export const highSecuritySets = { + useGetAll: ( + config?: QueryHookOptions< + HighSecuritySetListResponse, + PaginatedQueryVariables + > + ) => { + const GET_HIGH_SECURITY_SETS = gql` + query GetHighSecuritySets( + $limit: Int + $offset: Int + $orderBy: [HighSecuritySetOrderByInput!] + $where: HighSecuritySetWhereInput + ) { + highSecuritySets( + limit: $limit + offset: $offset + orderBy: $orderBy + where: $where + ) { + id + extrinsicHash + who { + id + } + interceptor { + id + } + timestamp + delay + block { + height + } + } + meta: highSecuritySetsConnection(orderBy: id_ASC, where: $where) { + totalCount + } + } + `; + + return useQuery< + HighSecuritySetListResponse, + PaginatedQueryVariables + >(GET_HIGH_SECURITY_SETS, { + ...config, + variables: { + orderBy: + config?.variables?.orderBy ?? HIGH_SECURITY_SET_SORTS.timestamp.DESC, + limit: config?.variables?.limit ?? QUERY_DEFAULT_LIMIT, + offset: config?.variables?.offset ?? 0, + where: config?.variables?.where + } + }); + }, + useGetRecent: ( + config?: Omit, 'variables'> + ) => { + const GET_RECENT_HIGH_SECURITY_SETS = gql` + query GetRecentHighSecuritySets( + $limit: Int + $offset: Int + $orderBy: [HighSecuritySetOrderByInput!] + $where: HighSecuritySetWhereInput + ) { + highSecuritySets( + limit: $limit + offset: $offset + orderBy: $orderBy + where: $where + ) { + id + extrinsicHash + who { + id + } + interceptor { + id + } + timestamp + delay + block { + height + } + } + } + `; + + return useQuery< + RecentHighSecuritySetsResponse, + PaginatedQueryVariables + >(GET_RECENT_HIGH_SECURITY_SETS, { + ...config, + variables: { + orderBy: HIGH_SECURITY_SET_SORTS.timestamp.DESC, + limit: QUERY_RECENT_LIMIT, + where: {} + } + }); + }, + useGetStats: ( + config?: Omit, 'variables'> + ) => { + const startDate = startOfToday().toISOString(); + const endDate = endOfToday().toISOString(); + + const GET_HIGH_SECURITY_SETS_STATS = gql` + query GetHighSecuritySetsStats( + $startDate: DateTime! + $endDate: DateTime! + ) { + last24Hour: highSecuritySetsConnection( + orderBy: id_ASC + where: { timestamp_gte: $startDate, timestamp_lte: $endDate } + ) { + totalCount + } + allTime: highSecuritySetsConnection(orderBy: id_ASC) { + totalCount + } + } + `; + + return useQuery( + GET_HIGH_SECURITY_SETS_STATS, + { + ...config, + variables: { + startDate, + endDate + } + } + ); + }, + getByHash: () => { + const QUERY = gql` + query GetHighSecuritySetByHash($hash: String!) { + highSecuritySets(where: { extrinsicHash_eq: $hash }) { + id + extrinsicHash + who { + id + } + interceptor { + id + } + timestamp + delay + block { + height + } + } + } + `; + + return { + useQuery: ( + hash: string, + config?: QueryHookOptions + ) => + useQuery(QUERY, { + ...config, + variables: { + hash + } + }) + }; + } +}; diff --git a/src/constants/query-sorts/high-security-sets.ts b/src/constants/query-sorts/high-security-sets.ts new file mode 100644 index 0000000..2a4355f --- /dev/null +++ b/src/constants/query-sorts/high-security-sets.ts @@ -0,0 +1,41 @@ +export const HIGH_SECURITY_SET_SORTS = { + id: { + ASC: 'id_ASC', + DESC: 'id_DESC' + }, + timestamp: { + ASC: 'timestamp_ASC', + DESC: 'timestamp_DESC' + }, + delay: { + ASC: 'delay_ASC', + DESC: 'delay_DESC' + }, + extrinsicHash: { + ASC: 'extrinsicHash_ASC', + DESC: 'extrinsicHash_DESC' + }, + blockHeight: { + ASC: 'block_height_ASC', + DESC: 'block_height_DESC' + }, + who: { + id_ASC: 'who_id_ASC', + id_DESC: 'who_id_DESC' + }, + interceptor: { + id_ASC: 'interceptor_id_ASC', + id_DESC: 'interceptor_id_DESC' + } +} as const; + +export const HIGH_SECURITY_SET_SORTS_LITERALS = Object.values( + HIGH_SECURITY_SET_SORTS +).flatMap((sort) => Object.values(sort)); + +export const HIGH_SECURITY_SET_SORTS_KEY = Object.keys(HIGH_SECURITY_SET_SORTS); + +// Adding null, because we can sort by null to indicate no sorting +export type HighSecuritySetSorts = + | (typeof HIGH_SECURITY_SET_SORTS_LITERALS)[number] + | null; diff --git a/src/constants/query-sorts/index.ts b/src/constants/query-sorts/index.ts index cf47f48..20ff909 100644 --- a/src/constants/query-sorts/index.ts +++ b/src/constants/query-sorts/index.ts @@ -1,5 +1,6 @@ export * from './accounts'; export * from './blocks'; +export * from './high-security-sets'; export * from './miner-rewards'; export * from './reversible-transactions'; export * from './transactions'; diff --git a/src/schemas/high-security-set.ts b/src/schemas/high-security-set.ts new file mode 100644 index 0000000..b43f6d7 --- /dev/null +++ b/src/schemas/high-security-set.ts @@ -0,0 +1,35 @@ +import type * as gql from '../__generated__/graphql'; + +export interface HighSecuritySet + extends Omit< + gql.HighSecuritySet, + 'id' | 'who' | 'interceptor' | 'block' | 'event' + > { + who: Pick; + interceptor: Pick; + block: Pick; +} + +export interface HighSecuritySetResponse { + highSecuritySets: HighSecuritySet[]; +} + +export interface HighSecuritySetListResponse { + highSecuritySets: HighSecuritySet[]; + meta: { + totalCount: number; + }; +} + +export interface RecentHighSecuritySetsResponse { + highSecuritySets: HighSecuritySet[]; +} + +export interface HighSecuritySetsStatsResponse { + allTime: { + totalCount: number; + }; + last24Hour: { + totalCount: number; + }; +} diff --git a/src/schemas/index.ts b/src/schemas/index.ts index 25af82b..acb05d8 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -1,6 +1,7 @@ export * from './account'; export * from './blocks'; export * from './chain-status'; +export * from './high-security-set'; export * from './miner-leaderboard'; export * from './miner-reward'; export * from './reversible-transaction'; From bb2ff19c8e1d6b2cbaefb4148819db67264eefd2 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 13:09:12 +0800 Subject: [PATCH 03/11] feat: finish adding high security listing --- src/api/index.tsx | 4 +- .../HIGH_SECURITY_SET_COLUMNS.tsx | 74 +++++++++ .../HighSecuritySetsHeading.tsx | 36 +++++ .../HighSecuritySetsStats.tsx | 56 +++++++ .../HighSecuritySetsTable.tsx | 20 +++ .../high-security-sets-table/hook.tsx | 149 ++++++++++++++++++ src/utils/formatter.ts | 45 ++++++ 7 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx create mode 100644 src/components/features/high-security-sets-listing/high-security-sets-heading/HighSecuritySetsHeading.tsx create mode 100644 src/components/features/high-security-sets-listing/high-security-sets-stats/HighSecuritySetsStats.tsx create mode 100644 src/components/features/high-security-sets-listing/high-security-sets-table/HighSecuritySetsTable.tsx create mode 100644 src/components/features/high-security-sets-listing/high-security-sets-table/hook.tsx diff --git a/src/api/index.tsx b/src/api/index.tsx index 6140484..c5d78a8 100644 --- a/src/api/index.tsx +++ b/src/api/index.tsx @@ -3,6 +3,7 @@ import { useFetchClient } from '@/hooks/useFetchClient'; import { accounts } from './accounts'; import { blocks } from './blocks'; import { chainStatus } from './chain-status'; +import { highSecuritySets } from './high-security-sets'; import { minerLeaderboard } from './miner-leaderboard'; import { minerRewards } from './miner-rewards'; import { reversibleTransactions } from './reversible-transactions'; @@ -20,7 +21,8 @@ const useApiClient = () => { search: search(fetcher), blocks, minerRewards, - minerLeaderboard + minerLeaderboard, + highSecuritySets }; return api; diff --git a/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx b/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx new file mode 100644 index 0000000..41ca94e --- /dev/null +++ b/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx @@ -0,0 +1,74 @@ +import { createColumnHelper } from '@tanstack/react-table'; + +import { LinkWithCopy } from '@/components/ui/composites/link-with-copy/LinkWithCopy'; +import { TimestampDisplay } from '@/components/ui/timestamp-display'; +import { RESOURCES } from '@/constants/resources'; +import type { HighSecuritySet } from '@/schemas'; +import { formatDuration, formatTxAddress } from '@/utils/formatter'; + +const columnHelper = createColumnHelper(); + +export const HIGH_SECURITY_SET_COLUMNS = [ + columnHelper.accessor('extrinsicHash', { + id: 'tx-hash', + header: 'Hash', + cell: (props) => + props.getValue() ? ( + + ) : ( + 'Is not available' + ), + enableSorting: false + }), + columnHelper.accessor('block.height', { + id: 'block_height', + header: 'Block', + cell: (props) => ( + + ), + enableSorting: true + }), + columnHelper.accessor('timestamp', { + id: 'timestamp', + header: 'Timestamp', + cell: (props) => , + enableSorting: true + }), + columnHelper.accessor('who.id', { + id: 'who', + header: 'Who', + cell: (props) => ( + + ), + enableSorting: false + }), + columnHelper.accessor('interceptor.id', { + id: 'interceptor', + header: 'Interceptor', + cell: (props) => ( + + ), + enableSorting: false + }), + columnHelper.accessor('delay', { + id: 'delay', + header: 'Delay', + cell: (props) => formatDuration(props.getValue()), + enableSorting: true + }) +]; diff --git a/src/components/features/high-security-sets-listing/high-security-sets-heading/HighSecuritySetsHeading.tsx b/src/components/features/high-security-sets-listing/high-security-sets-heading/HighSecuritySetsHeading.tsx new file mode 100644 index 0000000..5a7303a --- /dev/null +++ b/src/components/features/high-security-sets-listing/high-security-sets-heading/HighSecuritySetsHeading.tsx @@ -0,0 +1,36 @@ +import { Link, useSearch } from '@tanstack/react-router'; +import * as React from 'react'; + +export interface HighSecuritySetsHeadingProps {} + +export const HighSecuritySetsHeading: React.FC< + HighSecuritySetsHeadingProps +> = () => { + const { accountId, block } = useSearch({ + strict: false + }) as any; + + return ( +
+

High Security Sets

+ + {block && ( +
+ In block + + {block} + +
+ )} + + {accountId && ( +
+ By + + {accountId} + +
+ )} +
+ ); +}; diff --git a/src/components/features/high-security-sets-listing/high-security-sets-stats/HighSecuritySetsStats.tsx b/src/components/features/high-security-sets-listing/high-security-sets-stats/HighSecuritySetsStats.tsx new file mode 100644 index 0000000..804cb0b --- /dev/null +++ b/src/components/features/high-security-sets-listing/high-security-sets-stats/HighSecuritySetsStats.tsx @@ -0,0 +1,56 @@ +import { useSearch } from '@tanstack/react-router'; +import React from 'react'; + +import useApiClient from '@/api'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Skeleton } from '@/components/ui/skeleton'; +import { DATA_POOL_INTERVAL } from '@/constants/data-pool-interval'; + +export interface HighSecuritySetsStatsProps {} + +export const HighSecuritySetsStats: React.FC< + HighSecuritySetsStatsProps +> = () => { + const api = useApiClient(); + const { accountId, block } = useSearch({ + strict: false + }) as any; + + if (accountId || block) return null; + + const { loading, data, error } = api.highSecuritySets.useGetStats({ + pollInterval: DATA_POOL_INTERVAL + }); + + const success = !loading && !error; + + return ( +
+ + + +

Total High Security Sets

+
+
+ + {success &&

{data?.allTime.totalCount}

} + {loading && } + {error &&

Error: {error.message}

} +
+
+ + + + +

Recent High Security Sets (24H)

+
+
+ + {success &&

{data?.last24Hour.totalCount}

} + {loading && } + {error &&

Error: {error.message}

} +
+
+
+ ); +}; diff --git a/src/components/features/high-security-sets-listing/high-security-sets-table/HighSecuritySetsTable.tsx b/src/components/features/high-security-sets-listing/high-security-sets-table/HighSecuritySetsTable.tsx new file mode 100644 index 0000000..dc4a995 --- /dev/null +++ b/src/components/features/high-security-sets-listing/high-security-sets-table/HighSecuritySetsTable.tsx @@ -0,0 +1,20 @@ +import React from 'react'; + +import { DataTable } from '@/components/ui/composites/data-table/DataTable'; + +import { useHighSecuritySetsTable } from './hook'; + +export const HighSecuritySetsTable = () => { + const { getStatus, table, error } = useHighSecuritySetsTable(); + + return ( + Error: {error && error.message}

+ }} + withControls + /> + ); +}; diff --git a/src/components/features/high-security-sets-listing/high-security-sets-table/hook.tsx b/src/components/features/high-security-sets-listing/high-security-sets-table/hook.tsx new file mode 100644 index 0000000..4735312 --- /dev/null +++ b/src/components/features/high-security-sets-listing/high-security-sets-table/hook.tsx @@ -0,0 +1,149 @@ +import { useSearch } from '@tanstack/react-router'; +import type { + OnChangeFn, + PaginationState, + SortingState +} from '@tanstack/react-table'; +import { getCoreRowModel, useReactTable } from '@tanstack/react-table'; +import { parseAsInteger, parseAsStringLiteral, useQueryState } from 'nuqs'; +import { useEffect, useMemo, useState } from 'react'; + +import useApiClient from '@/api'; +import { HIGH_SECURITY_SET_COLUMNS } from '@/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS'; +import { DATA_POOL_INTERVAL } from '@/constants/data-pool-interval'; +import { QUERY_DEFAULT_LIMIT } from '@/constants/query-default-limit'; +import type { HighSecuritySetSorts } from '@/constants/query-sorts'; +import { HIGH_SECURITY_SET_SORTS_LITERALS } from '@/constants/query-sorts'; +import type { HighSecuritySet } from '@/schemas'; +import { transformSortLiteral } from '@/utils/transform-sort'; + +export const useHighSecuritySetsTable = () => { + const api = useApiClient(); + const { accountId, block } = useSearch({ + strict: false + }) as any; + + const [page, setPage] = useQueryState('page', parseAsInteger.withDefault(1)); + const [limit, setLimit] = useQueryState( + 'limit', + parseAsInteger.withDefault(QUERY_DEFAULT_LIMIT) + ); + const [sortBy, setSortBy] = useQueryState( + 'sortBy', + parseAsStringLiteral(HIGH_SECURITY_SET_SORTS_LITERALS) + ); + + const currentPageIndex = page - 1; + + const sortingValue: SortingState = transformSortLiteral(sortBy); + const paginationValue: PaginationState = { + pageSize: limit, + pageIndex: currentPageIndex + }; + + const handleChangeSorting: OnChangeFn = (sorting) => { + if (typeof sorting === 'function') { + const newValue = sorting(sortingValue); + + if (newValue[0]?.id) { + const key = newValue[0].id; + const order = newValue[0].desc ? 'DESC' : 'ASC'; + + const newSortBy = `${key}_${order}` as HighSecuritySetSorts; + + setSortBy(newSortBy); + } else { + setSortBy(null); + } + } else if (sorting[0]?.id) { + const key = sorting[0].id; + const order = sorting[0].desc ? 'DESC' : 'ASC'; + + const newSortBy = `${key}_${order}` as HighSecuritySetSorts; + + setSortBy(newSortBy); + } + }; + + const handleChangePagination: OnChangeFn = (pagination) => { + if (typeof pagination === 'function') { + const newPagination = pagination(paginationValue); + + setPage(newPagination.pageIndex + 1); + setLimit(newPagination.pageSize); + } else { + setPage(pagination.pageIndex + 1); + setLimit(pagination.pageSize); + } + }; + + const { + loading, + data, + error: fetchError + } = api.highSecuritySets.useGetAll({ + pollInterval: DATA_POOL_INTERVAL, + variables: { + orderBy: sortBy, + limit, + offset: currentPageIndex * limit, + ...(accountId && { + where: { + OR: [ + { who: { id_eq: accountId } }, + { interceptor: { id_eq: accountId } } + ] + } + }), + ...(block && { + where: { + block: { height_eq: Number(block) } + } + }) + } + }); + + const highSecuritySetColumns = useMemo(() => HIGH_SECURITY_SET_COLUMNS, []); + const [rowCount, setRowCount] = useState(data?.meta.totalCount ?? 0); + + const table = useReactTable({ + data: data?.highSecuritySets ?? [], + columns: highSecuritySetColumns, + getCoreRowModel: getCoreRowModel(), + state: { + sorting: sortingValue, + pagination: paginationValue + }, + rowCount, + onSortingChange: handleChangeSorting, + onPaginationChange: handleChangePagination, + manualSorting: true, + manualPagination: true + }); + + const success = !loading && !fetchError; + const error = !loading && fetchError; + + const getStatus = () => { + switch (true) { + case success: + return 'success'; + case !!error: + return 'error'; + case !!loading: + return 'loading'; + default: + return 'idle'; + } + }; + + useEffect(() => { + if (!loading && data?.meta.totalCount) setRowCount(data.meta.totalCount); + }, [loading, data?.meta.totalCount]); + + return { + table, + getStatus, + error + }; +}; diff --git a/src/utils/formatter.ts b/src/utils/formatter.ts index 3f2ff53..d1d57d9 100644 --- a/src/utils/formatter.ts +++ b/src/utils/formatter.ts @@ -80,3 +80,48 @@ export const formatOption = (option: string) => { return newSentence; }; + +/** + * Formats milliseconds into a human-readable duration string + * @param milliseconds - The duration in milliseconds (can be a string or BigInt from GraphQL) + * @returns Human-readable duration string (e.g., "1d 2h 3m 4s", "5m 30s", "500ms") + */ +export const formatDuration = ( + milliseconds: string | number | bigint +): string => { + let ms: number; + + // Convert to number if it's a string or BigInt + if (typeof milliseconds === 'string') { + ms = Number.parseInt(milliseconds, 10); + } else if (typeof milliseconds === 'bigint') { + ms = Number(milliseconds); + } else { + ms = milliseconds; + } + + if (Number.isNaN(ms) || ms < 0) { + return '0ms'; + } + + const SECOND = 1000; + const MINUTE = SECOND * 60; + const HOUR = MINUTE * 60; + const DAY = HOUR * 24; + + const days = Math.floor(ms / DAY); + const hours = Math.floor((ms % DAY) / HOUR); + const minutes = Math.floor((ms % HOUR) / MINUTE); + const seconds = Math.floor((ms % MINUTE) / SECOND); + const remainingMs = ms % SECOND; + + const parts: string[] = []; + + if (days > 0) parts.push(`${days}d`); + if (hours > 0) parts.push(`${hours}h`); + if (minutes > 0) parts.push(`${minutes}m`); + if (seconds > 0) parts.push(`${seconds}s`); + if (remainingMs > 0 && parts.length === 0) parts.push(`${remainingMs}ms`); + + return parts.length > 0 ? parts.join(' ') : '0ms'; +}; From 9fc33b4573ff5be63c44615c14d739d7f694ee58 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 13:13:33 +0800 Subject: [PATCH 04/11] feat: finish high security set details --- .../HighSecuritySetInformation.tsx | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/components/features/high-security-set-details/high-security-set-information/HighSecuritySetInformation.tsx diff --git a/src/components/features/high-security-set-details/high-security-set-information/HighSecuritySetInformation.tsx b/src/components/features/high-security-set-details/high-security-set-information/HighSecuritySetInformation.tsx new file mode 100644 index 0000000..1a21963 --- /dev/null +++ b/src/components/features/high-security-set-details/high-security-set-information/HighSecuritySetInformation.tsx @@ -0,0 +1,104 @@ +import { notFound } from '@tanstack/react-router'; +import * as React from 'react'; + +import useApiClient from '@/api'; +import { DataList } from '@/components/ui/composites/data-list/DataList'; +import { LinkWithCopy } from '@/components/ui/composites/link-with-copy/LinkWithCopy'; +import { TextWithCopy } from '@/components/ui/composites/text-with-copy/TextWithCopy'; +import { RESOURCES } from '@/constants/resources'; +import type { HighSecuritySetResponse } from '@/schemas'; +import { formatDuration, formatTimestamp } from '@/utils/formatter'; + +export interface HighSecuritySetInformationProps { + hash: string; +} + +type HighSecuritySet = HighSecuritySetResponse['highSecuritySets'][0]; + +export const HighSecuritySetInformation: React.FC< + HighSecuritySetInformationProps +> = ({ hash }) => { + const api = useApiClient(); + const { data, loading } = api.highSecuritySets.getByHash().useQuery(hash); + + if (!loading && (!data || data.highSecuritySets.length !== 1)) + throw notFound(); + + const highSecuritySet = data?.highSecuritySets[0]; + + const information: Partial[] = [ + { + extrinsicHash: highSecuritySet?.extrinsicHash, + block: highSecuritySet?.block, + timestamp: highSecuritySet?.timestamp, + who: highSecuritySet?.who, + interceptor: highSecuritySet?.interceptor, + delay: highSecuritySet?.delay + } + ]; + + return ( + > + loading={loading} + data={information} + fields={[ + { + label: 'Extrinsic Hash', + key: 'extrinsicHash', + render: (value) => ( + + ) + }, + { + label: 'Block', + key: 'block', + render: (value) => ( + + ) + }, + { + label: 'Timestamp', + key: 'timestamp', + render: (value) => formatTimestamp(value, true) + }, + { + label: 'Who', + key: 'who', + render: (value) => ( + + ) + }, + { + label: 'Interceptor', + key: 'interceptor', + render: (value) => ( + + ) + }, + { + label: 'Delay', + key: 'delay', + render: (value) => formatDuration(value as string | number | bigint) + } + ]} + /> + ); +}; From 933494c90643e5a115a11ec5e552b6b06d822495 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 13:16:46 +0800 Subject: [PATCH 05/11] feat: finish adding high security sets to landing --- .../features/landing/data-tabs/DataTabs.tsx | 7 ++- .../HighSecuritySetsTable.tsx | 17 +++++++ .../landing/high-security-sets-table/hook.tsx | 51 +++++++++++++++++++ .../RecentHighSecuritySets.tsx | 21 ++++++++ src/constants/resources.ts | 3 +- 5 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/components/features/landing/high-security-sets-table/HighSecuritySetsTable.tsx create mode 100644 src/components/features/landing/high-security-sets-table/hook.tsx create mode 100644 src/components/features/landing/recent-high-security-sets/RecentHighSecuritySets.tsx diff --git a/src/components/features/landing/data-tabs/DataTabs.tsx b/src/components/features/landing/data-tabs/DataTabs.tsx index 0b3a677..f2016c0 100644 --- a/src/components/features/landing/data-tabs/DataTabs.tsx +++ b/src/components/features/landing/data-tabs/DataTabs.tsx @@ -14,6 +14,7 @@ import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { formatOption } from '@/utils/formatter'; import { RecentBlocks } from '../recent-blocks/RecentBlocks'; +import { RecentHighSecuritySets } from '../recent-high-security-sets/RecentHighSecuritySets'; import { RecentMinerRewards } from '../recent-miner-rewards/RecentMinerRewards'; import { RecentReversibleTransactions } from '../recent-reversible-transactions/RecentReversibleTransactions'; import { RecentTransactions } from '../recent-transactions/RecentTransactions'; @@ -24,7 +25,8 @@ const TAB_OPTIONS = { immediate: 'immediate-transactions', reversible: 'reversible-transactions', blocks: 'blocks', - miners: 'miner-rewards' + miners: 'miner-rewards', + highSecuritySets: 'high-security-sets' } as const; const TAB_LIST = Object.values(TAB_OPTIONS); @@ -73,6 +75,9 @@ export const DataTabs: React.FC = () => { + + + diff --git a/src/components/features/landing/high-security-sets-table/HighSecuritySetsTable.tsx b/src/components/features/landing/high-security-sets-table/HighSecuritySetsTable.tsx new file mode 100644 index 0000000..1427281 --- /dev/null +++ b/src/components/features/landing/high-security-sets-table/HighSecuritySetsTable.tsx @@ -0,0 +1,17 @@ +import { DataTable } from '@/components/ui/composites/data-table/DataTable'; + +import { useHighSecuritySetsTable } from './hook'; + +export const HighSecuritySetsTable = () => { + const { getStatus, table, error } = useHighSecuritySetsTable(); + + return ( + Error : {error && error.message}

+ }} + /> + ); +}; diff --git a/src/components/features/landing/high-security-sets-table/hook.tsx b/src/components/features/landing/high-security-sets-table/hook.tsx new file mode 100644 index 0000000..c63cc09 --- /dev/null +++ b/src/components/features/landing/high-security-sets-table/hook.tsx @@ -0,0 +1,51 @@ +import { getCoreRowModel, useReactTable } from '@tanstack/react-table'; +import { useMemo } from 'react'; + +import useApiClient from '@/api'; +import { HIGH_SECURITY_SET_COLUMNS } from '@/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS'; +import { DATA_POOL_INTERVAL } from '@/constants/data-pool-interval'; +import type { HighSecuritySet } from '@/schemas'; + +export const useHighSecuritySetsTable = () => { + const api = useApiClient(); + const { + loading, + data, + error: fetchError + } = api.highSecuritySets.useGetRecent({ + pollInterval: DATA_POOL_INTERVAL + }); + const highSecuritySetColumns = useMemo(() => HIGH_SECURITY_SET_COLUMNS, []); + + const table = useReactTable({ + data: data?.highSecuritySets ?? [], + columns: highSecuritySetColumns, + getCoreRowModel: getCoreRowModel(), + enableSorting: false, + rowCount: data?.highSecuritySets?.length ?? 0, + manualPagination: true, + manualSorting: true + }); + + const success = !loading && !fetchError; + const error = !loading && fetchError; + + const getStatus = () => { + switch (true) { + case success: + return 'success'; + case !!error: + return 'error'; + case !!loading: + return 'loading'; + default: + return 'idle'; + } + }; + + return { + table, + getStatus, + error + }; +}; diff --git a/src/components/features/landing/recent-high-security-sets/RecentHighSecuritySets.tsx b/src/components/features/landing/recent-high-security-sets/RecentHighSecuritySets.tsx new file mode 100644 index 0000000..d38e4d5 --- /dev/null +++ b/src/components/features/landing/recent-high-security-sets/RecentHighSecuritySets.tsx @@ -0,0 +1,21 @@ +import { Link } from '@tanstack/react-router'; + +import { Button } from '@/components/ui/button'; +import { ContentContainer } from '@/components/ui/content-container'; +import { RESOURCES } from '@/constants/resources'; + +import { HighSecuritySetsTable } from '../high-security-sets-table/HighSecuritySetsTable'; + +export const RecentHighSecuritySets = () => { + return ( + +

Recent High Security Sets

+ + + + +
+ ); +}; diff --git a/src/constants/resources.ts b/src/constants/resources.ts index 9162dc8..b34e986 100644 --- a/src/constants/resources.ts +++ b/src/constants/resources.ts @@ -3,5 +3,6 @@ export const RESOURCES = { reversibleTransactions: '/reversible-transactions', accounts: '/accounts', blocks: '/blocks', - minerRewards: '/miner-rewards' + minerRewards: '/miner-rewards', + highSecuritySets: '/high-security-sets' } as const; From bbe5cb800149c3a87d9968c954fd585c60310696 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 13:24:43 +0800 Subject: [PATCH 06/11] feat: add high security to navbar --- src/config/site-navigations.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/config/site-navigations.ts b/src/config/site-navigations.ts index d8ce809..c43d95c 100644 --- a/src/config/site-navigations.ts +++ b/src/config/site-navigations.ts @@ -43,8 +43,18 @@ export const SITE_NAVIGATIONS: (SiteNavigation | ParentNavigation)[] = [ }, { label: 'Accounts', - path: '/accounts', - longLabel: 'Accounts' + children: [ + { + label: 'Accounts', + path: '/accounts', + longLabel: 'Accounts' + }, + { + label: 'High Security Sets', + path: '/high-security-sets', + longLabel: 'High Security Sets' + } + ] }, { label: 'Blocks', From 2c421b186b1d8889ce351ff8dda86fc3a09e2f29 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 15:10:34 +0800 Subject: [PATCH 07/11] feat: finish adding high security --- .../HIGH_SECURITY_SET_COLUMNS.tsx | 6 +-- .../HighSecuritySetInformation.tsx | 9 ++-- src/routeTree.gen.ts | 42 +++++++++++++++++++ src/routes/high-security-sets/$hash.tsx | 25 +++++++++++ src/routes/high-security-sets/index.tsx | 27 ++++++++++++ 5 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 src/routes/high-security-sets/$hash.tsx create mode 100644 src/routes/high-security-sets/index.tsx diff --git a/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx b/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx index 41ca94e..1b826b3 100644 --- a/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx +++ b/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx @@ -15,7 +15,7 @@ export const HIGH_SECURITY_SET_COLUMNS = [ cell: (props) => props.getValue() ? ( @@ -43,7 +43,7 @@ export const HIGH_SECURITY_SET_COLUMNS = [ }), columnHelper.accessor('who.id', { id: 'who', - header: 'Who', + header: 'Beneficiary', cell: (props) => ( ( formatTimestamp(value, true) }, { - label: 'Who', + label: 'Beneficiary', + tooltip: 'The account that set the high security feature', key: 'who', render: (value) => ( ( formatDuration(value as string | number | bigint) } diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index 0b6ca18..5ce4779 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -14,11 +14,13 @@ import { Route as ReversibleTransactionsIndexRouteImport } from './routes/revers import { Route as MinerRewardsIndexRouteImport } from './routes/miner-rewards/index' import { Route as MinerLeaderboardIndexRouteImport } from './routes/miner-leaderboard/index' import { Route as ImmediateTransactionsIndexRouteImport } from './routes/immediate-transactions/index' +import { Route as HighSecuritySetsIndexRouteImport } from './routes/high-security-sets/index' import { Route as BlocksIndexRouteImport } from './routes/blocks/index' import { Route as AccountsIndexRouteImport } from './routes/accounts/index' import { Route as ReversibleTransactionsHashRouteImport } from './routes/reversible-transactions/$hash' import { Route as MinerRewardsHashRouteImport } from './routes/miner-rewards/$hash' import { Route as ImmediateTransactionsHashRouteImport } from './routes/immediate-transactions/$hash' +import { Route as HighSecuritySetsHashRouteImport } from './routes/high-security-sets/$hash' import { Route as BlocksIdRouteImport } from './routes/blocks/$id' import { Route as AccountsIdRouteImport } from './routes/accounts/$id' @@ -49,6 +51,11 @@ const ImmediateTransactionsIndexRoute = path: '/immediate-transactions/', getParentRoute: () => rootRouteImport, } as any) +const HighSecuritySetsIndexRoute = HighSecuritySetsIndexRouteImport.update({ + id: '/high-security-sets/', + path: '/high-security-sets/', + getParentRoute: () => rootRouteImport, +} as any) const BlocksIndexRoute = BlocksIndexRouteImport.update({ id: '/blocks/', path: '/blocks/', @@ -76,6 +83,11 @@ const ImmediateTransactionsHashRoute = path: '/immediate-transactions/$hash', getParentRoute: () => rootRouteImport, } as any) +const HighSecuritySetsHashRoute = HighSecuritySetsHashRouteImport.update({ + id: '/high-security-sets/$hash', + path: '/high-security-sets/$hash', + getParentRoute: () => rootRouteImport, +} as any) const BlocksIdRoute = BlocksIdRouteImport.update({ id: '/blocks/$id', path: '/blocks/$id', @@ -91,11 +103,13 @@ export interface FileRoutesByFullPath { '/': typeof IndexRoute '/accounts/$id': typeof AccountsIdRoute '/blocks/$id': typeof BlocksIdRoute + '/high-security-sets/$hash': typeof HighSecuritySetsHashRoute '/immediate-transactions/$hash': typeof ImmediateTransactionsHashRoute '/miner-rewards/$hash': typeof MinerRewardsHashRoute '/reversible-transactions/$hash': typeof ReversibleTransactionsHashRoute '/accounts': typeof AccountsIndexRoute '/blocks': typeof BlocksIndexRoute + '/high-security-sets': typeof HighSecuritySetsIndexRoute '/immediate-transactions': typeof ImmediateTransactionsIndexRoute '/miner-leaderboard': typeof MinerLeaderboardIndexRoute '/miner-rewards': typeof MinerRewardsIndexRoute @@ -105,11 +119,13 @@ export interface FileRoutesByTo { '/': typeof IndexRoute '/accounts/$id': typeof AccountsIdRoute '/blocks/$id': typeof BlocksIdRoute + '/high-security-sets/$hash': typeof HighSecuritySetsHashRoute '/immediate-transactions/$hash': typeof ImmediateTransactionsHashRoute '/miner-rewards/$hash': typeof MinerRewardsHashRoute '/reversible-transactions/$hash': typeof ReversibleTransactionsHashRoute '/accounts': typeof AccountsIndexRoute '/blocks': typeof BlocksIndexRoute + '/high-security-sets': typeof HighSecuritySetsIndexRoute '/immediate-transactions': typeof ImmediateTransactionsIndexRoute '/miner-leaderboard': typeof MinerLeaderboardIndexRoute '/miner-rewards': typeof MinerRewardsIndexRoute @@ -120,11 +136,13 @@ export interface FileRoutesById { '/': typeof IndexRoute '/accounts/$id': typeof AccountsIdRoute '/blocks/$id': typeof BlocksIdRoute + '/high-security-sets/$hash': typeof HighSecuritySetsHashRoute '/immediate-transactions/$hash': typeof ImmediateTransactionsHashRoute '/miner-rewards/$hash': typeof MinerRewardsHashRoute '/reversible-transactions/$hash': typeof ReversibleTransactionsHashRoute '/accounts/': typeof AccountsIndexRoute '/blocks/': typeof BlocksIndexRoute + '/high-security-sets/': typeof HighSecuritySetsIndexRoute '/immediate-transactions/': typeof ImmediateTransactionsIndexRoute '/miner-leaderboard/': typeof MinerLeaderboardIndexRoute '/miner-rewards/': typeof MinerRewardsIndexRoute @@ -136,11 +154,13 @@ export interface FileRouteTypes { | '/' | '/accounts/$id' | '/blocks/$id' + | '/high-security-sets/$hash' | '/immediate-transactions/$hash' | '/miner-rewards/$hash' | '/reversible-transactions/$hash' | '/accounts' | '/blocks' + | '/high-security-sets' | '/immediate-transactions' | '/miner-leaderboard' | '/miner-rewards' @@ -150,11 +170,13 @@ export interface FileRouteTypes { | '/' | '/accounts/$id' | '/blocks/$id' + | '/high-security-sets/$hash' | '/immediate-transactions/$hash' | '/miner-rewards/$hash' | '/reversible-transactions/$hash' | '/accounts' | '/blocks' + | '/high-security-sets' | '/immediate-transactions' | '/miner-leaderboard' | '/miner-rewards' @@ -164,11 +186,13 @@ export interface FileRouteTypes { | '/' | '/accounts/$id' | '/blocks/$id' + | '/high-security-sets/$hash' | '/immediate-transactions/$hash' | '/miner-rewards/$hash' | '/reversible-transactions/$hash' | '/accounts/' | '/blocks/' + | '/high-security-sets/' | '/immediate-transactions/' | '/miner-leaderboard/' | '/miner-rewards/' @@ -179,11 +203,13 @@ export interface RootRouteChildren { IndexRoute: typeof IndexRoute AccountsIdRoute: typeof AccountsIdRoute BlocksIdRoute: typeof BlocksIdRoute + HighSecuritySetsHashRoute: typeof HighSecuritySetsHashRoute ImmediateTransactionsHashRoute: typeof ImmediateTransactionsHashRoute MinerRewardsHashRoute: typeof MinerRewardsHashRoute ReversibleTransactionsHashRoute: typeof ReversibleTransactionsHashRoute AccountsIndexRoute: typeof AccountsIndexRoute BlocksIndexRoute: typeof BlocksIndexRoute + HighSecuritySetsIndexRoute: typeof HighSecuritySetsIndexRoute ImmediateTransactionsIndexRoute: typeof ImmediateTransactionsIndexRoute MinerLeaderboardIndexRoute: typeof MinerLeaderboardIndexRoute MinerRewardsIndexRoute: typeof MinerRewardsIndexRoute @@ -227,6 +253,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ImmediateTransactionsIndexRouteImport parentRoute: typeof rootRouteImport } + '/high-security-sets/': { + id: '/high-security-sets/' + path: '/high-security-sets' + fullPath: '/high-security-sets' + preLoaderRoute: typeof HighSecuritySetsIndexRouteImport + parentRoute: typeof rootRouteImport + } '/blocks/': { id: '/blocks/' path: '/blocks' @@ -262,6 +295,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ImmediateTransactionsHashRouteImport parentRoute: typeof rootRouteImport } + '/high-security-sets/$hash': { + id: '/high-security-sets/$hash' + path: '/high-security-sets/$hash' + fullPath: '/high-security-sets/$hash' + preLoaderRoute: typeof HighSecuritySetsHashRouteImport + parentRoute: typeof rootRouteImport + } '/blocks/$id': { id: '/blocks/$id' path: '/blocks/$id' @@ -283,11 +323,13 @@ const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, AccountsIdRoute: AccountsIdRoute, BlocksIdRoute: BlocksIdRoute, + HighSecuritySetsHashRoute: HighSecuritySetsHashRoute, ImmediateTransactionsHashRoute: ImmediateTransactionsHashRoute, MinerRewardsHashRoute: MinerRewardsHashRoute, ReversibleTransactionsHashRoute: ReversibleTransactionsHashRoute, AccountsIndexRoute: AccountsIndexRoute, BlocksIndexRoute: BlocksIndexRoute, + HighSecuritySetsIndexRoute: HighSecuritySetsIndexRoute, ImmediateTransactionsIndexRoute: ImmediateTransactionsIndexRoute, MinerLeaderboardIndexRoute: MinerLeaderboardIndexRoute, MinerRewardsIndexRoute: MinerRewardsIndexRoute, diff --git a/src/routes/high-security-sets/$hash.tsx b/src/routes/high-security-sets/$hash.tsx new file mode 100644 index 0000000..75fdd49 --- /dev/null +++ b/src/routes/high-security-sets/$hash.tsx @@ -0,0 +1,25 @@ +import { createFileRoute } from '@tanstack/react-router'; +import * as React from 'react'; + +import { HighSecuritySetInformation } from '@/components/features/high-security-set-details/high-security-set-information/HighSecuritySetInformation'; +import { ContentContainer } from '@/components/ui/content-container'; +import { SectionContainer } from '@/components/ui/section-container'; + +export const Route = createFileRoute('/high-security-sets/$hash')({ + component: HighSecuritySetDetails +}); +function HighSecuritySetDetails() { + const { hash } = Route.useParams(); + + return ( + + +

High Security Set Details

+ + +
+
+ ); +} + +export default HighSecuritySetDetails; diff --git a/src/routes/high-security-sets/index.tsx b/src/routes/high-security-sets/index.tsx new file mode 100644 index 0000000..6992fb2 --- /dev/null +++ b/src/routes/high-security-sets/index.tsx @@ -0,0 +1,27 @@ +import { createFileRoute } from '@tanstack/react-router'; + +import { HighSecuritySetsHeading } from '@/components/features/high-security-sets-listing/high-security-sets-heading/HighSecuritySetsHeading'; +import { HighSecuritySetsStats } from '@/components/features/high-security-sets-listing/high-security-sets-stats/HighSecuritySetsStats'; +import { HighSecuritySetsTable } from '@/components/features/high-security-sets-listing/high-security-sets-table/HighSecuritySetsTable'; +import { ContentContainer } from '@/components/ui/content-container'; +import { SectionContainer } from '@/components/ui/section-container'; + +export const Route = createFileRoute('/high-security-sets/')({ + component: HighSecuritySets +}); + +function HighSecuritySets() { + return ( + + + + + + + + + + ); +} + +export default HighSecuritySets; From 6b69eb9bff4631b33a834f0772c05de37169fce0 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 15:23:46 +0800 Subject: [PATCH 08/11] feat: add high security to search --- src/api/search.tsx | 6 ++++++ .../HIGH_SECURITY_SET_COLUMNS.tsx | 2 +- .../HighSecuritySetInformation.tsx | 3 ++- .../search-preview/SearchPreview.tsx | 21 +++++++++++++++++-- src/schemas/searchs.ts | 2 ++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/api/search.tsx b/src/api/search.tsx index 257a7b1..3218ac9 100644 --- a/src/api/search.tsx +++ b/src/api/search.tsx @@ -34,6 +34,12 @@ export const search = (fetcher: DataFetcher) => ({ ) { height } + highSecuritySets( + limit: $limit + where: { extrinsicHash_startsWith: $keyword } + ) { + extrinsicHash + } minerRewards( limit: $limit where: { block: { hash_startsWith: $keyword } } diff --git a/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx b/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx index 1b826b3..faf4b1e 100644 --- a/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx +++ b/src/components/common/table-columns/HIGH_SECURITY_SET_COLUMNS.tsx @@ -67,7 +67,7 @@ export const HIGH_SECURITY_SET_COLUMNS = [ }), columnHelper.accessor('delay', { id: 'delay', - header: 'Delay', + header: 'Reversible Time', cell: (props) => formatDuration(props.getValue()), enableSorting: true }) diff --git a/src/components/features/high-security-set-details/high-security-set-information/HighSecuritySetInformation.tsx b/src/components/features/high-security-set-details/high-security-set-information/HighSecuritySetInformation.tsx index fda9aa6..41ebb55 100644 --- a/src/components/features/high-security-set-details/high-security-set-information/HighSecuritySetInformation.tsx +++ b/src/components/features/high-security-set-details/high-security-set-information/HighSecuritySetInformation.tsx @@ -97,7 +97,8 @@ export const HighSecuritySetInformation: React.FC< }, { label: 'Reversible Time', - tooltip: 'The time period to confirm the reversible transaction', + tooltip: + 'The enforced time period to confirm the reversible transaction', key: 'delay', render: (value) => formatDuration(value as string | number | bigint) } diff --git a/src/components/ui/composites/search-preview/SearchPreview.tsx b/src/components/ui/composites/search-preview/SearchPreview.tsx index 09fc728..83467e6 100644 --- a/src/components/ui/composites/search-preview/SearchPreview.tsx +++ b/src/components/ui/composites/search-preview/SearchPreview.tsx @@ -104,7 +104,8 @@ export const SearchPreview = forwardRef( transactions, blocks, reversibleTransactions, - minerRewards + minerRewards, + highSecuritySets } = searchResult || {}; if ( @@ -113,7 +114,8 @@ export const SearchPreview = forwardRef( !blocks && !minerRewards && !accounts && - !reversibleTransactions + !reversibleTransactions && + !highSecuritySets ) { return null; } @@ -204,6 +206,21 @@ export const SearchPreview = forwardRef( /> )} /> + + {/* High Security Sets */} +
( + + )} + /> diff --git a/src/schemas/searchs.ts b/src/schemas/searchs.ts index a364a9f..e4ac172 100644 --- a/src/schemas/searchs.ts +++ b/src/schemas/searchs.ts @@ -1,5 +1,6 @@ import type { Account } from './account'; import type { Block } from './blocks'; +import type { HighSecuritySet } from './high-security-set'; import type { MinerReward } from './miner-reward'; import type { ReversibleTransaction } from './reversible-transaction'; import type { Transaction } from './transcation'; @@ -9,5 +10,6 @@ export interface SearchAllResponse { reversibleTransactions: Pick[]; accounts: Pick[]; blocks: Pick[]; + highSecuritySets: Pick[]; minerRewards: Pick[]; } From 8f0170ad8629aa799754a2f40c1fce8f37aa5076 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 15:43:51 +0800 Subject: [PATCH 09/11] feat: add high security status to account details --- src/api/accounts.tsx | 48 +++++++++++++++++++ .../AccountInformation.tsx | 24 +++++++++- src/schemas/account.ts | 15 ++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/api/accounts.tsx b/src/api/accounts.tsx index 10942b3..ea428f0 100644 --- a/src/api/accounts.tsx +++ b/src/api/accounts.tsx @@ -132,6 +132,54 @@ export const accounts = { } } + totalCount + } + beneficiaryHighSecuritySets: highSecuritySetsConnection( + orderBy: timestamp_DESC + first: $limit + where: { who: { id_eq: $id } } + ) { + edges { + node { + extrinsicHash + who { + id + } + interceptor { + id + } + timestamp + delay + block { + height + } + } + } + + totalCount + } + guardianHighSecuritySets: highSecuritySetsConnection( + orderBy: timestamp_DESC + first: $limit + where: { interceptor: { id_eq: $id } } + ) { + edges { + node { + extrinsicHash + who { + id + } + interceptor { + id + } + timestamp + delay + block { + height + } + } + } + totalCount } } diff --git a/src/components/features/account-details/account-information/AccountInformation.tsx b/src/components/features/account-details/account-information/AccountInformation.tsx index 8516351..db965c6 100644 --- a/src/components/features/account-details/account-information/AccountInformation.tsx +++ b/src/components/features/account-details/account-information/AccountInformation.tsx @@ -1,4 +1,5 @@ import type { QueryResult } from '@apollo/client'; +import { Check, X } from 'lucide-react'; import * as React from 'react'; import { DataList } from '@/components/ui/composites/data-list/DataList'; @@ -26,6 +27,9 @@ export const AccountInformation: React.FC = ({ ); const transactions = data?.transactions.totalCount; const reversibleTransactions = data?.reversibleTransactions.totalCount; + const beneficiaryHighSecuritySets = + data?.beneficiaryHighSecuritySets.totalCount; + const guardianHighSecuritySets = data?.guardianHighSecuritySets.totalCount; const information = [ { @@ -35,7 +39,10 @@ export const AccountInformation: React.FC = ({ reserved: account?.reserved ?? 0, transactions, reversibleTransactions, - checksum + checksum, + isHighSecurity: + beneficiaryHighSecuritySets && beneficiaryHighSecuritySets > 0, + isGuardian: guardianHighSecuritySets && guardianHighSecuritySets > 0 } ]; @@ -61,6 +68,21 @@ export const AccountInformation: React.FC = ({ ) }, + { + label: 'Is High Security', + key: 'isHighSecurity', + tooltip: + 'Whether the account is a beneficiary of a high security set', + render: (value) => + value ? : + }, + { + label: 'Is Guardian', + key: 'isGuardian', + tooltip: 'Whether the account is a guardian of a high security set', + render: (value) => + value ? : + }, { label: 'Free Balance', key: 'free', diff --git a/src/schemas/account.ts b/src/schemas/account.ts index ce7bcba..0728053 100644 --- a/src/schemas/account.ts +++ b/src/schemas/account.ts @@ -1,4 +1,5 @@ import type * as gql from '../__generated__/graphql'; +import type { HighSecuritySet } from './high-security-set'; import type { MinerReward } from './miner-reward'; import type { ReversibleTransaction } from './reversible-transaction'; import type { Transaction } from './transcation'; @@ -23,6 +24,16 @@ export interface AccountResponse { /** @description the grand total of the reversible transactions regardless of the return node limit using `first` parameter */ totalCount: number; }; + beneficiaryHighSecuritySets: { + edges: AccountHighSecuritySet[]; + /** @description the grand total of the beneficiary high security sets regardless of the return node limit using `first` parameter */ + totalCount: number; + }; + guardianHighSecuritySets: { + edges: AccountHighSecuritySet[]; + /** @description the grand total of the guardian high security sets regardless of the return node limit using `first` parameter */ + totalCount: number; + }; } export interface AccountListResponse { @@ -44,6 +55,10 @@ export interface AccountReversibleTransaction { node: ReversibleTransaction; } +export interface AccountHighSecuritySet { + node: HighSecuritySet; +} + export interface AccountStatsResponse { all: { totalCount: number; From 33eb15ab28629509f671d02bb0d80074e17ed6bc Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 15:52:23 +0800 Subject: [PATCH 10/11] feat: add mining rewards to account details --- .../account-information/AccountInformation.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/features/account-details/account-information/AccountInformation.tsx b/src/components/features/account-details/account-information/AccountInformation.tsx index db965c6..53725e1 100644 --- a/src/components/features/account-details/account-information/AccountInformation.tsx +++ b/src/components/features/account-details/account-information/AccountInformation.tsx @@ -27,6 +27,7 @@ export const AccountInformation: React.FC = ({ ); const transactions = data?.transactions.totalCount; const reversibleTransactions = data?.reversibleTransactions.totalCount; + const miningRewards = data?.minerRewards.totalCount; const beneficiaryHighSecuritySets = data?.beneficiaryHighSecuritySets.totalCount; const guardianHighSecuritySets = data?.guardianHighSecuritySets.totalCount; @@ -39,6 +40,7 @@ export const AccountInformation: React.FC = ({ reserved: account?.reserved ?? 0, transactions, reversibleTransactions, + miningRewards, checksum, isHighSecurity: beneficiaryHighSecuritySets && beneficiaryHighSecuritySets > 0, @@ -113,6 +115,12 @@ export const AccountInformation: React.FC = ({ key: 'reversibleTransactions', render: (value) => value > 1 ? `${value} transactions` : `${value} transaction` + }, + { + label: 'Mining Rewards', + key: 'miningRewards', + render: (value) => + value > 1 ? `${value} rewards` : `${value} reward` } ]} /> From 709627407c0cea9ddeeaf77e022e8b1525a735b3 Mon Sep 17 00:00:00 2001 From: Beast Date: Tue, 20 Jan 2026 16:21:58 +0800 Subject: [PATCH 11/11] feat: add linking to account details for high security event --- src/api/accounts.tsx | 28 ++++------- .../ACCOUNT_BENEFICIARIES_COLUMNS.tsx | 40 ++++++++++++++++ .../ACCOUNT_GUARDIAN_COLUMNS.tsx | 40 ++++++++++++++++ .../AccountBeneficiaries.tsx | 42 +++++++++++++++++ .../account-beneficiaries/hook.tsx | 47 +++++++++++++++++++ .../account-data-tabs/AccountDataTabs.tsx | 12 ++++- .../account-guardian/AccountGuardian.tsx | 42 +++++++++++++++++ .../account-details/account-guardian/hook.tsx | 45 ++++++++++++++++++ .../AccountInformation.tsx | 10 ++-- .../account-miner-rewards/hook.tsx | 13 +++-- .../account-reversible-transactions/hook.tsx | 13 +++-- .../account-transactions/hook.tsx | 13 +++-- src/schemas/account.ts | 21 ++++++--- 13 files changed, 320 insertions(+), 46 deletions(-) create mode 100644 src/components/common/table-columns/ACCOUNT_BENEFICIARIES_COLUMNS.tsx create mode 100644 src/components/common/table-columns/ACCOUNT_GUARDIAN_COLUMNS.tsx create mode 100644 src/components/features/account-details/account-beneficiaries/AccountBeneficiaries.tsx create mode 100644 src/components/features/account-details/account-beneficiaries/hook.tsx create mode 100644 src/components/features/account-details/account-guardian/AccountGuardian.tsx create mode 100644 src/components/features/account-details/account-guardian/hook.tsx diff --git a/src/api/accounts.tsx b/src/api/accounts.tsx index ea428f0..01cc229 100644 --- a/src/api/accounts.tsx +++ b/src/api/accounts.tsx @@ -134,48 +134,36 @@ export const accounts = { totalCount } - beneficiaryHighSecuritySets: highSecuritySetsConnection( + guardian: highSecuritySetsConnection( orderBy: timestamp_DESC first: $limit where: { who: { id_eq: $id } } ) { edges { node { - extrinsicHash - who { - id - } interceptor { id - } - timestamp - delay - block { - height + free + frozen + reserved } } } totalCount } - guardianHighSecuritySets: highSecuritySetsConnection( + beneficiaries: highSecuritySetsConnection( orderBy: timestamp_DESC first: $limit where: { interceptor: { id_eq: $id } } ) { edges { node { - extrinsicHash who { id - } - interceptor { - id - } - timestamp - delay - block { - height + free + frozen + reserved } } } diff --git a/src/components/common/table-columns/ACCOUNT_BENEFICIARIES_COLUMNS.tsx b/src/components/common/table-columns/ACCOUNT_BENEFICIARIES_COLUMNS.tsx new file mode 100644 index 0000000..cf9ff2d --- /dev/null +++ b/src/components/common/table-columns/ACCOUNT_BENEFICIARIES_COLUMNS.tsx @@ -0,0 +1,40 @@ +import { createColumnHelper } from '@tanstack/react-table'; + +import { LinkWithCopy } from '@/components/ui/composites/link-with-copy/LinkWithCopy'; +import { RESOURCES } from '@/constants/resources'; +import type { AccountBeneficiary } from '@/schemas'; +import { formatMonetaryValue } from '@/utils/formatter'; + +const columnHelper = createColumnHelper(); + +export const ACCOUNT_BENEFICIARIES_COLUMNS = [ + columnHelper.accessor('node.who.id', { + id: 'id', + header: 'Identity', + cell: (props) => ( + + ), + enableSorting: false + }), + columnHelper.accessor('node.who.free', { + id: 'free', + header: 'Free', + cell: (props) => formatMonetaryValue(props.getValue(), 5), + enableSorting: true + }), + columnHelper.accessor('node.who.frozen', { + id: 'frozen', + header: 'Frozen', + cell: (props) => formatMonetaryValue(props.getValue(), 5), + enableSorting: true + }), + columnHelper.accessor('node.who.reserved', { + id: 'reserved', + header: 'Reserved', + cell: (props) => formatMonetaryValue(props.getValue(), 5), + enableSorting: true + }) +]; diff --git a/src/components/common/table-columns/ACCOUNT_GUARDIAN_COLUMNS.tsx b/src/components/common/table-columns/ACCOUNT_GUARDIAN_COLUMNS.tsx new file mode 100644 index 0000000..4ec5222 --- /dev/null +++ b/src/components/common/table-columns/ACCOUNT_GUARDIAN_COLUMNS.tsx @@ -0,0 +1,40 @@ +import { createColumnHelper } from '@tanstack/react-table'; + +import { LinkWithCopy } from '@/components/ui/composites/link-with-copy/LinkWithCopy'; +import { RESOURCES } from '@/constants/resources'; +import type { AccountGuardian } from '@/schemas'; +import { formatMonetaryValue } from '@/utils/formatter'; + +const columnHelper = createColumnHelper(); + +export const ACCOUNT_GUARDIAN_COLUMNS = [ + columnHelper.accessor('node.interceptor.id', { + id: 'id', + header: 'Identity', + cell: (props) => ( + + ), + enableSorting: false + }), + columnHelper.accessor('node.interceptor.free', { + id: 'free', + header: 'Free', + cell: (props) => formatMonetaryValue(props.getValue(), 5), + enableSorting: true + }), + columnHelper.accessor('node.interceptor.frozen', { + id: 'frozen', + header: 'Frozen', + cell: (props) => formatMonetaryValue(props.getValue(), 5), + enableSorting: true + }), + columnHelper.accessor('node.interceptor.reserved', { + id: 'reserved', + header: 'Reserved', + cell: (props) => formatMonetaryValue(props.getValue(), 5), + enableSorting: true + }) +]; diff --git a/src/components/features/account-details/account-beneficiaries/AccountBeneficiaries.tsx b/src/components/features/account-details/account-beneficiaries/AccountBeneficiaries.tsx new file mode 100644 index 0000000..5bfba36 --- /dev/null +++ b/src/components/features/account-details/account-beneficiaries/AccountBeneficiaries.tsx @@ -0,0 +1,42 @@ +import type { QueryResult } from '@apollo/client'; +import { Link } from '@tanstack/react-router'; +import React from 'react'; + +import { Button } from '@/components/ui/button'; +import { DataTable } from '@/components/ui/composites/data-table/DataTable'; +import { ContentContainer } from '@/components/ui/content-container'; +import { RESOURCES } from '@/constants/resources'; +import type { AccountResponse } from '@/schemas'; + +import { useAccountBeneficiaries } from './hook'; + +interface Props { + query: QueryResult; + accountId: string; +} + +export const AccountBeneficiaries: React.FC = ({ query, accountId }) => { + const { getStatus, table, error } = useAccountBeneficiaries(query); + + return ( + +

Beneficiary Accounts

+ + Error: {error && error.message}

+ }} + /> + + {!query.loading && query.data?.beneficiaries.totalCount !== 0 && ( + + )} +
+ ); +}; diff --git a/src/components/features/account-details/account-beneficiaries/hook.tsx b/src/components/features/account-details/account-beneficiaries/hook.tsx new file mode 100644 index 0000000..71f8158 --- /dev/null +++ b/src/components/features/account-details/account-beneficiaries/hook.tsx @@ -0,0 +1,47 @@ +import type { QueryResult } from '@apollo/client'; +import { getCoreRowModel, useReactTable } from '@tanstack/react-table'; +import { useCallback, useMemo } from 'react'; + +import { ACCOUNT_BENEFICIARIES_COLUMNS } from '@/components/common/table-columns/ACCOUNT_BENEFICIARIES_COLUMNS'; +import type { AccountBeneficiary, AccountResponse } from '@/schemas'; + +export const useAccountBeneficiaries = ( + query: QueryResult +) => { + const { data, error: fetchError, loading } = query; + const beneficiariesColumns = useMemo(() => ACCOUNT_BENEFICIARIES_COLUMNS, []); + + const tableData = useMemo( + () => data?.beneficiaries?.edges ?? [], + [data?.beneficiaries?.edges] + ); + + const table = useReactTable({ + data: tableData, + columns: beneficiariesColumns, + getCoreRowModel: getCoreRowModel(), + enableSorting: false + }); + + const success = !loading && !fetchError; + const error = !loading && fetchError; + + const getStatus = useCallback(() => { + switch (true) { + case success: + return 'success'; + case !!error: + return 'error'; + case !!loading: + return 'loading'; + default: + return 'idle'; + } + }, [success, error, loading]); + + return { + table, + getStatus, + error + }; +}; diff --git a/src/components/features/account-details/account-data-tabs/AccountDataTabs.tsx b/src/components/features/account-details/account-data-tabs/AccountDataTabs.tsx index a6a8890..9bb6e3d 100644 --- a/src/components/features/account-details/account-data-tabs/AccountDataTabs.tsx +++ b/src/components/features/account-details/account-data-tabs/AccountDataTabs.tsx @@ -14,6 +14,8 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import type { AccountResponse } from '@/schemas'; import { formatOption } from '@/utils/formatter'; +import { AccountBeneficiaries } from '../account-beneficiaries/AccountBeneficiaries'; +import { AccountGuardian } from '../account-guardian/AccountGuardian'; import { AccountMinerRewards } from '../account-miner-rewards/AccountMinerRewards'; import { AccountReversibleTransactions } from '../account-reversible-transactions/AccountReversibleTransactions'; import { AccountTransactions } from '../account-transactions/AccountTransactions'; @@ -26,7 +28,9 @@ export interface AccountDataTabsProps { const TAB_OPTIONS = { immediate: 'immediate-transactions', reversible: 'reversible-transactions', - miners: 'miner-rewards' + miners: 'miner-rewards', + guardian: 'guardian', + beneficiaries: 'beneficiaries' } as const; const TAB_LIST = Object.values(TAB_OPTIONS); @@ -78,6 +82,12 @@ export const AccountDataTabs: React.FC = ({ + + + + + + diff --git a/src/components/features/account-details/account-guardian/AccountGuardian.tsx b/src/components/features/account-details/account-guardian/AccountGuardian.tsx new file mode 100644 index 0000000..41bd563 --- /dev/null +++ b/src/components/features/account-details/account-guardian/AccountGuardian.tsx @@ -0,0 +1,42 @@ +import type { QueryResult } from '@apollo/client'; +import { Link } from '@tanstack/react-router'; +import React from 'react'; + +import { Button } from '@/components/ui/button'; +import { DataTable } from '@/components/ui/composites/data-table/DataTable'; +import { ContentContainer } from '@/components/ui/content-container'; +import { RESOURCES } from '@/constants/resources'; +import type { AccountResponse } from '@/schemas'; + +import { useAccountGuardian } from './hook'; + +interface Props { + query: QueryResult; + accountId: string; +} + +export const AccountGuardian: React.FC = ({ query, accountId }) => { + const { getStatus, table, error } = useAccountGuardian(query); + + return ( + +

Guardian Account

+ + Error: {error && error.message}

+ }} + /> + + {!query.loading && query.data?.guardian.totalCount !== 0 && ( + + )} +
+ ); +}; diff --git a/src/components/features/account-details/account-guardian/hook.tsx b/src/components/features/account-details/account-guardian/hook.tsx new file mode 100644 index 0000000..3a1cdef --- /dev/null +++ b/src/components/features/account-details/account-guardian/hook.tsx @@ -0,0 +1,45 @@ +import type { QueryResult } from '@apollo/client'; +import { getCoreRowModel, useReactTable } from '@tanstack/react-table'; +import { useCallback, useMemo } from 'react'; + +import { ACCOUNT_GUARDIAN_COLUMNS } from '@/components/common/table-columns/ACCOUNT_GUARDIAN_COLUMNS'; +import type { AccountGuardian, AccountResponse } from '@/schemas'; + +export const useAccountGuardian = (query: QueryResult) => { + const { data, error: fetchError, loading } = query; + const guardianColumns = useMemo(() => ACCOUNT_GUARDIAN_COLUMNS, []); + + const tableData = useMemo( + () => data?.guardian?.edges ?? [], + [data?.guardian?.edges] + ); + + const table = useReactTable({ + data: tableData, + columns: guardianColumns, + getCoreRowModel: getCoreRowModel(), + enableSorting: false + }); + + const success = !loading && !fetchError; + const error = !loading && fetchError; + + const getStatus = useCallback(() => { + switch (true) { + case success: + return 'success'; + case !!error: + return 'error'; + case !!loading: + return 'loading'; + default: + return 'idle'; + } + }, [success, error, loading]); + + return { + table, + getStatus, + error + }; +}; diff --git a/src/components/features/account-details/account-information/AccountInformation.tsx b/src/components/features/account-details/account-information/AccountInformation.tsx index 53725e1..26cf912 100644 --- a/src/components/features/account-details/account-information/AccountInformation.tsx +++ b/src/components/features/account-details/account-information/AccountInformation.tsx @@ -28,9 +28,8 @@ export const AccountInformation: React.FC = ({ const transactions = data?.transactions.totalCount; const reversibleTransactions = data?.reversibleTransactions.totalCount; const miningRewards = data?.minerRewards.totalCount; - const beneficiaryHighSecuritySets = - data?.beneficiaryHighSecuritySets.totalCount; - const guardianHighSecuritySets = data?.guardianHighSecuritySets.totalCount; + const beneficiaries = data?.beneficiaries.totalCount; + const guardians = data?.guardian.totalCount; const information = [ { @@ -42,9 +41,8 @@ export const AccountInformation: React.FC = ({ reversibleTransactions, miningRewards, checksum, - isHighSecurity: - beneficiaryHighSecuritySets && beneficiaryHighSecuritySets > 0, - isGuardian: guardianHighSecuritySets && guardianHighSecuritySets > 0 + isHighSecurity: guardians && guardians > 0, + isGuardian: beneficiaries && beneficiaries > 0 } ]; diff --git a/src/components/features/account-details/account-miner-rewards/hook.tsx b/src/components/features/account-details/account-miner-rewards/hook.tsx index 8a20af1..9ec9d54 100644 --- a/src/components/features/account-details/account-miner-rewards/hook.tsx +++ b/src/components/features/account-details/account-miner-rewards/hook.tsx @@ -1,6 +1,6 @@ import type { QueryResult } from '@apollo/client'; import { getCoreRowModel, useReactTable } from '@tanstack/react-table'; -import { useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { ACCOUNT_MINER_REWARDS_COLUMNS } from '@/components/common/table-columns/ACCOUNT_MINER_REWARDS_COLUMNS'; import type { AccountMinerRewards, AccountResponse } from '@/schemas'; @@ -9,8 +9,13 @@ export const useAccountMinerRewards = (query: QueryResult) => { const { data, error: fetchError, loading } = query; const minerRewardColumns = useMemo(() => ACCOUNT_MINER_REWARDS_COLUMNS, []); + const tableData = useMemo( + () => data?.minerRewards?.edges ?? [], + [data?.minerRewards?.edges] + ); + const table = useReactTable({ - data: data?.minerRewards?.edges ?? [], + data: tableData, columns: minerRewardColumns, getCoreRowModel: getCoreRowModel(), enableSorting: false @@ -19,7 +24,7 @@ export const useAccountMinerRewards = (query: QueryResult) => { const success = !loading && !fetchError; const error = !loading && fetchError; - const getStatus = () => { + const getStatus = useCallback(() => { switch (true) { case success: return 'success'; @@ -30,7 +35,7 @@ export const useAccountMinerRewards = (query: QueryResult) => { default: return 'idle'; } - }; + }, [success, error, loading]); return { table, diff --git a/src/components/features/account-details/account-reversible-transactions/hook.tsx b/src/components/features/account-details/account-reversible-transactions/hook.tsx index b37ae5e..d617457 100644 --- a/src/components/features/account-details/account-reversible-transactions/hook.tsx +++ b/src/components/features/account-details/account-reversible-transactions/hook.tsx @@ -1,6 +1,6 @@ import type { QueryResult } from '@apollo/client'; import { getCoreRowModel, useReactTable } from '@tanstack/react-table'; -import { useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { ACCOUNT_REVERSIBLE_TRANSACTION_COLUMNS } from '@/components/common/table-columns/ACCOUNT_REVERSIBLE_TRANSACTION_COLUMNS'; import type { AccountResponse, AccountReversibleTransaction } from '@/schemas'; @@ -14,8 +14,13 @@ export const useAccountReversibleTransactions = ( [] ); + const tableData = useMemo( + () => data?.reversibleTransactions?.edges ?? [], + [data?.reversibleTransactions?.edges] + ); + const table = useReactTable({ - data: data?.reversibleTransactions?.edges ?? [], + data: tableData, columns: transactionColumns, getCoreRowModel: getCoreRowModel(), enableSorting: false @@ -24,7 +29,7 @@ export const useAccountReversibleTransactions = ( const success = !loading && !fetchError; const error = !loading && fetchError; - const getStatus = () => { + const getStatus = useCallback(() => { switch (true) { case success: return 'success'; @@ -35,7 +40,7 @@ export const useAccountReversibleTransactions = ( default: return 'idle'; } - }; + }, [success, error, loading]); return { table, diff --git a/src/components/features/account-details/account-transactions/hook.tsx b/src/components/features/account-details/account-transactions/hook.tsx index 0c5d93f..292f54a 100644 --- a/src/components/features/account-details/account-transactions/hook.tsx +++ b/src/components/features/account-details/account-transactions/hook.tsx @@ -1,6 +1,6 @@ import type { QueryResult } from '@apollo/client'; import { getCoreRowModel, useReactTable } from '@tanstack/react-table'; -import { useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { ACCOUNT_TRANSACTION_COLUMNS } from '@/components/common/table-columns/ACCOUNT_TRANSACTION_COLUMNS'; import type { AccountResponse, AccountTransaction } from '@/schemas'; @@ -9,8 +9,13 @@ export const useAccountTransactions = (query: QueryResult) => { const { data, error: fetchError, loading } = query; const transactionColumns = useMemo(() => ACCOUNT_TRANSACTION_COLUMNS, []); + const tableData = useMemo( + () => data?.transactions?.edges ?? [], + [data?.transactions?.edges] + ); + const table = useReactTable({ - data: data?.transactions?.edges ?? [], + data: tableData, columns: transactionColumns, getCoreRowModel: getCoreRowModel(), enableSorting: false @@ -19,7 +24,7 @@ export const useAccountTransactions = (query: QueryResult) => { const success = !loading && !fetchError; const error = !loading && fetchError; - const getStatus = () => { + const getStatus = useCallback(() => { switch (true) { case success: return 'success'; @@ -30,7 +35,7 @@ export const useAccountTransactions = (query: QueryResult) => { default: return 'idle'; } - }; + }, [success, error, loading]); return { table, diff --git a/src/schemas/account.ts b/src/schemas/account.ts index 0728053..fef84d8 100644 --- a/src/schemas/account.ts +++ b/src/schemas/account.ts @@ -1,5 +1,4 @@ import type * as gql from '../__generated__/graphql'; -import type { HighSecuritySet } from './high-security-set'; import type { MinerReward } from './miner-reward'; import type { ReversibleTransaction } from './reversible-transaction'; import type { Transaction } from './transcation'; @@ -24,13 +23,13 @@ export interface AccountResponse { /** @description the grand total of the reversible transactions regardless of the return node limit using `first` parameter */ totalCount: number; }; - beneficiaryHighSecuritySets: { - edges: AccountHighSecuritySet[]; + beneficiaries: { + edges: AccountBeneficiary[]; /** @description the grand total of the beneficiary high security sets regardless of the return node limit using `first` parameter */ totalCount: number; }; - guardianHighSecuritySets: { - edges: AccountHighSecuritySet[]; + guardian: { + edges: AccountGuardian[]; /** @description the grand total of the guardian high security sets regardless of the return node limit using `first` parameter */ totalCount: number; }; @@ -55,8 +54,16 @@ export interface AccountReversibleTransaction { node: ReversibleTransaction; } -export interface AccountHighSecuritySet { - node: HighSecuritySet; +export interface AccountBeneficiary { + node: { + who: Account; + }; +} + +export interface AccountGuardian { + node: { + interceptor: Account; + }; } export interface AccountStatsResponse {