steem-ruby 0.9.1 → 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -1
- data/README.md +83 -10
- data/Rakefile +128 -31
- data/lib/steem.rb +49 -0
- data/lib/steem/api.rb +38 -36
- data/lib/steem/base_error.rb +32 -11
- data/lib/steem/block_api.rb +23 -3
- data/lib/steem/broadcast.rb +165 -2
- data/lib/steem/marshal.rb +231 -0
- data/lib/steem/mixins/jsonable.rb +37 -0
- data/lib/steem/mixins/retriable.rb +22 -13
- data/lib/steem/mixins/serializable.rb +45 -0
- data/lib/steem/operation.rb +141 -0
- data/lib/steem/operation/account_create.rb +10 -0
- data/lib/steem/operation/account_create_with_delegation.rb +12 -0
- data/lib/steem/operation/account_update.rb +8 -0
- data/lib/steem/operation/account_witness_proxy.rb +4 -0
- data/lib/steem/operation/account_witness_vote.rb +5 -0
- data/lib/steem/operation/cancel_transfer_from_savings.rb +4 -0
- data/lib/steem/operation/challenge_authority.rb +5 -0
- data/lib/steem/operation/change_recovery_account.rb +5 -0
- data/lib/steem/operation/claim_account.rb +5 -0
- data/lib/steem/operation/claim_reward_balance.rb +6 -0
- data/lib/steem/operation/comment.rb +9 -0
- data/lib/steem/operation/comment_options.rb +10 -0
- data/lib/steem/operation/convert.rb +5 -0
- data/lib/steem/operation/create_claimed_account.rb +10 -0
- data/lib/steem/operation/custom.rb +5 -0
- data/lib/steem/operation/custom_binary.rb +8 -0
- data/lib/steem/operation/custom_json.rb +6 -0
- data/lib/steem/operation/decline_voting_rights.rb +4 -0
- data/lib/steem/operation/delegate_vesting_shares.rb +5 -0
- data/lib/steem/operation/delete_comment.rb +4 -0
- data/lib/steem/operation/escrow_approve.rb +8 -0
- data/lib/steem/operation/escrow_dispute.rb +7 -0
- data/lib/steem/operation/escrow_release.rb +10 -0
- data/lib/steem/operation/escrow_transfer.rb +12 -0
- data/lib/steem/operation/feed_publish.rb +4 -0
- data/lib/steem/operation/limit_order_cancel.rb +4 -0
- data/lib/steem/operation/limit_order_create.rb +8 -0
- data/lib/steem/operation/limit_order_create2.rb +8 -0
- data/lib/steem/operation/prove_authority.rb +4 -0
- data/lib/steem/operation/recover_account.rb +6 -0
- data/lib/steem/operation/report_over_production.rb +5 -0
- data/lib/steem/operation/request_account_recovery.rb +6 -0
- data/lib/steem/operation/reset_account.rb +5 -0
- data/lib/steem/operation/set_reset_account.rb +5 -0
- data/lib/steem/operation/set_withdraw_vesting_route.rb +6 -0
- data/lib/steem/operation/transfer.rb +6 -0
- data/lib/steem/operation/transfer_from_savings.rb +7 -0
- data/lib/steem/operation/transfer_to_savings.rb +6 -0
- data/lib/steem/operation/transfer_to_vesting.rb +5 -0
- data/lib/steem/operation/vote.rb +6 -0
- data/lib/steem/operation/withdraw_vesting.rb +4 -0
- data/lib/steem/operation/witness_set_properties.rb +5 -0
- data/lib/steem/operation/witness_update.rb +7 -0
- data/lib/steem/rpc/base_client.rb +14 -2
- data/lib/steem/rpc/http_client.rb +17 -1
- data/lib/steem/stream.rb +385 -0
- data/lib/steem/transaction.rb +96 -0
- data/lib/steem/transaction_builder.rb +77 -70
- data/lib/steem/type/amount.rb +6 -0
- data/lib/steem/version.rb +1 -1
- data/steem-ruby.gemspec +9 -4
- metadata +203 -56
- data/Gemfile.lock +0 -73
@@ -0,0 +1,10 @@
|
|
1
|
+
class Steem::Operation::EscrowRelease < Steem::Operation
|
2
|
+
def_attr from: :string
|
3
|
+
def_attr to: :string
|
4
|
+
def_attr agent: :string
|
5
|
+
def_attr who: :string
|
6
|
+
def_attr receiver: :string
|
7
|
+
def_attr escrow_id: :uint32
|
8
|
+
def_attr sbd_amount: :amount
|
9
|
+
def_attr steem_amount: :amount
|
10
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Steem::Operation::EscrowTransfer < Steem::Operation
|
2
|
+
def_attr from: :string
|
3
|
+
def_attr to: :string
|
4
|
+
def_attr sbd_amount: :amount
|
5
|
+
def_attr steem_amount: :amount
|
6
|
+
def_attr escrow_id: :uint32
|
7
|
+
def_attr agent: :string
|
8
|
+
def_attr fee: :amount
|
9
|
+
def_attr json_metadata: :string
|
10
|
+
def_attr ratification_deadline: :point_in_time
|
11
|
+
def_attr escrow_expiration: :point_in_time
|
12
|
+
end
|
@@ -12,8 +12,7 @@ module Steem
|
|
12
12
|
MAX_TIMEOUT_BACKOFF = 30
|
13
13
|
|
14
14
|
# @private
|
15
|
-
TIMEOUT_ERRORS = [Net::ReadTimeout, Errno::EBADF,
|
16
|
-
IOError]
|
15
|
+
TIMEOUT_ERRORS = [Net::ReadTimeout, Errno::EBADF, IOError]
|
17
16
|
|
18
17
|
def initialize(options = {})
|
19
18
|
@chain = options[:chain] || :steem
|
@@ -162,6 +161,19 @@ module Steem
|
|
162
161
|
|
163
162
|
sleep @backoff
|
164
163
|
end
|
164
|
+
|
165
|
+
# @private
|
166
|
+
def raise_error_response(rpc_method_name, rpc_args, response)
|
167
|
+
raise UnknownError, "#{rpc_method_name}: #{response}" if response.error.nil?
|
168
|
+
|
169
|
+
error = response.error
|
170
|
+
|
171
|
+
if error.message == 'Invalid Request'
|
172
|
+
raise Steem::ArgumentError, "Unexpected arguments: #{rpc_args.inspect}. Expected: #{rpc_method_name} (#{args_keys_to_s(rpc_method_name)})"
|
173
|
+
end
|
174
|
+
|
175
|
+
BaseError.build_error(error, rpc_method_name)
|
176
|
+
end
|
165
177
|
end
|
166
178
|
end
|
167
179
|
end
|
@@ -17,7 +17,7 @@ module Steem
|
|
17
17
|
#
|
18
18
|
# @private
|
19
19
|
TIMEOUT_ERRORS = [Net::OpenTimeout, JSON::ParserError, Net::ReadTimeout,
|
20
|
-
Errno::EBADF, Errno::
|
20
|
+
Errno::EBADF, IOError, Errno::ENETDOWN, Steem::RemoteDatabaseLockError]
|
21
21
|
|
22
22
|
# @private
|
23
23
|
POST_HEADERS = {
|
@@ -108,6 +108,22 @@ module Steem
|
|
108
108
|
else; response
|
109
109
|
end
|
110
110
|
|
111
|
+
[response].flatten.each_with_index do |r, i|
|
112
|
+
if defined?(r.error) && !!r.error
|
113
|
+
if !!r.error.message
|
114
|
+
begin
|
115
|
+
rpc_method_name = "#{api_name}.#{api_method}"
|
116
|
+
rpc_args = [request_object].flatten[i]
|
117
|
+
raise_error_response rpc_method_name, rpc_args, r
|
118
|
+
rescue *TIMEOUT_ERRORS => e
|
119
|
+
throw retry_timeout(:tota_cera_pila, e)
|
120
|
+
end
|
121
|
+
else
|
122
|
+
raise Steem::ArgumentError, r.error.inspect
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
111
127
|
yield_response response, &block
|
112
128
|
when '504' # Gateway Timeout
|
113
129
|
throw retry_timeout(:tota_cera_pila, response.body)
|
data/lib/steem/stream.rb
ADDED
@@ -0,0 +1,385 @@
|
|
1
|
+
module Steem
|
2
|
+
# Steem::Stream allows a live view of the STEEM blockchain.
|
3
|
+
#
|
4
|
+
# Example streaming blocks:
|
5
|
+
#
|
6
|
+
# stream = Steem::Stream.new
|
7
|
+
#
|
8
|
+
# stream.blocks do |block, block_num|
|
9
|
+
# puts "#{block_num} :: #{block.witness}"
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# Example streaming transactions:
|
13
|
+
#
|
14
|
+
# stream = Steem::Stream.new
|
15
|
+
#
|
16
|
+
# stream.transactions do |trx, trx_id, block_num|
|
17
|
+
# puts "#{block_num} :: #{trx_id} :: operations: #{trx.operations.size}"
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# Example streaming operations:
|
21
|
+
#
|
22
|
+
# stream = Steem::Stream.new
|
23
|
+
#
|
24
|
+
# stream.operations do |op, trx_id, block_num|
|
25
|
+
# puts "#{block_num} :: #{trx_id} :: #{op.type}: #{op.value.to_json}"
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Allows streaming of block headers, full blocks, transactions, operations and
|
29
|
+
# virtual operations.
|
30
|
+
class Stream
|
31
|
+
attr_reader :database_api, :block_api, :account_history_api, :mode
|
32
|
+
|
33
|
+
BLOCK_INTERVAL = 3
|
34
|
+
MAX_BACKOFF_BLOCK_INTERVAL = 30
|
35
|
+
MAX_RETRY_COUNT = 10
|
36
|
+
|
37
|
+
VOP_TRX_ID = ('0' * 40).freeze
|
38
|
+
|
39
|
+
# @param options [Hash] additional options
|
40
|
+
# @option options [Steem::DatabaseApi] :database_api
|
41
|
+
# @option options [Steem::BlockApi] :block_api
|
42
|
+
# @option options [Steem::AccountHistoryApi || Steem::CondenserApi] :account_history_api
|
43
|
+
# @option options [Symbol] :mode we have the choice between
|
44
|
+
# * :head the last block
|
45
|
+
# * :irreversible the block that is confirmed by 2/3 of all block producers and is thus irreversible!
|
46
|
+
# @option options [Boolean] :no_warn do not generate warnings
|
47
|
+
def initialize(options = {mode: :irreversible})
|
48
|
+
@instance_options = options
|
49
|
+
@database_api = options[:database_api] || Steem::DatabaseApi.new(options)
|
50
|
+
@block_api = options[:block_api] || Steem::BlockApi.new(options)
|
51
|
+
@account_history_api = options[:account_history_api]
|
52
|
+
@mode = options[:mode] || :irreversible
|
53
|
+
@no_warn = !!options[:no_warn]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Use this method to stream block numbers. This is significantly faster
|
57
|
+
# than requesting full blocks and even block headers. Basically, the only
|
58
|
+
# thing this method does is call {Steem::Database#get_dynamic_global_properties} at 3 second
|
59
|
+
# intervals.
|
60
|
+
#
|
61
|
+
# @param options [Hash] additional options
|
62
|
+
# @option options [Integer] :at_block_num Starts the stream at the given block number. Default: nil.
|
63
|
+
# @option options [Integer] :until_block_num Ends the stream at the given block number. Default: nil.
|
64
|
+
def block_numbers(options = {}, &block)
|
65
|
+
block_objects(options.merge(object: :block_numbers), block)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Use this method to stream block headers. This is quite a bit faster than
|
69
|
+
# requesting full blocks.
|
70
|
+
#
|
71
|
+
# @param options [Hash] additional options
|
72
|
+
# @option options [Integer] :at_block_num Starts the stream at the given block number. Default: nil.
|
73
|
+
# @option options [Integer] :until_block_num Ends the stream at the given block number. Default: nil.
|
74
|
+
def block_headers(options = {}, &block)
|
75
|
+
block_objects(options.merge(object: :block_headers), block)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Use this method to stream full blocks.
|
79
|
+
#
|
80
|
+
# @param options [Hash] additional options
|
81
|
+
# @option options [Integer] :at_block_num Starts the stream at the given block number. Default: nil.
|
82
|
+
# @option options [Integer] :until_block_num Ends the stream at the given block number. Default: nil.
|
83
|
+
def blocks(options = {}, &block)
|
84
|
+
block_objects(options.merge(object: :blocks), block)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Use this method to stream each transaction.
|
88
|
+
#
|
89
|
+
# @param options [Hash] additional options
|
90
|
+
# @option options [Integer] :at_block_num Starts the stream at the given block number. Default: nil.
|
91
|
+
# @option options [Integer] :until_block_num Ends the stream at the given block number. Default: nil.
|
92
|
+
def transactions(options = {}, &block)
|
93
|
+
blocks(options) do |block, block_num|
|
94
|
+
if block.nil?
|
95
|
+
warn "Batch missing block_num: #{block_num}, retrying ..."
|
96
|
+
|
97
|
+
block = block_api.get_block(block_num: block_num) do |result|
|
98
|
+
result.block
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
block.transactions.each_with_index do |transaction, index|
|
103
|
+
trx_id = block.transaction_ids[index]
|
104
|
+
|
105
|
+
yield transaction, trx_id, block_num
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns the latest operations from the blockchain.
|
111
|
+
#
|
112
|
+
# stream = Steem::Stream.new
|
113
|
+
# stream.operations do |op|
|
114
|
+
# puts op.to_json
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
# If symbol are passed to `types` option, then only that operation is
|
118
|
+
# returned. Expected symbols are:
|
119
|
+
#
|
120
|
+
# account_create_operation
|
121
|
+
# account_create_with_delegation_operation
|
122
|
+
# account_update_operation
|
123
|
+
# account_witness_proxy_operation
|
124
|
+
# account_witness_vote_operation
|
125
|
+
# cancel_transfer_from_savings_operation
|
126
|
+
# change_recovery_account_operation
|
127
|
+
# claim_reward_balance_operation
|
128
|
+
# comment_operation
|
129
|
+
# comment_options_operation
|
130
|
+
# convert_operation
|
131
|
+
# custom_operation
|
132
|
+
# custom_json_operation
|
133
|
+
# decline_voting_rights_operation
|
134
|
+
# delegate_vesting_shares_operation
|
135
|
+
# delete_comment_operation
|
136
|
+
# escrow_approve_operation
|
137
|
+
# escrow_dispute_operation
|
138
|
+
# escrow_release_operation
|
139
|
+
# escrow_transfer_operation
|
140
|
+
# feed_publish_operation
|
141
|
+
# limit_order_cancel_operation
|
142
|
+
# limit_order_create_operation
|
143
|
+
# limit_order_create2_operation
|
144
|
+
# pow_operation
|
145
|
+
# pow2_operation
|
146
|
+
# recover_account_operation
|
147
|
+
# request_account_recovery_operation
|
148
|
+
# set_withdraw_vesting_route_operation
|
149
|
+
# transfer_operation
|
150
|
+
# transfer_from_savings_operation
|
151
|
+
# transfer_to_savings_operation
|
152
|
+
# transfer_to_vesting_operation
|
153
|
+
# vote_operation
|
154
|
+
# withdraw_vesting_operation
|
155
|
+
# witness_update_operation
|
156
|
+
#
|
157
|
+
# For example, to stream only votes:
|
158
|
+
#
|
159
|
+
# stream = Steem::Stream.new
|
160
|
+
# stream.operations(types: :vote_operation) do |vote|
|
161
|
+
# puts vote.to_json
|
162
|
+
# end
|
163
|
+
#
|
164
|
+
# ... Or ...
|
165
|
+
#
|
166
|
+
# stream = Steem::Stream.new
|
167
|
+
# stream.operations(:vote_operation) do |vote|
|
168
|
+
# puts vote.to_json
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
# You can also stream virtual operations:
|
172
|
+
#
|
173
|
+
# stream = Steem::Stream.new
|
174
|
+
# stream.operations(types: :author_reward_operation, only_virtual: true) do |vop|
|
175
|
+
# v = vop.value
|
176
|
+
# puts "#{v.author} got paid for #{v.permlink}: #{[v.sbd_payout, v.steem_payout, v.vesting_payout]}"
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
# ... or multiple virtual operation types;
|
180
|
+
#
|
181
|
+
# stream = Steem::Stream.new
|
182
|
+
# stream.operations(types: [:producer_reward_operation, :author_reward_operation], only_virtual: true) do |vop|
|
183
|
+
# puts vop.to_json
|
184
|
+
# end
|
185
|
+
#
|
186
|
+
# ... or all types, including virtual operation types from the head block number:
|
187
|
+
#
|
188
|
+
# stream = Steem::Stream.new(mode: :head)
|
189
|
+
# stream.operations(include_virtual: true) do |op|
|
190
|
+
# puts op.to_json
|
191
|
+
# end
|
192
|
+
#
|
193
|
+
# Expected virtual operation types:
|
194
|
+
#
|
195
|
+
# producer_reward_operation
|
196
|
+
# author_reward_operation
|
197
|
+
# curation_reward_operation
|
198
|
+
# fill_convert_request_operation
|
199
|
+
# fill_order_operation
|
200
|
+
# fill_vesting_withdraw_operation
|
201
|
+
# interest_operation
|
202
|
+
# shutdown_witness_operation
|
203
|
+
#
|
204
|
+
# @param args [Symbol || Array<Symbol> || Hash] the type(s) of operation or hash of expanded options, optional.
|
205
|
+
# @option args [Integer] :at_block_num Starts the stream at the given block number. Default: nil.
|
206
|
+
# @option args [Integer] :until_block_num Ends the stream at the given block number. Default: nil.
|
207
|
+
# @option args [Symbol || Array<Symbol>] :types the type(s) of operation, optional.
|
208
|
+
# @option args [Boolean] :only_virtual Only stream virtual options. Setting this true will improve performance because the stream only needs block numbers to then retrieve virtual operations. Default: false.
|
209
|
+
# @option args [Boolean] :include_virtual Also stream virtual options. Setting this true will impact performance. Default: false.
|
210
|
+
# @param block the block to execute for each result. Yields: |op, trx_id, block_num|
|
211
|
+
def operations(*args, &block)
|
212
|
+
options = {}
|
213
|
+
types = []
|
214
|
+
only_virtual = false
|
215
|
+
include_virtual = false
|
216
|
+
last_block_num = nil
|
217
|
+
|
218
|
+
case args.first
|
219
|
+
when Hash
|
220
|
+
options = args.first
|
221
|
+
types = transform_types(options[:types])
|
222
|
+
only_virtual = !!options[:only_virtual] || false
|
223
|
+
include_virtual = !!options[:include_virtual] || only_virtual || false
|
224
|
+
when Symbol, Array then types = transform_types(args)
|
225
|
+
end
|
226
|
+
|
227
|
+
if only_virtual
|
228
|
+
block_numbers(options) do |block_num|
|
229
|
+
get_virtual_ops(types, block_num, block)
|
230
|
+
end
|
231
|
+
else
|
232
|
+
transactions(options) do |transaction, trx_id, block_num|
|
233
|
+
transaction.operations.each do |op|
|
234
|
+
yield op, trx_id, block_num if types.none? || types.include?(op.type)
|
235
|
+
|
236
|
+
next unless last_block_num != block_num
|
237
|
+
|
238
|
+
last_block_num = block_num
|
239
|
+
|
240
|
+
get_virtual_ops(types, block_num, block) if include_virtual
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def account_history_api
|
247
|
+
@account_history_api ||= begin
|
248
|
+
Steem::AccountHistoryApi.new(@instance_options)
|
249
|
+
rescue Steem::UnknownApiError => e
|
250
|
+
warn "#{e.inspect}, falling back to Steem::CondenserApi." unless @no_warn
|
251
|
+
Steem::CondenserApi.new(@instance_options)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
private
|
255
|
+
# @private
|
256
|
+
def block_objects(options = {}, block)
|
257
|
+
object = options[:object]
|
258
|
+
object_method = "get_#{object}".to_sym
|
259
|
+
block_interval = BLOCK_INTERVAL
|
260
|
+
|
261
|
+
at_block_num, until_block_num = if !!block_range = options[:block_range]
|
262
|
+
[block_range.first, block_range.last]
|
263
|
+
else
|
264
|
+
[options[:at_block_num], options[:until_block_num]]
|
265
|
+
end
|
266
|
+
|
267
|
+
loop do
|
268
|
+
break if !!until_block_num && !!at_block_num && until_block_num < at_block_num
|
269
|
+
|
270
|
+
database_api.get_dynamic_global_properties do |properties|
|
271
|
+
current_block_num = find_block_number(properties)
|
272
|
+
current_block_num = [current_block_num, until_block_num].compact.min
|
273
|
+
at_block_num ||= current_block_num
|
274
|
+
|
275
|
+
if current_block_num >= at_block_num
|
276
|
+
range = at_block_num..current_block_num
|
277
|
+
|
278
|
+
if object == :block_numbers
|
279
|
+
range.each do |n|
|
280
|
+
block.call n
|
281
|
+
block_interval = BLOCK_INTERVAL
|
282
|
+
end
|
283
|
+
else
|
284
|
+
block_api.send(object_method, block_range: range) do |b, n|
|
285
|
+
block.call b, n
|
286
|
+
block_interval = BLOCK_INTERVAL
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
at_block_num = range.max + 1
|
291
|
+
else
|
292
|
+
# The stream has stalled, so let's back off and let the node sync
|
293
|
+
# up. We'll catch up with a bigger batch in the next cycle.
|
294
|
+
block_interval = [block_interval * 2, MAX_BACKOFF_BLOCK_INTERVAL].min
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
sleep block_interval
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# @private
|
303
|
+
def find_block_number(properties)
|
304
|
+
block_num = case mode
|
305
|
+
when :head then properties.head_block_number
|
306
|
+
when :irreversible then properties.last_irreversible_block_num
|
307
|
+
else; raise Steem::ArgumentError, "Unknown mode: #{mode}"
|
308
|
+
end
|
309
|
+
|
310
|
+
block_num
|
311
|
+
end
|
312
|
+
|
313
|
+
# @private
|
314
|
+
def transform_types(types)
|
315
|
+
[types].compact.flatten.map do |type|
|
316
|
+
type = type.to_s
|
317
|
+
|
318
|
+
unless type.end_with? '_operation'
|
319
|
+
warn "Op type #{type} is deprecated. Use #{type}_operation instead." unless @no_warn
|
320
|
+
type += '_operation'
|
321
|
+
end
|
322
|
+
|
323
|
+
type
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# @private
|
328
|
+
def get_virtual_ops(types, block_num, block)
|
329
|
+
retries = 0
|
330
|
+
|
331
|
+
loop do
|
332
|
+
get_ops_in_block_options = case account_history_api
|
333
|
+
when Steem::CondenserApi
|
334
|
+
[block_num, true]
|
335
|
+
when Steem::AccountHistoryApi
|
336
|
+
{
|
337
|
+
block_num: block_num,
|
338
|
+
only_virtual: true
|
339
|
+
}
|
340
|
+
end
|
341
|
+
|
342
|
+
response = account_history_api.get_ops_in_block(*get_ops_in_block_options)
|
343
|
+
|
344
|
+
if response.nil? || (result = response.result).nil?
|
345
|
+
if retries < MAX_RETRY_COUNT
|
346
|
+
warn "Retrying get_ops_in_block on block #{block_num}" unless @no_warn
|
347
|
+
retries = retries + 1
|
348
|
+
sleep 9
|
349
|
+
redo
|
350
|
+
else
|
351
|
+
raise TooManyRetriesError, "unable to get valid result while finding virtual operations for block: #{block_num}"
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
ops = case account_history_api
|
356
|
+
when Steem::CondenserApi
|
357
|
+
result.map do |trx|
|
358
|
+
op = {type: trx.op[0] + '_operation', value: trx.op[1]}
|
359
|
+
op = Hashie::Mash.new(op)
|
360
|
+
end
|
361
|
+
when Steem::AccountHistoryApi then result.ops.map { |trx| trx.op }
|
362
|
+
end
|
363
|
+
|
364
|
+
if ops.empty?
|
365
|
+
if retries < MAX_RETRY_COUNT
|
366
|
+
sleep 3
|
367
|
+
retries = retries + 1
|
368
|
+
redo
|
369
|
+
else
|
370
|
+
warn "unable to find virtual operations for block: #{block_num}"
|
371
|
+
# raise TooManyRetriesError, "unable to find virtual operations for block: #{block_num}"
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
ops.each do |op|
|
376
|
+
next if types.any? && !types.include?(op.type)
|
377
|
+
|
378
|
+
block.call op, VOP_TRX_ID, block_num
|
379
|
+
end
|
380
|
+
|
381
|
+
break
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|