steem-ruby 0.9.0 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -1
  3. data/README.md +88 -15
  4. data/Rakefile +128 -31
  5. data/lib/steem.rb +49 -0
  6. data/lib/steem/api.rb +39 -37
  7. data/lib/steem/base_error.rb +80 -41
  8. data/lib/steem/block_api.rb +23 -3
  9. data/lib/steem/broadcast.rb +465 -29
  10. data/lib/steem/chain_config.rb +3 -3
  11. data/lib/steem/marshal.rb +231 -0
  12. data/lib/steem/mixins/jsonable.rb +37 -0
  13. data/lib/steem/mixins/retriable.rb +30 -24
  14. data/lib/steem/mixins/serializable.rb +45 -0
  15. data/lib/steem/operation.rb +141 -0
  16. data/lib/steem/operation/account_create.rb +10 -0
  17. data/lib/steem/operation/account_create_with_delegation.rb +12 -0
  18. data/lib/steem/operation/account_update.rb +8 -0
  19. data/lib/steem/operation/account_witness_proxy.rb +4 -0
  20. data/lib/steem/operation/account_witness_vote.rb +5 -0
  21. data/lib/steem/operation/cancel_transfer_from_savings.rb +4 -0
  22. data/lib/steem/operation/challenge_authority.rb +5 -0
  23. data/lib/steem/operation/change_recovery_account.rb +5 -0
  24. data/lib/steem/operation/claim_account.rb +5 -0
  25. data/lib/steem/operation/claim_reward_balance.rb +6 -0
  26. data/lib/steem/operation/comment.rb +9 -0
  27. data/lib/steem/operation/comment_options.rb +10 -0
  28. data/lib/steem/operation/convert.rb +5 -0
  29. data/lib/steem/operation/create_claimed_account.rb +10 -0
  30. data/lib/steem/operation/custom.rb +5 -0
  31. data/lib/steem/operation/custom_binary.rb +8 -0
  32. data/lib/steem/operation/custom_json.rb +6 -0
  33. data/lib/steem/operation/decline_voting_rights.rb +4 -0
  34. data/lib/steem/operation/delegate_vesting_shares.rb +5 -0
  35. data/lib/steem/operation/delete_comment.rb +4 -0
  36. data/lib/steem/operation/escrow_approve.rb +8 -0
  37. data/lib/steem/operation/escrow_dispute.rb +7 -0
  38. data/lib/steem/operation/escrow_release.rb +10 -0
  39. data/lib/steem/operation/escrow_transfer.rb +12 -0
  40. data/lib/steem/operation/feed_publish.rb +4 -0
  41. data/lib/steem/operation/limit_order_cancel.rb +4 -0
  42. data/lib/steem/operation/limit_order_create.rb +8 -0
  43. data/lib/steem/operation/limit_order_create2.rb +8 -0
  44. data/lib/steem/operation/prove_authority.rb +4 -0
  45. data/lib/steem/operation/recover_account.rb +6 -0
  46. data/lib/steem/operation/report_over_production.rb +5 -0
  47. data/lib/steem/operation/request_account_recovery.rb +6 -0
  48. data/lib/steem/operation/reset_account.rb +5 -0
  49. data/lib/steem/operation/set_reset_account.rb +5 -0
  50. data/lib/steem/operation/set_withdraw_vesting_route.rb +6 -0
  51. data/lib/steem/operation/transfer.rb +6 -0
  52. data/lib/steem/operation/transfer_from_savings.rb +7 -0
  53. data/lib/steem/operation/transfer_to_savings.rb +6 -0
  54. data/lib/steem/operation/transfer_to_vesting.rb +5 -0
  55. data/lib/steem/operation/vote.rb +6 -0
  56. data/lib/steem/operation/withdraw_vesting.rb +4 -0
  57. data/lib/steem/operation/witness_set_properties.rb +5 -0
  58. data/lib/steem/operation/witness_update.rb +7 -0
  59. data/lib/steem/rpc/base_client.rb +16 -4
  60. data/lib/steem/rpc/http_client.rb +18 -2
  61. data/lib/steem/stream.rb +385 -0
  62. data/lib/steem/transaction.rb +96 -0
  63. data/lib/steem/transaction_builder.rb +176 -103
  64. data/lib/steem/type/amount.rb +61 -9
  65. data/lib/steem/version.rb +1 -1
  66. data/steem-ruby.gemspec +9 -4
  67. metadata +203 -56
  68. data/Gemfile.lock +0 -73
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4c0d2e4cfae2885bc24acaa7d2a5f046e73a1505
4
- data.tar.gz: ddfdd7c5505ada6ea5e67584e51f6b5241e74bb6
2
+ SHA256:
3
+ metadata.gz: 6ee068c00342f904efe37abe6e2cafa9332b1221cac3598071aefab473cfe996
4
+ data.tar.gz: b84eb953f450d52ebabfb1417b2e46a0154aeb8a1066981dcee937480b761632
5
5
  SHA512:
