cns 0.1.0 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('bigdecimal/util')
4
+
5
+ # @author Hernani Rodrigues Vaz
6
+ module Cns
7
+ # classe para processar transacoes trades/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 :bqd
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 = Apice.new
24
+ @bqd = dad
25
+ @ops = pop
26
+ end
27
+
28
+ # @return [Array<Hash>] lista trades bitcoinde novos
29
+ def trades
30
+ @trades ||= exd[:tt].select { |h| kyt.include?(h[:trade_id]) }
31
+ end
32
+
33
+ # @return [Array<Hash>] lista ledger (deposits + withdrawals) bitcoinde novos
34
+ def ledger
35
+ @ledger ||= exd[:tl].select { |h| kyl.include?(h[:txid]) }
36
+ end
37
+
38
+ # @return [String] texto saldos & transacoes & ajuste dias
39
+ def mostra_resumo
40
+ puts("\nBITCOINDE\ntipo bitcoinde bigquery")
41
+ exd[:sl].each { |k, v| puts(formata_saldos(k, v)) }
42
+ mostra_totais
43
+
44
+ mostra_trades
45
+ mostra_ledger
46
+ return if trades.empty?
47
+
48
+ puts("\nstring ajuste dias dos trades\n-h=#{kyt.map { |e| "#{e}:0" }.join(' ')}")
49
+ end
50
+
51
+ # @return [Hash] dados exchange bitcoinde - saldos & trades & deposits & withdrawals
52
+ def exd
53
+ @exd ||= {
54
+ sl: api.account_de,
55
+ tt: api.trades_de,
56
+ tl: api.deposits_de + api.withdrawals_de
57
+ }
58
+ end
59
+
60
+ # @return [Array<String>] lista txid dos trades novos
61
+ def kyt
62
+ @kyt ||= exd[:tt].map { |h| h[:trade_id] }.flatten - (ops[:t] ? [] : bqd[:nt].map { |e| e[:txid] })
63
+ end
64
+
65
+ # @return [Array<Integer>] lista txid dos ledger novos
66
+ def kyl
67
+ @kyl ||= exd[:tl].map { |h| h[:txid] }.flatten - (ops[:t] ? [] : bqd[:nl].map { |e| e[:txid] })
68
+ end
69
+
70
+ # @example (see Apice#account_de)
71
+ # @param [String] moe codigo bitcoinde da moeda
72
+ # @param [Hash] hsx saldo bitcoinde da moeda
73
+ # @return [String] texto formatado saldos
74
+ def formata_saldos(moe, hsx)
75
+ b = bqd[:sl][moe.downcase.to_sym].to_d
76
+ e = hsx[:total_amount].to_d
77
+ format(
78
+ '%<mo>-5.5s %<ex>21.9f %<bq>21.9f %<ok>3.3s',
79
+ mo: moe.upcase,
80
+ ex: e,
81
+ bq: b,
82
+ ok: e == b ? 'OK' : 'NOK'
83
+ )
84
+ end
85
+
86
+ # @example (see Apice#trades_de)
87
+ # @param (see Bigquery#det_val1)
88
+ # @return [String] texto formatado trade
89
+ def formata_trades(htx)
90
+ format(
91
+ '%<ky>-6.6s %<dt>19.19s %<dp>10.10s %<ty>-5.5s %<mo>-8.8s %<vl>18.8f %<co>8.2f',
92
+ ky: htx[:trade_id],
93
+ dt: Time.parse(htx[:successfully_finished_at]),
94
+ dp: Time.parse(htx[:trade_marked_as_paid_at]),
95
+ ty: htx[:type],
96
+ mo: htx[:trading_pair].upcase,
97
+ vl: htx[:amount_currency_to_trade].to_d,
98
+ co: htx[:volume_currency_to_pay].to_d
99
+ )
100
+ end
101
+
102
+ # @example (see Apice#deposits_unif_de)
103
+ # @example (see Apice#withdrawals_unif_de)
104
+ # @param (see Bigquery#del_val)
105
+ # @return [String] texto formatado ledger
106
+ def formata_ledger(hlx)
107
+ format(
108
+ '%<ky>6i %<dt>19.19s %<ty>-10.10s %<mo>-3.3s %<pr>19.8f %<vl>18.8f',
109
+ ky: hlx[:txid],
110
+ dt: hlx[:time],
111
+ ty: hlx[:tp],
112
+ mo: hlx[:moe].upcase,
113
+ pr: hlx[:qt].to_d,
114
+ vl: hlx[:fee].to_d
115
+ )
116
+ end
117
+
118
+ # @return [String] texto numero de transacoes
119
+ def mostra_totais
120
+ a = exd[:tt].count
121
+ b = bqd[:nt].count
122
+ c = exd[:tl].count
123
+ d = bqd[:nl].count
124
+
125
+ puts("TRADES #{format('%<a>20i %<b>21i %<o>3.3s', a: a, b: b, o: a == b ? 'OK' : 'NOK')}")
126
+ puts("LEDGER #{format('%<c>20i %<d>21i %<o>3.3s', c: c, d: d, o: c == d ? 'OK' : 'NOK')}")
127
+ end
128
+
129
+ # @return [String] texto transacoes trades
130
+ def mostra_trades
131
+ return unless ops[:v] && !trades.empty?
132
+
133
+ puts("\ntrades data hora dt criacao tipo par qtd eur")
134
+ trades.sort { |a, b| Time.parse(b[:successfully_finished_at]) <=> Time.parse(a[:successfully_finished_at]) }
135
+ .each { |h| puts(formata_trades(h)) }
136
+ end
137
+
138
+ # @return [String] texto transacoes ledger
139
+ def mostra_ledger
140
+ return unless ops[:v] && !ledger.empty?
141
+
142
+ puts("\nledger data hora tipo moe quantidade custo")
143
+ ledger.sort { |a, b| b[:time] <=> a[:time] }.each { |h| puts(formata_ledger(h)) }
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,119 @@
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 [Apibc] API blockchains
13
+ attr_reader :api
14
+ # @return [Array<Hash>] todos os dados bigquery
15
+ attr_reader :bqd
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 = Apibc.new
26
+ @bqd = dad
27
+ @ops = pop
28
+ end
29
+
30
+ # @return [Array<Hash>] lista transacoes normais novas
31
+ def novtx
32
+ @novtx ||= bcd.map { |e| e[:tx].select { |n| idt.include?(n[:itx]) } }.flatten
33
+ end
34
+
35
+ # @return [Array<Hash>] lista transacoes token novas
36
+ def novkx
37
+ @novkx ||= bcd.map { |e| e[:kx].select { |n| idk.include?(n[:itx]) } }.flatten
38
+ end
39
+
40
+ # @return [Array<String>] lista dos meus enderecos
41
+ def lax
42
+ @lax ||= bqd[:wb].map { |h| h[:ax] }
43
+ end
44
+
45
+ # @return [Array<Hash>] todos os dados etherscan - saldos & transacoes
46
+ def bcd
47
+ @bcd ||= api.account_es(lax).map { |e| base_bc(e) }
48
+ end
49
+
50
+ # @return [Array<Hash>] todos os dados juntos bigquery & etherscan
51
+ def dados
52
+ @dados ||= bqd[:wb].map { |b| bq_bc(b, bcd.select { |s| b[:ax] == s[:ax] }.first) }
53
+ end
54
+
55
+ # @return [Array<Integer>] lista indices transacoes normais novas
56
+ def idt
57
+ @idt ||= (bcd.map { |e| e[:tx].map { |n| n[:itx] } }.flatten - (ops[:t] ? [] : bqd[:nt].map { |t| t[:itx] }))
58
+ end
59
+
60
+ # @return [Array<Integer>] lista indices transacoes token novas
61
+ def idk
62
+ @idk ||= (bcd.map { |e| e[:kx].map { |n| n[:itx] } }.flatten - (ops[:t] ? [] : bqd[:nk].map { |t| t[:itx] }))
63
+ end
64
+
65
+ # @example (see Apibc#account_es)
66
+ # @param [Hash] abc account etherscan
67
+ # @return [Hash] dados etherscan - address, saldo & transacoes
68
+ def base_bc(abc)
69
+ a = abc[:account]
70
+ {
71
+ ax: a,
72
+ sl: (abc[:balance].to_d / 10**18).round(10),
73
+ tx: filtrar_tx(a, api.norml_es(a)),
74
+ kx: filtrar_tx(a, api.token_es(a))
75
+ }
76
+ end
77
+
78
+ # @param [Hash] wbq wallet bigquery
79
+ # @param [Hash] hbc dados etherscan - address, saldo & transacoes
80
+ # @return [Hash] dados juntos bigquery & etherscan
81
+ def bq_bc(wbq, hbc)
82
+ {
83
+ id: wbq[:id],
84
+ ax: wbq[:ax],
85
+ bs: wbq[:sl],
86
+ bt: bqd[:nt].select { |t| t[:iax] == wbq[:ax] },
87
+ bk: bqd[:nk].select { |t| t[:iax] == wbq[:ax] },
88
+ es: hbc[:sl],
89
+ et: hbc[:tx],
90
+ ek: hbc[:kx]
91
+ }
92
+ end
93
+
94
+ # @param add (see Apibc#norml_es)
95
+ # @param [Array<Hash>] ary lista transacoes/token events
96
+ # @return [Array<Hash>] lista transacoes/token events filtrada
97
+ def filtrar_tx(add, ary)
98
+ # elimina transferencia from: (lax) to: (add) - esta transferencia aparece em from: (add) to: (lax)
99
+ # elimina chaves irrelevantes (DL) & adiciona chave indice itx & adiciona identificador da carteira iax
100
+ ary.delete_if { |h| h[:to] == add && lax.include?(h[:from]) }
101
+ .map { |h| h.delete_if { |k, _| DL.include?(k) }.merge(itx: Integer(h[:blockNumber]), iax: add) }
102
+ end
103
+
104
+ # @return [Array<Hash>] lista ordenada transacoes normais novas
105
+ def sortx
106
+ novtx.sort { |a, b| a[:itx] <=> b[:itx] }
107
+ end
108
+
109
+ # @return [Array<Hash>] lista ordenada transacoes token novas
110
+ def sorkx
111
+ novkx.sort { |a, b| a[:itx] <=> b[:itx] }
112
+ end
113
+
114
+ # @return [Array<Hash>] lista ordenada transacoes (normais & token) novas
115
+ def sorax
116
+ (novtx + novkx).sort { |a, b| a[:itx] <=> b[:itx] }
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @author Hernani Rodrigues Vaz
4
+ module Cns
5
+ # classe para processar transacoes do etherscan
6
+ class Etherscan
7
+ # @return [String] texto carteiras & transacoes & ajuste dias
8
+ def mostra_resumo
9
+ return unless dados.count.positive?
10
+
11
+ puts("\nid address etherscan nm tk bigquery nm tk")
12
+ dados.each { |e| puts(formata_carteira(e)) }
13
+ mostra_transacao_norml
14
+ mostra_transacao_token
15
+ mostra_configuracao_ajuste_dias
16
+ end
17
+
18
+ # @param [Hash] hjn dados juntos bigquery & etherscan
19
+ # @return [String] texto formatado duma carteira
20
+ def formata_carteira(hjn)
21
+ format(
22
+ '%<s1>-6.6s %<s2>-32.32s ',
23
+ s1: hjn[:id],
24
+ s2: formata_endereco(hjn[:ax], 32)
25
+ ) + formata_valores(hjn)
26
+ end
27
+
28
+ # @param (see formata_carteira)
29
+ # @return [String] texto formatado valores duma carteira
30
+ def formata_valores(hjn)
31
+ format(
32
+ '%<v1>11.6f %<n1>2i %<n3>2i %<v2>12.6f %<n2>2i %<n4>2i %<ok>-3s',
33
+ v1: hjn[:es],
34
+ n1: hjn[:et].count,
35
+ n3: hjn[:ek].count,
36
+ v2: hjn[:bs],
37
+ n2: hjn[:bt].count,
38
+ n4: hjn[:bk].count,
39
+ ok: ok?(hjn) ? 'OK' : 'NOK'
40
+ )
41
+ end
42
+
43
+ # @param (see formata_carteira)
44
+ # @return [Boolean] carteira tem transacoes novas(sim=NOK, nao=OK)?
45
+ def ok?(hjn)
46
+ hjn[:bs] == hjn[:es] && hjn[:bt].count == hjn[:et].count && hjn[:bk].count == hjn[:ek].count
47
+ end
48
+
49
+ # @example ether address inicio..fim
50
+ # 0x10f3a0cf0b534c..c033cf32e8a03586
51
+ # @param add (see filtrar_tx)
52
+ # @param [Integer] max chars a mostrar
53
+ # @return [String] endereco formatado
54
+ def formata_endereco(add, max)
55
+ i = Integer((max - 2) / 2)
56
+ e = (max <= 20 ? bqd[:wb].select { |s| s[:ax] == add }.first : nil) || { id: add }
57
+ max < 7 ? 'erro' : "#{e[:id][0, i - 3]}..#{add[-i - 3..]}"
58
+ end
59
+
60
+ # @example (see Apibc#norml_es)
61
+ # @param [Hash] htx transacao normal etherscan
62
+ # @return [String] texto formatado transacao normal etherscan
63
+ def formata_transacao_norml(htx)
64
+ format(
65
+ '%<bn>9i %<fr>-20.20s %<to>-20.20s %<dt>10.10s %<vl>17.6f',
66
+ bn: htx[:blockNumber],
67
+ fr: formata_endereco(htx[:from], 20),
68
+ to: formata_endereco(htx[:to], 20),
69
+ dt: Time.at(Integer(htx[:timeStamp])),
70
+ vl: (htx[:value].to_d / 10**18).round(10)
71
+ )
72
+ end
73
+
74
+ # @example (see Apibc#token_es)
75
+ # @param [Hash] hkx transacao token etherscan
76
+ # @return [String] texto formatado transacao token etherscan
77
+ def formata_transacao_token(hkx)
78
+ format(
79
+ '%<bn>9i %<fr>-20.20s %<to>-20.20s %<dt>10.10s %<vl>11.3f %<sy>-5.5s',
80
+ bn: hkx[:blockNumber],
81
+ fr: formata_endereco(hkx[:from], 20),
82
+ to: formata_endereco(hkx[:to], 20),
83
+ dt: Time.at(Integer(hkx[:timeStamp])),
84
+ vl: (hkx[:value].to_d / 10**18).round(10),
85
+ sy: hkx[:tokenSymbol]
86
+ )
87
+ end
88
+
89
+ # @return [String] texto transacoes normais
90
+ def mostra_transacao_norml
91
+ return unless ops[:v] && novtx.count.positive?
92
+
93
+ puts("\ntx normal from to data valor")
94
+ sortx.each { |e| puts(formata_transacao_norml(e)) }
95
+ end
96
+
97
+ # @return [String] texto transacoes token
98
+ def mostra_transacao_token
99
+ return unless ops[:v] && novkx.count.positive?
100
+
101
+ puts("\ntx token from to data valor")
102
+ sorkx.each { |e| puts(formata_transacao_token(e)) }
103
+ end
104
+
105
+ # @return [String] texto configuracao ajuste dias das transacoes (normais & token)
106
+ def mostra_configuracao_ajuste_dias
107
+ return unless (novtx.count + novkx.count).positive?
108
+
109
+ puts("\nstring ajuste dias\n-h=#{sorax.map { |e| "#{e[:blockNumber]}:0" }.join(' ')}")
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('bigdecimal/util')
4
+
5
+ # @author Hernani Rodrigues Vaz
6
+ module Cns
7
+ # (see Greymass)
8
+ class Greymass
9
+ # @return [Apibc] API blockchains
10
+ attr_reader :api
11
+ # @return [Array<Hash>] todos os dados bigquery
12
+ attr_reader :bqd
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?
20
+ # @option pop [Boolean] :t (false) mostra transacoes todas ou somente novas?
21
+ # @return [Greymass] API greymass - processar transacoes
22
+ def initialize(dad, pop)
23
+ @api = Apibc.new
24
+ @bqd = dad
25
+ @ops = pop
26
+ end
27
+
28
+ # @return [Array<Hash>] lista transacoes novas
29
+ def novax
30
+ @novax ||= bcd.map { |e| e[:tx].select { |s| idt.include?(s[:itx]) } }.flatten
31
+ end
32
+
33
+ # @return [Array<String>] lista dos meus enderecos
34
+ def lax
35
+ @lax ||= bqd[:wb].map { |h| h[:ax] }
36
+ end
37
+
38
+ # @return [Array<Hash>] todos os dados greymass - saldos & transacoes
39
+ def bcd
40
+ @bcd ||= bqd[:wb].map { |e| base_bc(e) }
41
+ end
42
+
43
+ # @return [Array<Hash>] todos os dados juntos bigquery & greymass
44
+ def dados
45
+ @dados ||= bqd[:wb].map { |b| bq_bc(b, bcd.select { |s| b[:ax] == s[:ax] }.first) }
46
+ end
47
+
48
+ # @return [Array<Integer>] lista indices transacoes novas
49
+ def idt
50
+ @idt ||= (bcd.map { |e| e[:tx].map { |n| n[:itx] } }.flatten - (ops[:t] ? [] : bqd[:nt].map { |t| t[:itx] }))
51
+ end
52
+
53
+ # @example (see Apibc#account_gm)
54
+ # @param [Hash] wbq wallet bigquery
55
+ # @return [Hash] dados greymass - address, saldo & transacoes
56
+ def base_bc(wbq)
57
+ a = wbq[:ax]
58
+ {
59
+ ax: a,
60
+ sl: greymass_sl(a).inject(:+),
61
+ tx: filtrar_tx(a, api.ledger_gm(a))
62
+ }
63
+ end
64
+
65
+ # @param wbq (see base_bc)
66
+ # @param [Hash] hbc dados greymass - address, saldo & transacoes
67
+ # @return [Hash] dados juntos bigquery & greymass
68
+ def bq_bc(wbq, hbc)
69
+ {
70
+ id: wbq[:id],
71
+ ax: wbq[:ax],
72
+ bs: wbq[:sl],
73
+ bt: bqd[:nt].select { |t| t[:iax] == wbq[:ax] },
74
+ es: hbc[:sl],
75
+ et: hbc[:tx]
76
+ }
77
+ end
78
+
79
+ # @param (see filtrar_tx)
80
+ # @return [Array<BigDecimal>] lista recursos - liquido, net, spu
81
+ def greymass_sl(add)
82
+ v = api.account_gm(add)
83
+ [
84
+ v[:core_liquid_balance].to_d,
85
+ v[:total_resources][:net_weight].to_d,
86
+ v[:total_resources][:cpu_weight].to_d
87
+ ]
88
+ end
89
+
90
+ # @param add (see Apibc#account_gm)
91
+ # @param [Array<Hash>] ary lista transacoes
92
+ # @return [Array<Hash>] lista transacoes filtrada
93
+ def filtrar_tx(add, ary)
94
+ # elimina transferencia from: (lax) to: (add) - esta transferencia aparece em from: (add) to: (lax)
95
+ # adiciona chave indice itx & adiciona identificador da carteira iax
96
+ ary.delete_if { |h| act_data(h)[:to] == add && lax.include?(act_data(h)[:from]) }
97
+ .map { |h| h.merge(itx: h[:global_action_seq], iax: add) }
98
+ end
99
+
100
+ # @return [Array<Hash>] lista ordenada transacoes novas
101
+ def sorax
102
+ novax.sort { |a, b| b[:itx] <=> a[:itx] }
103
+ end
104
+ end
105
+ end