JSON-RPC
CKB exposes a set of RPCs in JSON-RPC 2.0 protocols for interactions.
Here are some initial tips:
- The RPCs exposed by CKB are only designed for internal usage. Please limit the access to the CKB RPCs strictly to trusted machines (by using rpc.listen_address configuration option). Exposing CKB RPCs to the public Internet is dangerous and strongly discouraged.
- CKB JSON-RPC only supports HTTP now. If you need SSL support, please setup a reverse proxy via nginx or other HTTPS servers.
- Subscriptions require a full duplex connection. CKB offers such connections in the form of tcp (enable with rpc.tcp_listen_address configuration option) and websockets (enable with rpc.ws_listen_address), plain HTTP connection does not support subscriptions. See below for examples on this.
Basic Usage
Here we try to provide a starting point for interacting with CKB's RPCs. For more details, please refer to CKB JSON RPC Protocols Documentation.
To use CKB JSON-RPC, you must first have a node running, please refer to existing guides on how to run a CKB Mainnet node, a CKB Testnet node, or a development-only CKB blockchain. The commands below also assumes you are exposing CKB JSON-RPC on the default 8114
port. If you are starting CKB JSON-RPC on a different port, please make changes accordingly.
The following commands uses get_tip_block_number RPC to fetch the tip
block number, of the latest block number in the longest blockchain:
echo '{
"id": 2,
"jsonrpc": "2.0",
"method": "get_tip_block_number",
"params": []
}' \
| tr -d '\n' \
| curl -H 'content-type: application/json' -d @- \
http://localhost:8114
(click here to view response)
{"jsonrpc":"2.0","result":"0x2cb4","id":2}
The following commands uses send_transaction
RPC send transactions to the ckb network:
echo '{
"id": 3,
"jsonrpc": "2.0",
"method": "send_transaction",
"params": [
{
"cell_deps": [
{
"dep_type": "code",
"out_point": {
"index": "0x0",
"tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
}
}
],
"header_deps": [
"0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed"
],
"inputs": [
{
"previous_output": {
"index": "0x0",
"tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17"
},
"since": "0x0"
}
],
"outputs": [
{
"capacity": "0x2540be400",
"lock": {
"code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
"hash_type": "data",
"args": "0x"
},
"type": null
}
],
"outputs_data": [
"0x"
],
"version": "0x0",
"witnesses": []
}
]
}'\
| tr -d '\n' \
| curl -H 'content-type: application/json' -d @- \
http://localhost:8114
(click here to view response)
{
"id": 3,
"jsonrpc": "2.0",
"result": "0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3"
}
It should be noted that send_transaction
is asynchronous, that is, the return of the transaction hash, does not mean that the transaction is fully verified, if you need to follow up on the status of the transaction, it is recommended to use the following get_transaction
rpc:
echo '{
"id": 4,
"jsonrpc": "2.0",
"method": "get_transaction",
"params": ["0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3"]
}' \
| tr -d '\n' \
| curl -H 'content-type: application/json' -d @- \
http://localhost:8114
(click here to view response)
{
"id": 4,
"jsonrpc": "2.0",
"result": {
"transaction": {
"cell_deps": [
{
"dep_type": "code",
"out_point": {
"index": "0x0",
"tx_hash": "0xa4037a893eb48e18ed4ef61034ce26eba9c585f15c9cee102ae58505565eccc3"
}
}
],
"hash": "0xa0ef4eb5f4ceeb08a4c8524d84c5da95dce2f608e0ca2ec8091191b0f330c6e3",
"header_deps": [
"0x7978ec7ce5b507cfb52e149e36b1a23f6062ed150503c85bbf825da3599095ed"
],
"inputs": [
{
"previous_output": {
"index": "0x0",
"tx_hash": "0x365698b50ca0da75dca2c87f9e7b563811d3b5813736b8cc62cc3b106faceb17"
},
"since": "0x0"
}
],
"outputs": [
{
"capacity": "0x2540be400",
"lock": {
"code_hash": "0x28e83a1277d48add8e72fadaa9248559e1b632bab2bd60b27955ebc4c03800a5",
"hash_type": "data",
"args": "0x"
},
"type": null
}
],
"outputs_data": [
"0x"
],
"version": "0x0",
"witnesses": []
},
"cycles": "0x219",
"time_added_to_pool" : "0x187b3d137a1",
"tx_status": {
"block_hash": null,
"status": "pending",
"reason": null
}
}
}
Subscription
To use subscription feature, you need to configure CKB to enable such features. In this section, we assume you use the following configuration in ckb.toml
section:
[rpc]
listen_address = "127.0.0.1:8114"
tcp_listen_address = "127.0.0.1:18114"
ws_listen_address = "127.0.0.1:18115"
# ... more configs
This above config ensures CKB listens at 8114 port for normal HTTP connections, 18114 port for TCP duplex connections, and 18115 port for WebSocket duplex connections.
TCP Based RPC
The following command uses netcat to connect via TCP to CKB, then fire the same get_tip_block_number
RPC as shown above to fetch the block number in the longest chain:
echo '{
"id": 2,
"jsonrpc": "2.0",
"method": "get_tip_block_number",
"params": []
}' \
| tr -d '\n' \
| sed -e "s/$/\n/"
| nc localhost 18114 -q 1
{"jsonrpc":"2.0","result":"0xdc90","id":2}
The following command uses netcat to connect to CKB, make a subscription request to monitor the latest committed block:
cat <(echo '{
"id": 2,
"jsonrpc": "2.0",
"method": "get_tip_block_number",
"params": []
}' \
| tr -d '\n' \
| sed -e "s/$/\n/") -
| nc localhost 18114
{"jsonrpc":"2.0","result":"0xa","id":2}
{"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a2810cf\",\"timestamp\":\"0x16ee81d0d5f\",\"number\":\"0x30673\",\"epoch\":\"0x5f102b400007a\",\"parent_hash\":\"0xc9020c79d4f19797022af3631eb9e76c57933bd608fe81a137b834975616c991\",\"transactions_root\":\"0x7d8e3c102a5c52598cdbe7d208deb986eb2f0af189bc4655e6dd1a71564c2b25\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"dao\":\"0x15b9ae7648400f2fb61d57e0379b2300fc641b7e8db5160000060394d5580007\",\"nonce\":\"0x1f86f056000002460000000053170600\",\"hash\":\"0xa3c8feda83d7e184f09cb4f05e535bccd4c159e2cc0ac7a06ea7d457e0051a08\"}","subscription":"0xa"}}
{"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a2810cf\",\"timestamp\":\"0x16ee81d1dfd\",\"number\":\"0x30674\",\"epoch\":\"0x5f102b500007a\",\"parent_hash\":\"0xa3c8feda83d7e184f09cb4f05e535bccd4c159e2cc0ac7a06ea7d457e0051a08\",\"transactions_root\":\"0x6d2dfc88bd8dda743b5bae14453f5f405a2a29a3cf6fff00c60f0f5c60a84fbe\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"dao\":\"0xb4e019376f400f2f34c172e7379b230031d1417d95b5160000a399ffd6580007\",\"nonce\":\"0xded8ffa1000000000000040a90000000\",\"hash\":\"0x7d10fd1fb459630aa2f87ee4de699b7466a5da6efc0aee6ff459ff17b6cc5904\"}","subscription":"0xa"}}
// ... more data
Use Ctrl-C
to exit netcat here.
WebSocket Based RPC
To play with WebSocket based RPC, please make sure to install wscat first:
npm install -g wscat
You can use the following command to start wscat and connect to CKB:
wscat -c ws://localhost:18115
Connected (press CTRL+C to quit)
>
Now we can run the same get_tip_block_number
request as above:
> {"id": 2, "jsonrpc": "2.0", "method": "get_tip_block_number", "params": []}
< {"jsonrpc":"2.0","result":"0x76887","id":2}
You can also create subscriptions for new blocks:
> {"id": 2, "jsonrpc": "2.0", "method": "subscribe", "params": ["new_tip_header"]} < {"jsonrpc":"2.0","result":"0x2","id":2} < {"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a216e17\",\"timestamp\":\"0x16f886b2223\",\"number\":\"0x77e2a\",\"epoch\":\"0x6c$01a9000135\",\"parent_hash\":\"0x2662c8056c638408d8f018a53785d68f633bd1edfa06b82d7c29ddcac1d98927\",\"transactions_root\":\"0xa6488b15373521ec0b1bc9dff1f117cc1cad7d3579e8a6c38cc6e35166dad9bd\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"dao\":\"0x1a1aab41ad3eb72fa260f4eedeb9230092c4510af45b390000547d684fc40007\",\"nonce\":\"0xce1aaca681000089001d0003cb2d0500\",\"hash\":\"0x993e593921024167c1779146348fe2d82864ecd3f657b3bd2b14fbdfa87c4f06\"}","subscription":"0x2"}}
< {"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a216e17\",\"timestamp\":\"0x16f886b29e3\",\"number\":\"0x77e2b\",\"epoch\":\"0x6c601aa000135\",\"parent_hash\":\"0x993e593921024167c1779146348fe2d82864ecd3f657b3bd2b14fbdfa87c4f06\",\"transactions_root\":\"0xe64cb6afb57e92a2af1da34d8a1d547fcd8b833e187697ae28a9dfadaaeba247\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0xa807c9cbb16a5af7cf36fd5c20b29535f6db4de52062138ad21ea6790ba9529c\",\"dao\":\"0xba227d3fcf3eb72fc8d61ff5deb92300402b3f12fb5b390000f113d450c40007\",\"nonce\":\"0xfb68521601000000000000503c9e2338\",\"hash\":\"0xf55d0f7ae1d9b106eee96139d86313e46b109ec8fa0d92f9eb6eb8bc81c294ec\"}","subscription":"0x2"}}
< {"jsonrpc":"2.0","method":"subscribe","params":{"result":"{\"version\":\"0x0\",\"compact_target\":\"0x1a216e17\",\"timestamp\":\"0x16f886b40a3\",\"number\":\"0x77e2c\",\"epoch\":\"0x6c601ab000135\",\"parent_hash\":\"0xf55d0f7ae1d9b106eee96139d86313e46b109ec8fa0d92f9eb6eb8bc81c294ec\",\"transactions_root\":\"0xad2c9e1eabc586c8e38cc1eaca61eba5e320bbf4655c510c5be5de9eaafea96f\",\"proposals_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"uncles_hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"dao\":\"0x5a2b4f3df13eb72feb4c4bfbdeb923008c922c1a025c3900008eaa3f52c40007\",\"nonce\":\"0x7b5ad85601000000000000005b340000\",\"hash\":\"0x2077e0c022514fe07844411436cfbf50e413694858a3d4775e0c836e787ce7ab\"}","subscription":"0x2"}}
<< // ... more data.
Serialization
CKB's RPCs returns data in JSON format. While most fields are self-explanatory, CKB has special handling for numbers and binary data:
Numbers
All numbers used in CKB's RPCs, including request parameters and return values, use hex encoding, the number is encoded first in hexadecimal in the most compact format(meaning useless leading zeros should be striped), and then prefixed with 0x
. Here are some examples:
0
is encoded as0x0
, we cannot remove the remaining0
since otherwise it won't be a proper number4
is encoded as0x4
15
is encoded as0xf
42
is encoded as0x2a
291
is encoded as0x123
3984
is encoded as0xf90
Binary data
All binary data, including all the hashes, args
in script, outputs_data
items, are represented as hex string with 0x
prefix. Some examples include:
0x65b253cdcb6226e7f8cffec5c47c959b3d74af2caf7970a1eb1500e9b92aa200
0x927f3e74dceb87c81ba65a19da4f098b4de75a0d
0x40420f00000000000000000000000000
0x
(empty data)
Unlike numbers, binary data should always have a even numbered length.