Skip to main content

Documentation Index

Fetch the complete documentation index at: https://core.anylayer.org/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Complete guide for integrating ZKScore smart contracts using wagmi hooks in React applications.

Installation

npm install wagmi viem @tanstack/react-query
# or
yarn add wagmi viem @tanstack/react-query

Basic Setup

Provider Configuration

import { WagmiProvider, createConfig, http } from 'wagmi';
import { mainnet, polygon, arbitrum, base } from 'wagmi/chains';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { injected, metaMask, walletConnect } from 'wagmi/connectors';

// Create wagmi config
const config = createConfig({
  chains: [mainnet, polygon, arbitrum, base],
  connectors: [
    injected(),
    metaMask(),
    walletConnect({ projectId: 'YOUR_PROJECT_ID' })
  ],
  transports: {
    [mainnet.id]: http(),
    [polygon.id]: http(),
    [arbitrum.id]: http(),
    [base.id]: http()
  }
});

// Query client
const queryClient = new QueryClient();

// App component
function App() {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <YourApp />
      </QueryClientProvider>
    </WagmiProvider>
  );
}

Contract Configuration

// Contract addresses
const CONTRACTS = {
  identitySBT: '0x1234567890123456789012345678901234567890',
  scoreCalculator: '0x2345678901234567890123456789012345678901',
  achievementRegistry: '0x3456789012345678901234567890123456789012',
  trustRegistry: '0x4567890123456789012345678901234567890123'
};

// Contract ABIs
import IdentitySBTABI from '@zkscore/contracts/abis/IdentitySBT.json';
import ScoreCalculatorABI from '@zkscore/contracts/abis/ScoreCalculator.json';

Identity Operations

Get Identity Hook

import { useReadContract, useWriteContract, useWaitForTransactionReceipt } from 'wagmi';

function useIdentity(userAddress) {
  const { data: identity, isLoading, error } = useReadContract({
    address: CONTRACTS.identitySBT,
    abi: IdentitySBTABI,
    functionName: 'getIdentity',
    args: [userAddress]
  });
  
  const { data: isActivated } = useReadContract({
    address: CONTRACTS.identitySBT,
    abi: IdentitySBTABI,
    functionName: 'isActivated',
    args: [userAddress]
  });
  
  return {
    identity,
    isActivated,
    isLoading,
    error
  };
}

Mint Identity Hook

function useMintIdentity() {
  const { writeContract, data: hash, isPending } = useWriteContract();
  const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
    hash
  });
  
  const mintIdentity = async (zksId, displayName, avatarUrl) => {
    try {
      // Get minting fee
      const mintingFee = await publicClient.readContract({
        address: CONTRACTS.identitySBT,
        abi: IdentitySBTABI,
        functionName: 'mintingFee'
      });
      
      await writeContract({
        address: CONTRACTS.identitySBT,
        abi: IdentitySBTABI,
        functionName: 'mintIdentity',
        args: [zksId, displayName, avatarUrl],
        value: mintingFee
      });
    } catch (error) {
      console.error('Minting failed:', error);
    }
  };
  
  return {
    mintIdentity,
    hash,
    isPending,
    isConfirming,
    isSuccess
  };
}

Score Operations

Get Score Hook

function useScore(userAddress) {
  const { data: score, isLoading, error } = useReadContract({
    address: CONTRACTS.scoreCalculator,
    abi: ScoreCalculatorABI,
    functionName: 'getScore',
    args: [userAddress]
  });
  
  const { data: breakdown } = useReadContract({
    address: CONTRACTS.scoreCalculator,
    abi: ScoreCalculatorABI,
    functionName: 'getScoreBreakdown',
    args: [userAddress]
  });
  
  return {
    score,
    breakdown,
    isLoading,
    error
  };
}

Score Events Hook

import { useWatchContractEvent } from 'wagmi';

