NEAR Protocol exposes a JSON-RPC 2.0 API with NEAR-specific methods like status, block, chunk, gas_price, tx, query, and validators, rather than EVM-style eth_* calls. The API can be served by a self-hosted near-core node, a hosted provider, or supplemented by indexer/archival services for historical data. Correctness depends on understanding NEAR's finality model—optimistic versus final—which affects transaction confirmation and block queries. Running a node requires a Rust toolchain and significant resources, and syncing can be done from genesis or a snapshot. Verifying an endpoint involves checking chain_id, block height advancement, and state queries to detect stale or dishonest nodes. Common errors include UNKNOWN_BLOCK, 'does not exist while viewing', and gas_price failures on unsynced nodes.
NEAR's Sharded Architecture and JSON-RPC Surface
NEAR Protocol is a sharded, account-based Layer 1 blockchain that uses a Nightshade-style sharded block production model. Unlike EVM chains where a single state trie is accessed via eth_* methods, NEAR's state is partitioned across shards, and its JSON-RPC API reflects this with methods such as status, block, chunk, gas_price, tx, query, and validators. This means existing EVM tooling and libraries cannot be used directly; developers must adapt to NEAR's method names and data structures.
The JSON-RPC 2.0 specification defines the request/response envelope, while NEAR's API documentation details the method semantics. The API is served by near-core nodes and hosted providers, with indexer services like NEAR Indexer Framework and NEAR Lake providing historical and aggregate queries. A plain node efficiently serves recent data, but historical queries may require an archival node.
- NEAR uses sharded state, so some queries resolve against a specific shard or chunk.
- Method names are NEAR-specific: status, block, chunk, gas_price, tx, query, validators.
- EVM tooling does not apply directly; NEAR SDKs and libraries are required.
Data Access Layers: Node, Provider, and Indexer
There are three primary ways to access NEAR data: (1) a self-hosted near-core node serving the JSON-RPC API, (2) a hosted provider offering the same API, and (3) indexer/archival services for historical and aggregate queries. Each has trade-offs. A self-hosted node gives you full control and data locality but requires significant resources and maintenance. Hosted providers offer convenience and reliability but may have rate limits or costs. Indexer services are essential for querying historical data beyond the node's retention window.
For most developers, a hosted provider is sufficient for recent data, but if you need to query old blocks or run analytics, an archival node or indexer is necessary. The NEAR documentation provides an introduction to the JSON-RPC API and endpoints.
- Self-hosted node: full control, requires Rust toolchain, CPU/RAM/disk, and sync time.
- Hosted provider: convenience, but check rate limits and data retention.
- Indexer/archival: for historical queries, aggregates, and analytics.
Key JSON-RPC Methods and Their Returns
The status method returns node identity, chain ID, sync state, and latest block height/hash. block and chunk return block and chunk data by height or hash, with finality options. gas_price provides fee estimation. tx returns transaction status and receipts. query is used for account state and contract view calls via the view-only path. validators returns the current validator set.
The query method is particularly important for reading account balances and contract state. According to the NEAR documentation on the query method, it supports account and contract state queries. Understanding these methods is crucial for building reliable applications.
- status: node identity, chain ID, sync state, latest block height/hash.
- block/chunk: block and chunk data by height/hash, with finality.
- gas_price: fee estimation.
- tx: transaction status and receipts.
- query: account state and contract view calls.
- validators: current validator set.
# Status: node identity, chain id and sync state
curl -s -X POST https://rpc.mainnet.near.org \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"status","params":[]}' | jq '.result.chain_id, .result.sync_info.latest_block_height'
# Block by finality: pass "final" or "optimistic" to choose the confirmation level
curl -s -X POST https://rpc.mainnet.near.org \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"block","params":{"finality":"final"}}' | jq '.result.header.height, .result.header.hash'
# query: read account state or call a view method (read-only, no gas)
curl -s -X POST https://rpc.mainnet.near.org \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"query","params":{"request_type":"view_account","finality":"final","account_id":"near"}}' | jq '.result.amount, .result.block_height'Finality: Optimistic vs Final and Its Impact
NEAR distinguishes between optimistic and final finality. When you query a block or transaction, you must specify which finality you want. Optimistic finality means the block is likely to be finalized but not yet guaranteed; final finality means the block is irreversible. This affects payment confirmation: for high-value transactions, you should wait for final finality. The NEAR finality documentation explains this in detail.
Choosing the wrong finality can lead to incorrect assumptions about transaction success. For example, querying a transaction with optimistic finality might show it as successful, but it could still be reverted. Always use final finality for critical operations.
- Optimistic finality: block is likely final but not guaranteed.
- Final finality: block is irreversible.
- Use final finality for payment confirmation and critical state changes.
Running a NEAR Node to Serve the JSON-RPC API
To run a NEAR node, you need to build near-core from source, which requires a Rust toolchain and non-trivial CPU, RAM, and disk resources. The node can sync from genesis or from a documented data snapshot. Once synced, it exposes the JSON-RPC endpoint on a configured port (default 3030).
The process involves cloning the nearcore repository, building with cargo, and configuring the node. Detailed instructions are available in the NEAR documentation. For developers familiar with other protocols, the setup is similar to running a full node on other networks, such as Aptos full node requirements and RPC setup or TON node and RPC API integration.
- Requires Rust toolchain and significant hardware resources.
- Sync from genesis or a snapshot (snapshot trades trust for speed).
- Default JSON-RPC port is 3030.
Verifying a NEAR JSON-RPC Endpoint
To verify that a NEAR JSON-RPC endpoint is live and honest, start by calling status and confirming the reported chain_id and latest block height. Then call block at the reported height and confirm the hash matches. Finally, call query for a known account to confirm state reads work. This detects an endpoint that is up but stale.
You can use curl or a Node.js script to perform these checks. Below is a runnable Node.js example that POSTs the status, block, and query methods and prints the returned block height and account balance.
const fetch = require('node-fetch');
async function checkEndpoint(url) {
const statusRes = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'status', params: [] })
});
const status = await statusRes.json();
console.log('Chain ID:', status.result.chain_id);
console.log('Latest block height:', status.result.sync_info.latest_block_height);
const blockRes = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 2, method: 'block', params: { finality: 'final' } })
});
const block = await blockRes.json();
console.log('Block hash:', block.result.header.hash);
const queryRes = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 3, method: 'query', params: { request_type: 'view_account', finality: 'final', account_id: 'example.near' } })
});
const query = await queryRes.json();
console.log('Account balance:', query.result.amount);
}
checkEndpoint('https://rpc.mainnet.near.org');Reproducible Endpoint Verification with a Results Table
To make verification reproducible, record the following metrics for your endpoint: reported chain_id, latest height at T0 and T1, finality used, and query latency. Fill in the table below with your own measurements. This method does not rely on invented numbers and allows you to compare endpoints objectively.
- Chain ID: [your value]
- Latest height at T0: [your value]
- Latest height at T1: [your value]
- Finality used: [optimistic/final]
- Query latency (ms): [your value]
Common Failures and Troubleshooting
When working with NEAR JSON-RPC, you may encounter errors such as UNKNOWN_BLOCK or 'does not exist while viewing' when a block is not yet finalised. gas_price calls may fail on a node that is not fully synced. Archive or legacy queries may fail on a non-archival node. These issues often stem from finality choices or node sync state.
To troubleshoot, ensure you are using the correct finality parameter, check that your node is fully synced, and verify that you are querying an archival node for historical data. For general JSON-RPC troubleshooting, see JSON-RPC vs gRPC vs REST.
- UNKNOWN_BLOCK: block not yet finalised; use final finality or wait.
- 'does not exist while viewing': account or contract state not available at that block.
- gas_price failure: node not fully synced.
- Archive query failure: node is not archival.
Trade-offs and Limitations of Self-Hosted Nodes
Running a self-hosted NEAR node involves trade-offs. Sharded state means some queries resolve against a specific shard or chunk, which can complicate data aggregation. Snapshot-based sync trades trust for speed, as you rely on the snapshot provider. A self-hosted node is justified only when query volume or data locality beats a managed endpoint.
For many developers, a hosted provider is more cost-effective and reliable. However, if you need full control, custom indexing, or low-latency access to specific shards, a self-hosted node may be necessary. Consider your use case carefully before committing to node operation.
- Sharded state: queries may need to target specific shards.
- Snapshot sync: faster but requires trust in the snapshot provider.
- Self-hosting: justified for high query volume or data locality.
Next Steps and Further Resources
To continue learning about NEAR and other protocols, explore the OnFinality Learn hub. For pricing and API service details, see RPC pricing and API service. If you are interested in other networks, check out Polkadot network guide and Substrate state_getMetadata and runtime versions.
For NEAR-specific development, refer to the official NEAR documentation and consider using a hosted provider for production workloads. Self-hosting is an option for advanced users with specific requirements.
- Explore OnFinality Learn for more protocol guides.
- Check RPC pricing and API service pages for managed options.
- Review sibling guides for other networks.