6
- metadata.gz: ec9da3a5222a1ef5bf503ab496eeb12b88609ff1b76d0fd888ca10a355fa3bf0c1bea497a75327a5922a7b002d7b8f19d38eb9b047b431d5fa532eea740c3fa3
7
- data.tar.gz: 3a3aac4b912eeb02c92c97b9e74be3c747595b0acfffd75318258d4b89b99b1569776ff9aa4d7393aa0176b45b2170f5723195aafc87729ae7e22f9cb733d944
6
+ metadata.gz: 824809d5a78d22ac1d15c812537e4c6fa11e85e56920cee365c18c18efc932ba7b265f049462407dd3acae1f460e912f0f582d6f2b05f07ebae8075a8c25b02a
7
+ data.tar.gz: b5fd1bb775ec114939ac338e9f4a83dee337af072b17d435475c420b84b272880bc5847ab3cb8b88f6f689e661fb2897ac729cc6d540ea8ac1fff1073bba69bc
data/.gitignore CHANGED
@@ -43,7 +43,7 @@ build-iPhoneSimulator/
43
43
 
44
44
  # for a library or gem, you might want to ignore these files since the code is
45
45
  # intended to run in multiple environments; otherwise, check them in:
46
- # Gemfile.lock
46
+ Gemfile.lock
47
47
  # .ruby-version
48
48
  # .ruby-gemset
49
49
 
data/README.md CHANGED
@@ -13,17 +13,17 @@ Full documentation: http://www.rubydoc.info/gems/steem-ruby
13
13
 
