cex 0.1.5 → 0.1.7

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,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('bigdecimal/util')
4
+
5
+ # @author Hernani Rodrigues Vaz
6
+ module Cex
7
+ # classe para processar saldos & transacoes ledger
8
+ class TheRock
9
+ # @return [Apius] API therock
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 [TheRock] API therock - obter saldos & transacoes ledger
22
+ def initialize(dad, pop)
23
+ # API therock base
24
+ @api = Apimt.new
25
+ @dbq = dad
26
+ @ops = pop
27
+ end
28
+
29
+ # @return [Hash] dados exchange therock - saldos & transacoes ledger
30
+ def exd
31
+ @exd ||= {
32
+ sl: api.account,
33
+ kl: api.ledger
34
+ }
35
+ end
36
+
37
+ # @return [Array<String>] lista txid de transacoes ledger
38
+ def kyl
39
+ @kyl ||= exd[:kl].map { |h| h[:id] } - (ops[:t] ? [] : dbq[:nl].map { |e| e[:txid] })
40
+ end
41
+
42
+ # @return [Hash] transacoes ledger
43
+ def ledger
44
+ @ledger ||= exd[:kl].select { |o| kyl.include?(o[:id]) }
45
+ end
46
+
47
+ # @example (see Apimt#account)
48
+ # @param [Hash] hsl saldo therock da moeda
49
+ # @return [String] texto formatado saldos (therock/bigquery) & iguais/ok/nok?
50
+ def formata_saldos(hsl)
51
+ b = dbq[:sl][hsl[:currency].downcase.to_sym].to_d
52
+ k = hsl[:balance].to_d
53
+ format(
54
+ '%<mo>-5.5s %<kr>21.9f %<bq>21.9f %<ok>3.3s',
55
+ mo: hsl[:currency].upcase,
56
+ kr: k,
57
+ bq: b,
58
+ ok: k == b ? 'OK' : 'NOK'
59
+ )
60
+ end
61
+
62
+ # @example (see Apimt#ledger)
63
+ # @param (see Bigquery#mtl_val1)
64
+ # @return [String] texto formatado transacao ledger
65
+ def formata_ledger(hlx)
66
+ format(
67
+ '%<ky>6i %<dt>19.19s %<ty>-27.27s %<mo>-4.4s %<vl>20.7f',
68
+ ky: hlx[:id],
69
+ dt: Time.parse(hlx[:date]),
70
+ ty: hlx[:type],
71
+ mo: hlx[:currency].upcase,
72
+ vl: hlx[:price].to_d
73
+ )
74
+ end
75
+
76
+ # @return [String] texto saldos & transacoes & ajuste dias
77
+ def mostra_resumo
78
+ puts("\nTHEROCK\nmoeda saldo therock saldo bigquery")
79
+ exd[:sl].each { |h| puts(formata_saldos(h)) }
80
+
81
+ mostra_ledger
82
+ return unless ledger.count.positive?
83
+
84
+ puts("\nstring ajuste dias da ledger\n-h=#{kyl.map { |e| "#{e}:0" }.join(' ')}")
85
+ end
86
+
87
+ # @return [String] texto transacoes ledger
88
+ def mostra_ledger
89
+ return unless ops[:v] && ledger.count.positive?
90
+
91
+ puts("\nledger data hora tipo moeda ---------quantidade")
92
+ ledger.sort { |a, b| b[:id] <=> a[:id] }.each { |o| puts(formata_ledger(o)) }
93
+ end
94
+ end
95
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cex
4
- VERSION = '0.1.5'
4
+ VERSION = '0.1.7'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hernâni Rodrigues Vaz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-02 00:00:00.000000000 Z
11
+ date: 2020-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,8 +94,8 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: Arquiva transactions kraken & bitcoinde no bigquery. Pode ajustar dias
98
- para reposicionamento temporal.
97
+ description: Arquiva transactions bitcoinde/kraken/paymium/therock no bigquery. Pode
98
+ ajustar dias para reposicionamento temporal.
99
99
  email:
100
100
  - hernanirvaz@gmail.com
101
101
  executables:
@@ -117,9 +117,16 @@ files:
117
117
  - cex.gemspec
118
118
  - exe/cex
119
119
  - lib/cex.rb
120
- - lib/cex/bigquery.rb
121
- - lib/cex/client.rb
120
+ - lib/cex/apide.rb
121
+ - lib/cex/apifr.rb
122
+ - lib/cex/apimt.rb
123
+ - lib/cex/apius.rb
124
+ - lib/cex/bigquery1.rb
125
+ - lib/cex/bigquery2.rb
126
+ - lib/cex/bitcoinde.rb
122
127
  - lib/cex/kraken.rb
128
+ - lib/cex/paymium.rb
129
+ - lib/cex/therock.rb
123
130
  - lib/cex/version.rb
124
131
  homepage: https://github.com/hernanirvaz/cex
125
132
  licenses:
@@ -145,5 +152,5 @@ requirements: []
145
152
  rubygems_version: 3.1.2
146
153
  signing_key:
147
154
  specification_version: 4
148
- summary: Arquiva transactions kraken & bitcoinde no bigquery.
155
+ summary: Arquiva transactions bitcoinde/kraken/paymium/therock no bigquery.
149
156
  test_files: []
@@ -1,126 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require('google/cloud/bigquery')
4
- require('bigdecimal/util')
5
-
6
- # @author Hernani Rodrigues Vaz
7
- module Cex
8
- BD = 'hernanirvaz.coins'
9
-
10
- # classe para processar bigquery & kraken
11
- class Bigquery
12
- # @return [Google::Cloud::Bigquery] API bigquery
13
- attr_reader :api
14
- # @return [Google::Cloud::Bigquery::QueryJob] job bigquery
15
- attr_reader :job
16
- # @return [Thor::CoreExt::HashWithIndifferentAccess] opcoes trabalho
17
- attr_reader :ops
18
- # @return (see sql)
19
- attr_reader :sqr
20
-
21
- # @param [Thor::CoreExt::HashWithIndifferentAccess] pop opcoes trabalho
22
- # @option pop [Hash] :h ({}) configuracao ajuste reposicionamento temporal
23
- # @option pop [Boolean] :v (false) mostra transacoes trades & ledger?
24
- # @option pop [Boolean] :t (false) mostra transacoes todas ou somente novas?
25
- # @return [Bigquery] API bigquery & kraken
26
- def initialize(pop)
27
- # usa env GOOGLE_APPLICATION_CREDENTIALS para obter credentials
28
- # @see https://cloud.google.com/bigquery/docs/authentication/getting-started
29
- @api = Google::Cloud::Bigquery.new
30
- @ops = pop
31
- end
32
-
33
- # @return [Kraken] API kraken - obter saldos & transacoes trades e ledger
34
- def transacoes
35
- @transacoes ||= Kraken.new(
36
- {
37
- sl: sql("select * from #{BD}.ussl")[0],
38
- nt: sql("select * from #{BD}.ustx order by time,txid"),
39
- nl: sql("select * from #{BD}.uslx order by time,txid")
40
- },
41
- ops
42
- )
43
- end
44
-
45
- # insere transacoes novas nas tabelas ust (trades), usl (ledger)
46
- def processa
47
- puts(format("%<n>2i TRADES INSERIDAS #{BD}.ust", n: transacoes.trades.count.positive? ? dml(ust_ins) : 0))
48
- puts(format("%<n>2i LEDGER INSERIDAS #{BD}.usl", n: transacoes.ledger.count.positive? ? dml(usl_ins) : 0))
49
- end
50
-
51
- # @return [String] comando insert SQL formatado ust (trades)
52
- def ust_ins
53
- "insert #{BD}.ust(txid,ordertxid,pair,time,type,ordertype,price,cost,fee,vol,margin,misc,ledgers,dias" \
54
- ") VALUES#{transacoes.trades.map { |k, v| ust_val1(k, v) }.join(',')}"
55
- end
56
-
57
- # @return [String] valores formatados ust (trades parte1)
58
- def ust_val1(idx, hes)
59
- "('#{idx}'," \
60
- "'#{hes['ordertxid']}'," \
61
- "'#{hes['pair']}'," \
62
- "PARSE_DATETIME('%s', '#{String(hes['time'].round)}')," \
63
- "'#{hes['type']}'," \
64
- "'#{hes['ordertype']}'," \
65
- "cast(#{hes['price']} as numeric)," \
66
- "cast(#{hes['cost']} as numeric)," \
67
- "cast(#{hes['fee']} as numeric)," \
68
- "#{ust_val2(idx, hes)}"
69
- end
70
-
71
- # @return [String] valores formatados ust (trades parte2)
72
- def ust_val2(idx, hes)
73
- "cast(#{hes['vol']} as numeric)," \
74
- "cast(#{hes['margin']} as numeric)," \
75
- "#{hes['misc'].length.zero? ? 'null' : "'#{hes['misc']}'"}," \
76
- "'#{transacoes.ledger.select { |_, v| v['refid'] == idx }.keys.join(',') || ''}'," \
77
- "#{Integer(ops[:h][idx] || 0)})"
78
- end
79
-
80
- # @return [String] comando insert SQL formatado usl (ledger)
81
- def usl_ins
82
- "insert #{BD}.usl(txid,refid,time,type,aclass,asset,amount,fee" \
83
- ") VALUES#{transacoes.ledger.map { |k, v| usl_val(k, v) }.join(',')}"
84
- end
85
-
86
- # @return [String] valores formatados usl (ledger)
87
- def usl_val(idx, hes)
88
- "('#{idx}'," \
89
- "'#{hes['refid']}'," \
90
- "PARSE_DATETIME('%s', '#{String(hes['time'].round)}')," \
91
- "'#{hes['type']}'," \
92
- "#{hes['aclass'].length.zero? ? 'null' : "'#{hes['aclass']}'"}," \
93
- "'#{hes['asset']}'," \
94
- "cast(#{hes['amount']} as numeric)," \
95
- "cast(#{hes['fee']} as numeric))"
96
- end
97
-
98
- # cria job bigquery & verifica execucao
99
- #
100
- # @param cmd (see sql)
101
- # @return [Boolean] job ok?
102
- def job?(cmd)
103
- @job = api.query_job(cmd)
104
- @job.wait_until_done!
105
- puts(@job.error['message']) if @job.failed?
106
- @job.failed?
107
- end
108
-
109
- # cria Structured Query Language (SQL) job bigquery
110
- #
111
- # @param [String] cmd comando SQL a executar
112
- # @param [String] red resultado quando SQL tem erro
113
- # @return [Google::Cloud::Bigquery::Data] resultado do SQL
114
- def sql(cmd, red = [])
115
- @sqr = job?(cmd) ? red : job.data
116
- end
117
-
118
- # cria Data Manipulation Language (DML) job bigquery
119
- #
120
- # @param cmd (see sql)
121
- # @return [Integer] numero linhas afetadas
122
- def dml(cmd)
123
- job?(cmd) ? 0 : job.num_dml_affected_rows
124
- end
125
- end
126
- end
@@ -1,154 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require('openssl')
4
- require('base64')
5
- require('curb')
6
- require('json')
7
-
8
- # @author Hernani Rodrigues Vaz
9
- module Cex
10
- # classe para processar dados no kraken
11
- class Client
12
- # @return [String] API key
13
- attr_reader :aky
14
- # @return [String] API secret
15
- attr_reader :asc
16
- # @return [String] API public url
17
- attr_reader :puu
18
- # @return [String] API private url
19
- attr_reader :pru
20
- # @return [String] API private path
21
- attr_reader :pth
22
-
23
- # @param [String] pky API key
24
- # @param [String] psc API secret
25
- # @return [Client] API kraken base
26
- def initialize(pky: ENV['KRAKEN_API_KEY'], psc: ENV['KRAKEN_API_SECRET'], options: {})
27
- b = options.fetch(:base_uri, 'https://api.kraken.com')
28
- v = options.fetch(:version, 0)
29
- @aky = pky
30
- @asc = psc
31
- @puu = "#{b}/#{v}/public/"
32
- @pru = "#{b}/#{v}/private/"
33
- @pth = "/#{v}/private/"
34
- end
35
-
36
- # @return [Hash] resultados ultimas transacoes trades no kraken
37
- # @example
38
- # {
39
- # 'trades' => {
40
- # 'TLADFV-QIUTN-QDNCBR' => {
41
- # 'ordertxid' => 'O2CRFG-5PCJA-EMX7VC',
42
- # 'pair' => 'XETHXXBT',
43
- # 'time' => 1_463_422_494.7069,
44
- # 'type' => 'buy',
45
- # 'ordertype' => 'market',
46
- # 'price' => '0.024400',
47
- # 'cost' => '1.358424',
48
- # 'fee' => '0.003532',
49
- # 'vol' => '55.67311475',
50
- # 'margin' => '0.000000',
51
- # 'misc' => ''
52
- # },
53
- # ...
54
- # },
55
- # 'count' => 156
56
- # }
57
- def trades_history
58
- post_private('TradesHistory')['result']
59
- end
60
-
61
- # @return [Hash] resultados ultimas transacoes ledger no kraken
62
- # @example
63
- # {
64
- # 'ledger' => {
65
- # 'LUK3QC-QW6TA-27B7NI' => {
66
- # 'refid' => 'A2BNCQS-CHCETZ-JYCER6',
67
- # 'time' => 1_584_349_306.9479,
68
- # 'type' => 'withdrawal',
69
- # 'subtype' => '',
70
- # 'aclass' => 'currency',
71
- # 'asset' => 'XETH',
72
- # 'amount' => '-29.2659039100',
73
- # 'fee' => '0.0050000000',
74
- # 'balance' => '1.1806988100'
75
- # }
76
- # ,
77
- # ...
78
- # },
79
- # 'count' => 373
80
- # }
81
- def ledger
82
- post_private('Ledgers')['result']
83
- end
84
-
85
- # @return [Hash] saldos no kraken
86
- # @example
87
- # {
88
- # 'ZEUR' => '0.0000',
89
- # 'XXBT' => '0.0000000000',
90
- # 'XETH' => '1.1806988100',
91
- # 'XETC' => '0.0000000000',
92
- # 'EOS' => '0.0000001700',
93
- # 'BCH' => '0.0000000000'
94
- # }
95
- def balance
96
- post_private('Balance')['result']
97
- end
98
-
99
- # @return [Hash] data hora kraken
100
- # @example
101
- # {
102
- # 'unixtime' => 1_598_956_727,
103
- # 'rfc1123' => 'Tue, 1 Sep 20 10:38:47 +0000'
104
- # }
105
- def server_time
106
- get_public('Time')['result']
107
- end
108
-
109
- private
110
-
111
- # HTTP GET request for public API queries.
112
- def get_public(method, **opts)
113
- parse_response(Curl.get("#{puu}#{method}", opts))
114
- end
115
-
116
- # HTTP POST request for private API queries involving user credentials.
117
- def post_private(method, **opts)
118
- # Generate a continually-increasing unsigned 51-bit integer nonce from the current Unix Time.
119
- opts.merge!({ nonce: Integer(Time.now) * 1_000_000 })
120
-
121
- parse_response(Curl.post("#{pru}#{method}", opts) do |r|
122
- r.headers = {
123
- 'api-key': aky,
124
- 'api-sign': authenticate(method, opts[:nonce], opts.map { |p| p.join('=') }.join('&'))
125
- }
126
- end)
127
- end
128
-
129
- def authenticate(method, nonce, params)
130
- raise(ArgumentError, 'API Key is not set') unless aky
131
- raise(ArgumentError, 'API Secret is not set') unless asc
132
-
133
- Base64.strict_encode64(OpenSSL::HMAC.digest(
134
- 'sha512',
135
- Base64.decode64(asc),
136
- "#{pth}#{method}#{Digest::SHA256.digest("#{nonce}#{params}")}"
137
- ))
138
- end
139
-
140
- def parse_response(http)
141
- # HTTP_SUCCESS = 200
142
- http.response_code == 200 ? JSON.parse(http.body) : http.status
143
- rescue JSON::ParserError,
144
- EOFError,
145
- Errno::ECONNRESET,
146
- Errno::EINVAL,
147
- Net::HTTPBadResponse,
148
- Net::HTTPHeaderSyntaxError,
149
- Net::ProtocolError,
150
- Timeout::Error => e
151
- "Erro da API #{e.inspect}"
152
- end
153
- end
154
- end