sibit 0.20.3 → 0.21.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 +3 -2
- data/.simplecov +7 -5
- data/Gemfile +1 -1
- data/bin/sibit +16 -15
- data/lib/sibit.rb +1 -1
- data/lib/sibit/bestof.rb +7 -5
- data/lib/sibit/bitcoinchain.rb +9 -8
- data/lib/sibit/blockchain.rb +20 -9
- data/lib/sibit/blockchair.rb +7 -6
- data/lib/sibit/btc.rb +14 -12
- data/lib/sibit/cex.rb +1 -1
- data/lib/sibit/cryptoapis.rb +12 -15
- data/lib/sibit/earn.rb +3 -2
- data/lib/sibit/firstof.rb +4 -0
- data/lib/sibit/json.rb +4 -2
- data/lib/sibit/log.rb +1 -1
- data/lib/sibit/version.rb +1 -1
- data/sibit.gemspec +12 -13
- data/test/test__helper.rb +1 -1
- data/test/test_blockchain.rb +11 -1
- data/test/test_live.rb +4 -6
- metadata +33 -47
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c72b1319eee0a3b3dc8370b7dd1447109cfd96d86754b5a3aa3444986fb8f9e7
|
|
4
|
+
data.tar.gz: 7694b4e1284ac6d656b0794c7e58e5ed4d8be6eabd62e126608395f355986635
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 60c20d72c1b6b6c37c785bb3c0252d5cf37ed9f55892e51ff8675c17ee8870d5f968dbeeb150efb10b959f7f3dc419a56e7f3a31531b76a4216b62654aea6323
|
|
7
|
+
data.tar.gz: 7da7246776833039f185b63c2829f387f4fa20f506ba5085d1746e31814d470a3064caf6928b125a2ec9d34226297a2cd6e50d2fd53cb898498cc022f4deec6c
|
data/.rubocop.yml
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
AllCops:
|
|
2
|
+
NewCops: enable
|
|
2
3
|
Exclude:
|
|
3
4
|
- 'assets/**/*'
|
|
4
5
|
DisplayCopNames: true
|
|
5
|
-
TargetRubyVersion: 2.
|
|
6
|
+
TargetRubyVersion: 2.5
|
|
6
7
|
|
|
7
8
|
Style/ClassAndModuleChildren:
|
|
8
9
|
Enabled: false
|
|
9
|
-
|
|
10
|
+
Layout/LineLength:
|
|
10
11
|
Max: 100
|
|
11
12
|
Layout/EndOfLine:
|
|
12
13
|
EnforcedStyle: lf
|
data/.simplecov
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Copyright (c) 2019-2020 Yegor Bugayenko
|
|
2
4
|
#
|
|
3
5
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
@@ -18,21 +20,21 @@
|
|
|
18
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
21
|
# SOFTWARE.
|
|
20
22
|
|
|
21
|
-
if Gem.win_platform?
|
|
23
|
+
if Gem.win_platform?
|
|
22
24
|
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
|
23
25
|
SimpleCov::Formatter::HTMLFormatter
|
|
24
26
|
]
|
|
25
27
|
SimpleCov.start do
|
|
26
|
-
add_filter
|
|
27
|
-
add_filter
|
|
28
|
+
add_filter '/test/'
|
|
29
|
+
add_filter '/features/'
|
|
28
30
|
end
|
|
29
31
|
else
|
|
30
32
|
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
|
31
33
|
[SimpleCov::Formatter::HTMLFormatter]
|
|
32
34
|
)
|
|
33
35
|
SimpleCov.start do
|
|
34
|
-
add_filter
|
|
35
|
-
add_filter
|
|
36
|
+
add_filter '/test/'
|
|
37
|
+
add_filter '/features/'
|
|
36
38
|
minimum_coverage 60
|
|
37
39
|
end
|
|
38
40
|
end
|
data/Gemfile
CHANGED
data/bin/sibit
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
# SOFTWARE.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
$stdout.sync = true
|
|
25
25
|
|
|
26
26
|
require 'slop'
|
|
27
27
|
require 'backtrace'
|
|
@@ -68,27 +68,28 @@ Options are:"
|
|
|
68
68
|
default: %w[earn blockchain btc bitcoinchain blockchair cex]
|
|
69
69
|
)
|
|
70
70
|
end
|
|
71
|
-
rescue Slop::Error =>
|
|
72
|
-
raise
|
|
71
|
+
rescue Slop::Error => e
|
|
72
|
+
raise e.message
|
|
73
73
|
end
|
|
74
74
|
raise 'Try --help' if opts.arguments.empty?
|
|
75
|
-
log = Sibit::Log.new(opts[:verbose] ?
|
|
75
|
+
log = Sibit::Log.new(opts[:verbose] ? $stdout : nil)
|
|
76
76
|
http = opts[:proxy] ? Sibit::HttpProxy.new(opts[:proxy]) : Sibit::Http.new
|
|
77
77
|
apis = opts[:api].map(&:downcase).map do |a|
|
|
78
78
|
api = nil
|
|
79
|
-
|
|
79
|
+
case a
|
|
80
|
+
when 'blockchain'
|
|
80
81
|
api = Sibit::Blockchain.new(http: http, log: log, dry: opts[:dry])
|
|
81
|
-
|
|
82
|
+
when 'btc'
|
|
82
83
|
api = Sibit::Btc.new(http: http, log: log, dry: opts[:dry])
|
|
83
|
-
|
|
84
|
+
when 'bitcoinchain'
|
|
84
85
|
api = Sibit::Bitcoinchain.new(http: http, log: log, dry: opts[:dry])
|
|
85
|
-
|
|
86
|
+
when 'blockchair'
|
|
86
87
|
api = Sibit::Blockchair.new(http: http, log: log, dry: opts[:dry])
|
|
87
|
-
|
|
88
|
+
when 'cex'
|
|
88
89
|
api = Sibit::Cex.new(http: http, log: log, dry: opts[:dry])
|
|
89
|
-
|
|
90
|
+
when 'fake'
|
|
90
91
|
api = Sibit::Fake.new
|
|
91
|
-
|
|
92
|
+
when 'earn'
|
|
92
93
|
api = Sibit::Earn.new(http: http, log: log, dry: opts[:dry])
|
|
93
94
|
else
|
|
94
95
|
raise Sibit::Error, "Unknown API \"#{a}\""
|
|
@@ -105,7 +106,7 @@ Options are:"
|
|
|
105
106
|
text = %i[S M L XL].map do |m|
|
|
106
107
|
sat = fees[m] * 250
|
|
107
108
|
usd = sat * sibit.price / 100_000_000
|
|
108
|
-
"#{m}: #{sat}sat / $#{format('
|
|
109
|
+
"#{m}: #{sat}sat / $#{format('%<usd>.02f', usd: usd)}"
|
|
109
110
|
end.join("\n")
|
|
110
111
|
puts text
|
|
111
112
|
when 'latest'
|
|
@@ -141,11 +142,11 @@ Options are:"
|
|
|
141
142
|
else
|
|
142
143
|
raise "Command #{opts.arguments[0]} is not supported"
|
|
143
144
|
end
|
|
144
|
-
rescue StandardError =>
|
|
145
|
+
rescue StandardError => e
|
|
145
146
|
if opts[:verbose]
|
|
146
|
-
puts Backtrace.new(
|
|
147
|
+
puts Backtrace.new(e).to_s
|
|
147
148
|
else
|
|
148
|
-
puts "ERROR: #{
|
|
149
|
+
puts "ERROR: #{e.message}"
|
|
149
150
|
end
|
|
150
151
|
exit(255)
|
|
151
152
|
end
|
data/lib/sibit.rb
CHANGED
|
@@ -48,7 +48,7 @@ class Sibit
|
|
|
48
48
|
# The +api+ argument can be an object or an array of objects. If an array
|
|
49
49
|
# is provided, we will make an attempt to try them one by one, until
|
|
50
50
|
# one of them succeedes.
|
|
51
|
-
def initialize(log:
|
|
51
|
+
def initialize(log: $stdout, api: Sibit::Blockchain.new(log: Sibit::Log.new(log)))
|
|
52
52
|
@log = Sibit::Log.new(log)
|
|
53
53
|
@api = api
|
|
54
54
|
end
|
data/lib/sibit/bestof.rb
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
+
require 'backtrace'
|
|
23
24
|
require_relative 'error'
|
|
24
25
|
require_relative 'log'
|
|
25
26
|
|
|
@@ -103,14 +104,15 @@ class Sibit
|
|
|
103
104
|
def best_of(method)
|
|
104
105
|
return yield @list unless @list.is_a?(Array)
|
|
105
106
|
results = []
|
|
107
|
+
errors = []
|
|
106
108
|
@list.each do |api|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
end
|
|
109
|
+
results << yield(api)
|
|
110
|
+
rescue Sibit::Error => e
|
|
111
|
+
errors << e
|
|
112
|
+
@log.info("The API #{api.class.name} failed at #{method}(): #{e.message}") if @verbose
|
|
112
113
|
end
|
|
113
114
|
if results.empty?
|
|
115
|
+
errors.each { |e| @log.info(Backtrace.new(e).to_s) }
|
|
114
116
|
raise Sibit::Error, "No APIs out of #{@list.length} managed to succeed at #{method}(): \
|
|
115
117
|
#{@list.map { |a| a.class.name }.join(', ')}"
|
|
116
118
|
end
|
data/lib/sibit/bitcoinchain.rb
CHANGED
|
@@ -20,13 +20,14 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
-
require '
|
|
23
|
+
require 'iri'
|
|
24
24
|
require 'json'
|
|
25
|
-
|
|
25
|
+
require 'uri'
|
|
26
26
|
require_relative 'error'
|
|
27
|
-
require_relative 'log'
|
|
28
27
|
require_relative 'http'
|
|
29
28
|
require_relative 'json'
|
|
29
|
+
require_relative 'log'
|
|
30
|
+
require_relative 'version'
|
|
30
31
|
|
|
31
32
|
# Bitcoinchain.com API.
|
|
32
33
|
#
|
|
@@ -56,7 +57,7 @@ class Sibit
|
|
|
56
57
|
# Get hash of the block after this one.
|
|
57
58
|
def next_of(hash)
|
|
58
59
|
block = Sibit::Json.new(http: @http, log: @log).get(
|
|
59
|
-
|
|
60
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/block').append(hash)
|
|
60
61
|
)[0]
|
|
61
62
|
raise Sibit::Error, "Block #{hash} not found" if block.nil?
|
|
62
63
|
nxt = block['next_block']
|
|
@@ -69,7 +70,7 @@ class Sibit
|
|
|
69
70
|
# Gets the balance of the address, in satoshi.
|
|
70
71
|
def balance(address)
|
|
71
72
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
72
|
-
|
|
73
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/address').append(address),
|
|
73
74
|
accept: [200, 409]
|
|
74
75
|
)[0]
|
|
75
76
|
b = json['balance']
|
|
@@ -91,7 +92,7 @@ class Sibit
|
|
|
91
92
|
# Gets the hash of the latest block.
|
|
92
93
|
def latest
|
|
93
94
|
hash = Sibit::Json.new(http: @http, log: @log).get(
|
|
94
|
-
|
|
95
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/status')
|
|
95
96
|
)['hash']
|
|
96
97
|
@log.info("The latest block hash is #{hash}")
|
|
97
98
|
hash
|
|
@@ -111,11 +112,11 @@ class Sibit
|
|
|
111
112
|
# an exception if the block is not found.
|
|
112
113
|
def block(hash)
|
|
113
114
|
head = Sibit::Json.new(http: @http, log: @log).get(
|
|
114
|
-
|
|
115
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/block').append(hash)
|
|
115
116
|
)[0]
|
|
116
117
|
raise Sibit::Error, "The block #{hash} is not found" if head.nil?
|
|
117
118
|
txs = Sibit::Json.new(http: @http, log: @log).get(
|
|
118
|
-
|
|
119
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/block/txs').append(hash)
|
|
119
120
|
)
|
|
120
121
|
nxt = head['next_block']
|
|
121
122
|
nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
|
data/lib/sibit/blockchain.rb
CHANGED
|
@@ -21,12 +21,13 @@
|
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
23
|
require 'bitcoin'
|
|
24
|
+
require 'iri'
|
|
24
25
|
require 'json'
|
|
25
26
|
require 'uri'
|
|
26
|
-
require_relative 'version'
|
|
27
27
|
require_relative 'error'
|
|
28
28
|
require_relative 'http'
|
|
29
29
|
require_relative 'json'
|
|
30
|
+
require_relative 'version'
|
|
30
31
|
|
|
31
32
|
# Blockchain.info API.
|
|
32
33
|
#
|
|
@@ -49,7 +50,7 @@ class Sibit
|
|
|
49
50
|
# Current price of BTC in USD (float returned).
|
|
50
51
|
def price(currency = 'USD')
|
|
51
52
|
h = Sibit::Json.new(http: @http, log: @log).get(
|
|
52
|
-
|
|
53
|
+
Iri.new('https://blockchain.info/ticker')
|
|
53
54
|
)[currency]
|
|
54
55
|
raise Error, "Unrecognized currency #{currency}" if h.nil?
|
|
55
56
|
price = h['15m']
|
|
@@ -59,13 +60,23 @@ class Sibit
|
|
|
59
60
|
|
|
60
61
|
# Get hash of the block after this one.
|
|
61
62
|
def next_of(_hash)
|
|
62
|
-
raise Sibit::NotSupportedError, 'Blockchain API
|
|
63
|
+
raise Sibit::NotSupportedError, 'next_of() in Blockchain API is broken, always returns NULL'
|
|
64
|
+
# json = Sibit::Json.new(http: @http, log: @log).get(
|
|
65
|
+
# Iri.new('https://blockchain.info/rawblock').append(hash)
|
|
66
|
+
# )
|
|
67
|
+
# nxt = json['next_block'][0]
|
|
68
|
+
# if nxt.nil?
|
|
69
|
+
# @log.info("There is no block after #{hash}")
|
|
70
|
+
# else
|
|
71
|
+
# @log.info("The next block of #{hash} is #{nxt}")
|
|
72
|
+
# end
|
|
73
|
+
# nxt
|
|
63
74
|
end
|
|
64
75
|
|
|
65
76
|
# The height of the block.
|
|
66
77
|
def height(hash)
|
|
67
78
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
68
|
-
|
|
79
|
+
Iri.new('https://blockchain.info/rawblock').append(hash)
|
|
69
80
|
)
|
|
70
81
|
h = json['height']
|
|
71
82
|
@log.info("The height of #{hash} is #{h}")
|
|
@@ -75,7 +86,7 @@ class Sibit
|
|
|
75
86
|
# Gets the balance of the address, in satoshi.
|
|
76
87
|
def balance(address)
|
|
77
88
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
78
|
-
|
|
89
|
+
Iri.new('https://blockchain.info/rawaddr').append(address).add(limit: 0),
|
|
79
90
|
accept: [200, 500]
|
|
80
91
|
)
|
|
81
92
|
b = json['final_balance']
|
|
@@ -92,7 +103,7 @@ class Sibit
|
|
|
92
103
|
# of Bitcoin addresses.
|
|
93
104
|
def utxos(sources)
|
|
94
105
|
Sibit::Json.new(http: @http, log: @log).get(
|
|
95
|
-
|
|
106
|
+
Iri.new('https://blockchain.info/unspent').add(active: sources.join('|'), limit: 1000)
|
|
96
107
|
)['unspent_outputs'].map do |u|
|
|
97
108
|
{
|
|
98
109
|
value: u['value'],
|
|
@@ -108,7 +119,7 @@ class Sibit
|
|
|
108
119
|
def push(hex)
|
|
109
120
|
return if @dry
|
|
110
121
|
Sibit::Json.new(http: @http, log: @log).post(
|
|
111
|
-
|
|
122
|
+
Iri.new('https://blockchain.info/pushtx'),
|
|
112
123
|
hex
|
|
113
124
|
)
|
|
114
125
|
end
|
|
@@ -116,7 +127,7 @@ class Sibit
|
|
|
116
127
|
# Gets the hash of the latest block.
|
|
117
128
|
def latest
|
|
118
129
|
hash = Sibit::Json.new(http: @http, log: @log).get(
|
|
119
|
-
|
|
130
|
+
Iri.new('https://blockchain.info/latestblock')
|
|
120
131
|
)['hash']
|
|
121
132
|
@log.info("The latest block hash is #{hash}")
|
|
122
133
|
hash
|
|
@@ -125,7 +136,7 @@ class Sibit
|
|
|
125
136
|
# This method should fetch a Blockchain block and return as a hash.
|
|
126
137
|
def block(hash)
|
|
127
138
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
128
|
-
|
|
139
|
+
Iri.new('https://blockchain.info/rawblock').append(hash)
|
|
129
140
|
)
|
|
130
141
|
{
|
|
131
142
|
hash: json['hash'],
|
data/lib/sibit/blockchair.rb
CHANGED
|
@@ -20,14 +20,15 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
-
require 'uri'
|
|
24
|
-
require 'json'
|
|
25
23
|
require 'cgi'
|
|
26
|
-
|
|
24
|
+
require 'iri'
|
|
25
|
+
require 'json'
|
|
26
|
+
require 'uri'
|
|
27
27
|
require_relative 'error'
|
|
28
|
-
require_relative 'log'
|
|
29
28
|
require_relative 'http'
|
|
30
29
|
require_relative 'json'
|
|
30
|
+
require_relative 'log'
|
|
31
|
+
require_relative 'version'
|
|
31
32
|
|
|
32
33
|
# Blockchair.com API.
|
|
33
34
|
#
|
|
@@ -64,7 +65,7 @@ class Sibit
|
|
|
64
65
|
# Gets the balance of the address, in satoshi.
|
|
65
66
|
def balance(address)
|
|
66
67
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
67
|
-
|
|
68
|
+
Iri.new('https://api.blockchair.com/bitcoin/dashboards/address').append(address).fragment(the_key)
|
|
68
69
|
)['data'][address]
|
|
69
70
|
if json.nil?
|
|
70
71
|
@log.info("Address #{address} not found")
|
|
@@ -94,7 +95,7 @@ class Sibit
|
|
|
94
95
|
# Push this transaction (in hex format) to the network.
|
|
95
96
|
def push(hex)
|
|
96
97
|
Sibit::Json.new(http: @http, log: @log).post(
|
|
97
|
-
|
|
98
|
+
Iri.new('https://api.blockchair.com/bitcoin/push/transaction').fragment(the_key),
|
|
98
99
|
"data=#{hex}"
|
|
99
100
|
)
|
|
100
101
|
@log.info("Transaction (#{hex.length} in hex) has been pushed to Blockchair")
|
data/lib/sibit/btc.rb
CHANGED
|
@@ -20,13 +20,14 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
-
require '
|
|
23
|
+
require 'iri'
|
|
24
24
|
require 'json'
|
|
25
|
-
|
|
25
|
+
require 'uri'
|
|
26
26
|
require_relative 'error'
|
|
27
|
-
require_relative 'log'
|
|
28
27
|
require_relative 'http'
|
|
29
28
|
require_relative 'json'
|
|
29
|
+
require_relative 'log'
|
|
30
|
+
require_relative 'version'
|
|
30
31
|
|
|
31
32
|
# Btc.com API.
|
|
32
33
|
#
|
|
@@ -52,7 +53,7 @@ class Sibit
|
|
|
52
53
|
|
|
53
54
|
# Gets the balance of the address, in satoshi.
|
|
54
55
|
def balance(address)
|
|
55
|
-
uri =
|
|
56
|
+
uri = Iri.new('https://chain.api.btc.com/v3/address').append(address).append('unspent')
|
|
56
57
|
json = Sibit::Json.new(http: @http, log: @log).get(uri)
|
|
57
58
|
if json['err_no'] == 1
|
|
58
59
|
@log.info("The balance of #{address} is zero (not found)")
|
|
@@ -76,13 +77,13 @@ class Sibit
|
|
|
76
77
|
# Get hash of the block after this one.
|
|
77
78
|
def next_of(hash)
|
|
78
79
|
head = Sibit::Json.new(http: @http, log: @log).get(
|
|
79
|
-
|
|
80
|
+
Iri.new('https://chain.api.btc.com/v3/block').append(hash)
|
|
80
81
|
)
|
|
81
82
|
data = head['data']
|
|
82
83
|
raise Sibit::Error, "The block #{hash} not found" if data.nil?
|
|
83
84
|
nxt = data['next_block_hash']
|
|
84
85
|
nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
|
|
85
|
-
@log.info("
|
|
86
|
+
@log.info("In BTC.com the block #{hash} is the latest, there is no next block") if nxt.nil?
|
|
86
87
|
@log.info("The next block of #{hash} is #{nxt}") unless nxt.nil?
|
|
87
88
|
nxt
|
|
88
89
|
end
|
|
@@ -90,7 +91,7 @@ class Sibit
|
|
|
90
91
|
# The height of the block.
|
|
91
92
|
def height(hash)
|
|
92
93
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
93
|
-
|
|
94
|
+
Iri.new('https://chain.api.btc.com/v3/block').append(hash)
|
|
94
95
|
)
|
|
95
96
|
data = json['data']
|
|
96
97
|
raise Sibit::Error, "The block #{hash} not found" if data.nil?
|
|
@@ -107,7 +108,7 @@ class Sibit
|
|
|
107
108
|
|
|
108
109
|
# Gets the hash of the latest block.
|
|
109
110
|
def latest
|
|
110
|
-
uri =
|
|
111
|
+
uri = Iri.new('https://chain.api.btc.com/v3/block/latest')
|
|
111
112
|
json = Sibit::Json.new(http: @http, log: @log).get(uri)
|
|
112
113
|
data = json['data']
|
|
113
114
|
raise Sibit::Error, 'The latest block not found' if data.nil?
|
|
@@ -121,7 +122,7 @@ class Sibit
|
|
|
121
122
|
txns = []
|
|
122
123
|
sources.each do |hash|
|
|
123
124
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
124
|
-
|
|
125
|
+
Iri.new('https://chain.api.btc.com/v3/address').append(hash).append('unspent')
|
|
125
126
|
)
|
|
126
127
|
data = json['data']
|
|
127
128
|
raise Sibit::Error, "The address #{hash} not found" if data.nil?
|
|
@@ -129,7 +130,7 @@ class Sibit
|
|
|
129
130
|
next if txns.nil?
|
|
130
131
|
txns.each do |u|
|
|
131
132
|
outs = Sibit::Json.new(http: @http, log: @log).get(
|
|
132
|
-
|
|
133
|
+
Iri.new('https://chain.api.btc.com/v3/tx').append(u['tx_hash']).add(verbose: 3)
|
|
133
134
|
)['data']['outputs']
|
|
134
135
|
outs.each_with_index do |o, i|
|
|
135
136
|
next unless o['addresses'].include?(hash)
|
|
@@ -154,7 +155,7 @@ class Sibit
|
|
|
154
155
|
# This method should fetch a Blockchain block and return as a hash.
|
|
155
156
|
def block(hash)
|
|
156
157
|
head = Sibit::Json.new(http: @http, log: @log).get(
|
|
157
|
-
|
|
158
|
+
Iri.new('https://chain.api.btc.com/v3/block').append(hash)
|
|
158
159
|
)
|
|
159
160
|
data = head['data']
|
|
160
161
|
raise Sibit::Error, "The block #{hash} not found" if data.nil?
|
|
@@ -177,7 +178,8 @@ class Sibit
|
|
|
177
178
|
all = []
|
|
178
179
|
loop do
|
|
179
180
|
data = Sibit::Json.new(http: @http, log: @log).get(
|
|
180
|
-
|
|
181
|
+
Iri.new('https://chain.api.btc.com/v3/block')
|
|
182
|
+
.append(hash).append('tx').add(page: page, pagesize: psize)
|
|
181
183
|
)['data']
|
|
182
184
|
raise Sibit::Error, "The block #{hash} has no data at page #{page}" if data.nil?
|
|
183
185
|
list = data['list']
|
data/lib/sibit/cex.rb
CHANGED
|
@@ -45,7 +45,7 @@ class Sibit
|
|
|
45
45
|
# Current price of BTC in USD (float returned).
|
|
46
46
|
def price(currency = 'USD')
|
|
47
47
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
48
|
-
|
|
48
|
+
Iri.new('https://cex.io/api/last_price/BTC').append(currency)
|
|
49
49
|
)
|
|
50
50
|
p = json['lprice'].to_f
|
|
51
51
|
@log.info("The price of BTC is #{p} #{currency}")
|
data/lib/sibit/cryptoapis.rb
CHANGED
|
@@ -20,13 +20,14 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
-
require '
|
|
23
|
+
require 'iri'
|
|
24
24
|
require 'json'
|
|
25
|
-
|
|
25
|
+
require 'uri'
|
|
26
26
|
require_relative 'error'
|
|
27
|
-
require_relative 'log'
|
|
28
27
|
require_relative 'http'
|
|
29
28
|
require_relative 'json'
|
|
29
|
+
require_relative 'log'
|
|
30
|
+
require_relative 'version'
|
|
30
31
|
|
|
31
32
|
# Cryptoapis.io API.
|
|
32
33
|
#
|
|
@@ -52,7 +53,7 @@ class Sibit
|
|
|
52
53
|
# Get hash of the block after this one.
|
|
53
54
|
def next_of(hash)
|
|
54
55
|
nxt = Sibit::Json.new(http: @http, log: @log).get(
|
|
55
|
-
|
|
56
|
+
Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks').append(hash),
|
|
56
57
|
headers: headers
|
|
57
58
|
)['payload']['hash']
|
|
58
59
|
@log.info("The block #{hash} is the latest, there is no next block") if nxt.nil?
|
|
@@ -63,7 +64,7 @@ class Sibit
|
|
|
63
64
|
# The height of the block.
|
|
64
65
|
def height(hash)
|
|
65
66
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
66
|
-
|
|
67
|
+
Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks').append(hash),
|
|
67
68
|
headers: headers
|
|
68
69
|
)['payload']
|
|
69
70
|
h = json['height']
|
|
@@ -74,7 +75,7 @@ class Sibit
|
|
|
74
75
|
# Gets the balance of the address, in satoshi.
|
|
75
76
|
def balance(address)
|
|
76
77
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
77
|
-
|
|
78
|
+
Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/address').append(address),
|
|
78
79
|
headers: headers
|
|
79
80
|
)['payload']
|
|
80
81
|
b = (json['balance'].to_f * 100_000_000).to_i
|
|
@@ -90,7 +91,7 @@ class Sibit
|
|
|
90
91
|
# Gets the hash of the latest block.
|
|
91
92
|
def latest
|
|
92
93
|
hash = Sibit::Json.new(http: @http, log: @log).get(
|
|
93
|
-
|
|
94
|
+
Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks/latest'),
|
|
94
95
|
headers: headers
|
|
95
96
|
)['payload']['hash']
|
|
96
97
|
@log.info("The latest block hash is #{hash}")
|
|
@@ -105,7 +106,7 @@ class Sibit
|
|
|
105
106
|
# Push this transaction (in hex format) to the network.
|
|
106
107
|
def push(hex)
|
|
107
108
|
Sibit::Json.new(http: @http, log: @log).post(
|
|
108
|
-
|
|
109
|
+
Iri.new('https://api.cryptoapis.io/v1/bc/btc/testnet/txs/send'),
|
|
109
110
|
JSON.pretty_generate(hex: hex),
|
|
110
111
|
headers: headers
|
|
111
112
|
)
|
|
@@ -114,7 +115,7 @@ class Sibit
|
|
|
114
115
|
# This method should fetch a Blockchain block and return as a hash.
|
|
115
116
|
def block(hash)
|
|
116
117
|
head = Sibit::Json.new(http: @http, log: @log).get(
|
|
117
|
-
|
|
118
|
+
Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks').append(hash),
|
|
118
119
|
headers: headers
|
|
119
120
|
)['payload']
|
|
120
121
|
{
|
|
@@ -141,12 +142,8 @@ class Sibit
|
|
|
141
142
|
all = []
|
|
142
143
|
loop do
|
|
143
144
|
txns = Sibit::Json.new(http: @http, log: @log).get(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
'https://api.cryptoapis.io/v1/bc/btc/mainnet/txs/block/',
|
|
147
|
-
"#{hash}?index=#{index}&limit=#{limit}"
|
|
148
|
-
].join
|
|
149
|
-
),
|
|
145
|
+
Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/txs/block/')
|
|
146
|
+
.append(hash).add(index: index, limit: limit),
|
|
150
147
|
headers: headers
|
|
151
148
|
)['payload'].map do |t|
|
|
152
149
|
{
|
data/lib/sibit/earn.rb
CHANGED
|
@@ -20,12 +20,13 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
+
require 'iri'
|
|
23
24
|
require 'json'
|
|
24
25
|
require 'uri'
|
|
25
|
-
require_relative 'version'
|
|
26
26
|
require_relative 'error'
|
|
27
27
|
require_relative 'http'
|
|
28
28
|
require_relative 'json'
|
|
29
|
+
require_relative 'version'
|
|
29
30
|
|
|
30
31
|
# Earn.com API.
|
|
31
32
|
#
|
|
@@ -66,7 +67,7 @@ class Sibit
|
|
|
66
67
|
# a hash: { S: 12, M: 45, L: 100, XL: 200 }
|
|
67
68
|
def fees
|
|
68
69
|
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
69
|
-
|
|
70
|
+
Iri.new('https://bitcoinfees.earn.com/api/v1/fees/recommended')
|
|
70
71
|
)
|
|
71
72
|
@log.info("Current recommended Bitcoin fees: \
|
|
72
73
|
#{json['hourFee']}/#{json['halfHourFee']}/#{json['fastestFee']} sat/byte")
|
data/lib/sibit/firstof.rb
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
+
require 'backtrace'
|
|
23
24
|
require_relative 'error'
|
|
24
25
|
require_relative 'log'
|
|
25
26
|
|
|
@@ -102,6 +103,7 @@ class Sibit
|
|
|
102
103
|
|
|
103
104
|
def first_of(method)
|
|
104
105
|
return yield @list unless @list.is_a?(Array)
|
|
106
|
+
errors = []
|
|
105
107
|
done = false
|
|
106
108
|
result = nil
|
|
107
109
|
@list.each do |api|
|
|
@@ -111,10 +113,12 @@ class Sibit
|
|
|
111
113
|
done = true
|
|
112
114
|
break
|
|
113
115
|
rescue Sibit::Error => e
|
|
116
|
+
errors << e
|
|
114
117
|
@log.info("The API #{api.class.name} failed at #{method}(): #{e.message}") if @verbose
|
|
115
118
|
end
|
|
116
119
|
end
|
|
117
120
|
unless done
|
|
121
|
+
errors.each { |e| @log.info(Backtrace.new(e).to_s) }
|
|
118
122
|
raise Sibit::Error, "No APIs out of #{@list.length} managed to succeed at #{method}(): \
|
|
119
123
|
#{@list.map { |a| a.class.name }.join(', ')}"
|
|
120
124
|
end
|
data/lib/sibit/json.rb
CHANGED
|
@@ -48,8 +48,9 @@ class Sibit
|
|
|
48
48
|
# Send GET request to the HTTP and return JSON response.
|
|
49
49
|
# This method will also log the process and will validate the
|
|
50
50
|
# response for correctness.
|
|
51
|
-
def get(
|
|
51
|
+
def get(address, headers: {}, accept: [200])
|
|
52
52
|
start = Time.now
|
|
53
|
+
uri = URI(address.to_s)
|
|
53
54
|
res = @http.client(uri).get(
|
|
54
55
|
"#{uri.path.empty? ? '/' : uri.path}#{uri.query ? "?#{uri.query}" : ''}",
|
|
55
56
|
{
|
|
@@ -66,8 +67,9 @@ class Sibit
|
|
|
66
67
|
JSON.parse(res.body)
|
|
67
68
|
end
|
|
68
69
|
|
|
69
|
-
def post(
|
|
70
|
+
def post(address, body, headers: {})
|
|
70
71
|
start = Time.now
|
|
72
|
+
uri = URI(address.to_s)
|
|
71
73
|
res = @http.client(uri).post(
|
|
72
74
|
"#{uri.path}?#{uri.query}",
|
|
73
75
|
"tx=#{CGI.escape(body)}",
|
data/lib/sibit/log.rb
CHANGED
|
@@ -34,7 +34,7 @@ class Sibit
|
|
|
34
34
|
# provide anything, the console will be used. The object you provide
|
|
35
35
|
# has to respond to the method +info+ or +puts+ in order to receive logging
|
|
36
36
|
# messages.
|
|
37
|
-
def initialize(log =
|
|
37
|
+
def initialize(log = $stdout)
|
|
38
38
|
@log = log
|
|
39
39
|
end
|
|
40
40
|
|
data/lib/sibit/version.rb
CHANGED
data/sibit.gemspec
CHANGED
|
@@ -31,7 +31,7 @@ Gem::Specification.new do |s|
|
|
|
31
31
|
s.required_rubygems_version = Gem::Requirement.new('>= 0')
|
|
32
32
|
end
|
|
33
33
|
s.rubygems_version = '2.2'
|
|
34
|
-
s.required_ruby_version = '>= 2.
|
|
34
|
+
s.required_ruby_version = '>= 2.5'
|
|
35
35
|
s.name = 'sibit'
|
|
36
36
|
s.version = Sibit::VERSION
|
|
37
37
|
s.license = 'MIT'
|
|
@@ -49,20 +49,19 @@ and Ruby 2.3+.'
|
|
|
49
49
|
s.rdoc_options = ['--charset=UTF-8']
|
|
50
50
|
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
|
51
51
|
s.add_runtime_dependency 'backtrace', '~> 0.3'
|
|
52
|
-
s.add_runtime_dependency 'bitcoin', '0.2.0'
|
|
53
52
|
s.add_runtime_dependency 'bitcoin-ruby', '0.0.19'
|
|
53
|
+
s.add_runtime_dependency 'iri', '~> 0.5'
|
|
54
54
|
s.add_runtime_dependency 'json', '~> 2'
|
|
55
55
|
s.add_runtime_dependency 'retriable_proxy', '1.0.2'
|
|
56
56
|
s.add_runtime_dependency 'slop', '~> 4.6'
|
|
57
|
-
s.add_development_dependency 'aruba', '~> 0
|
|
58
|
-
s.add_development_dependency 'codecov', '0.2.
|
|
59
|
-
s.add_development_dependency 'cucumber', '~> 1
|
|
60
|
-
s.add_development_dependency 'debase', '0.2
|
|
61
|
-
s.add_development_dependency 'minitest', '5.
|
|
62
|
-
s.add_development_dependency 'rake', '
|
|
63
|
-
s.add_development_dependency 'rspec-rails', '
|
|
64
|
-
s.add_development_dependency 'rubocop', '0.
|
|
65
|
-
s.add_development_dependency 'rubocop-rspec', '1.
|
|
66
|
-
s.add_development_dependency '
|
|
67
|
-
s.add_development_dependency 'webmock', '3.7.6'
|
|
57
|
+
s.add_development_dependency 'aruba', '~> 1.0'
|
|
58
|
+
s.add_development_dependency 'codecov', '0.2.11'
|
|
59
|
+
s.add_development_dependency 'cucumber', '~> 5.1'
|
|
60
|
+
s.add_development_dependency 'debase', '~> 0.2'
|
|
61
|
+
s.add_development_dependency 'minitest', '5.14.2'
|
|
62
|
+
s.add_development_dependency 'rake', '13.0.1'
|
|
63
|
+
s.add_development_dependency 'rspec-rails', '4.0.1'
|
|
64
|
+
s.add_development_dependency 'rubocop', '0.91.0'
|
|
65
|
+
s.add_development_dependency 'rubocop-rspec', '1.43.2'
|
|
66
|
+
s.add_development_dependency 'webmock', '3.9.1'
|
|
68
67
|
end
|
data/test/test__helper.rb
CHANGED
data/test/test_blockchain.rb
CHANGED
|
@@ -34,7 +34,7 @@ class TestBlockchain < Minitest::Test
|
|
|
34
34
|
def test_fetch_block
|
|
35
35
|
hash = '0000000000000000000f676241aabc9b62b748d26192a44bc25720c34de27d19'
|
|
36
36
|
stub_request(:get, "https://blockchain.info/rawblock/#{hash}")
|
|
37
|
-
.to_return(body: '{"next_block": "n", "prev_block": "p", "hash": "h",
|
|
37
|
+
.to_return(body: '{"next_block": ["n"], "prev_block": "p", "hash": "h",
|
|
38
38
|
"tx": [{"hash": "h1", "out": [{"hash": "oh", "value": 123}]}]}')
|
|
39
39
|
sibit = Sibit::Blockchain.new
|
|
40
40
|
json = sibit.block(hash)
|
|
@@ -45,4 +45,14 @@ class TestBlockchain < Minitest::Test
|
|
|
45
45
|
assert_equal('h1', json[:txns][0][:hash])
|
|
46
46
|
assert(json[:txns][0][:outputs].is_a?(Array))
|
|
47
47
|
end
|
|
48
|
+
|
|
49
|
+
def test_next_of
|
|
50
|
+
skip
|
|
51
|
+
hash = '0000000000000000000f676241aabc9b62b748d26192a44bc25720c34de27d19'
|
|
52
|
+
stub_request(:get, "https://blockchain.info/rawblock/#{hash}")
|
|
53
|
+
.to_return(body: '{"next_block": ["nxt"]}')
|
|
54
|
+
sibit = Sibit::Blockchain.new
|
|
55
|
+
nxt = sibit.next_of(hash)
|
|
56
|
+
assert_equal('nxt', nxt)
|
|
57
|
+
end
|
|
48
58
|
end
|
data/test/test_live.rb
CHANGED
|
@@ -107,7 +107,7 @@ class TestLive < Minitest::Test
|
|
|
107
107
|
json = api.utxos(['12fCwqBN4XsHq4iu2Wbfgq5e8YhqEGP3ee'])
|
|
108
108
|
assert_equal(3, json.length)
|
|
109
109
|
assert(json.find { |t| t[:value] == 16_200_000 }, 'UTXO not found')
|
|
110
|
-
assert(json.find { |t| t[:script].
|
|
110
|
+
assert(json.find { |t| t[:script].unpack1('H*').start_with?('76a9141231e760') })
|
|
111
111
|
end
|
|
112
112
|
end
|
|
113
113
|
|
|
@@ -130,11 +130,9 @@ class TestLive < Minitest::Test
|
|
|
130
130
|
require_relative '../lib/sibit/bitcoinchain'
|
|
131
131
|
apis << Sibit::Bitcoinchain.new
|
|
132
132
|
apis.each do |api|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
puts Backtrace.new(e).to_s
|
|
137
|
-
end
|
|
133
|
+
yield api
|
|
134
|
+
rescue Sibit::Error => e
|
|
135
|
+
puts Backtrace.new(e).to_s
|
|
138
136
|
end
|
|
139
137
|
end
|
|
140
138
|
end
|
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.21.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-11-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: backtrace
|
|
@@ -25,33 +25,33 @@ dependencies:
|
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0.3'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: bitcoin
|
|
28
|
+
name: bitcoin-ruby
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - '='
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 0.
|
|
33
|
+
version: 0.0.19
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - '='
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 0.
|
|
40
|
+
version: 0.0.19
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: iri
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
|
-
- -
|
|
45
|
+
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.
|
|
47
|
+
version: '0.5'
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
|
-
- -
|
|
52
|
+
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.
|
|
54
|
+
version: '0.5'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: json
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -100,154 +100,140 @@ dependencies:
|
|
|
100
100
|
requirements:
|
|
101
101
|
- - "~>"
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: 0
|
|
103
|
+
version: '1.0'
|
|
104
104
|
type: :development
|
|
105
105
|
prerelease: false
|
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
107
|
requirements:
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: 0
|
|
110
|
+
version: '1.0'
|
|
111
111
|
- !ruby/object:Gem::Dependency
|
|
112
112
|
name: codecov
|
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
|
114
114
|
requirements:
|
|
115
115
|
- - '='
|
|
116
116
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: 0.2.
|
|
117
|
+
version: 0.2.11
|
|
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.2.
|
|
124
|
+
version: 0.2.11
|
|
125
125
|
- !ruby/object:Gem::Dependency
|
|
126
126
|
name: cucumber
|
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
|
128
128
|
requirements:
|
|
129
129
|
- - "~>"
|
|
130
130
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: 1
|
|
131
|
+
version: '5.1'
|
|
132
132
|
type: :development
|
|
133
133
|
prerelease: false
|
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
135
|
requirements:
|
|
136
136
|
- - "~>"
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: 1
|
|
138
|
+
version: '5.1'
|
|
139
139
|
- !ruby/object:Gem::Dependency
|
|
140
140
|
name: debase
|
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
|
142
142
|
requirements:
|
|
143
|
-
- -
|
|
143
|
+
- - "~>"
|
|
144
144
|
- !ruby/object:Gem::Version
|
|
145
|
-
version: 0.2
|
|
145
|
+
version: '0.2'
|
|
146
146
|
type: :development
|
|
147
147
|
prerelease: false
|
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
|
149
149
|
requirements:
|
|
150
|
-
- -
|
|
150
|
+
- - "~>"
|
|
151
151
|
- !ruby/object:Gem::Version
|
|
152
|
-
version: 0.2
|
|
152
|
+
version: '0.2'
|
|
153
153
|
- !ruby/object:Gem::Dependency
|
|
154
154
|
name: minitest
|
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
|
156
156
|
requirements:
|
|
157
157
|
- - '='
|
|
158
158
|
- !ruby/object:Gem::Version
|
|
159
|
-
version: 5.
|
|
159
|
+
version: 5.14.2
|
|
160
160
|
type: :development
|
|
161
161
|
prerelease: false
|
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
|
163
163
|
requirements:
|
|
164
164
|
- - '='
|
|
165
165
|
- !ruby/object:Gem::Version
|
|
166
|
-
version: 5.
|
|
166
|
+
version: 5.14.2
|
|
167
167
|
- !ruby/object:Gem::Dependency
|
|
168
168
|
name: rake
|
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
|
170
170
|
requirements:
|
|
171
171
|
- - '='
|
|
172
172
|
- !ruby/object:Gem::Version
|
|
173
|
-
version:
|
|
173
|
+
version: 13.0.1
|
|
174
174
|
type: :development
|
|
175
175
|
prerelease: false
|
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
|
177
177
|
requirements:
|
|
178
178
|
- - '='
|
|
179
179
|
- !ruby/object:Gem::Version
|
|
180
|
-
version:
|
|
180
|
+
version: 13.0.1
|
|
181
181
|
- !ruby/object:Gem::Dependency
|
|
182
182
|
name: rspec-rails
|
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
|
184
184
|
requirements:
|
|
185
185
|
- - '='
|
|
186
186
|
- !ruby/object:Gem::Version
|
|
187
|
-
version:
|
|
187
|
+
version: 4.0.1
|
|
188
188
|
type: :development
|
|
189
189
|
prerelease: false
|
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
|
191
191
|
requirements:
|
|
192
192
|
- - '='
|
|
193
193
|
- !ruby/object:Gem::Version
|
|
194
|
-
version:
|
|
194
|
+
version: 4.0.1
|
|
195
195
|
- !ruby/object:Gem::Dependency
|
|
196
196
|
name: rubocop
|
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
|
198
198
|
requirements:
|
|
199
199
|
- - '='
|
|
200
200
|
- !ruby/object:Gem::Version
|
|
201
|
-
version: 0.
|
|
201
|
+
version: 0.91.0
|
|
202
202
|
type: :development
|
|
203
203
|
prerelease: false
|
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
|
205
205
|
requirements:
|
|
206
206
|
- - '='
|
|
207
207
|
- !ruby/object:Gem::Version
|
|
208
|
-
version: 0.
|
|
208
|
+
version: 0.91.0
|
|
209
209
|
- !ruby/object:Gem::Dependency
|
|
210
210
|
name: rubocop-rspec
|
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
|
212
212
|
requirements:
|
|
213
213
|
- - '='
|
|
214
214
|
- !ruby/object:Gem::Version
|
|
215
|
-
version: 1.
|
|
216
|
-
type: :development
|
|
217
|
-
prerelease: false
|
|
218
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
219
|
-
requirements:
|
|
220
|
-
- - '='
|
|
221
|
-
- !ruby/object:Gem::Version
|
|
222
|
-
version: 1.31.0
|
|
223
|
-
- !ruby/object:Gem::Dependency
|
|
224
|
-
name: ruby-debug-ide
|
|
225
|
-
requirement: !ruby/object:Gem::Requirement
|
|
226
|
-
requirements:
|
|
227
|
-
- - '='
|
|
228
|
-
- !ruby/object:Gem::Version
|
|
229
|
-
version: 0.6.1
|
|
215
|
+
version: 1.43.2
|
|
230
216
|
type: :development
|
|
231
217
|
prerelease: false
|
|
232
218
|
version_requirements: !ruby/object:Gem::Requirement
|
|
233
219
|
requirements:
|
|
234
220
|
- - '='
|
|
235
221
|
- !ruby/object:Gem::Version
|
|
236
|
-
version:
|
|
222
|
+
version: 1.43.2
|
|
237
223
|
- !ruby/object:Gem::Dependency
|
|
238
224
|
name: webmock
|
|
239
225
|
requirement: !ruby/object:Gem::Requirement
|
|
240
226
|
requirements:
|
|
241
227
|
- - '='
|
|
242
228
|
- !ruby/object:Gem::Version
|
|
243
|
-
version: 3.
|
|
229
|
+
version: 3.9.1
|
|
244
230
|
type: :development
|
|
245
231
|
prerelease: false
|
|
246
232
|
version_requirements: !ruby/object:Gem::Requirement
|
|
247
233
|
requirements:
|
|
248
234
|
- - '='
|
|
249
235
|
- !ruby/object:Gem::Version
|
|
250
|
-
version: 3.
|
|
236
|
+
version: 3.9.1
|
|
251
237
|
description: |-
|
|
252
238
|
This is a simple Bitcoin client, to use from command line
|
|
253
239
|
or from your Ruby app. You don't need to run any Bitcoin software,
|
|
@@ -324,7 +310,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
324
310
|
requirements:
|
|
325
311
|
- - ">="
|
|
326
312
|
- !ruby/object:Gem::Version
|
|
327
|
-
version: '2.
|
|
313
|
+
version: '2.5'
|
|
328
314
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
329
315
|
requirements:
|
|
330
316
|
- - ">="
|