npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

reality-data-service

v0.6.7

Published

A comprehensive library for interacting with Reality.eth questions and disputes across multiple blockchains.

Readme

Reality Data Service

A comprehensive library for interacting with Reality.eth questions and disputes across multiple blockchains.

Overview

Reality Data Service provides React hooks and utilities for fetching, filtering, and displaying Reality.eth questions and their associated dispute data. The library supports multiple blockchains including Ethereum, Gnosis Chain, and Polygon.

Installation

npm install reality-data-service

Core Exports

Hooks

useQuestions

A React hook for fetching and managing Reality.eth questions.

function useQuestions({
  chain,
  searchTerm,
  filters
}: UseQuestionsConfig): UseQuestionsResult

Parameters:

  • chain: The blockchain to fetch questions from (see Chain type)
  • searchTerm (optional): String to filter questions by title/content
  • filters (optional): Object with additional filtering criteria

Returns:

  • questions: Array of all fetched questions
  • filteredQuestions: Array of questions after filters are applied
  • loading: Boolean indicating if questions are being loaded
  • error: Error message if fetch failed, null otherwise
  • hasMore: Boolean indicating if more questions can be loaded
  • loadMore: Function to load more questions
  • refresh: Function to refresh the questions
  • loadingState: Object with detailed loading state information
  • status: Current fetch status ('idle', 'loading', 'success', 'error')

Example:

function QuestionsList() {
  const {
    questions,
    loading,
    error,
    loadMore,
    hasMore
  } = useQuestions({
    chain: SUPPORTED_CHAINS[0], // Ethereum
    searchTerm: "climate"
  });

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <>
      <ul>
        {questions.map(q => (
          <li key={q.id}>{q.title}</li>
        ))}
      </ul>
      {hasMore && <button onClick={loadMore}>Load More</button>}
    </>
  );
}

useDisputeData

A React hook for fetching dispute data for a specific Reality.eth question.

function useDisputeData(question: Question): {
  disputeId: string | null;
  dispute: Dispute | undefined;
  disputeLoading: boolean;
  evidences: Evidence[];
  metaEvidence: any;
  arbitrableContractAddress: string | undefined;
}

Parameters:

  • question: A Question object (must include the chain property)

Returns:

  • disputeId: The ID of the dispute, or null if no dispute exists
  • dispute: The dispute data, or undefined if not loaded
  • disputeLoading: Boolean indicating if dispute data is being loaded
  • evidences: Array of evidence submitted for the dispute
  • metaEvidence: Metadata about the dispute
  • arbitrableContractAddress: The address of the arbitrable contract

Example:

function DisputeView({ question }) {
  const {
    dispute,
    disputeLoading,
    evidences
  } = useDisputeData(question);

  if (disputeLoading) return <div>Loading dispute data...</div>;
  if (!dispute) return <div>No dispute found</div>;

  return (
    <div>
      <h2>Dispute #{dispute.id}</h2>
      <p>Status: {dispute.ruled ? 'Ruled' : 'Pending'}</p>
      <h3>Evidence ({evidences.length})</h3>
      {evidences.map(e => (
        <div key={e.id}>
          <h4>{e.URI_contents.name}</h4>
          <p>{e.URI_contents.description}</p>
          <small>Submitted by: {e.sender}</small>
        </div>
      ))}
    </div>
  );
}

Types

Question

Represents a Reality.eth question.

interface Question {
  id: string;                   // Unique identifier for the question
  title: string;                // Question title
  description: string;          // Detailed description
  arbitrator: string;           // Address of the arbitrator
  options: string[];            // Possible answer options
  qType: string;                // Question type (binary, multiple-choice, etc.)
  phase: QuestionPhase;         // Current phase of the question
  currentAnswer: string;        // Current answer value
  openingTimestamp: number;     // When the question opened for answering
  arbitrationStatus?: ArbitrationStatus; // Status of arbitration if requested
  currentBond: string;          // Current bond amount
  timeToOpen: number;           // Time until question opens (ms)
  timeRemaining: number;        // Time remaining until finalization (ms)
  answers: Answer[];            // Ignore, use responses instead for answer history
  contract: string;             // Contract address
  createdTimestamp: number;     // When the question was created
  currentScheduledFinalizationTimestamp?: string; // When finalization is scheduled
  finalAnswer?: string;         // Final answer if finalized
  disputeId?: number;           // ID of associated dispute
  appealPeriodEnd?: number;     // When appeal period ends
  minimumBond: string;          // Minimum bond required
  arbitrationRequestedBy?: string; // Who requested arbitration
  responses: {                  // User responses, should be used to construct the answer history
    value: string;
    timestamp: number;
    bond: string;
    user: string;
  }[];
  chain: Chain;                 // Blockchain the question is on
  template?: Template;          // Template used to create the question
}

QuestionPhase

Enum representing the possible phases of a question.

