405 lines
11 KiB
Markdown
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).
|