🤖 TUTORIAL - Paid Voting Bot - Building Bots With steem-js #4

in #utopian-io6 years ago (edited)

bot-tut-4.jpg

This tutorial is part of a series on ‘How To Build Bot’s Using Steem-JS Open Source Library’ it aims to demonstrate practical applications for bots and demystify the code used to create them.

In part 1 we built an auto-liking bot, part 2 we created a curation trail bot, with part 3 we made an auto-follow bot. Please check out those tutorials first as we will build on knowledge learned.

The completed bot code is here - I know some people find it easier to see everything in one block and follow along that way. ⬅️

Outline 📝

Upvote bots are very popular on Steem. Regardless of your stance on using these bots building one will be a good learning experience. We’ll create a bot that will vote on a post whenever someone sends it money. Our bot will work in a typical way, you send X amount of Steem/SBD with a memo to a user for a vote of X percentage.

Requirements

  • A plain text editor (I use atom.io )
  • Your private posting key - This is found in your wallet on the permissions tab on steemit.com, click ‘show private key’ (remember to keep this safe). This is what allows the bot to vote for you

Difficulty

This tutorial is intended to be beginner friendly. (I appreciate feedback on the teaching level)

Learning Goals

  • re-use knowledges learned about Steem-js in parts 1,2 & 3 Streaming transactions and Voting
  • look at the transfer transaction type on the Steem blockchain
  • practise breaking down data into relevant information
  • use control flow to decide on a vote strength before voting

Step 1 - Setup 💻

For this tutorial our bot will run in the web browser, a more effective way to use this bot would be on the command-line but I feel we’ll still benefit from this minimal in browser approach for now.

Use this template to get started - This is a base file for todayss project and includes code from the previous two tutorials. You’ll see the output in your browser console again like last time (refer to previous post if you can’t remember). Familiarise yourself with the functions streamTransactions() + broadcast.vote() and notice they are the same as we have already used.

In this tutorial, the ACCOUNT NAME will be the account who is getting sent Steem/sbd and the one who is doing the voting. Add your info to get started

        // Tutorial 04 - paid vote bot
        const ACCOUNT_NAME = ''
        const ACCOUNT_KEY = ''

Step 2 - Check Connection for Transfer 👀

If you’ve followed the previous tutorials hopefully streaming transactions feels pretty normal now. We’re going to go straight into checking for a transfer. Add a simple if statement.

steem.api.streamTransactions('head', function(err, result) {
    let txType = result.operations[0][0]
    let txData = result.operations[0][1]
     if(txType == 'transfer') {
        console.log(txType, txData)
    }
});

You’ll see the transfer data streaming in the console. All the information we need is there. When a transfer comes into us we’ll check the amount and memo and send out a vote

Screen Shot 2018-01-16 at 22.54.55.png

DATA -> from,to,amount,memo,

Step 3 - Calculate Voting Weight 🏋️‍♂️

We already looked at how to send a vote in tutorial#2, this time we’re looking to add a custom weight so we can charge more for a stronger vote.

Thinking about the data we need, we first want to check the if the transfer is Steem or SBD, we need to look at the actual amount and we’ll want to add some rules to decide what vote % we should give for each amount paid.

We’ll make a function that takes a single parameter to make out life easier.

function calcVoteWeight(amountPaid) {}

Screen Shot 2018-01-16 at 23.08.05.png

Looking at how we receive the data, the amount is a string where the token type is added to the end e.g ’10 SBD’ or 32 STEEM. We need to separate that data. My first thought here is to split the data at the space because that is common between both types of transfer. If we split the text at the space we’ll get an array where the first item is the amount of tokens sent and the second item is the type of token e.g [’45’, ‘STEEM’]. We could use the indexes [0] or [1] to separate that information but now might be a good time to intro pop() which returns the last item of an array and shift() which returns the first item in an array, useful to have in your arsenal.

let token = amountPaid.split(' ')
let tokenType = token.pop()
let tokenValue = token.shift()
let weight;

You can see I’ve also added a variable for vote weight let’s make a rule now we have our data in a readable format. To keep our bot simple for this tutorial I’m going to say our bot will give a 100% upvote for 1SBD, 50% upvote for 0.5SBD or 10% vote for 0.1SBD, we’ll also add in a calculation to reduce the weight slightly if they paid in STEEM. Create an if statement following those rules.

if (tokenValue >= 1){
  weight = 100
} else if (tokenValue >= 0.5) {
  weight = 50
} else {
  weight = 10
}

Next let's check the tokenType and adjust for Steem vs sbd. Ideally, we would want to check an exchange for the current price of steem/sbd but it’s a little out of the scope of this tutorial. For now, we’ll say that a STEEM is worth 80% of a SBD.
let steemToSbdRatio = 0.8

if( tokenType == 'STEEM') {
  return (weight * steemToSbdRatio) * 100
} else {
  return weight * 100
}

We’re checking if the token type is Steem and multiplying by the ratio we made. Remember when we send a vote of the Steem-js library there are no decimal places so we multiply by 100. e.g 10000 would be a 100% vote, 5438 would be a 54.38% vote.

