@photonite/subgraph-sync
v1.0.0
Published
React hooks and components for tracking subgraph synchronization states with Apollo Client
Maintainers
Readme
Subgraph Sync
A React library for handling subgraph synchronization states with Apollo Client. Track indexing progress, sync states, and ensure your dApp queries return up-to-date data from The Graph.
Features
🔄 Real-time Sync Tracking - Monitor subgraph indexing progress
🎯 Block & Timestamp Targeting - Wait for specific blocks or timestamps
⚡ Progress Calculation - Visual progress indicators (0-100%)
🔁 Automatic Retries - Configurable retry logic for failed queries
⏱️ Timeout Handling - Graceful timeout with callbacks
🎨 UI Components - Pre-built React components for sync indicators
📦 Context Provider - Manage multiple transaction sync states
� Type-Safe - Full TypeScript support
🔒 Type-Safe - Full TypeScript support
Installation
npm install subgraph-sync
# or
yarn add subgraph-sync
# or
pnpm add subgraph-syncPeer Dependencies
This library requires the following peer dependencies:
{
"@apollo/client": "^3.0.0",
"graphql": "^15.0.0 || ^16.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}Quick Start
Basic Usage with useSubgraphSync
import { useSubgraphSync } from "subgraph-sync";
function MyComponent() {
const syncState = useSubgraphSync(
{ blockNumber: 1000000 }, // Target block
{ pollInterval: 2000 } // Poll every 2 seconds
);
if (syncState.isIndexing) {
return <div>Syncing... {syncState.progress}%</div>;
}
if (syncState.isSynced) {
return <div>✅ Synced to block {syncState.currentBlock?.number}</div>;
}
return null;
}Combined Query + Sync
import { gql } from "@apollo/client";
import { useSubgraphQuery } from "subgraph-sync";
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
balance
}
}
`;
function UserBalance({ userId, targetBlock }) {
const { data, loading, isIndexing, isSynced, progress } = useSubgraphQuery(
GET_USER,
{
variables: { id: userId },
targetBlockNumber: targetBlock,
}
);
if (loading || isIndexing) {
return <div>Loading... {progress}%</div>;
}
return <div>Balance: {data.user.balance}</div>;
}Using the SyncIndicator Component
import { useSubgraphSync, SyncIndicator } from "subgraph-sync";
function TransactionTracker({ txHash, blockNumber }) {
const syncState = useSubgraphSync({ blockNumber });
return (
<div>
<h2>Transaction: {txHash}</h2>
<SyncIndicator
syncState={syncState}
showProgress={true}
showBlockInfo={true}
/>
</div>
);
}API Reference
useSubgraphSync(target, config?)
Track subgraph synchronization to a specific target.
Parameters:
target: SyncTarget- Target block or timestampblockNumber?: number- Target block numbertimestamp?: number- Target timestamp
config?: SyncConfig- Optional configurationpollInterval?: number- Polling interval in ms (default: 2000)timeout?: number- Timeout in ms (default: 120000)maxRetries?: number- Max retry attempts (default: 3)onTimeout?: () => void- Timeout callbackonError?: (error: Error) => void- Error callbackonSyncComplete?: (status: SubgraphStatus) => void- Success callback
Returns: UseSubgraphSyncResult
{
isIndexing: boolean; // Currently indexing
isSynced: boolean; // Reached target
isTimeout: boolean; // Timed out
isError: boolean; // Error occurred
currentBlock: Block | null; // Current indexed block
targetBlock: Block | null; // Target block
progress: number; // Progress 0-100
error: string | null; // Error message
retries: number; // Retry count
refetch: () => Promise<any>; // Manual refetch
reset: () => void; // Reset state
}useSubgraphQuery(query, options?)
Combines Apollo useQuery with sync tracking.
Parameters:
query: DocumentNode- GraphQL queryoptions?: QueryWithSyncOptions- Apollo query options + sync optionstargetBlockNumber?: number- Target blocktargetTimestamp?: number- Target timestampsyncConfig?: SyncConfig- Sync configuration- ...all Apollo
useQueryoptions
Returns: All Apollo QueryResult properties + UseSubgraphSyncResult properties
<SyncIndicator />
Pre-built UI component for displaying sync state.
Props:
{
syncState: UseSubgraphSyncResult; // Required: sync state
showProgress?: boolean; // Show progress bar (default: true)
showBlockInfo?: boolean; // Show block details (default: true)
className?: string; // Additional CSS classes
}Examples
Wait for Transaction Confirmation
import { useSubgraphSync } from "subgraph-sync";
function SendTransaction() {
const [targetBlock, setTargetBlock] = useState(null);
const syncState = useSubgraphSync(
{ blockNumber: targetBlock },
{
onSyncComplete: () => {
console.log("Transaction indexed!");
},
}
);
return (
<div>
<button onClick={() => setTargetBlock(1000000)}>Send Transaction</button>
{syncState.isIndexing && (
<div>Waiting for indexing... {syncState.progress}%</div>
)}
</div>
);
}Custom Error Handling
const syncState = useSubgraphSync(
{ blockNumber: 1000000 },
{
maxRetries: 5,
pollInterval: 1000,
timeout: 60000,
onError: (error) => {
console.error("Sync failed:", error);
},
onTimeout: () => {
console.warn("Sync timeout");
},
}
);Testing
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage reportTypeScript
Full TypeScript definitions included:
import type {
SyncConfig,
SyncTarget,
SyncState,
UseSubgraphSyncResult,
SubgraphStatus,
Block,
QueryWithSyncOptions,
} from "subgraph-sync";License
MIT
This library provides:
- Modular architecture for easy extension
- TypeScript support for better developer experience
- Flexible configuration for different use cases
- Pre-built components for quick integration
- Comprehensive documentation for easy adoption
- Build system for distribution
