cex 0.1.5 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
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