DocsThe data protocol
snapshot/v1
packages/core/schema/snapshot.schema.jsonOn this page
One network population at one moment. Every input module outputs this. Named by the SHA-256 of its RFC 8785 canonical JSON bytes. See data-model.md.
Fields
| Field | Type or allowed values | Presence in its parent | Description |
|---|---|---|---|
petal |
"snapshot/v1" | Required | |
network |
object | Required | |
network.id |
string | Required | |
network.chain |
string | Required | CAIP-2 chain id, or 'none' for non-chain networks |
network.population |
string | Required | |
network.title |
string | Required | |
network.description |
string | Optional | |
network.params |
object | Optional | |
network.params.* |
string | Optional | |
snapshot |
object | Required | |
snapshot.as_of |
string | Required | |
snapshot.block_height |
integer | Optional | |
snapshot.block_hash |
string | Optional | |
snapshot.epoch |
object | Optional | |
snapshot.window |
object | Optional | |
snapshot.window.from |
string | Optional | |
snapshot.window.to |
string | Optional | |
snapshot.window.from_block |
integer | Optional | |
snapshot.window.to_block |
integer | Optional | |
snapshot.window.note |
string | Optional | |
snapshot.final |
boolean | Required | true when every read was at a final block; only final snapshots are reused forever |
coverage |
object | Required | |
coverage.participants_total |
integer | Required | |
coverage.participants_included |
integer | Required | |
coverage.amount_total |
string | Required | |
coverage.amount_included |
string | Required | |
coverage.unit |
string | Required | |
coverage.measure |
string | Required | the holdings measure that the totals refer to |
coverage.grouped |
array | Optional | |
coverage.grouped[] |
object | Required | |
coverage.grouped[].rule |
string | Required | |
coverage.grouped[].rows_folded |
integer | Required | |
coverage.grouped[].amount |
string | Required | |
coverage.partial |
boolean | Optional | |
coverage.failed_sources |
array | Optional | |
coverage.failed_sources[] |
string | Required | |
coverage.note |
string | Optional | |
sources |
array | Required | |
sources[] |
object | Required | |
sources[].id |
string | Required | |
sources[].kind |
"chain" / "api" / "docs" / "forum" / "constitution" / "dataset" | Required | |
sources[].url |
string | Required | |
sources[].method |
string | Optional | |
sources[].fetched_at |
string | Required | |
sources[].block_height |
integer | Optional | |
participants |
array | Required | |
participants[] |
object | Required | |
participants[].id |
string | Required | |
participants[].label |
string | Required | |
participants[].kind |
"person" / "organisation" / "mining_pool" / "validator" / "staking_pool" / "staking_entity" / "delegator" / "exchange" / "custodian" / "contract" / "treasury" / "group" / "unknown" | Required | |
participants[].identity |
choice | Required | |
participants[].identity (variant 1) |
null | Required | |
participants[].identity (variant 2) |
object | Required | |
participants[].identity (variant 2).name |
string | Required | |
participants[].identity (variant 2).source |
string | Required | |
participants[].identity (variant 2).status |
"self-declared" / "verified" / "inferred" | Required | |
participants[].identity (variant 2).url |
string | Optional | |
participants[].roles |
array | Optional | |
participants[].roles[] |
string | Required | |
participants[].count |
integer | Optional | only for kind=group: how many accounts the row folds |
participants[].source |
string | Required | |
participants[].detail |
object | Optional | |
holdings |
array | Required | |
holdings[] |
object | Required | |
holdings[].participant |
string | Required | |
holdings[].asset |
string | Required | |
holdings[].measure |
string | Required | |
holdings[].amount |
string | Required | how much, in whole tokens (or whole units of what unit names), as decimal text: never a JSON number, so every digit survives hashing |
holdings[].amount_raw |
string | Optional | the same in the chain's base units, amount times ten to the token's decimals, as whole-number text |
holdings[].unit |
string | Required | what amount counts: a token's symbol, or a word such as votes |
holdings[].as_of |
string | Required | |
holdings[].source |
string | Required | |
relationships |
array | Required | |
relationships[] |
object | Required | |
relationships[].from |
string | Required | |
relationships[].to |
string | Required | |
relationships[].type |
string | Required | delegates_to, owned_by, member_of_role, holds_role:, proposed, voted:, ... |
relationships[].amount |
string | Optional | how much, in whole tokens (or whole units of what unit names), as decimal text: never a JSON number, so every digit survives hashing |
relationships[].amount_raw |
string | Optional | the same in the chain's base units, amount times ten to the token's decimals, as whole-number text |
relationships[].unit |
string | Optional | what amount counts: a token's symbol, or a word such as votes |
relationships[].role |
string | Optional | |
relationships[].bps |
integer | Optional | |
relationships[].as_of |
string | Required | |
relationships[].date_is |
string | Optional | when as_of is a proxy, say what it is (e.g. 'proposal submission_time') |
relationships[].source |
string | Required | |
relationships[].detail |
object | Optional | |
events |
array | Required | |
events[] |
object | Required | |
events[].participant |
string | Required | |
events[].type |
string | Required | |
events[].at |
string | Required | |
events[].detail |
object | Optional | |
events[].source |
string | Required | |
module |
object | Required | |
module.id |
string | Required | |
module.version |
string | Required | |
module.imported_from |
string | Optional | set when built from a stored file, e.g. research/data/near/producers.json |
Examples
snapshot.v1.json
{
"petal": "snapshot/v1",
"network": {
"id": "sample-pools",
"chain": "near:mainnet",
"population": "validators",
"title": "Two sample pools"
},
"snapshot": {
"as_of": "2026-11-03T19:42:00Z",
"block_height": 222915356,
"final": true
},
"coverage": {
"participants_total": 3,
"participants_included": 3,
"amount_total": "3000",
"amount_included": "3000",
"unit": "NEAR",
"measure": "validator_stake_current_epoch",
"grouped": [
{
"rule": "delegates_to rows under 1,000 NEAR, one group row per pool",
"rows_folded": 12,
"amount": "1000.5"
}
]
},
"sources": [
{
"id": "rpc-validators",
"kind": "chain",
"url": "https://rpc.mainnet.fastnear.com",
"method": "validators",
"fetched_at": "2026-11-03T19:42:00Z",
"block_height": 222915356
}
],
"participants": [
{
"id": "a.pool.near",
"label": "a.pool.near",
"kind": "staking_pool",
"identity": {
"name": "A",
"source": "rpc-validators",
"status": "self-declared"
},
"source": "rpc-validators"
},
{
"id": "b.pool.near",
"label": "b.pool.near",
"kind": "staking_pool",
"identity": null,
"source": "rpc-validators"
},
{
"id": "group:b.pool.near:other",
"label": "12 delegators under 1,000 NEAR",
"kind": "group",
"identity": null,
"count": 12,
"source": "rpc-validators"
}
],
"holdings": [
{
"participant": "a.pool.near",
"asset": "NEAR",
"measure": "validator_stake_current_epoch",
"amount": "2000",
"amount_raw": "2000000000000000000000000000",
"unit": "NEAR",
"as_of": "2026-11-03T19:42:00Z",
"source": "rpc-validators"
},
{
"participant": "b.pool.near",
"asset": "NEAR",
"measure": "validator_stake_current_epoch",
"amount": "1000.5",
"unit": "NEAR",
"as_of": "2026-11-03T19:42:00Z",
"source": "rpc-validators"
}
],
"relationships": [
{
"from": "group:b.pool.near:other",
"to": "b.pool.near",
"type": "delegates_to",
"amount": "1000.5",
"unit": "NEAR",
"as_of": "2026-11-03T19:42:00Z",
"source": "rpc-validators"
}
],
"events": [],
"module": {
"id": "sample",
"version": "0.0.0"
}
}
Full schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:petal:schema:snapshot:v1",
"title": "Petal snapshot (common table) v1",
"description": "One network population at one moment. Every input module outputs this. Named by the SHA-256 of its RFC 8785 canonical JSON bytes. See data-model.md.",
"type": "object",
"required": [
"petal",
"network",
"snapshot",
"coverage",
"sources",
"participants",
"holdings",
"relationships",
"events",
"module"
],
"additionalProperties": false,
"properties": {
"petal": {
"const": "snapshot/v1"
},
"network": {
"type": "object",
"required": [
"id",
"chain",
"population",
"title"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9-]*$"
},
"chain": {
"type": "string",
"description": "CAIP-2 chain id, or 'none' for non-chain networks",
"pattern": "^([-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}|none)$"
},
"population": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"params": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"snapshot": {
"type": "object",
"required": [
"as_of",
"final"
],
"additionalProperties": false,
"properties": {
"as_of": {
"$ref": "#/$defs/datetime"
},
"block_height": {
"type": "integer",
"minimum": 0
},
"block_hash": {
"type": "string"
},
"epoch": {
"type": "object",
"additionalProperties": true
},
"window": {
"type": "object",
"additionalProperties": false,
"properties": {
"from": {
"$ref": "#/$defs/datetime"
},
"to": {
"$ref": "#/$defs/datetime"
},
"from_block": {
"type": "integer"
},
"to_block": {
"type": "integer"
},
"note": {
"type": "string"
}
}
},
"final": {
"type": "boolean",
"description": "true when every read was at a final block; only final snapshots are reused forever"
}
}
},
"coverage": {
"type": "object",
"required": [
"participants_total",
"participants_included",
"amount_total",
"amount_included",
"unit",
"measure"
],
"additionalProperties": false,
"properties": {
"participants_total": {
"type": "integer",
"minimum": 0
},
"participants_included": {
"type": "integer",
"minimum": 0
},
"amount_total": {
"$ref": "#/$defs/decimal"
},
"amount_included": {
"$ref": "#/$defs/decimal"
},
"unit": {
"type": "string"
},
"measure": {
"type": "string",
"description": "the holdings measure that the totals refer to"
},
"grouped": {
"type": "array",
"items": {
"type": "object",
"required": [
"rule",
"rows_folded",
"amount"
],
"additionalProperties": false,
"properties": {
"rule": {
"type": "string"
},
"rows_folded": {
"type": "integer",
"minimum": 0
},
"amount": {
"$ref": "#/$defs/decimal"
}
}
}
},
"partial": {
"type": "boolean"
},
"failed_sources": {
"type": "array",
"items": {
"type": "string"
}
},
"note": {
"type": "string"
}
}
},
"sources": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"id",
"kind",
"url",
"fetched_at"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"kind": {
"enum": [
"chain",
"api",
"docs",
"forum",
"constitution",
"dataset"
]
},
"url": {
"type": "string"
},
"method": {
"type": "string"
},
"fetched_at": {
"$ref": "#/$defs/datetime"
},
"block_height": {
"type": "integer"
}
}
}
},
"participants": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"label",
"kind",
"identity",
"source"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"label": {
"type": "string"
},
"kind": {
"$ref": "#/$defs/kind"
},
"identity": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/$defs/identity"
}
]
},
"roles": {
"type": "array",
"items": {
"type": "string"
}
},
"count": {
"type": "integer",
"minimum": 1,
"description": "only for kind=group: how many accounts the row folds"
},
"source": {
"type": "string"
},
"detail": {
"type": "object"
}
}
}
},
"holdings": {
"type": "array",
"items": {
"type": "object",
"required": [
"participant",
"asset",
"measure",
"amount",
"unit",
"as_of",
"source"
],
"additionalProperties": false,
"properties": {
"participant": {
"type": "string"
},
"asset": {
"type": "string"
},
"measure": {
"type": "string"
},
"amount": {
"$ref": "#/$defs/decimal",
"description": "how much, in whole tokens (or whole units of what unit names), as decimal text: never a JSON number, so every digit survives hashing"
},
"amount_raw": {
"type": "string",
"pattern": "^[0-9]+$",
"description": "the same in the chain's base units, amount times ten to the token's decimals, as whole-number text"
},
"unit": {
"type": "string",
"description": "what amount counts: a token's symbol, or a word such as votes"
},
"as_of": {
"$ref": "#/$defs/datetime"
},
"source": {
"type": "string"
}
}
}
},
"relationships": {
"type": "array",
"items": {
"type": "object",
"required": [
"from",
"to",
"type",
"as_of",
"source"
],
"additionalProperties": false,
"properties": {
"from": {
"type": "string"
},
"to": {
"type": "string"
},
"type": {
"type": "string",
"description": "delegates_to, owned_by, member_of_role, holds_role:*, proposed, voted:*, ..."
},
"amount": {
"$ref": "#/$defs/decimal",
"description": "how much, in whole tokens (or whole units of what unit names), as decimal text: never a JSON number, so every digit survives hashing"
},
"amount_raw": {
"type": "string",
"pattern": "^[0-9]+$",
"description": "the same in the chain's base units, amount times ten to the token's decimals, as whole-number text"
},
"unit": {
"type": "string",
"description": "what amount counts: a token's symbol, or a word such as votes"
},
"role": {
"type": "string"
},
"bps": {
"type": "integer",
"minimum": 0,
"maximum": 10000
},
"as_of": {
"$ref": "#/$defs/datetime"
},
"date_is": {
"type": "string",
"description": "when as_of is a proxy, say what it is (e.g. 'proposal submission_time')"
},
"source": {
"type": "string"
},
"detail": {
"type": "object"
}
}
}
},
"events": {
"type": "array",
"items": {
"type": "object",
"required": [
"participant",
"type",
"at",
"source"
],
"additionalProperties": false,
"properties": {
"participant": {
"type": "string"
},
"type": {
"type": "string"
},
"at": {
"$ref": "#/$defs/datetime"
},
"detail": {
"type": "object"
},
"source": {
"type": "string"
}
}
}
},
"module": {
"type": "object",
"required": [
"id",
"version"
],
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"version": {
"type": "string"
},
"imported_from": {
"type": "string",
"description": "set when built from a stored file, e.g. research/data/near/producers.json"
}
}
}
},
"$defs": {
"datetime": {
"type": "string",
"format": "date-time"
},
"decimal": {
"type": "string",
"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
},
"kind": {
"enum": [
"person",
"organisation",
"mining_pool",
"validator",
"staking_pool",
"staking_entity",
"delegator",
"exchange",
"custodian",
"contract",
"treasury",
"group",
"unknown"
]
},
"identity": {
"type": "object",
"required": [
"name",
"source",
"status"
],
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"source": {
"type": "string"
},
"status": {
"enum": [
"self-declared",
"verified",
"inferred"
]
},
"url": {
"type": "string"
}
}
}
}
}