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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2aec3d67c687a641d2c2d780ceb6ed233270c3839fa61e1041f37105afde98cf
4
- data.tar.gz: d03ed6184e7db2a6493c4988d2b1a599d0c44a356e9b4ec9c9abe50b1196fa1a
3
+ metadata.gz: f2fa19d014cc04f9d459f5f9e8d117df96e6b407abf4425e6766dbf4a13d849a
4
+ data.tar.gz: 1ef05f9442252f24c785ab2b94ea3ce24841b083fe00220bfc52accd441f29f6
5
5
  SHA512:
6
- metadata.gz: 4fe7cf1fa27cff26759d0032fd8496fb950ed62cc836283dca645e064189991667747d19522cb445713b45c4f0b65419ef5ec98a562d98ecfa0af53def44c548
7
- data.tar.gz: 77721ad1ec5bd38bd569289b6e2c32d0185b2aec99c9109c76429e54a6537ea2707ae505e82a904d0f65f6ee9fe28da71c498139fb73daf49857cfafee6c8a31
6
+ metadata.gz: 8df577cc9ef381c64ff9b1dfedaf565e8d9721f3447a2324f3175a0dc27a6d2f42c820f8d51a46cd4e20ec7c133414448610b01788731c96ab111c2cb8f9645c
7
+ data.tar.gz: cf4c8639db1e32f5b3ab197498f25cf61f954cd947e39a83a427e4dc1196b8d52d12228075c3d9fe6b649097c4d9b352161c94d84d61c8003d0e0f20d76d1016
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cex (0.1.5)
4
+ cex (0.1.7)
5
5
  curb
6
6
  google-cloud-bigquery
7
7
  thor
@@ -18,7 +18,7 @@ GEM
18
18
  declarative-option (0.1.0)
19
19
  faraday (1.0.1)
20
20
  multipart-post (>= 1.2, < 3)
21
- google-api-client (0.44.0)
21
+ google-api-client (0.44.1)
22
22
  addressable (~> 2.5, >= 2.5.1)
23
23
  googleauth (~> 0.9)
