steem-ruby 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,8 @@
1
+ class Steem::Operation::LimitOrderCreate < Steem::Operation
2
+ def_attr owner: :string
3
+ def_attr orderid: :uint32
4
+ def_attr amount_to_sell: :amount
5
+ def_attr min_to_receive: :amount
6
+ def_attr fill_or_kill: :boolean
7
+ def_attr expiration: :point_in_time
8
+ end
@@ -0,0 +1,8 @@
1
+ class Steem::Operation::LimitOrderCreate2 < Steem::Operation
2
+ def_attr owner: :string
3
+ def_attr orderid: :uint32
4
+ def_attr amount_to_sell: :amount
5
+ def_attr fill_or_kill: :boolean
6
+ def_attr exchange_rate: :price
7
+ def_attr expiration: :point_in_time
8
+ end
@@ -0,0 +1,4 @@
1
+ class Steem::Operation::ProveAuthority < Steem::Operation
2
+ def_attr challenged: :string
3
+ def_attr require_owner: :boolean
4
+ end
@@ -0,0 +1,6 @@
1
+ class Steem::Operation::RecoverAccount < Steem::Operation
2
+ def_attr account_to_recover: :string
3
+ def_attr new_owner_authority: :authority
4
+ def_attr recent_owner_authority: :authority
5
+ def_attr extensions: :empty_array
6
+ end
@@ -0,0 +1,5 @@
1
+ class Steem::Operation::ReportOverProduction < Steem::Operation
2
+ def_attr reporter: :string
3
+ def_attr first_block: :string # FIXME signed_block_header
4
+ def_attr second_block: :string # FIXME signed_block_header
5
+ end
@@ -0,0 +1,6 @@
1
+ class Steem::Operation::RequestAccountRecovery < Steem::Operation
2
+ def_attr recovery_account: :string
3
+ def_attr account_to_recover: :string
4
+ def_attr new_owner_authority: :authority
5
+ def_attr extensions: :empty_array
6
+ end
@@ -0,0 +1,5 @@
1
+ class Steem::Operation::ResetAccount < Steem::Operation
2
+ def_attr reset_account: :string
3
+ def_attr account_to_reset: :string
4
+ def_attr new_owner_authority: :authority
5
+ end
@@ -0,0 +1,5 @@
1
+ class Steem::Operation::SetResetAccount < Steem::Operation
2
+ def_attr account: :string
3
+ def_attr current_reset_account: :string
4
+ def_attr reset_account: :string
5
+ end
@@ -0,0 +1,6 @@
1
+ class Steem::Operation::SetWithdrawVestingRoute < Steem::Operation
2
+ def_attr from: :string
3
+ def_attr to: :string
4
+ def_attr percent: :uint16
5
+ def_attr auto_vest: :boolean
6
+ end
@@ -0,0 +1,6 @@
1
+ class Steem::Operation::Transfer < Steem::Operation
2
+ def_attr from: :string
3
+ def_attr to: :string
4
+ def_attr amount: :amount
5
+ def_attr memo: :string
6
+ end
@@ -0,0 +1,7 @@
1
+ class Steem::Operation::TransferFromSavings < Steem::Operation
2
+ def_attr from: :string
3
+ def_attr request_id: :uint32
4
+ def_attr to: :string
5
+ def_attr amount: :amount
6
+ def_attr memo: :string
7
+ end
@@ -0,0 +1,6 @@
1
+ class Steem::Operation::TransferToSavings < Steem::Operation
2
+ def_attr from: :string
3
+ def_attr to: :string
4
+ def_attr amount: :amount
5
+ def_attr memo: :string
6
+ end
@@ -0,0 +1,5 @@
1
+ class Steem::Operation::TransferToVesting < Steem::Operation
2
+ def_attr from: :string
3
+ def_attr to: :string
4
+ def_attr amount: :amount
5
+ end
@@ -0,0 +1,6 @@
1
+ class Steem::Operation::Vote < Steem::Operation
2
+ def_attr voter: :string
3
+ def_attr author: :string
4
+ def_attr permlink: :string
5
+ def_attr weight: :int16
6
+ end
@@ -0,0 +1,4 @@
1
+ class Steem::Operation::WithdrawVesting < Steem::Operation
2
+ def_attr account: :string
3
+ def_attr vesting_shares: :amount
4
+ end
@@ -0,0 +1,5 @@
1
+ class Steem::Operation::WitnessSetProperties < Steem::Operation
2
+ def_attr owner: :string
3
+ def_attr props: :witness_properties
4
+ def_attr extensions: :empty_array
5
+ end
@@ -0,0 +1,7 @@
1
+ class Steem::Operation::WitnessUpdate < Steem::Operation
2
+ def_attr owner: :string
3
+ def_attr url: :string
4
+ def_attr block_signing_key: :public_key
5
+ def_attr props: :chain_properties
6
+ def_attr fee: :amount
7
+ end
@@ -161,6 +161,19 @@ module Steem
161
161
 
