How to use Tezos RPCs

Mathis Selvi
ON-X Blockchain (Chain-Accelerator)
11 min readJun 21, 2019
Tezos Logo

In this very short story, we’re going to learn how to use RPCs with Tezos. At the end of this, again, very short story, you should know how to use them and where to look for more information about it. Let’s get started!

Before starting

I highly suggest you to check my story “I tested Tezos” (Part. 1) https://medium.com/chain-accelerator/i-tested-tezos-b254504775be so you know how to run a node.

Once your node is running, you can now start using RPCs :)

Using RPCs

First thing to know about RPCs is that you can find a complete documentation about them here: http://tezos.gitlab.io/mainnet/api/rpc.html
You will have access to a list of all available RPCs that you can get.

You can do the same thing using the tezos-client, like this:

chainacc@tezos:~/tezos$ ./tezos-client rpc list

And you will get the list of all available RPCs. You can use the same command for each service. For example,

chainacc@tezos:~/tezos$ ./tezos-client rpc list /chains/main/ will return the following:

Warning:

This is NOT the Tezos Mainnet.

The node you are connecting to claims to be running on the
Tezos Alphanet DEVELOPMENT NETWORK.
Do NOT use your fundraiser keys on this network.
Alphanet is a testing network, with free tokens.
Available services:

+ chains/main/
- GET /chains/main/blocks
Lists known heads of the blockchain sorted with decreasing fitness.
Optional arguments allows to returns the list of predecessors for
known heads or the list of predecessors for a given list of blocks.
- /chains/main/blocks/<block_id> <dynamic>
- GET /chains/main/chain_id
The chain unique identifier.
- GET /chains/main/invalid_blocks
Lists blocks that have been declared invalid along with the errors
that led to them being declared invalid.
- GET /chains/main/invalid_blocks/<block_hash>
The errors that appears during the block (in)validation.
- DELETE /chains/main/invalid_blocks/<block_hash>
Remove an invalid block for the tezos storage
- /chains/main/mempool <dynamic>
Dynamic parameter description:

<block_hash>
block_hash (Base58Check-encoded)
<block_id>
A block identifier. This is either a block hash in Base58Check
notation, one the predefined aliases: 'genesis', 'head' or a block
level (index in the chain). One might also use 'head~N' or '<hash>~N'
where N is an integer to denote the Nth predecessor of the designated
block.Also, '<hash>+N' denotes the Nth successor of a block.

Which contains all the available services you can call under /chains/main/.

We are first going to handle a few GET and then we will do some POST in order to inject a transaction.

GET RPCs

Before I start, you must know that most of the responses (if not all) from the RPC calls I will make will be different from yours, which is completely normal.

For now, we’re going to use this route:

/chains/<chain_id>

with <chain_id> being main. So, to get the ID of the main chain, we can use this:

chainacc@tezos:~/tezos$ ./tezos-client rpc get /chains/main/chain_id

In my case, it returns:

"NetXgtSLGNJvNye"

which is the ID of the main chain. Let’s go further, let’s get some information about a block.

chainacc@tezos:~/tezos$ ./tezos-client rpc get /chains/main/blocks/

The above command will list known heads of the blockchain. You can now take one of them, and use it for our next command:

chainacc@tezos:~/tezos$ ./tezos-client rpc get /chains/main/blocks/BLOCK_HERE

So, the final command should look like this:

chainacc@tezos:~/tezos$ ./tezos-client rpc get /chains/main/blocks/BLfcT1XX1bx1QiYSxfMjdSuWvfqemPMYvnEssXTXzcrYyQnQbHL

It basically gets a bunch of information about the specified blocks. I will show you what it displayed for me at the moment I entered the command. It’s kinda huge, sorry in advance.

