Steem Delegations Tutorial Part One

in #utopian-io6 years ago (edited)

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 is part one of a tutorial series about Steem delegations. There will be three parts in total.

Steem Delegations App

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

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

Requirements

Knowledge of JavaScript is sufficient to go through this tutorial.

Difficulty

Intermediate

Steem Delegation Tutorial One

In this tutorial, you will learn how you can retrieve a user’s delegations. You can use my handle to see some data if you do not have made any delegations to another user yet. My user handle is @cutemachine.

The web application we will build in this tutorial is quite simple. There is just one input field where one can enter a Steemit user.
The application will then get the information from the blockchain and present it to the user in a table.

You can see the running application we will build in this tutorial by following this link.

Technologies Used

Getting Started

You can find the code for this tutorial on GitHub. You should clone the project to make it easier for yourself to follow along. I will not explain every line of code, but will instead give you a rundown of the most critical parts.

When you have cloned the project, you should install the dependencies with yarn. When the installation has finished, you can run the new app with yarn start. These are the steps in more detail:

git clone https://github.com/cutemachine/steem-delegations.git
cd steem-delegations
yarn
yarn start

When the dev server is running, then you can point your browser to the URL given in the Terminal. Normally this is localhost:1234.

Application Control Flow

The important files in the repository are:

  • src/views/HomeView.js
  • src/state/index.js
  • src/actions/index.js
  • src/common/utils.js

The files index.html, index.js, src/view/MainView.js are needed to bootstrap the application. All you need to know is that at the end of this bootstrap process stands the rendering of the home view. You can see the home view when you start the application in your browser. It has the input field where you can enter the Steem username and request the Steem delegation data by clicking the Request Delegations button.

In HomeView.js is the code to render the HTML input field:

<input
  onkeyup={
    event => {
      (event.keyCode === 13) ? actions.submitUsername() : actions.changeUsername(event.target.value)
    }
  }
  class="input"
  type="text"
  placeholder="username …"
  autofocus
/>



You can see that when a user enters a key into the input field, the action changeUsername will be called. You can find this action in src/actions/index.js. Here are the two actions used by the input field:

  changeUsername: (value) => (state, actions) => {
    return { username: value }
  },
  submitUsername: () => (state, actions) => {
    actions.requestDelegations(state.username)
  },



In HyperApp all changes in application state will be done through actions. These actions take the user’s input and will lead to state changes or new actions being called. You can see that changeUsername takes a value, the value from the input field, and returns an object { username: value }. This action will update the state in src/state/index.js. Here is the complete state tree of our application:

{
  location: location.state,
  isNavbarMenuActive: false,
  username: '',
  delegations: [],
  dynamicGlobalProperties: {},
}



You can ignore the location state. It is only used by the HyperApp router. Also ignore isNavbarMenuActive. It handles the menu in the Navbar.

The username will be stored in username as a string. And the delegations will hold the array of delegations we get back from the steem-js lib by calling the requestDelegations action. The last state is called dynamicGlobalProperties and is an object. This state-piece will be filled by a call to the steem-js lib as well.

The submitUsername action will not change the state tree directly but will trigger the action requestDelegations.

When the user has entered her username and has submitted the field by pressing return or by clicking the button, the requestDelegations action will be invoked.

…
  setDynamicGlobalProperties: obj => state => ({ dynamicGlobalProperties: obj }),
  setDelegations: arr => state => ({ delegations: arr }),
  requestDelegations: (username) => async (state, actions) => {
    try {
      const [delegations, dynamicGlobalProperties] = await Promise.all([
        steem.api.getVestingDelegationsAsync(username, -1, 100),
        steem.api.getDynamicGlobalPropertiesAsync()
      ])
      if (!delegations) { throw new Error('Sorry, could not get delegations for user.')}
      if (!dynamicGlobalProperties) { throw new Error('Sorry, could not get dynamic global properties.')}
      actions.setDelegations(delegations)
      console.log('Vesting Delegations', delegations)
      actions.setDynamicGlobalProperties(dynamicGlobalProperties)
      console.log('Dynamic Global Properties', dynamicGlobalProperties)
    } catch (error) {
      actions.error.set(error.message)
    }
  },
…



