steem-ruby 0.9.3 → 0.9.4

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +9 -5
  3. data/README.md +10 -10
  4. data/lib/steem.rb +48 -0
  5. data/lib/steem/api.rb +0 -21
  6. data/lib/steem/base_error.rb +5 -3
  7. data/lib/steem/broadcast.rb +21 -4
  8. data/lib/steem/marshal.rb +231 -0
  9. data/lib/steem/mixins/jsonable.rb +37 -0
  10. data/lib/steem/mixins/serializable.rb +45 -0
  11. data/lib/steem/operation.rb +141 -0
  12. data/lib/steem/operation/account_create.rb +10 -0
  13. data/lib/steem/operation/account_create_with_delegation.rb +12 -0
  14. data/lib/steem/operation/account_update.rb +8 -0
  15. data/lib/steem/operation/account_witness_proxy.rb +4 -0
  16. data/lib/steem/operation/account_witness_vote.rb +5 -0
  17. data/lib/steem/operation/cancel_transfer_from_savings.rb +4 -0
  18. data/lib/steem/operation/challenge_authority.rb +5 -0
  19. data/lib/steem/operation/change_recovery_account.rb +5 -0
  20. data/lib/steem/operation/claim_account.rb +5 -0
  21. data/lib/steem/operation/claim_reward_balance.rb +6 -0
  22. data/lib/steem/operation/comment.rb +9 -0
  23. data/lib/steem/operation/comment_options.rb +10 -0
  24. data/lib/steem/operation/convert.rb +5 -0
  25. data/lib/steem/operation/create_claimed_account.rb +10 -0
  26. data/lib/steem/operation/custom.rb +5 -0
  27. data/lib/steem/operation/custom_binary.rb +8 -0
  28. data/lib/steem/operation/custom_json.rb +6 -0
  29. data/lib/steem/operation/decline_voting_rights.rb +4 -0
  30. data/lib/steem/operation/delegate_vesting_shares.rb +5 -0
  31. data/lib/steem/operation/delete_comment.rb +4 -0
  32. data/lib/steem/operation/escrow_approve.rb +8 -0
  33. data/lib/steem/operation/escrow_dispute.rb +7 -0
  34. data/lib/steem/operation/escrow_release.rb +10 -0
  35. data/lib/steem/operation/escrow_transfer.rb +12 -0
  36. data/lib/steem/operation/feed_publish.rb +4 -0
  37. data/lib/steem/operation/limit_order_cancel.rb +4 -0
  38. data/lib/steem/operation/limit_order_create.rb +8 -0
  39. data/lib/steem/operation/limit_order_create2.rb +8 -0
  40. data/lib/steem/operation/prove_authority.rb +4 -0
  41. data/lib/steem/operation/recover_account.rb +6 -0
  42. data/lib/steem/operation/report_over_production.rb +5 -0
  43. data/lib/steem/operation/request_account_recovery.rb +6 -0
  44. data/lib/steem/operation/reset_account.rb +5 -0
  45. data/lib/steem/operation/set_reset_account.rb +5 -0
  46. data/lib/steem/operation/set_withdraw_vesting_route.rb +6 -0
  47. data/lib/steem/operation/transfer.rb +6 -0
  48. data/lib/steem/operation/transfer_from_savings.rb +7 -0
  49. data/lib/steem/operation/transfer_to_savings.rb +6 -0
  50. data/lib/steem/operation/transfer_to_vesting.rb +5 -0
  51. data/lib/steem/operation/vote.rb +6 -0
  52. data/lib/steem/operation/withdraw_vesting.rb +4 -0
  53. data/lib/steem/operation/witness_set_properties.rb +5 -0
  54. data/lib/steem/operation/witness_update.rb +7 -0
  55. data/lib/steem/rpc/base_client.rb +13 -0
  56. data/lib/steem/rpc/http_client.rb +17 -1
  57. data/lib/steem/stream.rb +12 -4
  58. data/lib/steem/transaction.rb +96 -0
  59. data/lib/steem/transaction_builder.rb +69 -69
  60. data/lib/steem/type/amount.rb +2 -0
  61. data/lib/steem/version.rb +1 -1
  62. data/steem-ruby.gemspec +2 -0
  63. metadata +90 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57f84dd9185bb2ad616730cb370450ff56816706a8ad5b26d452bf3a7921cd68