14
14
  The `steem-ruby` gem was written from the ground up by `@inertia`, who is also the author of [`radiator`](https://github.com/inertia186/radiator).
15
15
 
16
- > "I intend to continue work on `radiator` indefinitely. But in `radiator-0.5`, I intend to refactor `radiator` so that is uses `steem-ruby` as its core. This means that some features of `radiator` like Serialization will become redundant. I think it's still useful for radiator to do its own serialzation because it reduces the number of API requests." - @inertia
17
-
18
- | `radiator` | `steem-ruby` |
19
- |-|-|
20
- | Has internal failover logic | Can have failover delegated externally |
21
- | Passes `error` responses to the caller | Handles `error` responses and raises exceptions |
22
- | Supports tx signing, does its own serialization | Also supports tx signing, but delegates serialization to `database_api.get_transaction_hex` |
23
- | All apis and methods are hardcoded | Asks `jsonrpc` what apis and methods are available from the node |
24
- | (`radiator-0.4.x`) Only supports AppBase but relies on `condenser_api` | Only supports AppBase but does not rely on `condenser_api` **(WIP)**
25
- | Small list of helper methods for select ops (in addition to build your own transaction) | Complete implementation of helper methods for every op (in addition to build your own transaction) |
26
- | Does not (yet) support `json-rpc-batch` requests | Supports `json-rpc-batch` requests |
16
+ > "I intend to continue work on `radiator` indefinitely. But in `radiator-0.5`, I intend to refactor `radiator` so that is uses `steem-ruby` as its core. This means that some features of `radiator` like Serialization will become redundant. I think it's still useful for radiator to do its own serialization because it reduces the number of API requests." - @inertia
17
+
18
+ `radiator` | `steem-ruby`
19
+ ---------- | ------------
20
+ Has internal failover logic | Can have failover delegated externally
21
+ Passes `error` responses to the caller | Handles `error` responses and raises exceptions
22
+ Supports tx signing, does its own serialization | Also supports tx signing, but delegates serialization to `database_api.get_transaction_hex`, then deserializes to verify
23
+ All apis and methods are hardcoded | Asks `jsonrpc` what apis and methods are available from the node
24
+ (`radiator-0.4.x`) Only supports AppBase but relies on `condenser_api` | Only supports AppBase but does not rely on `condenser_api` **(WIP)**
25
+ Small list of helper methods for select ops (in addition to build your own transaction) | Complete implementation of helper methods for every op (in addition to build your own transaction)
26
+ Does not (yet) support `json-rpc-batch` requests | Supports `json-rpc-batch` requests
27
27
 
28
28
  ## Getting Started
29
29
 
@@ -70,6 +70,79 @@ end
70
70
 
71
71
  *See: [Broadcast](https://www.rubydoc.info/gems/steem-ruby/Steem/Broadcast)*
72
72
 
73
+ ### Streaming
74
+
75
+ The value passed to the block is an object, with the keys: `:type` and `:value`.
76
+
77
+ ```ruby
78
+ stream = Steem::Stream.new
79
+
80
+ stream.operations do |op|
81
+ puts "#{op.type}: #{op.value}"
82
+ end
83
+ ```
84
+
85
+ To start a stream from a specific block number, pass it as an argument:
86
+
87
+ ```ruby
88
+ stream = Steem::Stream.new
89
+
90
+ stream.operations(at_block_num: 9001) do |op|
91
+ puts "#{op.type}: #{op.value}"
92
+ end
93
+ ```
94
+
95
+ You can also grab the related transaction id and block number for each operation:
96
+
97
+ ```ruby
98
+ stream = Steem::Stream.new
99
+
100
+ stream.operations do |op, trx_id, block_num|
101
+ puts "#{block_num} :: #{trx_id}"
102
+ puts "#{op.type}: #{op.value}"
103
+ end
104
+ ```
105
+
106
+ To stream only certain operations:
107
+
108
+ ```ruby
109
+ stream = Steem::Stream.new
110
+
111
+ stream.operations(types: :vote_operation) do |op|
112
+ puts "#{op.type}: #{op.value}"
113
+ end
114
+ ```
115
+
116
+ Or pass an array of certain operations:
117
+
118
+ ```ruby
119
+ stream = Steem::Stream.new
120
+
121
+ stream.operations(types: [:comment_operation, :vote_operation]) do |op|
122
+ puts "#{op.type}: #{op.value}"
123
+ end
124
+ ```
125
+
126
+ Or (optionally) just pass the operation(s) you want as the only arguments. This is semantic sugar for when you want specific types and take all of the defaults.
127
+
128
+ ```ruby
129
+ stream = Steem::Stream.new
130
+
131
+ stream.operations(:vote_operation) do |op|
132
+ puts "#{op.type}: #{op.value}"
133
+ end
134
+ ```
135
+
136
+ To also include virtual operations:
137
+
138
+ ```ruby
139
+ stream = Steem::Stream.new
140
+
141
+ stream.operations(include_virtual: true) do |op|
142
+ puts "#{op.type}: #{op.value}"
143
+ end
144
+ ```
145
+
73
146
  ### Multisig
74
147
 
75
148
  You can use multisignature to broadcast an operation.
@@ -90,7 +163,7 @@ end
90
163
  In addition to signing with multiple `wif` private keys, it is possible to also export a partially signed transaction to have signing completed by someone else.
91
164
 
92
165
  ```ruby
93
- builder = TransactionBuilder.new(wif: wif1)
166
+ builder = Steem::TransactionBuilder.new(wif: wif1)
94
167
 
95
168
  builder.put(vote: {
96
169
  voter: voter,
@@ -110,10 +183,10 @@ Then send the contents of `trx.json` to the other signing party so they can priv
110
183
 
111
184
  ```ruby
112
185
  trx = open('trx.json').read
113
- builder = TransactionBuilder.new(wif: wif2, trx: trx)
114
- api = Steem::NetworkBroadcastApi.new
186
+ builder = Steem::TransactionBuilder.new(wif: wif2, trx: trx)
187
+ api = Steem::CondenserApi.new
115
188
  trx = builder.transaction
116
- api.broadcast_transaction_synchronous(trx: trx)
189
+ api.broadcast_transaction_synchronous(trx)
117
190
  ```
118
191
 
119
192
  ### Get Accounts
data/Rakefile CHANGED
@@ -138,44 +138,141 @@ end
138
138
 
139
139
  namespace :stream do
140
140
  desc 'Test the ability to stream a block range.'
141
- task :block_range do
142
- block_api = Steem::BlockApi.new(url: ENV['TEST_NODE'])
141
+ task :block_range, [:mode, :at_block_num] do |t, args|
142
+ mode = (args[:mode] || 'irreversible').to_sym
143
+ first_block_num = args[:at_block_num].to_i if !!args[:at_block_num]
144
+ stream = Steem::Stream.new(url: ENV['TEST_NODE'], mode: mode)
143
145
  api = Steem::Api.new(url: ENV['TEST_NODE'])
144
146
  last_block_num = nil
145
- first_block_num = nil
146
147
  last_timestamp = nil
148
+ range_complete = false
147
149
 
148
- loop do
149
- api.get_dynamic_global_properties do |properties|
150
- current_block_num = properties.last_irreversible_block_num
151
- # First pass replays latest a random number of blocks to test chunking.
152
- first_block_num ||= current_block_num - (rand * 200).to_i
150
+ api.get_dynamic_global_properties do |properties|
151
+ current_block_num = if mode == :head
152
+ properties.head_block_number
153
+ else
154
+ properties.last_irreversible_block_num
155
+ end
156
+
157
+ # First pass replays latest a random number of blocks to test chunking.
158
+ first_block_num ||= current_block_num - (rand * 200).to_i
159
+
160
+ range = first_block_num..current_block_num
161
+ puts "Initial block range: #{range.size}"
162
+
163
+ stream.blocks(at_block_num: range.first) do |block, block_num|
164
+ current_timestamp = Time.parse(block.timestamp + 'Z')
153
165
 
154
- if current_block_num >= first_block_num
155
- range = first_block_num..current_block_num
156
- puts "Got block range: #{range.size}"
157
- block_api.get_blocks(block_range: range) do |block, block_num|
158
- current_timestamp = Time.parse(block.timestamp + 'Z')
159
-
160
- if !!last_timestamp && block_num != last_block_num + 1
161
- puts "Bug: Last block number was #{last_block_num} then jumped to: #{block_num}"
162
- exit
163
- end
164
-
165
- if !!last_timestamp && current_timestamp < last_timestamp
166
- puts "Bug: Went back in time. Last timestamp was #{last_timestamp}, then jumped back to #{current_timestamp}"
167
- exit
168
- end
169
-
170
- puts "\t#{block_num} Timestamp: #{current_timestamp}, witness: #{block.witness}"
171
- last_block_num = block_num
172
- last_timestamp = current_timestamp
173
- end
174
-
175
- first_block_num = range.max + 1
166
+ if !range_complete && block_num > range.last
167
+ puts 'Done with initial range.'
168
+ range_complete = true
176
169
  end
177
170
 
178
- sleep 3
171
+ if !!last_timestamp && block_num != last_block_num + 1
172
+ puts "Bug: Last block number was #{last_block_num} then jumped to: #{block_num}"
173
+ exit
174
+ end
175
+
176
+ if !!last_timestamp && current_timestamp < last_timestamp
177
+ puts "Bug: Went back in time. Last timestamp was #{last_timestamp}, then jumped back to #{current_timestamp}"
178
+ exit
179
+ end
180
+
181
+ puts "\t#{block_num} Timestamp: #{current_timestamp}, witness: #{block.witness}"
182
+ last_block_num = block_num
183
+ last_timestamp = current_timestamp
184
+ end
185
+ end
186
+ end
187
+
188
+ desc 'Test the ability to stream a block range of transactions.'
189
+ task :trx_range, [:mode, :at_block_num] do |t, args|
190
+ mode = (args[:mode] || 'irreversible').to_sym
191
+ first_block_num = args[:at_block_num].to_i if !!args[:at_block_num]
192
+ stream = Steem::Stream.new(url: ENV['TEST_NODE'], mode: mode)
193
+ api = Steem::Api.new(url: ENV['TEST_NODE'])
194
+
195
+ api.get_dynamic_global_properties do |properties|
196
+ current_block_num = if mode == :head
197
+ properties.head_block_number
198
+ else
199
+ properties.last_irreversible_block_num
200
+ end
201
+
202
+ # First pass replays latest a random number of blocks to test chunking.
203
+ first_block_num ||= current_block_num - (rand * 200).to_i
204
+
205
+ stream.transactions(at_block_num: first_block_num) do |trx, trx_id, block_num|
206
+ puts "#{block_num} :: #{trx_id}; ops: #{trx.operations.map(&:type).join(', ')}"
207
+ end
208
+ end
209
+ end
210
+
211
+ desc 'Test the ability to stream a block range of operations.'
212
+ task :op_range, [:mode, :at_block_num] do |t, args|
213
+ mode = (args[:mode] || 'irreversible').to_sym
214
+ first_block_num = args[:at_block_num].to_i if !!args[:at_block_num]
215
+ stream = Steem::Stream.new(url: ENV['TEST_NODE'], mode: mode)
216
+ api = Steem::Api.new(url: ENV['TEST_NODE'])
217
+
218
+ api.get_dynamic_global_properties do |properties|
219
+ current_block_num = if mode == :head
220
+ properties.head_block_number
221
+ else
222
+ properties.last_irreversible_block_num
223
+ end
224
+
225
+ # First pass replays latest a random number of blocks to test chunking.
226
+ first_block_num ||= current_block_num - (rand * 200).to_i
227
+
228
+ stream.operations(at_block_num: first_block_num) do |op, trx_id, block_num|
229
+ puts "#{block_num} :: #{trx_id}; op: #{op.type}"
230
+ end
231
+ end
232
+ end
233
+
234
+ desc 'Test the ability to stream a block range of virtual operations.'
235
+ task :vop_range, [:mode, :at_block_num] do |t, args|
236
+ mode = (args[:mode] || 'irreversible').to_sym
237
+ first_block_num = args[:at_block_num].to_i if !!args[:at_block_num]
238
+ stream = Steem::Stream.new(url: ENV['TEST_NODE'], mode: mode)
239
+ api = Steem::Api.new(url: ENV['TEST_NODE'])
240
+
241
+ api.get_dynamic_global_properties do |properties|
242
+ current_block_num = if mode == :head
243
+ properties.head_block_number
244
+ else
245
+ properties.last_irreversible_block_num
246
+ end
247
+
248
+ # First pass replays latest a random number of blocks to test chunking.
249
+ first_block_num ||= current_block_num - (rand * 200).to_i
250
+
251
+ stream.operations(at_block_num: first_block_num, only_virtual: true) do |op, trx_id, block_num|
252
+ puts "#{block_num} :: #{trx_id}; op: #{op.type}"
253
+ end
254
+ end
255
+ end
256
+
257
+ desc 'Test the ability to stream a block range of all operations (including virtual).'
258
+ task :all_op_range, [:mode, :at_block_num] do |t, args|
259
+ mode = (args[:mode] || 'irreversible').to_sym
260
+ first_block_num = args[:at_block_num].to_i if !!args[:at_block_num]
261
+ stream = Steem::Stream.new(url: ENV['TEST_NODE'], mode: mode)
262
+ api = Steem::Api.new(url: ENV['TEST_NODE'])
263
+
264
+ api.get_dynamic_global_properties do |properties|
265
+ current_block_num = if mode == :head
266
+ properties.head_block_number
267
+ else
268
+ properties.last_irreversible_block_num
269
+ end
270
+
271
+ # First pass replays latest a random number of blocks to test chunking.
272
+ first_block_num ||= current_block_num - (rand * 200).to_i
273
+
274
+ stream.operations(at_block_num: first_block_num, include_virtual: true) do |op, trx_id, block_num|
275
+ puts "#{block_num} :: #{trx_id}; op: #{op.type}"
179
276
  end
180
277
  end
181
278
  end
@@ -6,10 +6,58 @@ require 'hashie'
6
6
  require 'steem/version'
7
7
  require 'steem/utils'
8
8
  require 'steem/base_error'
9
+ require 'steem/mixins/serializable'
10
+ require 'steem/mixins/jsonable'
9
11
  require 'steem/mixins/retriable'
10
12
  require 'steem/chain_config'
11
13
  require 'steem/type/base_type'
12
14
  require 'steem/type/amount'
15
+ require 'steem/operation'
16
+ require 'steem/operation/account_create.rb'
17
+ require 'steem/operation/account_create_with_delegation.rb'
18
+ require 'steem/operation/account_update.rb'
19
+ require 'steem/operation/account_witness_proxy.rb'
20
+ require 'steem/operation/account_witness_vote.rb'
21
+ require 'steem/operation/cancel_transfer_from_savings.rb'
22
+ require 'steem/operation/challenge_authority.rb'
23
+ require 'steem/operation/change_recovery_account.rb'
24
+ require 'steem/operation/claim_account.rb'
25
+ require 'steem/operation/claim_reward_balance.rb'
26
+ require 'steem/operation/comment.rb'
27
+ require 'steem/operation/comment_options.rb'
28
+ require 'steem/operation/convert.rb'
29
+ require 'steem/operation/create_claimed_account.rb'
30
+ require 'steem/operation/custom.rb'
31
+ require 'steem/operation/custom_binary.rb'
32
+ require 'steem/operation/custom_json.rb'
33
+ require 'steem/operation/decline_voting_rights.rb'
34
+ require 'steem/operation/delegate_vesting_shares.rb'
35
+ require 'steem/operation/delete_comment.rb'
36
+ require 'steem/operation/escrow_approve.rb'
37
+ require 'steem/operation/escrow_dispute.rb'
38
+ require 'steem/operation/escrow_release.rb'
39
+ require 'steem/operation/escrow_transfer.rb'
40
+ require 'steem/operation/feed_publish.rb'
41
+ require 'steem/operation/limit_order_cancel.rb'
42
+ require 'steem/operation/limit_order_create.rb'
43
+ require 'steem/operation/limit_order_create2.rb'
44
+ require 'steem/operation/prove_authority.rb'
45
+ require 'steem/operation/recover_account.rb'
46
+ require 'steem/operation/report_over_production.rb'
47
+ require 'steem/operation/request_account_recovery.rb'
48
+ require 'steem/operation/reset_account.rb'
49
+ require 'steem/operation/set_reset_account.rb'
50
+ require 'steem/operation/set_withdraw_vesting_route.rb'
51
+ require 'steem/operation/transfer.rb'
52
+ require 'steem/operation/transfer_from_savings.rb'
53
+ require 'steem/operation/transfer_to_savings.rb'
54
+ require 'steem/operation/transfer_to_vesting.rb'
55
+ require 'steem/operation/vote.rb'
56
+ require 'steem/operation/withdraw_vesting.rb'
57
+ require 'steem/operation/witness_update.rb'
58
+ require 'steem/operation/witness_set_properties.rb'
59
+ require 'steem/marshal'
60
+ require 'steem/transaction'
13
61
  require 'steem/transaction_builder'
14
62
  require 'steem/rpc/base_client'
15
63
  require 'steem/rpc/http_client'
@@ -19,6 +67,7 @@ require 'steem/jsonrpc'
19
67
  require 'steem/block_api'
20
68
  require 'steem/formatter'
21
69
  require 'steem/broadcast'
70
+ require 'steem/stream'
22
71
 
23
72
  module Steem
24
73
  def self.api_classes
@@ -1,6 +1,6 @@
1
1
  module Steem
2
2
  # This ruby API works with
3
- # {https://github.com/steemit/steem/releases steemd-0.19.4} and other AppBase
3
+ # {https://github.com/steemit/steem/releases steemd-0.19.10} and other AppBase
4
4
  # compatible upstreams. To access different API namespaces, use the
5
5
  # following:
6
6
  #
@@ -36,10 +36,10 @@ module Steem
36
36
  #
37
37
  # Also see: {https://developers.steem.io/apidefinitions/ Complete API Definitions}
38
38
  class Api
39
- attr_accessor :chain, :methods
39
+ attr_accessor :chain, :methods, :rpc_client
40
40
 
41
41
  # Use this for debugging naive thread handler.
42
- # DEFAULT_RPC_CLIENT_CLASS = RPC::BaseClient
42
+ # DEFAULT_RPC_CLIENT_CLASS = RPC::HttpClient
43
43
  DEFAULT_RPC_CLIENT_CLASS = RPC::ThreadSafeHttpClient
44
44
 
45
45
  def self.api_name=(api_name)
@@ -57,17 +57,37 @@ module Steem
57
57
  @api_name.to_s.split('_').map(&:capitalize).join
58
58
  end
59
59
 
60
- def self.jsonrpc=(jsonrpc)
61
- @jsonrpc = jsonrpc
60
+ def self.jsonrpc=(jsonrpc, url = nil)
61
+ @jsonrpc ||= {}
62
+ @jsonrpc[url || jsonrpc.rpc_client.uri.to_s] = jsonrpc
62
63
  end
63
64
 
64
- def self.jsonrpc
65
- @jsonrpc
65
+ def self.jsonrpc(url = nil)
66
+ if @jsonrpc.size < 2 && url.nil?
67
+ @jsonrpc.values.first
68
+ else
69
+ @jsonrpc[url]
70
+ end
66
71
  end
67
72
 
68
- # Override this if you want to use your own client.
73
+ # Override this if you want to just use your own client. Otherwise, inject
74
+ # the default using:
75
+ #
76
+ # Steem::Api.register default_rpc_client_class: MyClient
69
77
  def self.default_rpc_client_class
70
- 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
71
91
  end
72
92
 
73
93
  def initialize(options = {})
@@ -89,7 +109,7 @@ module Steem
89
109
  # have access to instance options until now.
90
110
 
91
111
  Api::jsonrpc = Jsonrpc.new(options)
92
- @methods = Api::jsonrpc.get_api_methods
112
+ @methods = Api::jsonrpc(rpc_client.uri.to_s).get_api_methods
93
113
 
94
114
  unless !!@methods[@api_name]
95
115
  raise UnknownApiError, "#{@api_name} (known APIs: #{@methods.keys.join(' ')})"
@@ -115,28 +135,18 @@ module Steem
115
135
  end
116
136
  private
117
137
  # @private
118
- def self.args_keys_to_s(rpc_method_name)
138
+ def args_keys_to_s(rpc_method_name)
119
139
  args = signature(rpc_method_name).args
120
140
  args_keys = JSON[args.to_json]
121
141
  end
122
142
 
123
143
  # @private
124
- def self.signature(rpc_method_name)
125
- @@signatures ||= {}
126
- @@signatures[rpc_method_name] ||= jsonrpc.get_signature(method: rpc_method_name).result
127
- end
128
-
129
- # @private
130
- def self.raise_error_response(rpc_method_name, rpc_args, response)
131
- raise UnknownError, "#{rpc_method_name}: #{response}" if response.error.nil?
132
-
133
- error = response.error
134
-
135
- if error.message == 'Invalid Request'
136
- raise Steem::ArgumentError, "Unexpected arguments: #{rpc_args.inspect}. Expected: #{rpc_method_name} (#{args_keys_to_s(rpc_method_name)})"
137
- end
144
+ def signature(rpc_method_name)
145
+ url = rpc_client.uri.to_s
138
146
 
139
- BaseError.build_error(error, rpc_method_name)
147
+ @@signatures ||= {}
148
+ @@signatures[url] ||= {}
149
+ @@signatures[url][rpc_method_name] ||= Api::jsonrpc(url).get_signature(method: rpc_method_name).result
140
150
  end
141
151
 
142
152
  # @private
@@ -153,9 +163,9 @@ module Steem
153
163
  when :condenser_api then args
154
164
  when :jsonrpc then args.first
155
165
  else
156
- expected_args = Api::signature(rpc_method_name).args || []
166
+ expected_args = signature(rpc_method_name).args || []
157
167
  expected_args_key_string = if expected_args.size > 0
158
- " (#{Api::args_keys_to_s(rpc_method_name)})"
168
+ " (#{args_keys_to_s(rpc_method_name)})"
159
169
  end
160
170
  expected_args_size = expected_args.size
161
171
 
@@ -178,15 +188,7 @@ module Steem
178
188
  args
179
189
  end
180
190
 
181
- response = @rpc_client.rpc_execute(@api_name, m, rpc_args)
182
-
183
- if defined?(response.error) && !!response.error
184
- if !!response.error.message
185
- Api::raise_error_response rpc_method_name, rpc_args, response
186
- else
187
- raise Steem::ArgumentError, response.error.inspect
188
- end
189
- end
191
+ response = rpc_client.rpc_execute(@api_name, m, rpc_args)
190
192
 
191
193
  if !!block
192
194
  case response