dig-rpc-types
Pure serde-derived JSON-RPC wire types for the DIG Network fullnode / validator / future wallet RPC surface. The single source of truth for every request and response shape exchanged between a DIG server and its clients.
- No I/O — no tokio, no reqwest, no Axum in the default build.
- No business logic — a method's wire shape is defined; dispatch lives elsewhere.
- Stable error codes —
ErrorCodenumeric values never change once assigned. - Additive enum evolution — every enum is
#[non_exhaustive]. - JSON-RPC 2.0 strict — request/response envelopes match the spec exactly.
See docs/resources/SPEC.md for the design doc.
Table of contents
- Install
- At-a-glance
- Quick reference
- Envelope types
ErrorCode- Shared domain types
- Fullnode methods
- Validator methods
- Stability contract
- Feature flags
- License
Install
[]
= "0.1"
Minimum Rust: 1.70. Zero optional features are required for the core wire types.
At-a-glance
| Module | Re-exported at crate root | Role |
|---|---|---|
envelope |
✓ | JSON-RPC 2.0 request / response / error / id / version |
errors |
✓ | Stable numeric error codes (ErrorCode) |
types |
✓ (partial) | Shared domain types (HashHex, PubkeyHex, SignatureHex, Amount, BlockSummary, ValidatorSummary, ValidatorStatus) |
fullnode |
— | 21 fullnode RPC method pairs |
validator |
— | 9 validator RPC method pairs |
Every method's request carries a pub const METHOD: &'static str for the wire name (GetBlockchainStateRequest::METHOD == "get_blockchain_state").
Quick reference
use ;
// Build a request.
let req: = JsonRpcRequest ;
// Decode a typed response off the wire.
let raw = r#"{"jsonrpc":"2.0","id":1,"result":{
"height": 100, "tip_hash":"0x1111111111111111111111111111111111111111111111111111111111111111",
"synced":true,"sync_progress":1.0,"finalized_epoch": 3, "sealed_height": 95
}}"#;
let _resp: = from_str.unwrap;
Envelope types
Module: dig_rpc_types::envelope. All re-exported at the crate root.
JsonRpcRequest<P = serde_json::Value>
Inputs to construct: any P that implements Serialize. For typed requests, use the method-specific {Method}Request types under fullnode:: / validator:: as P. For generic proxies, leave P = serde_json::Value.
Output on the wire: {"jsonrpc":"2.0","id":...,"method":"...","params":...} — params is omitted entirely when None.
JsonRpcResponse<R = serde_json::Value>
Output on the wire: exactly one of {"jsonrpc":"2.0","id":...,"result":...} or {"jsonrpc":"2.0","id":...,"error":{...}} — never both, never neither. This is enforced by the untagged enum.
JsonRpcError
Inputs: code is any ErrorCode variant; message is a human-readable short description; data carries optional structured context.
RequestId
Echoed unchanged in the matching response.
Version
; // ZST; serde impls hard-code "2.0"
Rejecting any string other than "2.0" at deserialize time is structural — no hand-coded check needed.
ErrorCode
Module: dig_rpc_types::errors. Re-exported at the crate root.
#[repr(i32)], #[non_exhaustive], Serialize_repr / Deserialize_repr — serialises as a bare integer on the wire, matching JSON-RPC 2.0.
Variants and wire values
| Variant | Value | Range | When |
|---|---|---|---|
ParseError |
-32700 |
JSON-RPC reserved | Invalid JSON received |
InvalidRequest |
-32600 |
JSON-RPC reserved | JSON valid but not a Request |
MethodNotFound |
-32601 |
JSON-RPC reserved | Unknown method |
InvalidParams |
-32602 |
JSON-RPC reserved | Params don't match schema |
InternalError |
-32603 |
JSON-RPC reserved | Server bug / panic caught |
NotSynced |
10001 |
DIG sync/auth | Server not yet synced; data may be stale |
PeerUnauthorized |
10002 |
DIG sync/auth | Client cert unresolved to a role |
PermissionDenied |
10003 |
DIG sync/auth | Role below method's min_role |
RateLimited |
10004 |
DIG sync/auth | Per-peer token bucket exhausted |
ResourceNotFound |
10005 |
DIG sync/auth | Block / coin / validator not found |
SlashingGuardBlocked |
10010 |
DIG crypto | Validator's local slashing DB vetoed the sig |
InvalidSignature |
10011 |
DIG crypto | BLS signature failed verification |
InvalidProof |
10012 |
DIG crypto | Groth16 / other ZK proof failed |
L1Unavailable |
10020 |
DIG L1 | Cannot reach Chia L1 |
WalletLocked |
10030 |
DIG wallet | Wallet must unlock before signing |
ShutdownPending |
10040 |
DIG lifecycle | Server shutting down |
NetworkMismatch |
10050 |
DIG protocol | Client/server network id mismatch |
VersionMismatch |
10051 |
DIG protocol | Client/server schema major mismatch |
Helpers
| Method | Signature | Purpose |
|---|---|---|
code |
self -> i32 |
Raw numeric value |
is_jsonrpc_reserved |
self -> bool |
In -32768..=-32000 |
is_dig_specific |
self -> bool |
In 10000.. |
Shared domain types
Module: dig_rpc_types::types. HashHex, PubkeyHex, SignatureHex, Amount, BlockSummary, ValidatorSummary, ValidatorStatus are re-exported at the crate root.
Hex-encoded byte arrays
| Type | Byte length | Wire form | Use |
|---|---|---|---|
HashHex |
32 | "0x" + 64 lowercase hex chars |
Block hash, coin id, state root, beacon-block root |
PubkeyHex |
48 | "0x" + 96 lowercase hex chars |
BLS12-381 G1 compressed pubkey |
SignatureHex |
96 | "0x" + 192 lowercase hex chars |
BLS12-381 G2 compressed signature |
All three share the same contract:
- Construct —
T::new([u8; N])isconst fn. - Serialize —
"0x"+ lowercase hex. - Deserialize — accepts upper / lower / mixed case, optional
0xprefix. FromStr— returnsHexParseErroron length mismatch or invalid hex.as_bytes() -> &[u8; N]— borrow the underlying bytes.
HexParseError
Amount
; // mojos; 1 XCH = 10^12 mojos
Serialises as a bare JSON number. Safe for amounts up to 2^53 − 1 mojos (~9000 XCH) before JavaScript's float precision kicks in.
BlockSummary
Returned by get_block_records and embedded in get_blockchain_state.
ValidatorStatus
Wire form: "pending_register", "active", etc.
ValidatorSummary
Fullnode methods
Module: dig_rpc_types::fullnode. Every method has a {Method}Request + {Method}Response pair and a const METHOD: &'static str on the request.
Blockchain state
| Method | Request fields | Response fields |
|---|---|---|
get_blockchain_state |
— | height: u64, tip_hash: HashHex, synced: bool, sync_progress: f32, finalized_epoch: u64, sealed_height: u64 |
get_network_info |
— | network_id: String, genesis_challenge: HashHex, chain_age_seconds: u64 |
healthz |
— | ok: bool |
Blocks
| Method | Request fields | Response fields |
|---|---|---|
get_block |
hash: HashHex |
block: Option<BlockFull> |
get_block_by_height |
height: u64 |
block: Option<BlockFull> |
get_block_records |
start_height: u64, count: u32 |
records: Vec<BlockSummary> |
BlockFull carries {header: BlockHeaderWire, body_hex: String, canonical: bool}. BlockHeaderWire carries {height, hash, parent_hash, timestamp, proposer, state_root, receipts_root, weight, total_iters: u128, signature: SignatureHex}.
Coins
| Method | Request fields | Response fields |
|---|---|---|
get_coin_record |
coin_id: HashHex |
record: Option<CoinRecordWire> |
get_coin_records_by_hint |
hint: HashHex, include_spent_coins: bool, start_height?: u64, end_height?: u64 |
records: Vec<CoinRecordWire> |
get_coin_records_by_puzzle_hash |
puzzle_hash: HashHex, include_spent_coins: bool, start_height?: u64, end_height?: u64 |
records: Vec<CoinRecordWire> |
CoinRecordWire = {coin_id, parent_coin_info, puzzle_hash, amount: Amount, confirmed_block_height, spent_block_height, coinbase: bool, timestamp}.
Mempool
| Method | Request fields | Response fields |
|---|---|---|
get_mempool |
— | total_cost: u64, total_fees: Amount, items: Vec<MempoolItem> |
push_tx |
spend_bundle_hex: String |
status: PushTxStatus, details?: String |
MempoolItem = {spend_bundle_name: HashHex, cost: u64, fee: Amount, is_cpfp: bool}.
PushTxStatus = "success" / "rejected" / "already_exists".
Peers
| Method | Request fields | Response fields |
|---|---|---|
get_connections |
— | peers: Vec<PeerInfoWire> |
ban_peer |
peer_id: HashHex, reason: String, duration_secs: u64 |
banned: bool |
PeerInfoWire = {peer_id, remote_addr, node_type, connected_since: u64, penalty: u32}.
Checkpoint
| Method | Request fields | Response fields |
|---|---|---|
submit_partial_checkpoint_signature |
epoch: u64, validator_index: u32, partial_sig: SignatureHex |
accepted: bool, reason?: String |
get_checkpoint_pool |
epoch?: u64 |
epochs: Vec<CheckpointEpochStatus> |
CheckpointEpochStatus = {epoch, partials_count, threshold, aggregated}.
Validator set
| Method | Request fields | Response fields |
|---|---|---|
get_validator |
pubkey: PubkeyHex |
validator: Option<ValidatorSummary> |
get_active_validators |
limit: u32, offset: u32 |
validators: Vec<ValidatorSummary>, total: u32 |
get_current_proposer |
height: u64 |
proposer: Option<ValidatorSummary> |
Admin
| Method | Request fields | Response fields |
|---|---|---|
stop_node |
reason?: String |
accepted: bool |
get_recovery_status |
— | mode: RecoveryMode, last_anomaly?: String, attempts: u32 |
get_version |
— | version: String, build_commit: String |
RecoveryMode = "running" / "recovering" / "loop_breaker_open".
Validator methods
Module: dig_rpc_types::validator. Smaller, operator-facing surface.
Status
| Method | Request fields | Response fields |
|---|---|---|
get_status |
— | pubkey: PubkeyHex, validator_index?: u32, can_participate: bool, last_duty_at?: u64, active_connections: u32 |
get_duty_history |
limit: u32, since?: u64 |
entries: Vec<DutyEntry> |
DutyEntry = {at: u64, kind: DutyKind, ok: bool, detail?: String}.
DutyKind = "propose" / "attest" / "sign_checkpoint" / "observe_l1".
Helper: validator::now_unix_seconds() -> u64 for populating since.
Slashing DB
| Method | Request fields | Response fields |
|---|---|---|
get_slashing_db |
— | last_proposed_slot: u64, last_attested_source: u64, last_attested_target: u64, last_attested_root: HashHex |
export_slashing_db |
path: String |
written_bytes: u64 |
reset_slashing_db |
confirm_token: String |
reset: bool |
Admin
| Method | Request fields | Response fields |
|---|---|---|
stop_node |
reason?: String |
accepted: bool |
reload_config |
— | accepted: bool, applied_changes: Vec<String> |
healthz |
— | ok: bool |
get_version |
— | version: String, build_commit: String |
Stability contract
- Every enum is
#[non_exhaustive]— adding variants is additive. ErrorCodenumeric values never change once assigned. New variants take the next unused integer.- Method names are snake_case and stable.
- Hex-encoded fields emit
0x+ lowercase; accept case-insensitive + optional0xon parse. - Response envelopes are valid JSON-RPC 2.0 — exactly one of
resultorerror. SCHEMA_VERSIONconstant ("1") is bumped on wire-breaking changes.
Versioning policy
- Additive changes (new methods, new optional fields, new enum variants) → bump minor. Older clients continue to work.
- Removing or reshaping a field → bump major. Servers may serve multiple majors behind
/v1/,/v2/URL prefixes.
Feature flags
| Flag | Default | Effect |
|---|---|---|
client |
off | Optional blocking reqwest-backed client (not implemented in v0.1) |
schema-export |
off | JSON-Schema dumps via schemars for Go/TS codegen |
License
Licensed under either of Apache-2.0 or MIT at your option.