radiator 0.3.0dev1 → 0.3.0dev2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: db2757e072c1d05c7f12eb6228245cb66680af4a
4
- data.tar.gz: 33ade0af04c25fdae0dce9bf94322367d68cfbe3
3
+ metadata.gz: e876d3ec41bf655bc3bfc4494f22d862b71f4442
4
+ data.tar.gz: 65bec4acf06c108bd56ca239c9cdb660332c91a9
5
5
  SHA512:
6
- metadata.gz: 8c5a3a4079b0f5d92f142fee590f3e6e0256bdba99c2f78951f2030dc68ad4f3f42cc6fd013293cab4342b596be3789432acea19f518de5cf06a8097da1048c1
7
- data.tar.gz: 836ea02d0e39a9ac338b301ff65ed9efc8256336b3fccc482e377f573d131970459cb4dee3af3102c49583b61b308a8e77b1241cbca9cdd2755f8bc901285de8
6
+ metadata.gz: 9e1f48eb220ecd006335906909f88e493f7d806a4147e5443f1f9b8663c0ea941d6239bb1a610180414c514e85e9c1b084309d21cc698d0f20e730f9e292f546
7
+ data.tar.gz: 5e8c2376494c49046e0f18ef34b7a0e235e8230bbc5acbf76515adbced6e17de80942cdfb1214340e41c2ccecf9c4f85684b959fc00f99e65ae787b5afeb7bc0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- radiator (0.3.0dev1)
4
+ radiator (0.3.0dev2)
5
5
  bitcoin-ruby (= 0.0.11)
6
6
  ffi (= 1.9.18)
7
7
  hashie (~> 3.5, >= 3.5.5)
data/lib/radiator/api.rb CHANGED
@@ -15,6 +15,9 @@ module Radiator
15
15
  'https://steemd-int.steemit.com',
16
16
  'https://steemd.steemitstage.com',
17
17
  'https://gtg.steem.house:8090',
18
+ "https://seed.bitcoiner.me",
19
+ "https://steemd.minnowsupportproject.org",
20
+ "https://steemd.privex.io",
18
21
  'https://rpc.steemliberator.com'
19
22
  ]
20
23
 
@@ -30,7 +33,6 @@ module Radiator
30
33
  @failover_urls = options[:failover_urls] || (DEFAULT_FAILOVER_URLS - [@url])
31
34
  @preferred_failover_urls = @failover_urls.dup
32
35
  @debug = !!options[:debug]
33
- @net_http_persistent_enabled = true
34
36
  @logger = options[:logger] || Radiator.logger
35
37
  @hashie_logger = options[:hashie_logger] || Logger.new(nil)
36
38
 
@@ -38,8 +40,15 @@ module Radiator
38
40
  @hashie_logger = Logger.new(@hashie_logger)
39
41
  end
40
42
 
43
+ @recover_transactions_on_error = if options.keys.include? :recover_transactions_on_error
44
+ options[:recover_transactions_on_error]
45
+ else
46
+ true
47
+ end
48
+
41
49
  Hashie.logger = @hashie_logger
42
50
  @method_names = nil
51
+ @api_options = options.dup
43
52
  end
44
53
 
45
54
  def method_names
@@ -64,11 +73,11 @@ module Radiator
64
73
 
65
74
  if !!block
66
75
  block_number.each do |i|
67
- yield get_block(i).result, i
76
+ yield api.get_block(i).result, i
68
77
  end
69
78
  else
70
79
  block_number.map do |i|
71
- get_block(i).result
80
+ api.get_block(i).result
72
81
  end
73
82
  end
74
83
  end
@@ -80,43 +89,45 @@ module Radiator
80
89
  # @return [Hash]
81
90
  def find_block(block_number, &block)
82
91
  if !!block
83
- yield get_blocks(block_number).first
92
+ yield api.get_blocks(block_number).first
84
93
  else
85
- get_blocks(block_number).first
94
+ api.get_blocks(block_number).first
86
95
  end
87
96
  end
88
97
 
89
98
  def find_account(id, &block)
90
99
  if !!block
91
- yield get_accounts([id]).result.first
100
+ yield api.get_accounts([id]).result.first
92
101
  else
93
- get_accounts([id]).result.first
102
+ api.get_accounts([id]).result.first
94
103
  end
95
104
  end
96
105
 
97
- # TODO: Need to rename this to base_per_mvest and alias to steem_per_mvest
98
- def steem_per_mvest
99
- properties = get_dynamic_global_properties.result
106
+ def base_per_mvest
107
+ api.get_dynamic_global_properties do |properties|
108
+ total_vesting_fund_steem = properties.total_vesting_fund_steem.to_f
109
+ total_vesting_shares_mvest = properties.total_vesting_shares.to_f / 1e6
100
110
 