enum QuestionPhase {
  NOT_CREATED = 'NOT_CREATED',
  OPEN = 'OPEN',
  UPCOMING = 'UPCOMING',
  PENDING_ARBITRATION = 'PENDING_ARBITRATION',
  FINALIZED = 'FINALIZED',
  SETTLED_TOO_SOON = 'SETTLED_TOO_SOON'
}

ArbitrationStatus

Enum representing the possible statuses of arbitration.

enum ArbitrationStatus {
  WAITING = 'WAITING',
  APPEALABLE = 'APPEALABLE',
  SOLVED = 'SOLVED'
}

Answer

Represents an answer to a question.

interface Answer {
  value: string;      // Answer value
  bond: string;       // Bond amount
  timestamp: number;  // When the answer was provided
  provider: string;   // Address of the answer provider
}

Evidence

Represents evidence submitted for a dispute.

interface Evidence {
  id: string;                 // Unique identifier
  URI: string;                // URI pointing to evidence
  URI_contents: {             // Contents of the evidence
    name: string;
    description: string;
  };
  creationTime: string;       // When the evidence was created
  sender: string;             // Address of the evidence submitter
}

Note: When working with evidence URIs from subgraphs, you must prepend https://cdn.kleros.link to the URI to form the complete URL. For example, if the URI is /ipfs/QmRXgRaKkcKKfXjTFozwoWLosFHmtcEaeuj1cL1G8xKHJd/file.pdf, the complete URL would be https://cdn.kleros.link/ipfs/QmRXgRaKkcKKfXjTFozwoWLosFHmtcEaeuj1cL1G8xKHJd/file.pdf.

Evidence JSON Format: The JSON retrieved from an evidence URI typically follows this structure:

{
  "name": "Response to \"The new candidate' justification for Invalid stands\"",
  "description": "The response argues against the claim that a \"new pool of candidates\" makes an election invalid...",
  "fileURI": "/ipfs/QmRXgRaKkcKKfXjTFozwoWLosFHmtcEaeuj1cL1G8xKHJd/Response.pdf",
  "evidenceSide": 0
}

The fileURI field may point to additional documents, which also need to be prefixed with https://cdn.kleros.link.

Template

Represents a template used to create a Reality.eth question.

interface Template {
  templateId: string;         // Unique identifier for the template
  questionText: string;       // Text of the template with placeholders
  creationTimestamp: string;  // When the template was created
  creator: string;            // Address of the template creator
}

Note: Templates contain placeholders like ${0}, ${1}, etc. that are replaced with actual values when a question is created. The template system allows for standardized question formats across the Reality.eth ecosystem.

Dispute

Represents a dispute for a question.

interface Dispute {
  id: string;                 // Unique identifier
  period: number;             // Current period of the dispute
  periodDeadline: string;     // Deadline for the current period
  nbRounds: string;           // Number of rounds
  nbChoices: string;          // Number of choices
  rounds: {                   // Information about rounds
    jurors: string;
    isCurrentRound: boolean;
  }[];
  lastPeriodChangeTs: string; // Timestamp of last period change
  arbitrableHistory: {        // History of arbitrable events
    id: string;
    metaEvidence: string;
  }[];
  arbitrated: string;         // Address of arbitrated contract
  ruled: boolean;             // Whether the dispute has been ruled
  ruling: string;             // The ruling
  evidenceGroup: {            // Group of evidence
    id: string;
    length: string;
    evidence: Evidence[];
  };
}

Chain

Represents a blockchain network.

interface Chain {
  id: string;           // Unique identifier (e.g., "ethereum")
  name: string;         // Display name (e.g., "Ethereum")
  subgraphUrl: string;  // URL for The Graph subgraph
  public_rpc_url: string; // Public RPC endpoint
  native_currency: string; // The native currency of the chain, used for the bonds of each question
}

Bridge

Represents a bridge between chains for Reality.eth questions.

interface Bridge {
  Name: string;
  Comment: string | null;
  "Home Chain": string;
  "Home Proxy": string | null;
  "Foreign Chain": string;
  "Foreign Proxy": string | null;
  Testnet: "Yes" | "No";
  Oracle: string | null;
  Bond: string | null;
  Appeals: boolean | null;
  Governor: boolean | null;
  Bot: boolean | false | "?" | null;
  Dispute: string | null;
}

Constants

SUPPORTED_CHAINS

Array of supported blockchain networks.

const SUPPORTED_CHAINS: Chain[] = [
  {
    id: "ethereum",
    name: "Ethereum",
    subgraphUrl: "https://gateway-arbitrum.network.thegraph.com/api/9a2c1f62c4da897f79c95a6a67600891/subgraphs/id/AGLkTv6eaW7JhQsLgB6SMzo43uM9V12ZoNkjAw7uijra",
    public_rpc_url: "https://rpc.ankr.com/eth",
  },
  {
    id: "gnosis",
    name: "Gnosis",
    subgraphUrl: "https://gateway-arbitrum.network.thegraph.com/api/9a2c1f62c4da897f79c95a6a67600891/subgraphs/id/E7ymrCnNcQdAAgLbdFWzGE5mvr5Mb5T9VfT43FqA7bNh",
    public_rpc_url: "https://rpc.ankr.com/gnosis",
  },
  {
    id: "polygon",
    name: "Polygon",
    subgraphUrl: "https://gateway-arbitrum.network.thegraph.com/api/9a2c1f62c4da897f79c95a6a67600891/subgraphs/id/AWx6jkeKZ3xKRzkrzgfCAMPT7d6Jc3AMcqB8koN3QEqE",
    public_rpc_url: "https://rpc.ankr.com/polygon",
  },
]

