JSON-RPC overview
NULL exposes two JSON-RPC 2.0 services over HTTP: the node, nulld, for chain, mempool and mining data, and the wallet daemon, null-wallet-rpc, for addresses, balances, deposits and withdrawals. This page covers what they have in common. The method pages list every call.
A shielded-only chain
Integration guides for Bitcoin-like coins assume things that are not true here. Read this before you design a deposit or payout system.
- The chain shows no addresses and no amounts. Every output is encrypted. No call returns the balance of an address or the transactions sent to an address. Deposits are found by trial-decrypting outputs with a viewing key, and the wallet daemon does that for you. That is why there are two services: the node holds no keys, and the wallet daemon holds the keys of one wallet.
- Sending takes seconds. Every payment carries a zero-knowledge proof. Proving takes about a second for a small transaction and about five seconds for a 16-action one. Send calls (
sendmany,consolidate) return an operation id at once, and you poll the operation until it is confirmed. - The node builds the coinbase. The coinbase is a shielded transaction with its own proof, so a pool cannot assemble it from a script.
getblocktemplatetakes your payout address, builds and proves the coinbase, and returns the exact header bytes to grind. - One key, many addresses. A wallet derives as many diversified addresses as you need from one key, and its viewing key detects payments to all of them. Give every customer their own deposit address; you never manage per-customer keys.
- Batching is built in. A transaction holds up to 16 actions at a fixed fee of 10,000 units per action. One withdrawal can pay up to 15 recipients plus change.
- Every output has a memo. A 512-byte encrypted memo travels with each output, readable only by the recipient and the sender.
Coinbase rewards mature after 100 blocks on mainnet. The network refuses reorganizations deeper than 200 blocks. See Exchanges and Mining pools for walk-throughs.
The two services
- Name
nulld- Type
- node
- Description
Serves chain, transaction, mempool, peer, mining and disclosure-verification methods on the address given to
--rpc-http. Holds no keys. A mining pool needs only this service.
- Name
null-wallet-rpc- Type
- wallet daemon
- Description
Holds one wallet file. Syncs from a node through the node's control socket (
--rpc,127.0.0.1:18444by default) and serves the wallet methods on its own listener with its own token,127.0.0.1:18447by default. An exchange runs one node and one or more wallet daemons, for example a hot wallet and a watch-only deposit wallet.
Both binaries ship in the release archives at github.com/NullNetProtocol/null-chain/releases.
Enable the node RPC
The node's JSON-RPC listener is off until you pass --rpc-http. It has no default address; these docs use 127.0.0.1:18446.
nulld run --network main --rpc-http 127.0.0.1:18446
The listener uses the same token as the control socket. Pass it with --rpc-token or the NULL_RPC_TOKEN variable. If you give none, the node generates one and writes it to rpc.token in its data directory. The default data directory is <user data>/main/chain/, where <user data> is ~/.local/share/null on Linux, ~/Library/Application Support/Null on macOS and %LOCALAPPDATA%\Null on Windows. With --datadir the token is written there instead. The node prints the token location at startup.
TOKEN=$(cat ~/.local/share/null/main/chain/rpc.token)
--blocknotify '<command>' runs a shell command on every new main-chain tip, with %s replaced by the block hash. See Run a node for the other flags.
Enable the wallet daemon
Create the wallet file first with nulld create (see Command line), then start the daemon:
export NULL_WALLET_PASSPHRASE='the wallet passphrase'
null-wallet-rpc --wallet /srv/hot/hot.redb --network main \
--node 127.0.0.1:18444 \
--node-token-file ~/.local/share/null/main/chain/rpc.token \
--listen 127.0.0.1:18447
WALLET_TOKEN=$(cat /srv/hot/wallet-rpc.token)
- Name
--wallet- Type
- path
- Description
The wallet file. Defaults to
<user data>/main/wallet.redb. The daemon refuses to start if the file does not exist.
- Name
--network- Type
- main | test
- Description
Defaults to
main.
- Name
--node- Type
- host:port
- Description
The node's control socket. Defaults to
127.0.0.1:18444.
- Name
--node-token, --node-token-file- Type
- string, path
- Description
The node's token, or a file holding it. Also read from
NULL_RPC_TOKEN. Defaults to therpc.tokena defaultnulld runwrites.
- Name
--listen- Type
- host:port
- Description
Where the wallet JSON-RPC listens. Defaults to
127.0.0.1:18447.
- Name
--token- Type
- string
- Description
The token the wallet JSON-RPC demands. Also read from
NULL_WALLET_RPC_TOKEN. If omitted, a random token is written towallet-rpc.tokennext to the wallet file.
- Name
--sync-interval- Type
- seconds
- Description
Time between syncs from the node. Defaults to 2.
- Name
--light- Type
- flag
- Description
Scan compact blocks instead of full blocks. Faster, but memos are not recovered.
The wallet passphrase comes from NULL_WALLET_PASSPHRASE or an interactive prompt.
Both listeners should stay on localhost. The token is the only protection, and the wallet daemon can spend funds. If another host needs access, put your own authenticated proxy or tunnel in front.
Transport and conventions
- HTTP POST, JSON-RPC 2.0. One
POSTper connection, to any path. The body is a call object or a batch array, up to 32 MB. Every call carries"jsonrpc": "2.0"and a stringmethod. - Authentication. Send
Authorization: Bearer <token>on every request. - Parameters are positional (an array) or named (an object):
{"params": [6200]}and{"params": {"height": 6200}}are the same call.paramsmay be omitted when a method takes none. Anullvalue counts as omitted. - Batches. Send an array of calls. The answers come back as an array in the same order, one per call. An empty array is an error.
- Amounts are integers in the smallest unit, written as decimal strings so they never lose precision in a JSON number. 1 NULL is
100000000units. The wallet daemon also accepts whole JSON numbers for amounts in requests. - Hex. Hashes, txids, nullifiers, keys, blocks and transactions are lowercase hex. Block hashes and txids are 32 bytes (64 hex characters).
- Numbers. Heights, counts, sizes and timestamps (Unix seconds) are JSON numbers.
- Compact targets are 8 hex characters without
0x, for example"1e11e4e5". Branch ids are0xand 8 hex characters, for example"0x4d41494e". - Addresses are bech32m text:
null1…on mainnet,tnull1…on testnet. Full viewing keys arenullview1…andtnullview1…. - Confirmations count the block itself: a transaction in the tip block has 1.
Single call
curl -s http://127.0.0.1:18446/ \
-H "Authorization: Bearer $TOKEN" \
-d '{"jsonrpc":"2.0","id":1,"method":"getblockhash","params":{"height":6200}}'
Response
{
"jsonrpc": "2.0",
"result": "0000041e3f6c9e069db217c9e40e047f0ef33e9113bb066fb106c1c83a7414f6",
"id": 1
}
Batch
curl -s http://127.0.0.1:18446/ \
-H "Authorization: Bearer $TOKEN" \
-d '[{"jsonrpc":"2.0","id":"a","method":"getblockcount"},
{"jsonrpc":"2.0","id":"b","method":"nosuchmethod"}]'
Response
[
{ "jsonrpc": "2.0", "result": 6206, "id": "a" },
{
"jsonrpc": "2.0",
"error": { "code": -32601, "message": "unknown method nosuchmethod" },
"id": "b"
}
]
Errors
Transport failures get an HTTP error status with a JSON-RPC error body and "id": null: 400 for a malformed HTTP request, 405 for a method other than POST, 401 for a missing or wrong token. Everything else is HTTP 200 with either a result or an error object. An error has a numeric code and a message. Both services use the same codes.
- Name
-32700- Type
- parse error
- Description
The body is not JSON.
- Name
-32600- Type
- invalid request
- Description
Not a JSON-RPC 2.0 call:
jsonrpcis not"2.0",methodis missing or not a string,paramsis neither an array nor an object, or the batch is empty. Also sent for a malformed HTTP request (HTTP 400) and a non-POST method (HTTP 405).
- Name
-32601- Type
- method not found
- Description
Unknown method.
- Name
-32602- Type
- invalid params
- Description
A parameter is missing or has the wrong type, hex is invalid or the wrong length, or an address does not decode for this network.
- Name
-32603- Type
- internal error
- Description
The service failed while serving the call.
- Name
-32001- Type
- unauthorized
- Description
Token missing or wrong. Sent with HTTP 401.
- Name
-1- Type
- not found
- Description
The block, transaction, operation or output does not exist.
- Name
-2- Type
- rejected
- Description
The service refused the request; the message says why. Examples: an invalid block or transaction, insufficient funds, a watch-only wallet asked to spend, a node not ready to mine.
- Name
-3- Type
- node stopped
- Description
The node is shutting down.
Error response
{
"jsonrpc": "2.0",
"error": {
"code": -1,
"message": "block not found"
},
"id": 1
}
HTTP 401
{
"jsonrpc": "2.0",
"error": {
"code": -32001,
"message": "unauthorized"
},
"id": null
}
Method index
- Node methods:
getblockchaininfo,getblockcount,getbestblockhash,getblockhash,getblock,getblockheader,getcompactblock,getrawtransaction,gettransactionstatus,sendrawtransaction,getrawmempool,getmempoolinfo,getnullifierstatus,getpeerinfo,getnetworkinfo,getconnectioncount,uptime,stop,help. - Mining methods:
getmininginfo,getblocktemplate,submitblock. - Wallet methods:
getwalletinfo,getnewaddress,listaddresses,getaddressinfo,validateaddress,exportviewingkey,getbalance,listunspent,listreceived,gettransaction,rescan,estimatefee,quotepayment,sendmany,getoperationstatus,listoperations,canceloperation,quoteconsolidation,consolidate,help. - Selective disclosure:
getpaymentdisclosureandanswerchallengeon the wallet daemon,verifypaymentdisclosureandcreatechallengeon the node.