Advertisement
We understand ads are no fun, but they are what makes Gridcoinstats possible.
No ad to show here right now. We understand ads are no fun, but they are what makes Gridcoinstats possible.
The ads are blocked in your browser. We understand ads are no fun, but they are what makes Gridcoinstats possible.
Advertisement
We understand ads are no fun, but they are what makes Gridcoinstats possible.
No ad to show here right now. We understand ads are no fun, but they are what makes Gridcoinstats possible.
The ads are blocked in your browser. We understand ads are no fun, but they are what makes Gridcoinstats possible.
Gridcoin Wallet API
read-onlyRead-only chain and governance data from a Gridcoin Research wallet, answered as JSON:API documents (application/vnd.api+json). Nothing here makes the wallet do something: every wallet call goes through a guard with an allowlist of read-only methods, a budget and stale answers, so the API keeps answering from its cache when the wallet is slow. Amounts are decimal strings with 8 decimals (GRC); times are Unix seconds. Two networks, named in the URL. For statistics from the cache database (lists, charts, supply) there is the Gridcoinstats API (/gridcoinstats/v4); this one is for what only the wallet knows. The groups are added one at a time; this description lists what exists.
It is for what only the wallet knows: the height of its chain, a block by its height or hash as the wallet has it, and the consensus rules by height. It never changes anything in the wallet. For lists, charts and the coin supply there is the Gridcoinstats API.
curl -s https://api.gridcoinstats.eu/wallet/v3/mainnet/status
Conventions
Answers are JSON:API documents (application/vnd.api+json). Every answer has jsonapi.version, data (or errors), meta.network and meta.version, and most have links.self.
Amounts are decimal strings with 8 decimals in GRC ("12.50000000"); the money supply is a float in the wallet, so it has about 7 reliable decimals. Times are Unix seconds. A claim field the wallet did not send for an old block is null.
Blocks come in pages. page[size] (default 25, at most 100), page[number] and sort=height or sort=-height (the default); meta.page and the links (first, prev, next, last) say where the page is. A block is also read by its height or its 64 character hash. There is no confirmations: it changes with every block, so subtract the height of the block from the tip in /status.
Caching. Every read sends Cache-Control: public, max-age=N, stale-while-revalidate=M and an ETag; ask again with If-None-Match and an unchanged answer is a 304. The deeper a block, the longer it is kept; errors are never cached.
Read only, open to any site. The API has no call that changes anything, and every wallet call goes through a guard that only lets read-only methods through. CORS is open (Access-Control-Allow-Origin: *), so a page on another site can read it. When the wallet is down /status and the blocks answer 503; the description, /protocol and the networks keep answering.
Errors and limits
An error is a JSON:API document with an errors list: status, title, detail, and for a wrong query parameter code and source.parameter.
| Status | When |
|---|---|
| 400 | A value out of range or of the wrong kind (`source.parameter` names it), or a parameter the endpoint does not take. |
| 404 | No such block (a height above the tip, or an unknown hash). |
| 405 | A method the API does not answer: it only reads. |
| 429 | More requests than the limit allows (60 a minute from one client by default, fewer for some groups). `Retry-After` says how long to wait. |
| 503 | The wallet is not reachable or is busy (`Retry-After` when the wallet guard says when to try again). Errors are never cached. |
The limit is 60 requests a minute from one client, all endpoints together, and at most 20 in 10 seconds; the answers carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a 429 has Retry-After. Only the requests that reach our server count: Cloudflare keeps an answer for its max-age. Poll no faster than the max-age of the endpoint.
Description
What the API is and links to the networks. No wallet is asked.
GET /wallet/v3
The API and its networks. What the API is, with a link to each network. No wallet is asked. Kept for 1 h.
curl -s "https://api.gridcoinstats.eu/wallet/v3"
An answer
{
"jsonapi": {
"version": "1.1"
},
"data": {
"type": "api",
"id": "wallet",
"attributes": {
"name": "Gridcoin Wallet API",
"description": "Read-only Gridcoin chain and governance data from a Gridcoin Research wallet",
"version": "3.0.0",
"networks": [
"mainnet",
"testnet"
]
}
},
"links": {
"self": "/wallet/v3",
"mainnet": "/wallet/v3/mainnet",
"testnet": "/wallet/v3/testnet"
},
"meta": {
"version": "3.0.0"
}
}
The 5 attributes
| AttributeType | Type | What |
|---|---|---|
| namestring | string | |
| descriptionstring | string | |
| versionstring | string | |
| networkstring | string | |
| networksarray | array |
GET /wallet/v3/{network}
One network. The description of one network, with the link to `status`. No wallet is asked. Kept for 1 h.
| ParameterIn · type | In | Type | What |
|---|---|---|---|
| networkpath, required · string: mainnet, testnet | path, required | string: mainnet, testnet | The network. |
curl -s "https://api.gridcoinstats.eu/wallet/v3/mainnet"
An answer
{
"jsonapi": {
"version": "1.1"
},
"data": {
"type": "api",
"id": "wallet",
"attributes": {
"name": "Gridcoin Wallet API",
"description": "Read-only Gridcoin chain and governance data from a Gridcoin Research wallet",
"version": "3.0.0",
"network": "mainnet"
}
},
"links": {
"self": "/wallet/v3/mainnet",
"status": "/wallet/v3/mainnet/status"
},
"meta": {
"network": "mainnet",
"version": "3.0.0"
}
}
The 5 attributes
| AttributeType | Type | What |
|---|---|---|
| namestring | string | |
| descriptionstring | string | |
| versionstring | string | |
| networkstring | string | |
| networksarray | array |
Status
Whether the wallet answers and how high its chain is.
GET /wallet/v3/{network}/status
The wallet's chain height. The height of the chain as the wallet sees it: the answer to "is the wallet caught up". It asks the wallet (through the wallet guard), so it is a 503 while the wallet is down. Kept for 15 s.
| ParameterIn · type | In | Type | What |
|---|---|---|---|
| networkpath, required · string: mainnet, testnet | path, required | string: mainnet, testnet | The network. |
curl -s "https://api.gridcoinstats.eu/wallet/v3/mainnet/status"
An answer
{
"jsonapi": {
"version": "1.1"
},
"data": {
"type": "status",
"id": "wallet",
"attributes": {
"height": 3300784
}
},
"meta": {
"network": "mainnet",
"version": "3.0.0"
},
"links": {
"self": "/wallet/v3/mainnet/status"
}
}
The 1 attributes
| AttributeType | Type | What |
|---|---|---|
| heightinteger | integer | The wallet's chain height. |
Protocol
The consensus rules by height. Static.
GET /wallet/v3/{network}/protocol
The consensus rules by height. The network's consensus rules and when each block version and height-gated feature switches on. Static: no wallet is asked, so it answers while the wallet is down. `active_from_height` is the first block height a rule applies to, or `null` while it is not active on that network. Kept for 1 h.
| ParameterIn · type | In | Type | What |
|---|---|---|---|
| networkpath, required · string: mainnet, testnet | path, required | string: mainnet, testnet | The network. |
curl -s "https://api.gridcoinstats.eu/wallet/v3/mainnet/protocol"
An answer
{
"jsonapi": {
"version": "1.1"
},
"data": {
"type": "protocol",
"id": "mainnet",
"attributes": {
"network": "mainnet",
"last_pow_block": 2050,
"target_spacing_seconds": 90,
"superblock_spacing_seconds": 86400,
"max_block_size": 1000000,
"coinbase_maturity": 100,
"stake_min_age_seconds": 57600,
"gates": [
{
"name": "protocol_v2",
"title": "Protocol v2: 90 second block spacing",
"block_version": null,
"active_from_height": 85401
},
{
"name": "superblock_spacing_24h",
"title": "Superblock spacing 24 hours instead of 12 hours (testnet always 24 hours)",
"block_version": null,
"active_from_height": 364500
},
{
"name": "research_age",
"title": "Research age",
"block_version": null,
"active_from_height": 364501
}
]
}
},
"meta": {
"network": "mainnet",
"version": "3.0.0"
},
"links": {
"self": "/wallet/v3/mainnet/protocol"
}
}
The 8 attributes
| AttributeType | Type | What |
|---|---|---|
| networkstring | string | |
| last_pow_blockinteger | integer | The last proof-of-work block. |
| target_spacing_secondsinteger | integer | The block spacing now (60 seconds before `protocol_v2`). |
| superblock_spacing_secondsinteger | integer | The superblock spacing now (12 hours before `superblock_spacing_24h`). |
| max_block_sizeinteger | integer | |
| coinbase_maturityinteger | integer | Blocks before a reward can be spent. |
| stake_min_age_secondsinteger | integer | How long coins rest before they stake. |
| gatesarray | array | Each block version (8 to 15) and each height-gated feature. |
Blocks
Blocks of the chain as the wallet has them.
GET /wallet/v3/{network}/blocks
A page of blocks. A page of blocks, newest first by default, straight from the wallet. `meta.page` and the pagination `links` say where the page is; a page past the end is an empty list. Kept for 30 s.
| ParameterIn · type | In | Type | What |
|---|---|---|---|
| networkpath, required · string: mainnet, testnet | path, required | string: mainnet, testnet | The network. |
| page[size]query · integer (default 25) | query | integer (default 25) | How many blocks on a page. At most 100 by default (the operator can lower it). |
| page[number]query · integer (default 1) | query | integer (default 1) | The page, from 1. |
| sortquery · string: height, -height (default -height) | query | string: height, -height (default -height) | `-height` is the newest first, `height` the oldest first. |
curl -sg "https://api.gridcoinstats.eu/wallet/v3/mainnet/blocks?page[size]=5"
An answer
{
"jsonapi": {
"version": "1.1"
},
"data": [
{
"type": "block",
"id": "3300784",
"attributes": {
"hash": "0000000000000000000000000000000000000000000000000000000000325db0",
"height": 3300784,
"in_best_chain": true,
"time": 1760000000,
"size": 1873,
"version": 13,
"merkle_root": "abababababababababababababababababababababababababababababababab",
"previous_block_hash": "0000000000000000000000000000000000000000000000000000000000325daf",
"next_block_hash": "0000000000000000000000000000000000000000000000000000000000325db1",
"difficulty": 1.5,
"bits": "1a0ffff0",
"nonce": 0,
"flags": "proof-of-stake",
"proof_hash": "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
"mint": "12.50000000",
"money_supply": "478123456.78000000",
"fees_collected": "0.01000000",
"mrc_foundation_fees": "0.00000000",
"mrc_staker_fees": "0.00000000",
"is_superblock": false,
"is_contract": false,
"claim": {
"mining_id": "INVESTOR",
"client_version": "5.4.8.0",
"block_subsidy": "12.50000000",
"research_subsidy": "0.00000000",
"magnitude": 0,
"magnitude_unit": 0.25
},
"tx_count": 2,
"tx": [
"2222222222222222222222222222222222222222222222222222222222222222",
"3333333333333333333333333333333333333333333333333333333333333333"
]
},
"links": {
"self": "/wallet/v3/mainnet/blocks/3300784",
"prev": "/wallet/v3/mainnet/blocks/3300783",
"next": "/wallet/v3/mainnet/blocks/3300785"
}
},
{
"type": "block",
"id": "3300783",
"attributes": {
"hash": "0000000000000000000000000000000000000000000000000000000000325daf",
"height": 3300783,
"in_best_chain": true,
"time": 1760000000,
"size": 1873,
"version": 13,
"merkle_root": "abababababababababababababababababababababababababababababababab",
"previous_block_hash": "0000000000000000000000000000000000000000000000000000000000325dae",
"next_block_hash": "0000000000000000000000000000000000000000000000000000000000325db0",
"difficulty": 1.5,
"bits": "1a0ffff0",
"nonce": 0,
"flags": "proof-of-stake",
"proof_hash": "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
"mint": "12.50000000",
"money_supply": "478123456.78000000",
"fees_collected": "0.01000000",
"mrc_foundation_fees": "0.00000000",
"mrc_staker_fees": "0.00000000",
"is_superblock": false,
"is_contract": false,
"claim": {
"mining_id": "INVESTOR",
"client_version": "5.4.8.0",
"block_subsidy": "12.50000000",
"research_subsidy": "0.00000000",
"magnitude": 0,
"magnitude_unit": 0.25
},
"tx_count": 2,
"tx": [
"2222222222222222222222222222222222222222222222222222222222222222",
"3333333333333333333333333333333333333333333333333333333333333333"
]
},
"links": {
"self": "/wallet/v3/mainnet/blocks/3300783",
"prev": "/wallet/v3/mainnet/blocks/3300782",
"next": "/wallet/v3/mainnet/blocks/3300784"
}
}
],
"meta": {
"page": {
"number": 1,
"size": 2,
"total": 3300785,
"totalPages": 1650393
},
"network": "mainnet",
"version": "3.0.0"
},
"links": {
"self": "/wallet/v3/mainnet/blocks?page[size]=2&page[number]=1",
"first": "/wallet/v3/mainnet/blocks?page[size]=2&page[number]=1",
"next": "/wallet/v3/mainnet/blocks?page[size]=2&page[number]=2",
"last": "/wallet/v3/mainnet/blocks?page[size]=2&page[number]=1650393"
}
}
The 24 attributes
| AttributeType | Type | What |
|---|---|---|
| hashstring | string | The block hash, 64 hex characters. |
| heightinteger | integer | The block height. |
| in_best_chainboolean | boolean | `false` for a block dropped in a reorganisation. |
| timeinteger | integer | Unix seconds. |
| sizeinteger | integer | Bytes. |
| versioninteger | integer | The block version: which rules it was made under (see `/protocol`). |
| merkle_rootstring | string | |
| previous_block_hashstring or null | string or null | The hash of the block before (null for the first block). |
| next_block_hashstring or null | string or null | The hash of the next block (null at the tip). |
| difficultynumber | number | |
| bitsstring | string | |
| nonceinteger | integer | |
| flagsstring | string | `proof-of-stake` or `proof-of-work`. |
| proof_hashstring or null | string or null | The proof hash, null when the wallet sends none. |
| mintstring | string | The coins created, GRC with 8 decimals. |
| money_supplystring | string | The wallet's money supply after the block. The wallet keeps it as a float, so it has about 7 reliable decimals. |
| fees_collectedstring | string | GRC with 8 decimals. |
| mrc_foundation_feesstring | string | Zero before block version 12. |
| mrc_staker_feesstring | string | Zero before block version 12. |
| is_superblockboolean | boolean | |
| is_contractboolean | boolean | The block carries a contract. |
| claimobject | object | |
| tx_countinteger | integer | |
| txarray | array | The transaction ids. |
GET /wallet/v3/{network}/blocks/{id}
One block. One block by its height or its 64 character hash: the same resource either way, and its `id` is always the height. A block dropped in a reorganisation can still be fetched by hash (`in_best_chain` is `false`). There is no `confirmations`: it changes with every block, so subtract the block's height from the tip in `/status`. The deeper a block, the longer it is cached.
| ParameterIn · type | In | Type | What |
|---|---|---|---|
| networkpath, required · string: mainnet, testnet | path, required | string: mainnet, testnet | The network. |
| idpath, required · string | path, required | string | The block height, or its 64 character hash. |
curl -s "https://api.gridcoinstats.eu/wallet/v3/mainnet/blocks/3300784"
An answer
{
"jsonapi": {
"version": "1.1"
},
"data": {
"type": "block",
"id": "3300784",
"attributes": {
"hash": "0000000000000000000000000000000000000000000000000000000000325db0",
"height": 3300784,
"in_best_chain": true,
"time": 1760000000,
"size": 1873,
"version": 13,
"merkle_root": "abababababababababababababababababababababababababababababababab",
"previous_block_hash": "0000000000000000000000000000000000000000000000000000000000325daf",
"next_block_hash": "0000000000000000000000000000000000000000000000000000000000325db1",
"difficulty": 1.5,
"bits": "1a0ffff0",
"nonce": 0,
"flags": "proof-of-stake",
"proof_hash": "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
"mint": "12.50000000",
"money_supply": "478123456.78000000",
"fees_collected": "0.01000000",
"mrc_foundation_fees": "0.00000000",
"mrc_staker_fees": "0.00000000",
"is_superblock": false,
"is_contract": false,
"claim": {
"mining_id": "INVESTOR",
"client_version": "5.4.8.0",
"block_subsidy": "12.50000000",
"research_subsidy": "0.00000000",
"magnitude": 0,
"magnitude_unit": 0.25
},
"tx_count": 2,
"tx": [
"2222222222222222222222222222222222222222222222222222222222222222",
"3333333333333333333333333333333333333333333333333333333333333333"
]
},
"links": {
"self": "/wallet/v3/mainnet/blocks/3300784",
"prev": "/wallet/v3/mainnet/blocks/3300783",
"next": "/wallet/v3/mainnet/blocks/3300785"
}
},
"meta": {
"network": "mainnet",
"version": "3.0.0"
}
}
The 24 attributes
| AttributeType | Type | What |
|---|---|---|
| hashstring | string | The block hash, 64 hex characters. |
| heightinteger | integer | The block height. |
| in_best_chainboolean | boolean | `false` for a block dropped in a reorganisation. |
| timeinteger | integer | Unix seconds. |
| sizeinteger | integer | Bytes. |
| versioninteger | integer | The block version: which rules it was made under (see `/protocol`). |
| merkle_rootstring | string | |
| previous_block_hashstring or null | string or null | The hash of the block before (null for the first block). |
| next_block_hashstring or null | string or null | The hash of the next block (null at the tip). |
| difficultynumber | number | |
| bitsstring | string | |
| nonceinteger | integer | |
| flagsstring | string | `proof-of-stake` or `proof-of-work`. |
| proof_hashstring or null | string or null | The proof hash, null when the wallet sends none. |
| mintstring | string | The coins created, GRC with 8 decimals. |
| money_supplystring | string | The wallet's money supply after the block. The wallet keeps it as a float, so it has about 7 reliable decimals. |
| fees_collectedstring | string | GRC with 8 decimals. |
| mrc_foundation_feesstring | string | Zero before block version 12. |
| mrc_staker_feesstring | string | Zero before block version 12. |
| is_superblockboolean | boolean | |
| is_contractboolean | boolean | The block carries a contract. |
| claimobject | object | |
| tx_countinteger | integer | |
| txarray | array | The transaction ids. |
Advertisement
We understand ads are no fun, but they are what makes Gridcoinstats possible.
No ad to show here right now. We understand ads are no fun, but they are what makes Gridcoinstats possible.
The ads are blocked in your browser. We understand ads are no fun, but they are what makes Gridcoinstats possible.
Advertisement
We understand ads are no fun, but they are what makes Gridcoinstats possible.
No ad to show here right now. We understand ads are no fun, but they are what makes Gridcoinstats possible.
The ads are blocked in your browser. We understand ads are no fun, but they are what makes Gridcoinstats possible.
Advertisement
We understand ads are no fun, but they are what makes Gridcoinstats possible.
No ad to show here right now. We understand ads are no fun, but they are what makes Gridcoinstats possible.
The ads are blocked in your browser. We understand ads are no fun, but they are what makes Gridcoinstats possible.
Advertisement
We understand ads are no fun, but they are what makes Gridcoinstats possible.
No ad to show here right now. We understand ads are no fun, but they are what makes Gridcoinstats possible.
The ads are blocked in your browser. We understand ads are no fun, but they are what makes Gridcoinstats possible.
