cns 0.1.0 → 0.1.1
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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/cns.rb +20 -2
- data/lib/cns/apide.rb +240 -0
- data/lib/cns/apies.rb +161 -0
- data/lib/cns/apifr.rb +139 -0
- data/lib/cns/apigm.rb +181 -0
- data/lib/cns/apimt.rb +138 -0
- data/lib/cns/apius.rb +167 -0
- data/lib/cns/bigquery1.rb +114 -0
- data/lib/cns/bigquery2.rb +76 -0
- data/lib/cns/bigquery3.rb +122 -0
- data/lib/cns/bigquery4.rb +151 -0
- data/lib/cns/bitcoinde.rb +135 -0
- data/lib/cns/etherscan1.rb +118 -0
- data/lib/cns/etherscan2.rb +110 -0
- data/lib/cns/greymass1.rb +104 -0
- data/lib/cns/greymass2.rb +85 -0
- data/lib/cns/kraken.rb +132 -0
- data/lib/cns/paymium.rb +106 -0
- data/lib/cns/therock.rb +95 -0
- data/lib/cns/version.rb +3 -1
- metadata +19 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3b7d92c5d0783aab6b1400ba4bd7e397e4f7391cfbf83d1d7faf5a8c52349aa
|
4
|
+
data.tar.gz: 43aa372a6d6f6d148f17c33065e8f0550647a2b0b78f213b00363c7ea2f74828
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22fb5e905b0469a4022c278d643bcf06b11afab7a011329775ab3cffee92bccfeb9392c676c993569ddd7404e090ab8d2a469c1aabfff4c833b873053f3f7435
|
7
|
+
data.tar.gz: 0d7531ba08be4fe655a578475f4752d80330e41930b5d5d7732463838539357ae2936e6d11bcbe9bbd112508190404b523bceed6d4f1475853eb9f3b1b29c9e2
|
data/Gemfile.lock
CHANGED
data/lib/cns.rb
CHANGED
@@ -1,6 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require('thor')
|
4
|
+
require('cns/apide')
|
5
|
+
require('cns/apies')
|
6
|
+
require('cns/apifr')
|
7
|
+
require('cns/apigm')
|
8
|
+
require('cns/apimt')
|
9
|
+
require('cns/apius')
|
10
|
+
require('cns/bigquery1')
|
11
|
+
require('cns/bigquery2')
|
12
|
+
require('cns/bigquery3')
|
13
|
+
require('cns/bigquery4')
|
14
|
+
require('cns/bitcoinde')
|
15
|
+
require('cns/etherscan1')
|
16
|
+
require('cns/etherscan2')
|
17
|
+
require('cns/greymass1')
|
18
|
+
require('cns/greymass2')
|
19
|
+
require('cns/kraken')
|
20
|
+
require('cns/paymium')
|
21
|
+
require('cns/therock')
|
4
22
|
require('cns/version')
|
5
23
|
|
6
24
|
module Cns
|
@@ -18,7 +36,7 @@ module Cns
|
|
18
36
|
option :h, type: :hash, default: {}, desc: 'configuracao ajuste reposicionamento temporal'
|
19
37
|
# carrega transacoes novas no bigquery
|
20
38
|
def work
|
21
|
-
|
39
|
+
Bigquery.new(options).processa_tudo
|
22
40
|
end
|
23
41
|
|
24
42
|
desc 'show', 'mostra resumo transacoes'
|
@@ -26,7 +44,7 @@ module Cns
|
|
26
44
|
option :t, type: :boolean, default: false, desc: 'mostra transacoes todas ou somente novas'
|
27
45
|
# mostra resumo transacoes
|
28
46
|
def show
|
29
|
-
|
47
|
+
Bigquery.new(options).mostra_tudo
|
30
48
|
end
|
31
49
|
|
32
50
|
default_task :show
|
data/lib/cns/apide.rb
ADDED
@@ -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 Cns
|
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
|
data/lib/cns/apies.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('faraday')
|
4
|
+
require('json')
|
5
|
+
|
6
|
+
# @author Hernani Rodrigues Vaz
|
7
|
+
module Cns
|
8
|
+
# classe para acesso dados blockchain ETH
|
9
|
+
class Apies
|
10
|
+
# @return [String] apikey a juntar aos pedidos HTTP url:
|
11
|
+
attr_reader :key
|
12
|
+
# @return [String] base URL to use as a prefix for all requests
|
13
|
+
attr_reader :url
|
14
|
+
|
15
|
+
# @param [String] chv apikey a juntar aos pedidos HTTP url:
|
16
|
+
# @param [String] www base URL to use as a prefix for all requests
|
17
|
+
# @return [Apies] API etherscan base
|
18
|
+
def initialize(chv: ENV['ETHERSCAN_API_KEY'], www: 'https://api.etherscan.io/')
|
19
|
+
@key = chv
|
20
|
+
@url = www
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [<Symbol>] adapter for the connection - default :net_http
|
24
|
+
def adapter
|
25
|
+
@adapter ||= Faraday.default_adapter
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [<Faraday::Connection>] connection object with an URL & adapter
|
29
|
+
def conn
|
30
|
+
@conn ||=
|
31
|
+
Faraday.new(url: url) do |c|
|
32
|
+
c.request(:url_encoded)
|
33
|
+
c.adapter(adapter)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @example
|
38
|
+
# [
|
39
|
+
# { account: '0x...', balance: '4000000000000000000' },
|
40
|
+
# { account: '0x...', balance: '87000000000000000000' }
|
41
|
+
# ]
|
42
|
+
# @param [String] ads lista enderecos carteiras ETH (max 20)
|
43
|
+
# @return [Array<Hash>] devolve lista com dados & saldo de carteiras ETH
|
44
|
+
def account(ads)
|
45
|
+
raise(Erro, 'maximo de 20 enderecos') if ads.size > 20
|
46
|
+
|
47
|
+
get(action: 'balancemulti', address: ads.join(','), tag: 'latest')[:result]
|
48
|
+
end
|
49
|
+
|
50
|
+
# @example
|
51
|
+
# [
|
52
|
+
# {
|
53
|
+
# blockNumber: '4984535',
|
54
|
+
# timeStamp: '1517094794',
|
55
|
+
# hash: '0x...',
|
56
|
+
# nonce: '10',
|
57
|
+
# blockHash: '0x...',
|
58
|
+
# transactionIndex: '17',
|
59
|
+
# from: '0x...',
|
60
|
+
# to: '0x...',
|
61
|
+
# value: '52627271000000000000',
|
62
|
+
# gas: '21000',
|
63
|
+
# gasPrice: '19000000000',
|
64
|
+
# isError: '0',
|
65
|
+
# txreceipt_status: '1',
|
66
|
+
# input: '0x',
|
67
|
+
# contractAddress: '',
|
68
|
+
# gasUsed: '21000',
|
69
|
+
# cumulativeGasUsed: '566293',
|
70
|
+
# confirmations: '5848660'
|
71
|
+
# },
|
72
|
+
# {}
|
73
|
+
# ]
|
74
|
+
# @param [String] add endereco carteira ETH
|
75
|
+
# @param [Hash] arg argumentos trabalho
|
76
|
+
# @option arg [Integer] :start_block starting blockNo to retrieve results
|
77
|
+
# @option arg [Integer] :end_block ending blockNo to retrieve results
|
78
|
+
# @option arg [String] :sort asc -> ascending order, desc -> descending order
|
79
|
+
# @option arg [Integer] :page to get paginated results
|
80
|
+
# @option arg [Integer] :offset max records to return
|
81
|
+
# @return [Array<Hash>] lista de transacoes
|
82
|
+
def norml_tx(add, **arg)
|
83
|
+
raise(Erro, 'endereco tem de ser definido') if add.nil? || add.empty?
|
84
|
+
|
85
|
+
ledger(**arg.merge(action: 'txlist', address: add))
|
86
|
+
end
|
87
|
+
|
88
|
+
# @example registo duplicado
|
89
|
+
# [
|
90
|
+
# {
|
91
|
+
# blockNumber: '3967652',
|
92
|
+
# timeStamp: '1499081515',
|
93
|
+
# hash: '0x registo duplicado com todos os dados iguais',
|
94
|
+
# nonce: '3',
|
95
|
+
# blockHash: '0x00a49e999036dc13dc6c4244bb1d51d3146fe7f00bfb500a7624d82e299c7328',
|
96
|
+
# from: '0xd0a6e6c54dbc68db5db3a091b171a77407ff7ccf',
|
97
|
+
# contractAddress: '0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0',
|
98
|
+
# to: '0x...',
|
99
|
+
# value: '0',
|
100
|
+
# tokenName: 'EOS',
|
101
|
+
# tokenSymbol: 'EOS',
|
102
|
+
# tokenDecimal: '18',
|
103
|
+
# transactionIndex: '83',
|
104
|
+
# gas: '173399',
|
105
|
+
# gasPrice: '21000000000',
|
106
|
+
# gasUsed: '173398',
|
107
|
+
# input: 'deprecated',
|
108
|
+
# cumulativeGasUsed: '7484878',
|
109
|
+
# confirmations: '3442641'
|
110
|
+
# },
|
111
|
+
# {}
|
112
|
+
# ]
|
113
|
+
# @param add (see norml_tx)
|
114
|
+
# @param [String] cdd token address (nil to get a list of all ERC20 transactions)
|
115
|
+
# @param arg (see norml_tx)
|
116
|
+
# @option arg (see norml_tx)
|
117
|
+
# @return [Array<Hash>] lista de token transfer events
|
118
|
+
def token_tx(add, cdd = nil, **arg)
|
119
|
+
raise(Erro, 'contrato ou endereco tem de estar definido') if (cdd || add).nil? || (cdd || add).empty?
|
120
|
+
|
121
|
+
# registos duplicados aparecem em token events (ver exemplo acima)
|
122
|
+
# -quando ha erros na blockchain (acho)
|
123
|
+
# -quando ha token events identicos no mesmo block (acho)
|
124
|
+
ledger(**arg.merge(action: 'tokentx', address: add, contractaddress: cdd))
|
125
|
+
end
|
126
|
+
|
127
|
+
# @param [Integer] pag pagina das transacoes a devolver
|
128
|
+
# @param [Array<Hash>] ary lista acumuladora das transacoes a devolver
|
129
|
+
# @param arg (see norml_tx)
|
130
|
+
# @option arg (see norml_tx)
|
131
|
+
# @return [Array<Hash>] devolve lista de transacoes/token transfer events
|
132
|
+
def ledger(pag = 0, ary = [], **arg)
|
133
|
+
r = get(**arg.merge(page: pag + 1, offset: 10_000))[:result]
|
134
|
+
ary += r
|
135
|
+
r.count < 10_000 ? ary : ledger(pag + 1, ary, **arg)
|
136
|
+
rescue StandardError
|
137
|
+
ary
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
# @example
|
143
|
+
# {
|
144
|
+
# status: '1',
|
145
|
+
# message: 'OK',
|
146
|
+
# result: []
|
147
|
+
# }
|
148
|
+
# @return [Hash] resultado do HTTP request
|
149
|
+
def get(**arg)
|
150
|
+
JSON.parse(
|
151
|
+
(conn.get('api') do |o|
|
152
|
+
o.headers = { content_type: 'application/json', accept: 'application/json', user_agent: 'etherscan;ruby' }
|
153
|
+
o.params = arg.merge(module: 'account', apikey: key).reject { |_, v| v.nil? }
|
154
|
+
end).body,
|
155
|
+
symbolize_names: true
|
156
|
+
)
|
157
|
+
rescue StandardError
|
158
|
+
{ result: [] }
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|