class Hive::Api

This ruby API works with {github.com/openhive-network/hive/releases hived-0.23.00} and other AppBase compatible upstreams. To access different API namespaces, use the following:

api = Hive::Api.new
api.get_dynamic_global_properties

The above example will make an instance that can access the {developers.hive.io/apidefinitions/condenser-api.html condenser_api} namespace. Alternatively, you may also create a direct instances with its full name, if you prefer:

api = Hive::CondenserApi.new
api.get_dynamic_global_properties

If you know the name of another API that is supported by the remote node, you can create an instance to that instead, for example:

api = Hive::MarketHistoryApi.new
api.get_volume

All known API by namespace:

Also see: {developers.hive.io/apidefinitions/ Complete API Definitions}

Constants

DEFAULT_RPC_CLIENT_CLASS

Use this for debugging naive thread handler. DEFAULT_RPC_CLIENT_CLASS = RPC::HttpClient

jsonrpc

Note, we have to wait until initialize to check this because we don't have access to instance options until now.

Attributes

chain[RW]
methods[RW]
rpc_client[RW]

Public Class Methods

api_class_name() click to toggle source
# File lib/hive/api.rb, line 56
def self.api_class_name
  @api_name.to_s.split('_').map(&:capitalize).join
end
api_name() click to toggle source
# File lib/hive/api.rb, line 52
def self.api_name
  @api_name
end
api_name=(api_name) click to toggle source
# File lib/hive/api.rb, line 45
def self.api_name=(api_name)
  @api_name = api_name.to_s.
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr('-', '_').downcase.to_sym
end
default_rpc_client_class() click to toggle source

Override this if you want to just use your own client. Otherwise, inject the default using:

Hive::Api.register default_rpc_client_class: MyClient
# File lib/hive/api.rb, line 77
def self.default_rpc_client_class
  if !!@injected_dependencies && !!@injected_dependencies[:default_rpc_client_class]
    @injected_dependencies[:default_rpc_client_class]
  else
    DEFAULT_RPC_CLIENT_CLASS
  end
end
jsonrpc(url = nil) click to toggle source
# File lib/hive/api.rb, line 65
def self.jsonrpc(url = nil)
  if @jsonrpc.size < 2 && url.nil?
    @jsonrpc.values.first
  else
    @jsonrpc[url]
  end
end
jsonrpc=(jsonrpc, url = nil) click to toggle source
# File lib/hive/api.rb, line 60
def self.jsonrpc=(jsonrpc, url = nil)
  @jsonrpc ||= {}
  @jsonrpc[url || jsonrpc.rpc_client.uri.to_s] = jsonrpc
end
new(options = {}) click to toggle source
# File lib/hive/api.rb, line 93
def initialize(options = {})
  @chain = options[:chain] || :hive
  @error_pipe = options[:error_pipe] || STDERR
  @api_name = self.class.api_name ||= :condenser_api
  
  @rpc_client = if !!options[:rpc_client]
    options[:rpc_client]
  else
    rpc_client_class = self.class.default_rpc_client_class
    rpc_client_class.new(options.merge(api_name: @api_name))
  end
  
  if @api_name == :jsonrpc
    Api::jsonrpc = self
  else
    # Note, we have to wait until initialize to check this because we don't
    # have access to instance options until now.
    
    Api::jsonrpc = Jsonrpc.new(options)
    
    @methods = begin
      Api::jsonrpc(rpc_client.uri.to_s).get_api_methods
    rescue => e
      Fallback::API_METHODS
    end
    
    if Jsonrpc::UNLISTED_APIS.include? @api_name
      @methods ||= {}
      @methods[@api_name] ||= []
      @methods[@api_name] += Fallback::API_METHODS[@api_name]
      @methods[@api_name] = @methods[@api_name].uniq
    end
    
    unless !!@methods[@api_name]
      raise UnknownApiError, "#{@api_name} (known APIs: #{@methods.keys.join(' ')})"
    end
    
    @methods = @methods[@api_name]
  end
    
  @try_count = 0
end
register(register) click to toggle source

Used for dependency injection. Currently, the only key supported is:

`default_rpc_client_class`

# File lib/hive/api.rb, line 88
def self.register(register)
  @injected_dependencies ||= {}
  @injected_dependencies = @injected_dependencies.merge register
end

Public Instance Methods

inspect() click to toggle source
# File lib/hive/api.rb, line 136
def inspect
  properties = %w(chain methods).map do |prop|
    if !!(v = instance_variable_get("@#{prop}"))
      case v
      when Array then "@#{prop}=<#{v.size} #{v.size == 1 ? 'element' : 'elements'}>" 
      else; "@#{prop}=#{v}" 
      end
    end
  end.compact.join(', ')
  
  "#<#{self.class.api_class_name} [#{properties}]>"
end

Private Instance Methods

args_keys_to_s(rpc_method_name) click to toggle source

@private

# File lib/hive/api.rb, line 150
def args_keys_to_s(rpc_method_name)
  args = signature(rpc_method_name).args
  args_keys = JSON[args.to_json]
end
method_missing(m, *args) { |result, error, id| ... } click to toggle source

@private

Calls superclass method
# File lib/hive/api.rb, line 175
def method_missing(m, *args, &block)
  super unless respond_to_missing?(m)
  
  rpc_method_name = "#{@api_name}.#{m}"
  rpc_args = case @api_name
  when :condenser_api then args
  when :jsonrpc then args.first
  else
    expected_args = signature(rpc_method_name).args || []
    expected_args_key_string = if expected_args.size > 0
      " (#{args_keys_to_s(rpc_method_name)})"
    end
    expected_args_size = expected_args.size
    
    begin
      args = args.first.to_h
      args_size = args.size
      
      # Some argument are optional, but if the arguments passed are greater
      # than the expected arguments size, we can warn.
      if args_size > expected_args_size
        if rpc_method_name == 'account_history_api.get_account_history' && expected_args_size == 3 && args_size == 6
          # TODO Remove this condition if they ever fix this issue:
          # https://gitlab.syncad.com/hive/hive/-/issues/100
        elsif rpc_method_name == 'account_history_api.get_ops_in_block' && expected_args_size == 2 && args_size == 3
          # TODO Remove this condition if they ever fix this issue:
          # https://gitlab.syncad.com/hive/hive/-/issues/100
        elsif rpc_method_name == 'account_history_api.enum_virtual_ops' && expected_args_size == 2 && args_size == 3
          # TODO Remove this condition if they ever fix this issue:
          # https://gitlab.syncad.com/hive/hive/-/issues/100
        else
          @error_pipe.puts "Warning #{rpc_method_name} expects arguments: #{expected_args_size}, got: #{args_size}"
        end
      end
    rescue NoMethodError => e
      error = Hive::ArgumentError.new("#{rpc_method_name} expects arguments: #{expected_args_size}", e)
      raise error
    rescue => e
      raise UnknownError.new("#{rpc_method_name} unknown error.", e)
    end
    
    args
  end
  
  response = rpc_client.rpc_execute(@api_name, m, rpc_args)
  
  if !!block
    case response
    when Hashie::Mash then yield response.result, response.error, response.id
    when Hashie::Array
      response.each do |r|
        r = Hashie::Mash.new(r)
        yield r.result, r.error, r.id
      end
    else; yield response
    end
  else
    return response
  end
end
respond_to_missing?(m, include_private = false) click to toggle source

@private

# File lib/hive/api.rb, line 170
def respond_to_missing?(m, include_private = false)
  methods.nil? ? false : methods.include?(m.to_sym)
end
signature(rpc_method_name) click to toggle source

@private

# File lib/hive/api.rb, line 156
def signature(rpc_method_name)
  url = rpc_client.uri.to_s
  
  @@signatures ||= {}
  @@signatures[url] ||= {}
  
  @@signatures[url][rpc_method_name] ||= begin
    Api::jsonrpc(url).get_signature(method: rpc_method_name).result
  rescue => e
    Hashie::Mash.new({args: Fallback::API_METHOD_SIGNATURES[@api_name][rpc_method_name.split('.').last.to_sym]})
  end
end