Dev snippet: How to subscribe to blocks

in #steem8 years ago

I'm going to try something new with this post: Sharing small specific howtos to help other developers integrate code with Steem.

Today we'll look at processing blocks as they come in. We can actually get event notifications for new blocks using the set_block_applied_callback function, which is defined in database_api.hpp as follows [1]:

void set_block_applied_callback( std::function<void(const variant& block_header)> cb );

This is confusing -- it takes a single parameter which is a callback function. While you can create an std::function in C++, how's it possible to pass this function over the network or use this API from non-C++ languages?

The answer is that instead of accepting actual functions, the steemd server's API's accept a number representing a function. This number is then passed by server-pushed callback notifications, and the client is responsible for routing the notification to the proper client-side callback function.

Because notifications require server push, we have to use a websocket connection. Here's a simple example with the wscat utility which lets us interact with websockets in the terminal:

$ wscat -c ws://127.0.0.1:8090/
> {"jsonrpc": "2.0", "method": "call", "params": ["database_api","set_block_applied_callback",[1234]], "id": 1}
< {"id":1,"result":null}
< {"method":"notice","params":[1234,[{"previous":"0033cb1b...","timestamp":"2016-07-21T17:40:36","witness":"xeldal",...}]]}
< {"method":"notice","params":[1234,[{"previous":"0033cb1c...","timestamp":"2016-07-21T17:40:39","witness":"blocktrades",...}]]}
< {"method":"notice","params":[1234,[{"previous":"0033cb1d...","timestamp":"2016-07-21T17:40:42","witness":"bhuz",...}]]}

This example should be very enlightening. We called set_block_applied_callback to establish a subscription, and the server started sending us notifications. The number the client passes as the callback can be any value, it is simply echoed by the server with each notification. If we subscribe to multiple callbacks on the same websocket connection, the client needs some way to route each notification to its corresponding subscription -- so it should simply assign diffferent callback ID's for each subscription.

Now we want to call get_block to get the full block data, for that we need a block number ("block height" in Bitcoin terminology). In Steem, the first 4 bytes (8 hex digits) of the block ID represents the block number, so we can simply take the first 8 characters of the previous member, convert to integer and add 1 to get the block number which can be passed to the get_block API call:

> {"jsonrpc": "2.0", "method": "call", "params": ["database_api","get_block",[3394332]], "id": 1}
< {"id":1,"result":{"previous":"0033cb1b171069d351390acdc91b962a2b5bb6db","timestamp":"2016-07-21T17:40:36","witness":"xeldal",...}}

[1] Even if you're not a C++ coder, looking at the *_api.hpp files in the Steem source tree is very helpful because it will tell you what API methods are available and what parameters they take.

Sort:  

very interesting ,i hope more people will use it. Thank you

Lol great post)))

Hey, this is not in regards to this post, but i wanted to mention that i wrote about you in my latest post. Also, please fact check it because I am not sure that I described your role as mathematician of voting rewards algorithm..........let me know if i need to correct anything. https://steemit.com/vacation/@stellabelle/christmas-in-july-our-vacation-was-funded-entirely-by-steem-dollars