Tutorial - User Wallet History with Steem.js #12

in #utopian-io6 years ago (edited)

steem-12.png

This tutorial is part of series that aims to demonstrate
how to use steem.js to build STEEM projects and bot with real work application.

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

In this tutorial, we look at how to get the wallet data of a STEEM user. Particularly we’ll look at getting ’transfer’ data where usually the wallet also contains information about powering up/down and claiming rewards.

Difficulty

Beginner - This is a fairly friendly tutorial for those familiar with Steem-js and Javascript. Please re-visit tutorials 1-10 if you’re unsure of any aspects of this tutorial.

Learning Goals

  • look at the getAccountHistory() steem.js library function
  • display a list of the latest user wallet history

Preface

Before diving into the tutorial I thought I’d share how I decided to make this tutorial. I’ve been looking at adding new features to steem-js-boilerplate while working on personal steem platform based projects. I release I had not yet looked into where the wallet data is stored and how to retrieve it. in my doc search/googling I came across this GitHub issue How to get user wallet history? That had gone unanswered.

My initial attempt worked backwards through blocks one by one looking for a relevant user and incoming/outgoing ‘transfer’ type transactions. While this totally works it’s completely unreasonable for a web app and pretty slow for a bot style script taking roughly 5minutes to process 1hour of blocks.

I went in search of another way. Looking through the postpromoter bot code I found the function I needed. While not immediately obvious it makes sense after you know that getAccountHistory() gets all actions affecting a user over the blockchain, these can be filtered to show just votes/comments/transfers etc.

Intro/Setup

This tutorial is focussed around building the page in the browser and running the code on the front end but of course, there is no reason why this couldn’t be on the backend or as part of a separate micro-service.

I’ve created a starting template here a single html file with CDN links for bootstrap, Steem.js, jQuery and the basic html structure ready to go.

Getting Account/Wallet History

getAccountHistory function is listed in the docs but without any explanation, it’s not inherently clear exactly what this should be used for. In fact, this shows all actions that affected a user account and works great for what we need.

The function has 3 parameters and a callback function -

account - A single steem username

from - The first transactions you want. Works backwards in time from this number. E.g A value of 100 would get the users 100th, 99th, 98th etc. Use -1 to get latest

limit - The number of transactions to get. From 100 with limit 100 would get from 100 - 0. Accepts large numbers e.g 9999.

steem.api.getAccountHistory(account, from, limit, function(err, result) {
  console.log(err, result);
})

First, add data and the get account history to see it in actions. We’ll use 50 for ‘from’ and 50 for ‘limit’ to get the first 50 transactions on my account.

        const ACCOUNT_NAME = 'sambillingham'
        steem.api.getAccountHistory(ACCOUNT_NAME, 50, 50, (err, result) => {
          console.log(err, result)
        });

tut-1.png

Check the console and you should notice the very first transactions contained in the array if your account creation. You might also notice that this function actually returns the block number along with the relevant data in op (operations) or virtual_op.

Moving on we’ll use -1 for ‘from’ and 50 for ‘limit’ to get the latest 50 transactions. We can use a simple filter to check each transaction for its type and store the relevant ones. Each transaction is an array where the first property is its own index and the second property is the data. We’ll first take the second property of the data e.g tx[1] where tx represents the transaction from there the data contains the block, op, op_in_trx, timestamp, trx_id, trx_in_block and virtual_op. we want to select the first property of the operation which is its type, leaving us with tx[1].op[0] and in this case, we’ll check it against transfer

        const ACCOUNT_NAME = 'sambillingham'
        const WALLET_FILTER = 'transfer'
        steem.api.getAccountHistory(ACCOUNT_NAME, -1, 50, (err, result) => {
          let transfers = result.filter( tx => tx[1].op[0] === WALLET_FILTER )
          console.log(transfers)
        });

You may see significantly less transfers in the console. Remember while we retrieve 50 transactions on our account many of those may be votes/comments/posts etc so after the filter you may need to increase you limit property.

Displaying latest wallet transactions

The console is great but with a couple more lines we can have it in the browser in a more realistic environment. A basic bootstrap table is already added to the html. We’ll loop over the transactions and add the individual data as a new row.

        const ACCOUNT_NAME = 'sambillingham'
        const WALLET_FILTER = 'transfer'
        steem.api.getAccountHistory(ACCOUNT_NAME, -1, 50, (err, result) => {
          let transfers = result.filter( tx => tx[1].op[0] === WALLET_FILTER )
          displayTransactions(transfers)
        });
        function displayTransactions(transactions){
          transactions.forEach((tx) => {
            let transfer = tx[1].op[1]
            let template =
            `<tr>
              <td>${transfer.from}</td>
              <td>${transfer.to}</td>
              <td>${transfer.amount}</td>
              <td>${transfer.memo}</td>
            </tr>`
            $('tbody').prepend(template)
          });
        }