Combine all of this together will give us our complete calculation function.

Step 4 - Sending vote based on memo 📋

This whole bot is about sending votes to the user who has sent us money. The way a user submits a post is by entering the URL as the memo. Let’s create a function for sending a vote with the information we need. We’ll have three parameters.
function sendVote(author, memo, amountPaid){}

A memo will be a full URL, when working with Steem-js we need to get the permlink which is know as the very last part of the URL. e.g my-awesome-new-post-about-steem-js. Learning what we used from the the vote calculation above we can split the URL to get an array, this time we’ll split at the /. The permlink will then just be the last part of the array which we grab with pop.

let memoToPermlink = memo.split('/')
let permlink = memoToPermlink.pop()
let weight = calcVoteWeight(amountPaid)

Now’s the time to use that function we made for the weight calculations. we can now make sure the parameters of the broadcast function match our data.

steem.broadcast.vote(ACCOUNT_KEY, ACCOUNT_NAME, author, permlink, weight, function(err, result) {
    console.log(err, result)
});

Step 5 Combine it all Together

The final step! Use our new function inside of our transaction stream like so.

steem.api.streamTransactions('head', function(err, result) {
    let txType = result.operations[0][0]
    let txData = result.operations[0][1]
    if(txType == 'transfer' && txData.to == ACCOUNT_NAME) {
        sendVote(txData.from, txData.memo, txData.amount)
    }
});

💥 Just like that, we have our voting bot, you can advertise away and see if you can get some votes going. There's a lot more we could do here. First it's common to send the person a transfer/memo and or a comment along with the upvote. In future we could also look at creating a bid bot that allows users to get a greater share based on the other bids in a given time. Far too much for one tutorial but do let me know if you would find that useful.

Our fourth Bot is now finished and ready to open up a vote canon. It’s worth mentioning that I’m not actually a big fan of the vote bots that exist, I think it gives a false representation of post values. With that said I’d rather you have the skills to make one yourself than not.

Here’s the full code #4 🤖

There’s still a lot more we can do with bots and the Steem API but I hope you find this interesting and useful. If you’re looking into building bots let me know or ask any questions below ✌️

Other Posts in This series



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Thank you for the contribution. It has been approved.

You can contact us on Discord.
[utopian-moderator]

appreciate you reviewing the tutorial, thanks 👊

Hey @sambillingham I am @utopian-io. I have just upvoted you!

Achievements

  • You have less than 500 followers. Just gave you a gift to help you succeed!
  • Seems like you contribute quite often. AMAZING!

Suggestions

  • Contribute more often to get higher and higher rewards. I wish to see you often!
  • Work on your followers to increase the votes/rewards. I follow what humans do and my vote is mainly based on that. Good luck!

Get Noticed!

  • Did you know project owners can manually vote with their own voting power or by voting power delegated to their projects? Ask the project owner to review your contributions!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x

Great tutorial as usual, really in-depth! Btw, I used your notifier all day on Ubuntu today and it seemed to work completely fine!

That's awesome! Glad to hear it didn't have any issues. Thanks for the continued support 👊

Thank you for keeping this series up. Beginner friendly & clean as always.

Hello, when I run this bot I get error after some time:

Unhandled rejection TypeError: Cannot read property 'operations' of undefined at /root/curation.js:7:31 at /root/node_modules/steem/lib/api/index.js:347:21 at /root/node_modules/steem/lib/api/index.js:320:21 at /root/node_modules/steem/lib/api/index.js:291:21 at tryCatcher (/root/node_modules/bluebird/js/release/util.js:16:23) at Promise._settlePromiseFromHandler (/root/node_modules/bluebird/js/release/promise.js:512:31) at Promise._settlePromise (/root/node_modules/bluebird/js/release/promise.js:569:18) at Promise._settlePromise0 (/root/node_modules/bluebird/js/release/promise.js:614:10) at Promise._settlePromises (/root/node_modules/bluebird/js/release/promise.js:689:18) at Async._drainQueue (/root/node_modules/bluebird/js/release/async.js:133:16) at Async._drainQueues (/root/node_modules/bluebird/js/release/async.js:143:10) at Immediate.Async.drainQueues [as _onImmediate] (/root/node_modules/bluebird/js/release/async.js:17:14) at runCallback (timers.js:756:18) at tryOnImmediate (timers.js:717:5) at processImmediate [as _immediateCallback] (timers.js:697:5)

Loading...

Thanks for the insight as I always wondered how people create bots. I don't know what all this means - but at least I have a faint idea. Lol

Hi Sam,

I hope this message can reach you. I have read your post and it's absolutely amazing. I have a plan to operate a voting service which is quite similar to smartsteem.com.

Can you please help me to build up this website? If you're interested in, we can definitely discuss further regarding payment term.

I'm looking forwards to your response.

Kind regards

John.

Thanks for this post. I'll have to look into this in more detail.

Such code is ONLY to be used on your own machine, not to install onservers as the const , thus your keys would be readable

Coin Marketplace

STEEM 0.19
TRX 0.13
JST 0.030
BTC 59965.71
ETH 3286.33
USDT 1.00
SBD 2.36