Skip to main content

Overview

The ZKScore React SDK provides a comprehensive set of hooks that make it easy to integrate reputation scores, identities, achievements, and more into your React applications.

Installation

npm install @zkscore/react

Provider Setup

Wrap your app with the ZKScoreProvider:
import { ZKScoreProvider } from '@zkscore/react';

function App() {
  return (
    <ZKScoreProvider
      apiKey={process.env.REACT_APP_ZKSCORE_API_KEY}
      network="mainnet"
    >
      <YourApp />
    </ZKScoreProvider>
  );
}

Provider Props

apiKey
string
required
Your ZKScore API key
network
string
Network to use: 'mainnet' or 'testnet' (default: 'mainnet')
cacheTime
number
Cache duration in milliseconds (default: 300000 - 5 minutes)
retryAttempts
number
Number of retry attempts for failed requests (default: 3)

Available Hooks

Identity Hooks

useIdentity

Get identity information for an address

useMintIdentity

Mint a new ZKScore identity

useCheckUsername

Check username availability

Score Hooks

useScore

Get reputation score for an address

useScoreBreakdown

Get detailed score breakdown

useScoreHistory

Get historical score data

useLeaderboard

Get score leaderboard

Achievement Hooks

useAchievements

List all available achievements

useUserAchievements

Get user’s earned achievements

useAchievementProgress

Track achievement progress

useClaimAchievement

Claim an achievement

Trading Hooks

useTradingStats

Get trading statistics

useTradingHistory

Get trading history

useTradingLeaderboard

Get trading leaderboard

Trust Layer Hooks

useAttestations

Get attestations for an address

useCreateAttestation

Create new attestations

useTrustPolicy

Evaluate trust policies

Hook Patterns

Basic Usage

import { useScore } from '@zkscore/react';

function ScoreDisplay({ address }: { address: string }) {
  const { score, loading, error } = useScore(address);

  if (loading) return <div>Loading score...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!score) return <div>No score available</div>;

  return (
    <div>
      <h2>Score: {score.overall}/1000</h2>
      <p>Rank: #{score.rank}</p>
    </div>
  );
}

With Auto-Refresh

import { useScore } from '@zkscore/react';

function LiveScore({ address }: { address: string }) {
  const { score, loading, refetch } = useScore(address, {
    refreshInterval: 30000, // Refresh every 30 seconds
  });

  return (
    <div>
      <h2>Score: {score?.overall || 0}</h2>
      <button onClick={() => refetch()}>Refresh Now</button>
    </div>
  );
}

Conditional Fetching

import { useScore } from '@zkscore/react';

function ConditionalScore({ address, enabled }: { address: string; enabled: boolean }) {
  const { score, loading } = useScore(address, {
    enabled, // Only fetch when enabled is true
  });

  if (!enabled) return <div>Score fetching disabled</div>;
  if (loading) return <div>Loading...</div>;

  return <div>Score: {score?.overall}</div>;
}

Error Handling

import { useScore } from '@zkscore/react';

function ScoreWithErrorHandling({ address }: { address: string }) {
  const { score, loading, error, refetch } = useScore(address, {
    retry: 3,
    retryDelay: 1000,
  });

  if (loading) return <Spinner />;

  if (error) {
    return (
      <ErrorCard>
        <p>{error.message}</p>
        <button onClick={() => refetch()}>Try Again</button>
      </ErrorCard>
    );
  }

  return <ScoreCard score={score} />;
}

Multiple Hooks

import { useIdentity, useScore, useUserAchievements } from '@zkscore/react';

function UserProfile({ address }: { address: string }) {
  const { identity } = useIdentity(address);
  const { score } = useScore(address);
  const { achievements } = useUserAchievements(address);

  return (
    <div>
      <h1>{identity?.username || 'Anonymous'}</h1>
      <p>Score: {score?.overall}/1000</p>
      <p>Achievements: {achievements?.length || 0}</p>
    </div>
  );
}

Common Hook Options

Most hooks accept these common options:
enabled
boolean
Enable/disable the query (default: true)
refreshInterval
number
Auto-refresh interval in milliseconds
retry
number
Number of retry attempts (default: 3)
retryDelay
number
Delay between retries in milliseconds (default: 1000)
cacheTime
number
How long to cache data in milliseconds
staleTime
number
Time until data is considered stale in milliseconds
onSuccess
function
Callback when query succeeds
onError
function
Callback when query fails