{ "protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"chain_id": "NetXgtSLGNJvNye",
"hash": "BLfcT1XX1bx1QiYSxfMjdSuWvfqemPMYvnEssXTXzcrYyQnQbHL",
"header":
{ "level": 439394, "proto": 2,
"predecessor": "BLKsHXHjacbLYQFTZ1hgymZjkjefpTj5YgQUfW4HYFsDE5akn1V",
"timestamp": "2019-06-13T14:12:48Z", "validation_pass": 4,
"operations_hash":
"LLoZVZcZ5qNUEWHoBCXcfYitfDJZiGzDJQgvUdpavwjejMFc7UVBo",
"fitness": [ "00", "0000000000c98f02" ],
"context": "CoWAK4SWWt9cWFbt3tQBzJ1ZxRSpdKBW326kmo4MaNukkdnJDeqe",
"priority": 0, "proof_of_work_nonce": "00000003b6818d3e",
"signature":
"sigqPNHueubaGZmr8yMbTAGMsPGmjKDCe5u9zFpGpfH4BcXmUXa52gtUhXjQNDngpp9qqiErEBLdjHwyf6ZGuBH54psrAq4R" },
"metadata":
{ "protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"next_protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"test_chain_status": { "status": "not_running" },
"max_operations_ttl": 60, "max_operation_data_length": 16384,
"max_block_header_length": 238,
"max_operation_list_length":
[ { "max_size": 32768, "max_op": 32 }, { "max_size": 32768 },
{ "max_size": 135168, "max_op": 132 }, { "max_size": 524288 } ],
"baker": "tz1X7fu4GXBXp9A8fchu1px3zzMDKtagDBk3",
"level":
{ "level": 439394, "level_position": 439393, "cycle": 214,
"cycle_position": 1121, "voting_period": 53,
"voting_period_position": 5217, "expected_commitment": false },
"voting_period_kind": "proposal", "nonce_hash": null,
"consumed_gas": "0", "deactivated": [],
"balance_updates":
[ { "kind": "contract",
"contract": "tz1X7fu4GXBXp9A8fchu1px3zzMDKtagDBk3",
"change": "-512000000" },
{ "kind": "freezer", "category": "deposits",
"delegate": "tz1X7fu4GXBXp9A8fchu1px3zzMDKtagDBk3", "cycle": 214,
"change": "512000000" },
{ "kind": "freezer", "category": "rewards",
"delegate": "tz1X7fu4GXBXp9A8fchu1px3zzMDKtagDBk3", "cycle": 214,
"change": "16000000" } ] },
"operations":
[ [ { "protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"chain_id": "NetXgtSLGNJvNye",
"hash": "ooQNZYbkneJgRewPBBR8hBYktx3BLuZAtyunpRwJUZ7hyK7o65b",
"branch": "BLKsHXHjacbLYQFTZ1hgymZjkjefpTj5YgQUfW4HYFsDE5akn1V",
"contents":
[ { "kind": "endorsement", "level": 439393,
"metadata":
{ "balance_updates":
[ { "kind": "contract",
"contract": "tz3gN8NTLNLJg5KRsUU47NHNVHbdhcFXjjaB",
"change": "-512000000" },
{ "kind": "freezer", "category": "deposits",
"delegate": "tz3gN8NTLNLJg5KRsUU47NHNVHbdhcFXjjaB",
"cycle": 214, "change": "512000000" },
{ "kind": "freezer", "category": "rewards",
"delegate": "tz3gN8NTLNLJg5KRsUU47NHNVHbdhcFXjjaB",
"cycle": 214, "change": "16000000" } ],
"delegate": "tz3gN8NTLNLJg5KRsUU47NHNVHbdhcFXjjaB",
"slots": [ 29, 26, 11, 10, 4, 3, 2, 0 ] } } ],
"signature":
"sigNjvJvNKNTtXuRU4bSCnXAqKB9dk6XgqV7bsnK9nVxTFQd6t75Sn8NDsTwnxgNUJUWyNG4bQny6faQjuEagu8cbzXcGJae" },
{ "protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"chain_id": "NetXgtSLGNJvNye",
"hash": "opKz7E5nfF2d6mi9KHPNVGSktYK7PfCSiwYhrhvLYMHgBZ5YEq6",
"branch": "BLKsHXHjacbLYQFTZ1hgymZjkjefpTj5YgQUfW4HYFsDE5akn1V",
"contents":
[ { "kind": "endorsement", "level": 439393,
"metadata":
{ "balance_updates":
[ { "kind": "contract",
"contract": "tz1X7fu4GXBXp9A8fchu1px3zzMDKtagDBk3",
"change": "-64000000" },
{ "kind": "freezer", "category": "deposits",
"delegate": "tz1X7fu4GXBXp9A8fchu1px3zzMDKtagDBk3",
"cycle": 214, "change": "64000000" },
{ "kind": "freezer", "category": "rewards",
"delegate": "tz1X7fu4GXBXp9A8fchu1px3zzMDKtagDBk3",
"cycle": 214, "change": "2000000" } ],
"delegate": "tz1X7fu4GXBXp9A8fchu1px3zzMDKtagDBk3",
"slots": [ 22 ] } } ],
"signature":
"sigTWUypVPf9qzWpHGTEAzxwN2ts9KKPH8g91mcXuQ3RJFsYMup4FFF1UGJdvGz5FV6AARXf717zpUckPUsbizFXgoeEUBdZ" },
{ "protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"chain_id": "NetXgtSLGNJvNye",
"hash": "opZGJcoEQVoLtbGjL6qrCahLA62DDu1oYYFdeXpoitc5CbeLd7N",
"branch": "BLKsHXHjacbLYQFTZ1hgymZjkjefpTj5YgQUfW4HYFsDE5akn1V",
"contents":
[ { "kind": "endorsement", "level": 439393,
"metadata":
{ "balance_updates":
[ { "kind": "contract",
"contract": "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9",
"change": "-64000000" },
{ "kind": "freezer", "category": "deposits",
"delegate": "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9",
"cycle": 214, "change": "64000000" },
{ "kind": "freezer", "category": "rewards",
"delegate": "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9",
"cycle": 214, "change": "2000000" } ],
"delegate": "tz1aWXP237BLwNHJcCD4b3DutCevhqq2T1Z9",
"slots": [ 24 ] } } ],
"signature":
"signjdkRNh9DHPgQ2jNZdTcamZwMNLaB6d9v8UPQZUuadhF51k9e4qPvK1pjYkWWw6NjamPaDhDnA9tR95WiTzzBcwBHvb1i" },
{ "protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"chain_id": "NetXgtSLGNJvNye",
"hash": "opKomgXnBYA5YoYin9B67EVejJGhDnhfUrroYeQ5B1psvnXUoUk",
"branch": "BLKsHXHjacbLYQFTZ1hgymZjkjefpTj5YgQUfW4HYFsDE5akn1V",
"contents":
[ { "kind": "endorsement", "level": 439393,
"metadata":
{ "balance_updates":
[ { "kind": "contract",
"contract": "tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5",
"change": "-576000000" },
{ "kind": "freezer", "category": "deposits",
"delegate": "tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5",
"cycle": 214, "change": "576000000" },
{ "kind": "freezer", "category": "rewards",
"delegate": "tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5",
"cycle": 214, "change": "18000000" } ],
"delegate": "tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5",
"slots": [ 31, 28, 23, 19, 17, 15, 14, 13, 6 ] } } ],
"signature":
"sigmJf62sxchuvAYysyGzhBVz5u1tMo9BLJL7STJFfb1kMK9anJL9uZh4rrYhyUTJoEpn81XzpPhkq4z5uvrBjsUi1U8KgTh" },
{ "protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"chain_id": "NetXgtSLGNJvNye",
"hash": "ooUreTSWpUiexpmU2EeeEEPGdvzZtVAohjTM9Mf3ydpK3f2QDwg",
"branch": "BLKsHXHjacbLYQFTZ1hgymZjkjefpTj5YgQUfW4HYFsDE5akn1V",
"contents":
[ { "kind": "endorsement", "level": 439393,
"metadata":
{ "balance_updates":
[ { "kind": "contract",
"contract": "tz1hodJSw6uv7LqArLW86zKuUjkXiayJvqCf",
"change": "-128000000" },
{ "kind": "freezer", "category": "deposits",
"delegate": "tz1hodJSw6uv7LqArLW86zKuUjkXiayJvqCf",
"cycle": 214, "change": "128000000" },
{ "kind": "freezer", "category": "rewards",
"delegate": "tz1hodJSw6uv7LqArLW86zKuUjkXiayJvqCf",
"cycle": 214, "change": "4000000" } ],
"delegate": "tz1hodJSw6uv7LqArLW86zKuUjkXiayJvqCf",
"slots": [ 21, 8 ] } } ],
"signature":
"sigoU9KqeiEmghqR8nF2Snvf3jKcsac3rBQhtumDJn3mq3VJnxUWJkXtD4osc6syS18BB1LQj86x5aAUaoTk2WC4KUfL5u3T" },
{ "protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"chain_id": "NetXgtSLGNJvNye",
"hash": "ooJMd8NBKnVtFzc6RuzboYTgB31titPzPkUX2rBpxwdMh5sJija",
"branch": "BLKsHXHjacbLYQFTZ1hgymZjkjefpTj5YgQUfW4HYFsDE5akn1V",
"contents":
[ { "kind": "endorsement", "level": 439393,
"metadata":
{ "balance_updates":
[ { "kind": "contract",
"contract": "tz1YCABRTa6H8PLKx2EtDWeCGPaKxUhNgv47",
"change": "-320000000" },
{ "kind": "freezer", "category": "deposits",
"delegate": "tz1YCABRTa6H8PLKx2EtDWeCGPaKxUhNgv47",
"cycle": 214, "change": "320000000" },
{ "kind": "freezer", "category": "rewards",
"delegate": "tz1YCABRTa6H8PLKx2EtDWeCGPaKxUhNgv47",
"cycle": 214, "change": "10000000" } ],
"delegate": "tz1YCABRTa6H8PLKx2EtDWeCGPaKxUhNgv47",
"slots": [ 30, 27, 16, 7, 1 ] } } ],
"signature":
"sigVzAUw89uitmc1uT2XHTmZrsBYYyzQSwJS4uNVJ1vSA7PtHTXscMiPjTYx2GtSi62ZAuQPiqueeC8BvLkFRcpp81WYnsoH" } ],
[], [], [] ] }

