sibit 0.18.5 → 0.19.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f85d6af8efe3b90b84fd7a5756ebda0c31ed50da36cc9a264424a531c8a8b10
4
- data.tar.gz: 8008c7deb9d9981a7a0fc8b959effb2eb4d77b4fd58080e9a0e7a8b2df9476bd
3
+ metadata.gz: 63efa03d475df765f994bd609f8f5deb31cea1450566f1e68a8c5a8ac497ec0c
4
+ data.tar.gz: c36540c991e462bf6825d9a48109a3f0c1a4ca1934b4741a17074a3cf8503565
5
5
  SHA512:
6
- metadata.gz: ea92cf18899819136b9ff0f4a7e8a1fae200a70633e79e9dcfdb01006c42518757577f0105f3b7e78604275b0a38cf23ee37a2f5758c2caddb6add807032305d
7
- data.tar.gz: 7e2cfe391ea6862616eb475c09ca5a7fb86cc92d95c1366dc56c4d32dba4d3d8fa1d6974d36b0e52ed1eee60658ff82d0fca0ccf56042ed4ce3dcb31781025b9
6
+ metadata.gz: 98cc194b64718dc11ba35650a6c1bda4b52e4ca04cd935784f45387fb6dbdb552de00343d5e7dfd90ba796137500028bf5c31177006a087f2ec2a754751d3a5e
7
+ data.tar.gz: 161f739388531e1b79ca07860d374023c0ff8109de32b35d35dc487892b4fa09e2db2471a524983aa8f2e35723806053dcbeb0e98ecc9ff2e8ecfe2e1da737ec
@@ -4,6 +4,8 @@ AllCops:
4
4
  DisplayCopNames: true
5
5
  TargetRubyVersion: 2.3
6
6
 
7
+ Style/ClassAndModuleChildren:
8
+ Enabled: false
7
9
  Metrics/LineLength:
8
10
  Max: 100
9
11
  Layout/EndOfLine:
@@ -1,15 +1,11 @@
1
1
  assets:
2
2
  rubygems.yml: yegor256/home#assets/rubygems.yml
3
3
  install: |
4
- export GEM_HOME=~/.ruby
5
- export GEM_PATH=$GEM_HOME:$GEM_PATH
6
- sudo apt-get -y update
7
- sudo gem install pdd -v 0.20.5
8
- bundle install
4
+ pdd -f /dev/null
5
+ sudo bundle install --no-color "--gemfile=$(pwd)/Gemfile"
9
6
  release:
10
7
  script: |-
11
8
  bundle exec rake
12
- rm -rf *.gem
13
9
  sed -i "s/1\.0\.snapshot/${tag}/g" lib/sibit/version.rb
14
10
  git add lib/sibit/version.rb
15
11
  git commit -m "version set to ${tag}"
@@ -19,7 +15,6 @@ release:
19
15
  merge:
20
16
  script: |-
21
17
  bundle exec rake
22
- pdd -f /dev/null
23
18
  deploy:
24
19
  script: |-
25
20
  echo "There is nothing to deploy"
data/README.md CHANGED
@@ -107,7 +107,7 @@ pkey = sibit.generate
107
107
  address = sibit.create(pkey)
108
108
  balance = sibit.balance(address)
109
109
  target = sibit.create(pkey) # where to send coins to
110
- change = sibit.create(pkey) # where the change will sent to
110
+ change = sibit.create(pkey) # where the change will be sent to
111
111
  tx = sibit.pay(10_000_000, 'XL', { address => pkey }, target, change)
112
112
  ```
113
113
 
@@ -145,7 +145,14 @@ will be used one by one, until a successful response is obtained:
145
145
  require 'sibit'
146
146
  require 'sibit/btc'
147
147
  require 'sibit/cryptoapis'
148
- sibit = Sibit.new(api: [Sibit::Btc.new, Sibit::Cryptoapis.new('key')])
148
+ sibit = Sibit.new(
149
+ api: Sibit::FirstOf.new(
150
+ [
151
+ Sibit::Btc.new,
152
+ Sibit::Cryptoapis.new('key')
153
+ ]
154
+ )
155
+ )
149
156
  ```
150
157
 
151
158
  If you think we may need to use some other API, you can submit a ticket,
