class Peatio::Tron::Blockchain
Constants
- DEFAULT_FEATURES
- TOKEN_EVENT_IDENTIFIER
Public Class Methods
new(custom_features = {})
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 9 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/tron/blockchain.rb, line 14 def configure(settings = {}) # Clean client state during configure. @client = nil @trc10 = []; @trc20 = []; @trx = [] @settings.merge!(settings.slice(*SUPPORTED_SETTINGS)) @settings[:currencies]&.each do |c| if c.dig(:options, :trc10_token_id).present? @trc10 << c elsif c.dig(:options, :trc20_contract_address).present? @trc20 << c else @trx << c end end end
fetch_block!(block_number)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 32 def fetch_block!(block_number) client.json_rpc(path: 'wallet/getblockbynum', params: { num: block_number }) .fetch('transactions', []).each_with_object([]) do |tx, txs_array| if %w[TransferContract TransferAssetContract].include? tx.dig('raw_data', 'contract')[0].fetch('type', nil) next if invalid_transaction?(tx) else tx = client.json_rpc(path: 'wallet/gettransactioninfobyid', params: { value: tx['txID'] }) next if tx.nil? || invalid_trc20_transaction?(tx) end txs = build_transaction(tx.merge('block_number' => block_number)).map do |ntx| Peatio::Transaction.new(ntx) end txs_array.append(*txs) end.yield_self { |txs_array| Peatio::Block.new(block_number, txs_array) } rescue Client::Error => e raise Peatio::Blockchain::ClientError, e end
latest_block_number()
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 53 def latest_block_number client.json_rpc(path: 'wallet/getblockbylatestnum', params: { num: 1 }) .fetch('block')[0]['block_header']['raw_data']['number'] rescue Client::Error => e raise Peatio::Blockchain::ClientError, e end
load_balance_of_address!(address, currency_id)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 60 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, :trc10_token_id).present? client.json_rpc(path: 'wallet/getaccount', params: { address: reformat_decode_address(address) } ).fetch('assetV2', []) .find { |a| a['key'] == currency.dig(:options, :trc10_token_id) } .try(:fetch, 'value', 0) elsif currency.dig(:options, :trc20_contract_address).present? client.json_rpc(path: 'wallet/triggersmartcontract', params: { owner_address: reformat_decode_address(address), contract_address: reformat_decode_address(currency.dig(:options, :trc20_contract_address)), function_selector: 'balanceOf(address)', parameter: abi_encode(reformat_decode_address(address)[2..42]) } ).fetch('constant_result')[0].hex else client.json_rpc(path: 'wallet/getaccount', params: { address: reformat_decode_address(address) } ).fetch('balance', nil) end.yield_self { |amount| convert_from_base_unit(amount.to_i, currency) } rescue Client::Error => e raise Peatio::Blockchain::ClientError, e end
Private Instance Methods
build_coin_transaction(tx_hash)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 153 def build_coin_transaction(tx_hash) tx = tx_hash['raw_data']['contract'][0] @trx.map do |currency| { hash: reformat_txid(tx_hash['txID']), amount: convert_from_base_unit(tx['parameter']['value']['amount'], currency), to_address: reformat_encode_address(tx['parameter']['value']['to_address']), txout: 0, block_number: tx_hash['block_number'], currency_id: currency.fetch(:id), status: 'success' } end end
build_invalid_trc20_transaction(tx_hash)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 166 def build_invalid_trc20_transaction(tx_hash) currencies = @trc20.select do |c| c.dig(:options, :trc20_contract_address) == reformat_encode_address(tx_hash.fetch('contract_address')) end return [] if currencies.blank? currencies.each_with_object([]) do |currency, invalid_txs| invalid_txs << { hash: reformat_txid(tx_hash.fetch('txID')), block_number: tx_hash.fetch('block_number'), currency_id: currency.fetch(:id), status: trc20_transaction_status(tx_hash) } end end
build_transaction(tx_hash)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 89 def build_transaction(tx_hash) if tx_hash.has_key?('contract_address') build_trc20_transaction(tx_hash) else case tx_hash['raw_data']['contract'][0]['type'] when 'TransferContract' build_coin_transaction(tx_hash) when 'TransferAssetContract' build_trc10_transaction(tx_hash) end end end
build_trc10_transaction(tx_hash)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 102 def build_trc10_transaction(tx_hash) tx = tx_hash['raw_data']['contract'][0] currencies = @trc10.select do |c| c.dig(:options, :trc10_token_id) == decode_hex(tx['parameter']['value']['asset_name']) end formatted_txs = [] currencies.each do |currency| formatted_txs << { hash: reformat_txid(tx_hash['txID']), amount: convert_from_base_unit(tx['parameter']['value']['amount'], currency), to_address: reformat_encode_address(tx['parameter']['value']['to_address']), txout: 0, block_number: tx_hash['block_number'], currency_id: currency.fetch(:id), status: 'success' } end formatted_txs end
build_trc20_transaction(tx_hash)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 121 def build_trc20_transaction(tx_hash) # Build invalid transaction for failed withdrawals if trc20_transaction_status(tx_hash) == 'failed' && tx_hash.fetch('log', []).blank? return build_invalid_trc20_transaction(tx_hash) end formatted_txs = [] tx_hash.fetch('log', []).each_with_index do |log, index| next if log.fetch('topics', []).blank? || log.fetch('topics')[0] != TOKEN_EVENT_IDENTIFIER # Skip if TRC20 contract address doesn't match. currencies = @trc20.select do |c| c.dig(:options, :trc20_contract_address) == reformat_encode_address("41#{log.fetch('address')}") end next if currencies.blank? destination_address = reformat_encode_address("41#{log.fetch('topics').last[-40..-1]}") currencies.each do |currency| formatted_txs << { hash: reformat_txid(tx_hash.fetch('id')), amount: convert_from_base_unit(log.fetch('data').hex, currency), to_address: destination_address, txout: index, block_number: tx_hash['block_number'], currency_id: currency.fetch(:id), status: trc20_transaction_status(tx_hash) } end end formatted_txs end
client()
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 198 def client @client ||= Client.new(settings_fetch(:server)) end
convert_from_base_unit(value, currency)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 194 def convert_from_base_unit(value, currency) value.to_d / currency.fetch(:base_factor).to_d end
invalid_transaction?(tx)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 184 def invalid_transaction?(tx) tx['raw_data']['contract'][0]['parameter']['value']['amount'].to_i == 0 \ || tx['ret'][0]['contractRet'] == 'REVERT' end
invalid_trc20_transaction?(tx)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 189 def invalid_trc20_transaction?(tx) tx.fetch('contract_address', '').blank? \ || tx.fetch('log', []).blank? end
settings_fetch(key)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 202 def settings_fetch(key) @settings.fetch(key) { raise Peatio::Blockchain::MissingSettingError, key.to_s } end
trc20_transaction_status(txn_hash)
click to toggle source
# File lib/peatio/tron/blockchain.rb, line 180 def trc20_transaction_status(txn_hash) txn_hash['receipt']['result'] == 'SUCCESS' ? 'success' : 'failed' end