Write a Steemit Web App: Part 3 - Current Voting PowersteemCreated with Sketch.

in #steem-dev7 years ago (edited)

(Previous Post: Part 2)

What is Voting Power?

Voting Power is a rate-limiting feature of Steem to help prevent abuse. Each vote cast reduces the user's voting power by 2% of their remaining pool. So, if someone (or a bot) goes wild and upvotes hundreds of posts, then each upvote is worth less than the previous one (eventually being worth nothing).

Voting power regenerates linearly over 5 days, or 20% per day. So, with HF19, most people have set a goal of only depleting 20% of their voting power per day so that it will regenerate to 100% within 24 hours. This means that they can vote 11 times (at 100% per vote - only worth noting for those with enough steem power to unlock the ability to choose how much each vote is worth):

#Voting Power
(Start)100.00%
Vote 198.0%
Vote 296.04%
Vote 394.12%
Vote 492.24%
Vote 590.40%
Vote 688.58%
Vote 786.81%
Vote 885.08%
Vote 983.37%
Vote 1081.71%
Vote 1180.07%

Representing Voting Power in a Web App

When you fetch account information with Steem.js, such as with the getAccounts() function, you get a voting_power number in the account data object: { ..., voting_power: 9668, ... }. However, if you keep refreshing, you will not see this number ever change on its own - even if it's been five days since the last vote. This value is only updated when a user casts a vote.

Note: A LOT of the Steem applications out there are guilty of just showing this value... so even if you are really at 100% voting power, the apps won't reflect that.

But, there is another value in the account data object that is also updated when a vote is cast: {..., last_vote_time: "2017-07-03T01:12:15", ...}. So, your web app must do the task of calculating the current voting power value given these two inputs.

The basic formula is to take the reported voting_power and add in how much should have been regenerated since the last_vote_time. The maximum result would be 100%.

JavaScript Code

In the first post of this series, we used the following code in the naive way to represent the user's voting power:

vm.$set(vm.userData, 'power', result[0].voting_power / 100)


To correct this, we must first figure out how many seconds have passed:

let secondsago = (new Date - new Date(result[0].last_vote_time + "Z")) / 1000


Next, divide the secondsago by the number of seconds in 5 days (432000) in order to get a percentage of how much of the 5 days has elapsed. Multiply this by 10000 (100%) to calculate how much voting power has regenerated so far, and add to the voting_power value from the account object:

let vpow = result[0].voting_power + (10000 * secondsago / 432000)


Now we can set the value in our viewmodel (taking care of formatting and ensuring that the max is 100%):

vm.$set(vm.userData, 'power', Math.min(vpow / 100, 100).toFixed(2))


The whole thing together would look like:

steem.api.getAccountsAsync([accountName])
  .then(function (result) {
    ...
    let secondsago = (new Date - new Date(result[0].last_vote_time + "Z")) / 1000
    let vpow = result[0].voting_power + (10000 * secondsago / 432000)
    vm.$set(vm.userData, 'power', Math.min(vpow / 100, 100).toFixed(2))  
    ...
  })


Improvements to this would be to periodically recalculate the value using a timer so that the user always sees their latest voting power (especially if they are waiting for it to tick over to 100%).

javascriptlogo.png

(Next Post: Part 4)

Sort:  

Sir you are a great inspiration for people out there.

Thanks so much for posting these. I look forward to trying out the code.

Congratulations @jfollas! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of posts published

Click on any badge to view your own Board of Honnor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

3 months later, I find your post. Helped me tremendously, wish I had found it sooner so I could have voted on it.

Thanks for putting this up here for people like me to find.

To make the refresh add this function to the end where refreshAccountData function was called:

        refreshAccountData(vm.user)
        function timeout() {
          refreshAccountData(vm.user,true)
          setTimeout(function () {
            timeout();
          }, 1000);
        }
        timeout()

No need to refresh follow(ers/ing) each time:

        function refreshAccountData(accountName,refresh=false) {
           ...
              if( ! refresh ) {
                getFollowersList()
                getFollowingList()
                getIgnoredList()
           ...
              }