Using Steem-API with Ruby Part 2 — Print Account Balances
Repository
steem-ruby
- Project Name: Steem Ruby
- Repository: https://github.com/steemit/steem-ruby
radiator
- Project Name: Radiator
- Repository: https://github.com/inertia186/radiator
- Official Tutorial: https://developers.steem.io/tutorials-ruby/getting_started
What Will I Learn?
This tutorial shows how to interact with the Steem blockchain and Steem database using Ruby. When using Ruby you have two APIs available to chose: steem-api and radiator which differentiates in how return values and errors are handled:
- steem-api uses closures and exceptions and provides low level computer readable data.
- radiator uses classic function return values and provides high level human readable data.
Since both APIs have advantages and disadvantages I have provided sample code for both APIs so you can decide which is more suitable for you.
In this 2nd part you learn the use of the classes Steem::Type::Amount
and Radiator::Type::Amount
and how to handle account balances using them.
Requirements
You should have basic knowledge of Ruby programming you need to install at least Ruby 2.5 as well as the following ruby gems:
gem install bundler
gem install colorize
gem install steem-ruby
gem install radiator
If there is anything not clear you can ask in the comments.
Note: Both steem-ruby and radiator provide a file called steem.rb
. This means that:
- When you install both APIs you need to tell ruby which one to use.
- You can't use both APIs in the same script.
Difficulty
Provided you have some programming experience this tutorial is basic level.
Tutorial Contents
In this second part of the tutorial I demonstrate how to print out account balances from a list of accounts passed on command line. The data will be formatted and a simple calculation is performed to show how you can use arithmetic on account balances.
As mentioned there will be two examples showing the differences. Both …::Amount
classes have there weaknesses which I compensate by introducing an extended Amount
class making the rest of the code identical.
You might notice that Steem Power is output in VESTS. In a future part I will show you how to convert VEST value into STEEM value.
Implementation using steem-ruby
Steem-ruby keeps balance data in low level structures which is rather cumbersome to use. Here an example:
"sbd_balance"=>{"amount"=>"8716549", "precision"=>3, "nai"=>"@@000000013"},
The constructor Steem::Type::Amount
class will parse the structure for you and make the data within more accessible and printable. Let's look in detail how to use Steem::Type::Amount
:
Make the script executable under Unix. Of course you need to add the correct path to your ruby executable.
#!/opt/local/bin/ruby
Use the "steem.rb" file from the steem-ruby gem. This is only needed if you have both steem-api and radiator installed.
gem "steem-ruby", :require => "steem"
require 'pp'
require 'colorize'
require 'steem'
Steem-ruby comes with a helpful Steem::Type::Amoun
class to handle account balances. However Steem::Type::Amoun
won't let you access the actual amount as float which is quite cumbersome when you want to make calculations.
This class expands Steem::Type::Amoun
to add the missing functions.
class Amount < Steem::Type::Amount
Return amount as float to be used for calculations
def to_f
return @amount.to_f
end # to_f
Operator to add two balances for the users convenience
def +(right)
return (if right.is_a?(Numeric) then
@amount.to_f + right
else
@amount.to_f + right.to_f
end)
end
Operator to subtract two balances for the users convenience
def -(right)
return (if right.is_a?(Numeric) then
@amount.to_f - right
else
@amount.to_f - right.to_f
end)
end
end # Amount
Print account information for an array of accounts
def print_account_balances (accounts)
accounts.each do |account|
Create an amount instances for each balance to be used for further processing
_balance = Amount.new account.balance
_savings_balance = Amount.new account.savings_balance
_sbd_balance = Amount.new account.sbd_balance
_savings_sbd_balance = Amount.new account.savings_sbd_balance
_vesting_shares = Amount.new account.vesting_shares
_delegated_vesting_shares = Amount.new account.delegated_vesting_shares
_received_vesting_shares = Amount.new account.received_vesting_shares
Calculate actual vesting by adding and subtracting delegation.
_actual_vesting = _vesting_shares - (_delegated_vesting_shares + _received_vesting_shares)
Pretty print out the balances. Note that for a quick printout Steem::Type::Amount provides a simple to_s method. But this method won't align the decimal point
puts ("Account: " + account.name).colorize(:blue)
puts " Steem = %1$15.3f %2$s" % [_balance.to_f, _balance.asset]
puts " Steem Savings = %1$15.3f %2$s" % [_savings_balance.to_f, _savings_balance.asset]
puts " SBD = %1$15.3f %2$s" % [_sbd_balance.to_f, _sbd_balance.asset]
puts " SBD Savings = %1$15.3f %2$s" % [_savings_sbd_balance.to_f, _savings_sbd_balance.asset]
puts " Steem Power = %1$18.6f %2$s" % [_vesting_shares.to_f, _vesting_shares.asset]
puts " Delegated Steem = %1$18.6f %2$s" % [_delegated_vesting_shares.to_f, _delegated_vesting_shares.asset]
puts " Received Steem = %1$18.6f %2$s" % [_received_vesting_shares.to_f, _received_vesting_shares.asset]
puts " Actual Power = %1$18.6f VESTS" % _actual_vesting
end
return
end # Print_Account_Balances
if ARGV.length == 0 then
puts """
Steem-Dump-Balances — Dump account balances.
Usage:
Steem-Dump-Balances account_name …
"""
else
Read arguments from command line
Account_Names = ARGV
Create instance to the steem database API
Database_Api = Steem::DatabaseApi.new
Request account information from the Steem database and print out the accounts balances found using a new function or print out error information when an error occurred.
Database_Api.find_accounts(accounts: Account_Names) do |result|
Accounts = result.accounts
if Accounts.length == 0 then
puts "No accounts found.".yellow
else
Print out the actual account balances.
print_account_balances Accounts
end
rescue => error
puts "Error reading accounts:".red
pp error
end
end
Hint: Follow this link on Github for the complete script with syntax highlighting: Steem-Dump-Balances.rb on GitHub.
The output of the command (for the steem account) looks like this:
Steem-Print-Accounts.rb using radiator
Radiator keeps the amount data inside a string which nice for printing but still cumbersome for any further processing:
"sbd_balance"=>"8716.549 SBD",
Luckily we don't need to parse the string ourself. The constructor Radiator::Type::Amount
class will do that for you and provides the same functionality then Radiator::Type::Amount
. Let's look in detail how to use Radiator::Type::Amount
:
Make the script executable under Unix. Of course you need to add the correct path to your ruby executable.
#!/opt/local/bin/ruby
use the "steem.rb" file from the radiator gem. This is only needed if you have both steem-api and radiator installed.
gem "radiator", :require => "steem"
require 'pp'
require 'colorize'
require 'radiator'
steem-ruby comes with a helpful Radiator::Type::Amount
class to handle account balances. However Radiator::Type::Amount
won't let you access any attributes which makes using the class quite cumbersome.
This class expands Radiator::Type::Amount
to add the missing functions making it super convenient.
class Amount < Radiator::Type::Amount
add the missing attribute reader.
attr_reader :amount, :precision, :asset, :value
return amount as float to be used for calculations
def to_f
return @amount.to_f
end # to_f
Operator to add two balances for the users convenience
def +(right)
return (if right.is_a?(Numeric) then
@amount.to_f + right
else
@amount.to_f + right.to_f
end)
end
Operator to subtract two balances for the users convenience
def -(right)
return (if right.is_a?(Numeric) then
@amount.to_f - right
else
@amount.to_f - right.to_f
end)
end
end # Amount
Print account information for an array of accounts
def print_account_balances (accounts)
accounts.each do |account|
Create an amount instances for each balance to be used for further processing
_balance = Amount.new account.balance
_savings_balance = Amount.new account.savings_balance
_sbd_balance = Amount.new account.sbd_balance
_savings_sbd_balance = Amount.new account.savings_sbd_balance
_vesting_shares = Amount.new account.vesting_shares
_delegated_vesting_shares = Amount.new account.delegated_vesting_shares
_received_vesting_shares = Amount.new account.received_vesting_shares
calculate actual vesting by adding and subtracting delegation.
_actual_vesting = _vesting_shares - (_delegated_vesting_shares + _received_vesting_shares)
Pretty print out the balances. Note that for a quick printout Radiator::Type::Amount provides a simple to_s
method. But this code will create a nicer output.
puts ("Account: " + account.name).colorize(:blue)
puts " Steem = %1$15.3f %2$s" % [_balance.to_f, _balance.asset]
puts " Steem Savings = %1$15.3f %2$s" % [_savings_balance.to_f, _savings_balance.asset]
puts " SBD = %1$15.3f %2$s" % [_sbd_balance.to_f, _sbd_balance.asset]
puts " SBD Savings = %1$15.3f %2$s" % [_savings_sbd_balance.to_f, _savings_sbd_balance.asset]
puts " Steem Power = %1$18.6f %2$s" % [_vesting_shares.to_f, _vesting_shares.asset]
puts " Delegated Steem = %1$18.6f %2$s" % [_delegated_vesting_shares.to_f, _delegated_vesting_shares.asset]
puts " Received Steem = %1$18.6f %2$s" % [_received_vesting_shares.to_f, _received_vesting_shares.asset]
puts " Actual Power = %1$18.6f VESTS" % _actual_vesting
end
return
end # Print_Account_Balances
if ARGV.length == 0 then
puts """
Steem-Print-Balances — Print account balances.
Usage:
Steem-Print-Balances account_name …
"""
else
Read arguments from command line
Account_Names = ARGV
Create instance to the steem database API
Database_Api = Radiator::DatabaseApi.new
Request account information from the Steem database and print out the accounts balances found using a new function or print out error information when an error occurred.
Result = Database_Api.get_accounts(Account_Names)
if Result.key?('error') then
puts "Error reading accounts:".red
pp Result.error
elsif Result.result.length == 0 then
puts "No accounts found.".yellow
else
print_account_balances Result.result
end
end
Hint: Follow this link to Github for the complete script with syntax highlighting: Steem-Print-Balances.rb on GitHub.
The output of the command (for the steem account) look identical to the previous output:
Thank you for your contribution.
Looking forward to future work of yours.
Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.
To view those questions and the relevant answers related to your post, click here.
Need help? Chat with us on Discord.
[utopian-moderator]
That's precisely what I have planned for tutorial 3. 😉 — I don't want to put too much into one tutorial.
The explanations are currently all in the comments. But I could beak up the code into smaller snippets and use text blocks for explanations. And I still have a few days to edit and improve.
I missed that one. Luckily there is no overlap yet. I'll make sure it stays that way. Also I try to make fully working examples with error handling.
Thank you for your review, @mcfarhat! Keep up the good work!
Hi @krischik!
Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server
Hi, @krischik!
You just got a 0.09% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.
Hey, @krischik!
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!
Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!