zenith-docs/docs/api/zenith-watcher.md
2025-11-28 15:34:21 -05:00

405 lines
11 KiB
Markdown

# Zenith Watcher API
The Zenith Watcher indexes the Zenith blockchain across all network stages, providing access to account information, transactions, validators, scry bindings, and treasury claims.
**GraphQL Endpoint**: `https://zenith-watcher.zenith-test.tlon.systems/graphql`
## GraphQL API
### Query Account Information
```graphql
query GetAccount($address: String!) {
account(address: $address) {
address
balances {
denom
amount
}
transactions {
hash
type
timestamp
blockHeight
success
}
}
}
```
### Query Transactions
```graphql
query GetTransactions($address: String!, $limit: Int!) {
transactions(
where: {
or: [
{ sender: $address }
{ receiver: $address }
]
}
limit: $limit
orderBy: timestamp
orderDirection: desc
) {
hash
sender
receiver
amount
denom
timestamp
blockHeight
success
}
}
```
### Query Validators
```graphql
query GetValidators {
validators {
address
moniker
votingPower
commission
jailed
uptime
}
}
```
### Query Scry Bindings
```graphql
query GetScryBindings($path: String!) {
scryBindings(where: { path: $path }) {
path
hash
blockHeight
timestamp
signatures {
signer
signature
}
}
}
```
### Query Treasury Claims
```graphql
query GetClaims($address: String!) {
treasuryClaims(where: { claimer: $address }) {
claimer
amount
denom
timestamp
blockHeight
transactionHash
}
}
```
## REST API
The Zenith Watcher also provides REST API endpoints for querying scry oracle data.
### 1. Get Binding by Path
The `/laconic/scryoracle/v1/binding_by_path` API retrieves the binding (hash, block number, and block hash) for a specific path.
**Example:**
```bash
curl -X 'GET' -H 'accept: application/json' \
"http://127.0.0.1:3008/rest/laconic/scryoracle/v1/binding_by_path?path=/~zod/group-store/groups/random-group/json" | jq
```
**Response:**
```json
{
"binding": {
"hash": "d5af5fddee9de5cedbe1ad1df367f96f67347f8edaddef75",
"block_number": "23",
"block_hash": "a9521112d4ee58da8221c893c8dae465b236456c4becc25edffe85ae3b0ac15e"
},
"binding_with_verification": null
}
```
**With include_verification_data parameter:**
```bash
curl -X 'GET' -H 'accept: application/json' \
"http://127.0.0.1:3008/rest/laconic/scryoracle/v1/binding_by_path?path=/~zod/group-store/groups/random-group/json&include_verification_data=true" | jq
```
**Parameters:**
- `path` (required): The exact path to lookup
- `include_verification_data` (optional): Whether to return signature and life (default: false)
### 2. Get Bindings by Path Prefix
The `/laconic/scryoracle/v1/bindings_by_prefix` API gets path-to-hash mappings using a path prefix with support for both cursor-based and offset-based pagination.
#### Cursor-based Pagination
**Example - First page:**
```bash
curl -X 'GET' -H 'accept: application/json' \
"http://127.0.0.1:3008/rest/laconic/scryoracle/v1/bindings_by_prefix?path_prefix=/~zod&pagination.limit=3" | jq
```
**Response:**
```json
{
"path_bindings": {
"/~zod/group-store/groups/random-group/json": {
"hash": "d5af5fddee9de5cedbe1ad1df367f96f67347f8edaddef75",
"block_number": "23",
"block_hash": "a9521112d4ee58da8221c893c8dae465b236456c4becc25edffe85ae3b0ac15e"
},
"/~zod/group-store/members/random-group/json": {
"hash": "77873b7b96bd7f4d5bddff366ba6f6779738edad1fddef75",
"block_number": "23",
"block_hash": "a9521112d4ee58da8221c893c8dae465b236456c4becc25edffe85ae3b0ac15e"
},
"/~zod/metadata-store/associations/groups/random-group/json": {
"hash": "73b7b96bd77a6f47f5ddff367786b57366f97bd7f8edad37",
"block_number": "23",
"block_hash": "a9521112d4ee58da8221c893c8dae465b236456c4becc25edffe85ae3b0ac15e"
}
},
"pagination": {
"next_key": "eyJwYWdpbmF0aW9uX3NraXAiOjN9",
"total": "0"
}
}
```
!!! note "Using next_key"
Use `next_key` from pagination output of the above API response in a subsequent request (as `pagination.key`) to get the next page of results.
**Example - Next page using next_key:**
```bash
curl -X 'GET' -H 'accept: application/json' \
"http://127.0.0.1:3008/rest/laconic/scryoracle/v1/bindings_by_prefix?path_prefix=/~zod&pagination.key=eyJwYWdpbmF0aW9uX3NraXAiOjN9" | jq
```
#### Offset-based Pagination
**Example:**
```bash
curl -X 'GET' -H 'accept: application/json' \
"http://127.0.0.1:3008/rest/laconic/scryoracle/v1/bindings_by_prefix?path_prefix=/~zod&pagination.limit=10&pagination.offset=2&pagination.count_total=true" | jq
```
**Parameters:**
- `path_prefix` (required): The path prefix to match against
- `pagination.limit` (optional): Number of results per page (default: 100)
- `pagination.key` (optional): Base64-encoded cursor for next page
- `pagination.offset` (optional): Offset for traditional pagination (cannot be used with key)
- `pagination.count_total` (optional): Whether to return total count (default: false)
- `include_verification_data` (optional): Whether to return signature and life (default: false)
!!! warning "Pagination Note"
You cannot use both `pagination.key` and `pagination.offset` in the same request.
### 3. Get Bindings by Block Number
The `/laconic/scryoracle/v1/bindings_by_block_number` API gets path-to-hash mappings added at a specific block number.
**Example:**
```bash
curl -X 'GET' -H 'accept: application/json' \
"http://127.0.0.1:3008/rest/laconic/scryoracle/v1/bindings_by_block_number?block_number=25&path_prefix=/~zod" | jq
```
**Response:**
```json
{
"path_bindings": {
"/~zod/publish/comments/2025.3.6..15.30.20..0000/json": {
"hash": "6b477973b7fdd5ee9be367f76fd6b577cd9cd1fe3b7b9dda",
"block_number": "25",
"block_hash": "5a932989009ea3ed054e8a98752eea09384e3bf134ebeb833984f11e52ea8bf5"
},
"/~zod/publish/posts/2025.3.6..15.30.20..0000/json": {
"hash": "ddff757786bb6f4d9ce9ee5af5ff376f57397746b8ef67ba",
"block_number": "25",
"block_hash": "5a932989009ea3ed054e8a98752eea09384e3bf134ebeb833984f11e52ea8bf5"
}
}
}
```
**Parameters:**
- `block_number` (required): The block number to query
- `path_prefix` (optional): Filter results by path prefix
- `include_verification_data` (optional): Whether to return signature and life (default: false)
### 4. Get Bindings in Block Range
The `/laconic/scryoracle/v1/bindings_in_block_range` API gets path-to-hash mappings added within a block range.
**Example:**
```bash
curl -X 'GET' -H 'accept: application/json' \
"http://127.0.0.1:3008/rest/laconic/scryoracle/v1/bindings_in_block_range?from_block=10&to_block=100&path_prefix=/~zod/publish" | jq
```
**Response:**
```json
{
"path_bindings": {
"/~zod/publish/comments/2025.3.6..15.30.20..0000/json": {
"hash": "6b477973b7fdd5ee9be367f76fd6b577cd9cd1fe3b7b9dda",
"block_number": "25",
"block_hash": "5a932989009ea3ed054e8a98752eea09384e3bf134ebeb833984f11e52ea8bf5"
},
"/~zod/publish/posts/2025.3.6..15.30.20..0000/json": {
"hash": "ddff757786bb6f4d9ce9ee5af5ff376f57397746b8ef67ba",
"block_number": "25",
"block_hash": "5a932989009ea3ed054e8a98752eea09384e3bf134ebeb833984f11e52ea8bf5"
}
}
}
```
**Parameters:**
- `from_block` (required): Starting block number (inclusive)
- `to_block` (required): Ending block number (inclusive)
- `path_prefix` (optional): Filter results by path prefix
- `include_verification_data` (optional): Whether to return signature and life (default: false)
!!! note "Block Range Limit"
The block range is limited to 1000 blocks maximum.
### 5. Get Bindings by Wildcard Pattern
The `/laconic/scryoracle/v1/bindings_by_wildcard` API gets path-to-hash mappings using wildcard pattern matching with support for both cursor-based and offset-based pagination.
**Example - Match any path between ~zod and random-group/json:**
```bash
curl -X 'GET' -H 'accept: application/json' \
"http://127.0.0.1:3008/rest/laconic/scryoracle/v1/bindings_by_wildcard?path_pattern=/~zod/*/random-group/json" | jq
```
**Response:**
```json
{
"path_bindings": {
"/~zod/group-store/groups/random-group/json": {
"hash": "d5af5fddee9de5cedbe1ad1df367f96f67347f8edaddef75",
"block_number": "23",
"block_hash": "a9521112d4ee58da8221c893c8dae465b236456c4becc25edffe85ae3b0ac15e"
},
"/~zod/group-store/members/random-group/json": {
"hash": "77873b7b96bd7f4d5bddff366ba6f6779738edad1fddef75",
"block_number": "23",
"block_hash": "a9521112d4ee58da8221c893c8dae465b236456c4becc25edffe85ae3b0ac15e"
},
"/~zod/metadata-store/associations/groups/random-group/json": {
"hash": "73b7b96bd77a6f47f5ddff367786b57366f97bd7f8edad37",
"block_number": "23",
"block_hash": "a9521112d4ee58da8221c893c8dae465b236456c4becc25edffe85ae3b0ac15e"
}
},
"pagination": {
"next_key": null,
"total": "0"
}
}
```
**Parameters:**
- `path_pattern` (required): The wildcard pattern to match (use `*` for wildcard matching)
- `pagination.limit` (optional): Number of results per page (default: 100)
- `pagination.key` (optional): Base64-encoded cursor for next page
- `pagination.offset` (optional): Offset for traditional pagination (cannot be used with key)
- `pagination.count_total` (optional): Whether to return total count (default: false)
- `include_verification_data` (optional): Whether to return signature and life (default: false)
!!! warning "Pagination Note"
You cannot use both `pagination.key` and `pagination.offset` in the same request.
## Using the APIs
### With curl (GraphQL)
```bash
# Query Zenith Watcher
curl -X POST https://zenith-watcher.zenith-test.tlon.systems/graphql \
-H "Content-Type: application/json" \
-d '{
"query": "query { validators { moniker votingPower jailed } }"
}'
```
### With JavaScript/TypeScript (GraphQL)
```javascript
const query = `
query GetAccount($address: String!) {
account(address: $address) {
balances {
denom
amount
}
}
}
`;
const variables = { address: "zenith1..." };
const response = await fetch('https://zenith-watcher.zenith-test.tlon.systems/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables })
});
const data = await response.json();
```
### With GraphQL Client Libraries
```javascript
import { GraphQLClient } from 'graphql-request';
const client = new GraphQLClient(
'https://zenith-watcher.zenith-test.tlon.systems/graphql'
);
const query = `
query GetAccount($address: String!) {
account(address: $address) {
balances { denom amount }
}
}
`;
const data = await client.request(query, { address: 'zenith1...' });
```
## Rate Limiting and Best Practices
- **Rate Limits**: Public watcher endpoints have rate limiting in place. For production applications, consider running your own watcher instances.
- **Pagination**: Use pagination parameters for queries that return large result sets.
- **Caching**: Cache frequently accessed data to reduce API load.
- **Error Handling**: Implement proper error handling and retry logic for network failures.
!!! note "Watcher Documentation"
For more information about the watcher architecture and deployment, see the [Watchers documentation](../documentation/watchers.md).