Now, this is where the rubber hits the road. I think especially this part needs a little explanation:

      const [delegations, dynamicGlobalProperties] = await Promise.all([
        steem.api.getVestingDelegationsAsync(username, -1, 100),
        steem.api.getDynamicGlobalPropertiesAsync()
      ])



Here we make two calls to the steem-js library. We do not want to block the user interface. Therefore we call the API asynchronously. We use the new async / await syntax. Because we can make the two calls in parallel, we use Promise.all and provide an array of the two API calls. When the Promise will resolve we will get back an array which we destructure with const [delegations, dynamicGlobalProperties] =.

When all goes well, we will have an array with the delegation information in the delegations variable and an object with the dynamic global properties in the dynamicGlobalProperties variable.

Let’s have a look at some example data you might get back from the Steem blockchain.

Data Structure returned by the async call to the Steem API steem.api.getVestingDelegationsAsync(username, -1, 100):

    [{
      delegatee: "jerrybanfield”,
      delegator: "cutemachine”,
      id: 620276,
      min_delegation_time: "2018-02-05T16:44:21”,
      vesting_shares: "2248194.554501 VESTS"
    }]



As you can see, the delegation amount is given in VESTS. You might have expected to see STEEM or Steem Power here as the unit. But we have to convert VESTS to SP ourselves. To convert VESTS to SP, we will use the two functions in src/common/utils.js.

export const unitString2Number = (stringWithUnit) => Number(stringWithUnit.split(' ')[0])

export const vests2Steem = (vestingShares, dynamicGlobalProperties) => {
  const { total_vesting_fund_steem, total_vesting_shares } = dynamicGlobalProperties
  const totalVestingFundSteemNumber = unitString2Number(total_vesting_fund_steem)
  const totalVestingSharesNumber = unitString2Number(total_vesting_shares)
  const vestingSharesNumber = unitString2Number(vestingShares)

  return (totalVestingFundSteemNumber * (vestingSharesNumber / totalVestingSharesNumber)).toFixed(6)
}



unitString2Number() can be used to convert the vesting_shares to a JavaScript Number. It will be used in vests2Steem. vests2Steem will be used to convert VESTS to SP. Here we need to make use of the dynamic global properties. To calculate the conversion properly, we need to know the total_vesting_fund_steem and total_vesting_shares.

Data structure returned by the async call to the Steem API steem.api.getDynamicGlobalPropertiesAsync():

    {
      average_block_size: 17395,
      confidential_sbd_supply: "0.000 SBD",
      confidential_supply: "0.000 STEEM",
      current_aslot: 20215178,
      current_reserve_ratio: 15036532,
      current_sbd_supply: "9571439.677 SBD",
      current_supply: "264562933.899 STEEM",
      current_witness: "blocktrades",
      head_block_id: "01337ebdd28d40cb21bb1b6772794047a9737647",
      head_block_number: 20151997,
      id: 0,
      last_irreversible_block_num: 20151982,
      max_virtual_bandwidth: "19866352688824320000",
      maximum_block_size: 65536,
      num_pow_witnesses: 172,
      participation_count: 128,
      pending_rewarded_vesting_shares: "312264752.226184 VESTS",
      pending_rewarded_vesting_steem: "151881.086 STEEM",
      recent_slots_filled: "340282366920938463463374607431768211455",
      sbd_interest_rate: 0,
      sbd_print_rate: 10000,
      time: "2018-02-24T13:58:54",
      total_pow: 514415,
      total_reward_fund_steem: "0.000 STEEM",
      total_reward_shares2: "0",
      total_vesting_fund_steem: "186284011.937 STEEM",
      total_vesting_shares: "380674659866.674495 VESTS",
      virtual_supply: "267334853.874 STEEM",
      vote_power_reserve_rate: 10
    }



Good. Now we have all the pieces we need to render the result table. The rendering is done in the HomeView.js file.

let delegationItems = state.delegations.map((item, index) => {
  return (
    <tr>
        <td>{item.delegator}</td>
        <td>{item.delegatee}</td>
        <td>{unitString2Number(item.vesting_shares)} VESTS</td>
        <td>{vests2Steem(item.vesting_shares, state.dynamicGlobalProperties)} SP</td>
        <td>{item.min_delegation_time}</td>
    </tr>
  )
})