data/bin/sibit CHANGED
@@ -32,6 +32,7 @@ require_relative '../lib/sibit/blockchain'
32
32
  require_relative '../lib/sibit/btc'
33
33
  require_relative '../lib/sibit/bitcoinchain'
34
34
  require_relative '../lib/sibit/earn'
35
+ require_relative '../lib/sibit/firstof'
35
36
 
36
37
  begin
37
38
  begin
@@ -86,7 +87,7 @@ Options are:"
86
87
  api = RetriableProxy.for_object(api, on: Sibit::Error) if opts[:attempts] > 1
87
88
  api
88
89
  end
89
- sibit = Sibit.new(log: log, api: apis)
90
+ sibit = Sibit.new(log: log, api: Sibit::FirstOf.new(apis, log: log))
90
91
  case opts.arguments[0]
91
92
  when 'price'
92
93
  puts sibit.price
@@ -55,9 +55,7 @@ class Sibit
55
55
 
56
56
  # Current price of 1 BTC in USD (or another currency), float returned.
57
57
  def price(currency = 'USD')
58
- first_one do |api|
59
- api.price(currency)
60
- end
58
+ @api.price(currency)
61
59
  end
62
60
 
63
61
  # Generates new Bitcon private key and returns in Hash160 format.
@@ -76,29 +74,23 @@ class Sibit
76
74
 
77
75
  # Gets the balance of the address, in satoshi.
78
76
  def balance(address)
79
- first_one do |api|
80
- api.balance(address)
81
- end
77
+ @api.balance(address)
82
78
  end
83
79
 
84
80
  # Get the height of the block.
85
81
  def height(hash)
86
- first_one do |api|
87
- api.height(hash)
88
- end
82
+ @api.height(hash)
89
83
  end
90
84
 
91
85
  # Get the hash of the next block.
92
86
  def next_of(hash)
93
- first_one do |api|
94
- api.next_of(hash)
95
- end
87
+ @api.next_of(hash)
96
88
  end
97
89
 
98
90
  # Get recommended fees, in satoshi per byte. The method returns
99
91
  # a hash: { S: 12, M: 45, L: 100, XL: 200 }
100
92
  def fees
101
- first_one(&:fees)
93
+ @api.fees
102
94
  end
103
95
 
104
96
  # Sends a payment and returns the transaction hash.
@@ -124,7 +116,7 @@ class Sibit
124
116
  builder = Bitcoin::Builder::TxBuilder.new
125
117
  unspent = 0
126
118
  size = 100
