sibit 0.14.2 → 0.14.3

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: 80dd8e6fa8034a499c63c15f1333cf366800c85da969af2891b392cc7a09c6ac
4
- data.tar.gz: f8126179a4de258e575daf7dc04e9e21cd5bd31c214699573366b7ede67eacca
3
+ metadata.gz: e3746b345c4e7b36083c7a2377e4a5449532116978e38f964ac558046670fb5d
4
+ data.tar.gz: 480071555f2cc5e4b15a81274b526fb74a75c223d7b98a98226a134dd87e0e03
5
5
  SHA512:
6
- metadata.gz: 8ba3f4cd38f43af06f5399caf63be7e48cbcfa63192ceec6c42d892d92800863773e482cbc3a431ba4843042db85b970950d65bbc4c299cf0ec18fc81f2456ab
7
- data.tar.gz: b6a759fc3c29c1ca6d6cfad246501ca36abfc81f7ef4caebdcf0e77ed462e0a97328e61d3dfac23d47f56b7a5d6fc8e1ecc44e0cf3267eb86d5512c379fb03ee
6
+ metadata.gz: '097f3d44a66b8ef449e26429ec068bc8395258d80a2e0d5f520f9af24f5e0323d1f83f2f41e691d9daee570fb9527288c4b721ffdfa43762eafd1ef8c62d8095'
7
+ data.tar.gz: 8e9d7c89c01e6d537d159e16af0facdffbee6ea1ed4c16104a1c1fd33e4342b0a0a44bc7b3b5b2b5b45e11fa0fd222b4ac8e54aa4de6a75e416e4837540bc796
data/bin/sibit CHANGED
@@ -31,6 +31,7 @@ require_relative '../lib/sibit/version'
31
31
  require_relative '../lib/sibit/blockchain'
32
32
  require_relative '../lib/sibit/btc'
33
33
  require_relative '../lib/sibit/bitcoinchain'
34
+ require_relative '../lib/sibit/earn'
34
35
 
35
36
  begin
36
37
  begin
@@ -57,7 +58,11 @@ Options are:"
57
58
  exit
58
59
  end
59
60
  o.bool '--verbose', 'Print all possible debug messages'
60
- o.array '--api', 'Ordered List of APIs to use, e.g. "blockchain,btc"', default: ['blockchain']
61
+ o.array(
62
+ '--api',
63
+ 'Ordered List of APIs to use, e.g. "earn,blockchain,btc,bitcoinchain"',
64
+ default: %w[earn blockchain btc bitcoinchain]
65
+ )
61
66
  end
62
67
  rescue Slop::Error => ex
63
68
  raise ex.message
@@ -73,6 +78,8 @@ Options are:"
73
78
  api = Sibit::Btc.new(http: http, log: log, dry: opts[:dry])
74
79
  elsif a == 'bitcoinchain'
75
80
  api = Sibit::Bitcoinchain.new(http: http, log: log, dry: opts[:dry])
81
+ elsif a == 'earn'
82
+ api = Sibit::Earn.new(http: http, log: log, dry: opts[:dry])
76
83
  else
77
84
  raise Sibit::Error, "Unknown API \"#{a}\""
78
85
  end
@@ -60,11 +60,6 @@ class Sibit
60
60
  raise Sibit::Error, 'Not implemented yet'
61
61
  end
62
62
 
63
- # Sends a payment and returns the transaction hash.
64
- def pay(_amount, _fee, _sources, _target, _change)
65
- raise Sibit::Error, 'Not implemented yet'
66
- end
67
-
68
63
  # Gets the hash of the latest block.
69
64
  def latest
70
65
  Sibit::Json.new(http: @http, log: @log).get(
@@ -72,6 +67,16 @@ class Sibit
72
67
  )['hash']
73
68
  end
74
69
 
70
+ # Fetch all unspent outputs per address.
71
+ def utxos(_sources)
72
+ raise Sibit::Error, 'Not implemented yet'
73
+ end
74
+
75
+ # Push this transaction (in hex format) to the network.
76
+ def push(_hex)
77
+ raise Sibit::Error, 'Not implemented yet'
78
+ end
79
+
75
80
  # This method should fetch a Blockchain block and return as a hash. Raises
76
81
  # an exception if the block is not found.
77
82
  def block(hash)
