sibit 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/sibit +6 -0
- data/lib/sibit/version.rb +1 -1
- data/lib/sibit.rb +26 -15
- data/test/test_sibit.rb +12 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 478069971b53901e3037034ee2830d5b66154a77fc1b5087b17f15e94870ca39
|
4
|
+
data.tar.gz: 48039e52d5835aef4515e28c3fa3575e946e99556fcdb424f71c9f4c022f66e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80d804206aa880655b81a696a73558a47fc8dd1eee00d0c82fe7965283469d0b0586e56cace8d6309114af8572f8781deda7c259f6522317a9180c889a3e7fe5
|
7
|
+
data.tar.gz: 92d14ce0a35f45a1d994615a18fdde4472b33e39ff30c64f22606c0691bf37beed91db3a0c71f8a0f9f8b690da11eae24b8606030483213b5d34f42aae36d0fb
|
data/bin/sibit
CHANGED
@@ -31,6 +31,8 @@ begin
|
|
31
31
|
opts = Slop.parse(ARGV, strict: true, help: true) do |o|
|
32
32
|
o.banner = "Usage (#{Sibit::VERSION}): sibit [options] command [args]
|
33
33
|
Commands are:
|
34
|
+
price: Get current price of BTC in USD
|
35
|
+
latest: Get hash of the latest block
|
34
36
|
generate: Generate a new private key
|
35
37
|
create: Create a public Bitcoin address from the key
|
36
38
|
balance: Check the balance of the Bitcoin address
|
@@ -48,6 +50,10 @@ Options are:"
|
|
48
50
|
raise 'Try --help' if opts.arguments.empty?
|
49
51
|
sibit = Sibit.new(log: opts[:verbose] ? STDOUT : nil)
|
50
52
|
case opts.arguments[0]
|
53
|
+
when 'price'
|
54
|
+
puts sibit.price
|
55
|
+
when 'latest'
|
56
|
+
puts sibit.latest
|
51
57
|
when 'generate'
|
52
58
|
puts sibit.generate
|
53
59
|
when 'create'
|
data/lib/sibit/version.rb
CHANGED
data/lib/sibit.rb
CHANGED
@@ -34,6 +34,9 @@ require 'json'
|
|
34
34
|
# Copyright:: Copyright (c) 2019 Yegor Bugayenko
|
35
35
|
# License:: MIT
|
36
36
|
class Sibit
|
37
|
+
# If something goes wrong.
|
38
|
+
class Error < StandardError; end
|
39
|
+
|
37
40
|
# Constructor.
|
38
41
|
#
|
39
42
|
# You may provide the log you want to see the messages in. If you don't
|
@@ -46,8 +49,8 @@ class Sibit
|
|
46
49
|
|
47
50
|
# Current price of 1 BTC.
|
48
51
|
def price(cur = 'USD')
|
49
|
-
h = get_json('
|
50
|
-
raise "Unrecognized currency #{cur}" if h.nil?
|
52
|
+
h = get_json('/ticker')[cur.upcase]
|
53
|
+
raise Error, "Unrecognized currency #{cur}" if h.nil?
|
51
54
|
h['15m']
|
52
55
|
end
|
53
56
|
|
@@ -63,7 +66,7 @@ class Sibit
|
|
63
66
|
|
64
67
|
# Gets the balance of the address, in satoshi.
|
65
68
|
def balance(address)
|
66
|
-
json = get_json("
|
69
|
+
json = get_json("/rawaddr/#{address}")
|
67
70
|
debug("Total transactions: #{json['n_tx']}")
|
68
71
|
debug("Received/sent: #{json['total_received']}/#{json['total_sent']}")
|
69
72
|
json['final_balance']
|
@@ -92,7 +95,7 @@ class Sibit
|
|
92
95
|
unspent = 0
|
93
96
|
size = 100
|
94
97
|
utxos = get_json(
|
95
|
-
"
|
98
|
+
"/unspent?active=#{sources.join('|')}&limit=1000"
|
96
99
|
)['unspent_outputs']
|
97
100
|
debug("#{utxos.count} UTXOs found:")
|
98
101
|
utxos.each do |utxo|
|
@@ -107,7 +110,7 @@ class Sibit
|
|
107
110
|
debug(" #{utxo['value']}/#{utxo['confirmations']} at #{utxo['tx_hash_big_endian']}")
|
108
111
|
break if unspent > satoshi
|
109
112
|
end
|
110
|
-
raise "Not enough funds to send #{amount}, only #{unspent} left" if unspent < satoshi
|
113
|
+
raise Error, "Not enough funds to send #{amount}, only #{unspent} left" if unspent < satoshi
|
111
114
|
builder.output(satoshi, target)
|
112
115
|
tx = builder.tx(
|
113
116
|
input_value: unspent,
|
@@ -118,6 +121,22 @@ class Sibit
|
|
118
121
|
tx.hash
|
119
122
|
end
|
120
123
|
|
124
|
+
# Gets the hash of the latest block.
|
125
|
+
def latest
|
126
|
+
get_json('/latestblock')['hash']
|
127
|
+
end
|
128
|
+
|
129
|
+
# Send GET request to the Blockchain API and return JSON response.
|
130
|
+
# This method will also log the process and will validate the
|
131
|
+
# response for correctness.
|
132
|
+
def get_json(uri)
|
133
|
+
start = Time.now
|
134
|
+
res = Net::HTTP.get_response(URI('https://blockchain.info' + uri))
|
135
|
+
raise Error, "Failed to retrieve #{uri}: #{res.code}" unless res.code == '200'
|
136
|
+
debug("GET #{uri}: #{res.code} in #{age(start)}")
|
137
|
+
JSON.parse(res.body)
|
138
|
+
end
|
139
|
+
|
121
140
|
private
|
122
141
|
|
123
142
|
# Convert text to amount.
|
@@ -138,7 +157,7 @@ class Sibit
|
|
138
157
|
when 'XL'
|
139
158
|
return 250 * size
|
140
159
|
else
|
141
|
-
raise "Can't understand the fee: #{fee.inspect}"
|
160
|
+
raise Error, "Can't understand the fee: #{fee.inspect}"
|
142
161
|
end
|
143
162
|
end
|
144
163
|
|
@@ -157,18 +176,10 @@ class Sibit
|
|
157
176
|
start = Time.now
|
158
177
|
uri = URI('https://blockchain.info/pushtx')
|
159
178
|
res = Net::HTTP.post_form(uri, tx: body)
|
160
|
-
raise "Failed to post tx to #{uri}: #{res.code}" unless res.code == '200'
|
179
|
+
raise Error, "Failed to post tx to #{uri}: #{res.code}" unless res.code == '200'
|
161
180
|
debug("POST #{uri}: #{res.code} in #{age(start)}")
|
162
181
|
end
|
163
182
|
|
164
|
-
def get_json(uri)
|
165
|
-
start = Time.now
|
166
|
-
res = Net::HTTP.get_response(URI(uri))
|
167
|
-
raise "Failed to retrieve #{uri}: #{res.code}" unless res.code == '200'
|
168
|
-
debug("GET #{uri}: #{res.code} in #{age(start)}")
|
169
|
-
JSON.parse(res.body)
|
170
|
-
end
|
171
|
-
|
172
183
|
def debug(msg)
|
173
184
|
if @log.respond_to?(:debug)
|
174
185
|
@log.debug(msg)
|
data/test/test_sibit.rb
CHANGED
@@ -57,7 +57,7 @@ class TestSibit < Minitest::Test
|
|
57
57
|
assert(/^1[0-9a-zA-Z]+$/.match?(address))
|
58
58
|
end
|
59
59
|
|
60
|
-
def
|
60
|
+
def test_get_balance
|
61
61
|
stub_request(
|
62
62
|
:get,
|
63
63
|
'https://blockchain.info/rawaddr/1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f'
|
@@ -68,7 +68,17 @@ class TestSibit < Minitest::Test
|
|
68
68
|
assert_equal(100, balance)
|
69
69
|
end
|
70
70
|
|
71
|
-
def
|
71
|
+
def test_get_latest_block
|
72
|
+
stub_request(:get, 'https://blockchain.info/latestblock').to_return(
|
73
|
+
status: 200,
|
74
|
+
body: '{"hash": "0000000000000538200a48202ca6340e983646ca088c7618ae82d68e0c76ef5a"}'
|
75
|
+
)
|
76
|
+
sibit = Sibit.new
|
77
|
+
hash = sibit.latest
|
78
|
+
assert_equal('0000000000000538200a48202ca6340e983646ca088c7618ae82d68e0c76ef5a', hash)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_send_payment
|
72
82
|
json = {
|
73
83
|
unspent_outputs: [
|
74
84
|
{
|