101
- total_vesting_fund_steem = properties.total_vesting_fund_steem.to_f
102
- total_vesting_shares_mvest = properties.total_vesting_shares.to_f / 1e6
103
-
104
- total_vesting_fund_steem / total_vesting_shares_mvest
111
+ total_vesting_fund_steem / total_vesting_shares_mvest
112
+ end
105
113
  end
106
114
 
107
- # TODO: Need to rename this to base_per_debt and alias to steem_per_debt
108
- def steem_per_usd
109
- feed_history = get_feed_history.result
110
-
111
- current_median_history = feed_history.current_median_history
112
- base = current_median_history.base
113
- base = base.split(' ').first.to_f
114
- quote = current_median_history.quote
115
- quote = quote.split(' ').first.to_f
115
+ alias steem_per_mvest base_per_mvest
116
+
117
+ def base_per_debt
118
+ get_feed_history do |feed_history|
119
+ current_median_history = feed_history.current_median_history
120
+ base = current_median_history.base
121
+ base = base.split(' ').first.to_f
122
+ quote = current_median_history.quote
123
+ quote = quote.split(' ').first.to_f
116
124
 
117
- (base / quote) * steem_per_mvest
125
+ (base / quote) * steem_per_mvest
126
+ end
118
127
  end
119
128
 
129
+ alias steem_per_usd base_per_debt
130
+
120
131
  def respond_to_missing?(m, include_private = false)
121
132
  method_names.include?(m.to_sym)
122
133
  end
@@ -124,6 +135,7 @@ module Radiator
124
135
  def method_missing(m, *args, &block)
125
136
  super unless respond_to_missing?(m)
126
137
 
138
+ response = nil
127
139
  options = {
128
140
  jsonrpc: "2.0",
129
141
  params: [api_name, m, args],
@@ -131,35 +143,57 @@ module Radiator
131
143
  method: "call"
132
144
  }
133
145
 
146
+ tries = 0
147
+ timestamp = Time.now.utc
148
+
134
149
  loop do
150
+ tries += 1
151
+
135
152
  begin
153
+ if @recover_transactions_on_error
154
+ signatures = extract_signatures(options)
155
+
156
+ if tries > 1 && !!signatures && signatures.any?
157
+ if !!(response = recover_transaction(signatures, rpc_id, timestamp))
158
+ @logger.warn 'Found recovered transaction after retry.'
159
+ response = Hashie::Mash.new(response)
160
+ end
161
+ end
162
+ end
163
+
136
164
  response = request(options)
137
165
 
138
166
  if response.nil?
139
167
  @logger.error "No response, retrying ..."
140
168
  backoff
141
169
  redo
170
+ elsif !response.kind_of? Net::HTTPSuccess
171
+ @logger.warn "Unexpected response: #{response.inspect}"
172
+ backoff
173
+ redo
142
174
  end
143
175
 
144
- case response.code
176
+ response = case response.code
145
177
  when '200'
146
- response = JSON[response.body]
178
+ body = response.body
179
+ response = JSON[body]
147
180
 
148
- return Hashie::Mash.new(response)
149
- when '400'
150
- @logger.warn 'Code 400: Bad Request, retrying ...'
151
- when '502'
152
- @logger.warn 'Code 502: Bad Gateway, retrying ...'
153
- when '503'
154
- @logger.warn 'Code 503: Service Unavailable, retrying ...'
155
- when '504'
156
- @logger.warn 'Code 504: Gateway Timeout, retrying ...'
181
+ if response.keys.include?('result') && response['result'].nil?
182
+ @logger.warn 'Invalid response from node, retrying ...'; nil
183
+ else
184
+ Hashie::Mash.new(response)
185
+ 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
157
190
  else
158
191
  @logger.warn "Unknown code #{response.code}, retrying ..."
159
192
  ap response
160
193
  end
161
-
162
- backoff
194
+ rescue Net::HTTP::Persistent::Error => e
195
+ @logger.warn "Unable to perform request: #{e} :: #{!!e.cause ? "cause: #{e.cause.message}" : ''}"
196
+ @wakka = true
163
197
  rescue Errno::ECONNREFUSED => e
164
198
  @logger.warn 'Connection refused, retrying ...'
165
199
  rescue Errno::EADDRNOTAVAIL => e
@@ -178,9 +212,17 @@ module Radiator
178
212
  @logger.warn "JSON Parse Error (#{e.message}), retrying ..."
179
213
  rescue => e
180
214
  @logger.warn "Unknown exception from request ..."
181
- ap e
215
+ ap e if defined? ap
182
216
  end
183
-
217
+
218
+ if !!response
219
+ if !!block
220
+ return yield(response.result, response.error, response.id)
221
+ else
222
+ return response
223
+ end
224
+ end
225
+
184
226
  backoff
