sibit 0.18.7 → 0.19.3
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/.rubocop.yml +2 -0
- data/.rultor.yml +2 -2
- data/README.md +9 -2
- data/bin/sibit +2 -1
- data/lib/sibit.rb +11 -41
- data/lib/sibit/bestof.rb +119 -0
- data/lib/sibit/blockchair.rb +1 -1
- data/lib/sibit/btc.rb +6 -1
- data/lib/sibit/firstof.rb +122 -0
- data/lib/sibit/version.rb +1 -1
- data/test/test_bestof.rb +62 -0
- data/test/test_btc.rb +11 -0
- data/test/test_firstof.rb +62 -0
- data/test/test_sibit.rb +4 -2
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1954a732f204708506dbbba992e87c8e1e49f111cbfb822d493214e031b06ee2
|
|
4
|
+
data.tar.gz: 6cd88b88f880045ce63597644280d6d27df2ee0249189c13abdbcdda8ed00203
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6d301e854ae0915e62bd6d9903f7ed2e5ef37b6e68f1a7b94d813ca9c5d4c0f0f8a590019a3cdc8f15b7aeb6ffa9eeb391e5da17af8e1518be22bf2c3cdde68a
|
|
7
|
+
data.tar.gz: 9772fc2ec4c8f445bad36b6c7403ed97dff4a050b79609bf8cefc083c69358b319e4cc5a6c8020e51aae739177fa931b3a83e14d3ae0b3ebec75d3037c7c3b3f
|
data/.rubocop.yml
CHANGED
data/.rultor.yml
CHANGED
|
@@ -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/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(
|
|
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
|
data/lib/sibit.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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',
|
data/lib/sibit/bestof.rb
ADDED
|
@@ -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 #{@list.length} managed to succeed at #{method}(): \
|
|
114
|
+
#{@list.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
|
data/lib/sibit/blockchair.rb
CHANGED
data/lib/sibit/btc.rb
CHANGED
|
@@ -58,7 +58,12 @@ class Sibit
|
|
|
58
58
|
@log.info("The balance of #{address} is zero (not found)")
|
|
59
59
|
return 0
|
|
60
60
|
end
|
|
61
|
-
|
|
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']
|
|
62
67
|
balance = txns.map { |tx| tx['value'] }.inject(&:+) || 0
|
|
63
68
|
@log.info("The balance of #{address} is #{balance}, total txns: #{txns.count}")
|
|
64
69
|
balance
|
|
@@ -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 #{@list.length} managed to succeed at #{method}(): \
|
|
117
|
+
#{@list.map { |a| a.class.name }.join(', ')}"
|
|
118
|
+
end
|
|
119
|
+
result
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
data/lib/sibit/version.rb
CHANGED
data/test/test_bestof.rb
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
|
|
51
|
+
def test_all_fail
|
|
52
|
+
api = Class.new do
|
|
53
|
+
def latest
|
|
54
|
+
raise Sibit::Error, 'intentionally'
|
|
55
|
+
end
|
|
56
|
+
end.new
|
|
57
|
+
sibit = Sibit::BestOf.new([api, api])
|
|
58
|
+
assert_raises Sibit::Error do
|
|
59
|
+
sibit.latest
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
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_broken_balance
|
|
46
|
+
stub_request(
|
|
47
|
+
:get,
|
|
48
|
+
'https://chain.api.btc.com/v3/address/1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f/unspent'
|
|
49
|
+
).to_return(body: '{}')
|
|
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_empty_balance
|
|
46
57
|
stub_request(
|
|
47
58
|
:get,
|
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
|
|
51
|
+
def test_all_fail
|
|
52
|
+
api = Class.new do
|
|
53
|
+
def latest
|
|
54
|
+
raise Sibit::Error, 'intentionally'
|
|
55
|
+
end
|
|
56
|
+
end.new
|
|
57
|
+
sibit = Sibit::FirstOf.new([api, api])
|
|
58
|
+
assert_raises Sibit::Error do
|
|
59
|
+
sibit.latest
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
data/test/test_sibit.rb
CHANGED
|
@@ -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.
|
|
4
|
+
version: 0.19.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-07-09 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
|