4
- data.tar.gz: 59934f9af8d4e20da692c06b9d8b55b71c54aaead980bec892c400ef100cc77c
3
+ metadata.gz: 67cb40fbb1b8cf229d3b7fe3388ce1f9ea0b922b2f16f42d73873d965971e209
4
+ data.tar.gz: b687c618e644cf4a0128875b4e40d16407b3138d91d777c69879585b0c561a93
5
5
  SHA512:
6
- metadata.gz: f909db06bc8e7db70da6180d385e0527e6153134b2535e275e6864f9c21511506bb93ae685fee51187024819dd9ad243939efa88213f29af8b51d28c6826290b
7
- data.tar.gz: 1b9d47fbb3775b639c53fc767f4a71a7d19578ca848f9f196ce1fd53ffe09d2b4eabc90ce70404a9deb523b448d0e2c70ceff53f2058b708e1b9d6be7dd983a2
6
+ metadata.gz: 8235f9f83af323bce4df042c7eb2c6c504af5385cc137520b068c850ca5bc2f661e492ac547001dbb1892f6cc3dd053f1d1db8c9df3977b5ca0dcdb5ab7d31b9
7
+ data.tar.gz: 23948d457b71f64db355850214d61b8d5a61439b8ae7af3f60e8583a7cb3335af861572f21a0daba5ae218e92a60caeec1bb651ab64399de73ea88f47a6ab743
@@ -1,7 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steem-ruby (0.9.3)
4
+ steem-ruby (0.9.4)
5
+ base58 (~> 0.2, >= 0.2.3)
6
+ bindata (~> 2.4, >= 2.4.4)
5
7
  bitcoin-ruby (~> 0.0, >= 0.0.18)
6
8
  ffi (~> 1.9, >= 1.9.23)
7
9
  hashie (~> 3.5, >= 3.5.7)
@@ -14,6 +16,8 @@ GEM
14
16
  addressable (2.5.2)
15
17
  public_suffix (>= 2.0.2, < 4.0)
16
18
  awesome_print (1.8.0)
19
+ base58 (0.2.3)
20
+ bindata (2.4.4)
17
21
  bitcoin-ruby (0.0.18)
18
22
  coderay (1.1.2)
19
23
  crack (0.4.3)
@@ -27,17 +31,17 @@ GEM
27
31
  logging (2.2.2)
28
32
  little-plugger (~> 1.1)
29
33
  multi_json (~> 1.10)
30
- method_source (0.9.0)
34
+ method_source (0.9.1)
31
35
  minitest (5.11.3)
32
36
  minitest-line (0.6.5)
33
37
  minitest (~> 5.0)
34
38
  minitest-proveit (1.0.0)
35
39
  minitest (> 5, < 7)
36
40
  multi_json (1.13.1)
37
- pry (0.11.3)
41
+ pry (0.12.0)
38
42
  coderay (~> 1.1.0)
39
43
  method_source (~> 0.9.0)
40
- public_suffix (3.0.2)
44
+ public_suffix (3.0.3)
41
45
  rake (12.3.1)
42
46
  safe_yaml (1.0.4)
43
47
  simplecov (0.16.1)
@@ -50,7 +54,7 @@ GEM
50
54
  addressable (>= 2.3.6)
51
55
  crack (>= 0.3.2)
52
56
  hashdiff
53
- yard (0.9.15)
57
+ yard (0.9.16)
54
58
 
55
59
  PLATFORMS
56
60
  ruby
data/README.md CHANGED
@@ -15,15 +15,15 @@ The `steem-ruby` gem was written from the ground up by `@inertia`, who is also t
15
15
 
16
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
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 |
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
 
@@ -186,7 +186,7 @@ trx = open('trx.json').read
186
186
  builder = Steem::TransactionBuilder.new(wif: wif2, trx: trx)
187
187
  api = Steem::CondenserApi.new
188
188
  trx = builder.transaction