24
24
  httpclient (>= 2.8.1, < 3.0)
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Cex [![Build Status](https://travis-ci.com/hernanirvaz/cex.svg?branch=master)](https://travis-ci.com/hernanirvaz/cex)
2
2
 
3
- Arquiva transactions kraken & bitcoinde no bigquery. Pode ajustar dias para reposicionamento temporal.
3
+ Arquiva transactions bitcoinde/kraken/paymium/therock no bigquery. Pode ajustar dias para reposicionamento temporal.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Hernâni Rodrigues Vaz']
9
9
  spec.email = ['hernanirvaz@gmail.com']
10
10
 
11
- spec.summary = 'Arquiva transactions kraken & bitcoinde no bigquery.'
11
+ spec.summary = 'Arquiva transactions bitcoinde/kraken/paymium/therock no bigquery.'
12
12
  spec.description = "#{spec.summary} Pode ajustar dias para reposicionamento temporal."
13
13
  spec.homepage = 'https://github.com/hernanirvaz/cex'
14
14
  spec.license = 'MIT'
data/lib/cex.rb CHANGED
@@ -1,9 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require('thor')
4
- require('cex/bigquery')
5
- require('cex/client')
4
+ require('cex/apide')
5
+ require('cex/apius')
6
+ require('cex/apifr')
7
+ require('cex/apimt')
8
+ require('cex/bigquery1')
9
+ require('cex/bigquery2')
10
+ require('cex/bitcoinde')
6
11
  require('cex/kraken')
12
+ require('cex/paymium')
13
+ require('cex/therock')
7
14
  require('cex/version')
8
15
 
9
16
  module Cex
@@ -15,7 +22,7 @@ module Cex
15
22
  option :h, type: :hash, default: {}, desc: 'configuracao ajuste reposicionamento temporal'
16
23
  # carrega transacoes novas no bigquery
17
24
  def work
18
- Bigquery.new(options).processa
25
+ Bigquery.new(options).processa_tudo
19
26
  end
20
27
 
21
28
  desc 'show', 'mostra resumo saldos & transacoes'
@@ -23,7 +30,7 @@ module Cex
23
30
  option :t, type: :boolean, default: false, desc: 'mostra transacoes todas ou somente novas'
24
31
  # mostra resumo saldos & transacoes
25
32
  def show
26
- Bigquery.new(options).transacoes.mostra_resumo
33
+ Bigquery.new(options).mostra_tudo
27
34
  end
28
35
 
29
36
  default_task :show
@@ -0,0 +1,240 @@
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 bitcoinde
11
+ class Apide
12
+ # @return [String] API key
13
+ attr_reader :aky
14
+ # @return [String] API secret
15
+ attr_reader :asc
16
+ # @return [String] API url base
17
+ attr_reader :urb
18
+
19
+ # @param [String] pky API key
20
+ # @param [String] psc API secret
21
+ # @param [Hash] ops parametrizacao base da API
22
+ # @return [Apide] API bitcoinde base
23
+ def initialize(
24
+ pky: ENV['BITCOINDE_API_KEY'],
25
+ psc: ENV['BITCOINDE_API_SECRET'],
26
+ ops: { www: 'https://api.bitcoin.de', ver: 4 }
27
+ )
28
+ @aky = pky
29
+ @asc = psc
30
+ @urb = "#{ops[:www]}/v#{ops[:ver]}"
31
+ end
32
+
33
+ # @example
34
+ # {
35
+ # data: {
36
+ # balances: {
37
+ # btc: { total_amount: '0.00000000000000000000', available_amount: '0', reserved_amount: '0' },
38
+ # bch: { total_amount: '0.00000000000000000000', available_amount: '0', reserved_amount: '0' },
39
+ # btg: { total_amount: '0.00000000000000000000', available_amount: '0', reserved_amount: '0' },
40
+ # eth: { total_amount: '0.00000000000000000000', available_amount: '0', reserved_amount: '0' },
41
+ # bsv: { total_amount: '0.00000000000000000000', available_amount: '0', reserved_amount: '0' },
42
+ # ltc: { total_amount: '0.00000000000000000000', available_amount: '0', reserved_amount: '0' }
43
+ # },
44
+ # encrypted_information: { uid: '0y...', bic_short: '0y...', bic_full: '0y...' }
45
+ # },
46
+ # errors: [],
47
+ # credits: 23
48
+ # }
49
+ # @return [Hash] saldos no bitcoinde
50
+ def account
51
+ api_get('account')[:data][:balances]
52
+ end
53
+
54
+ # @example
55
+ # {
56
+ # trades: [{
57
+ # trade_id: 'XUWWD3',
58
+ # trading_pair: 'btceur',
59
+ # is_external_wallet_trade: false,
60
+ # type: 'sell',
61
+ # amount_currency_to_trade: '0.1',
62
+ # price: 430,
63
+ # volume_currency_to_pay: 43,
64
+ # volume_currency_to_pay_after_fee: 42.79,
65
+ # amount_currency_to_trade_after_fee: 0.099,
66
+ # fee_currency_to_pay: 0.22,
67
+ # fee_currency_to_trade: '0.00100000',
68
+ # created_at: '2014-03-22T08:14:48+01:00',
69
+ # successfully_finished_at: '2014-03-25T14:03:22+01:00',
70
+ # state: 1,
71
+ # is_trade_marked_as_paid: true,
72
+ # trade_marked_as_paid_at: '2014-03-22T08:20:01+01:00',
73
+ # payment_method: 1,
74
+ # my_rating_for_trading_partner: 'positive',
75
+ # trading_partner_information: {
76
+ # username: 'emax2000',
77
+ # is_kyc_full: false,
78
+ # trust_level: 'bronze',
79
+ # amount_trades: 4,
80
+ # rating: 100,
81
+ # bank_name: 'CASSA DI RISPARMIO DI CIVITAVECCHIA SPA',
82
+ # bic: 'CRFIIT2CXXX',
83
+ # seat_of_bank: 'IT'
84
+ # }
85
+ # }, {}],
86
+ # page: { current: 1, last: 2 },
87
+ # errors: [],
88
+ # credits: 22
89
+ # }
90
+ # @param [Integer] pag pagina dos dados a obter
91
+ # @param [Array] ary lista acumuladora dos dados a obter
92
+ # @return [Array<Hash>] lista trades no bitcoinde
93
+ def trades(pag = 0, ary = [])
94
+ r = api_get('trades', state: 1, page: pag + 1)
95
+ ary += r[:trades]
96
+ r[:page][:current] < r[:page][:last] ? trades(pag + 1, ary) : ary
97
+ rescue StandardError
98
+ ary
99
+ end
100
+
101
+ # @example
102
+ # {
103
+ # deposits: [{}, {}],
104
+ # page: { current: 1, last: 1 },
105
+ # errors: [],
106
+ # credits: 23
107
+ # }
108
+ # @param (see trades)
109
+ # @return [Array<Hash>] lista depositos no bitcoinde
110
+ def deposits(pag = 0, ary = [])
111
+ r = api_get('btc/deposits', state: 2, page: pag + 1)
112
+ ary += r[:deposits].map { |h| deposit_hash(h) }
113
+ r[:page][:current] < r[:page][:last] ? deposits(pag + 1, ary) : ary
114
+ rescue StandardError
115
+ ary
116
+ end
117
+
118
+ # @example
119
+ # {
120
+ # withdrawals: [{}, {}],
121
+ # page: { current: 1, last: 2 },
122
+ # errors: [],
123
+ # credits: 23
124
+ # }
125
+ # @param (see trades)
126
+ # @return [Array<Hash>] lista withdrawals no bitcoinde
127
+ def withdrawals(pag = 0, ary = [])
128
+ r = api_get('btc/withdrawals', state: 1, page: pag + 1)
129
+ ary += r[:withdrawals].map { |h| withdrawal_hash(h) }
130
+ r[:page][:current] < r[:page][:last] ? withdrawals(pag + 1, ary) : ary
131
+ rescue StandardError
132
+ ary
133
+ end
134
+
135
+ # @example
136
+ # {
137
+ # withdrawal_id: '136605',
138
+ # address: '1K9YMDDrmMV25EoYNqi7KUEK57Kn3TCNUJ',
139
+ # amount: '0.120087',
140
+ # network_fee: '0',
141
+ # comment: '',
142
+ # created_at: '2014-02-05T13:01:09+01:00',
143
+ # txid: '6264fe528116fcb87c812a306ca8409eecfec8fa941546c86f98984b882c8042',
144
+ # transferred_at: '2014-02-05T13:05:17+01:00',
145
+ # state: 1
146
+ # }
147
+ # @param [Hash] hwi dados duma withdrawal
148
+ # @return [Hash] withdrawal unifirmizada
149
+ def withdrawal_hash(hwi)
150
+ {
151
+ id: hwi[:address],
152
+ tp: 'out',
153
+ qtxt: 'btc',
154
+ fee: hwi[:network_fee],
155
+ time: Time.parse(hwi[:transferred_at]),
156
+ qt: hwi[:amount],
157
+ lgid: Integer(hwi[:withdrawal_id])
158
+ }
159
+ end
160
+
161
+ # @example
162
+ # {
163
+ # deposit_id: '177245',
164
+ # txid: '84f9e85bc5709cd471e3d58a7d0f42d2c4a7bbd888cabf844e200efbf0a7fda2',
165
+ # address: '1KK6HhG3quojFS4CY1mPcbyrjQ8BMDQxmT',
166
+ # amount: '0.13283',
167
+ # confirmations: 6,
168
+ # state: 2,
169
+ # created_at: '2014-01-31T22:01:30+01:00'
170
+ # }
171
+ # @param [Hash] hde dados dum deposit
172
+ # @return [Hash] deposit uniformizado
173
+ def deposit_hash(hde)
174
+ {
175
+ id: hde[:address],
176
+ tp: 'deposit',
177
+ qtxt: 'btc',
178
+ fee: '0',
179
+ time: Time.parse(hde[:created_at]),
180
+ qt: hde[:amount],
181
+ lgid: Integer(hde[:deposit_id])
182
+ }
183
+ end
184
+
185
+ private
186
+
187
+ # HTTP GET request for public bitcoinde API queries.
188
+ def api_get(uri, **ops)
189
+ t = url("#{urb}/#{uri}", ops)
190
+ resposta(Curl.get(t) { |r| r.headers = hdrs('GET', t, nonce, {}) })
191
+ end
192
+
193
+ # HTTP POST request for private bitcoinde API queries involving user credentials.
194
+ def api_post(uri, **ops)
195
+ # pedidos POST HTTP nao levam parametros no URL - somente no header e ordenados
196
+ resposta(Curl.post("#{urb}/#{uri}") { |r| r.headers = hdrs('POST', "#{urb}/#{uri}", nonce, ops.sort) })
197
+ end
198
+
199
+ # @return [String] URL do pedido formatado com todos os parametros
200
+ def url(uri, ops)
201
+ ops.empty? ? uri : "#{uri}?#{URI.encode_www_form(ops)}"
202
+ end
203
+
204
+ # @return [Hash] headers necessarios para pedido HTTP
205
+ def hdrs(typ, qry, non, ops)
206
+ {
207
+ 'X-API-KEY': aky,
208
+ 'X-API-NONCE': non,
209
+ 'X-API-SIGNATURE': auth(typ, qry, non, URI.encode_www_form(ops))
210
+ }
211
+ end
212
+
213
+ # @return [String] assinarura codificada dos pedidos HTTP
214
+ def auth(typ, qry, non, par)
215
+ raise(ArgumentError, 'API Key is not set') unless aky
216
+ raise(ArgumentError, 'API Secret is not set') unless asc
217
+
218
+ OpenSSL::HMAC.hexdigest('sha256', asc, [typ, qry, aky, non, Digest::MD5.hexdigest(par)].join('#'))
219
+ end
220
+
221
+ # @return [Integer] continually-increasing unsigned integer nonce from the current Unix Time
222
+ def nonce
223
+ Integer(Float(Time.now) * 1e6)
224
+ end
225
+
226
+ # @return [Hash] resposta do pedido HTTP
227
+ def resposta(http)
228
+ http.response_code == 200 ? JSON.parse(http.body, symbolize_names: true) : http.status
229
+ rescue JSON::ParserError,
230
+ EOFError,
231
+ Errno::ECONNRESET,
232
+ Errno::EINVAL,
233
+ Net::HTTPBadResponse,
234
+ Net::HTTPHeaderSyntaxError,
235
+ Net::ProtocolError,
236
+ Timeout::Error => e
237
+ "Erro da API bitcoinde #{e.inspect}"
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,139 @@
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 paymium
11
+ class Apifr
12
+ # @return [String] API key
13
+ attr_reader :aky
14
+ # @return [String] API secret
15
+ attr_reader :asc
16
+ # @return [String] API url base
17
+ attr_reader :urb
18
+
19
+ # @param [String] pky API key
20
+ # @param [String] psc API secret
21
+ # @param [Hash] ops parametrizacao base da API
22
+ # @return [Apius] API paymium base
23
+ def initialize(
24
+ pky: ENV['PAYMIUM_API_KEY'],
25
+ psc: ENV['PAYMIUM_API_SECRET'],
26
+ ops: { www: 'https://paymium.com', ver: 1 }
27
+ )
28
+ @aky = pky
29
+ @asc = psc
30
+ @urb = "#{ops[:www]}/api/v#{ops[:ver]}"
31
+ end
32
+
33
+ # @example
34
+ # {
35
+ # name: '...',
36
+ # email: '...',
37
+ # locale: 'en',
38
+ # channel_id: '...',
39
+ # meta_state: 'approved',
40
+ # balance_eur: '0.0',
41
+ # locked_eur: '0.0',
42
+ # balance_btc: '0.0',
43
+ # locked_btc: '0.0',
44
+ # balance_lbtc: '0.0',
45
+ # locked_lbtc: '0.0'
46
+ # }
47
+ # @return [Hash] saldos no paymium
48
+ def account
49
+ api_get('user')
50
+ end
51
+
52
+ # @example
53
+ # [
54
+ # {
55
+ # uuid: '50551e61-4e74-4ae7-85fd-9c2040542818',
56
+ # currency_amount: nil,
57
+ # state: 'executed',
58
+ # btc_fee: '0.0',
59
+ # currency_fee: '0.0',
60
+ # created_at: '2014-03-04T09:00Z',
61
+ # updated_at: '2014-03-04T09:00Z',
62
+ # currency: 'EUR',
63
+ # comment: '5723',
64
+ # amount: '100.0',
65
+ # type: 'WireDeposit',
66
+ # account_operations: [{
67
+ # uuid: 'b5058a68-cf99-4438-86d3-e773eba418ec',
68
+ # name: 'wire_deposit',
69
+ # amount: '100.0',
70
+ # currency: 'EUR',
71
+ # created_at: '2014-03-04T09:00Z',
72
+ # created_at_int: 1_393_923_644,
73
+ # is_trading_account: false
74
+ # }, {}]
75
+ # }, {}
76
+ # ]
77
+ # @return [Hash] ledger no paymium
78
+ def ledger(pag = 0, ary = [])
79
+ r = api_get('user/orders', offset: pag)
80
+ r.empty? ? ary : ledger(pag + r.size, ary + r)
81
+ rescue StandardError
82
+ ary
83
+ end
84
+
85
+ private
86
+
87
+ # HTTP GET request for public paymium API queries.
88
+ def api_get(uri, **ops)
89
+ resposta(Curl.get("#{urb}/#{uri}", ops) { |r| r.headers = hdrs(url(uri, ops), nonce, {}) })
90
+ end
91
+
92
+ # HTTP POST request for private paymium API queries involving user credentials.
93
+ def api_post(uri, **ops)
94
+ resposta(Curl.post("#{urb}/#{uri}", ops) { |r| r.headers = hdrs(uri, nonce, ops) })
95
+ end
96
+
97
+ # @return [String] URL do pedido formatado com todos os parametros
98
+ def url(uri, ops)
99
+ ops.empty? ? uri : "#{uri}?#{URI.encode_www_form(ops)}"
100
+ end
101
+
102
+ # @return [Hash] headers necessarios para pedido HTTP
103
+ def hdrs(qry, non, ops)
104
+ {
105
+ content_type: 'application/json',
106
+ 'Api-Key': aky,
107
+ 'Api-Nonce': non,
108
+ 'Api-Signature': auth(qry, non, URI.encode_www_form(ops))
109
+ }
110
+ end
111
+
112
+ # @return [String] assinarura codificada dos pedidos HTTP
113
+ def auth(qry, non, par)
114
+ raise(ArgumentError, 'API Key is not set') unless aky
115
+ raise(ArgumentError, 'API Secret is not set') unless asc
116
+
117
+ OpenSSL::HMAC.hexdigest('sha256', asc, [non, "#{urb}/#{qry}", par].join)
118
+ end
119
+
120
+ # @return [Integer] continually-increasing unsigned integer nonce from the current Unix Time
121
+ def nonce
122
+ Integer(Float(Time.now) * 1e6)
123
+ end
124
+
125
+ # @return [Hash] resposta do pedido HTTP
126
+ def resposta(http)
127
+ http.response_code == 200 ? JSON.parse(http.body, symbolize_names: true) : http.status
128
+ rescue JSON::ParserError,
129
+ EOFError,
130
+ Errno::ECONNRESET,
131
+ Errno::EINVAL,
132
+ Net::HTTPBadResponse,
133
+ Net::HTTPHeaderSyntaxError,
134
+ Net::ProtocolError,
135
+ Timeout::Error => e
136
+ "Erro da API paymium #{e.inspect}"
137
+ end
138
+ end
139
+ end