It is pretty self-explanatory, so I advise you to take some time and read what the command returns.

Let’s go further and add /context/constants at the end of the line in order to get some information about the block’s constants.

chainacc@tezos:~/tezos$ ./tezos-client rpc get /chains/main/blocks/BLfcT1XX1bx1QiYSxfMjdSuWvfqemPMYvnEssXTXzcrYyQnQbHL/context/constants

Here is what it returns for me:

{ "proof_of_work_nonce_size": 8, "nonce_length": 32,
"max_revelations_per_block": 32, "max_operation_data_length": 16384,
"max_proposals_per_delegate": 20, "preserved_cycles": 3,
"blocks_per_cycle": 2048, "blocks_per_commitment": 32,
"blocks_per_roll_snapshot": 256, "blocks_per_voting_period": 8192,
"time_between_blocks": [ "30", "40" ], "endorsers_per_block": 32,
"hard_gas_limit_per_operation": "800000",
"hard_gas_limit_per_block": "8000000",
"proof_of_work_threshold": "70368744177663",
"tokens_per_roll": "8000000000", "michelson_maximum_type_size": 1000,
"seed_nonce_revelation_tip": "125000", "origination_size": 257,
"block_security_deposit": "512000000",
"endorsement_security_deposit": "64000000", "block_reward": "16000000",
"endorsement_reward": "2000000", "cost_per_byte": "1000",
"hard_storage_limit_per_operation": "60000",
"test_chain_duration": "1966080" }

