# frozen_string_literal: true require('bigdecimal/util') # @author Hernani Rodrigues Vaz module Cns # classe para processar transacoes do greymass class Greymass # @return [Apibc] API blockchains attr_reader :api # @return [Array<Hash>] todos os dados bigquery attr_reader :bqd # @return [Thor::CoreExt::HashWithIndifferentAccess] opcoes trabalho attr_reader :ops # @param [Hash] dad todos os dados bigquery # @param [Thor::CoreExt::HashWithIndifferentAccess] pop opcoes trabalho # @option pop [Hash] :h ({}) configuracao dias ajuste reposicionamento temporal # @option pop [Boolean] :v (false) mostra dados transacoes? # @option pop [Boolean] :t (false) mostra transacoes todas ou somente novas? # @return [Greymass] API greymass - processar transacoes def initialize(dad, pop) @api = Apibc.new @bqd = dad @ops = pop end # @return [Array<Hash>] lista transacoes novas def novax @novax ||= bcd.map { |obc| obc[:tx].select { |obj| idt.include?(obj[:itx]) } }.flatten end # @return [Array<String>] lista dos meus enderecos def lax @lax ||= bqd[:wb].map { |obj| obj[:ax] } end # @return [Array<Hash>] todos os dados greymass - saldos & transacoes def bcd @bcd ||= bqd[:wb].map { |obj| base_bc(obj) } end # @return [Array<Hash>] todos os dados juntos bigquery & greymass def dados @dados ||= bqd[:wb].map { |obq| bq_bc(obq, bcd.select { |obj| obq[:ax] == obj[:ax] }.first) } end # @return [Array<Integer>] lista indices transacoes novas def idt @idt ||= bcd.map { |obc| obc[:tx].map { |obj| obj[:itx] } }.flatten - (ops[:t] ? [] : bqd[:nt].map { |obq| obq[:itx] }) end # @example (see Apibc#account_gm) # @param [Hash] wbq wallet bigquery # @return [Hash] dados greymass - address, saldo & transacoes def base_bc(wbq) xbq = wbq[:ax] { ax: xbq, sl: greymass_sl(xbq).inject(:+), tx: filtrar_tx(xbq, api.ledger_gm(xbq)) } end # @param wbq (see base_bc) # @param [Hash] hbc dados greymass - address, saldo & transacoes # @return [Hash] dados juntos bigquery & greymass def bq_bc(wbq, hbc) xbq = wbq[:ax] { id: wbq[:id], ax: xbq, bs: wbq[:sl], bt: bqd[:nt].select { |obj| obj[:iax] == xbq }, es: hbc[:sl], et: hbc[:tx] } end # @param (see filtrar_tx) # @return [Array<BigDecimal>] lista recursos - liquido, net, spu def greymass_sl(add) hac = api.account_gm(add) htr = hac[:total_resources] [ hac[:core_liquid_balance].to_d, htr[:net_weight].to_d, htr[:cpu_weight].to_d ] end # @param add (see Apibc#account_gm) # @param [Array<Hash>] ary lista transacoes # @return [Array<Hash>] lista transacoes filtrada def filtrar_tx(add, ary) # elimina transferencia from: (lax) to: (add) - esta transferencia aparece em from: (add) to: (lax) # adiciona chave indice itx & adiciona identificador da carteira iax (ary.delete_if do |odl| adt = odl[:action_trace][:act][:data] adt[:to] == add && lax.include?(adt[:from]) end).map { |omp| omp.merge(itx: omp[:global_action_seq], iax: add) } end # @return [Array<Hash>] lista ordenada transacoes novas def sorax novax.sort { |ant, prx| prx[:itx] <=> ant[:itx] } end # @return [String] texto carteiras & transacoes & ajuste dias def mostra_resumo return unless dados.count.positive? puts("\naddress greymass ntx bigquery ntx") dados.each { |obj| puts(formata_carteira(obj)) } mostra_transacoes_novas mostra_configuracao_ajuste_dias end # @param [Hash] hjn dados juntos bigquery & greymass # @return [String] texto formatado duma carteira def formata_carteira(hjn) format( '%<s1>-12.12s %<v1>14.4f %<n1>4i %<v2>14.4f %<n2>4i %<ok>-3s', s1: hjn[:ax], v1: hjn[:es], n1: hjn[:et].count, v2: hjn[:bs], n2: hjn[:bt].count, ok: ok?(hjn) ? 'OK' : 'NOK' ) end # @param (see formata_carteira) # @return [Boolean] carteira tem transacoes novas(sim=NOK, nao=OK)? def ok?(hjn) hjn[:bs] == hjn[:es] && hjn[:bt].count == hjn[:et].count end # @example (see Apibc#ledger_gm) # @param [Hash] hlx ledger greymass # @return [String] texto formatado ledger greymass def formata_ledger(hlx) format( '%<bn>12i %<fr>-12.12s %<to>-12.12s %<ac>-10.10s %<dt>10.10s %<vl>12.4f %<sy>-6.6s', ac: (act = hlx[:action_trace][:act])[:name], fr: (adt = act[:data])[:from], vl: (aqt = adt[:quantity].to_s).to_d, bn: hlx[:itx], to: adt[:to], dt: Date.parse(hlx[:block_time]), sy: aqt[/[[:upper:]]+/] ) end # @return [String] texto transacoes def mostra_transacoes_novas return unless ops[:v] && novax.count.positive? puts("\nsequence num from to accao data valor moeda") sorax.each { |obj| puts(formata_ledger(obj)) } end # @return [String] texto configuracao ajuste dias das transacoes def mostra_configuracao_ajuste_dias return unless novax.count.positive? puts("\nstring ajuste dias\n-h=#{sorax.map { |obj| "#{obj[:itx]}:0" }.join(' ')}") end end end