radiator 0.3.0dev2 → 0.3.0dev3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e876d3ec41bf655bc3bfc4494f22d862b71f4442
4
- data.tar.gz: 65bec4acf06c108bd56ca239c9cdb660332c91a9
3
+ metadata.gz: 768d130d67520d82f31a14a1ce99236e5b17688b
4
+ data.tar.gz: 6da4c36f9d54a3de922ac26ec4ed8f70aee0def1
5
5
  SHA512:
6
- metadata.gz: 9e1f48eb220ecd006335906909f88e493f7d806a4147e5443f1f9b8663c0ea941d6239bb1a610180414c514e85e9c1b084309d21cc698d0f20e730f9e292f546
7
- data.tar.gz: 5e8c2376494c49046e0f18ef34b7a0e235e8230bbc5acbf76515adbced6e17de80942cdfb1214340e41c2ccecf9c4f85684b959fc00f99e65ae787b5afeb7bc0
6
+ metadata.gz: 2c8507502286b7d4f07c6705bbbd8fdd0bfc04d5a6187747b1573a9714bcdf58ecf5dcb12e615fa2eb3218ef91a1b934470c70c0da742f0fdb6fdb448697a12f
7
+ data.tar.gz: 86d7090a11dbd508db65305bccf71d3c6c1533a962cbdc66c8b4c9b42105470341274d81010fd8aed902e43085fbae3fa7f06fbd9561cfd6800c9f986a39975c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- radiator (0.3.0dev2)
4
+ radiator (0.3.0dev3)
5
5
  bitcoin-ruby (= 0.0.11)
6
6
  ffi (= 1.9.18)
