radiator 0.3.0dev1 → 0.3.0dev2
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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/radiator/api.rb +134 -64
- data/lib/radiator/stream.rb +1 -1
- data/lib/radiator/transaction.rb +1 -0
- data/lib/radiator/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e876d3ec41bf655bc3bfc4494f22d862b71f4442
|
4
|
+
data.tar.gz: 65bec4acf06c108bd56ca239c9cdb660332c91a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e1f48eb220ecd006335906909f88e493f7d806a4147e5443f1f9b8663c0ea941d6239bb1a610180414c514e85e9c1b084309d21cc698d0f20e730f9e292f546
|
7
|
+
data.tar.gz: 5e8c2376494c49046e0f18ef34b7a0e235e8230bbc5acbf76515adbced6e17de80942cdfb1214340e41c2ccecf9c4f85684b959fc00f99e65ae787b5afeb7bc0
|
data/Gemfile.lock
CHANGED
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
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
102
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
-
|
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
|
-
|
178
|
+
body = response.body
|
179
|
+
response = JSON[body]
|
147
180
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
when '
|
154
|
-
|
155
|
-
when '
|
156
|
-
|
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
|
-
|
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
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
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
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
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
|
-
|
253
|
-
|
305
|
+
timestamp = Time.parse(block.timestamp + 'Z')
|
306
|
+
break if timestamp < after
|
254
307
|
|
255
|
-
|
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
|
data/lib/radiator/stream.rb
CHANGED
data/lib/radiator/transaction.rb
CHANGED
data/lib/radiator/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2017-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|