162
162
  sleep @backoff
163
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
164
177
  end
165
178
  end
166
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, IOError, Errno::ENETDOWN]
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)
@@ -91,6 +91,14 @@ module Steem
91
91
  # @option options [Integer] :until_block_num Ends the stream at the given block number. Default: nil.
92
92
  def transactions(options = {}, &block)
93
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
+
94
102
  block.transactions.each_with_index do |transaction, index|
95
103
  trx_id = block.transaction_ids[index]
96
104
 
@@ -332,9 +340,8 @@ module Steem
332
340
  end
333
341
 
334
342
  response = account_history_api.get_ops_in_block(*get_ops_in_block_options)
335
- result = response.result
336
343
 
337
- if result.nil?
344
+ if response.nil? || (result = response.result).nil?
338
345
  if retries < MAX_RETRY_COUNT
339
346
  warn "Retrying get_ops_in_block on block #{block_num}" unless @no_warn
340
347
  retries = retries + 1
@@ -360,7 +367,8 @@ module Steem
360
367
  retries = retries + 1
361
368
  redo
362
369
  else
363
- raise TooManyRetriesError, "unable to find virtual operations for block: #{block_num}"
370
+ warn "unable to find virtual operations for block: #{block_num}"
371
+ # raise TooManyRetriesError, "unable to find virtual operations for block: #{block_num}"
364
372
  end
365
373
  end
366
374
 
@@ -374,4 +382,4 @@ module Steem
374
382
  end
375
383
  end
376
384
  end
