class Peatio::Ripple::Blockchain

Constants

DEFAULT_FEATURES
UndefinedCurrencyError

Flow: get block_number from params fetch transactions from this block build transactions from prev step

Public Class Methods

new(custom_features = {}) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 15
def initialize(custom_features = {})
  @features = DEFAULT_FEATURES.merge(custom_features).slice(*SUPPORTED_FEATURES)
  @settings = {}
end

Public Instance Methods

configure(settings = {}) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 20
def configure(settings = {})
  # Clean client state during configure.
  @client = nil
  @settings.merge!(settings.slice(*SUPPORTED_SETTINGS))
end
fetch_block!(ledger_index) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 26
def fetch_block!(ledger_index)
  ledger = client.json_rpc(:ledger,
                               [
                                 {
                                   ledger_index: ledger_index || 'validated',
                                   transactions: true,
                                   expand: true
                                 }
                               ]).dig('ledger')

  return if ledger.blank?
  ledger.fetch('transactions').each_with_object([]) do |tx, txs_array|
    next unless valid_transaction?(tx)

    txs = build_transaction(tx).map do |ntx|
      Peatio::Transaction.new(ntx.merge(block_number: ledger_index))
    end
    txs_array.append(*txs)
  end.yield_self { |txs_array| Peatio::Block.new(ledger_index, txs_array) }
rescue Client::Error => e
  raise Peatio::Blockchain::ClientError, e
end
latest_block_number() click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 49
def latest_block_number
  client.json_rpc(:ledger, [{ ledger_index: 'validated' }]).fetch('ledger_index')
rescue Client::Error => e
  raise Peatio::Blockchain::ClientError, e
end
load_balance_of_address!(address, currency_id) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 55
def load_balance_of_address!(address, currency_id)
  currency = settings[:currencies].find { |c| c[:id] == currency_id.to_s }
  raise UndefinedCurrencyError unless currency

  client.json_rpc(:account_info,
                  [account: normalize_address(address), ledger_index: 'validated', strict: true])
                  .fetch('account_data')
                  .fetch('Balance')
                  .to_d
                  .yield_self { |amount| convert_from_base_unit(amount, currency) }

rescue Client::Error => e
  raise Peatio::Blockchain::ClientError, e
end

Private Instance Methods

build_transaction(tx_hash) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 72
def build_transaction(tx_hash)
  destination_tag = tx_hash['DestinationTag'] || destination_tag_from(tx_hash['Destination'])
  address = "#{to_address(tx_hash)}?dt=#{destination_tag}"

  settings_fetch(:currencies).each_with_object([]) do |currency, formatted_txs|
    formatted_txs << { hash: tx_hash['hash'],
                       txout: tx_hash.dig('metaData','TransactionIndex'),
                       to_address: address,
                       status: check_status(tx_hash),
                       currency_id: currency[:id],
                       amount: convert_from_base_unit(tx_hash.dig('metaData', 'delivered_amount'), currency) }
  end
end
check_status(tx_hash) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 90
def check_status(tx_hash)
  tx_hash.dig('metaData', 'TransactionResult') == 'tesSUCCESS' ? 'success' : 'failed'
end
client() click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 128
def client
  @client ||= Client.new(settings_fetch(:server))
end
convert_from_base_unit(value, currency) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 124
def convert_from_base_unit(value, currency)
  value.to_d / currency.fetch(:base_factor).to_d
end
destination_tag_from(address) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 115
def destination_tag_from(address)
  address =~ /\?dt=(\d*)\Z/
  $1.to_i
end
inspect_address!(address) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 100
def inspect_address!(address)
  {
    address:  normalize_address(address),
    is_valid: valid_address?(normalize_address(address))
  }
end
normalize_address(address) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 107
def normalize_address(address)
  address.gsub(/\?dt=\d*\Z/, '')
end
settings_fetch(key) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 86
def settings_fetch(key)
  @settings.fetch(key) { raise Peatio::Blockchain::MissingSettingError, key.to_s }
end
to_address(tx) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 120
def to_address(tx)
  normalize_address(tx['Destination'])
end
valid_address?(address) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 111
def valid_address?(address)
  /\Ar[0-9a-zA-Z]{24,34}(:?\?dt=[1-9]\d*)?\z/.match?(address)
end
valid_transaction?(tx) click to toggle source
# File lib/peatio/ripple/blockchain.rb, line 94
def valid_transaction?(tx)
  inspect_address!(tx['Account'])[:is_valid] &&
    tx['TransactionType'].to_s == 'Payment' &&
    String === tx.dig('metaData', 'delivered_amount')
end