Public API.
Read-only, with no names, contacts or KYC data. Aggregate endpoints feed this explorer; per-address endpoints serve holder applications with pseudonymous data only – pseudonymous addresses can still be personal data under the GDPR, which is why they are gated. Aggregate endpoints need no authentication; fair-use rate limits apply.
Endpoints
Base URL https://explorer.blockgns.com/v1 (also served at https://rpc.blockgns.com/v1). JSON, CORS enabled, UTC timestamps as Unix seconds, amounts as decimal strings.
JSON-RPC
Standard Ethereum JSON-RPC, read methods only (eth_*, net_*, web3_*, qbft_*), batches up to 50 calls. Writes are not accepted on the public endpoint.
curl -s https://rpc.blockgns.com -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockByNumber","params":["latest",false]}'Chain metadata
EIP-3085 style description for wallets and integrators, plus genesis hash, validator set, contract addresses and API locations.
curl -s https://explorer.blockgns.com/.well-known/genesis.json
Event stream
Server-Sent Events for dashboards, the NRDK and other policy-enforcement points: one event per block (with recovered signers), per audit anchor and per daily snapshot. Reconnects automatically; no polling.
curl -N https://explorer.blockgns.com/v1/events
event: block
data: {"number":725,"txs":0,"proposer":"0x2e3b…","signers":["0x2712…","0x9f20…","0xa19e…"],"verified":true}Holder applications
Per-address endpoints (/holders/{address}, /holders/{address}/transfers, /snapshots/{date}/proof/{address}) require an application key issued to holder apps, until the data-protection review clears public address-level access.
curl -H 'Authorization: Bearer <application key>' \ https://explorer.blockgns.com/v1/holders/0x…
Daily balance snapshots
Once a day the observer reads every balance of both tokens at one block, builds a Merkle tree per token and anchors the SHA-256 of the public snapshot in GenesisAuditAnchor (record type DAILY_SNAPSHOT). The public snapshot holds roots and totals only; balances stay off the public page. A holder proves inclusion with a Merkle proof.
- Leaf:
keccak256(abi.encode(address token, address holder, uint256 balance))for every address with a non-zero balance at the snapshot block. - Tree: leaves sorted ascending; each level hashes sorted pairs
keccak256(min ‖ max); an odd last node is carried up unchanged (OpenZeppelin MerkleProof compatible). - Snapshot hash: SHA-256 of the canonical JSON of the public snapshot without the
snapshotHashandanchorfields; it is therecordHashanchored on chain. - Proof:
GET /v1/snapshots/{date}/proof/{address}returns the leaf, the sibling hashes and the root; recompute upwards and compare with the root in the snapshot, then check the snapshot hash against the anchor.
// verify an inclusion proof (ethers v6) let h = proof.leaf; for (const p of proof.proof) h = h.toLowerCase() < p.toLowerCase() ? ethers.keccak256(ethers.concat([h, p])) : ethers.keccak256(ethers.concat([p, h])); console.log(h === proof.root); // true = balance included in the anchored snapshot
Audit anchor ledger
Every record ever anchored in GenesisAuditAnchor, newest first. Types: control-plane decisions, issuance batches, supervisory and daily snapshots, explorer builds.
| # | Type | Record hash | Writer | Block | Time |
|---|