Steem Delegations Tutorial Part Two
Delegating your Steem Power to another user can be a great way to invest in Steem and Steemit. You can get an excellent annual percentage rate (APR) on your investment if you delegate your Steem Power to another user.
This post is part two of a tutorial series about Steem delegations. There will be three parts in total.

Curriculum
Part One
You will learn how to …
- get the current delegations for a user from the Steem blockchain
- convert VESTS to Steem Power (SP)
- show the information in a simple web application
Part Two (this post)
You will learn how to …
- get the transaction history for an account
- how to filter relevant data from the historical transaction data
- calculate the annual percentage rate for your investments
- show the information in a simple web application
Part Three
You will learn how to …
- make a simple form for new delegations
- delegate your Steem Power to another Steem user
- to remove your delegation
- to increase or decrease your delegation
Steem Delegation Tutorial Two
In this part of the tutorial series, you will learn how to get the transaction history for an account. Furthermore, you will learn how to filter this transaction data for relevant delegation data and calculate the annual percentage rate for your investments.
We will also build upon the web application we coded in the first part of this tutorial as we want to show the delegation in our web application.
At the end of this tutorial, we want to have a list of all relevant delegations and the associated transfers. We also want to be able to see the APRs for our invested Steem Power.
Have a look at the live version of the small web app we will build in this tutorial series. If the link is broken, you can find detailed instructions on how to run the app locally in the first part of this tutorial series.
Please, contact me if you run into any problems. I’m happy to help if I can.
Technologies Used
- SteemJS—Steem.js the official JavaScript library for the Steem blockchain
- Next generation JavaScript
- Hyperapp—1 KB JavaScript library for building frontend applications
- Hyperapp Router—Declarative routing for Hyperapp using the History API
- Bulma—free and open source CSS framework based on Flexbox
- Fontawesome—the web’s most popular icon set
- Parcel—Blazing fast, zero configuration web application bundler
Recapitulation First Part
In the first part, we used a call to steem.api.getVestingDelegationsAsync
to get a list of the current delegations a user has made for her account. This API call is a quick way to get an overview of the current delegations.
But the current delegations will not help to calculate the APR for a transfer we received in the past. What if we received a transfer for our delegation last week, but have changed the delegation two days ago? We need to find a way to get the delegated SP for historical data. We can do this by going through our account history. From the account history we will be able to build a delegation history by filtering the data for two transaction types: transfer and delegate_vesting_shares
Requesting The Account History
We will make a call to steem.api.getAccountHistoryAsync
which will return the account history for the user given in the first parameter. The second parameter is the from parameter and the third is the limit parameter. If you want to get the latest items you can pass -1
to the from parameter. We want to get the latest 5000 entries of our account history.
setAccountHistory: arr => state => ({ accountHistory: arr }),
requestAccountHistory: (username) => async (state, actions) => {
try {
let accountHistory = await steem.api.getAccountHistoryAsync(username, -1, 5000)
if (!accountHistory) { throw new Error('Sorry, no account history found.')}
actions.setAccountHistory(accountHistory)
actions.setDelegationHistory(assembleDelegationHistory(accountHistory, state.dynamicGlobalProperties).reverse())
} catch (error) {
actions.error.set(error.message)
}
},
When we receive the data, we will save the data in our application state by dispatching the setAccountHistory
action. We also call the setDelegationHistory
to trigger the second step: filtering the historical account data.
Assembling The Delegation History
Here is the code to build the delegation history:
const assembleDelegationHistory = (accountHistory, dynamicGlobalProperties) => {
let currentDelegations = {}
let delegationHistory = accountHistory.reduce((result, item) => {
const transactionType = item[1].op[0]
let record = item[1].op[1]
let key
switch (transactionType) {
case TRANSACTION_TYPES.DELEGATE_VESTING_SHARES:
key = `${record.delegator}_${record.delegatee}`
currentDelegations[key] = record.vesting_shares
result.push({
type: 'DELEGATION',
from: record.delegator,
to: record.delegatee,
delegatedSteemPower: vests2Steem(record.vesting_shares, dynamicGlobalProperties),
amount: 'n/a',
timestamp: item[1].timestamp
})
break;
case TRANSACTION_TYPES.TRANSFER:
key = `${record.to}_${record.from}`
if (currentDelegations[key]) {
let currentDelegation = vests2Steem(currentDelegations[key], dynamicGlobalProperties)
result.push({
type: 'TRANSFER',
from: record.from,
to: record.to,
delegatedSteemPower: currentDelegation,
amount: record.amount,
timestamp: item[1].timestamp
})
}
// else {
// No delegation found in currentDelegations object.
// This means we need to go back furhter in the account history to find the delegation for this transfer.
// We do nothing here, which means we ignore transfers we have no delegation for.
// }
break;
default:
// Do nothing. Ignore item.
}
return result
}, [])
return delegationHistory
}
It is not the most elegant code, but it gets the job done.
We use a reducer to walk through the complete account history and build a new array called delegationHistory
. The reducer will only add data to the delegation history when the transaction in the account history is a delegation or if it is a transfer from an account we delegated to.
We keep track of our current delegations in the currentDelegation
object by using a key we build ourselves by concatenation the delegator and delegatee information. We do the same for a transfer record by concatenating the to and from fields.
Here is an example from my account history:
I made a delegation to @jerrybanfield for 1100 Steem Power. So our code will calculate a key of cutemachine_jerrybanfield
and keep track of the delegated SP in currentDelegation
. We will not store the SP but the vesting shares. We can convert between vesting shares and SP by using the function vests2Steem
we wrote in the first part of the tutorial.
We can store delegation records like the following in our delegation history.
DELEGATION cutemachine jerrybanfield 1100.629608 n/a n/a 2018-02-21T20:21:36
Now, when we receive a transfer from @jerrybanfield to @cutemachine, we can look up the vesting shares (SP) in our currentDelegation
object by using the key cutemachine_jerrybanfield (to_from). With this data we can build records like these to store in our delegation history.
TRANSFER jerrybanfield cutemachine 1100.629608 0.736 SBD 24.41 2018-02-22T02:06:09
TRANSFER jerrybanfield cutemachine 1100.629608 0.162 STEEM 5.37 2018-02-22T02:06:06
The only step left to do is to display the data in our web application.
Showing Delegation History
The changes to show the delegation history can be found in src/views/HomeView.js
.
First, we build an array of items by using map
on the delegationHistory
state.
let delegationHistoryItems = state.delegationHistory.map((item, index) => {
let APR = (item.type === 'DELEGATION')
? 'n/a'
: (unitString2Number(item.amount) / item.delegatedSteemPower * 100 * 365).toFixed(2)
return (
<tr>
<td>{item.type}</td>
<td>{item.from}</td>
<td>{item.to}</td>
<td>{item.delegatedSteemPower}</td>
<td>{item.amount}</td>
<td>{APR}</td>
<td>{item.timestamp}</td>
</tr>
)
})
Then we add a section with a table showing the items we just calculated:
<div class='container'>
<h2 class='title'>Delegation History</h2>
<table class='table is-hoverable is-fullwidth'>
<thead>
<tr>
<th>Type</th>
<th>From</th>
<th>To</th>
<th>Delegated SP</th>
<th>Amount</th>
<th>APR</th>
<th>Timestamp</th>
</tr>
</thead>
<tbody>
{ delegationHistoryItems }
</tbody>
</table>
</div>
That's all :)
Room For Improvement
There are three problems with the above approach.
The first is that we do not have historical data for the dynamic global properties. This missing data will result in inaccurate conversions between vesting shares (VESTS) and SP. To get around this, you will need to build a dedicated database. If you know where one can get historical data for the dynamic global properties, please leave a comment.
The second problem is that we receive transfers not only in Steem but also in SBD. At the moment there is not much difference between the two currencies, but to have precise calculations you will need to convert SBD to Steem with historical data from an exchange.
The third issue is that our code makes the assumption that payouts are on a daily basis. Which is not always the case. For example, if you delegate to smartsteem you will receive weekly transfers. Our program will show a wrong APR for such transfers.
Still, the data we display in our app is pretty useful. Well, at least to me :)
Conclusion
You have to jump through a lot of hoops to get the data you need from the Steem blockchain. But most of it can be achieved without the need for a dedicated database.
In the third part of this tutorial series, I will share with you how you can make a form and delegate your Steem Power to another user.
Stay tuned and stay awesome,
Jo
Posted on Utopian.io - Rewarding Open Source Contributors
Why does it say I am not receiving any rewards?
It looks like you made another delegation this morning setting the delegated SP to 0:
I do not see any transfers in the history.
Can you be more concise in your question, please? Do you mean there should be any displayed in the history because you received transfers? Or, are you asking why you did not receive anything from @yoitsme?
I was asking the reason I wasn't showing any ROI on the delegation... ?
@cutemachine
Well, because it is just the delegation and not a transfer back to your account. The estimated APR is shown for transfers only. The APR is calculated based on the amount you received.
There is no APR I can show on delegations. That's why you see the n/a (not applicable).
Does this answer your question?
Yes it does and thank you @cutemachine
Great, you are welcome.
Would you happen to know why these say "not computed" ?
"2016-08-25 17:17:08","SBD","0.05","BTS","6.34059","melchezedek-776","Input memo: e093e8fd-e118-4434-9294-35acbd8aaf48","76e819486bc0cdb85199c3161dde897f22c4b8db","output_transaction_broadcast","Not computed","71a20b77b85100857bff7e1c399e0c0d6a48d534",null
Can you provide more context? Where do you see it? Whats the API call?
@cutemachine, Upvote for supporting you.
nice post. good info