(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 1 | 98.0% |
Vote 2 | 96.04% |
Vote 3 | 94.12% |
Vote 4 | 92.24% |
Vote 5 | 90.40% |
Vote 6 | 88.58% |
Vote 7 | 86.81% |
Vote 8 | 85.08% |
Vote 9 | 83.37% |
Vote 10 | 81.71% |
Vote 11 | 80.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%).
(Next Post: Part 4)