cns 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @author Hernani Rodrigues Vaz
4
+ module Cns
5
+ # (see Bigquery)
6
+ class Bigquery
7
+ # @return [String] comando insert SQL formatado det (trades)
8
+ def det_ins
9
+ "insert #{BD}.det(tp,btc,eur,time,user,id,dtc,dias) VALUES#{apide.trades.map { |h| det_val1(h) }.join(',')}"
10
+ end
11
+
12
+ # @example (see Apide#trades)
13
+ # @param [Hash] htx transacao trade apide
14
+ # @return [String] valores formatados det (trades parte1)
15
+ def det_val1(htx)
16
+ "('#{htx[:type]}'," \
17
+ 'cast(' \
18
+ "#{htx[:type] == 'buy' ? htx[:amount_currency_to_trade_after_fee] : "-#{htx[:amount_currency_to_trade]}"}" \
19
+ ' as numeric),' \
20
+ "cast(#{htx[:volume_currency_to_pay_after_fee]} as numeric)," \
21
+ "DATETIME(TIMESTAMP('#{htx[:successfully_finished_at]}'))," \
22
+ "'#{htx[:trading_partner_information][:username]}'," \
23
+ "#{det_val2(htx)}"
24
+ end
25
+
26
+ # @param (see #det_val1)
27
+ # @return [String] valores formatados det (trades parte2)
28
+ def det_val2(htx)
29
+ "'#{htx[:trade_id]}'," \
30
+ "DATETIME(TIMESTAMP('#{htx[:trade_marked_as_paid_at]}'))," \
31
+ "#{Integer(ops[:h][htx[:trade_id]] || 0)})"
32
+ end
33
+
34
+ # @return [String] comando insert SQL formatado ust (trades)
35
+ def ust_ins
36
+ "insert #{BD}.ust(txid,ordertxid,pair,time,type,ordertype,price,cost,fee,vol,margin,misc,ledgers,dias) " \
37
+ "VALUES#{apius.trades.map { |k, v| ust_val1(k, v) }.join(',')}"
38
+ end
39
+
40
+ # @example (see Apius#trades)
41
+ # @param [String] idx identificador transacao
42
+ # @param [Hash] htx transacao trade apius
43
+ # @return [String] valores formatados ust (trades parte1)
44
+ def ust_val1(idx, htx)
45
+ "('#{idx}'," \
46
+ "'#{htx[:ordertxid]}'," \
47
+ "'#{htx[:pair]}'," \
48
+ "PARSE_DATETIME('%s', '#{String(htx[:time].round)}')," \
49
+ "'#{htx[:type]}'," \
50
+ "'#{htx[:ordertype]}'," \
51
+ "cast(#{htx[:price]} as numeric)," \
52
+ "cast(#{htx[:cost]} as numeric)," \
53
+ "cast(#{htx[:fee]} as numeric)," \
54
+ "#{ust_val2(idx, htx)}"
55
+ end
56
+
57
+ # @param (see #ust_val1)
58
+ # @return [String] valores formatados ust (trades parte2)
59
+ def ust_val2(idx, htx)
60
+ "cast(#{htx[:vol]} as numeric)," \
61
+ "cast(#{htx[:margin]} as numeric)," \
62
+ "#{htx[:misc].to_s.empty? ? 'null' : "'#{htx[:misc]}'"}," \
63
+ "'#{apius.ledger.select { |_, v| v[:refid] == idx }.keys.join(',') || ''}'," \
64
+ "#{Integer(ops[:h][idx] || 0)})"
65
+ end
66
+
67
+ # @return [String] comando insert SQL formatado del (ledger)
68
+ def del_ins
69
+ "insert #{BD}.del(time,tp,qtxt,id,qt,fee,lgid) VALUES#{apide.ledger.map { |h| del_val(h) }.join(',')}"
70
+ end
71
+
72
+ # @example (see Apide#deposit_hash)
73
+ # @example (see Apide#withdrawal_hash)
74
+ # @param [Hash] hlx transacao uniformizada deposits + withdrawals apide
75
+ # @return [String] valores formatados del (ledger)
76
+ def del_val(hlx)
77
+ "(DATETIME(TIMESTAMP('#{hlx[:time].iso8601}'))," \
78
+ "'#{hlx[:tp]}'," \
79
+ "'#{hlx[:qtxt]}'," \
80
+ "'#{hlx[:id]}'," \
81
+ "cast(#{hlx[:tp] == 'out' ? '-' : ''}#{hlx[:qt]} as numeric)," \
82
+ "cast(#{hlx[:fee]} as numeric)," \
83
+ "#{hlx[:lgid]})"
84
+ end
85
+
86
+ # @return [String] comando insert SQL formatado usl (ledger)
87
+ def usl_ins
88
+ "insert #{BD}.usl(txid,refid,time,type,aclass,asset,amount,fee) " \
89
+ "VALUES#{apius.ledger.map { |k, v| usl_val(k, v) }.join(',')}"
90
+ end
91
+
92
+ # @example (see Apius#ledger)
93
+ # @param idx (see #ust_val1)
94
+ # @param [Hash] hlx transacao ledger apius
95
+ # @return [String] valores formatados usl (ledger)
96
+ def usl_val(idx, hlx)
97
+ "('#{idx}'," \
98
+ "'#{hlx[:refid]}'," \
99
+ "PARSE_DATETIME('%s', '#{String(hlx[:time].round)}')," \
100
+ "'#{hlx[:type]}'," \
101
+ "#{hlx[:aclass].to_s.empty? ? 'null' : "'#{hlx[:aclass]}'"}," \
102
+ "'#{hlx[:asset]}'," \
103
+ "cast(#{hlx[:amount]} as numeric)," \
104
+ "cast(#{hlx[:fee]} as numeric))"
105
+ end
106
+
107
+ # @return [String] comando insert SQL formatado fr (ledger)
108
+ def frl_ins
109
+ "insert #{BD}.fr(uuid,tipo,valor,moe,time,dias) VALUES#{apifr.ledger.map { |h| frl_val(h) }.join(',')}"
110
+ end
111
+
112
+ # @example (see Apifr#ledger)
113
+ # @param [Hash] hlx transacao ledger apifr
114
+ # @return [String] valores formatados frl (ledger)
115
+ def frl_val(hlx)
116
+ "('#{hlx[:uuid]}'," \
117
+ "'#{hlx[:name]}'," \
118
+ "cast(#{hlx[:amount]} as numeric)," \
119
+ "'#{hlx[:currency]}'," \
120
+ "PARSE_DATETIME('%s', '#{hlx[:created_at_int]}')," \
121
+ "#{Integer(ops[:h][hlx[:uuid]] || 0)})"
122
+ end
123
+
124
+ # @return [String] comando insert SQL formatado fr (ledger)
125
+ def mtl_ins
126
+ "insert #{BD}.mt(id,time,type,valor,moe,pair,note,trade_id,dias) " \
127
+ "VALUES#{apimt.ledger.map { |h| mtl_val1(h) }.join(',')}"
128
+ end
129
+
130
+ # @example (see Apimt#ledger)
131
+ # @param [Hash] hlx transacao ledger apimt
132
+ # @return [String] valores formatados mtl (ledger parte1)
133
+ def mtl_val1(hlx)
134
+ "(#{hlx[:id]}," \
135
+ "DATETIME(TIMESTAMP('#{hlx[:date]}'))," \
136
+ "'#{hlx[:type]}'," \
137
+ "cast(#{hlx[:price]} as numeric)," \
138
+ "'#{hlx[:currency]}'," \
139
+ "#{hlx[:fund_id].to_s.empty? ? 'null' : "'#{hlx[:fund_id]}'"}," \
140
+ "#{mtl_val2(hlx)}"
141
+ end
142
+
143
+ # @param hlx (see #mtl_val1)
144
+ # @return [String] valores formatados mtl (ledger parte2)
145
+ def mtl_val2(hlx)
146
+ "#{hlx[:note].to_s.empty? ? 'null' : "'#{hlx[:note]}'"}," \
147
+ "#{hlx[:trade_id].to_s.empty? ? 'null' : (hlx[:trade_id]).to_s}," \
148
+ "#{Integer(ops[:h][String(hlx[:id])] || 0)})"
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('bigdecimal/util')
4
+
5
+ # @author Hernani Rodrigues Vaz
6
+ module Cns
7
+ # classe para processar saldos & transacoes trades e ledger do bitcoinde
8
+ class Bitcoinde
9
+ # @return [Apius] API bitcoinde
10
+ attr_reader :api
11
+ # @return [Array<Hash>] todos os dados bigquery
12
+ attr_reader :dbq
13
+ # @return [Thor::CoreExt::HashWithIndifferentAccess] opcoes trabalho
14
+ attr_reader :ops
15
+
16
+ # @param [Hash] dad todos os dados bigquery
17
+ # @param [Thor::CoreExt::HashWithIndifferentAccess] pop opcoes trabalho
18
+ # @option pop [Hash] :h ({}) configuracao dias ajuste reposicionamento temporal
19
+ # @option pop [Boolean] :v (false) mostra dados transacoes trades & ledger?
20
+ # @option pop [Boolean] :t (false) mostra transacoes todas ou somente novas?
21
+ # @return [Bitcoinde] API bitcoinde - obter saldos & transacoes trades e ledger
22
+ def initialize(dad, pop)
23
+ # API bitcoinde base
24
+ @api = Apide.new
25
+ @dbq = dad
26
+ @ops = pop
27
+ end
28
+
29
+ # @return [Hash] dados exchange bitcoinde - saldos & transacoes trades e ledger
30
+ def exd
31
+ @exd ||= {
32
+ sl: api.account,
33
+ tt: api.trades,
34
+ tl: api.deposits + api.withdrawals
35
+ }
36
+ end
37
+
38
+ # @return [Array<String>] lista txid de transacoes trades
39
+ def kyt
40
+ @kyt ||= exd[:tt].map { |h| h[:trade_id] }.flatten - (ops[:t] ? [] : dbq[:nt].map { |e| e[:txid] })
41
+ end
42
+
43
+ # @return [Array<Integer>] lista txid de transacoes ledger
44
+ def kyl
45
+ @kyl ||= exd[:tl].map { |h| h[:lgid] }.flatten - (ops[:t] ? [] : dbq[:nl].map { |e| e[:txid] })
46
+ end
47
+
48
+ # @return [Hash] transacoes trades
49
+ def trades
50
+ @trades ||= exd[:tt].select { |h| kyt.include?(h[:trade_id]) }
51
+ end
52
+
53
+ # @return [Hash] transacoes ledger
54
+ def ledger
55
+ @ledger ||= exd[:tl].select { |h| kyl.include?(h[:lgid]) }
56
+ end
57
+
58
+ # @example (see Apide#account)
59
+ # @param [String] moe codigo bitcoinde da moeda
60
+ # @param [Hash] hsx saldo bitcoinde da moeda
61
+ # @return [String] texto formatado saldos (bitcoinde)
62
+ def formata_saldos(moe, hsx)
63
+ b = dbq[:sl][moe.downcase.to_sym].to_d
64
+ e = hsx[:total_amount].to_d
65
+ format(
66
+ '%<mo>-5.5s %<ex>21.9f %<bq>21.9f %<ok>3.3s',
67
+ mo: moe.upcase,
68
+ ex: e,
69
+ bq: b,
70
+ ok: e == b ? 'OK' : 'NOK'
71
+ )
72
+ end
73
+
74
+ # @example (see Apide#trades)
75
+ # @param (see Bigquery#det_val1)
76
+ # @return [String] texto formatado transacao trade
77
+ def formata_trades(htx)
78
+ format(
79
+ '%<ky>-6.6s %<dt>19.19s %<dp>10.10s %<ty>-5.5s %<mo>-8.8s %<vl>18.8f %<co>8.2f',
80
+ ky: htx[:trade_id],
81
+ dt: Time.parse(htx[:successfully_finished_at]),
82
+ dp: Time.parse(htx[:trade_marked_as_paid_at]),
83
+ ty: htx[:type],
84
+ mo: htx[:trading_pair].upcase,
85
+ vl: htx[:amount_currency_to_trade].to_d,
86
+ co: htx[:volume_currency_to_pay].to_d
87
+ )
88
+ end
89
+
90
+ # @example (see Apide#deposit_hash)
91
+ # @example (see Apide#withdrawal_hash)
92
+ # @param (see Bigquery#del_val)
93
+ # @return [String] texto formatado transacao ledger
94
+ def formata_ledger(hlx)
95
+ format(
96
+ '%<ky>6i %<dt>19.19s %<ty>-10.10s %<mo>-3.3s %<pr>19.8f %<vl>18.8f',
97
+ ky: hlx[:lgid],
98
+ dt: hlx[:time],
99
+ ty: hlx[:tp],
100
+ mo: hlx[:qtxt].upcase,
101
+ pr: hlx[:qt].to_d,
102
+ vl: hlx[:fee].to_d
103
+ )
104
+ end
105
+
106
+ # @return [String] texto saldos & transacoes & ajuste dias
107
+ def mostra_resumo
108
+ puts("\nBITCOINDE\nmoeda saldo bitcoinde saldo bigquery")
109
+ exd[:sl].each { |k, v| puts(formata_saldos(k, v)) }
110
+
111
+ mostra_trades
112
+ mostra_ledger
113
+ return unless trades.count.positive?
114
+
115
+ puts("\nstring ajuste dias dos trades\n-h=#{kyt.map { |e| "#{e}:0" }.join(' ')}")
116
+ end
117
+
118
+ # @return [String] texto transacoes trades
119
+ def mostra_trades
120
+ return unless ops[:v] && trades.count.positive?
121
+
122
+ puts("\ntrades data hora dt criacao tipo par ---------------qtd -----eur")
123
+ trades.sort { |a, b| Time.parse(b[:successfully_finished_at]) <=> Time.parse(a[:successfully_finished_at]) }
124
+ .each { |h| puts(formata_trades(h)) }
125
+ end
126
+
127
+ # @return [String] texto transacoes ledger
128
+ def mostra_ledger
129
+ return unless ops[:v] && ledger.count.positive?
130
+
131
+ puts("\nledger data hora tipo moe ---------quantidade -------------custo")
132
+ ledger.sort { |a, b| b[:time] <=> a[:time] }.each { |h| puts(formata_ledger(h)) }
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('bigdecimal/util')
4
+
5
+ # @author Hernani Rodrigues Vaz
6
+ module Cns
7
+ # chaves a eliminar da API - resultado deve ser ignirado pois muda a cada pedido API feito
8
+ DL = %i[cumulativeGasUsed confirmations].freeze
9
+
10
+ # (see Etherscan)
11
+ class Etherscan
12
+ # @return [Apies] API etherscan
13
+ attr_reader :api
14
+ # @return [Array<Hash>] todos os dados bigquery
15
+ attr_reader :dbq
16
+ # @return [Thor::CoreExt::HashWithIndifferentAccess] opcoes trabalho
17
+ attr_reader :ops
18
+
19
+ # @param [Hash] dad todos os dados bigquery
20
+ # @param [Thor::CoreExt::HashWithIndifferentAccess] pop opcoes trabalho
21
+ # @option pop [Hash] :h ({}) configuracao dias ajuste reposicionamento temporal
22
+ # @option pop [Boolean] :v (false) mostra dados transacoes normais & tokens?
23
+ # @return [Etherscan] API etherscan - processar transacoes normais e tokens
24
+ def initialize(dad, pop)
25
+ @api = Apies.new
26
+ @dbq = dad
27
+ @ops = pop
28
+ end
29
+
30
+ # @return [Array<String>] lista dos meus enderecos
31
+ def lax
32
+ @lax ||= dbq[:wb].map { |h| h[:ax] }
33
+ end
34
+
35
+ # @return [Array<Hash>] todos os dados etherscan - saldos & transacoes
36
+ def dbc
37
+ @dbc ||= api.account(lax).map { |e| base_bc(e) }
38
+ end
39
+
40
+ # @return [Array<Hash>] todos os dados juntos bigquery & etherscan
41
+ def dados
42
+ @dados ||= dbq[:wb].map { |b| bq_bc(b, dbc.select { |s| b[:ax] == s[:ax] }.first) }
43
+ end
44
+
45
+ # @return [Array<Integer>] lista indices transacoes normais novas
46
+ def bnt
47
+ @bnt ||= (dbc.map { |e| e[:tx].map { |n| n[:itx] } }.flatten - (ops[:t] ? [] : dbq[:nt].map { |t| t[:itx] }))
48
+ end
49
+
50
+ # @return [Array<Integer>] lista indices transacoes token novas
51
+ def bnk
52
+ @bnk ||= (dbc.map { |e| e[:kx].map { |n| n[:itx] } }.flatten - (ops[:t] ? [] : dbq[:nk].map { |t| t[:itx] }))
53
+ end
54
+
55
+ # @return [Array<Hash>] lista transacoes normais novas
56
+ def novtx
57
+ @novtx ||= dbc.map { |e| e[:tx].select { |n| bnt.include?(n[:itx]) } }.flatten
58
+ end
59
+
60
+ # @return [Array<Hash>] lista transacoes token novas
61
+ def novkx
62
+ @novkx ||= dbc.map { |e| e[:kx].select { |n| bnk.include?(n[:itx]) } }.flatten
63
+ end
64
+
65
+ # @param [Hash] hbc dados etherscan
66
+ # @return [Hash] dados etherscan - address, saldo & transacoes
67
+ def base_bc(hbc)
68
+ a = hbc[:account]
69
+ {
70
+ ax: a,
71
+ sl: (hbc[:balance].to_d / 10**18).round(10),
72
+ tx: filtrar_tx(a, api.norml_tx(a)),
73
+ kx: filtrar_tx(a, api.token_tx(a))
74
+ }
75
+ end
76
+
77
+ # @param [Hash] hbq dados bigquery
78
+ # @param hbc (see base_bc)
79
+ # @return [Hash] dados juntos bigquery & etherscan
80
+ def bq_bc(hbq, hbc)
81
+ {
82
+ id: hbq[:id],
83
+ ax: hbq[:ax],
84
+ bs: hbq[:sl],
85
+ bt: dbq[:nt].select { |t| t[:iax] == hbq[:ax] },
86
+ bk: dbq[:nk].select { |t| t[:iax] == hbq[:ax] },
87
+ es: hbc[:sl],
88
+ et: hbc[:tx],
89
+ ek: hbc[:kx]
90
+ }
91
+ end
92
+
93
+ # @param [String] add endereco carteira ETH
94
+ # @param [Array<Hash>] ary lista das transacoes
95
+ # @return [Array<Hash>] devolve lista de transacoes/token transfer events filtrada
96
+ def filtrar_tx(add, ary)
97
+ # elimina transferencia from: (lax) to: (add) - esta transferencia aparece em from: (add) to: (lax)
98
+ # elimina chaves irrelevantes (DL) & adiciona chave indice itx & adiciona identificador da carteira iax
99
+ ary.delete_if { |h| h[:to] == add && lax.include?(h[:from]) }
100
+ .map { |h| h.delete_if { |k, _| DL.include?(k) }.merge(itx: Integer(h[:blockNumber]), iax: add) }
101
+ end
102
+
103
+ # @return [Array<Hash>] lista ordenada transacoes normais novas
104
+ def sortx
105
+ novtx.sort { |a, b| a[:itx] <=> b[:itx] }
106
+ end
107
+
108
+ # @return [Array<Hash>] lista ordenada transacoes token novas
109
+ def sorkx
110
+ novkx.sort { |a, b| a[:itx] <=> b[:itx] }
111
+ end
112
+
113
+ # @return [Array<Hash>] lista ordenada transacoes (normais & token) novas
114
+ def sorax
115
+ (novtx + novkx).sort { |a, b| a[:itx] <=> b[:itx] }
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @author Hernani Rodrigues Vaz
4
+ module Cns
5
+ # classe para processar carteiras & transacoes normais e tokens
6
+ class Etherscan
7
+ # @param [Hash] hjn dados juntos bigquery & etherscan
8
+ # @return [String] texto formatado duma carteira
9
+ def formata_carteira(hjn)
10
+ format(
11
+ '%<s1>-6.6s %<s2>-32.32s ',
12
+ s1: hjn[:id],
13
+ s2: formata_endereco(hjn[:ax], 32)
14
+ ) + formata_valores(hjn)
15
+ end
16
+
17
+ # @param (see formata_carteira)
18
+ # @return [String] texto formatado valores duma carteira
19
+ def formata_valores(hjn)
20
+ format(
21
+ '%<v1>11.6f %<n1>2i %<n3>2i %<v2>12.6f %<n2>2i %<n4>2i %<ok>-3s',
22
+ v1: hjn[:bs],
23
+ n1: hjn[:bt].count,
24
+ n3: hjn[:bk].count,
25
+ v2: hjn[:es],
26
+ n2: hjn[:et].count,
27
+ n4: hjn[:ek].count,
28
+ ok: ok?(hjn) ? 'OK' : 'NOK'
29
+ )
30
+ end
31
+
32
+ # @param (see formata_carteira)
33
+ # @return [Boolean] carteira tem transacoes novas(sim=NOK, nao=OK)?
34
+ def ok?(hjn)
35
+ hjn[:bs] == hjn[:es] && hjn[:bt].count == hjn[:et].count && hjn[:bk].count == hjn[:ek].count
36
+ end
37
+
38
+ # @example ether address inicio..fim
39
+ # 0x10f3a0cf0b534c..c033cf32e8a03586
40
+ # @param add (see filtrar_tx)
41
+ # @param [Integer] max chars a mostrar
42
+ # @return [String] endereco formatado
43
+ def formata_endereco(add, max)
44
+ i = Integer((max - 2) / 2)
45
+ e = (max <= 20 ? dbq[:wb].select { |s| s[:ax] == add }.first : nil) || { id: add }
46
+ max < 7 ? 'erro' : "#{e[:id][0, i - 3]}..#{add[-i - 3..]}"
47
+ end
48
+
49
+ # @param [Hash] htx transacao normal
50
+ # @return [String] texto formatado transacao normal
51
+ def formata_transacao_norml(htx)
52
+ format(
53
+ '%<bn>9i %<fr>-20.20s %<to>-20.20s %<dt>10.10s %<vl>17.6f',
54
+ bn: htx[:blockNumber],
55
+ fr: formata_endereco(htx[:from], 20),
56
+ to: formata_endereco(htx[:to], 20),
57
+ dt: Time.at(Integer(htx[:timeStamp])),
58
+ vl: (htx[:value].to_d / 10**18).round(10)
59
+ )
60
+ end
61
+
62
+ # @param [Hash] hkx transacao token
63
+ # @return [String] texto formatado transacao token
64
+ def formata_transacao_token(hkx)
65
+ format(
66
+ '%<bn>9i %<fr>-20.20s %<to>-20.20s %<dt>10.10s %<vl>11.3f %<sy>-5.5s',
67
+ bn: hkx[:blockNumber],
68
+ fr: formata_endereco(hkx[:from], 20),
69
+ to: formata_endereco(hkx[:to], 20),
70
+ dt: Time.at(Integer(hkx[:timeStamp])),
71
+ vl: (hkx[:value].to_d / 10**18).round(10),
72
+ sy: hkx[:tokenSymbol]
73
+ )
74
+ end
75
+
76
+ # @return [String] texto carteiras & transacoes & ajuste dias
77
+ def mostra_resumo
78
+ return unless dados.count.positive?
79
+
80
+ puts("\nid address bigquery nm tk etherscan nm tk")
81
+ dados.each { |e| puts(formata_carteira(e)) }
82
+ mostra_transacao_norml
83
+ mostra_transacao_token
84
+ mostra_configuracao_ajuste_dias
85
+ end
86
+
87
+ # @return [String] texto transacoes normais
88
+ def mostra_transacao_norml
89
+ return unless ops[:v] && novtx.count.positive?
90
+
91
+ puts("\ntx normal from to data valor")
92
+ sortx.each { |e| puts(formata_transacao_norml(e)) }
93
+ end
94
+
95
+ # @return [String] texto transacoes token
96
+ def mostra_transacao_token
97
+ return unless ops[:v] && novkx.count.positive?
98
+
99
+ puts("\ntx token from to data valor")
100
+ sorkx.each { |e| puts(formata_transacao_token(e)) }
101
+ end
102
+
103
+ # @return [String] texto configuracao ajuste dias das transacoes (normais & token)
104
+ def mostra_configuracao_ajuste_dias
105
+ return unless (novtx.count + novkx.count).positive?
106
+
107
+ puts("\nstring ajuste dias\n-h=#{sorax.map { |e| "#{e[:blockNumber]}:0" }.join(' ')}")
108
+ end
109
+ end
110
+ end