185
227
  end # loop
186
228
  end
@@ -201,6 +243,10 @@ module Radiator
201
243
  end.compact.freeze
202
244
  end
203
245
 
246
+ def api
247
+ @api ||= self.class == Api ? self : Api.new(@api_options)
248
+ end
249
+
204
250
  def rpc_id
205
251
  @rpc_id ||= 0
206
252
  @rpc_id = @rpc_id + 1
@@ -225,35 +271,59 @@ module Radiator
225
271
  end
226
272
 
227
273
  def request(options)
228
- if !!@net_http_persistent_enabled
229
- begin
230
- request = post_request
231
- request.body = JSON[options]
232
- response = http.request(uri, request)
233
-
234
- return response if response.kind_of? Net::HTTPSuccess
235
- @logger.warn "Unexpeced response: #{response.inspect}; temporarily falling back to non-persistent-http"
236
- backoff
237
- @net_http_persistent_enabled = false
238
- rescue Net::HTTP::Persistent::Error => e
239
- @logger.warn "Unable to perform request: #{request} :: #{e} :: #{!!e.cause ? "cause: #{e.cause.message}" : ''}; temporarily falling back to non-persistent-http"
240
- backoff
241
- @net_http_persistent_enabled = false
242
- end
243
- end
274
+ request = post_request
275
+ request.body = JSON[options]
276
+ http.request(uri, request)
277
+ end
278
+
279
+ def extract_signatures(options)
280
+ return unless options[:params].include? :network_broadcast_api
281
+
282
+ options[:params].map do |param|
283
+ next unless defined? param.map
244
284
 
245
- unless @net_http_persistent_enabled
246
- non_persistent_http = Net::HTTP.new(uri.host, uri.port)
247
- non_persistent_http.use_ssl = true
248
- non_persistent_http.verify_mode = OpenSSL::SSL::VERIFY_NONE
249
- request = post_request
250
- request.body = JSON[options]
285
+ param.map { |tx| tx[:signatures] }
286
+ end.flatten.compact
287
+ end
288
+
289
+ def recover_transaction(signatures, rpc_id, after)
290
+ now = Time.now.utc
291
+ block_range = api.get_dynamic_global_properties do |properties|
292
+ high = properties.head_block_number
293
+ low = high - 100
294
+ [*(low..(high))].reverse
295
+ end
296
+
297
+ # It would be nice if Steemit, Inc. would add an API method like
298
+ # `get_transaction`, call it `get_transaction_by_signature`, so we didn't
299
+ # have to scan the latest blocks like this. At most, we read 100 blocks
300
+ # but we also give up once the block time is before the `after` argument.
301
+
302
+ api.get_blocks(block_range) do |block, block_num|
303
+ raise "Race condition detected at: #{block_num}" if block.nil?
251
304
 
252
- # Try to go back to http persistent on next request.
253
- @net_http_persistent_enabled = true
305
+ timestamp = Time.parse(block.timestamp + 'Z')
306
+ break if timestamp < after
254
307
 
255
- non_persistent_http.request(request)
308
+ block.transactions.each_with_index do |tx, index|
309
+ next unless ((tx['signatures'] || []) & signatures).any?
310
+
311
+ puts "Found matching signatures in #{(Time.now.utc - now)} seconds: #{signatures}"
312
+ ap tx
313
+
314
+ return {
315
+ id: rpc_id,
316
+ result: {
317
+ id: block.transaction_ids[index],
318
+ block_num: block_num,
319
+ trx_num: index,
320
+ expired: false
321
+ }
322
+ }
323
+ end
256
324
  end
325
+
326
+ puts "Took #{(Time.now.utc - now)} seconds to scan for signatures."
257
327
  end
258
328
 
259
329
  def reset_failover
@@ -16,7 +16,7 @@ module Radiator
16
16
  MAX_BLOCKS_PER_NODE = 100
17
17
 
18
18
  def initialize(options = {})
19
- @api_options = options
19
+ @api_options = options.dup
20
20
  @logger = @api_options[:logger] || Radiator.logger
21
21
  end
22
22
 
@@ -16,6 +16,7 @@ module Radiator
16
16
  VALID_OPTIONS.each { |option| attr_accessor option }
17
17
 
18
18
  def initialize(options = {})
19
+ options = options.dup
19
20
  options.each do |k, v|
20
21
  k = k.to_sym
21
22
  if VALID_OPTIONS.include?(k.to_sym)
@@ -1,3 +1,3 @@
1
1
  module Radiator
2
- VERSION = '0.3.0dev1'
2
+ VERSION = '0.3.0dev2'
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.0dev1
4
+ version: 0.3.0dev2
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-28 00:00:00.000000000 Z
11
+ date: 2017-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler