Class: Steem::RPC::BaseClient

Inherits:
Object
  • Object
show all
Includes:
ChainConfig
Defined in:
lib/steem/rpc/base_client.rb

Direct Known Subclasses

ThreadSafeClient

Constant Summary collapse

POST_HEADERS =
{
  'Content-Type' => 'application/json; charset=utf-8',
  'User-Agent' => Steem::AGENT_ID
}

Constants included from ChainConfig

ChainConfig::EXPIRE_IN_SECS, ChainConfig::EXPIRE_IN_SECS_PROPOSAL, ChainConfig::NETWORKS_STEEM_ADDRESS_PREFIX, ChainConfig::NETWORKS_STEEM_CHAIN_ID, ChainConfig::NETWORKS_STEEM_CORE_ASSET, ChainConfig::NETWORKS_STEEM_DEBT_ASSET, ChainConfig::NETWORKS_STEEM_DEFAULT_NODE, ChainConfig::NETWORKS_STEEM_VEST_ASSET, ChainConfig::NETWORKS_TEST_ADDRESS_PREFIX, ChainConfig::NETWORKS_TEST_CHAIN_ID, ChainConfig::NETWORKS_TEST_CORE_ASSET, ChainConfig::NETWORKS_TEST_DEBT_ASSET, ChainConfig::NETWORKS_TEST_DEFAULT_NODE, ChainConfig::NETWORKS_TEST_VEST_ASSET, ChainConfig::NETWORK_CHAIN_IDS

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ BaseClient

Returns a new instance of BaseClient.



14
15
16
17
18
19
20
21
22
23
# File 'lib/steem/rpc/base_client.rb', line 14

def initialize(options = {})
  @chain = options[:chain] || :steem
  @error_pipe = options[:error_pipe] || STDERR
  @api_name = options[:api_name]
  @url = case @chain
  when :steem then options[:url] || NETWORKS_STEEM_DEFAULT_NODE
  when :test then options[:url] || NETWORKS_TEST_DEFAULT_NODE
  else; raise UnsupportedChainError, "Unsupported chain: #{@chain}"
  end
end

Instance Attribute Details

#chainObject

Returns the value of attribute chain.



6
7
8
# File 'lib/steem/rpc/base_client.rb', line 6

def chain
  @chain
end

#error_pipeObject

Returns the value of attribute error_pipe.



6
7
8
# File 'lib/steem/rpc/base_client.rb', line 6

def error_pipe
  @error_pipe
end

Instance Method Details

#evaluate_id(options = {}) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/steem/rpc/base_client.rb', line 61

def evaluate_id(options = {})
  debug = options[:debug] || ENV['DEBUG'] == 'true'
  request = options[:request]
  response = options[:response]
  api_method = options[:api_method]
  req_id = request[:id].to_i
  res_id = !!response['id'] ? response['id'].to_i : nil
  method = [@api_name, api_method].join('.')
  
  if debug
    req = JSON.pretty_generate(request)
    res = JSON.parse(response) rescue response
    res = JSON.pretty_generate(response) rescue response
    
    error_pipe.puts '=' * 80
    error_pipe.puts "Request:"
    error_pipe.puts req
    error_pipe.puts '=' * 80
    error_pipe.puts "Response:"
    error_pipe.puts res
    error_pipe.puts '=' * 80
    error_pipe.puts Thread.current.backtrace.join("\n")
  end
  
  error = response['error'].to_json if !!response['error']
        
  if req_id != res_id
    raise IncorrectResponseIdError, "#{method}: The json-rpc id did not match.  Request was: #{req_id}, got: #{res_id.inspect}", error.nil? ? nil : error.to_json
  end
end

#httpObject



29
30
31
32
33
34
35
36
37
38
# File 'lib/steem/rpc/base_client.rb', line 29

def http
  @http ||= Net::HTTP.new(uri.host, uri.port).tap do |http|
    http.use_ssl = true
    http.keep_alive_timeout = 2 # seconds
    
    # WARNING This method opens a serious security hole. Never use this
    # method in production code.
    # http.set_debug_output(STDOUT) if !!ENV['DEBUG']
  end
end

#http_postObject



40
41
42
# File 'lib/steem/rpc/base_client.rb', line 40

def http_post
  @http_post ||= Net::HTTP::Post.new(uri.request_uri, POST_HEADERS)
end

#http_request(request) ⇒ Object



92
93
94
# File 'lib/steem/rpc/base_client.rb', line 92

def http_request(request)
  http.request(request)
end

#put(api_name = @api_name, api_method = nil, options = {}) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/steem/rpc/base_client.rb', line 44

def put(api_name = @api_name, api_method = nil, options = {})
  current_rpc_id = rpc_id
  rpc_method_name = "#{api_name}.#{api_method}"
  options ||= {}
  request_body = defined?(options.delete) ? options.delete(:request_body) : []
  request_body ||= []
  
  request_body << {
    jsonrpc: '2.0',
    id: current_rpc_id,
    method: rpc_method_name,
    params: options
  }
  
  request_body
end

#rpc_idObject



148
149
150
151
# File 'lib/steem/rpc/base_client.rb', line 148

def rpc_id
  @rpc_id ||= 0
  @rpc_id += 1
end

#rpc_post(api_name = @api_name, api_method = nil, options = {}, &block) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/steem/rpc/base_client.rb', line 96

def rpc_post(api_name = @api_name, api_method = nil, options = {}, &block)
  request = http_post
  
  request_body = if !!api_name && !!api_method
    put(api_name, api_method, options)
  elsif !!options && defined?(options.delete)
    options.delete(:request_body)
  end
  
  request.body = if request_body.size == 1
    request_body.first.to_json
  else
    request_body.to_json
  end
  
  response = http_request(request)
  
  case response.code
  when '200'
    response = JSON[response.body]
    response = case response
    when Hash
      Hashie::Mash.new(response).tap do |r|
        evaluate_id(request: request_body.first, response: r, api_method: api_method)
      end
    when Array
      Hashie::Array.new(response).tap do |r|
        request_body.each_with_index do |req, index|
          evaluate_id(request: req, response: r[index], api_method: api_method)
        end
      end
    else; response
    end
    
    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
  else
    raise UnknownError, "#{api_name}.#{api_method}: #{response.body}"
  end
end

#uriObject



25
26
27
# File 'lib/steem/rpc/base_client.rb', line 25

def uri
  @uri ||= URI.parse(@url)
end