Among other interesting information, we get the hard gas limit per operation ("hard_gas_limit_per_operation": "800000") for this specific block. We also have the "tokens_per_roll" which is equivalent to 8,000 tez (it used to be 10,000 but it decreased a few weeks ago).

This is a very basic approach to how you can use Tezos RPCs GET. Please, do use Tezos’ official documentation linked at the beginning of the story, to learn more about them and what you can do with them.

Let’s now see POST RPCs.

POST RPCs

What is better than creating a transaction to use POST RPCs? Let’s do this!

So, in order to create a transaction, we’re going to need:

  • The hash of the head block
  • The sender
  • The gas limit
  • The storage limit
  • and the receiver

You can get everything using the GET RPCs we used above. In order to run the operation, use the following POST RPC:

chainacc@tezos:~/tezos$ ./tezos-client rpc post /chains/main/blocks/head/helpers/scripts/run_operation

When entering this, it will ask you for the following:

{ "branch": "/definitions/block_hash",
"contents": [ "/definitions/operation.alpha.contents" ],
"signature": "/definitions/Signature" }

After editing it, it should look like this:

{ "branch": "BLnfTrJ6zwakFL6LbBzrD2tRSQuVJ2YymAnNHsYqW9FqEQLEFHT",
"contents": [
{ "kind": "transaction",
"source": "tz1VFgcWrcLvxpWcMvKnzFZpLjWxNT4wuosx",
"fee": "1",
"counter": "36904",
"gas_limit": "800000",
"storage_limit": "60000",
"amount": "1",
"destination": "tz1hBT7dx9aaiZTEsSJUnB8fKQ76EswyTLgZ" }
],
"signature": "edsigtXomBKi5CTRf5cjATJWSyaRvhfYNHqSUGrn4SdbYRcGwQrUGjzEfQDTuqHhuA8b2d8NarZjz8TRf65WkpQmo423BtomS8Q"
}