127
- utxos = first_one { |api| api.utxos(sources.keys) }
119
+ utxos = @api.utxos(sources.keys)
128
120
  @log.info("#{utxos.count} UTXOs found, these will be used \
129
121
  (value/confirmations at tx_hash):")
130
122
  utxos.each do |utxo|
@@ -170,15 +162,13 @@ class Sibit
170
162
  Amount: #{num(satoshi, p)}
171
163
  Target address: #{target}
172
164
  Change address is #{change}")
173
- first_one do |api|
174
- api.push(tx.to_payload.bth)
175
- end
165
+ @api.push(tx.to_payload.bth)
176
166
  tx.hash
177
167
  end
178
168
 
179
169
  # Gets the hash of the latest block.
180
170
  def latest
181
- first_one(&:latest)
171
+ @api.latest
182
172
  end
183
173
 
184
174
  # You call this method and provide a callback. You provide the hash
@@ -197,7 +187,7 @@ class Sibit
197
187
  wrong = []
198
188
  json = {}
199
189
  loop do
200
- json = first_one { |api| api.block(block) }
190
+ json = @api.block(block)
201
191
  if json[:orphan]
202
192
  steps = 4
203
193
  @log.info("Orphan block found at #{block}, moving #{steps} steps back...")
@@ -206,7 +196,7 @@ class Sibit
206
196
  block = json[:previous]
207
197
  wrong << block
208
198
  @log.info("Moved back to #{block}")
209
- json = first_one { |api| api.block(block) }
199
+ json = @api.block(block)
210
200
  end
211
201
  next
212
202
  end
@@ -224,13 +214,13 @@ class Sibit
224
214
  end
225
215
  checked += 1
226
216
  end
217
+ count += 1
227
218
  @log.info("We checked #{checked} txns and #{checked_outputs} outputs in block #{block}")
228
219
  block = json[:next]
229
220
  if block.nil?
230
221
  @log.info("The next_block is empty in block #{json[:hash]}, this is the end of Blockchain")
231
222
  break
232
223
  end
233
- count += 1
234
224
  if count > max
235
225
  @log.info("Too many blocks (#{count}) in one go, let's get back to it next time")
236
226
  break
@@ -242,26 +232,6 @@ class Sibit
242
232
 
243
233
  private
244
234
 
245
- def first_one
246
- return yield @api unless @api.is_a?(Array)
247
- done = false
248
- result = nil
249
- @api.each do |api|
250
- begin
251
- result = yield api
252
- done = true
253
- break
254
- rescue Sibit::Error => e
255
- @log.info("The API #{api.class.name} failed: #{e.message}")
256
- end
257
- end
258
- unless done
259
- raise Sibit::Error, "No APIs out of #{@api.length} managed to succeed: \
260
- #{@api.map { |a| a.class.name }.join(', ')}"
261
- end
262
- result
263
- end
264
-
265
235
  def num(satoshi, usd)
266
236
  format(
267
237
  '%<satoshi>ss/$%<dollars>0.2f',
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-2020 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require_relative 'error'
24
+ require_relative 'log'
25
+
26
+ # API best of.
27
+ #
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2019-2020 Yegor Bugayenko
30
+ # License:: MIT
31
+ class Sibit
32
+ # Best of API.
33
+ class BestOf
34
+ # Constructor.
35
+ def initialize(list, log: Sibit::Log.new)
36
+ @list = list
37
+ @log = log
38
+ end
39
+
40
+ # Current price of BTC in USD (float returned).
41
+ def price(currency = 'USD')
42
+ best_of('price') do |api|
43
+ api.price(currency)
44
+ end
45
+ end
46
+
47
+ # Gets the balance of the address, in satoshi.
48
+ def balance(address)
49
+ best_of('balance') do |api|
50
+ api.balance(address)
51
+ end
52
+ end
53
+
54
+ # Get the height of the block.
55
+ def height(hash)
56
+ best_of('height') do |api|
57
+ api.height(hash)
58
+ end
59
+ end
60
+
61
+ # Get the hash of the next block.
62
+ def next_of(hash)
63
+ best_of('next_of') do |api|
64
+ api.next_of(hash)
65
+ end
66
+ end
67
+
68
+ # Get recommended fees, in satoshi per byte. The method returns
69
+ # a hash: { S: 12, M: 45, L: 100, XL: 200 }
70
+ def fees
71
+ best_of('fees', &:fees)
72
+ end
73
+
74
+ # Fetch all unspent outputs per address.
75
+ def utxos(keys)
76
+ best_of('utxos') do |api|
77
+ api.utxos(keys)
78
+ end
79
+ end
80
+
81
+ # Latest block hash.
82
+ def latest
83
+ best_of('latest', &:latest)
84
+ end
85
+
86
+ # Push this transaction (in hex format) to the network.
87
+ def push(hex)
88
+ best_of('push') do |api|
89
+ api.push(hex)
90
+ end
91
+ end
92
+
93
+ # This method should fetch a block and return as a hash.
94
+ def block(hash)
95
+ best_of('block') do |api|
96
+ api.block(hash)
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def best_of(method)
103
+ return yield @list unless @list.is_a?(Array)
104
+ results = []
105
+ @list.each do |api|
106
+ begin
107
+ results << yield(api)
108
+ rescue Sibit::Error => e
109
+ @log.info("The API #{api.class.name} failed at #{method}(): #{e.message}")
110
+ end
111
+ end
112
+ if results.empty?
113
+ raise Sibit::Error, "No APIs out of #{@api.length} managed to succeed at #{method}(): \
114
+ #{@api.map { |a| a.class.name }.join(', ')}"
115
+ end
116
+ results.group_by(&:to_s).values.max_by(&:size)[0]
117
+ end
118
+ end
119
+ end
@@ -72,7 +72,7 @@ class Sibit
72
72
  end
73
73
  a = json['address']
74
74
  b = a['balance']
75
- @log.info("The balance of #{address} is #{b} satoshi (#{a['transactions'].length} txns)")
75
+ @log.info("The balance of #{address} is #{b} satoshi")
76
76
  b
77
77
  end
78
78
 
@@ -69,7 +69,9 @@ class Sibit
69
69
  head = Sibit::Json.new(http: @http, log: @log).get(
70
70
  URI("https://chain.api.btc.com/v3/block/#{hash}")
71
71
  )
72
- nxt = head['data']['next_block_hash']
72
+ data = head['data']
73
+ raise Sibit::Error, "The block #{hash} not found" if data.nil?
74
+ nxt = data['next_block_hash']
73
75
  nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
74
76
  @log.info("The block #{hash} is the latest, there is no next block") if nxt.nil?
75
77
  @log.info("The next block of #{hash} is #{nxt}") unless nxt.nil?
@@ -81,7 +83,9 @@ class Sibit
81
83
  json = Sibit::Json.new(http: @http, log: @log).get(
82
84
  URI("https://chain.api.btc.com/v3/block/#{hash}")
83
85
  )
84
- h = json['data']['height']
86
+ data = json['data']
87
+ raise Sibit::Error, "The block #{hash} not found" if data.nil?
88
+ h = data['height']
85
89
  @log.info("The height of #{hash} is #{h}")
86
90
  h
87
91
  end
@@ -95,7 +99,9 @@ class Sibit
95
99
  def latest
96
100
  uri = URI('https://chain.api.btc.com/v3/block/latest')
97
101
  json = Sibit::Json.new(http: @http, log: @log).get(uri)
98
- hash = json['data']['hash']
102
+ data = json['data']
103
+ raise Sibit::Error, 'The latest block not found' if data.nil?
104
+ hash = data['hash']
99
105
  @log.info("The hash of the latest block is #{hash}")
100
106
  hash
101
107
  end
@@ -107,7 +113,9 @@ class Sibit
107
113
  json = Sibit::Json.new(http: @http, log: @log).get(
108
114
  URI("https://chain.api.btc.com/v3/address/#{hash}/unspent")
109
115
  )
110
- json['data']['list'].each do |u|
116
+ data = json['data']
117
+ raise Sibit::Error, "The address #{hash} not found" if data.nil?
118
+ data['list'].each do |u|
111
119
  outs = Sibit::Json.new(http: @http, log: @log).get(
112
120
  URI("https://chain.api.btc.com/v3/tx/#{u['tx_hash']}?verbose=3")
113
121
  )['data']['outputs']
@@ -136,13 +144,15 @@ class Sibit
136
144
  head = Sibit::Json.new(http: @http, log: @log).get(
137
145
  URI("https://chain.api.btc.com/v3/block/#{hash}")
138
146
  )
139
- nxt = head['data']['next_block_hash']
147
+ data = head['data']
148
+ raise Sibit::Error, "The block #{hash} not found" if data.nil?
149
+ nxt = data['next_block_hash']
140
150
  nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
141
151
  {
142
- hash: head['data']['hash'],
143
- orphan: head['data']['is_orphan'],
152
+ hash: data['hash'],
153
+ orphan: data['is_orphan'],
144
154
  next: nxt,
145
- previous: head['data']['prev_block_hash'],
155
+ previous: data['prev_block_hash'],
146
156
  txns: txns(hash)
147
157
  }
148
158
  end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-2020 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require_relative 'error'
24
+ require_relative 'log'
25
+
26
+ # API first of.
27
+ #
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2019-2020 Yegor Bugayenko
30
+ # License:: MIT
31
+ class Sibit
32
+ # First of API.
33
+ class FirstOf
34
+ # Constructor.
35
+ def initialize(list, log: Sibit::Log.new)
36
+ @list = list
37
+ @log = log
38
+ end
39
+
40
+ # Current price of BTC in USD (float returned).
41
+ def price(currency = 'USD')
42
+ first_of('price') do |api|
43
+ api.price(currency)
44
+ end
45
+ end
46
+
47
+ # Gets the balance of the address, in satoshi.
48
+ def balance(address)
49
+ first_of('balance') do |api|
50
+ api.balance(address)
51
+ end
52
+ end
53
+
54
+ # Get the height of the block.
55
+ def height(hash)
56
+ first_of('height') do |api|
57
+ api.height(hash)
58
+ end
59
+ end
60
+
61
+ # Get the hash of the next block.
62
+ def next_of(hash)
63
+ first_of('next_of') do |api|
64
+ api.next_of(hash)
65
+ end
66
+ end
67
+
68
+ # Get recommended fees, in satoshi per byte. The method returns
69
+ # a hash: { S: 12, M: 45, L: 100, XL: 200 }
70
+ def fees
71
+ first_of('fees', &:fees)
72
+ end
73
+
74
+ # Fetch all unspent outputs per address.
75
+ def utxos(keys)
76
+ first_of('utxos') do |api|
77
+ api.utxos(keys)
78
+ end
79
+ end
80
+
81
+ # Latest block hash.
82
+ def latest
83
+ first_of('latest', &:latest)
84
+ end
85
+
86
+ # Push this transaction (in hex format) to the network.
87
+ def push(hex)
88
+ first_of('push') do |api|
89
+ api.push(hex)
90
+ end
91
+ end
92
+
93
+ # This method should fetch a block and return as a hash.
94
+ def block(hash)
95
+ first_of('block') do |api|
96
+ api.block(hash)
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def first_of(method)
103
+ return yield @list unless @list.is_a?(Array)
104
+ done = false
105
+ result = nil
106
+ @list.each do |api|
107
+ begin
108
+ result = yield api
109
+ done = true
110
+ break
111
+ rescue Sibit::Error => e
112
+ @log.info("The API #{api.class.name} failed at #{method}(): #{e.message}")
113
+ end
114
+ end
115
+ unless done
116
+ raise Sibit::Error, "No APIs out of #{@api.length} managed to succeed at #{method}(): \
117
+ #{@api.map { |a| a.class.name }.join(', ')}"
118
+ end
119
+ result
120
+ end
121
+ end
122
+ end
@@ -26,5 +26,5 @@
26
26
  # License:: MIT
27
27
  class Sibit
28
28
  # Current version of the library.
29
- VERSION = '0.18.5'
29
+ VERSION = '0.19.1'
30
30
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-2020 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require_relative '../lib/sibit'
25
+ require_relative '../lib/sibit/fake'
26
+ require_relative '../lib/sibit/bestof'
27
+
28
+ # Sibit::BestOf test.
29
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
30
+ # Copyright:: Copyright (c) 2019-2020 Yegor Bugayenko
31
+ # License:: MIT
32
+ class TestBestOf < Minitest::Test
33
+ def test_not_array
34
+ sibit = Sibit::BestOf.new(Sibit::Fake.new)
35
+ assert_equal(64, sibit.latest.length)
36
+ assert_equal(12, sibit.fees[:S])
37
+ end
38
+
39
+ def test_one_apis
40
+ sibit = Sibit::BestOf.new([Sibit::Fake.new])
41
+ assert_equal(64, sibit.latest.length)
42
+ assert_equal(12, sibit.fees[:S])
43
+ end
44
+
45
+ def test_two_apis
46
+ sibit = Sibit::BestOf.new([Sibit::Fake.new, Sibit::Fake.new])
47
+ assert_equal(64, sibit.latest.length)
48
+ assert_equal(12, sibit.fees[:S])
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-2020 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require_relative '../lib/sibit'
25
+ require_relative '../lib/sibit/fake'
26
+ require_relative '../lib/sibit/firstof'
27
+
28
+ # Sibit::FirstOf test.
29
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
30
+ # Copyright:: Copyright (c) 2019-2020 Yegor Bugayenko
31
+ # License:: MIT
32
+ class TestFirstOf < Minitest::Test
33
+ def test_not_array
34
+ sibit = Sibit::FirstOf.new(Sibit::Fake.new)
35
+ assert_equal(64, sibit.latest.length)
36
+ assert_equal(12, sibit.fees[:S])
37
+ end
38
+
39
+ def test_one_apis
40
+ sibit = Sibit::FirstOf.new([Sibit::Fake.new])
41
+ assert_equal(64, sibit.latest.length)
42
+ assert_equal(12, sibit.fees[:S])
43
+ end
44
+
45
+ def test_two_apis
46
+ sibit = Sibit::FirstOf.new([Sibit::Fake.new, Sibit::Fake.new])
47
+ assert_equal(64, sibit.latest.length)
48
+ assert_equal(12, sibit.fees[:S])
49
+ end
50
+ end
@@ -27,6 +27,8 @@ require_relative '../lib/sibit'
27
27
  require_relative '../lib/sibit/earn'
28
28
  require_relative '../lib/sibit/fake'
29
29
  require_relative '../lib/sibit/blockchain'
30
+ require_relative '../lib/sibit/firstof'
31
+ require_relative '../lib/sibit/bestof'
30
32
 
31
33
  # Sibit.
32
34
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -127,7 +129,7 @@ class TestSibit < Minitest::Test
127
129
  'https://blockchain.info/unspent?active=1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi&limit=1000'
128
130
  ).to_return(body: JSON.pretty_generate(json))
129
131
  stub_request(:post, 'https://blockchain.info/pushtx').to_return(status: 200)
130
- sibit = Sibit.new(api: [Sibit::Earn.new, Sibit::Blockchain.new])
132
+ sibit = Sibit.new(api: Sibit::FirstOf.new([Sibit::Earn.new, Sibit::Blockchain.new]))
131
133
  target = sibit.create(sibit.generate)
132
134
  change = sibit.create(sibit.generate)
133
135
  tx = sibit.pay(
@@ -156,7 +158,7 @@ class TestSibit < Minitest::Test
156
158
  :get,
157
159
  'https://blockchain.info/unspent?active=1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi&limit=1000'
158
160
  ).to_return(body: JSON.pretty_generate(json))
159
- sibit = Sibit.new
161
+ sibit = Sibit.new(api: Sibit::BestOf.new([Sibit::Fake.new, Sibit::Fake.new]))
160
162
  target = sibit.create(sibit.generate)
161
163
  change = sibit.create(sibit.generate)
162
164
  assert_raises Sibit::Error do
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.18.5
4
+ version: 0.19.1
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-03-29 00:00:00.000000000 Z
11
+ date: 2020-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -281,6 +281,7 @@ files:
281
281
  - features/step_definitions/steps.rb
282
282
  - features/support/env.rb
283
283
  - lib/sibit.rb
284
+ - lib/sibit/bestof.rb
284
285
  - lib/sibit/bitcoinchain.rb
285
286
  - lib/sibit/blockchain.rb
286
287
  - lib/sibit/blockchair.rb
@@ -290,6 +291,7 @@ files:
290
291
  - lib/sibit/earn.rb
291
292
  - lib/sibit/error.rb
292
293
  - lib/sibit/fake.rb
294
+ - lib/sibit/firstof.rb
293
295
  - lib/sibit/http.rb
294
296
  - lib/sibit/json.rb
295
297
  - lib/sibit/log.rb
@@ -297,6 +299,7 @@ files:
297
299
  - logo.svg
298
300
  - sibit.gemspec
299
301
  - test/test__helper.rb
302
+ - test/test_bestof.rb
300
303
  - test/test_bitcoinchain.rb
301
304
  - test/test_blockchain.rb
302
305
  - test/test_blockchair.rb
@@ -304,6 +307,7 @@ files:
304
307
  - test/test_cex.rb
305
308
  - test/test_cryptoapis.rb
306
309
  - test/test_fake.rb
310
+ - test/test_firstof.rb
307
311
  - test/test_json.rb
308
312
  - test/test_live.rb
309
313
  - test/test_sibit.rb
@@ -337,6 +341,7 @@ test_files:
337
341
  - features/step_definitions/steps.rb
338
342
  - features/support/env.rb
339
343
  - test/test__helper.rb
344
+ - test/test_bestof.rb
340
345
  - test/test_bitcoinchain.rb
341
346
  - test/test_blockchain.rb
342
347
  - test/test_blockchair.rb
@@ -344,6 +349,7 @@ test_files:
344
349
  - test/test_cex.rb
345
350
  - test/test_cryptoapis.rb
346
351
  - test/test_fake.rb
352
+ - test/test_firstof.rb
347
353
  - test/test_json.rb
348
354
  - test/test_live.rb
349
355
  - test/test_sibit.rb