189
- api.broadcast_transaction_synchronous(trx: trx)
189
+ api.broadcast_transaction_synchronous(trx)
190
190
  ```
191
191
 
192
192
  ### Get Accounts
@@ -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'
@@ -149,19 +149,6 @@ module Steem
149
149
  @@signatures[url][rpc_method_name] ||= Api::jsonrpc(url).get_signature(method: rpc_method_name).result
150
150
  end
151
151
 
152
- # @private
153
- def raise_error_response(rpc_method_name, rpc_args, response)
154
- raise UnknownError, "#{rpc_method_name}: #{response}" if response.error.nil?
155
-
156
- error = response.error
157
-
158
- if error.message == 'Invalid Request'
159
- raise Steem::ArgumentError, "Unexpected arguments: #{rpc_args.inspect}. Expected: #{rpc_method_name} (#{args_keys_to_s(rpc_method_name)})"
160
- end
161
-
162
- BaseError.build_error(error, rpc_method_name)
163
- end
164
-
165
152
  # @private
166
153
  def respond_to_missing?(m, include_private = false)
167
154
  methods.nil? ? false : methods.include?(m.to_sym)
@@ -203,14 +190,6 @@ module Steem
203
190
 
204
191
  response = rpc_client.rpc_execute(@api_name, m, rpc_args)
205
192
 
206
- if defined?(response.error) && !!response.error
207
- if !!response.error.message
208
- raise_error_response rpc_method_name, rpc_args, response
209
- else
210
- raise Steem::ArgumentError, response.error.inspect
211
- end
212
- end
213
-
214
193
  if !!block
215
194
  case response
216
195
  when Hashie::Mash then yield response.result, response.error, response.id
@@ -10,7 +10,7 @@ module Steem
10
10
  detail[:error] = @error if !!@error
11
11
  detail[:cause] = @cause if !!@cause
12
12
 
13
- JSON[detail] rescue detai.to_s
13
+ JSON[detail] rescue detail.to_s
14
14
  end
15
15
 
16
16
  def self.build_error(error, context)
@@ -19,11 +19,11 @@ module Steem
19
19
  end
20
20
 
21
21
  if error.message.include? 'Internal Error'
22
- raise Steem::RemoteNodeError.new, error.message, build_backtrace(error)
22
+ raise Steem::RemoteNodeError, error.message, build_backtrace(error)
23
23
  end
24
24
 
25
25
  if error.message.include? 'Server error'
26
- raise Steem::RemoteNodeError.new, error.message, build_backtrace(error)
26
+ raise Steem::RemoteNodeError, error.message, build_backtrace(error)
27
27
  end
28
28
 
29
29
  if error.message.include? 'plugin not enabled'
@@ -176,6 +176,8 @@ module Steem
176
176
  end
177
177
  end
178
178
 
179
+ class DeserializationError < BaseError; end
180
+ class SerializationMismatchError < BaseError; end
179
181
  class UnsupportedChainError < BaseError; end
180
182
  class ArgumentError < BaseError; end
181
183
  class TypeError < BaseError; end
@@ -197,13 +197,17 @@ module Steem
197
197
  permlink: params[:permlink],
198
198
  max_accepted_payout: max_accepted_payout,
199
199
  percent_steem_dollars: params[:percent_steem_dollars] || 10000,
200
+ # allow_replies: allow_replies,
200
201
  allow_votes: allow_votes,
201
202
  allow_curation_rewards: allow_curation_rewards,
202
203
  extensions: []
203
204
  }
204
205
 
205
206
  if !!params[:beneficiaries]
206
- comment_options[:extensions] << [0, {beneficiaries: params[:beneficiaries]}]
207
+ comment_options[:extensions] << [
208
+ comment_options[:extensions].size,
209
+ normalize_beneficiaries(options.merge(beneficiaries: params[:beneficiaries]))
210
+ ]
207
211
  end
208
212
 
209
213
  ops << [:comment_options, comment_options]
@@ -567,7 +571,7 @@ module Steem
567
571
  check_required_fields(params, *required_fields)
568
572
 
569
573
  params[:extensions] ||= []
570
- ops = [[:account_create, params]]
574
+ ops = [[:create_claimed_account, params]]
571
575
 
572
576
  process(options.merge(ops: ops), &block)
573
577
  end
@@ -714,13 +718,21 @@ module Steem
714
718
  end
715
719
 
716
720
  if !!(sbd_exchange_rate = params[:props][:sbd_exchange_rate] rescue nil)
717
- params[:props][:sbd_exchange_rate] = normalize_amount(options.merge amount: sbd_exchange_rate, serialize: true)
721
+ params[:props][:sbd_exchange_rate][:base] = normalize_amount(options.merge amount: sbd_exchange_rate[:base], serialize: true)
722
+ params[:props][:sbd_exchange_rate][:quote] = normalize_amount(options.merge amount: sbd_exchange_rate[:quote], serialize: true)
723
+ params[:props][:sbd_exchange_rate] = params[:props][:sbd_exchange_rate].to_json
724
+ end
725
+
726
+ %i(key new_signing_key).each do |key|
727
+ if !!params[key] && params[key].size == 53
728
+ params[key] = params[key][3..-1]
729
+ end
718
730
  end
719
731
 
720
732
  %i(account_creation_fee sbd_exchange_rate url new_signing_key).each do |key|
721
733
  next unless !!params[:props][key]
722
734
 
723
- val = params[:props][key]
735
+ val = params[:props][key].to_s
724
736
 
725
737
  params[:props][key] = hexlify val unless val =~ /^[0-9A-F]+$/i
726
738
  end
@@ -1282,6 +1294,11 @@ module Steem
1282
1294
  end
1283
1295
  end
1284
1296
 
1297
+ def self.normalize_beneficiaries(options)
1298
+ # Type::Beneficiaries.new(options[:beneficiaries])
1299
+ {beneficiaries: options[:beneficiaries]}
1300
+ end
1301
+
1285
1302
  # @private
1286
1303
  def self.database_api(options)
1287
1304
  options[:database_api] ||= if !!options[:app_base]
@@ -0,0 +1,231 @@
1
+ require 'bindata'
2
+ require 'base58'
3
+
4
+ module Steem
5
+ class Marshal
6
+ include Utils
7
+ include ChainConfig
8
+
9
+ PUBLIC_KEY_DISABLED = '1111111111111111111111111111111114T1Anm'
10
+
11
+ attr_reader :bytes, :cursor
12
+
13
+ def initialize(options = {})
14
+ @bytes = if !!(hex = options[:hex])
15
+ unhexlify hex
16
+ else
17
+ options[:bytes]
18
+ end
19
+
20
+ @chain = options[:chain] || :steem
21
+ @prefix ||= case @chain
22
+ when :steem then NETWORKS_STEEM_ADDRESS_PREFIX
23
+ when :test then NETWORKS_TEST_ADDRESS_PREFIX
24
+ else; raise UnsupportedChainError, "Unsupported chain: #{@chain}"
25
+ end
26
+ @cursor = 0
27
+ end
28
+
29
+ def hex
30
+ hexlify bytes
31
+ end
32
+
33
+ def rewind!
34
+ @cursor = 0
35
+ end
36
+
37
+ def step(n = 0)
38
+ @cursor += n
39
+ end
40
+
41
+ def scan(len)
42
+ bytes.slice(@cursor..(@cursor - 1) + len).tap { |_| @cursor += len }
43
+ end
44
+
45
+ def operation_type
46
+ Operation::IDS[unsigned_char]
47
+ end
48
+
49
+ def unsigned_char; BinData::Uint8le.read(scan(1)); end # 8-bit unsigned
50
+ def uint16; BinData::Uint16le.read(scan(2)); end # 16-bit unsigned, VAX (little-endian) byte order
51
+ def uint32; BinData::Uint32le.read(scan(4)); end # 32-bit unsigned, VAX (little-endian) byte order
52
+ def uint64; BinData::Uint64le.read(scan(8)); end # 64-bit unsigned, little-endian
53
+
54
+ def signed_char; BinData::Int8le.read(scan(1)); end # 8-bit signed
55
+ def int16; BinData::Int16le.read(scan(2)); end # 16-bit signed, little-endian
56
+ def int32; BinData::Int32le.read(scan(4)); end # 32-bit signed, little-endian
57
+ def int64; BinData::Int64le.read(scan(8)); end # 64-bit signed, little-endian
58
+
59
+ def boolean; scan(1) == "\x01"; end
60
+
61
+ def varint
62
+ shift = 0
63
+ result = 0
64
+ bytes = []
65
+
66
+ while (n = unsigned_char) >> 7 == 1
67
+ bytes << n
68
+ end
69
+
70
+ bytes << n
71
+
72
+ bytes.each do |b|
73
+ result += ((b & 0x7f) << shift)
74
+ break unless (b & 0x80)
75
+ shift += 7
76
+ end
77
+
78
+ result
79
+ end
80
+
81
+ def string(len = nil); scan(len || varint); end
82
+
83
+ def raw_bytes(len = nil); scan(len || varint).force_encoding('BINARY'); end
84
+
85
+ def point_in_time
86
+ if (time = uint32) == 2**32-1
87
+ Time.at -1
88
+ else
89
+ Time.at time
90
+ end.utc
91
+ end
92
+
93
+ def public_key(prefix = @prefix)
94
+ raw_public_key = raw_bytes(33)
95
+ checksum = OpenSSL::Digest::RIPEMD160.digest(raw_public_key)
96
+ key = Base58.binary_to_base58(raw_public_key + checksum.slice(0, 4), :bitcoin)
97
+
98
+ prefix + key unless key == PUBLIC_KEY_DISABLED
99
+ end
100
+
101
+ def amount
102
+ amount = uint64.to_f
103
+ precision = signed_char
104
+ asset = scan(7).strip
105
+
106
+ amount = "%.#{precision}f #{asset}" % (amount / 10 ** precision)
107
+
108
+ Steem::Type::Amount.new(amount)
109
+ end
110
+
111
+ def price
112
+ {base: amount, quote: amount}
113
+ end
114
+
115
+ def authority(options = {optional: false})
116
+ return if !!options[:optional] && unsigned_char == 0
117
+
118
+ {
119
+ weight_threshold: uint32,
120
+ account_auths: varint.times.map { [string, uint16] },
121
+ key_auths: varint.times.map { [public_key, uint16] }
122
+ }
123
+ end
124
+
125
+ def optional_authority
126
+ authority(optional: true)
127
+ end
128
+
129
+ def comment_options_extensions
130
+ if scan(1) == "\x01"
131
+ beneficiaries
132
+ else
133
+ []
134
+ end
135
+ end
136
+
137
+ def beneficiaries
138
+ if scan(1) == "\x00"
139
+ varint.times.map {{account: string, weight: uint16}}
140
+ end
141
+ end
142
+
143
+ def chain_properties
144
+ {
145
+ account_creation_fee: amount,
146
+ maximum_block_size: uint32,
147
+ sbd_interest_rate: uint16
148
+ }
149
+ end
150
+
151
+ def required_auths
152
+ varint.times.map { string }
153
+ end
154
+
155
+ def witness_properties
156
+ properties = {}
157
+
158
+ varint.times do
159
+ key = string.to_sym
160
+ properties[key] = case key
161
+ when :account_creation_fee then Steem::Type::Amount.new(string)
162
+ when :account_subsidy_budget then scan(3)
163
+ when :account_subsidy_decay, :maximum_block_size then uint32
164
+ when :url then string
165
+ when :sbd_exchange_rate
166
+ JSON[string].tap do |rate|
167
+ rate["base"] = Steem::Type::Amount.new(rate["base"])
168
+ rate["quote"] = Steem::Type::Amount.new(rate["quote"])
169
+ end
170
+ when :sbd_interest_rate then uint16
171
+ when :key, :new_signing_key then @prefix + scan(50)
172
+ else; raise "Unknown witness property: #{key}"
173
+ end
174
+ end
175
+
176
+ properties
177
+ end
178
+
179
+ def empty_array
180
+ unsigned_char == 0 and [] or raise "Found non-empty array."
181
+ end
182
+
183
+ def transaction(options = {})
184
+ trx = options[:trx] || Transaction.new
185
+
186
+ trx.ref_block_num = uint16
187
+ trx.ref_block_prefix = uint32
188
+ trx.expiration = point_in_time
189
+
190
+ trx.operations = operations
191
+
192
+ trx
193
+ rescue => e
194
+ raise DeserializationError.new("Transaction failed\nOriginal serialized bytes:\n[#{hex[0..(@cursor * 2) - 1]}]#{hex[((@cursor) * 2)..-1]}", e)
195
+ end
196
+
197
+ def operations
198
+ operations_len = signed_char
199
+ operations = []
200
+
201
+ while operations.size < operations_len do
202
+ begin
203
+ type = operation_type
204
+ break if type.nil?
205
+
206
+ op_class_name = type.to_s.sub!(/_operation$/, '')
207
+ op_class_name = "Steem::Operation::" + op_class_name.split('_').map(&:capitalize).join
208
+ op_class = Object::const_get(op_class_name)
209
+ op = op_class.new
210
+
211
+ op_class::serializable_types.each do |k, v|
212
+ begin
213
+ # binding.pry if v == :comment_options_extensions
214
+ op.send("#{k}=", send(v))
215
+ rescue => e
216
+ raise DeserializationError.new("#{type}.#{k} (#{v}) failed", e)
217
+ end
218
+ end
219
+
220
+ operations << {type: type, value: op}
221
+ rescue => e
222
+ raise DeserializationError.new("#{type} failed", e)
223
+ end
224
+ end
225
+
226
+ operations
227
+ rescue => e
228
+ raise DeserializationError.new("Operations failed", e)
229
+ end
230
+ end
231
+ end