As it’s just a simulation, it doesn’t check for signature. So you can use a fake one, but it has to be in the good format. Use this one:

edsigtXomBKi5CTRf5cjATJWSyaRvhfYNHqSUGrn4SdbYRcGwQrUGjzEfQDTuqHhuA8b2d8NarZjz8TRf65WkpQmo423BtomS8Q

And you can save and run the call. What we do with this RPC call is we simulate the transaction to make sure everything is fine. It should return something like this:

{ "contents":
[ { "kind": "transaction",
"source": "tz1VFgcWrcLvxpWcMvKnzFZpLjWxNT4wuosx", "fee": "1",
"counter": "36904", "gas_limit": "800000", "storage_limit": "60000",
"amount": "1", "destination": "tz1hBT7dx9aaiZTEsSJUnB8fKQ76EswyTLgZ",
"metadata":
{ "balance_updates":
[ { "kind": "contract",
"contract": "tz1VFgcWrcLvxpWcMvKnzFZpLjWxNT4wuosx",
"change": "-1" },
{ "kind": "freezer", "category": "fees",
"delegate": "tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU",
"cycle": 223, "change": "1" } ],
"operation_result":
{ "status": "applied",
"balance_updates":
[ { "kind": "contract",
"contract": "tz1VFgcWrcLvxpWcMvKnzFZpLjWxNT4wuosx",
"change": "-1" },
{ "kind": "contract",
"contract": "tz1hBT7dx9aaiZTEsSJUnB8fKQ76EswyTLgZ",
"change": "1" } ], "consumed_gas": "10200" } } } ] }

We can see it consumed “10200” gas and no storage. The status is applied, which means that the transaction was successfully simulated by our node.

Before continuing and pre-applying the transaction, we need a signature, and this time: a real one. To do so, we’re going to forge a binary operation. Be careful: the node is going to send us a binary transaction, so you have to be SURE that you can trust the node. Otherwise, it could just send you a different binary transaction.

Based on the previous response, we know that our operation should be like this:

{ "branch": "BLnfTrJ6zwakFL6LbBzrD2tRSQuVJ2YymAnNHsYqW9FqEQLEFHT",
"contents": [
{ "kind": "transaction",
"source": "tz1VFgcWrcLvxpWcMvKnzFZpLjWxNT4wuosx",
"fee": "1",
"counter": "36904",
"gas_limit": "10500",
"storage_limit": "0",
"amount": "1",
"destination": "tz1hBT7dx9aaiZTEsSJUnB8fKQ76EswyTLgZ" }
]
}

We updated gas_limit based on the info we received from the simulation (it was 10200 but we added 300 for security) and storage_limit to 0. The signature is not here yet, it’s normal since we don’t have it. Speaking about it, let’s get the signature right now.

We have to translate the above operation to a binary format. To do so, let’s use a new POST RPC:

chainacc@tezos:~/tezos$ ./tezos-client rpc post /chains/main/blocks/head/helpers/forge/operations

It should show you something like:

"/definitions/operation.alpha.unsigned_operation"

Which you can delete and paste your operation (see above) instead. It returns this, which should obviously be different for you:

"8da5164e7a0ae00e8282e57f7950367a9cc2ef777271cf21ed89971d2218a34d08000069775863172a9ee22b0b72e9aa8d2fe8a7747dc901a8a002845200010000ec4bec608f7f8ccd26e9419999736ed7918b8d9900"

This basically is the binary representation of your operation in a hexadecimal format. Although, we also need the operation to be signed by the manager before continuing.

We’re going to use tezos-client to do so, but we could also do it on our own using the secret key of the sender. As it’s easier and a little bit less technical, we’re going to do it with tezos-client for this article (tezos-client already knows the secret key).

First, save the binary representation you got earlier, without quotes, in a file savedOperation.hex. Then, run the following command:

chainacc@tezos:~/tezos$ ./tezos-client sign bytes 0x03$(cat savedOperation.hex) for Alice

A little bit of explanation from OcamlPro:

The 0x03$(cat operation.hex) is the concatenation of the 0x03 prefix and the hexa content of the operation.hex, which is equivalent to 0x03ce69...3c00. The prefix is used (1) to indicate that the representation is hexadecimal (0x), and (2) that it should start with 03, which is a watermark for operations in Tezos.

Note that Alice is the account I use as the sender, but it will probably be different for you. Adapt accordingly.

It gives me the following:

Signature: edsigtxQAGyXJAAS4eSX8RNvSpknW4ynfSdrTAZTEcedNyKxsgDHiqVjoNf9JDUByFJAUCDMcoZ2EEHNiEN7tqGX3ZMvfQWWuD9

Awesome! We have our signature. It is in a base68check format, which is enough for the run_operation and preapply RPCs. However, it is not enough for the injection RPC.

Let’s add our signature to our operation, as well as the protocol at the top:

[ { "protocol": "Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd",
"branch": "BLnfTrJ6zwakFL6LbBzrD2tRSQuVJ2YymAnNHsYqW9FqEQLEFHT",
"contents": [
{ "kind": "transaction",
"source": "tz1VFgcWrcLvxpWcMvKnzFZpLjWxNT4wuosx",
"fee": "1",
"counter": "36904",
"gas_limit": "10500",
"storage_limit": "0",
"amount": "1",
"destination": "tz1hBT7dx9aaiZTEsSJUnB8fKQ76EswyTLgZ" }
],
"signature": "edsigtxQAGyXJAAS4eSX8RNvSpknW4ynfSdrTAZTEcedNyKxsgDHiqVjoNf9JDUByFJAUCDMcoZ2EEHNiEN7tqGX3ZMvfQWWuD9"
} ]

We can then pre-apply this operation. We simulate it again, but this time with signature check and with adjusted fees, gas limit, storage limit, etc… Let’s do it:

chainacc@tezos:~/tezos$ ./tezos-client rpc post /chains/main/blocks/head/helpers/preapply/operations

It should show you something like this:

[ "/definitions/next_operation" ]

As usual, simply delete that and paste your operation from above, with the real signature we made. After calling the RPC, it should return something like this:

[ { "contents":
[ { "kind": "transaction",
"source": "tz1VFgcWrcLvxpWcMvKnzFZpLjWxNT4wuosx", "fee": "1",
"counter": "36904", "gas_limit": "10500", "storage_limit": "0",
"amount": "1",
"destination": "tz1hBT7dx9aaiZTEsSJUnB8fKQ76EswyTLgZ",
"metadata":
{ "balance_updates":
[ { "kind": "contract",
"contract": "tz1VFgcWrcLvxpWcMvKnzFZpLjWxNT4wuosx",
"change": "-1" },
{ "kind": "freezer", "category": "fees",
"delegate": "tz1Ke2h7sDdakHJQh8WX4Z372du1KChsksyU",
"cycle": 223, "change": "1" } ],
"operation_result":
{ "status": "applied",
"balance_updates":
[ { "kind": "contract",
"contract": "tz1VFgcWrcLvxpWcMvKnzFZpLjWxNT4wuosx",
"change": "-1" },
{ "kind": "contract",
"contract": "tz1hBT7dx9aaiZTEsSJUnB8fKQ76EswyTLgZ",
"change": "1" } ], "consumed_gas": "10200" } } } ],
"signature":
"edsigtxQAGyXJAAS4eSX8RNvSpknW4ynfSdrTAZTEcedNyKxsgDHiqVjoNf9JDUByFJAUCDMcoZ2EEHNiEN7tqGX3ZMvfQWWuD9" } ]

