sibit 0.19.2 → 0.20.2

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: db71c5de986c5aeacfb60ddde907c84eade4b53e2b764f513cd6ea20c7a95c45
4
- data.tar.gz: c79bc1c5b9c544bcc16a61fff3912f09dd5b05152d5cbf667b418d5207d37575
3
+ metadata.gz: 0734db295c639e548f4b51d170e87bbabe2c6b94d7d4ba7e858716b74f145185
4
+ data.tar.gz: 9ff51aecc8e78f13917907f62e6485800531dd7d36198df80b5a089831fcbfcc
5
5
  SHA512:
6
- metadata.gz: 951c554ef902b64007c6807976c99f44f909a28730bff366135d5fb2728cae935df206fd065f9500d4f885982c10175c9775ba3001bb37de42ad2f2969dd45ee
7
- data.tar.gz: b60396b85498717187962637e00008b394eddcb030cdfb5839b3d043bfc086974f05f638057940f621ab1d7d60016857ed19d7bb0354325adcd3e5ebc964f3da
6
+ metadata.gz: '0095805aee3fbe209a73bcda6a9832e9aa26b43414232c6fa59d6fbed09a7648bcd6739e76a558106f86a152a9ebbf5b36c32afffd927f9a2f5feaa34fa4c4d4'
7
+ data.tar.gz: 0fde0492c34a1f636180f01d0a331da019e8b461b0819909869cd9f0b5b3f6fb9070f1d79fa6a80f87f3f8903975abeeb7a6e30e9b9b8a4fa5de7f8fbf522794
@@ -5,7 +5,7 @@ install: |
5
5
  sudo bundle install --no-color "--gemfile=$(pwd)/Gemfile"
6
6
  release:
7
7
  script: |-
8
- bundle exec rake
8
+ bundle exec rake clean test rubocop copyright
9
9
  sed -i "s/1\.0\.snapshot/${tag}/g" lib/sibit/version.rb
10
10
  git add lib/sibit/version.rb
11
11
  git commit -m "version set to ${tag}"
@@ -14,7 +14,7 @@ release:
14
14
  gem push *.gem --config-file ../rubygems.yml
15
15
  merge:
16
16
  script: |-
17
- bundle exec rake
17
+ bundle exec rake clean test rubocop copyright
18
18
  deploy:
19
19
  script: |-
20
20
  echo "There is nothing to deploy"
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
@@ -31,5 +31,5 @@ Feature: Command Line Processing
31
31
  Then Exit code is zero
32
32
 
33
33
  Scenario: Bitcoin fees can be printed
34
- When I run bin/sibit with "fees --verbose"
34
+ When I run bin/sibit with "fees --verbose --api=fake"
35
35
  Then Exit code is zero
@@ -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?
@@ -58,7 +58,16 @@ class Sibit
58
58
  @log.info("The balance of #{address} is zero (not found)")
59
59
  return 0
60
60
  end
61
- txns = json['data']['list']
61
+ data = json['data']
62
+ if data.nil?
63
+ @log.info("The balance of #{address} is probably zero (not found)")
64
+ return 0
65
+ end
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
62
71
  balance = txns.map { |tx| tx['value'] }.inject(&:+) || 0
63
72
  @log.info("The balance of #{address} is #{balance}, total txns: #{txns.count}")
64
73
  balance
@@ -86,6 +95,7 @@ class Sibit
86
95
  data = json['data']
87
96
  raise Sibit::Error, "The block #{hash} not found" if data.nil?
88
97
  h = data['height']
98
+ raise Sibit::Error, "The block #{hash} found but the height is absent" if h.nil?
89
99
  @log.info("The height of #{hash} is #{h}")
90
100
  h
91
101
  end
@@ -115,7 +125,9 @@ class Sibit
115
125
  )
116
126
  data = json['data']
117
127
  raise Sibit::Error, "The address #{hash} not found" if data.nil?
118
- data['list'].each do |u|
128
+ txns = data['list']
129
+ next if txns.nil?
130
+ txns.each do |u|
119
131
  outs = Sibit::Json.new(http: @http, log: @log).get(
120
132
  URI("https://chain.api.btc.com/v3/tx/#{u['tx_hash']}?verbose=3")
121
133
  )['data']['outputs']
@@ -164,9 +176,13 @@ class Sibit
164
176
  psize = 50
165
177
  all = []
166
178
  loop do
167
- txns = Sibit::Json.new(http: @http, log: @log).get(
179
+ data = Sibit::Json.new(http: @http, log: @log).get(
168
180
  URI("https://chain.api.btc.com/v3/block/#{hash}/tx?page=#{page}&pagesize=#{psize}")
169
- )['data']['list'].map do |t|
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|
170
186
  {
171
187
  hash: t['hash'],
172
188
  outputs: t['outputs'].reject { |o| o['spent_by_tx'] }.map do |o|
@@ -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
@@ -26,5 +26,5 @@
26
26
  # License:: MIT
27
27
  class Sibit
28
28
  # Current version of the library.
29
- VERSION = '0.19.2'
29
+ VERSION = '0.20.2'
30
30
  end
@@ -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.1.10'
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'
@@ -42,6 +42,28 @@ 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
+
56
+ def test_get_broken_balance
57
+ stub_request(
58
+ :get,
59
+ 'https://chain.api.btc.com/v3/address/1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f/unspent'
60
+ ).to_return(body: '{}')
61
+ sibit = Sibit::Btc.new
62
+ balance = sibit.balance('1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f')
63
+ assert(balance.is_a?(Integer))
64
+ assert_equal(0, balance)
65
+ end
66
+
45
67
  def test_get_empty_balance
46
68
  stub_request(
47
69
  :get,
@@ -64,6 +86,18 @@ class TestBtc < Minitest::Test
64
86
  assert_equal(123, balance)
65
87
  end
66
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
+
67
101
  def test_fetch_block
68
102
  hash = '000000000000000007341915521967247f1dec17b3a311b8a8f4495392f1439b'
69
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.19.2
4
+ version: 0.20.2
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-07-08 00:00:00.000000000 Z
11
+ date: 2020-08-27 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.1.10
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.1.10
124
+ version: 0.2.8
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: cucumber
127
127
  requirement: !ruby/object:Gem::Requirement