Class: Peatio::Infura::Blockchain

Inherits:
Blockchain::Abstract
  • Object
show all
Defined in:
lib/peatio/infura/blockchain.rb

Constant Summary collapse

UndefinedCurrencyError =
Class.new(StandardError)
TOKEN_EVENT_IDENTIFIER =
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
SUCCESS =
'0x1'
FAILED =
'0x0'
DEFAULT_FEATURES =
{ case_sensitive: false, cash_addr_format: false }.freeze

Instance Method Summary collapse

Constructor Details

#initialize(custom_features = {}) ⇒ Blockchain

Returns a new instance of Blockchain.



14
15
16
17
# File 'lib/peatio/infura/blockchain.rb', line 14

def initialize(custom_features = {})
  @features = DEFAULT_FEATURES.merge(custom_features).slice(*SUPPORTED_FEATURES)
  @settings = {}
end

Instance Method Details

#configure(settings = {}) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/peatio/infura/blockchain.rb', line 19

def configure(settings = {})
  # Clean client state during configure.
  @client = nil
  @erc20 = []; @eth = []

  @settings.merge!(settings.slice(*SUPPORTED_SETTINGS))
  @settings[:currencies]&.each do |c|
    if c.dig(:options, :erc20_contract_address).present?
      @erc20 << c
    else
      @eth << c
    end
  end
end

#fetch_block!(block_number) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/peatio/infura/blockchain.rb', line 34

def fetch_block!(block_number)
  block_json = client.json_rpc(:eth_getBlockByNumber, ["0x#{block_number.to_s(16)}", true])

  if block_json.blank? || block_json['transactions'].blank?
    return Peatio::Block.new(block_number, [])
  end
  block_json.fetch('transactions').each_with_object([]) do |tx, block_arr|
    if tx.fetch('input').hex <= 0
      next if invalid_eth_transaction?(tx)
    else
      next if @erc20.find { |c| c.dig(:options, :erc20_contract_address) == normalize_address(tx.fetch('to')) }.blank?
      tx = client.json_rpc(:eth_getTransactionReceipt, [normalize_txid(tx.fetch('hash'))])
      next if tx.nil? || tx.fetch('to').blank?
    end

    txs = build_transactions(tx).map do |ntx|
      Peatio::Transaction.new(ntx)
    end

    block_arr.append(*txs)
  end.yield_self { |block_arr| Peatio::Block.new(block_number, block_arr) }
rescue Infura::Client::Error => e
  raise Peatio::Blockchain::ClientError, e
end

#fetch_transaction(transaction) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/peatio/infura/blockchain.rb', line 81

def fetch_transaction(transaction)
  currency = settings[:currencies].find { |c| c.fetch(:id) == transaction.currency_id }
  return if currency.blank?
  txn_receipt = client.json_rpc(:eth_getTransactionReceipt, [transaction.hash])
  if currency.in?(@eth)
    txn_json = client.json_rpc(:eth_getTransactionByHash, [transaction.hash])
    attributes = {
      amount: convert_from_base_unit(txn_json.fetch('value').hex, currency),
      to_address: normalize_address(txn_json['to']),
      status: transaction_status(txn_receipt)
    }
  else
    txn_json = txn_receipt.fetch('logs').find { |log| log['logIndex'].to_i(16) == transaction.txout }
    attributes = {
      amount: convert_from_base_unit(txn_json.fetch('data').hex, currency),
      to_address: normalize_address('0x' + txn_json.fetch('topics').last[-40..-1]),
      status: transaction_status(txn_receipt)
    }
  end
  transaction.assign_attributes(attributes)
  transaction
end

#latest_block_numberObject



59
60
61
62
63
# File 'lib/peatio/infura/blockchain.rb', line 59

def latest_block_number
  client.json_rpc(:eth_blockNumber).to_i(16)
rescue Infura::Client::Error => e
  raise Peatio::Blockchain::ClientError, e
end

#load_balance_of_address!(address, currency_id) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/peatio/infura/blockchain.rb', line 65

def load_balance_of_address!(address, currency_id)
  currency = settings[:currencies].find { |c| c[:id] == currency_id.to_s }
  raise UndefinedCurrencyError unless currency

  if currency.dig(:options, :erc20_contract_address).present?
    load_erc20_balance(address, currency)
  else
    client.json_rpc(:eth_getBalance, [normalize_address(address), 'latest'])
          .hex
          .to_d
          .yield_self { |amount| convert_from_base_unit(amount, currency) }
  end
rescue Infura::Client::Error => e
  raise Peatio::Blockchain::ClientError, e
end