utopian-io tutorials ruby steem-api programming
- Project Name: Steem Ruby
- Repository: https://github.com/steemit/steem-ruby
- Project Name: Radiator
- Repository: https://github.com/inertia186/radiator
- Official Tutorial: https://developers.steem.io/tutorials-ruby/getting_started
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.
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.
Provided you have some programming experience this tutorial is basic level.
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.
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:
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:
![comment](https://steemitimages.com/50x60/http://steemitboard.com/@krischik/Comments.png) ![votes](http://steemitimages.com/60x70/http://steemitboard.com/@krischik/Votes.png) ![posts](http://steemitimages.com/70x80/http://steemitboard.com/@krischik/Posts.png) ![level](http://steemitimages.com/100x80/http://steemitboard.com/@krischik/Level.png) ![payout](http://steemitimages.com/70x80/http://steemitboard.com/@krischik/Payout.png) ![commented](http://steemitimages.com/60x70/http://steemitboard.com/@krischik/Commented.png) ![voted](https://steemitimages.com/50x60/http://steemitboard.com/@krischik/voted.png)