As you can see, we take the delegations from our state tree and iterate over it with map. The call to map will return a new array with all the delegations the user in question has made. You can also see how we call our vests2Steem utility function to convert the VESTS to SP.

Easy wasn’t it.

Conclusion

It is not too complicated to retrieve a user’s delegation from the blockchain. But you need to know where to get all the pieces to the puzzle you want to solve.

In the next part, we will see how we can retrieve all the rewards a user received for her delegations, which will be even trickier.

Stay awesome,
Jo



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  

Thank you for the contribution. It has been approved.

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

Hey @amosbastian, I just gave you a tip for your hard work on moderation. Upvote this comment to support the utopian moderators and increase your future rewards!

Thanks a lot, Amos.

Thank you VERY much for this information and tutorial! I appreciate it immensely! I am still learning many things on the GREAT STEEMIT platform! It is truly the Caring Social Network! I truly appreciate posts like these! Thanks Again! Your Friend @extraterrestrial :)

Many thanks for your kind words @extraterrestrial. I loved E.T. as a kid :)

It is good to hear that you appreciate my posts. Feedback like yours keep me motivated to write more.

Slightly OT. There's something I've been wondering about Utopian. When you create a post with Utopian, it uses comment_options to add itself as a beneficiary with 25% payout.

When a whale comes along and votes like postpromoter, does Utopian end up getting 25% of that?

Hmm, good question. To be honest, I do not know, but I think so. Will have to dig into it.
@sambillingham, by any chance, do you have a prompt answer​?


Update 3rd of March:

Here is a screenshot of the pending payout for this post:

PostPayout.png

And the actual payout per my wallet was:

Your current rewards: 19.049 SBD and 5.962 SP

If you do the math for the SBD only:

33.89 * 0.75 = 25.42 = Author payout after curation rewards
25.42 * 0.75 = 19.07 = Actual payout I received. 25% goes to Utopian

So, it seems that Utopian is getting a share of the postpromoter vote. Interesting.

Would be great if anybody could confirm this calculation.

@r351574nc3, hope this helps.

Yeah. I think that clenches it. I'm not buying votes for my utopian posts. LOL

:) Buying votes for your Utopian posts is a bad investment financially. I know, because I spent 23 SBD on upvote bots for this post. So all the reward went to curators, bots, and Utopian. That makes me a good Steemit citizen LOL

I would like to thank you for your question. It did not come to my attention that buying votes for Utopian posts is a bad idea. I used upvote bots before and it was always a good investment, as you make a little more money, your reputation increases, and most importantly you get more readers to your posts.

Also, I think #dlive, #dtube, and #busy are doing similar. Which is weird to me because some voting bots have stopped selling votes for these, but in retrospect that's having the opposite to the desired effect. Hehe

Hey @cutemachine 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!

Suggestions

  • Contribute more often to get higher and higher rewards. I wish to see you often!
  • Work on your followers to increase the votes/rewards. I follow what humans do and my vote is mainly based on that. Good luck!

Get Noticed!

  • Did you know project owners can manually vote with their own voting power or by voting power delegated to their projects? Ask the project owner to review your contributions!

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

You just rose by 64.5995% upvote from @therising courtesy of @cutemachine. Earn 43.8% APR by delegating SP to therising. For more details visit: https://steemit.com/budget/@therising/auto-daily-payout-of-43-8-apr-for-steem-power-delegations-starting-from-500-sp-only-limited-period-offer.

You got a 3.30% upvote from @postpromoter courtesy of @cutemachine!

Want to promote your posts too? Check out the Steem Bot Tracker website for more info. If you would like to support the development of @postpromoter and the bot tracker please vote for @yabapmatt for witness!

You got a 2.31% upvote from @buildawhale courtesy of @cutemachine!
If you believe this post is spam or abuse, please report it to our Discord #abuse channel.

If you want to support our Curation Digest or our Spam & Abuse prevention efforts, please vote @themarkymark as witness.

You got a 41.62% upvote from @bid4joy courtesy of @cutemachine!

You got a 31.25% upvote from @luckyvotes courtesy of @cutemachine!

Coin Marketplace

STEEM 0.20
TRX 0.13
JST 0.030
BTC 63974.07
ETH 3426.40
USDT 1.00
SBD 2.54