hive-ruby 1.0.0.pre.1
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 +7 -0
- data/.gitignore +54 -0
- data/CONTRIBUTING.md +79 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +91 -0
- data/LICENSE +21 -0
- data/README.md +248 -0
- data/Rakefile +358 -0
- data/gource.sh +6 -0
- data/hive-ruby.gemspec +40 -0
- data/images/Anthony Martin.png +0 -0
- data/lib/hive.rb +89 -0
- data/lib/hive/api.rb +223 -0
- data/lib/hive/base_error.rb +218 -0
- data/lib/hive/block_api.rb +78 -0
- data/lib/hive/bridge.rb +12 -0
- data/lib/hive/broadcast.rb +1334 -0
- data/lib/hive/chain_config.rb +34 -0
- data/lib/hive/fallback.rb +287 -0
- data/lib/hive/formatter.rb +14 -0
- data/lib/hive/jsonrpc.rb +112 -0
- data/lib/hive/marshal.rb +231 -0
- data/lib/hive/mixins/jsonable.rb +37 -0
- data/lib/hive/mixins/retriable.rb +58 -0
- data/lib/hive/mixins/serializable.rb +45 -0
- data/lib/hive/operation.rb +141 -0
- data/lib/hive/operation/account_create.rb +10 -0
- data/lib/hive/operation/account_create_with_delegation.rb +12 -0
- data/lib/hive/operation/account_update.rb +8 -0
- data/lib/hive/operation/account_witness_proxy.rb +4 -0
- data/lib/hive/operation/account_witness_vote.rb +5 -0
- data/lib/hive/operation/cancel_transfer_from_savings.rb +4 -0
- data/lib/hive/operation/challenge_authority.rb +5 -0
- data/lib/hive/operation/change_recovery_account.rb +5 -0
- data/lib/hive/operation/claim_account.rb +5 -0
- data/lib/hive/operation/claim_reward_balance.rb +6 -0
- data/lib/hive/operation/comment.rb +9 -0
- data/lib/hive/operation/comment_options.rb +10 -0
- data/lib/hive/operation/convert.rb +5 -0
- data/lib/hive/operation/create_claimed_account.rb +10 -0
- data/lib/hive/operation/custom.rb +5 -0
- data/lib/hive/operation/custom_binary.rb +8 -0
- data/lib/hive/operation/custom_json.rb +6 -0
- data/lib/hive/operation/decline_voting_rights.rb +4 -0
- data/lib/hive/operation/delegate_vesting_shares.rb +5 -0
- data/lib/hive/operation/delete_comment.rb +4 -0
- data/lib/hive/operation/escrow_approve.rb +8 -0
- data/lib/hive/operation/escrow_dispute.rb +7 -0
- data/lib/hive/operation/escrow_release.rb +10 -0
- data/lib/hive/operation/escrow_transfer.rb +12 -0
- data/lib/hive/operation/feed_publish.rb +4 -0
- data/lib/hive/operation/limit_order_cancel.rb +4 -0
- data/lib/hive/operation/limit_order_create.rb +8 -0
- data/lib/hive/operation/limit_order_create2.rb +8 -0
- data/lib/hive/operation/prove_authority.rb +4 -0
- data/lib/hive/operation/recover_account.rb +6 -0
- data/lib/hive/operation/report_over_production.rb +5 -0
- data/lib/hive/operation/request_account_recovery.rb +6 -0
- data/lib/hive/operation/reset_account.rb +5 -0
- data/lib/hive/operation/set_reset_account.rb +5 -0
- data/lib/hive/operation/set_withdraw_vesting_route.rb +6 -0
- data/lib/hive/operation/transfer.rb +6 -0
- data/lib/hive/operation/transfer_from_savings.rb +7 -0
- data/lib/hive/operation/transfer_to_savings.rb +6 -0
- data/lib/hive/operation/transfer_to_vesting.rb +5 -0
- data/lib/hive/operation/vote.rb +6 -0
- data/lib/hive/operation/withdraw_vesting.rb +4 -0
- data/lib/hive/operation/witness_set_properties.rb +5 -0
- data/lib/hive/operation/witness_update.rb +7 -0
- data/lib/hive/rpc/base_client.rb +179 -0
- data/lib/hive/rpc/http_client.rb +143 -0
- data/lib/hive/rpc/thread_safe_http_client.rb +35 -0
- data/lib/hive/stream.rb +385 -0
- data/lib/hive/transaction.rb +115 -0
- data/lib/hive/transaction_builder.rb +406 -0
- data/lib/hive/type/amount.rb +126 -0
- data/lib/hive/type/base_type.rb +10 -0
- data/lib/hive/utils.rb +17 -0
- data/lib/hive/version.rb +4 -0
- metadata +502 -0
data/lib/hive/api.rb
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
module Hive
|
2
|
+
# This ruby API works with
|
3
|
+
# {https://github.com/openhive-network/hive/releases hived-0.23.00} and other AppBase
|
4
|
+
# compatible upstreams. To access different API namespaces, use the
|
5
|
+
# following:
|
6
|
+
#
|
7
|
+
# api = Hive::Api.new
|
8
|
+
# api.get_dynamic_global_properties
|
9
|
+
#
|
10
|
+
# The above example will make an instance that can access the
|
11
|
+
# {https://developers.hive.io/apidefinitions/condenser-api.html condenser_api}
|
12
|
+
# namespace. Alternatively, you may also create a direct instances with its
|
13
|
+
# full name, if you prefer:
|
14
|
+
#
|
15
|
+
# api = Hive::CondenserApi.new
|
16
|
+
# api.get_dynamic_global_properties
|
17
|
+
#
|
18
|
+
# If you know the name of another API that is supported by the remote node,
|
19
|
+
# you can create an instance to that instead, for example:
|
20
|
+
#
|
21
|
+
# api = Hive::MarketHistoryApi.new
|
22
|
+
# api.get_volume
|
23
|
+
#
|
24
|
+
# All known API by namespace:
|
25
|
+
#
|
26
|
+
# * {AccountByKeyApi}
|
27
|
+
# * {AccountHistoryApi}
|
28
|
+
# * {BlockApi}
|
29
|
+
# * {DatabaseApi}
|
30
|
+
# * {FollowApi}
|
31
|
+
# * {Jsonrpc}
|
32
|
+
# * {MarketHistoryApi}
|
33
|
+
# * {NetworkBroadcastApi}
|
34
|
+
# * {TagsApi}
|
35
|
+
# * {WitnessApi}
|
36
|
+
#
|
37
|
+
# Also see: {https://developers.hive.io/apidefinitions/ Complete API Definitions}
|
38
|
+
class Api
|
39
|
+
attr_accessor :chain, :methods, :rpc_client
|
40
|
+
|
41
|
+
# Use this for debugging naive thread handler.
|
42
|
+
# DEFAULT_RPC_CLIENT_CLASS = RPC::HttpClient
|
43
|
+
DEFAULT_RPC_CLIENT_CLASS = RPC::ThreadSafeHttpClient
|
44
|
+
|
45
|
+
def self.api_name=(api_name)
|
46
|
+
@api_name = api_name.to_s.
|
47
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
48
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
49
|
+
tr('-', '_').downcase.to_sym
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.api_name
|
53
|
+
@api_name
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.api_class_name
|
57
|
+
@api_name.to_s.split('_').map(&:capitalize).join
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.jsonrpc=(jsonrpc, url = nil)
|
61
|
+
@jsonrpc ||= {}
|
62
|
+
@jsonrpc[url || jsonrpc.rpc_client.uri.to_s] = jsonrpc
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.jsonrpc(url = nil)
|
66
|
+
if @jsonrpc.size < 2 && url.nil?
|
67
|
+
@jsonrpc.values.first
|
68
|
+
else
|
69
|
+
@jsonrpc[url]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Override this if you want to just use your own client. Otherwise, inject
|
74
|
+
# the default using:
|
75
|
+
#
|
76
|
+
# Hive::Api.register default_rpc_client_class: MyClient
|
77
|
+
def self.default_rpc_client_class
|
78
|
+
if !!@injected_dependencies && !!@injected_dependencies[:default_rpc_client_class]
|
79
|
+
@injected_dependencies[:default_rpc_client_class]
|
80
|
+
else
|
81
|
+
DEFAULT_RPC_CLIENT_CLASS
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Used for dependency injection. Currently, the only key supported is:
|
86
|
+
#
|
87
|
+
# `default_rpc_client_class`
|
88
|
+
def self.register(register)
|
89
|
+
@injected_dependencies ||= {}
|
90
|
+
@injected_dependencies = @injected_dependencies.merge register
|
91
|
+
end
|
92
|
+
|
93
|
+
def initialize(options = {})
|
94
|
+
@chain = options[:chain] || :hive
|
95
|
+
@error_pipe = options[:error_pipe] || STDERR
|
96
|
+
@api_name = self.class.api_name ||= :condenser_api
|
97
|
+
|
98
|
+
@rpc_client = if !!options[:rpc_client]
|
99
|
+
options[:rpc_client]
|
100
|
+
else
|
101
|
+
rpc_client_class = self.class.default_rpc_client_class
|
102
|
+
rpc_client_class.new(options.merge(api_name: @api_name))
|
103
|
+
end
|
104
|
+
|
105
|
+
if @api_name == :jsonrpc
|
106
|
+
Api::jsonrpc = self
|
107
|
+
else
|
108
|
+
# Note, we have to wait until initialize to check this because we don't
|
109
|
+
# have access to instance options until now.
|
110
|
+
|
111
|
+
Api::jsonrpc = Jsonrpc.new(options)
|
112
|
+
|
113
|
+
@methods = begin
|
114
|
+
Api::jsonrpc(rpc_client.uri.to_s).get_api_methods
|
115
|
+
rescue => e
|
116
|
+
Fallback::API_METHODS
|
117
|
+
end
|
118
|
+
|
119
|
+
if Jsonrpc::UNLISTED_APIS.include? @api_name
|
120
|
+
@methods ||= {}
|
121
|
+
@methods[@api_name] ||= Fallback::API_METHODS[@api_name]
|
122
|
+
end
|
123
|
+
|
124
|
+
unless !!@methods[@api_name]
|
125
|
+
raise UnknownApiError, "#{@api_name} (known APIs: #{@methods.keys.join(' ')})"
|
126
|
+
end
|
127
|
+
|
128
|
+
@methods = @methods[@api_name]
|
129
|
+
end
|
130
|
+
|
131
|
+
@try_count = 0
|
132
|
+
end
|
133
|
+
|
134
|
+
def inspect
|
135
|
+
properties = %w(chain methods).map do |prop|
|
136
|
+
if !!(v = instance_variable_get("@#{prop}"))
|
137
|
+
case v
|
138
|
+
when Array then "@#{prop}=<#{v.size} #{v.size == 1 ? 'element' : 'elements'}>"
|
139
|
+
else; "@#{prop}=#{v}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end.compact.join(', ')
|
143
|
+
|
144
|
+
"#<#{self.class.api_class_name} [#{properties}]>"
|
145
|
+
end
|
146
|
+
private
|
147
|
+
# @private
|
148
|
+
def args_keys_to_s(rpc_method_name)
|
149
|
+
args = signature(rpc_method_name).args
|
150
|
+
args_keys = JSON[args.to_json]
|
151
|
+
end
|
152
|
+
|
153
|
+
# @private
|
154
|
+
def signature(rpc_method_name)
|
155
|
+
url = rpc_client.uri.to_s
|
156
|
+
|
157
|
+
@@signatures ||= {}
|
158
|
+
@@signatures[url] ||= {}
|
159
|
+
|
160
|
+
@@signatures[url][rpc_method_name] ||= begin
|
161
|
+
Api::jsonrpc(url).get_signature(method: rpc_method_name).result
|
162
|
+
rescue => e
|
163
|
+
Hashie::Mash.new({args: Fallback::API_METHOD_SIGNATURES[@api_name][rpc_method_name.split('.').last.to_sym]})
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# @private
|
168
|
+
def respond_to_missing?(m, include_private = false)
|
169
|
+
methods.nil? ? false : methods.include?(m.to_sym)
|
170
|
+
end
|
171
|
+
|
172
|
+
# @private
|
173
|
+
def method_missing(m, *args, &block)
|
174
|
+
super unless respond_to_missing?(m)
|
175
|
+
|
176
|
+
rpc_method_name = "#{@api_name}.#{m}"
|
177
|
+
rpc_args = case @api_name
|
178
|
+
when :condenser_api then args
|
179
|
+
when :jsonrpc then args.first
|
180
|
+
else
|
181
|
+
expected_args = signature(rpc_method_name).args || []
|
182
|
+
expected_args_key_string = if expected_args.size > 0
|
183
|
+
" (#{args_keys_to_s(rpc_method_name)})"
|
184
|
+
end
|
185
|
+
expected_args_size = expected_args.size
|
186
|
+
|
187
|
+
begin
|
188
|
+
args = args.first.to_h
|
189
|
+
args_size = args.size
|
190
|
+
|
191
|
+
# Some argument are optional, but if the arguments passed are greater
|
192
|
+
# than the expected arguments size, we can warn.
|
193
|
+
if args_size > expected_args_size
|
194
|
+
@error_pipe.puts "Warning #{rpc_method_name} expects arguments: #{expected_args_size}, got: #{args_size}"
|
195
|
+
end
|
196
|
+
rescue NoMethodError => e
|
197
|
+
error = Hive::ArgumentError.new("#{rpc_method_name} expects arguments: #{expected_args_size}", e)
|
198
|
+
raise error
|
199
|
+
rescue => e
|
200
|
+
raise UnknownError.new("#{rpc_method_name} unknown error.", e)
|
201
|
+
end
|
202
|
+
|
203
|
+
args
|
204
|
+
end
|
205
|
+
|
206
|
+
response = rpc_client.rpc_execute(@api_name, m, rpc_args)
|
207
|
+
|
208
|
+
if !!block
|
209
|
+
case response
|
210
|
+
when Hashie::Mash then yield response.result, response.error, response.id
|
211
|
+
when Hashie::Array
|
212
|
+
response.each do |r|
|
213
|
+
r = Hashie::Mash.new(r)
|
214
|
+
yield r.result, r.error, r.id
|
215
|
+
end
|
216
|
+
else; yield response
|
217
|
+
end
|
218
|
+
else
|
219
|
+
return response
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
module Hive
|
2
|
+
class BaseError < StandardError
|
3
|
+
def initialize(error = nil, cause = nil)
|
4
|
+
@error = error
|
5
|
+
@cause = cause
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
detail = {}
|
10
|
+
detail[:error] = @error if !!@error
|
11
|
+
detail[:cause] = @cause if !!@cause
|
12
|
+
|
13
|
+
JSON[detail] rescue detail.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.build_error(error, context)
|
17
|
+
if error.message == 'Unable to acquire database lock'
|
18
|
+
raise Hive::RemoteDatabaseLockError, error.message, build_backtrace(error)
|
19
|
+
end
|
20
|
+
|
21
|
+
if error.message.include? 'Internal Error'
|
22
|
+
raise Hive::RemoteNodeError, error.message, build_backtrace(error)
|
23
|
+
end
|
24
|
+
|
25
|
+
if error.message.include? 'Server error'
|
26
|
+
raise Hive::RemoteNodeError, error.message, build_backtrace(error)
|
27
|
+
end
|
28
|
+
|
29
|
+
if error.message.include? 'plugin not enabled'
|
30
|
+
raise Hive::PluginNotEnabledError, error.message, build_backtrace(error)
|
31
|
+
end
|
32
|
+
|
33
|
+
if error.message.include? 'argument'
|
34
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
35
|
+
end
|
36
|
+
|
37
|
+
if error.message.include? 'Invalid params'
|
38
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
39
|
+
end
|
40
|
+
|
41
|
+
if error.message.start_with? 'Bad Cast:'
|
42
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
43
|
+
end
|
44
|
+
|
45
|
+
if error.message.include? 'prefix_len'
|
46
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
47
|
+
end
|
48
|
+
|
49
|
+
if error.message.include? 'Parse Error'
|
50
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
51
|
+
end
|
52
|
+
|
53
|
+
if error.message.include? 'unknown key'
|
54
|
+
raise Hive::ArgumentError, "#{context}: #{error.message} (or content has been deleted)", build_backtrace(error)
|
55
|
+
end
|
56
|
+
|
57
|
+
if error.message.include? 'Comment is not in account\'s comments'
|
58
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
59
|
+
end
|
60
|
+
|
61
|
+
if error.message.include? 'Could not find comment'
|
62
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
63
|
+
end
|
64
|
+
|
65
|
+
if error.message.include? 'unable to convert ISO-formatted string to fc::time_point_sec'
|
66
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
67
|
+
end
|
68
|
+
|
69
|
+
if error.message.include? 'Input data have to treated as object.'
|
70
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
71
|
+
end
|
72
|
+
|
73
|
+
if error.message.include? 'base.amount > share_type(0)'
|
74
|
+
raise Hive::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
75
|
+
end
|
76
|
+
|
77
|
+
if error.message.include? 'blk->transactions.size() > itr->trx_in_block'
|
78
|
+
raise Hive::VirtualOperationsNotAllowedError, "#{context}: #{error.message}", build_backtrace(error)
|
79
|
+
end
|
80
|
+
|
81
|
+
if error.message.include? 'A transaction must have at least one operation'
|
82
|
+
raise Hive::EmptyTransactionError, "#{context}: #{error.message}", build_backtrace(error)
|
83
|
+
end
|
84
|
+
|
85
|
+
if error.message.include? 'transaction expiration exception'
|
86
|
+
raise Hive::TransactionExpiredError, "#{context}: #{error.message}", build_backtrace(error)
|
87
|
+
end
|
88
|
+
|
89
|
+
if error.message.include? 'Duplicate transaction check failed'
|
90
|
+
raise Hive::DuplicateTransactionError, "#{context}: #{error.message}", build_backtrace(error)
|
91
|
+
end
|
92
|
+
|
93
|
+
if error.message.include? 'signature is not canonical'
|
94
|
+
raise Hive::NonCanonicalSignatureError, "#{context}: #{error.message}", build_backtrace(error)
|
95
|
+
end
|
96
|
+
|
97
|
+
if error.message.include? 'attempting to push a block that is too old'
|
98
|
+
raise Hive::BlockTooOldError, "#{context}: #{error.message}", build_backtrace(error)
|
99
|
+
end
|
100
|
+
|
101
|
+
if error.message.include? 'irrelevant signature'
|
102
|
+
raise Hive::IrrelevantSignatureError, "#{context}: #{error.message}", build_backtrace(error)
|
103
|
+
end
|
104
|
+
|
105
|
+
if error.message.include? 'missing required posting authority'
|
106
|
+
raise Hive::MissingPostingAuthorityError, "#{context}: #{error.message}", build_backtrace(error)
|
107
|
+
end
|
108
|
+
|
109
|
+
if error.message.include? 'missing required active authority'
|
110
|
+
raise Hive::MissingActiveAuthorityError, "#{context}: #{error.message}", build_backtrace(error)
|
111
|
+
end
|
112
|
+
|
113
|
+
if error.message.include? 'missing required owner authority'
|
114
|
+
raise Hive::MissingOwnerAuthorityError, "#{context}: #{error.message}", build_backtrace(error)
|
115
|
+
end
|
116
|
+
|
117
|
+
if error.message.include? 'missing required other authority'
|
118
|
+
raise Hive::MissingOtherAuthorityError, "#{context}: #{error.message}", build_backtrace(error)
|
119
|
+
end
|
120
|
+
|
121
|
+
if error.message.include? 'Upstream response error'
|
122
|
+
raise Hive::UpstreamResponseError, "#{context}: #{error.message}", build_backtrace(error)
|
123
|
+
end
|
124
|
+
|
125
|
+
if error.message.include? 'Bad or missing upstream response'
|
126
|
+
raise Hive::BadOrMissingUpstreamResponseError, "#{context}: #{error.message}", build_backtrace(error)
|
127
|
+
end
|
128
|
+
|
129
|
+
if error.message.include? 'operator has disabled operation indexing by transaction_id'
|
130
|
+
raise Hive::TransactionIndexDisabledError, "#{context}: #{error.message}", build_backtrace(error)
|
131
|
+
end
|
132
|
+
|
133
|
+
if error.message.include? 'is_valid_account_name'
|
134
|
+
raise Hive::InvalidAccountError, "#{context}: #{error.message}", build_backtrace(error)
|
135
|
+
end
|
136
|
+
|
137
|
+
if error.message.include?('Method') && error.message.include?(' does not exist.')
|
138
|
+
raise Hive::UnknownMethodError, "#{context}: #{error.message}", build_backtrace(error)
|
139
|
+
end
|
140
|
+
|
141
|
+
if error.message.include? 'Invalid operation name'
|
142
|
+
raise Hive::UnknownOperationError, "#{context}: #{error.message}", build_backtrace(error)
|
143
|
+
end
|
144
|
+
|
145
|
+
if error.message =~ /Invalid object name: .+_operation/
|
146
|
+
raise Hive::UnknownOperationError, "#{context}: #{error.message}", build_backtrace(error)
|
147
|
+
end
|
148
|
+
|
149
|
+
if error.message.include? 'Author not found'
|
150
|
+
raise Hive::AuthorNotFoundError, "#{context}: #{error.message}", build_backtrace(error)
|
151
|
+
end
|
152
|
+
|
153
|
+
if error.message.include? ' != fc::time_point_sec::maximum()'
|
154
|
+
raise Hive::ReachedMaximumTimeError, "#{context}: #{error.message}", build_backtrace(error)
|
155
|
+
end
|
156
|
+
|
157
|
+
if error.message.include? 'Cannot transfer a negative amount (aka: stealing)'
|
158
|
+
raise Hive::TheftError, "#{context}: #{error.message}", build_backtrace(error)
|
159
|
+
end
|
160
|
+
|
161
|
+
if error.message.include? 'Must transfer a nonzero amount'
|
162
|
+
raise Hive::NonZeroRequiredError, "#{context}: #{error.message}", build_backtrace(error)
|
163
|
+
end
|
164
|
+
|
165
|
+
if error.message.include? 'is_asset_type'
|
166
|
+
raise Hive::UnexpectedAssetError, "#{context}: #{error.message}", build_backtrace(error)
|
167
|
+
end
|
168
|
+
|
169
|
+
puts JSON.pretty_generate(error) if ENV['DEBUG']
|
170
|
+
raise UnknownError, "#{context}: #{error.message}", build_backtrace(error)
|
171
|
+
end
|
172
|
+
private
|
173
|
+
def self.build_backtrace(error)
|
174
|
+
backtrace = Thread.current.backtrace.reject{ |line| line =~ /base_error/ }
|
175
|
+
JSON.pretty_generate(error) + "\n" + backtrace.join("\n")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class DeserializationError < BaseError; end
|
180
|
+
class SerializationMismatchError < BaseError; end
|
181
|
+
class UnsupportedChainError < BaseError; end
|
182
|
+
class ArgumentError < BaseError; end
|
183
|
+
class TypeError < BaseError; end
|
184
|
+
class EmptyTransactionError < ArgumentError; end
|
185
|
+
class InvalidAccountError < ArgumentError; end
|
186
|
+
class AuthorNotFoundError < ArgumentError; end
|
187
|
+
class ReachedMaximumTimeError < ArgumentError; end
|
188
|
+
class VirtualOperationsNotAllowedError < ArgumentError; end
|
189
|
+
class TheftError < ArgumentError; end
|
190
|
+
class NonZeroRequiredError < ArgumentError; end
|
191
|
+
class UnexpectedAssetError < ArgumentError; end
|
192
|
+
class TransactionExpiredError < BaseError; end
|
193
|
+
class DuplicateTransactionError < TransactionExpiredError; end
|
194
|
+
class NonCanonicalSignatureError < TransactionExpiredError; end
|
195
|
+
class BlockTooOldError < BaseError; end
|
196
|
+
class IrrelevantSignatureError < BaseError; end
|
197
|
+
class MissingAuthorityError < BaseError; end
|
198
|
+
class MissingPostingAuthorityError < MissingAuthorityError; end
|
199
|
+
class MissingActiveAuthorityError < MissingAuthorityError; end
|
200
|
+
class MissingOwnerAuthorityError < MissingAuthorityError; end
|
201
|
+
class MissingOtherAuthorityError < MissingAuthorityError; end
|
202
|
+
class IncorrectRequestIdError < BaseError; end
|
203
|
+
class IncorrectResponseIdError < BaseError; end
|
204
|
+
class RemoteNodeError < BaseError; end
|
205
|
+
class UpstreamResponseError < RemoteNodeError; end
|
206
|
+
class RemoteDatabaseLockError < UpstreamResponseError; end
|
207
|
+
class PluginNotEnabledError < UpstreamResponseError; end
|
208
|
+
class BadOrMissingUpstreamResponseError < UpstreamResponseError; end
|
209
|
+
class TransactionIndexDisabledError < BaseError; end
|
210
|
+
class NotAppBaseError < BaseError; end
|
211
|
+
class UnknownApiError < BaseError; end
|
212
|
+
class UnknownMethodError < BaseError; end
|
213
|
+
class UnknownOperationError < BaseError; end
|
214
|
+
class JsonRpcBatchMaximumSizeExceededError < BaseError; end
|
215
|
+
class TooManyTimeoutsError < BaseError; end
|
216
|
+
class TooManyRetriesError < BaseError; end
|
217
|
+
class UnknownError < BaseError; end
|
218
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Hive
|
2
|
+
# {BlockApi} is used to query values related to the block plugin. It can also
|
3
|
+
# be used to access a range of multiple blocks by using
|
4
|
+
# {http://www.jsonrpc.org/specification#batch JSON-RPC 2.0 batch} requests.
|
5
|
+
#
|
6
|
+
# Also see: {https://developers.hive.io/apidefinitions/block-api.html Block API Definitions}
|
7
|
+
class BlockApi < Api
|
8
|
+
MAX_RANGE_SIZE = 50
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
self.class.api_name = :block_api
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
# Uses a batched requst on a range of block headers.
|
16
|
+
#
|
17
|
+
# @param options [Hash] The attributes to get a block range with.
|
18
|
+
# @option options [Range] :block_range starting on one block number and ending on an higher block number.
|
19
|
+
def get_block_headers(options = {block_range: (0..0)}, &block)
|
20
|
+
get_block_objects(options.merge(object: :block_header), block)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Uses a batched requst on a range of blocks.
|
24
|
+
#
|
25
|
+
# @param options [Hash] The attributes to get a block range with.
|
26
|
+
# @option options [Range] :block_range starting on one block number and ending on an higher block number.
|
27
|
+
def get_blocks(options = {block_range: (0..0)}, &block)
|
28
|
+
get_block_objects(options.merge(object: :block), block)
|
29
|
+
end
|
30
|
+
private
|
31
|
+
def get_block_objects(options = {block_range: (0..0)}, block = nil)
|
32
|
+
object = options[:object]
|
33
|
+
object_method = "get_#{object}".to_sym
|
34
|
+
block_range = options[:block_range] || (0..0)
|
35
|
+
|
36
|
+
if (start = block_range.first) < 1
|
37
|
+
raise Hive::ArgumentError, "Invalid starting block: #{start}"
|
38
|
+
end
|
39
|
+
|
40
|
+
chunks = if block_range.size > MAX_RANGE_SIZE
|
41
|
+
block_range.each_slice(MAX_RANGE_SIZE)
|
42
|
+
else
|
43
|
+
[block_range]
|
44
|
+
end
|
45
|
+
|
46
|
+
for sub_range in chunks do
|
47
|
+
request_object = []
|
48
|
+
|
49
|
+
for i in sub_range do
|
50
|
+
@rpc_client.put(self.class.api_name, object_method, block_num: i, request_object: request_object)
|
51
|
+
end
|
52
|
+
|
53
|
+
if !!block
|
54
|
+
index = 0
|
55
|
+
@rpc_client.rpc_batch_execute(request_object: request_object) do |result, error, id|
|
56
|
+
block_num = sub_range.to_a[index]
|
57
|
+
index = index + 1
|
58
|
+
|
59
|
+
case object
|
60
|
+
when :block_header
|
61
|
+
block.call(result.nil? ? nil : result[:header], block_num)
|
62
|
+
else
|
63
|
+
block.call(result.nil? ? nil : result[object], block_num)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
else
|
67
|
+
blocks = []
|
68
|
+
|
69
|
+
@rpc_client.rpc_batch_execute(request_object: request_object) do |result, error, id|
|
70
|
+
blocks << result
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
blocks
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|