# Proof Explorer Data Schema + API Docs
The proof explorer is a frontend that displays useful information about the Saturn proof aggregation contract. Here is a rough sketch of the information it should display:

## Information Flow
1. [The Graph Protocol](https://thegraph.com/docs/en/developing/creating-a-subgraph/) will dump contract data into a PostgresQL database.
2. The Graph Protocol also makes this database easily queryable via GraphQL, according to a schema we define in the [GraphQL Schema](#GraphQL-Schema) section.
3. Our custom `data-fetcher` TypeScript package wraps useful GraphQL queries. This package can then be used by the frontend. See [here](https://github.com/NebraZKP/Saturn/tree/main/data-fetcher) for an outdated example of a `data-fetcher` package. Preliminary API for the `data-fetcher` package in the [data-fetcher](#Data-Fetcher-API) section.
## GraphQL Schema
Therefore, we also set our GraphQL schema this way.
The `ProofData` entity consists of:
1. An `id` which is its `proofId`
2. `submitProofBlockTimestamp` is the timestamp of the block in which this proof was submitted to the `Saturn` contract.
3. `circuitId`.
4. `proofIdx`
5. `publicInputs`
6. `verifiedProofBlockTimestamp` is timestamp of block which this proof was verified OR null if it has not been verified.
7. `verifiedProofTxHash` is tx hash of proof verification tx OR null if proof has not been verified.
```graphql!
type ProofData @entity {
id: Bytes! # proofId
submittedProofBlockTimestamp: BigInt!
circuitId: Bytes!
proofIdx: BigInt!
publicInputs: [BigInt!]
verifiedProofBlockTimestamp: BigInt
verifiedProofTxHash: Bytes # txHash
}
type CircuitState @entity {
id: Bytes! # circuitId
lastVerifiedProofIdx: BigInt!
}
```
## Data Fetcher API
```typescript=
// Used for getting data within a certain block timestamp range
// Allows us to NOT reload all data on every query
// Instead we query for all data since last queried timestamp
enum SupportedNetwork {
SEPOLIA = "sepolia",
HARDHAT = "hardhat",
}
type TimestampOptions = {
blockTimestamp?: Date;
blockTimestampGte?: Date;
blockTimestampLte?: Date;
};
type ProofDataResponse = {
id: string;
submitProofBlockTimestamp: BigInt;
circuitId: string;
proofIdx: BigInt;
publicInputs: BigInt[];
verifiedProofBlockTimestamp: BigInt | null;
verifiedProofTxHash: string | null;
};
type CircuitStateResponse = {
id: string;
lastVerifiedProofIdx: BigInt;
};
/**
* Returns CircuitState for a given circuitId. Useful for getting lastVerifiedProofIdx.
* @param circuitId Circuit ID. Expected to be hex string.
*/
async getCircuitState(circuitId: string): Promise<CircuitStateResponse>
/**
* @param circuitId Circuit ID. Expected to be hex string.
* @param lastVerifiedProofIdx Last verified proof index for the circuitId.
* @param first Number of proofs to fetch (max 1000).
* @param skip Number of proofs to skip (useful if need to query in batches)
* @param options Options to select the pending proofs timetamp parameters.
* @returns List of pending proofs by circuitId
*/
async getPendingProofsByCircuitId(
circuitId: string,
lastVerifiedProofIdx: BigInt,
options: TimestampOptions = {},
first: number = 1000,
skip: number = 0
): Promise<ProofDataResponse[]>
/**
* @param circuitId Circuit ID. Expected to be hex string.
* @param lastVerifiedProofIdx Last verified proof index for the circuitId.
* @param first Number of proofs to fetch (max 1000).
* @param skip Number of proofs to skip (useful if need to query in batches)
* @param options Options to select the proofs timetamp parameters.
* @returns List of rejected proofs by circuitId
*/
async getRejectedProofsByCircuitId(
circuitId: string,
lastVerifiedProofIdx: BigInt,
options: TimestampOptions = {},
first: number = 1000,
skip: number = 0
): Promise<ProofDataResponse[]>
/**
* @param first Number of proofs to fetch (max 1000).
* @param skip Number of proofs to skip (useful if need to query in batches)
* @param options Options to select the proofs timetamp parameters.
* @returns List of verified proofs
*/
async getVerifiedProofs(
options: TimestampOptions = {},
first: number = 1000,
skip: number = 0
): Promise<ProofDataResponse[]>
/**
* @param proofId
* @returns proof with a particular proofId
*/
async getProofByProofId(proofId: string): Promise<ProofDataResponse>
/**
* @param circuitId
* @param first Number of proofs to fetch.
* @param skip Number of proofs to skip (useful if need to query in batches)
* @returns proofs with a particular circuitId
*/
async getProofsByCircuitId(
circuitId: string,
first: number = 1000,
skip: number = 0
): Promise<ProofDataResponse[]>
```