@photonite/subgraph-sync
Version:
React hooks and components for tracking subgraph synchronization states with Apollo Client
216 lines (210 loc) • 7.4 kB
TypeScript
import * as graphql from 'graphql';
import * as _apollo_client from '@apollo/client';
import { OperationVariables, DocumentNode } from '@apollo/client';
import React from 'react';
/**
* Represents a blockchain block with its number and timestamp.
*/
interface Block {
/** Block number */
number: number;
/** Block timestamp (Unix timestamp in seconds) */
timestamp: number;
/** Optional block hash */
hash?: string;
}
/**
* Subgraph metadata and indexing status.
*/
interface SubgraphStatus {
/** Current block information */
block: Block;
/** Whether the subgraph has indexing errors */
hasIndexingErrors: boolean;
/** Optional deployment identifier */
deployment?: string;
}
/**
* Configuration options for subgraph synchronization.
*/
interface SyncConfig {
/** Polling interval in milliseconds (default: 2000) */
pollInterval?: number;
/** Timeout duration in milliseconds (default: 120000) */
timeout?: number;
/** Maximum number of retry attempts (default: 3) */
maxRetries?: number;
/** Callback invoked when sync times out */
onTimeout?: () => void;
/** Callback invoked when an error occurs after max retries */
onError?: (error: Error) => void;
/** Callback invoked when sync completes successfully */
onSyncComplete?: (status: SubgraphStatus) => void;
}
/**
* Target block or timestamp for synchronization.
* At least one property should be specified.
*/
interface SyncTarget {
/** Target block number to wait for */
blockNumber?: number;
/** Target timestamp to wait for (Unix timestamp in seconds) */
timestamp?: number;
/** Optional transaction hash (not currently used) */
txHash?: string;
}
/**
* Current state of subgraph synchronization.
*/
interface SyncState {
/** Whether the subgraph is currently indexing to reach the target */
isIndexing: boolean;
/** Whether the subgraph has reached the target block/timestamp */
isSynced: boolean;
/** Whether the sync operation has timed out */
isTimeout: boolean;
/** Whether an error occurred during syncing */
isError: boolean;
/** Current block that the subgraph has indexed */
currentBlock: Block | null;
/** Target block that we're waiting for */
targetBlock: Block | null;
/** Progress percentage (0-100) */
progress: number;
/** Error message if an error occurred */
error: string | null;
/** Number of retry attempts made */
retries: number;
}
/**
* Return type of useSubgraphSync hook, extending SyncState with control functions.
*/
interface UseSubgraphSyncResult extends SyncState {
/** Manually refetch the current subgraph status */
refetch: () => Promise<any>;
/** Reset the sync state to initial values */
reset: () => void;
}
/**
* Options for useSubgraphQuery, combining Apollo query options with sync tracking.
*/
interface QueryWithSyncOptions<TVariables = any> {
/** Sync configuration options */
syncConfig?: SyncConfig;
/** Target block number to wait for */
targetBlockNumber?: number;
/** Target timestamp to wait for */
targetTimestamp?: number;
/** GraphQL query variables */
variables?: TVariables;
}
/**
* Hook for tracking subgraph synchronization progress to a target block or timestamp.
*
* @param target - The sync target (block number and/or timestamp)
* @param config - Optional configuration for polling, timeout, retries, and callbacks
*
* @returns Sync state including indexing status, progress, current block, and control functions
*
* @example
* ```tsx
* const syncState = useSubgraphSync(
* { blockNumber: 1000000 },
* {
* pollInterval: 2000,
* timeout: 60000,
* onSyncComplete: () => console.log('Synced!'),
* }
* );
*
* if (syncState.isIndexing) {
* return <div>Progress: {syncState.progress}%</div>;
* }
* ```
*/
declare const useSubgraphSync: (target: SyncTarget, config?: SyncConfig) => UseSubgraphSyncResult;
/**
* Enhanced Apollo useQuery hook that includes subgraph synchronization tracking.
* Combines GraphQL query execution with sync state monitoring.
*
* @param query - GraphQL query document
* @param options - Combined Apollo query options and sync configuration
*
* @returns All Apollo query result properties plus sync state
*
* @example
* ```tsx
* const { data, loading, isIndexing, isSynced, progress } = useSubgraphQuery(
* GET_USER_QUERY,
* {
* variables: { id: '0x123' },
* targetBlockNumber: 1000000,
* syncConfig: { pollInterval: 2000 },
* }
* );
* ```
*/
declare function useSubgraphQuery<TData = any, TVariables extends OperationVariables = OperationVariables>(query: DocumentNode, options?: QueryWithSyncOptions<TVariables>): {
isLoading: boolean;
hasError: boolean;
refetch: () => Promise<any>;
reset: () => void;
isIndexing: boolean;
isSynced: boolean;
isTimeout: boolean;
isError: boolean;
currentBlock: Block | null;
targetBlock: Block | null;
progress: number;
error: string | null;
retries: number;
called: boolean;
client: _apollo_client.ApolloClient<any>;
observable: _apollo_client.ObservableQuery<TData, TVariables>;
data: TData | undefined;
previousData?: TData | undefined;
errors?: readonly graphql.GraphQLFormattedError[] | undefined;
loading: boolean;
networkStatus: _apollo_client.NetworkStatus;
startPolling: (pollInterval: number) => void;
stopPolling: () => void;
subscribeToMore: _apollo_client.SubscribeToMoreFunction<TData, TVariables>;
updateQuery: (mapFn: _apollo_client.UpdateQueryMapFn<TData, TVariables>) => void;
reobserve: (newOptions?: Partial<_apollo_client.WatchQueryOptions<TVariables, TData>> | undefined, newNetworkStatus?: _apollo_client.NetworkStatus | undefined) => Promise<_apollo_client.ApolloQueryResult<TData>>;
variables: TVariables | undefined;
fetchMore: <TFetchData = TData, TFetchVars extends OperationVariables = TVariables>(fetchMoreOptions: _apollo_client.FetchMoreQueryOptions<TFetchVars, TFetchData> & {
updateQuery?: ((previousQueryResult: _apollo_client.Unmasked<TData>, options: {
fetchMoreResult: _apollo_client.Unmasked<TFetchData>;
variables: TFetchVars;
}) => _apollo_client.Unmasked<TData>) | undefined;
}) => Promise<_apollo_client.ApolloQueryResult<TFetchData>>;
};
interface SyncIndicatorProps {
/** Sync state from useSubgraphSync hook */
syncState: UseSubgraphSyncResult;
/** Whether to show progress bar (default: true) */
showProgress?: boolean;
/** Whether to show block information (default: true) */
showBlockInfo?: boolean;
/** Additional CSS class names */
className?: string;
}
/**
* Pre-built UI component for displaying subgraph synchronization state.
* Shows sync status, progress bar, and block information.
*
* @example
* ```tsx
* const syncState = useSubgraphSync({ blockNumber: 1000000 });
*
* return (
* <SyncIndicator
* syncState={syncState}
* showProgress={true}
* showBlockInfo={true}
* />
* );
* ```
*/
declare const SyncIndicator: React.FC<SyncIndicatorProps>;
export { Block, QueryWithSyncOptions, SubgraphStatus, SyncConfig, SyncIndicator, SyncState, SyncTarget, UseSubgraphSyncResult, useSubgraphQuery, useSubgraphSync };