sibit 0.19.3 → 0.20.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/sibit +11 -2
- data/features/cli.feature +1 -1
- data/lib/sibit/bestof.rb +3 -2
- data/lib/sibit/btc.rb +14 -3
- data/lib/sibit/firstof.rb +4 -2
- data/lib/sibit/http.rb +2 -2
- data/lib/sibit/json.rb +11 -1
- data/lib/sibit/version.rb +1 -1
- data/sibit.gemspec +1 -1
- data/test/test_btc.rb +23 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a10cbcbf86d4a0c612ebba219e7e5d0a09480444280a106fd47bb41cbadd0405
|
4
|
+
data.tar.gz: 5c3ede973fe824a8f247099c6980b938dc83b07481553bf7925678837553d4ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bd040eb2e985bd9af773e4bcda1108939cecbcea6b4719f3779eba70a3ce3d2bd69c1deb5c8a748eaaeee85f98fcc6ac5f447189ef635befbd75d68abde6aff
|
7
|
+
data.tar.gz: ee1ba5bc4c7bd03d0f975a38c0d2f5d315804eb3444dad26b93511fed19ce3092420907d0a338d4d871dc1abc7fd9307bc3d9f4f7a97a46a6a5824be52c13c62
|
data/bin/sibit
CHANGED
@@ -29,9 +29,12 @@ require 'retriable_proxy'
|
|
29
29
|
require_relative '../lib/sibit'
|
30
30
|
require_relative '../lib/sibit/version'
|
31
31
|
require_relative '../lib/sibit/blockchain'
|
32
|
+
require_relative '../lib/sibit/blockchair'
|
32
33
|
require_relative '../lib/sibit/btc'
|
33
34
|
require_relative '../lib/sibit/bitcoinchain'
|
35
|
+
require_relative '../lib/sibit/cex'
|
34
36
|
require_relative '../lib/sibit/earn'
|
37
|
+
require_relative '../lib/sibit/fake'
|
35
38
|
require_relative '../lib/sibit/firstof'
|
36
39
|
|
37
40
|
begin
|
@@ -62,7 +65,7 @@ Options are:"
|
|
62
65
|
o.array(
|
63
66
|
'--api',
|
64
67
|
'Ordered List of APIs to use, e.g. "earn,blockchain,btc,bitcoinchain"',
|
65
|
-
default: %w[earn blockchain btc bitcoinchain]
|
68
|
+
default: %w[earn blockchain btc bitcoinchain blockchair cex]
|
66
69
|
)
|
67
70
|
end
|
68
71
|
rescue Slop::Error => ex
|
@@ -79,6 +82,12 @@ Options are:"
|
|
79
82
|
api = Sibit::Btc.new(http: http, log: log, dry: opts[:dry])
|
80
83
|
elsif a == 'bitcoinchain'
|
81
84
|
api = Sibit::Bitcoinchain.new(http: http, log: log, dry: opts[:dry])
|
85
|
+
elsif a == 'blockchair'
|
86
|
+
api = Sibit::Blockchair.new(http: http, log: log, dry: opts[:dry])
|
87
|
+
elsif a == 'cex'
|
88
|
+
api = Sibit::Cex.new(http: http, log: log, dry: opts[:dry])
|
89
|
+
elsif a == 'fake'
|
90
|
+
api = Sibit::Fake.new
|
82
91
|
elsif a == 'earn'
|
83
92
|
api = Sibit::Earn.new(http: http, log: log, dry: opts[:dry])
|
84
93
|
else
|
@@ -87,7 +96,7 @@ Options are:"
|
|
87
96
|
api = RetriableProxy.for_object(api, on: Sibit::Error) if opts[:attempts] > 1
|
88
97
|
api
|
89
98
|
end
|
90
|
-
sibit = Sibit.new(log: log, api: Sibit::FirstOf.new(apis, log: log))
|
99
|
+
sibit = Sibit.new(log: log, api: Sibit::FirstOf.new(apis, log: log, verbose: true))
|
91
100
|
case opts.arguments[0]
|
92
101
|
when 'price'
|
93
102
|
puts sibit.price
|
data/features/cli.feature
CHANGED
data/lib/sibit/bestof.rb
CHANGED
@@ -32,9 +32,10 @@ class Sibit
|
|
32
32
|
# Best of API.
|
33
33
|
class BestOf
|
34
34
|
# Constructor.
|
35
|
-
def initialize(list, log: Sibit::Log.new)
|
35
|
+
def initialize(list, log: Sibit::Log.new, verbose: false)
|
36
36
|
@list = list
|
37
37
|
@log = log
|
38
|
+
@verbose = verbose
|
38
39
|
end
|
39
40
|
|
40
41
|
# Current price of BTC in USD (float returned).
|
@@ -106,7 +107,7 @@ class Sibit
|
|
106
107
|
begin
|
107
108
|
results << yield(api)
|
108
109
|
rescue Sibit::Error => e
|
109
|
-
@log.info("The API #{api.class.name} failed at #{method}(): #{e.message}")
|
110
|
+
@log.info("The API #{api.class.name} failed at #{method}(): #{e.message}") if @verbose
|
110
111
|
end
|
111
112
|
end
|
112
113
|
if results.empty?
|
data/lib/sibit/btc.rb
CHANGED
@@ -64,6 +64,10 @@ class Sibit
|
|
64
64
|
return 0
|
65
65
|
end
|
66
66
|
txns = data['list']
|
67
|
+
if txns.nil?
|
68
|
+
@log.info("The balance of #{address} is probably zero (not found)")
|
69
|
+
return 0
|
70
|
+
end
|
67
71
|
balance = txns.map { |tx| tx['value'] }.inject(&:+) || 0
|
68
72
|
@log.info("The balance of #{address} is #{balance}, total txns: #{txns.count}")
|
69
73
|
balance
|
@@ -91,6 +95,7 @@ class Sibit
|
|
91
95
|
data = json['data']
|
92
96
|
raise Sibit::Error, "The block #{hash} not found" if data.nil?
|
93
97
|
h = data['height']
|
98
|
+
raise Sibit::Error, "The block #{hash} found but the height is absent" if h.nil?
|
94
99
|
@log.info("The height of #{hash} is #{h}")
|
95
100
|
h
|
96
101
|
end
|
@@ -120,7 +125,9 @@ class Sibit
|
|
120
125
|
)
|
121
126
|
data = json['data']
|
122
127
|
raise Sibit::Error, "The address #{hash} not found" if data.nil?
|
123
|
-
data['list']
|
128
|
+
txns = data['list']
|
129
|
+
next if txns.nil?
|
130
|
+
txns.each do |u|
|
124
131
|
outs = Sibit::Json.new(http: @http, log: @log).get(
|
125
132
|
URI("https://chain.api.btc.com/v3/tx/#{u['tx_hash']}?verbose=3")
|
126
133
|
)['data']['outputs']
|
@@ -169,9 +176,13 @@ class Sibit
|
|
169
176
|
psize = 50
|
170
177
|
all = []
|
171
178
|
loop do
|
172
|
-
|
179
|
+
data = Sibit::Json.new(http: @http, log: @log).get(
|
173
180
|
URI("https://chain.api.btc.com/v3/block/#{hash}/tx?page=#{page}&pagesize=#{psize}")
|
174
|
-
)['data']
|
181
|
+
)['data']
|
182
|
+
raise Sibit::Error, "The block #{hash} has no data at page #{page}" if data.nil?
|
183
|
+
list = data['list']
|
184
|
+
raise Sibit::Error, "The list is empty for block #{hash} at page #{page}" if list.nil?
|
185
|
+
txns = list.map do |t|
|
175
186
|
{
|
176
187
|
hash: t['hash'],
|
177
188
|
outputs: t['outputs'].reject { |o| o['spent_by_tx'] }.map do |o|
|
data/lib/sibit/firstof.rb
CHANGED
@@ -32,9 +32,10 @@ class Sibit
|
|
32
32
|
# First of API.
|
33
33
|
class FirstOf
|
34
34
|
# Constructor.
|
35
|
-
def initialize(list, log: Sibit::Log.new)
|
35
|
+
def initialize(list, log: Sibit::Log.new, verbose: false)
|
36
36
|
@list = list
|
37
37
|
@log = log
|
38
|
+
@verbose = verbose
|
38
39
|
end
|
39
40
|
|
40
41
|
# Current price of BTC in USD (float returned).
|
@@ -104,12 +105,13 @@ class Sibit
|
|
104
105
|
done = false
|
105
106
|
result = nil
|
106
107
|
@list.each do |api|
|
108
|
+
@log.info("Calling #{api.class.name}##{method}()...")
|
107
109
|
begin
|
108
110
|
result = yield api
|
109
111
|
done = true
|
110
112
|
break
|
111
113
|
rescue Sibit::Error => e
|
112
|
-
@log.info("The API #{api.class.name} failed at #{method}(): #{e.message}")
|
114
|
+
@log.info("The API #{api.class.name} failed at #{method}(): #{e.message}") if @verbose
|
113
115
|
end
|
114
116
|
end
|
115
117
|
unless done
|
data/lib/sibit/http.rb
CHANGED
@@ -33,7 +33,7 @@ class Sibit
|
|
33
33
|
def client(uri)
|
34
34
|
http = Net::HTTP.new(uri.host, uri.port)
|
35
35
|
http.use_ssl = true
|
36
|
-
http.read_timeout =
|
36
|
+
http.read_timeout = 240
|
37
37
|
http
|
38
38
|
end
|
39
39
|
end
|
@@ -47,7 +47,7 @@ class Sibit
|
|
47
47
|
def client(uri)
|
48
48
|
http = Net::HTTP.new(uri.host, uri.port, @host, @port.to_i)
|
49
49
|
http.use_ssl = true
|
50
|
-
http.read_timeout =
|
50
|
+
http.read_timeout = 240
|
51
51
|
http
|
52
52
|
end
|
53
53
|
end
|
data/lib/sibit/json.rb
CHANGED
@@ -62,7 +62,7 @@ class Sibit
|
|
62
62
|
unless accept.include?(res.code.to_i)
|
63
63
|
raise Sibit::Error, "Failed to retrieve #{uri} (#{res.code}): #{res.body}"
|
64
64
|
end
|
65
|
-
@log.info("GET #{uri}: #{res.code}/#{res.body.length}
|
65
|
+
@log.info("GET #{uri}: #{res.code}/#{length(res.body.length)} in #{age(start)}")
|
66
66
|
JSON.parse(res.body)
|
67
67
|
end
|
68
68
|
|
@@ -91,6 +91,16 @@ class Sibit
|
|
91
91
|
"#{((Time.now - start) * 1000).round}ms"
|
92
92
|
end
|
93
93
|
|
94
|
+
def length(bytes)
|
95
|
+
if bytes > 1024 * 1024
|
96
|
+
"#{bytes / (1024 * 1024)}mb"
|
97
|
+
elsif bytes > 1024
|
98
|
+
"#{bytes / 1024}kb"
|
99
|
+
else
|
100
|
+
"#{bytes}b"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
94
104
|
def user_agent
|
95
105
|
"Anonymous/#{Sibit::VERSION}"
|
96
106
|
end
|
data/lib/sibit/version.rb
CHANGED
data/sibit.gemspec
CHANGED
@@ -55,7 +55,7 @@ and Ruby 2.3+.'
|
|
55
55
|
s.add_runtime_dependency 'retriable_proxy', '1.0.2'
|
56
56
|
s.add_runtime_dependency 'slop', '~> 4.6'
|
57
57
|
s.add_development_dependency 'aruba', '~> 0.14.1'
|
58
|
-
s.add_development_dependency 'codecov', '0.
|
58
|
+
s.add_development_dependency 'codecov', '0.2.8'
|
59
59
|
s.add_development_dependency 'cucumber', '~> 1.3.17'
|
60
60
|
s.add_development_dependency 'debase', '0.2.2'
|
61
61
|
s.add_development_dependency 'minitest', '5.5.0'
|
data/test/test_btc.rb
CHANGED
@@ -42,6 +42,17 @@ class TestBtc < Minitest::Test
|
|
42
42
|
assert_equal(0, balance)
|
43
43
|
end
|
44
44
|
|
45
|
+
def test_get_zero_balance_no_txns
|
46
|
+
stub_request(
|
47
|
+
:get,
|
48
|
+
'https://chain.api.btc.com/v3/address/1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f/unspent'
|
49
|
+
).to_return(body: '{"data":{}}')
|
50
|
+
sibit = Sibit::Btc.new
|
51
|
+
balance = sibit.balance('1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f')
|
52
|
+
assert(balance.is_a?(Integer))
|
53
|
+
assert_equal(0, balance)
|
54
|
+
end
|
55
|
+
|
45
56
|
def test_get_broken_balance
|
46
57
|
stub_request(
|
47
58
|
:get,
|
@@ -75,6 +86,18 @@ class TestBtc < Minitest::Test
|
|
75
86
|
assert_equal(123, balance)
|
76
87
|
end
|
77
88
|
|
89
|
+
def test_fetch_block_broken
|
90
|
+
hash = '000000000000000007341915521967247f1dec17b3a311b8a8f4495392f1439b'
|
91
|
+
stub_request(:get, "https://chain.api.btc.com/v3/block/#{hash}")
|
92
|
+
.to_return(body: '{"data": {"next_block_hash": "n", "hash": "h", "prev_block_hash": "p"}}')
|
93
|
+
stub_request(:get, "https://chain.api.btc.com/v3/block/#{hash}/tx?page=1&pagesize=50")
|
94
|
+
.to_return(body: '{}')
|
95
|
+
sibit = Sibit::Btc.new
|
96
|
+
assert_raises Sibit::Error do
|
97
|
+
sibit.block(hash)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
78
101
|
def test_fetch_block
|
79
102
|
hash = '000000000000000007341915521967247f1dec17b3a311b8a8f4495392f1439b'
|
80
103
|
stub_request(:get, "https://chain.api.btc.com/v3/block/#{hash}")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sibit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.20.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backtrace
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - '='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
117
|
+
version: 0.2.8
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - '='
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
124
|
+
version: 0.2.8
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: cucumber
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|