Class: Radiator::Transaction

Inherits:
Object
  • Object
show all
Includes:
ChainConfig, Utils
Defined in:
lib/radiator/transaction.rb

Overview

  • graphenej:

    * https://github.com/kenCode-de/graphenej/blob/master/graphenej/src/main/java/de/bitsharesmunich/graphenej/Transaction.java#L142
    

Constant Summary collapse

VALID_OPTIONS =
%w(
  wif private_key ref_block_num ref_block_prefix expiration
  chain use_condenser_namespace
).map(&:to_sym)

Constants included from ChainConfig

ChainConfig::EXPIRE_IN_SECS, ChainConfig::EXPIRE_IN_SECS_PROPOSAL, ChainConfig::NETWORKS_HIVE_ADDRESS_PREFIX, ChainConfig::NETWORKS_HIVE_CHAIN_ID, ChainConfig::NETWORKS_HIVE_CORE_ASSET, ChainConfig::NETWORKS_HIVE_DEBT_ASSET, ChainConfig::NETWORKS_HIVE_DEFAULT_NODE, ChainConfig::NETWORKS_HIVE_VEST_ASSET, ChainConfig::NETWORKS_STEEM_ADDRESS_PREFIX, ChainConfig::NETWORKS_STEEM_CHAIN_ID, ChainConfig::NETWORKS_STEEM_CORE_ASSET, ChainConfig::NETWORKS_STEEM_DEBT_ASSET, ChainConfig::NETWORKS_STEEM_DEFAULT_NODE, ChainConfig::NETWORKS_STEEM_VEST_ASSET, ChainConfig::NETWORKS_TEST_ADDRESS_PREFIX, ChainConfig::NETWORKS_TEST_CHAIN_ID, ChainConfig::NETWORKS_TEST_CORE_ASSET, ChainConfig::NETWORKS_TEST_DEBT_ASSET, ChainConfig::NETWORKS_TEST_DEFAULT_NODE, ChainConfig::NETWORKS_TEST_VEST_ASSET, ChainConfig::NETWORK_CHAIN_IDS

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utils

#debug, #error, #extract_signatures, #hexlify, #pakArr, #pakC, #pakHash, #pakI, #pakL!, #pakS, #pakStr, #pakc, #paks, #send_log, #unhexlify, #varint, #warning

Constructor Details

#initialize(options = {}) ⇒ Transaction

Returns a new instance of Transaction.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/radiator/transaction.rb', line 18

def initialize(options = {})
  options = options.dup
  options.each do |k, v|
    k = k.to_sym
    if VALID_OPTIONS.include?(k.to_sym)
      options.delete(k)
      send("#{k}=", v)
    end
  end

  @url = options[:url] || url
  @chain ||= 'hive'
  @chain = @chain.to_sym
  @chain_id = chain_id options[:chain_id]
  @operations = options[:operations] || []
  
  @self_logger = false
  @logger = if options[:logger].nil?
    @self_logger = true
    Radiator.logger
  else
    options[:logger]
  end
  
  unless NETWORK_CHAIN_IDS.include? @chain_id
    warning "Unknown chain id: #{@chain_id}"
  end

  if !!wif && !!private_key
    raise TransactionError, "Do not pass both wif and private_key.  That's confusing."
  end

  if !!wif
    @private_key = if ENV['RADIATOR_USE_LEGACY_BITCOIN_RUBY_SIGNER'] == '1'
      Bitcoin::Key.from_base58 wif
    else
      Hive::SigningKey.from_base58 wif
    end
  end

  @ref_block_num ||= nil
  @ref_block_prefix ||= nil
  @expiration ||= nil
  @immutable_expiration = !!@expiration

  options = options.merge(
    url: @url,
    chain: @chain,
    pool_size: 1,
    persist: false,
    reuse_ssl_sessions: false
  )

  @api = Api.new(options)
  @network_broadcast_api = NetworkBroadcastApi.new(options)
  
  @use_condenser_namespace = if options.keys.include? :use_condenser_namespace
    options[:use_condenser_namespace]
  else
    true
  end
  
  ObjectSpace.define_finalizer(self, self.class.finalize(@api, @network_broadcast_api, @self_logger, @logger))
end

Class Method Details

.finalize(api, network_broadcast_api, self_logger, logger) ⇒ Object



