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