Repository
https://github.com/jnordberg/dsteem/
Outline
In this tutorial we’re going to be looking into the DSteem javascript library. DSteem, created by @almost-digital is significantly more performant than steem-js. We’ll use DSteem to create a script that watches for transactions on the blockchain and automatically votes posts from a specific user.
👨🏼💻 The full code for the script can be found on Github & CodePen 🚀
Requirements
- A plain text editor (I use VS Code)
- A browser (I use Brave)
Difficulty
Beginner
Learning Goals
- Connect to the api.steemit.com using DSteem
- listen for blockchain transactions
- Check transactions against rules
- Send votes using DSteem
Preface
There are a bunch of tutorials, plenty in fact. There’s 34 tutorials in the official repo to be precise. So then why do I get the sentiment from the community that dSteem is unapproachable and steem-js is easier to use?! Has anyone else thought or felt this?
While the documentation is great the code example might be lost on beginners. Why? Well, as a developer with some experience you can clone a repo, install the dependencies and kickstart a dev server all whist sipping coffee with your other hand. The new dev is thinking WTF am I doing, why do I have 9 files already and why do I have to enter the matrix just to run one line of code from this library!
No you don’t need Node.js or a development server to make use of Dsteem. Yes you can create simple scripts in the browser to interact with the Steem blockchain.
Let’s do this.
We’ll stream blocks from the blockchain. Check for specific users. Vote as a response when a specific user post comes through. kaboom!
Step 1 - Setup
We can run this script in the browser. Create a .html
file. We’ll include a specific version of dsteem and create a script tag for out own javascript code.
<html>
<head>
<script src="https://unpkg.com/[email protected]/dist/dsteem.js"></script>
<script>
// Tutorial Code here
</script>
</head>
<body></body>
</html>
Alternatively you can work in codepen.io - Fork this Pen.
Step 2 - Listen for transactions on the Blockchain
Now we’re setup we can start to interact with the blockchain using DSteem. First up we need to setup a connection to one of the Steem API servers. We’ll use Steemit.com’s API server. This client is what we’ll use to make calls against the API.
const client = new dsteem.Client('https://api.steemit.com');
DSteem has a number of helper functions separated into categories blockchain
, broadcast
and database
. As part of the blockchain helpers we can stream blocks as they’re processed by the network.
First save a reference to the stream
const stream = client.blockchain.getBlockStream();
If you’ve never used Streams before and are confused dig into this article to learn more. Streams emit events we can hook into (‘data’, ‘end’, ‘error’, ‘close’, ‘readable’). We’ll listen for the data event and for each chunk of data we receive from the stream we’ll run a function. For now lets log the result.
const stream = client.blockchain.getBlockStream();
stream.on('data', (block) => console.log(block))
You should start seeing blocks in your console
Nice. lets abstract this out to keep our code friendly
const stream = client.blockchain.getBlockStream();
stream.on('data', (block) => processBlock(block))
// Helper function to separate logic into smaller pieces
function processBlock(block) {
console.log(block)
}
Digging into the console results you’ll notice the blocks contain and array of transactions. Of those transactions each has an operation type which we’re used to understanding ‘vote’, ‘comment’, ‘custom_json’ etc. Dsteem also has a helper for streaming operations directly but I think it’s useful to look at inspecting the blocks ourselves. Operations are stored in an array of each transaction, it doesn’t look the friendliest to access.
// check individual operation type
block.transactions[0].operations[0][0]
Now we can filter the array to check for a specific type of operation. In this project we’re going to be looking for comments (also includes top level posts) by a specific author. Filter for ‘comment’.
function processBlock(block) {
// Each block contains multiple transactions
const txs = block.transactions.filter( tx => tx.operations[0][0] === ‘comment’ )
// you’ll see arrays of varying lengths populating the console
console.log(txs)
}
lets extract our filter function into something more generalised. This way we can reuse this function through our app for different purposes.
function processBlock(block) {
// filter by operation type
block.transactions.filter( tx => filterTransactions(tx, ’comment’) )
}
function filterTransaction(tx, operationType){
return tx.operations[0][0] === operationType
}
Step 3 - Check for specific data within a transaction
We’ve split the transactions in the blocks to only show those we’re interested in. Next we’ll check the specific data of each of the transactions. First lets see each transaction in the console. Similar to the operationType the operationData is also nested in an array.
// check individual operation Data
block.transactions[0].operations[0][1]
function processBlock(block) {
// Each block contains multiple transactions
block.transactions
// create a new list of transactions that only include a specific type of operation
.filter( tx => filterTransaction(tx, 'comment') )
// Check the data of each operation
.forEach( tx => console.log(tx.operations[0][1] ))
}
Again we can abstract the operationsData into a friendly function. This makes working with our app less cognitively intensive. We can use words that describe whats happening instead of looking at nested objects and arrays.
// Helper for nested transaction Data
function transactionData(tx){
return tx.operations[0][1]
}
Now we can abstract the processing of the data into a separate function also.
function processBlock(block) {
block.transactions
.filter( tx => filterTransaction(tx, 'comment') )
.forEach( tx => processTransaction( transactionData(tx) ))
}
processTransaction( txData) {
console.log(txData)
}
We now have a functions that has access to individual transaction data. We can choose how to process the data and how to respond. For this project we’re interested in the author of the comment. If the author matches that of a predetermined list we’ll send a vote.
Make a list of usernames.
// perhaps you want your list to look like this and to support my content ;)
const AUTO_VOTE_LIST = ['sambillingham', 'codewithsam', 'finallynetwork']
create a helper function for checking this list of usernames. If a username exists in our list it should return true.
// Helper for checking vote list
function isAutoVote(name){
return (AUTO_VOTE_LIST.indexOf(name) > -1);
}
Edit the processTransaction
function to make use of our new helper.
processTransaction( txData) {
if ( isAutoVote(txData.author) ) console.log( `${txData.author} just posted a comment` )
}
Let's move on to broadacting a transaction instead of just viewing data.
Step 4 - Broadcast Votes
Different from Steem-js library DSteem creates a decoded instance of the posting key rather than using the raw string.
setup our username and private posting key (wif). Grab this from the steemit.com permissions tab.
const USERNAME = ''
const POSTING_KEY = dsteem.PrivateKey.fromString('')
We’ll use the broadcast
helper and call vote client.broadcast.vote
, passing an object with the relevant data. let’s wrap the DSteem library call into our own function.
// Broadcast vote using DSteem
function sendVote(author, permlink) {
client.broadcast.vote({
voter: USERNAME,
author: author,
permlink: permlink,
weight: 10000
}, POSTING_KEY)
.then( (result) => {
console.log(`VOTE FOR ${author}:${permlink}`)
console.log(result)
})
}
We can now send votes with a small helper function sendVote(author, permlink)
passing in an author and permlink to vote on. Moving back to the processTransaction()
function we can broadcast a vote instead of logging the data.
// Process Post against any rules and send response
function processTransaction(txData){
if ( isAutoVote(txData.author) ) sendVote(txData.author, txData.permlink)
}
Just like that we’ve created a simple auto voting bot. Go ahead and test it, make a post from your testing account or add username you know are posting regularly.
👨🏼💻 The full code for the script can be found on Github & CodePen 🚀
I hope you have found this tutorial useful. If you have questions or I can help with a project please comment below.
I thank you for your contribution. Here are my thoughts. Note that, my thoughts are my personal ideas on your post and they are not directly related to the review and scoring unlike the answers I gave in the questionnaire;
Structure
Language
Content
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]
Thank you for your review, @yokunjon! Keep up the good work!
Congratulations @codewithsam! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
Click here to view your Board of Honor
If you no longer want to receive notifications, reply to this comment with the word
STOP
To support your work, I also upvoted your post!
Congratulations @codewithsam! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
Click here to view your Board of Honor
If you no longer want to receive notifications, reply to this comment with the word
STOP
Hi @codewithsam!
Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server
Hey, @codewithsam!
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!
Thank you for posting! Probably helped me out a lot.