cns 0.9.0 → 0.9.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/apibc.rb +24 -13
- data/lib/cns/apice.rb +80 -78
- data/lib/cns/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bda8e993fc38693b8934e9b077c7eb1e7f2f005eeaa011d3495417d921b7479
|
4
|
+
data.tar.gz: e4e7bbe97475f2c4f9022073c36d5773040e985aaabf23054b6e7706b88a57d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 103f27e4ee78a762d99947a8a7d8c7686fd4a47b9c280ee6c23855e48864731eb42960352f6c759adb6498b1dbae39592148875140f036e2a962bdc558499ff8
|
7
|
+
data.tar.gz: d93225bc64141c49ec230467c52a54e6e52619c6fa65eed618f19e781981ebfe9a7adbc4b7634179d6c0b4a72ec5c38fc00e410de46b2612f322e7f1f93c3080
|
data/Gemfile.lock
CHANGED
data/lib/cns/apibc.rb
CHANGED
@@ -7,12 +7,20 @@ require('json')
|
|
7
7
|
module Cns
|
8
8
|
# classe para acesso dados blockchains
|
9
9
|
class Apibc
|
10
|
+
ESPS = 10_000
|
11
|
+
GMPS = 100
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@etherscan_conn = connection('https://api.etherscan.io')
|
15
|
+
@greymass_conn = connection('https://eos.greymass.com')
|
16
|
+
end
|
17
|
+
|
10
18
|
# Get account balances for multiple ETH addresses
|
11
19
|
# @param addresses [Array<String>] List of ETH addresses (max 20)
|
12
20
|
# @return [Array<Hash>] List of addresses with balances
|
13
21
|
def account_es(addresses)
|
14
22
|
response = etherscan_req('balancemulti', addresses.join(','), 1, tag: 'latest')
|
15
|
-
response
|
23
|
+
response[:status] == '1' ? response[:result] || [] : []
|
16
24
|
end
|
17
25
|
|
18
26
|
# Get normal transactions for ETH address
|
@@ -55,7 +63,7 @@ module Cns
|
|
55
63
|
# @return [Hash] Account details with resources
|
56
64
|
def account_gm(address)
|
57
65
|
response = greymass_req('/v1/chain/get_account', account_name: address)
|
58
|
-
response
|
66
|
+
response[:core_liquid_balance]&.to_d&.positive? ? response : gm_erro
|
59
67
|
end
|
60
68
|
|
61
69
|
# Get complete transaction history for EOS account
|
@@ -65,12 +73,12 @@ module Cns
|
|
65
73
|
actions = []
|
66
74
|
pos = 0
|
67
75
|
loop do
|
68
|
-
response = greymass_req('/v1/history/get_actions', account_name: address, pos: pos, offset:
|
69
|
-
batch = response
|
70
|
-
actions
|
71
|
-
break if batch.size <
|
76
|
+
response = greymass_req('/v1/history/get_actions', account_name: address, pos: pos, offset: GMPS)
|
77
|
+
batch = response[:actions] || []
|
78
|
+
actions.concat(batch)
|
79
|
+
break if batch.size < GMPS
|
72
80
|
|
73
|
-
pos +=
|
81
|
+
pos += GMPS
|
74
82
|
end
|
75
83
|
actions
|
76
84
|
end
|
@@ -80,7 +88,10 @@ module Cns
|
|
80
88
|
# Reusable Faraday connection
|
81
89
|
def connection(base_url)
|
82
90
|
Faraday.new(base_url) do |conn|
|
91
|
+
conn.request(:json) # Automatically encodes body as JSON
|
83
92
|
conn.headers = { content_type: 'application/json', accept: 'application/json', user_agent: 'blockchain-api-client' }
|
93
|
+
conn.options.timeout = 30
|
94
|
+
conn.options.open_timeout = 10
|
84
95
|
conn.adapter(Faraday.default_adapter)
|
85
96
|
end
|
86
97
|
end
|
@@ -88,7 +99,7 @@ module Cns
|
|
88
99
|
# Generic Etherscan API request handler
|
89
100
|
def etherscan_req(action, address, page = 1, params = {})
|
90
101
|
params = { module: 'account', action: action, address: address, page: page, apikey: ENV.fetch('ETHERSCAN_API_KEY') }.merge(params)
|
91
|
-
parse_json(
|
102
|
+
parse_json(@etherscan_conn.get('/api', params))
|
92
103
|
rescue Faraday::Error
|
93
104
|
{ status: '0' }
|
94
105
|
end
|
@@ -103,11 +114,11 @@ module Cns
|
|
103
114
|
page = 1
|
104
115
|
loop do
|
105
116
|
response = etherscan_req(action, address, page, params)
|
106
|
-
break unless response
|
117
|
+
break unless response[:status] == '1'
|
107
118
|
|
108
|
-
batch = response
|
109
|
-
results
|
110
|
-
break if batch.size <
|
119
|
+
batch = response[:result] || []
|
120
|
+
results.concat(batch)
|
121
|
+
break if batch.size < ESPS
|
111
122
|
|
112
123
|
page += 1
|
113
124
|
end
|
@@ -121,7 +132,7 @@ module Cns
|
|
121
132
|
|
122
133
|
# Generic Greymass API request handler
|
123
134
|
def greymass_req(endpoint, payload)
|
124
|
-
parse_json(
|
135
|
+
parse_json(@greymass_conn.post(endpoint) { |req| req.body = payload })
|
125
136
|
rescue Faraday::Error
|
126
137
|
gm_erro
|
127
138
|
end
|
data/lib/cns/apice.rb
CHANGED
@@ -11,133 +11,117 @@ module Cns
|
|
11
11
|
|
12
12
|
# classe para acesso dados centralized exchanges
|
13
13
|
class Apice
|
14
|
+
def initialize
|
15
|
+
@curl = Curl::Easy.new
|
16
|
+
@curl.timeout = 30
|
17
|
+
@curl.connect_timeout = 10
|
18
|
+
@curl.follow_location = true
|
19
|
+
@curl.ssl_verify_peer = true
|
20
|
+
end
|
21
|
+
|
14
22
|
# @return [Hash] saldos no bitcoinde
|
15
23
|
def account_de
|
16
24
|
uri = "#{API[:de]}/account"
|
17
|
-
|
25
|
+
run_curl(@curl, uri, headers: hde(uri))
|
26
|
+
parse_json(@curl).dig(:data, :balances) || {}
|
18
27
|
rescue Curl::Err::CurlError
|
19
28
|
{}
|
20
29
|
end
|
21
30
|
|
22
31
|
# @return [Array<Hash>] trades bitcoinde
|
23
32
|
def trades_de
|
24
|
-
|
25
|
-
ary = []
|
26
|
-
loop do
|
27
|
-
url = "#{API[:de]}/trades?#{URI.encode_www_form(state: 1, page: pag)}"
|
28
|
-
data = parse_json(Curl.get(url) { |obj| obj.headers = hde(url) })
|
29
|
-
ary += data.fetch(:trades, [])
|
30
|
-
break if data[:page][:current] >= data[:page][:last]
|
31
|
-
|
32
|
-
pag += 1
|
33
|
-
end
|
34
|
-
ary
|
33
|
+
pag_de_req("#{API[:de]}/trades", { state: 1 }, :trades)
|
35
34
|
rescue Curl::Err::CurlError
|
36
|
-
|
35
|
+
[]
|
37
36
|
end
|
38
37
|
|
39
38
|
# @return [Array<Hash>] depositos uniformizados bitcoinde
|
40
39
|
def deposits_de
|
41
|
-
|
42
|
-
ary = []
|
43
|
-
loop do
|
44
|
-
url = "#{API[:de]}/btc/deposits?#{URI.encode_www_form(state: 2, page: pag)}"
|
45
|
-
data = parse_json(Curl.get(url) { |obj| obj.headers = hde(url) })
|
46
|
-
ary += data.fetch(:deposits, []).map { |has| deposit_unif(has) }
|
47
|
-
break if data[:page][:current] >= data[:page][:last]
|
48
|
-
|
49
|
-
pag += 1
|
50
|
-
end
|
51
|
-
ary
|
40
|
+
pag_de_req("#{API[:de]}/btc/deposits", { state: 2 }, :deposits) { |i| i.map { |h| deposit_unif(h) } }
|
52
41
|
rescue Curl::Err::CurlError
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
# @return [Hash] deposito uniformizado bitcoinde
|
57
|
-
def deposit_unif(has)
|
58
|
-
{ add: has[:address], time: Time.parse(has[:created_at]), qt: has[:amount], txid: Integer(has[:deposit_id]) }.merge(tp: 'deposit', moe: 'btc', fee: '0')
|
42
|
+
[]
|
59
43
|
end
|
60
44
|
|
61
45
|
# @return [Array<Hash>] withdrawals uniformizadas bitcoinde
|
62
46
|
def withdrawals_de
|
63
|
-
|
64
|
-
pag = 1
|
65
|
-
loop do
|
66
|
-
url = "#{API[:de]}/btc/withdrawals?#{URI.encode_www_form(state: 1, page: pag)}"
|
67
|
-
data = parse_json(Curl.get(url) { |obj| obj.headers = hde(url) })
|
68
|
-
ary += data.fetch(:withdrawals, []).map { |has| withdrawal_unif(has) }
|
69
|
-
break if data[:page][:current] >= data[:page][:last]
|
70
|
-
|
71
|
-
pag += 1
|
72
|
-
end
|
73
|
-
ary
|
47
|
+
pag_de_req("#{API[:de]}/btc/withdrawals", { state: 1 }, :withdrawals) { |i| i.map { |h| withdrawal_unif(h) } }
|
74
48
|
rescue Curl::Err::CurlError
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
# @return [Hash] withdrawal uniformizada bitcoinde
|
79
|
-
def withdrawal_unif(has)
|
80
|
-
{
|
81
|
-
add: has[:address],
|
82
|
-
time: Time.parse(has[:transferred_at]),
|
83
|
-
qt: has[:amount],
|
84
|
-
fee: has[:network_fee],
|
85
|
-
txid: Integer(has[:withdrawal_id])
|
86
|
-
}.merge(tp: 'withdrawal', moe: 'btc')
|
49
|
+
[]
|
87
50
|
end
|
88
51
|
|
89
52
|
# @return [Hash] saldos kraken
|
90
53
|
def account_us
|
91
54
|
uri = 'Balance'
|
92
55
|
ops = { nonce: nnc }
|
93
|
-
|
56
|
+
run_curl(@curl, "#{API[:us]}/#{uri}", method: :post, post_data: ops, headers: hus(uri, ops))
|
57
|
+
parse_json(@curl).fetch(:result, {})
|
94
58
|
rescue Curl::Err::CurlError
|
95
59
|
{}
|
96
60
|
end
|
97
61
|
|
98
62
|
# @return [Hash] trades kraken
|
99
63
|
def trades_us
|
100
|
-
|
101
|
-
has = {}
|
102
|
-
ofs = 0
|
103
|
-
loop do
|
104
|
-
sleep(1)
|
105
|
-
ops = { nonce: nnc, ofs: ofs }
|
106
|
-
result = parse_json(Curl.post("#{API[:us]}/#{uri}", ops) { |hed| hed.headers = hus(uri, ops) }).fetch(:result, {})
|
107
|
-
break if result.fetch(:trades, []).empty?
|
108
|
-
|
109
|
-
has.merge!(result[:trades])
|
110
|
-
ofs += result[:trades].size
|
111
|
-
end
|
112
|
-
has
|
64
|
+
pag_us_req('TradesHistory', :trades)
|
113
65
|
rescue Curl::Err::CurlError
|
114
|
-
|
66
|
+
{}
|
115
67
|
end
|
116
68
|
|
117
69
|
# @return [Hash] ledger kraken
|
118
70
|
def ledger_us
|
119
|
-
|
71
|
+
pag_us_req('Ledgers', :ledger)
|
72
|
+
rescue Curl::Err::CurlError
|
73
|
+
{}
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
# Generic paginated request handler for Kraken
|
79
|
+
def pag_us_req(uri, key)
|
120
80
|
has = {}
|
121
81
|
ofs = 0
|
122
82
|
loop do
|
123
|
-
sleep(2)
|
83
|
+
sleep(ofs.zero? ? 0 : 2)
|
124
84
|
ops = { nonce: nnc, ofs: ofs }
|
125
|
-
|
126
|
-
|
85
|
+
run_curl(@curl, "#{API[:us]}/#{uri}", method: :post, post_data: ops, headers: hus(uri, ops))
|
86
|
+
batch = parse_json(@curl).fetch(:result, {}).fetch(key, [])
|
87
|
+
break if batch.empty?
|
127
88
|
|
128
|
-
has.merge!(
|
129
|
-
ofs +=
|
89
|
+
has.merge!(batch)
|
90
|
+
ofs += batch.size
|
130
91
|
end
|
131
92
|
has
|
132
|
-
rescue Curl::Err::CurlError
|
133
|
-
has
|
134
93
|
end
|
135
94
|
|
136
|
-
|
95
|
+
# Generic paginated request handler for Bitcoin.de
|
96
|
+
def pag_de_req(base_url, params, key)
|
97
|
+
ary = []
|
98
|
+
pag = 1
|
99
|
+
loop do
|
100
|
+
url = "#{base_url}?#{URI.encode_www_form(params.merge(page: pag))}"
|
101
|
+
run_curl(@curl, url, headers: hde(url))
|
102
|
+
result = parse_json(@curl)
|
103
|
+
batch = result.fetch(key, [])
|
104
|
+
ary.concat(block_given? ? yield(batch) : batch)
|
105
|
+
break if result[:page]&.[](:current)&.>= result[:page]&.[](:last)
|
106
|
+
|
107
|
+
pag += 1
|
108
|
+
end
|
109
|
+
ary
|
110
|
+
end
|
111
|
+
|
112
|
+
# Configure Curl object for request
|
113
|
+
def run_curl(curl, url, method: :get, post_data: nil, headers: {})
|
114
|
+
curl.reset
|
115
|
+
curl.url = url
|
116
|
+
curl.http(method == :post ? 'POST' : 'GET')
|
117
|
+
curl.headers = headers
|
118
|
+
curl.post_body = URI.encode_www_form(post_data) if post_data
|
119
|
+
curl.perform
|
120
|
+
end
|
137
121
|
|
138
122
|
# Safe JSON parsing with error handling
|
139
123
|
def parse_json(res)
|
140
|
-
JSON.parse(res.
|
124
|
+
JSON.parse(res.body_str, symbolize_names: true)
|
141
125
|
rescue JSON::ParserError
|
142
126
|
{}
|
143
127
|
end
|
@@ -147,6 +131,24 @@ module Cns
|
|
147
131
|
Integer(Float(Time.now) * 1e6)
|
148
132
|
end
|
149
133
|
|
134
|
+
# @return [Hash] deposito uniformizado bitcoinde
|
135
|
+
def deposit_unif(has)
|
136
|
+
{ add: has[:address], time: Time.parse(has[:created_at]), qt: has[:amount], txid: Integer(has[:deposit_id]) }.merge(tp: 'deposit', moe: 'btc', fee: '0')
|
137
|
+
end
|
138
|
+
|
139
|
+
# @return [Hash] withdrawal uniformizada bitcoinde
|
140
|
+
def withdrawal_unif(has)
|
141
|
+
{
|
142
|
+
add: has[:address],
|
143
|
+
time: Time.parse(has[:transferred_at]),
|
144
|
+
qt: has[:amount],
|
145
|
+
fee: has[:network_fee],
|
146
|
+
txid: Integer(has[:withdrawal_id]),
|
147
|
+
tp: 'withdrawal',
|
148
|
+
moe: 'btc'
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
150
152
|
# @param [String] qde query a incluir no pedido HTTP
|
151
153
|
# @param [Integer] non continually-increasing unsigned integer
|
152
154
|
# @return [Hash] headers necessarios para pedido HTTP da exchange bitcoinde
|
data/lib/cns/version.rb
CHANGED