tut-2.png

The wallet page of steemit.com includes other types of transactions too. If you’re attempting to replicate that type of interface you’ll also need to filter for power up/down and claiming rewards.

The final code for this project can be found here

Let me know if you found this useful for any of your projects. Check out the previous tutorials



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Very nice and concise tutorial.

I noticed you don't use promises, is there a reason for this? Steem-js api comes with bluebird as a dependency. It already provides Async methods. For example, filtering can be done as:

steem.api.getAccountHistoryAsync(ACCOUNT_NAME, -1, 50)
        .filter( tx => tx[1].op[0] === WALLET_FILTER )
        .each((transfer) => {
             displayTransactions(transfer)
        })

You may want to checkout my tutorial from awhile ago that shows account history traversal by date using generator functions and promises.

https://utopian.io/utopian-io/@r351574nc3/tutorial-viewing-steemit-account-history

hey, I did not realise Steem-js had bluebird as a dependency, that's pretty cool. I avoid using promises in the tutorials because I feel promises are less approachable to newer developers. As per your example, it does produce far cleaner code. I'm totally going to look at where I can implement some of this style into my projects and dig through your other tutorials. Thanks!

Thank you for the contribution. It has been approved.

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

Thanks a lot for the tutorial. By reading the wallet history of an upvoting bot, adding up the bids for each round, I think we can build something like the Steem Bot Tracker. But I don't know how to get the start/end of a bidding round yet. I am going to read this whole series of tutorials in details. It is fun and useful. Thank you so much.

Thanks for sharing this tutorial.
I will try this when I have enough power.

Cheers!

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!

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

Sam, another great tutorial.

Your tutorial came a bit too late for me as I just have published a similar tutorial. But I did the same thing; I looked at the postpromoter code to learn :)

Did you find a good way to load more account data after your first request? I initially load 5000 rows from the account history, which takes some time. Would be better to load the data incrementally.​

Thanks, Jo. just been over to look at your latest post. Great tutorial and project you have there!

Index 0 of each returned item in the results array is an ID of sorts. You can get 50 items from -1, then item 0 will be your starting point for the previous 50 etc. e.g

        steem.api.getAccountHistory(ACCOUNT_NAME, -1, 50, (err, result) => {
          let endItem = result[0][0]
          
          steem.api.getAccountHistory(ACCOUNT_NAME, endItem, 50, (err, result) => {
            //
          });
        });

Excuse this horrible code but hopefully that illustrates better.

Thank you, Sam; for the kind words and the code :)

We're all just republishing the same tutorial!!!! LOL

Check this out. I use your favorite language (Typescript) to traverse the entire account history and filter by date. Enjoy the use of generator functions FTW!

https://utopian.io/utopian-io/@r351574nc3/tutorial-viewing-steemit-account-history

Thank you for the timely tutorial. I am working on balance transfer, steem escrow related projects. This will be a great help.

Glad you think it will be helpful! Let me know if you get stuck with your projects and I'll always try to help.

I definitely will.

Siempre agradecido con usted por aportarnos de su gran información amigo muy buen tutorial Saludos :D

Wow, I really enjoy your work. I started looking through your stuff last night and I have learned a ton. You also have some great tools I've been missing. I was wondering if you have a way to find out if specific people have ever upvoted you? A tool that could go through your followers and following and list the votes they've placed for you would be very helpful. With the things I learn from your posts maybe I could make it some day? 🙂

Thanks for checking out the tutorials. https://steemworld.org/@sambillingham has a feature to look at who has upvoted your content but it only stores the previous week. Using http://steemsql.com/ it would be quite easy to make a tool that found info about which followers have upvoted you etc. Are you learning to code?

That was my plan, it's just so overwhelming to learn. Plus access to steemsql was expensive considering I wouldn't be making money off it or at least for a long time. I'd actually rather hire someone to write a few things I'd want. I'm looking for someone who would not only create a bot but host it as well. I haven't found any out there that are exactly what I'm looking for. I am slowly learning some code through your poasts though.

Coin Marketplace

STEEM 0.20
TRX 0.13
JST 0.029
BTC 67402.68
ETH 3481.04
USDT 1.00
SBD 2.65