When Reactive Programming meets STEEM...

5개월 전


image.png

Repository

https://github.com/adasq/reactive-steem

What is the project about?

TL;DR

The reactive-steem is a node.js package allowing you to subscribe to changes emitted to the STEEM blockchain via blocks produced by the witnesses. The library API is designed with reactive-programming approach.

What is Reactive Programming?

Reactive programming is a hot topic in software development since last few years.

There are tons of libraries for vast majority of programming languages. Reactive programming is used in mobile development world, web or backend services.

Let's see the wikipedia's definition:

In computing, reactive programming is a declarative programming paradigm concerned with data streams and the propagation of change. With this paradigm it is possible to express static (e.g., arrays) or dynamic (e.g., event emitters) data streams with ease, and also communicate that an inferred dependency within the associated execution model exists, which facilitates the automatic propagation of the changed data flow.

Still too enigmatic? Let's play with this technology in our blockchain-based world, STEEM.

STEEM context

Imagine we have a source of asynchronous data representing blocks. Each three seconds a new block is being produced by a witness. This is a constant process, so you can see it as a stream of information we can subscribe to:

const { stream } = require('reactive-steem')

steem()
    .blocks
    .subscribe(({ block }) => {
        console.log(block)
        console.log(block.blockNo)
    })

So, each time a new block is being produced, we will print its data to the console.

Now, let's say we want to subscribe to the blocks, which height number is even... How to do it? Using operators (being more precise - filter operator):

const { stream } = require('reactive-steem')

const isEvenBlockNumber = filter(
    ({ block }) => block.blockNo % 2 === 0
)

steem()
    .blocks
    .pipe(isEvenBlockNumber)
    .subscribe(({ block }) => {
        console.log(block.blockNo)
    })

Not really useful but simple, huh?

As you know, blocks include list of transactions, which then include list of operations. We can print very first operation included in the block:

const { stream } =  require('reactive-steem')

steem()
    .blocks
    .subscribe(({ block }) => {
        console.log(block.transactions[0].operations[0])
    })

Imagine now, we want to process all operations. In the example we might iterate over block.transactions list in order to do some additional stuff, but it seems not to be comfortable. Using operators, we can map our source into transactions rather than block stream. And it goes like this:

const { stream, toTransaction } =  require('reactive-steem')

steem()
    .blocks
    .pipe(toTransaction)
    .subscribe(({ block, transaction }: Activity) => {
        console.log(transaction.operations)
    })

Now we are subscribing to transaction, rather than block stream. Operations might be vote, comment or transfer. Let's say, we are interested in comment operations. We can take an advantage of introduced earlier filter operator:

const { stream, toTransaction } =  require('reactive-steem')

const is = opType => filter(
    (({ transaction: { operations } }): Activity => operations[0][0] === opType)
)

steem()
    .blocks
    .pipe(toActivity)
    .pipe(is('comment'))
    .subscribe(({block, transaction }: Activity) => {
        console.log(transaction.operations[0][1])
    })

Pretty easy, right? Those are very basic operators - but there are more of them. I do recommend visiting https://rxmarbles.com/. Each operator description includes visual representation of the way given operator behaves.

Let's return to our blockchain world... how about watching for steemian's comments, which have been self-voted within 60 seconds after publishing?

const { stream, toTransaction } =  require('reactive-steem')

const isSelfVote = /* ... */
const transactions = steem().blocks.pipe(toTransaction)

transactions
    .pipe(isSelfVote(transactions))
    .subscribe(result) => {
        console.log(result)
    })

The implementation of isSelfVote filter is more complex, but still easy to read. It is available here.

You can clone the project repo and run npm run playground in order to start selfvote watcher on your own!

An example output:

image.png

A diffSecs property describes number a of seconds between a post has been published and a vote has been made by an author.

A descriptive unit tests describes the way it works as well:

image.png

As you have probably noticed in the example - we are no longer narrowed to one block operations context. Via operators we can search for specific patterns across a numbers of blocks.

Any other usecases of reactive-steem?

We might extend above's example slightly to check whom of the self-voters used whale voting service as well. Do you feel there is a value standing behind the project? Give me some feedback!

Technology Stack

This is a nodejs library published to NPM registry. Build with a TypeScript. The main dependancy is rxjs, but some of utility libraries are being used as well.

Roadmap

Ordered by priorities

  1. Reliability support
    1.1 automatically switch source of STEEM blocks, whenever data fetching fails

  2. Custom STEEM - related filter operators
    2.1 filters: isCommentActivity, isVoteActivity
    2.2 map: toOperation

  3. Metadata
    3.1. Additional information propagated to users, i.e. actual block delay

  4. Configuration
    4.1 preffered STEEM nodes (i.e. api.steemit.com or steemd.privex.io)
    4.2 block fetch interval (i.e. each 1000ms or 2000ms)
    4.3 specific block height: (stream from last irreversible block or head block or user-specified)

  5. Support for TypeScript clients

How to contribute?

Post an issue or a pull-request on github. Feel free to post your suggestions below in the comments section.

GitHub Account

https://github.com/adasq

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
STEEMKR.COM IS SPONSORED BY
ADVERTISEMENT
Sort Order:  trending

Hello, @adasq! Thank you for your contribution. Sorry, the review is coming late. You have done a decent amount of work on here. Well done.
The post is already on its sixth day, so, I hope it gets added to the next vote round.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Chat with us on Discord.

[utopian-moderator]

·

Thank you for your review, @knowledges! Keep up the good work!

Hi, @adasq!

You just got a 0.06% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.

Hey, @adasq!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!


@adasq, sorry to see you have less Steem Power.
Your level lowered and you are now a Red Fish!
Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Congratulations @adasq! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!