377
- end
385
+ end
@@ -0,0 +1,96 @@
1
+ module Steem
2
+ class Transaction
3
+ include JSONable
4
+ include Utils
5
+
6
+ ATTRIBUTES = %i(id ref_block_num ref_block_prefix expiration operations
7
+ extensions signatures)
8
+
9
+ attr_accessor *ATTRIBUTES
10
+
11
+ def initialize(options = {})
12
+ if !!(hex = options.delete(:hex))
13
+ marshal = Marshal.new(hex: hex)
14
+ marshal.transaction(trx: self)
15
+ end
16
+
17
+ options.each do |k, v|
18
+ raise Steem::ArgumentError, "Invalid option specified: #{k}" unless ATTRIBUTES.include?(k.to_sym)
19
+
20
+ send("#{k}=", v)
21
+ end
22
+
23
+ self.operations ||= []
24
+ self.extensions ||= []
25
+ self.signatures ||= []
26
+
27
+ self.expiration = case @expiration
28
+ when String then Time.parse(@expiration + 'Z')
29
+ else; @expiration
30
+ end
31
+ end
32
+
33
+ def inspect
34
+ properties = ATTRIBUTES.map do |prop|
35
+ unless (v = instance_variable_get("@#{prop}")).nil?
36
+ v = if v.respond_to? :strftime
37
+ v.strftime('%Y-%m-%dT%H:%M:%S')
38
+ else
39
+ v
40
+ end
41
+
42
+ "@#{prop}=#{v}"
43
+ end
44
+ end.compact.join(', ')
45
+
46
+ "#<#{self.class.name} [#{properties}]>"
47
+ end
48
+
49
+ def expiration
50
+ if @expiration.respond_to? :strftime
51
+ @expiration.strftime('%Y-%m-%dT%H:%M:%S')
52
+ else
53
+ @expiration
54
+ end
55
+ end
56
+
57
+ def expired?
58
+ @expiration.nil? || @expiration < Time.now
59
+ end
60
+
61
+ def [](key)
62
+ key = key.to_sym
63
+ send(key) if self.class.attributes.include?(key)
64
+ end
65
+
66
+ def []=(key, value)
67
+ key = key.to_sym
68
+ send("#{key}=", value) if self.class.attributes.include?(key)
69
+ end
70
+
71
+ def ==(other_trx)
72
+ return true if self.equal? other_trx
73
+ return false unless self.class == other_trx.class
74
+
75
+ begin
76
+ return false if self[:ref_block_num].to_i != other_trx[:ref_block_num].to_i
77
+ return false if self[:ref_block_prefix].to_i != other_trx[:ref_block_prefix].to_i
78
+ return false if self[:expiration].to_i != other_trx[:expiration].to_i
79
+ return false if self[:operations].size != other_trx[:operations].size
80
+
81
+ op_values = self[:operations].map do |type, value|
82
+ [type.to_s, value.values.map{|v| v.to_s.gsub(/[^a-zA-Z0-9-]/, '')}]
83
+ end.flatten.sort
84
+
85
+ other_op_values = other_trx[:operations].map do |type, value|
86
+ [type.to_s, value.values.map{|v| v.to_s.gsub(/[^a-zA-Z0-9-]/, '')}]
87
+ end.flatten.sort
88
+ # binding.pry unless op_values == other_op_values
89
+ op_values == other_op_values
90
+ rescue => e
91
+ # binding.pry
92
+ false
93
+ end
94
+ end
95
+ end
96
+ end
@@ -28,10 +28,11 @@ module Steem
28
28
 
29
29
  attr_accessor :app_base, :database_api, :block_api, :expiration, :operations
30
30
  attr_writer :wif
31
- attr_reader :signed, :testnet
31
+ attr_reader :signed, :testnet, :force_serialize
32
32
 
33
33
  alias app_base? app_base
34
34
  alias testnet? testnet
35
+ alias force_serialize? force_serialize
35
36
 
36
37
  def initialize(options = {})
37
38
  @app_base = !!options[:app_base] # default false
@@ -49,6 +50,7 @@ module Steem
49
50
  @wif = [options[:wif]].flatten
50
51
  @signed = false
51
52
  @testnet = !!options[:testnet]
53
+ @force_serialize = !!options[:force_serialize]
52
54
 
53
55
  if !!(trx = options[:trx])
54
56
  trx = case trx
@@ -56,28 +58,10 @@ module Steem
56
58
  else; trx
57
59
  end
58
60
 
59
- trx_options = {
60
- ref_block_num: trx['ref_block_num'],
61
- ref_block_prefix: trx['ref_block_prefix'],
62
- extensions: (trx['extensions']),
63
- operations: trx['operations'],
64
- signatures: (trx['signatures']),
65
- }
66
-
67
- trx_options[:expiration] = case trx['expiration']
68
- when String then Time.parse(trx['expiration'] + 'Z')
69
- else; trx['expiration']
70
- end
71
-
72
- options = options.merge(trx_options)
61
+ @trx = Transaction.new(trx)
73
62
  end
74
63
 
75
- @ref_block_num = options[:ref_block_num]
76
- @ref_block_prefix = options[:ref_block_prefix]
77
- @operations = options[:operations] || []
78
- @expiration = options[:expiration]
79
- @extensions = options[:extensions] || []
80
- @signatures = options[:signatures] || []
64
+ @trx ||= Transaction.new
81
65
  @chain = options[:chain] || :steem