335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/radiator/transaction.rb', line 335

def self.finalize(api, network_broadcast_api, self_logger, logger)
  proc {
    if !!api && !api.stopped?
      puts "DESTROY: #{api.inspect}" if ENV['LOG'] == 'TRACE'
      api.shutdown
      api = nil
    end

    if !!network_broadcast_api && !network_broadcast_api.stopped?
      puts "DESTROY: #{network_broadcast_api.inspect}" if ENV['LOG'] == 'TRACE'
      network_broadcast_api.shutdown
      network_broadcast_api = nil
    end

    begin
      if self_logger
        if !!logger && defined?(logger.close)
          if defined?(logger.closed?)
            logger.close unless logger.closed?
          end
        end
      end
    rescue IOError, NoMethodError => _; end
  }
end

Instance Method Details

#chain_id(chain_id = nil) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/radiator/transaction.rb', line 83

def chain_id(chain_id = nil)
  return chain_id if !!chain_id

  case chain.to_s.downcase.to_sym
  when :steem then NETWORKS_STEEM_CHAIN_ID
  when :hive
    database_api = Hive::DatabaseApi.new(url: @url)
    database_api.get_config do |config|
      config['HIVE_CHAIN_ID']
    end rescue nil || NETWORKS_HIVE_CHAIN_ID
  when :test then NETWORKS_TEST_CHAIN_ID
  end
end

#inspectObject



181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/radiator/transaction.rb', line 181

def inspect
  properties = %w(
    url ref_block_num ref_block_prefix expiration chain
    use_condenser_namespace immutable_expiration payload
  ).map do |prop|
    if !!(v = instance_variable_get("@#{prop}"))
      "@#{prop}=#{v}" 
    end
  end.compact.join(', ')
  
  "#<#{self.class.name} [#{properties}]>"
end

#operationsObject



151
152
153
154
155
156
157
158
# File 'lib/radiator/transaction.rb', line 151

def operations
  @operations = @operations.map do |op|
    case op
    when Operation then op
    else; Operation.new(op.merge(chain: @chain))
    end
  end
end

#operations=(operations) ⇒ Object



160
161
162
# File 'lib/radiator/transaction.rb', line 160

def operations=(operations)
  @operations = operations
end

#process(broadcast = false) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/radiator/transaction.rb', line 105

def process(broadcast = false)
  prepare

  if broadcast
    loop do
      response = broadcast_payload(payload)

      if !!response.error
        parser = ErrorParser.new(response)

        if parser.can_reprepare?
          debug "Error code: #{parser}, repreparing transaction ..."
          prepare
          redo
        end
      end

      return response
    end
  else
    self
  end
rescue OperationError => e
  trx_builder, network_api = case @chain.to_sym
  when :steem then [
    Steem::TransactionBuilder.new(wif: @wif),
    Steem::NetworkBroadcastApi.new(url: @url)
  ]
  when :hive then [
    Hive::TransactionBuilder.new(wif: @wif),
    Hive::NetworkBroadcastApi.new(url: @url)
  ]
  end
  
  raise e if trx_builder.nil?
  
  @operations.each do |op|
    type = op.delete(:type)
    trx_builder.put({type => op})
  end
  
  network_api.broadcast_transaction_synchronous(trx_builder.transaction)
ensure
  shutdown
end

#shutdownObject



164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/radiator/transaction.rb', line 164

def shutdown
  @api.shutdown if !!@api
  @network_broadcast_api.shutdown if !!@network_broadcast_api

  if @self_logger
    if !!@logger && defined?(@logger.close)
      if defined?(@logger.closed?)
        @logger.close unless @logger.closed?
      end
    end
  end
end

#urlObject



97
98
99
100
101
102
103
# File 'lib/radiator/transaction.rb', line 97

def url
  case chain.to_s.downcase.to_sym
  when :steem then NETWORKS_STEEM_DEFAULT_NODE
  when :hive then NETWORKS_HIVE_DEFAULT_NODE
  when :test then NETWORKS_TEST_DEFAULT_NODE
  end
end

#use_condenser_namespace?Boolean

Returns:

  • (Boolean)


177
178
179
# File 'lib/radiator/transaction.rb', line 177

def use_condenser_namespace?
  !!@use_condenser_namespace
end