function useScoreEvents(userAddress) {
  const [scoreUpdates, setScoreUpdates] = useState([]);
  
  useWatchContractEvent({
    address: CONTRACTS.scoreCalculator,
    abi: ScoreCalculatorABI,
    eventName: 'ScoreUpdated',
    args: {
      user: userAddress
    },
    onLogs: (logs) => {
      setScoreUpdates(prev => [...prev, ...logs]);
    }
  });
  
  return scoreUpdates;
}

Achievement Operations

Get Achievements Hook

function useAchievements(userAddress) {
  const { data: achievementCount } = useReadContract({
    address: CONTRACTS.achievementRegistry,
    abi: AchievementRegistryABI,
    functionName: 'getUserAchievementCount',
    args: [userAddress]
  });
  
  const achievements = useMemo(() => {
    if (!achievementCount) return [];
    
    const achievementPromises = [];
    for (let i = 0; i < Number(achievementCount); i++) {
      achievementPromises.push(
        publicClient.readContract({
          address: CONTRACTS.achievementRegistry,
          abi: AchievementRegistryABI,
          functionName: 'getUserAchievement',
          args: [userAddress, BigInt(i)]
        })
      );
    }
    
    return Promise.all(achievementPromises);
  }, [achievementCount, userAddress]);
  
  return {
    achievements,
    count: achievementCount
  };
}

Claim Achievement Hook

function useClaimAchievement() {
  const { writeContract, data: hash, isPending } = useWriteContract();
  const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
    hash
  });
  
  const claimAchievement = async (achievementId) => {
    try {
      await writeContract({
        address: CONTRACTS.achievementRegistry,
        abi: AchievementRegistryABI,
        functionName: 'claimAchievement',
        args: [achievementId]
      });
    } catch (error) {
      console.error('Claim failed:', error);
    }
  };
  
  return {
    claimAchievement,
    hash,
    isPending,
    isConfirming,
    isSuccess
  };
}

React Components

Identity Component

function IdentityCard({ userAddress }) {
  const { identity, isActivated, isLoading } = useIdentity(userAddress);
  const { mintIdentity, isPending } = useMintIdentity();
  
  if (isLoading) return <div>Loading...</div>;
  
  if (!identity?.exists) {
    return (
      <div>
        <h3>No Identity Found</h3>
        <button 
          onClick={() => mintIdentity('alice.zks', 'Alice Smith', 'https://example.com/avatar.jpg')}
          disabled={isPending}
        >
          {isPending ? 'Minting...' : 'Mint Identity'}
        </button>
      </div>
    );
  }
  
  return (
    <div>
      <h3>{identity.displayName}</h3>
      <p>ZKS ID: {identity.zksId}</p>
      <p>Status: {isActivated ? 'Activated' : 'Not Activated'}</p>
    </div>
  );
}

Score Component

function ScoreDisplay({ userAddress }) {
  const { score, breakdown, isLoading } = useScore(userAddress);
  const scoreUpdates = useScoreEvents(userAddress);
  
  if (isLoading) return <div>Loading score...</div>;
  
  return (
    <div>
      <h3>ZKScore: {score?.total.toString() || '0'}</h3>
      <div>
        <h4>Breakdown:</h4>
        <ul>
          <li>DeFi: {breakdown?.defi.toString() || '0'}</li>
          <li>NFT: {breakdown?.nft.toString() || '0'}</li>
          <li>Social: {breakdown?.social.toString() || '0'}</li>
          <li>Trading: {breakdown?.trading.toString() || '0'}</li>
        </ul>
      </div>
      {scoreUpdates.length > 0 && (
        <div>
          <h4>Recent Updates:</h4>
          {scoreUpdates.map((update, index) => (
            <div key={index}>
              Score: {update.args.oldScore.toString()}{update.args.newScore.toString()}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

Best Practices

  1. Use Hooks: Leverage wagmi’s built-in hooks for state management
  2. Handle Loading States: Always handle loading and error states
  3. Optimize Re-renders: Use useMemo and useCallback appropriately
  4. Error Boundaries: Implement error boundaries for better UX
  5. Type Safety: Use TypeScript for better development experience