Common Return Values

All hooks return an object with these common properties:
data
any
The fetched data (e.g., score, identity, achievements)
loading
boolean
Whether the data is currently being fetched
error
Error | null
Error object if the request failed
refetch
function
Function to manually refetch the data
isStale
boolean
Whether the cached data is stale

Advanced Patterns

Prefetching Data

import { useZKScore } from '@zkscore/react';

function PrefetchExample() {
  const { prefetch } = useZKScore();

  const handleMouseEnter = (address: string) => {
    // Prefetch data on hover
    prefetch.score(address);
    prefetch.achievements(address);
  };

  return (
    <div onMouseEnter={() => handleMouseEnter('0x123...')}>
      <UserCard address="0x123..." />
    </div>
  );
}

Mutations

import { useMintIdentity } from '@zkscore/react';

function MintIdentityForm() {
  const { mutate, loading, error } = useMintIdentity({
    onSuccess: (identity) => {
      console.log('Identity minted:', identity);
    },
    onError: (error) => {
      console.error('Failed to mint:', error);
    },
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    mutate({
      address: '0x123...',
      username: 'alice',
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="username" required />
      <button type="submit" disabled={loading}>
        {loading ? 'Minting...' : 'Mint Identity'}
      </button>
      {error && <p className="error">{error.message}</p>}
    </form>
  );
}

Optimistic Updates

import { useClaimAchievement, useUserAchievements } from '@zkscore/react';

function ClaimButton({ address, achievementId }: Props) {
  const { achievements, refetch } = useUserAchievements(address);
  const { mutate } = useClaimAchievement({
    onMutate: () => {
      // Optimistically update UI
      // This runs before the API call
    },
    onSuccess: () => {
      // Refetch to get updated data
      refetch();
    },
  });

  return (
    <button onClick={() => mutate({ achievementId })}>
      Claim Achievement
    </button>
  );
}

Dependent Queries

import { useIdentity, useScore } from '@zkscore/react';

function DependentQueries({ address }: { address: string }) {
  // First query
  const { identity } = useIdentity(address);

  // Second query only runs if first succeeds
  const { score } = useScore(address, {
    enabled: !!identity,
  });

  return (
    <div>
      {identity && <h1>{identity.username}</h1>}
      {score && <p>Score: {score.overall}</p>}
    </div>
  );
}

Pagination

import { useTradingHistory } from '@zkscore/react';
import { useState } from 'react';

function TradingHistoryTable({ address }: { address: string }) {
  const [page, setPage] = useState(0);
  const { history, loading, pagination } = useTradingHistory(address, {
    limit: 20,
    offset: page * 20,
  });

  return (
    <div>
      {loading ? (
        <Spinner />
      ) : (
        <table>
          {history?.trades.map((trade) => (
            <tr key={trade.txHash}>
              <td>{trade.tokenIn.symbol}</td>
              <td>{trade.tokenOut.symbol}</td>
              <td>{trade.timestamp}</td>
            </tr>
          ))}
        </table>
      )}
      
      <Pagination
        page={page}
        hasMore={pagination?.hasMore}
        onNext={() => setPage(p => p + 1)}
        onPrev={() => setPage(p => Math.max(0, p - 1))}
      />
    </div>
  );
}

TypeScript Support

All hooks are fully typed for TypeScript:
import { useScore } from '@zkscore/react';
import type { Score, ScoreBreakdown } from '@zkscore/types';

function TypedScore({ address }: { address: string }) {
  // Type is inferred automatically
  const { score, loading, error } = useScore(address);
  
  // score is typed as Score | undefined
  // error is typed as Error | null
  // loading is typed as boolean
  
  return <div>{score?.overall}</div>;
}

Performance Tips

  1. Use Appropriate Cache Times: Set longer cache times for rarely-changing data
  2. Disable Auto-Refetch: For static data, set refreshInterval: 0
  3. Enable Suspense: Use React Suspense for better loading states
  4. Prefetch: Prefetch data on hover or route changes
  5. Batch Requests: Use multiple hooks to fetch related data in parallel

Next Steps

useIdentity

Learn about identity hooks

useScore

Learn about score hooks

useAchievements

Learn about achievement hooks

Components

Pre-built React components