BRIDGES

Array of bridges between chains for Reality.eth questions.

Advanced Usage

Filtering Questions

The useQuestions hook supports filtering questions by various criteria:

const { filteredQuestions } = useQuestions({
  chain: SUPPORTED_CHAINS[0],
  filters: {
    phase: QuestionPhase.OPEN,
    // Add any property from the Question type
  }
});

Handling Pagination

The useQuestions hook supports pagination through the loadMore function:

function QuestionsList() {
  const { questions, hasMore, loadMore, loadingState } = useQuestions({
    chain: SUPPORTED_CHAINS[0]
  });

  return (
    <div>
      <ul>{questions.map(q => <li key={q.id}>{q.title}</li>)}</ul>
      
      {loadingState.loadingMore && <div>Loading more...</div>}
      
      {hasMore && (
        <button onClick={loadMore} disabled={loadingState.loadingMore}>
          Load More
        </button>
      )}
    </div>
  );
}

Complete Question Flow

This example shows how to list questions and then view details for a selected question:

function RealityApp() {
  const [selectedChain, setSelectedChain] = useState(SUPPORTED_CHAINS[0]);
  const [selectedQuestion, setSelectedQuestion] = useState(null);
  
  const { questions, loading } = useQuestions({
    chain: selectedChain
  });
  
  if (loading) return <div>Loading questions...</div>;
  
  if (selectedQuestion) {
    return (
      <QuestionDetail 
        question={selectedQuestion}
        onBack={() => setSelectedQuestion(null)}
      />
    );
  }
  
  return (
    <div>
      <h1>Reality.eth Questions</h1>
      <select onChange={e => {
        const chain = SUPPORTED_CHAINS.find(c => c.id === e.target.value);
        if (chain) setSelectedChain(chain);
      }}>
        {SUPPORTED_CHAINS.map(chain => (
          <option key={chain.id} value={chain.id}>
            {chain.name}
          </option>
        ))}
      </select>
      
      <ul>
        {questions.map(question => (
          <li key={question.id}>
            <h3>{question.title}</h3>
            <p>Phase: {question.phase}</p>
            <button onClick={() => setSelectedQuestion(question)}>
              View Details
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

function QuestionDetail({ question, onBack }) {
  const { dispute, disputeLoading, evidences } = useDisputeData(question);
  
  return (
    <div>
      <button onClick={onBack}>Back to List</button>
      <h2>{question.title}</h2>
      <p>{question.description}</p>
      
      <h3>Options:</h3>
      <ul>
        {question.options.map((option, i) => (
          <li key={i}>{option}</li>
        ))}
      </ul>
      
      <h3>Current Answer: {question.currentAnswer}</h3>
      <p>Current Bond: {question.currentBond}</p>
      
      <h3>Dispute Information:</h3>
      {disputeLoading ? (
        <p>Loading dispute data...</p>
      ) : dispute ? (
        <div>
          <p>Dispute ID: {dispute.id}</p>
          <p>Status: {dispute.ruled ? 'Ruled' : 'Pending'}</p>
          <p>Ruling: {dispute.ruling}</p>
          
          <h4>Evidence:</h4>
          {evidences.length > 0 ? (
            <ul>
              {evidences.map(e => (
                <li key={e.id}>
                  <h5>{e.URI_contents.name}</h5>
                  <p>{e.URI_contents.description}</p>
                  <small>From: {e.sender}</small>
                </li>
              ))}
            </ul>
          ) : (
            <p>No evidence submitted</p>
          )}
        </div>
      ) : (
        <p>No dispute found for this question</p>
      )}
    </div>
  );
}

Technical Details

Data Flow

  1. useQuestions fetches questions from The Graph subgraphs for the selected chain
  2. Questions are transformed and cached for performance
  3. When a specific question is selected, useDisputeData fetches dispute information
  4. Dispute data is retrieved through a combination of:
    • The Graph subgraphs for dispute details
    • RPC calls to determine dispute IDs
    • Bridge information to handle cross-chain disputes

Cross-Chain Support

Reality.eth questions can be created on one chain and have their disputes resolved on another. The library handles this complexity through:

  1. Bridge configurations that map home chains to foreign chains
  2. Automatic detection of the appropriate chain for dispute resolution
  3. Proper routing of RPC calls to the correct endpoints

Troubleshooting

Common Issues

  1. No questions loading: Verify the chain's subgraph URL is correct and accessible
  2. Dispute data not loading: Check that the question has an arbitrator assigned and that arbitration has been requested
  3. Missing evidence: Evidence may take time to be indexed by The Graph