Contribution - Actifits NodeJS voting bot and token calculator
Introduction
Hello Utopians! @cryptouru over here with my second contribution :)
This time I come with a Voting bot and a SMT token tracker for the @actifit community (a community you should totally check out BTW). This development is a direct response of this task:
Before going into task details I want to thank @mcfarhat for the opportunity and say that it was a pleasure working with him and very nice to meet him. He really knows what he wants and how to communicate it, working with him was a breeze and we always seemed to be on the same page. I would totally repeat this experience :)
Repository
https://github.com/mcfarhat/actifit-bot
I divided the task into three separate node processes. The voting process, the token calculation process and an API process.
Voting Process
The voting process is heavily based on @yabapmatt community bot script:
https://github.com/MattyIce/communitybot
As the task requested this process does the following:
- Waits until 100% voting power and 24hs have passed since last vote
- Gets all actifit posts and filters them out acording to the following criteria
- actifit is main tag
- @actifit and @actifit.pay are beneficiaries
- Post has not been previously voted by accout or flagged by known trusted accounts
- Post has the property step_count in it's json_metadata
- Calculates vote weight according to the rules shared on the task request.
- Votes and comments in a synchronous way to avoid hitting API or transaction limits .
Besides the previous logic I added configuration options to exclude posts with paid votes from voting round and to set a minimum post age as filter. Paid votes filtering is done by consulting the steembottracker API to load an array of bots. (thanks again @yabapmatt !)
The main technologies involved on this task were:
- NodeJS
- SteemJS
- Axios
Token Balances & Transactions
Calculating token balances was no easy feat. My first approach was getDiscussionsByCreated
a well known steemJS API method to bring new posts with the capability of filtering them by a tag.
When results were = 100 I made another request until results was <> 100 or the last post from the request was the same post used to index.
On paper this approach should have eventually loaded all actifit posts, yet there is an unspoken API limitation in regards unpopular tags, that is that you usually can't go more than a week back when using this method. I haven't found this documented anywhere, yet from experience I can say it is the case for many tags.
After hitting this wall I decided to go after the @actifit voting history. @mcfarhat told me that it should include all posts elegible for token rewards. This approach was harder and more tedious but eventually brought all the posts we expected.
After the previous was running the process was as it follows:
- Filter out posts with beneficiary rule
- Use step_count rule to calculate post token rewards (details on task request)
- Go through post votes and reblogs to generate appropiate token transactions and rewards
- Save everything into a mongoDB database:
user_tokens: with fields user, total_token_count
token_transactions: with fields user, reward_activity, post_permalink, date, and token_count.
In paralel there is a process which queries the token_transactions table and groups token counts with users. With this the user_tokens table/collection is filled
As a bonus I did setup the script to backup all post data that passes the filter, as I find this safe-guard to be good in the case or unexpected API limitations.
The main technologies involved int this task were:
- NodeJS
- MongoDB and it's node driver
- SteemJS
API
Well... This is just 20 < lines of code Express API that queries the previous implementation.
It has two methods:
- User: receives username and shows token balances
- Transactions: shows last 250 global token transactions or last 250 of given user if such param is present:
The main technologies involved int this task were:
- NodeJS
- MongoDB and it's node driver
- Express Server
Bonus
Email Service
I'm sort of an email guy, so I could not help but to implement an email notifications system. In case of an error, the configured email would get notified and after each voting round an e-mail summary would be sent.
Ok....
I think that's all of it :)
If anyone has any doubt or concern just let me know. I'll hapilly reply.
Here's the pull request:
You did a great job with this task request. It really cool to take the time to improve an open source project and actifits is worth it in my opinion.
Let's go for the review:
Why the gitignore is so huge? It seems a little bit of an overkill
Useless comments war mouahaha, are those really necessary? You got a few of these.

but this one is good!
https://github.com/mcfarhat/actifit-bot/pull/1/files#diff-0364f57fbff2fabbe941ed20c328ef1aR38 => Why do you keep this?
You're using a lot of console.log but you've implemented a log util why not use it? Either log what's useful or remove console.log that are here for debug purposes.
You're mixin
const
var
andlet
notation. You should drop thevar
Sometimes you're using
{}
sometime not with ifs and elses which leads to things like thatI think it's weird to read
You've got useless padding
Using
++
is a bad practice => https://eslint.org/docs/rules/no-plusplusYou're mixin
function(){}
with() => {}
arrow notationSometimes you use
==
instead of===
You're mixing camelCase and snakeCase notation

You've left dead code :p feeling sentimental?
You've got indentation issues
From the few previous issues I think you should add prettier and/or eslint to have a homogeneous code.
Nicely done on the
getVotingPower
function implementation you didn't forgot about the last vote time!Yeah you use the Async syntaxe
steem.api.getRebloggedByAsync
! +1I see that you've got some knowledge of mongodb
await db.collection('token_transactions').aggregate
+1 too :pIn overall this is a good but you're using old javascript notations with new ones (ES6, ...) if think using eslint would really benefit you.
Keep up the work, congrats!
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? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]
Hey @gregory.latinier
Here's a tip for your valuable feedback! @Utopian-io loves and incentivises informative comments.
Contributing on Utopian
Learn how to contribute on our website.
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!
Thanks @gregory.latinier you're the man! Your review is awesome and very well thought. Even though it's kinda harsh for me I really appreciate you took the time to write it and I will use it to learn and improve.
As your review came with some questions I will try to answer some to my best. Though many of the cases are errors I made with no particular explanation.
I used some boilerplate .gitignore which may have been quite an over kill.
I kinda like the mix of both of them. I appreciate the additional information when I manually execute but aknowledge there is no need to log it.
Totally! I 'm moving into ES6 yet the original codebase wasn't so. So it sorta ended up very messy :/
Eslint will surely help! I really apreciate this feedback. Thanks againt.
Cheers :)
Thank you for all the help on this, well done !
Hey @cryptouru
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!
Hey @utopian-io thanks for giving developers the space to contribute this way.
You're awesome!
thanks for information
Congratulations @cryptouru! You have received a personal award!
Click on the badge to view your Board of Honor.
Do not miss the last post from @steemitboard:
SteemitBoard World Cup Contest - The results, the winners and the prizes
Wow all that wen't way over my head,thank you for working with the actifit teem. I like this app and I am glad to see it getting better all the time!
Congratulations @cryptouru! You have completed the following achievement on Steemit and have been rewarded with new badge(s) :
Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word
STOP
Congratulations @cryptouru! You have completed the following achievement on Steemit and have been rewarded with new badge(s) :
Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word
STOP
Congratulations @cryptouru! You have completed the following achievement on Steemit and have been rewarded with new badge(s) :
Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word
STOP
Congratulations @cryptouru! You have completed the following achievement on Steemit and have been rewarded with new badge(s) :
Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word
STOP