@@ -67,85 +67,33 @@ class Sibit
67
67
  json['final_balance']
68
68
  end
69
69
 
70
- # Get recommended fees, in satoshi per byte. The method returns
71
- # a hash: { S: 12, M: 45, L: 100, XL: 200 }
70
+ # Get recommended fees.
72
71
  def fees
73
- json = Sibit::Json.new(http: @http, log: @log).get(
74
- URI('https://bitcoinfees.earn.com/api/v1/fees/recommended')
75
- )
76
- @log.info("Current recommended Bitcoin fees: \
77
- #{json['hourFee']}/#{json['halfHourFee']}/#{json['fastestFee']} sat/byte")
78
- {
79
- S: json['hourFee'] / 3,
80
- M: json['hourFee'],
81
- L: json['halfHourFee'],
82
- XL: json['fastestFee']
83
- }
72
+ raise Sibit::Error, 'fees() not implemented yet'
84
73
  end
85
74
 
86
- # Sends a payment and returns the transaction hash.
87
- def pay(amount, fee, sources, target, change)
88
- p = price('USD')
89
- satoshi = satoshi(amount)
90
- f = mfee(fee, size_of(amount, sources))
91
- satoshi += f if f.negative?
92
- raise Error, "The fee #{f.abs} covers the entire amount" if satoshi.zero?
93
- raise Error, "The fee #{f.abs} is bigger than the amount #{satoshi}" if satoshi.negative?
94
- builder = Bitcoin::Builder::TxBuilder.new
95
- unspent = 0
96
- size = 100
97
- utxos = Sibit::Json.new(http: @http, log: @log).get(
75
+ # Fetch all unspent outputs per address.
76
+ def utxos(sources)
77
+ Sibit::Json.new(http: @http, log: @log).get(
98
78
  URI("https://blockchain.info/unspent?active=#{sources.keys.join('|')}&limit=1000")
99
- )['unspent_outputs']
100
- @log.info("#{utxos.count} UTXOs found, these will be used \
101
- (value/confirmations at tx_hash):")
102
- utxos.each do |utxo|
103
- unspent += utxo['value']
104
- builder.input do |i|
105
- i.prev_out(utxo['tx_hash_big_endian'])
106
- i.prev_out_index(utxo['tx_output_n'])
107
- i.prev_out_script = [utxo['script']].pack('H*')
108
- address = Bitcoin::Script.new([utxo['script']].pack('H*')).get_address
109
- i.signature_key(key(sources[address]))
110
- end
111
- size += 180
112
- @log.info(
113
- " #{num(utxo['value'], p)}/#{utxo['confirmations']} at #{utxo['tx_hash_big_endian']}"
114
- )
115
- break if unspent > satoshi
79
+ )['unspent_outputs'].map do |u|
80
+ {
81
+ value: u['value'],
82
+ hash: u['tx_hash_big_endian'],
83
+ index: u['tx_output_n'],
84
+ confirmations: u['confirmations'],
85
+ script: [u['script']].pack('H*')
86
+ }
116
87
  end
117
- if unspent < satoshi
118
- raise Error, "Not enough funds to send #{num(satoshi, p)}, only #{num(unspent, p)} left"
119
- end
120
- builder.output(satoshi, target)
121
- f = mfee(fee, size)
122
- tx = builder.tx(
123
- input_value: unspent,
124
- leave_fee: true,
125
- extra_fee: [f, Bitcoin.network[:min_tx_fee]].max,
126
- change_address: change
88
+ end
89
+
90
+ # Push this transaction (in hex format) to the network.
91
+ def push(hex)
92
+ return if @dry
93
+ Sibit::Json.new(http: @http, log: @log).post(
94
+ URI('https://blockchain.info/pushtx'),
95
+ hex
127
96
  )
128
- left = unspent - tx.outputs.map(&:value).inject(&:+)
129
- @log.info("A new Bitcoin transaction #{tx.hash} prepared:
130
- #{tx.in.count} input#{tx.in.count > 1 ? 's' : ''}:
131
- #{tx.inputs.map { |i| " in: #{i.prev_out.bth}:#{i.prev_out_index}" }.join("\n ")}
132
- #{tx.out.count} output#{tx.out.count > 1 ? 's' : ''}:
133
- #{tx.outputs.map { |o| "out: #{o.script.bth} / #{num(o.value, p)}" }.join("\n ")}
134
- Min tx fee: #{num(Bitcoin.network[:min_tx_fee], p)}
135
- Fee requested: #{num(f, p)} as \"#{fee}\"
136
- Fee actually paid: #{num(left, p)}
137
- Tx size: #{size} bytes
138
- Unspent: #{num(unspent, p)}
139
- Amount: #{num(satoshi, p)}
140
- Target address: #{target}
141
- Change address is #{change}")
142
- unless @dry
143
- Sibit::Json.new(http: @http, log: @log).post(
144
- URI('https://blockchain.info/pushtx'),
145
- tx.to_payload.bth
146
- )
147
- end
148
- tx.hash
149
97
  end
150
98
 
151
99
  # Gets the hash of the latest block.
@@ -157,74 +105,7 @@ class Sibit
157
105
 
158
106
  # This method should fetch a Blockchain block and return as a hash.
159
107
  def block(_hash)
160
- raise Sibit::Error, 'Not implemented yet'
161
- end
162
-
163
- private
164
-
165
- def num(satoshi, usd)
166
- format(
167
- '%<satoshi>ss/$%<dollars>0.2f',
168
- satoshi: satoshi.to_s.gsub(/\d(?=(...)+$)/, '\0,'),
169
- dollars: satoshi * usd / 100_000_000
170
- )
171
- end
172
-
173
- # Convert text to amount.
174
- def satoshi(amount)
175
- return amount if amount.is_a?(Integer)
176
- raise Error, 'Amount should either be a String or Integer' unless amount.is_a?(String)
177
- return (amount.gsub(/BTC$/, '').to_f * 100_000_000).to_i if amount.end_with?('BTC')
178
- raise Error, "Can't understand the amount #{amount.inspect}"
179
- end
180
-
181
- # Calculates a fee in satoshi for the transaction of the specified size.
182
- # The +fee+ argument could be a number in satoshi, in which case it will
183
- # be returned as is, or a string like "XL" or "S", in which case the
184
- # fee will be calculated using the +size+ argument (which is the size
185
- # of the transaction in bytes).
186
- def mfee(fee, size)
187
- return fee.to_i if fee.is_a?(Integer)
188
- raise Error, 'Fee should either be a String or Integer' unless fee.is_a?(String)
189
- mul = 1
190
- if fee.start_with?('+', '-')
191
- mul = -1 if fee.start_with?('-')
192
- fee = fee[1..-1]
193
- end
194
- sat = fees[fee.to_sym]
195
- raise Error, "Can't understand the fee: #{fee.inspect}" if sat.nil?
196
- mul * sat * size
197
- end
198
-
199
- # Make key from private key string in Hash160.
200
- def key(hash160)
201
- key = Bitcoin::Key.new
202
- key.priv = hash160
203
- key
204
- end
205
-
206
- # Calculate an approximate size of the transaction.
207
- def size_of(amount, sources)
208
- satoshi = satoshi(amount)
209
- builder = Bitcoin::Builder::TxBuilder.new
210
- unspent = 0
211
- size = 100
212
- utxos = Sibit::Json.new(http: @http, log: @log).get(
213
- URI("https://blockchain.info/unspent?active=#{sources.keys.join('|')}&limit=1000")
214
- )['unspent_outputs']
215
- utxos.each do |utxo|
216
- unspent += utxo['value']
217
- builder.input do |i|
218
- i.prev_out(utxo['tx_hash_big_endian'])
219
- i.prev_out_index(utxo['tx_output_n'])
220
- i.prev_out_script = [utxo['script']].pack('H*')
221
- address = Bitcoin::Script.new([utxo['script']].pack('H*')).get_address
222
- i.signature_key(key(sources[address]))
223
- end
224
- size += 180
225
- break if unspent > satoshi
226
- end
227
- size
108
+ raise Sibit::Error, 'block() not implemented yet'
228
109
  end
229
110
  end
230
111
  end
data/lib/sibit/btc.rb CHANGED
@@ -68,11 +68,6 @@ class Sibit
68
68
  raise Sibit::Error, 'Not implemented yet'
69
69
  end
70
70
 
71
- # Sends a payment and returns the transaction hash.
72
- def pay(_amount, _fee, _sources, _target, _change)
73
- raise Sibit::Error, 'Not implemented yet'
74
- end
75
-
76
71
  # Gets the hash of the latest block.
77
72
  def latest
78
73
  uri = URI('https://chain.api.btc.com/v3/block/latest')
@@ -82,6 +77,16 @@ class Sibit
82
77
  hash
83
78
  end
84
79
 
80
+ # Fetch all unspent outputs per address.
81
+ def utxos(_sources)
82
+ raise Sibit::Error, 'Not implemented yet'
83
+ end
84
+
85
+ # Push this transaction (in hex format) to the network.
86
+ def push(_hex)
87
+ raise Sibit::Error, 'Not implemented yet'
88
+ end
89
+
85
90
  # This method should fetch a Blockchain block and return as a hash.
86
91
  def block(hash)
87
92
  head = Sibit::Json.new(http: @http, log: @log).get(
data/lib/sibit/earn.rb ADDED
@@ -0,0 +1,91 @@
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 'json'
24
+ require 'uri'
25
+ require_relative 'version'
26
+ require_relative 'error'
27
+ require_relative 'http'
28
+ require_relative 'json'
29
+
30
+ # Earn.com API.
31
+ #
32
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
33
+ # Copyright:: Copyright (c) 2019-2020 Yegor Bugayenko
34
+ # License:: MIT
35
+ class Sibit
36
+ # Blockchain.info API.
37
+ class Earn
38
+ # Constructor.
39
+ def initialize(log: Sibit::Log.new, http: Sibit::Http.new, dry: false)
40
+ @http = http
41
+ @log = log
42
+ @dry = dry
43
+ end
44
+
45
+ # Current price of BTC in USD (float returned).
46
+ def price(_currency)
47
+ raise Sibit::Error, 'price() doesn\'t work here'
48
+ end
49
+
50
+ # Gets the balance of the address, in satoshi.
51
+ def balance(_address)
52
+ raise Sibit::Error, 'balance() doesn\'t work here'
53
+ end
54
+
55
+ # Get recommended fees, in satoshi per byte. The method returns
56
+ # a hash: { S: 12, M: 45, L: 100, XL: 200 }
57
+ def fees
58
+ json = Sibit::Json.new(http: @http, log: @log).get(
59
+ URI('https://bitcoinfees.earn.com/api/v1/fees/recommended')
60
+ )
61
+ @log.info("Current recommended Bitcoin fees: \
62
+ #{json['hourFee']}/#{json['halfHourFee']}/#{json['fastestFee']} sat/byte")
63
+ {
64
+ S: json['hourFee'] / 3,
65
+ M: json['hourFee'],
66
+ L: json['halfHourFee'],
67
+ XL: json['fastestFee']
68
+ }
69
+ end
70
+
71
+ # Fetch all unspent outputs per address.
72
+ def utxos(_sources)
73
+ raise Sibit::Error, 'Not implemented yet'
74
+ end
75
+
76
+ # Push this transaction (in hex format) to the network.
77
+ def push(_hex)
78
+ raise Sibit::Error, 'Not implemented yet'
79
+ end
80
+
81
+ # Gets the hash of the latest block.
82
+ def latest
83
+ raise Sibit::Error, 'latest() doesn\'t work here'
84
+ end
85
+
86
+ # This method should fetch a Blockchain block and return as a hash.
87
+ def block(_hash)
88
+ raise Sibit::Error, 'block() doesn\'t work here'
89
+ end
90
+ end
91
+ end
data/lib/sibit/fake.rb CHANGED
@@ -42,8 +42,12 @@ class Sibit
42
42
  100_000_000
43
43
  end
44
44
 
45
- def pay(_amount, _fee, _sources, _target, _change)
46
- '9dfe55a30b5ee732005158c589179a398117117a68d21531fb6c78b85b544c54'
45
+ def utxos(_sources)
46
+ []
47
+ end
48
+
49
+ def push(hex)
50
+ # Nothing to do here
47
51
  end
48
52
 
49
53
  def latest
data/lib/sibit/version.rb CHANGED
@@ -26,5 +26,5 @@
26
26
  # License:: MIT
27
27
  class Sibit
28
28
  # Current version of the library.
29
- VERSION = '0.14.2'
29
+ VERSION = '0.14.3'
30
30
  end
data/lib/sibit.rb CHANGED
@@ -105,9 +105,61 @@ class Sibit
105
105
  # +target+: the target address to send to
106
106
  # +change+: the address where the change has to be sent to
107
107
  def pay(amount, fee, sources, target, change)
108
+ p = price('USD')
109
+ satoshi = satoshi(amount)
110
+ builder = Bitcoin::Builder::TxBuilder.new
111
+ unspent = 0
112
+ size = 100
113
+ utxos = first_one { |api| api.utxos(sources) }
114
+ @log.info("#{utxos.count} UTXOs found, these will be used \
115
+ (value/confirmations at tx_hash):")
116
+ utxos.each do |utxo|
117
+ unspent += utxo[:value]
118
+ builder.input do |i|
119
+ i.prev_out(utxo[:hash])
120
+ i.prev_out_index(utxo[:index])
121
+ i.prev_out_script = utxo[:script]
122
+ address = Bitcoin::Script.new(utxo[:script]).get_address
123
+ i.signature_key(key(sources[address]))
124
+ end
125
+ size += 180
126
+ @log.info(
127
+ " #{num(utxo[:value], p)}/#{utxo[:confirmations]} at #{utxo[:hash]}"
128
+ )
129
+ break if unspent > satoshi
130
+ end
131
+ if unspent < satoshi
132
+ raise Error, "Not enough funds to send #{num(satoshi, p)}, only #{num(unspent, p)} left"
133
+ end
134
+ builder.output(satoshi, target)
135
+ f = mfee(fee, size)
136
+ satoshi += f if f.negative?
137
+ raise Error, "The fee #{f.abs} covers the entire amount" if satoshi.zero?
138
+ raise Error, "The fee #{f.abs} is bigger than the amount #{satoshi}" if satoshi.negative?
139
+ tx = builder.tx(
140
+ input_value: unspent,
141
+ leave_fee: true,
142
+ extra_fee: [f, Bitcoin.network[:min_tx_fee]].max,
143
+ change_address: change
144
+ )
145
+ left = unspent - tx.outputs.map(&:value).inject(&:+)
146
+ @log.info("A new Bitcoin transaction #{tx.hash} prepared:
147
+ #{tx.in.count} input#{tx.in.count > 1 ? 's' : ''}:
148
+ #{tx.inputs.map { |i| " in: #{i.prev_out.bth}:#{i.prev_out_index}" }.join("\n ")}
149
+ #{tx.out.count} output#{tx.out.count > 1 ? 's' : ''}:
150
+ #{tx.outputs.map { |o| "out: #{o.script.bth} / #{num(o.value, p)}" }.join("\n ")}
151
+ Min tx fee: #{num(Bitcoin.network[:min_tx_fee], p)}
152
+ Fee requested: #{num(f, p)} as \"#{fee}\"
153
+ Fee actually paid: #{num(left, p)}
154
+ Tx size: #{size} bytes
155
+ Unspent: #{num(unspent, p)}
156
+ Amount: #{num(satoshi, p)}
157
+ Target address: #{target}
158
+ Change address is #{change}")
108
159
  first_one do |api|
109
- api.pay(amount, fee, sources, target, change)
160
+ api.push(tx.to_payload.bth)
110
161
  end
162
+ tx.hash
111
163
  end
112
164
 
113
165
  # Gets the hash of the latest block.
@@ -186,7 +238,51 @@ class Sibit
186
238
  @log.info("The API #{api.class.name} failed: #{e.message}")
187
239
  end
188
240
  end
189
- raise Sibit::Error, 'No APIs managed to succeed' unless done
241
+ unless done
242
+ raise Sibit::Error, "No APIs out of #{@api.length} managed to succeed: \
243
+ #{@api.map { |a| a.class.name }.join(', ')}"
244
+ end
190
245
  result
191
246
  end
247
+
248
+ def num(satoshi, usd)
249
+ format(
250
+ '%<satoshi>ss/$%<dollars>0.2f',
251
+ satoshi: satoshi.to_s.gsub(/\d(?=(...)+$)/, '\0,'),
252
+ dollars: satoshi * usd / 100_000_000
253
+ )
254
+ end
255
+
256
+ # Convert text to amount.
257
+ def satoshi(amount)
258
+ return amount if amount.is_a?(Integer)
259
+ raise Error, 'Amount should either be a String or Integer' unless amount.is_a?(String)
260
+ return (amount.gsub(/BTC$/, '').to_f * 100_000_000).to_i if amount.end_with?('BTC')
261
+ raise Error, "Can't understand the amount #{amount.inspect}"
262
+ end
263
+
264
+ # Calculates a fee in satoshi for the transaction of the specified size.
265
+ # The +fee+ argument could be a number in satoshi, in which case it will
266
+ # be returned as is, or a string like "XL" or "S", in which case the
267
+ # fee will be calculated using the +size+ argument (which is the size
268
+ # of the transaction in bytes).
269
+ def mfee(fee, size)
270
+ return fee.to_i if fee.is_a?(Integer)
271
+ raise Error, 'Fee should either be a String or Integer' unless fee.is_a?(String)
272
+ mul = 1
273
+ if fee.start_with?('+', '-')
274
+ mul = -1 if fee.start_with?('-')
275
+ fee = fee[1..-1]
276
+ end
277
+ sat = fees[fee.to_sym]
278
+ raise Error, "Can't understand the fee: #{fee.inspect}" if sat.nil?
279
+ mul * sat * size
280
+ end
281
+
282
+ # Make key from private key string in Hash160.
283
+ def key(hash160)
284
+ key = Bitcoin::Key.new
285
+ key.priv = hash160
286
+ key
287
+ end
192
288
  end
data/test/test_fake.rb CHANGED
@@ -35,10 +35,7 @@ class TestFake < Minitest::Test
35
35
  assert_equal(4_000, sibit.price)
36
36
  assert_equal(12, sibit.fees[:S])
37
37
  assert_equal(100_000_000, sibit.balance(''))
38
- assert_equal(
39
- '9dfe55a30b5ee732005158c589179a398117117a68d21531fb6c78b85b544c54',
40
- sibit.pay(0, 'M', {}, '', '')
41
- )
38
+ assert_equal([], sibit.utxos(nil))
42
39
  assert_equal('00000000000000000008df8a6e1b61d1136803ac9791b8725235c9f780b4ed71', sibit.latest)
43
40
  end
44
41
 
data/test/test_sibit.rb CHANGED
@@ -24,6 +24,9 @@ require 'minitest/autorun'
24
24
  require 'webmock/minitest'
25
25
  require 'json'
26
26
  require_relative '../lib/sibit'
27
+ require_relative '../lib/sibit/earn'
28
+ require_relative '../lib/sibit/fake'
29
+ require_relative '../lib/sibit/blockchain'
27
30
 
28
31
  # Sibit.
29
32
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -34,7 +37,7 @@ class TestSibit < Minitest::Test
34
37
  stub_request(
35
38
  :get, 'https://bitcoinfees.earn.com/api/v1/fees/recommended'
36
39
  ).to_return(body: '{"fastestFee":300,"halfHourFee":200,"hourFee":180}')
37
- sibit = Sibit.new
40
+ sibit = Sibit.new(api: Sibit::Earn.new)
38
41
  fees = sibit.fees
39
42
  assert_equal(60, fees[:S])
40
43
  assert_equal(180, fees[:M])
@@ -124,7 +127,7 @@ class TestSibit < Minitest::Test
124
127
  'https://blockchain.info/unspent?active=1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi&limit=1000'
125
128
  ).to_return(body: JSON.pretty_generate(json))
126
129
  stub_request(:post, 'https://blockchain.info/pushtx').to_return(status: 200)
127
- sibit = Sibit.new
130
+ sibit = Sibit.new(api: [Sibit::Earn.new, Sibit::Blockchain.new])
128
131
  target = sibit.create(sibit.generate)
129
132
  change = sibit.create(sibit.generate)
130
133
  tx = sibit.pay(
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sibit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.2
4
+ version: 0.14.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
@@ -284,6 +284,7 @@ files:
284
284
  - lib/sibit/bitcoinchain.rb
285
285
  - lib/sibit/blockchain.rb
286
286
  - lib/sibit/btc.rb
287
+ - lib/sibit/earn.rb
287
288
  - lib/sibit/error.rb
288
289
  - lib/sibit/fake.rb
289
290
  - lib/sibit/http.rb