82
66
  @error_pipe = options[:error_pipe] || STDERR
83
67
  @chain_id = options[:chain_id]
@@ -93,12 +77,9 @@ module Steem
93
77
  end
94
78
 
95
79
  def inspect
96
- properties = %w(
97
- ref_block_num ref_block_prefix expiration operations extensions
98
- signatures
99
- ).map do |prop|
80
+ properties = %w(trx).map do |prop|
100
81
  if !!(v = instance_variable_get("@#{prop}"))
101
- "@#{prop}=#{v}"
82
+ "@#{prop}=#{v.inspect}"
102
83
  end
103
84
  end.compact.join(', ')
104
85
 
@@ -106,21 +87,12 @@ module Steem
106
87
  end
107
88
 
108
89
  def reset
109
- @ref_block_num = nil
110
- @ref_block_prefix = nil
111
- @expiration = nil
112
- @operations = []
113
- @extensions = []
114
- @signatures = []
90
+ @trx = Transaction.new
115
91
  @signed = false
116
92
 
117
93
  self
118
94
  end
119
95
 
120
- def expired?
121
- @expiration.nil? || @expiration < Time.now
122
- end
123
-
124
96
  # If the transaction can be prepared, this method will do so and set the
125
97
  # expiration. Once the expiration is set, it will not re-prepare. If you
126
98
  # call {#put}, the expiration is set {::Nil} so that it can be re-prepared.
@@ -129,7 +101,7 @@ module Steem
129
101
  #
130
102
  # @return {TransactionBuilder}
131
103
  def prepare
132
- if expired?
104
+ if @trx.expired?
133
105
  catch :prepare_header do; begin
134
106
  @database_api.get_dynamic_global_properties do |properties|
135
107
  block_number = properties.last_irreversible_block_num
@@ -146,9 +118,9 @@ module Steem
146
118
  result
147
119
  end
148
120
 
149
- @ref_block_num = (block_number - 1) & 0xFFFF
150
- @ref_block_prefix = unhexlify(header.previous[8..-1]).unpack('V*')[0]
151
- @expiration ||= (Time.parse(properties.time + 'Z') + EXPIRE_IN_SECS).utc
121
+ @trx.ref_block_num = (block_number - 1) & 0xFFFF
122
+ @trx.ref_block_prefix = unhexlify(header.previous[8..-1]).unpack('V*')[0]
123
+ @trx.expiration ||= (Time.parse(properties.time + 'Z') + EXPIRE_IN_SECS).utc
152
124
  end
153
125
  end
154
126
  rescue => e
@@ -166,9 +138,9 @@ module Steem
166
138
 
167
139
  # Sets operations all at once, then prepares.
168
140
  def operations=(operations)
169
- @operations = operations.map{ |op| normalize_operation(op) }
141
+ @trx.operations = operations.map{ |op| normalize_operation(op) }
170
142
  prepare
171
- @operations
143
+ @trx.operations
172
144
  end
173
145
 
174
146
  # A quick and flexible way to append a new operation to the transaction.
@@ -194,8 +166,8 @@ module Steem
194
166
  # builder.put(vote: vote1).put(vote: vote2)
195
167
  # @return {TransactionBuilder}
196
168
  def put(type, op = nil)
197
- @expiration = nil
198
- @operations << normalize_operation(type, op)
169
+ @trx.expiration = nil
170
+ @trx.operations << normalize_operation(type, op)
199
171
  prepare
200
172
  self
201
173
  end
@@ -218,9 +190,17 @@ module Steem
218
190
  # ]],
219
191
  # :signatures => ["1c45b65740b4b2c17c4bcf6bcc3f8d90ddab827d50532729fc3b8f163f2c465a532b0112ae4bf388ccc97b7c2e0bc570caadda78af48cf3c261037e65eefcd941e"]
220
192
  # }
