Temporal RPC Quickstart

Query finalized temporal data without losing nanosecond precision.

Build with ROKO nanosecond time

ROKO timestamps ordinary EVM and Substrate transactions automatically. A user does not submit a special “timed transaction” envelope.

Know which time you are reading

ValueMeaning
mesh consensus timethe node's current PTP² mesh estimate
canonical transaction timestamptimestamp assigned to a transaction
transaction watermarkhighest canonical timestamp processed by chain state
block nanosecond timestamptemporal metadata attached to a block
EVM block.timestampconventional EVM seconds, not ROKO nanoseconds

Nanosecond representation does not promise nanosecond wall-clock accuracy. Inspect convergence, peer count, time quality, source distance, and application latency.

Query mesh time

curl --fail --silent --show-error https://rpc.roko.network \
  -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"temporal_getConsensusTime","params":[]}'

Current shape:

{
  "consensusTimeNs": "1785196016508998403",
  "timeQuality": 7697,
  "convergenceState": "Converged",
  "peerCount": 5,
  "consensusOffsetNs": "-1062154"
}

Treat the value as authoritative for your use only when convergenceState == "Converged" and your policy accepts the quality and peer count. timeQuality uses 0..10,000, where 10,000 is 100%.

Query a transaction

Both a Substrate extrinsic hash and an Ethereum transaction hash are accepted:

curl --fail --silent --show-error https://rpc.roko.network \
  -H 'content-type: application/json' \
  --data '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"temporal_getTransactionTimestamp",
    "params":["<32_BYTE_TRANSACTION_HASH>"]
  }'

The result is a decimal nanosecond string or null when unknown.

For finality-aware processing:

  1. subscribe to or poll finalized heads;
  2. resolve the finalized block number/hash;
  3. call temporal_getBlockTransactionTimestamps;
  4. correlate substrateHash or ethHash;
  5. store timestampNs as a decimal string or arbitrary-precision integer.

Precision rules

Unix nanoseconds are already larger than JavaScript's Number.MAX_SAFE_INTEGER.

const ns = BigInt(response.result.consensusTimeNs);
const seconds = ns / 1_000_000_000n;
const subsecondNs = ns % 1_000_000_000n;

Never call Number() on a full nanosecond value. Convert only a bounded display unit after checking its range. JSON.stringify also rejects BigInt, so serialize nanoseconds back to decimal strings.

Python's int preserves these values:

ns = int(result["consensusTimeNs"])
seconds, subsecond_ns = divmod(ns, 1_000_000_000)

Current wire-format caveat

Most current temporal RPC nanosecond fields are quoted decimal strings. The legacy temporal_getWatermarkInfo and temporal_getBlockMetadata responses can still contain unquoted JSON integers larger than JavaScript's safe range. Native JSON.parse() can round those values before application code sees them. Until those RPCs emit strings consistently, use a lossless/BigInt JSON parser or query them from a language such as Python with arbitrary-precision JSON integers.

Useful methods

MethodUse
temporal_getConsensusTimecurrent mesh estimate and quality
temporal_getMeshStateconvergence and per-peer measurement summary
temporal_getWatermarkInfocurrent transaction watermark
temporal_getTransactionTimestampcanonical timestamp by transaction hash
temporal_getBlockMetadatatemporal metadata for a block number
temporal_getBlockTransactionTimestampshashes and timestamps by extrinsic index
temporal_getQueueStatslocal fee-priority queue statistics
temporal_getTransactionWaitTimelocal queue timing for one transaction
temporal_getRecentWaitTimesrecent local wait-time samples

Queue statistics are node-local and can reset on restart. Historical data may require an archive node.

Examples

See examples/temporal-rpc:

  • Node.js reads string-encoded nanoseconds as BigInt;
  • Python preserves all JSON integer precision and polls finalized temporal block metadata.

Failure handling

  • null means “not available/known,” not timestamp zero.
  • Reject malformed or non-32-byte transaction hashes.
  • Apply an HTTP timeout and exponential backoff.
  • Use finalized heads when reorganization would be harmful.
  • Degrade gracefully when the mesh is initializing, converging, degraded, or below your minimum peer/quality policy.
  • Verify chain genesis and EVM chain ID before trusting an endpoint.