Now, let’s get to the final step: the injection. Before that, we need the signed_operation_bytes. It corresponds to operation_bytes (that we saved in savedOperation.hex) + the decoded signature.

So, let’s first decode the signature. There is a few ways of doing this. One would be to use Python and the base58check module. Altough, for this post, we’re going to use an online website that does it for us. After typing “Decode base58” on Google, I found this website: https://incoherency.co.uk/base58/ which we can use to do so. Simply paste your signature (remember, mine is edsigtxQAGyXJAAS4eSX8RNvSpknW4ynfSdrTAZTEcedNyKxsgDHiqVjoNf9JDUByFJAUCDMcoZ2EEHNiEN7tqGX3ZMvfQWWuD9) on the right box and click on “Decode”.

It gave me this:

09f5cd8612bbfac1a5ef087e3a1fefb4e577e14925c0afea5725b57f6275bcdec4f6193bead3cfd550e29984080ed66f8cf8f2cae9e106f5fb30704a6f21544aec9efee00b2391e6c8

However, there is a prefix and a suffix in this that we do not need. Indeed, current representation is (prefix)(decoded_signature)(suffix). We need to remove the prefix and suffix. Prefix is most of the times 09f5cd8612 (first 10 hexadecimal characters) and suffix is composed of the last 8 hex characters (in my case: 2391e6c8). So let’s remove those and here is what it looks like for me:

bbfac1a5ef087e3a1fefb4e577e14925c0afea5725b57f6275bcdec4f6193bead3cfd550e29984080ed66f8cf8f2cae9e106f5fb30704a6f21544aec9efee00b

Above is my DECODED SIGNATURE. Now we can have our signed_operation_bytes by adding our decoded_signature next to our operation_bytes (saved in savedOperation.hex), it should like this:

8da5164e7a0ae00e8282e57f7950367a9cc2ef777271cf21ed89971d2218a34d08000069775863172a9ee22b0b72e9aa8d2fe8a7747dc901a8a002845200010000ec4bec608f7f8ccd26e9419999736ed7918b8d9900bbfac1a5ef087e3a1fefb4e577e14925c0afea5725b57f6275bcdec4f6193bead3cfd550e29984080ed66f8cf8f2cae9e106f5fb30704a6f21544aec9efee00b

I’ve separated the two parts by putting the decode_signature in bold, so you can see it more clearly.

We can now inject the operation into the chain ;)

chainacc@tezos:~/tezos$ ./tezos-client rpc post /injection/operation?chain=main

It will display two double quotes "" in which you can paste your long string, so it looks like this:

"8da5164e7a0ae00e8282e57f7950367a9cc2ef777271cf21ed89971d2218a34d08000069775863172a9ee22b0b72e9aa8d2fe8a7747dc901a8a002845200010000ec4bec608f7f8ccd26e9419999736ed7918b8d9900bbfac1a5ef087e3a1fefb4e577e14925c0afea5725b57f6275bcdec4f6193bead3cfd550e29984080ed66f8cf8f2cae9e106f5fb30704a6f21544aec9efee00b"

After running, it displays:

"opRG9VZ5duM7jtXhY2qbzNVpdeqzZbUEoGvBJ2EDrEF6VE4fnuY"

Which, obviously, will be different for you.

Congratulations! You just injected an operation in the block, and you can now check it on https://alphanet.tzscan.io/

And we’re done for this article! ;) Stay tuned for next ones!

Let us know which offer you are interested in and apply here => this form.

Don’t forget to follow us on social medias : twitter, telegram, slack

--

--

Mathis Selvi
ON-X Blockchain (Chain-Accelerator)

🛠️ Working on Tezos 👟 Fashion Enthusiast 💿 Music Lover