221
- def transaction
222
- prepare
223
- sign
193
+ def transaction(options = {prepare: true, sign: true})
194
+ options[:prepare] = true unless options.has_key? :prepare
195
+ options[:sign] = true unless options.has_key? :sign
196
+
197
+ prepare if !!options[:prepare]
198
+
199
+ if !!options[:sign]
200
+ sign
201
+ else
202
+ @trx
203
+ end
224
204
  end
225
205
 
226
206
  # Appends to the `signatures` array of the transaction, built from a
@@ -229,39 +209,42 @@ module Steem
229
209
  # @return {Hash | TransactionBuilder} The fully signed transaction if a `wif` is provided or the instance of the {TransactionBuilder} if a `wif` has not yet been provided.
230
210
  def sign
231
211
  return self if @wif.empty?
232
- return self if expired?
233
-
234
- trx = {
235
- ref_block_num: @ref_block_num,
236
- ref_block_prefix: @ref_block_prefix,
237
- expiration: @expiration.strftime('%Y-%m-%dT%H:%M:%S'),
238
- operations: @operations,
239
- extensions: @extensions,
240
- signatures: @signatures
241
- }
212
+ return self if @trx.expired?
242
213
 
243
214
  unless @signed
244
215
  catch :serialize do; begin
245
- transaction_hex_args = if app_base?
246
- {trx: trx}
247
- else
248
- trx
249
- end
250
-
251
- @database_api.get_transaction_hex(transaction_hex_args) do |result|
216
+ transaction_hex.tap do |result|
252
217
  hex = if app_base?
253
218
  result.hex
254
219
  else
255
220
  result
256
221
  end
222
+
223
+ unless force_serialize?
224
+ derrived_trx = Transaction.new(hex: hex)
225
+ derrived_ops = derrived_trx.operations
226
+ derrived_trx.operations = derrived_ops.map do |op|
227
+ op_name = if app_base?
228
+ op[:type].to_sym
229
+ else
230
+ op[:type].to_s.sub(/_operation$/, '').to_sym
231
+ end
232
+
233
+ normalize_operation op_name, JSON[op[:value].to_json]
234
+ end
235
+
236
+ raise SerializationMismatchError unless @trx == derrived_trx
237
+ end
238
+
239
+ hex = hex[0..-4] # drop empty signature array
240
+ @trx.id = Digest::SHA256.hexdigest(unhexlify(hex))[0..39]
257
241
 
258
- hex = @chain_id + hex[0..-4] # Why do we have to chop the last two bytes?
242
+ hex = @chain_id + hex
259
243
  digest = unhexlify(hex)
260
244
  digest_hex = Digest::SHA256.digest(digest)
261
245
  private_keys = @wif.map{ |wif| Bitcoin::Key.from_base58 wif }
262
246
  ec = Bitcoin::OpenSSL_EC
263
247
  count = 0
264
- sigs = []
265
248
 
266
249
  private_keys.each do |private_key|
267
250
  sig = nil
@@ -276,11 +259,10 @@ module Steem
276
259
  break if canonical? sig
277
260
  end
278
261
 
279
- @signatures << hexlify(sig)
262
+ @trx.signatures << hexlify(sig)
280
263
  end
281
264
 
282
265
  @signed = true
283
- trx[:signatures] = @signatures
284
266
  end
285
267
  rescue => e
286
268
  if can_retry? e
@@ -292,7 +274,25 @@ module Steem
292
274
  end; end
293
275
  end
294
276
 
295
- Hashie::Mash.new trx
277
+ @trx
278
+ end
279
+
280
+ def transaction_hex
281
+ trx = transaction(prepare: true, sign: false)
282
+
283
+ transaction_hex_args = if app_base?
284
+ {trx: trx}
285
+ else
286
+ trx
287
+ end
288
+
289
+ @database_api.get_transaction_hex(transaction_hex_args) do |result|
290
+ if app_base?
291
+ result[:hex]
292
+ else
293
+ result
294
+ end
295
+ end
296
296
  end
297
297
 
298
298
  # @return [Array] All public keys that could possibly sign for a given transaction.