7
7
  hashie (~> 3.5, >= 3.5.5)
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  [![Build Status](https://travis-ci.org/inertia186/radiator.svg?branch=master)](https://travis-ci.org/inertia186/radiator)
2
2
  [![Code Climate](https://codeclimate.com/github/inertia186/radiator/badges/gpa.svg)](https://codeclimate.com/github/inertia186/radiator)
3
3
  [![Test Coverage](https://codeclimate.com/github/inertia186/radiator/badges/coverage.svg)](https://codeclimate.com/github/inertia186/radiator)
4
+ [![Inline docs](http://inch-ci.org/github/inertia186/radiator.svg?branch=master&style=shields)](http://inch-ci.org/github/inertia186/radiator)
4
5
 
5
6
  [radiator](https://github.com/inertia186/radiator)
6
7
  ========
@@ -29,6 +30,10 @@ Radiator is an API Client for interaction with the STEEM network using Ruby.
29
30
 
30
31
  ---
31
32
 
33
+ Also see: [Documentation](http://www.rubydoc.info/gems/radiator)
34
+
35
+ ---
36
+
32
37
  ### Quick Start
33
38
 
34
39
  Add the gem to your Gemfile:
data/lib/radiator/api.rb CHANGED
@@ -6,6 +6,130 @@ require 'openssl'
6
6
  require 'net/http/persistent'
7
7
 
8
8
  module Radiator
9
+ # Radiator::Api allows you to call remote methods to interact with the STEEM
10
+ # blockchain. The `Api` class is a shortened name for
11
+ # `Radiator::DatabaseApi`.
12
+ #
13
+ # Examples:
14
+ #
15
+ # api = Radiator::Api.new
16
+ # response = api.get_dynamic_global_properties
17
+ # virtual_supply = response.result.virtual_supply
18
+ #
19
+ # ... or ...
20
+ #
21
+ # api = Radiator::Api.new
22
+ # virtual_supply = api.get_dynamic_global_properties do |prop|
23
+ # prop.virtual_supply
24
+ # end
25
+ #
26
+ # If you need access to the `error` property, they can be accessed as follows:
27
+ #
28
+ # api = Radiator::Api.new
29
+ # response = api.get_dynamic_global_properties
30
+ # if response.result.nil?
31
+ # puts response.error
32
+ # exit
33
+ # end
34
+ #
35
+ # virtual_supply = response.result.virtual_supply
36
+ #
37
+ # ... or ...
38
+ #
39
+ # api = Radiator::Api.new
40
+ # virtual_supply = api.get_dynamic_global_properties do |prop, error|
41
+ # if prop.nil?
42
+ # puts error
43
+ # exis
44
+ # end
45
+ #
46
+ # prop.virtual_supply
47
+ # end
48
+ #
49
+ # List of remote methods:
50
+ #
51
+ # set_subscribe_callback
52
+ # set_pending_transaction_callback
53
+ # set_block_applied_callback
54
+ # cancel_all_subscriptions
55
+ # get_trending_tags
56
+ # get_tags_used_by_author
57
+ # get_post_discussions_by_payout
58
+ # get_comment_discussions_by_payout
59
+ # get_discussions_by_trending
60
+ # get_discussions_by_trending30
61
+ # get_discussions_by_created
62
+ # get_discussions_by_active
63
+ # get_discussions_by_cashout
64
+ # get_discussions_by_payout
65
+ # get_discussions_by_votes
66
+ # get_discussions_by_children
67
+ # get_discussions_by_hot
68
+ # get_discussions_by_feed
69
+ # get_discussions_by_blog
70
+ # get_discussions_by_comments
71
+ # get_discussions_by_promoted
72
+ # get_block_header
73
+ # get_block
74
+ # get_ops_in_block
75
+ # get_state
76
+ # get_trending_categories
77
+ # get_best_categories
78
+ # get_active_categories
79
+ # get_recent_categories
80
+ # get_config
81
+ # get_dynamic_global_properties
82
+ # get_chain_properties
83
+ # get_feed_history
84
+ # get_current_median_history_price
85
+ # get_witness_schedule
86
+ # get_hardfork_version
87
+ # get_next_scheduled_hardfork
88
+ # get_accounts
89
+ # get_account_references
90
+ # lookup_account_names
91
+ # lookup_accounts
92
+ # get_account_count
93
+ # get_conversion_requests
94
+ # get_account_history
95
+ # get_owner_history
96
+ # get_recovery_request
97
+ # get_escrow
98
+ # get_withdraw_routes
99
+ # get_account_bandwidth
100
+ # get_savings_withdraw_from
101
+ # get_savings_withdraw_to
102
+ # get_order_book
103
+ # get_open_orders
104
+ # get_liquidity_queue
105
+ # get_transaction_hex
106
+ # get_transaction
107
+ # get_required_signatures
108
+ # get_potential_signatures
109
+ # verify_authority
110
+ # verify_account_authority
111
+ # get_active_votes
112
+ # get_account_votes
113
+ # get_content
114
+ # get_content_replies
115
+ # get_discussions_by_author_before_date
116
+ # get_replies_by_last_update
117
+ # get_witnesses
118
+ # get_witness_by_account
119
+ # get_witnesses_by_vote
120
+ # lookup_witness_accounts
121
+ # get_witness_count
122
+ # get_active_witnesses
123
+ # get_miner_queue
124
+ # get_reward_fund
125
+ #
126
+ # These methods and their characteristics are copied directly from methods
127
+ # marked as `database_api` in `steem-js`:
128
+ #
129
+ # https://raw.githubusercontent.com/steemit/steem-js/master/src/api/methods.js
130
+ #
131
+ # @see https://steemit.github.io/steemit-docs/#accounts
132
+ #
9
133
  class Api
10
134
  DEFAULT_URL = 'https://steemd.steemit.com'
11
135
 
@@ -21,10 +145,22 @@ module Radiator
21
145
  'https://rpc.steemliberator.com'
22
146
  ]
23
147
 
148
+ # @private
24
149
  POST_HEADERS = {
25
150
  'Content-Type' => 'application/json'
26
151
  }
27
152
 
153
+ # Cretes a new instance of Radiator::Api.
154
+ #
155
+ # Examples:
156
+ #
157
+ # api = Radiator::Api.new(url: 'https://api.example.com')
158
+ #
159
+ # @param options [Hash] The attributes to initialize the Radiator::Api with.
160
+ # @option options [String] :url URL that points at a full node, like `https://steemd.steemit.com`. Default from DEFAULT_URL.
161
+ # @option options [Array<String>] :failover_urls An array that contains one or more full nodes to fall back on. Default from DEFAULT_FAILOVER_URLS.
162
+ # @option options [Logger] :logger An instance of `Logger` to send debug messages to.
163
+ # @option options [Boolean] :recover_transactions_on_error Have Radiator try to recover transactions that are accepted but could not be confirmed due to an error like network timeout. Default: `true`
28
164
  def initialize(options = {})
29
165
  @user = options[:user]
30
166
  @password = options[:password]
@@ -51,20 +187,22 @@ module Radiator
51
187
  @api_options = options.dup
52
188
  end
53
189
 
54
- def method_names
55
- return @method_names if !!@method_names
56
-
57
- @method_names = Radiator::Api.methods(api_name).map do |e|
58
- e['method'].to_sym
59
- end
60
- end
61
-
62
- def api_name
63
- :database_api
64
- end
65
-
66
190
  # Get a specific block or range of blocks.
67
- #
191
+ #
192
+ # Example:
193
+ #
194
+ # api = Radiator::Api.new
195
+ # blocks = api.get_blocks(10..20)
196
+ # transactions = blocks.flat_map(&:transactions)
197
+ #
198
+ # ... or ...
199
+ #
200
+ # api = Radiator::Api.new
201
+ # transactions = []
202
+ # api.get_blocks(10..20) do |block|
203
+ # transactions += block.transactions
204
+ # end
205
+ #
68
206
  # @param block_number [Fixnum || Array<Fixnum>]
69
207
  # @param block the block to execute for each result, optional.
70
208
  # @return [Array]
@@ -82,7 +220,20 @@ module Radiator
82
220
  end
83
221
  end
84
222
 
85
- # Find a specific block
223
+ # Find a specific block.
224
+ #
225
+ # Example:
226
+ #
227
+ # api = Radiator::Api.new
228
+ # block = api.find_block(12345678)
229
+ # transactions = block.transactions
230
+ #
231
+ # ... or ...
232
+ #
233
+ # api = Radiator::Api.new
234
+ # transactions = api.find_block(12345678) do |block|
235
+ # block.transactions
236
+ # end
86
237
  #
87
238
  # @param block_number [Fixnum]
88
239
  # @param block the block to execute for each result, optional.
@@ -95,6 +246,24 @@ module Radiator
95
246
  end
96
247
  end
97
248
 
249
+ # Find a specific account.
250
+ #
251
+ # Example:
252
+ #
253
+ # api = Radiator::Api.new
254
+ # ned = api.find_account('ned')
255
+ # vesting_shares = ned.vesting_shares
256
+ #
257
+ # ... or ...
258
+ #
259
+ # api = Radiator::Api.new
260
+ # vesting_shares = api.find_account('ned') do |ned|
261
+ # ned.vesting_shares
262
+ # end
263
+ #
264
+ # @param id [String] Name of the account to find.
265
+ # @param block the block to execute for each result, optional.
266
+ # @return [Hash]
98
267
  def find_account(id, &block)
99
268
  if !!block
100
269
  yield api.get_accounts([id]).result.first
@@ -103,6 +272,8 @@ module Radiator
103
272
  end
104
273
  end
105
274
 
275
+ # Returns the current base (STEEM) price in the vest asset (VESTS).
276
+ #
106
277
  def base_per_mvest
107
278
  api.get_dynamic_global_properties do |properties|
108
279
  total_vesting_fund_steem = properties.total_vesting_fund_steem.to_f
@@ -114,6 +285,8 @@ module Radiator
114
285
 
115
286
  alias steem_per_mvest base_per_mvest
116
287
 
288
+ # Returns the current base (STEEM) price in the debt asset (SBD).
289
+ #
117
290
  def base_per_debt
118
291
  get_feed_history do |feed_history|
119
292
  current_median_history = feed_history.current_median_history
@@ -121,17 +294,40 @@ module Radiator
121
294
  base = base.split(' ').first.to_f
122
295
  quote = current_median_history.quote
123
296
  quote = quote.split(' ').first.to_f
124
-
297
+
125
298
  (base / quote) * steem_per_mvest
126
299
  end
127
300
  end
128
301
 
129
302
  alias steem_per_usd base_per_debt
130
303
 
304
+ # Stops the persistant http connections.
305
+ #
306
+ def shutdown
307
+ @http.shutdown if !!@http && defined?(@http.shutdown)
308
+ @http = nil
309
+ end
310
+
311
+ # @private
312
+ def method_names
313
+ return @method_names if !!@method_names
314
+
315
+ @method_names = Radiator::Api.methods(api_name).map do |e|
316
+ e['method'].to_sym
317
+ end
318
+ end
319
+
320
+ # @private
321
+ def api_name
322
+ :database_api
323
+ end
324
+
325
+ # @private
131
326
  def respond_to_missing?(m, include_private = false)
132
327
  method_names.include?(m.to_sym)
133
328
  end
134
329
 
330
+ # @private
135
331
  def method_missing(m, *args, &block)
136
332
  super unless respond_to_missing?(m)
137
333
 
@@ -161,39 +357,36 @@ module Radiator
161
357
  end
162
358
  end
163
359
 
164
- response = request(options)
165
-
166
360
  if response.nil?
167
- @logger.error "No response, retrying ..."
168
- backoff
169
- redo
170
- elsif !response.kind_of? Net::HTTPSuccess
171
- @logger.warn "Unexpected response: #{response.inspect}"
172
- backoff
173
- redo
174
- end
175
-
176
- response = case response.code
177
- when '200'
178
- body = response.body
179
- response = JSON[body]
361
+ response = request(options)
180
362
 
181
- if response.keys.include?('result') && response['result'].nil?
182
- @logger.warn 'Invalid response from node, retrying ...'; nil
363
+ response = if response.nil?
364
+ @logger.error "No response, retrying ..."; nil
365
+ elsif !response.kind_of? Net::HTTPSuccess
366
+ @logger.warn "Unexpected response (code: #{response.code}): #{response.inspect}, retrying ..."; nil
183
367
  else
184
- Hashie::Mash.new(response)
368
+ case response.code
369
+ when '200'
370
+ body = response.body
371
+ response = JSON[body]
372
+
373
+ if response.keys.include?('result') && response['result'].nil?
374
+ @logger.warn 'Invalid response from node, retrying ...'; nil
375
+ else
376
+ Hashie::Mash.new(response)
377
+ end
378
+ when '400' then @logger.warn 'Code 400: Bad Request, retrying ...'; nil
379
+ when '502' then @logger.warn 'Code 502: Bad Gateway, retrying ...'; nil
380
+ when '503' then @logger.warn 'Code 503: Service Unavailable, retrying ...'; nil
381
+ when '504' then @logger.warn 'Code 504: Gateway Timeout, retrying ...'; nil
382
+ else
383
+ @logger.warn "Unknown code #{response.code}, retrying ..."
384
+ ap response
385
+ end
185
386
  end
186
- when '400' then @logger.warn 'Code 400: Bad Request, retrying ...'; nil
187
- when '502' then @logger.warn 'Code 502: Bad Gateway, retrying ...'; nil
188
- when '503' then @logger.warn 'Code 503: Service Unavailable, retrying ...'; nil
189
- when '504' then @logger.warn 'Code 504: Gateway Timeout, retrying ...'; nil
190
- else
191
- @logger.warn "Unknown code #{response.code}, retrying ..."
192
- ap response
193
387
  end
194
388
  rescue Net::HTTP::Persistent::Error => e
195
- @logger.warn "Unable to perform request: #{e} :: #{!!e.cause ? "cause: #{e.cause.message}" : ''}"
196
- @wakka = true
389
+ @logger.warn "Unable to perform request: #{e} :: #{!!e.cause ? "cause: #{e.cause.message}" : ''}, retrying ..."
197
390
  rescue Errno::ECONNREFUSED => e
198
391
  @logger.warn 'Connection refused, retrying ...'
199
392
  rescue Errno::EADDRNOTAVAIL => e
@@ -211,7 +404,7 @@ module Radiator
211
404
  rescue JSON::ParserError => e
212
405
  @logger.warn "JSON Parse Error (#{e.message}), retrying ..."
213
406
  rescue => e
214
- @logger.warn "Unknown exception from request ..."
407
+ @logger.warn "Unknown exception from request, retrying ..."
215
408
  ap e if defined? ap
216
409
  end
217
410
 
@@ -226,11 +419,6 @@ module Radiator
226
419
  backoff
227
420
  end # loop
228
421
  end
229
-
230
- def shutdown
231
- @http.shutdown if !!@http && defined?(@http.shutdown)
232
- @http = nil
233
- end
234
422
  private
235
423
  def self.methods_json_path
236
424
  @methods_json_path ||= "#{File.dirname(__FILE__)}/methods.json"
@@ -1,4 +1,5 @@
1
1
  module Radiator
2
+ # @see Api
2
3
  class DatabaseApi < Api
3
4
  end
4
5
  end
@@ -10,9 +10,17 @@ module Radiator
10
10
  # stream.current_witness do |witness|
11
11
  # puts witness
12
12
  # end
13
+ #
14
+ # More importantly, full blocks, transactions, and operations can be streamed.
13
15
  class Stream < Api
16
+
17
+ # @private
14
18
  INITIAL_TIMEOUT = 0.0200
19
+
20
+ # @private
15
21
  MAX_TIMEOUT = 80
22
+
23
+ # @private
16
24
  MAX_BLOCKS_PER_NODE = 100
17
25
 
18
26
  def initialize(options = {})
@@ -20,52 +28,12 @@ module Radiator
20
28
  @logger = @api_options[:logger] || Radiator.logger
21
29
  end
22
30
 
23
- def api
24
- @api ||= Api.new(@api_options)
25
- end
26
-
27
- def method_names
28
- @method_names ||= [
29
- :head_block_number,
30
- :head_block_id,
31
- :time,
32
- :current_witness,
33
- :total_pow,
34
- :num_pow_witnesses,
35
- :virtual_supply,
36
- :current_supply,
37
- :confidential_supply,
38
- :current_sbd_supply,
39
- :confidential_sbd_supply,
40
- :total_vesting_fund_steem,
41
- :total_vesting_shares,
42
- :total_reward_fund_steem,
43
- :total_reward_shares2,
44
- :total_activity_fund_steem,
45
- :total_activity_fund_shares,
46
- :sbd_interest_rate,
47
- :average_block_size,
48
- :maximum_block_size,
49
- :current_aslot,
50
- :recent_slots_filled,
51
- :participation_count,
52
- :last_irreversible_block_num,
53
- :max_virtual_bandwidth,
54
- :current_reserve_ratio,
55
- :block_numbers,
56
- :blocks
57
- ].freeze
58
- end
59
-
60
- def method_params(method)
61
- case method
62
- when :block_numbers then {head_block_number: nil}
63
- when :blocks then {get_block: :head_block_number}
64
- else; nil
65
- end
66
- end
67
-
68
31
  # Returns the latest operations from the blockchain.
32
+ #
33
+ # stream = Radiator::Stream.new
34
+ # stream.operations do |op|
35
+ # puts op.to_json
36
+ # end
69
37
  #
70
38
  # If symbol are passed, then only that operation is returned. Expected
71
39
  # symbols are:
@@ -98,6 +66,13 @@ module Radiator
98
66
  # pow
99
67
  # custom
100
68
  #
69
+ # For example, to stream only votes:
70
+ #
71
+ # stream = Radiator::Stream.new
72
+ # stream.operations(:vote) do |vote|
73
+ # puts vote.to_json
74
+ # end
75
+ #
101
76
  # @param type [symbol || Array<symbol>] the type(s) of operation, optional.
102
77
  # @param start starting block
103
78
  # @param mode we have the choice between
@@ -127,7 +102,12 @@ module Radiator
127
102
  end
128
103
 
129
104
  # Returns the latest transactions from the blockchain.
130
- #
105
+ #
106
+ # stream = Radiator::Stream.new
107
+ # stream.transactions do |tx, trx_id|
108
+ # puts "[#{trx_id}] #{tx.to_json}"
109
+ # end
110
+ #
131
111
  # @param start starting block
132
112
  # @param mode we have the choice between
133
113
  # * :head the last block
@@ -150,6 +130,11 @@ module Radiator
150
130
  end
151
131
 
152
132
  # Returns the latest blocks from the blockchain.
133
+ #
134
+ # stream = Radiator::Stream.new
135
+ # stream.blocks do |bk, num|
136
+ # puts "[#{num}] #{bk.to_json}"
137
+ # end
153
138
  #
154
139
  # @param start starting block
155
140
  # @param mode we have the choice between
@@ -201,6 +186,65 @@ module Radiator
201
186
  end
202
187
  end
203
188
 
189
+ # Stops the persistant http connections.
190
+ #
191
+ def shutdown
192
+ begin
193
+ @api.shutdown
194
+ rescue => e
195
+ @logger.warn("Unable to shut down: #{e}")
196
+ end
197
+
198
+ @api = nil
199
+ end
200
+
201
+ # @private
202
+ def method_names
203
+ @method_names ||= [
204
+ :head_block_number,
205
+ :head_block_id,
206
+ :time,
207
+ :current_witness,
208
+ :total_pow,
209
+ :num_pow_witnesses,
210
+ :virtual_supply,
211
+ :current_supply,
212
+ :confidential_supply,
213
+ :current_sbd_supply,
214
+ :confidential_sbd_supply,
215
+ :total_vesting_fund_steem,
216
+ :total_vesting_shares,
217
+ :total_reward_fund_steem,
218
+ :total_reward_shares2,
219
+ :total_activity_fund_steem,
220
+ :total_activity_fund_shares,
221
+ :sbd_interest_rate,
222
+ :average_block_size,
223
+ :maximum_block_size,
224
+ :current_aslot,
225
+ :recent_slots_filled,
226
+ :participation_count,
227
+ :last_irreversible_block_num,
228
+ :max_virtual_bandwidth,
229
+ :current_reserve_ratio,
230
+ :block_numbers,
231
+ :blocks
232
+ ].freeze
233
+ end
234
+
235
+ # @private
236
+ def method_params(method)
237
+ case method
238
+ when :block_numbers then {head_block_number: nil}
239
+ when :blocks then {get_block: :head_block_number}
240
+ else; nil
241
+ end
242
+ end
243
+ private
244
+ def api
245
+ @api ||= Api.new(@api_options)
246
+ end
247
+
204
248
  def method_missing(m, *args, &block)
205
249
  super unless respond_to_missing?(m)
206
250
 
@@ -248,17 +292,5 @@ module Radiator
248
292
  @timeout = INITIAL_TIMEOUT if @timeout > MAX_TIMEOUT
249
293
  @timeout
250
294
  end
251
-
252
- # Stops the persistant http connections.
253
- #
254
- def shutdown
255
- begin
256
- @api.shutdown
257
- rescue => e
258
- @logger.warn("Unable to shut down: #{e}")
259
- end
260
-
261
- @api = nil
262
- end
263
295
  end
264
296
  end
@@ -1,3 +1,3 @@
1
1
  module Radiator
2
- VERSION = '0.3.0dev2'
2
+ VERSION = '0.3.0dev3'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: radiator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0dev2
4
+ version: 0.3.0dev3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Martin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-29 00:00:00.000000000 Z
11
+ date: 2017-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler