sibit 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/README.md +4 -1
- data/Rakefile +0 -3
- data/appveyor.yml +1 -1
- data/bin/sibit +3 -1
- data/features/cli.feature +4 -0
- data/lib/sibit/version.rb +1 -1
- data/lib/sibit.rb +21 -13
- data/logo.png +0 -0
- data/test/test_sibit.rb +43 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 420c1f144c205270b6147f9f7841dc623f406da2229515491a6e62394b666a7a
|
4
|
+
data.tar.gz: 4038585222353146bcfb9095edea86cec8f16b4ec8bf2561c134e5e09df8c3a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2327d071a6deecf933409c9a56869889adcbece633fba1072e269130e247ea24a841e8f4b6698eaa91b0b2c6c11c54a654c10fb1049e52245270bc3449890b35
|
7
|
+
data.tar.gz: 590ff2cd99e4f060043a5d067b38013d5bf0fd0dfb09c6def61559a993d4b8c175b94122f4680b1db99e313ea33d34df6c7e8d54e7be7ad2fed57e3ea6f8c1a9
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
<img src="
|
1
|
+
<img src="/logo.png" width="64px"/>
|
2
2
|
|
3
3
|
[![EO principles respected here](http://www.elegantobjects.org/badge.svg)](http://www.elegantobjects.org)
|
4
4
|
[![Managed by Zerocracy](https://www.0crat.com/badge/C3RFVLU72.svg)](https://www.0crat.com/p/C3RFVLU72)
|
@@ -26,6 +26,9 @@ something more complex, I would recommend using
|
|
26
26
|
[bitcoin-ruby](https://github.com/lian/bitcoin-ruby) for Ruby and
|
27
27
|
[Electrum](https://electrum.org/) as a GUI client.
|
28
28
|
|
29
|
+
You may want to discuss this tool at [Bitcointalk](https://bitcointalk.org/index.php?topic=5130324)
|
30
|
+
and give the thread a few merits.
|
31
|
+
|
29
32
|
This is a Ruby gem, install it first (if doesn't work, there are
|
30
33
|
some hints at the bottom of this page):
|
31
34
|
|
data/Rakefile
CHANGED
@@ -36,7 +36,6 @@ end
|
|
36
36
|
task default: %i[clean test features rubocop copyright]
|
37
37
|
|
38
38
|
require 'rake/testtask'
|
39
|
-
desc 'Run all unit tests'
|
40
39
|
Rake::TestTask.new(:test) do |test|
|
41
40
|
Rake::Cleaner.cleanup_files(['coverage'])
|
42
41
|
test.libs << 'lib' << 'test'
|
@@ -45,7 +44,6 @@ Rake::TestTask.new(:test) do |test|
|
|
45
44
|
end
|
46
45
|
|
47
46
|
require 'rdoc/task'
|
48
|
-
desc 'Build RDoc documentation'
|
49
47
|
Rake::RDocTask.new do |rdoc|
|
50
48
|
rdoc.rdoc_dir = 'rdoc'
|
51
49
|
rdoc.title = "#{name} #{version}"
|
@@ -54,7 +52,6 @@ Rake::RDocTask.new do |rdoc|
|
|
54
52
|
end
|
55
53
|
|
56
54
|
require 'rubocop/rake_task'
|
57
|
-
desc 'Run RuboCop on all directories'
|
58
55
|
RuboCop::RakeTask.new(:rubocop) do |task|
|
59
56
|
task.fail_on_error = true
|
60
57
|
task.requires << 'rubocop-rspec'
|
data/appveyor.yml
CHANGED
data/bin/sibit
CHANGED
@@ -39,6 +39,7 @@ Commands are:
|
|
39
39
|
pay: Send a new Bitcoin transaction
|
40
40
|
Options are:"
|
41
41
|
o.string '--proxy', 'HTTPS proxy for all requests, e.g. "localhost:3128"'
|
42
|
+
o.bool '--dry', 'Don\'t send a real payment, run in a read-only mode'
|
42
43
|
o.bool '--help', 'Read this: https://github.com/yegor256/sibit' do
|
43
44
|
puts o
|
44
45
|
exit
|
@@ -51,7 +52,8 @@ Options are:"
|
|
51
52
|
raise 'Try --help' if opts.arguments.empty?
|
52
53
|
sibit = Sibit.new(
|
53
54
|
log: opts[:verbose] ? STDOUT : nil,
|
54
|
-
http: opts[:proxy] ? Sibit.proxy_http(opts[:proxy]) : Sibit.default_http
|
55
|
+
http: opts[:proxy] ? Sibit.proxy_http(opts[:proxy]) : Sibit.default_http,
|
56
|
+
dry: opts[:dry]
|
55
57
|
)
|
56
58
|
case opts.arguments[0]
|
57
59
|
when 'price'
|
data/features/cli.feature
CHANGED
@@ -25,3 +25,7 @@ Feature: Command Line Processing
|
|
25
25
|
Scenario: Bitcoin balance can be checked
|
26
26
|
When I run bin/sibit with "balance 1MZT1fa6y8H9UmbZV6HqKF4UY41o9MGT5f --verbose"
|
27
27
|
Then Exit code is zero
|
28
|
+
|
29
|
+
Scenario: Bitcoin transaction can be sent
|
30
|
+
When I run bin/sibit with "--verbose --dry pay 100000 S 1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi:fd2333686f49d8647e1ce8d5ef39c304520b08f3c756b67068b30a3db217dcb2 1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi 1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi"
|
31
|
+
Then Exit code is zero
|
data/lib/sibit/version.rb
CHANGED
data/lib/sibit.rb
CHANGED
@@ -25,6 +25,7 @@ require 'uri'
|
|
25
25
|
require 'bitcoin'
|
26
26
|
require 'json'
|
27
27
|
require 'cgi'
|
28
|
+
require_relative 'sibit/version'
|
28
29
|
|
29
30
|
# Sibit main class.
|
30
31
|
#
|
@@ -90,9 +91,10 @@ class Sibit
|
|
90
91
|
# provide anything, the console will be used. The object you provide
|
91
92
|
# has to respond to the method +info+ or +puts+ in order to receive logging
|
92
93
|
# messages.
|
93
|
-
def initialize(log: STDOUT, http: Sibit.default_http)
|
94
|
+
def initialize(log: STDOUT, http: Sibit.default_http, dry: false)
|
94
95
|
@log = log
|
95
96
|
@http = http
|
97
|
+
@dry = dry
|
96
98
|
end
|
97
99
|
|
98
100
|
# Current price of 1 BTC.
|
@@ -138,6 +140,7 @@ class Sibit
|
|
138
140
|
# +target+: the target address to send to
|
139
141
|
# +change+: the address where the change has to be sent to
|
140
142
|
def pay(amount, fee, sources, target, change)
|
143
|
+
p = price
|
141
144
|
satoshi = satoshi(amount)
|
142
145
|
builder = Bitcoin::Builder::TxBuilder.new
|
143
146
|
unspent = 0
|
@@ -157,11 +160,11 @@ class Sibit
|
|
157
160
|
i.signature_key(key(sources[address]))
|
158
161
|
end
|
159
162
|
size += 180
|
160
|
-
info(" #{num(utxo['value'])}/#{utxo['confirmations']} at #{utxo['tx_hash_big_endian']}")
|
163
|
+
info(" #{num(utxo['value'], p)}/#{utxo['confirmations']} at #{utxo['tx_hash_big_endian']}")
|
161
164
|
break if unspent > satoshi
|
162
165
|
end
|
163
166
|
if unspent < satoshi
|
164
|
-
raise Error, "Not enough funds to send #{num(
|
167
|
+
raise Error, "Not enough funds to send #{num(satoshi, p)}, only #{num(unspent, p)} left"
|
165
168
|
end
|
166
169
|
builder.output(satoshi, target)
|
167
170
|
f = mfee(fee, size)
|
@@ -171,20 +174,21 @@ class Sibit
|
|
171
174
|
extra_fee: f - Bitcoin.network[:min_tx_fee],
|
172
175
|
change_address: change
|
173
176
|
)
|
177
|
+
left = unspent - tx.outputs.map(&:value).inject(&:+)
|
174
178
|
info("A new Bitcoin transaction #{tx.hash} prepared:
|
175
179
|
#{tx.in.count} input#{tx.in.count > 1 ? 's' : ''}:
|
176
180
|
#{tx.inputs.map { |i| " in: #{i.prev_out.bth}:#{i.prev_out_index}" }.join("\n ")}
|
177
181
|
#{tx.out.count} output#{tx.out.count > 1 ? 's' : ''}:
|
178
|
-
#{tx.outputs.map { |o| "out: #{o.script.bth} / #{num(o.value)}" }.join("\n ")}
|
179
|
-
Fee required: #{num(f)}
|
180
|
-
Min tx fee: #{num(Bitcoin.network[:min_tx_fee])}
|
181
|
-
Fee left: #{num(
|
182
|
-
Tx size: #{
|
183
|
-
Unspent: #{num(unspent)}
|
184
|
-
Amount: #{num(satoshi)}
|
182
|
+
#{tx.outputs.map { |o| "out: #{o.script.bth} / #{num(o.value, p)}" }.join("\n ")}
|
183
|
+
Fee required: #{num(f, p)}
|
184
|
+
Min tx fee: #{num(Bitcoin.network[:min_tx_fee], p)}
|
185
|
+
Fee left: #{num(left, p)}
|
186
|
+
Tx size: #{size} bytes
|
187
|
+
Unspent: #{num(unspent, p)}
|
188
|
+
Amount: #{num(satoshi, p)}
|
185
189
|
Target address: #{target}
|
186
190
|
Change address is #{change}")
|
187
|
-
post_tx(tx.to_payload.bth)
|
191
|
+
post_tx(tx.to_payload.bth) unless @dry
|
188
192
|
tx.hash
|
189
193
|
end
|
190
194
|
|
@@ -211,8 +215,12 @@ class Sibit
|
|
211
215
|
|
212
216
|
private
|
213
217
|
|
214
|
-
def num(
|
215
|
-
|
218
|
+
def num(satoshi, usd)
|
219
|
+
format(
|
220
|
+
'%<satoshi>ss/$%<dollars>0.2f',
|
221
|
+
satoshi: satoshi.to_s.gsub(/\d(?=(...)+$)/, '\0,'),
|
222
|
+
dollars: satoshi * usd / 100_000_000
|
223
|
+
)
|
216
224
|
end
|
217
225
|
|
218
226
|
# Convert text to amount.
|
data/logo.png
ADDED
Binary file
|
data/test/test_sibit.rb
CHANGED
@@ -80,6 +80,9 @@ class TestSibit < Minitest::Test
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def test_send_payment
|
83
|
+
stub_request(
|
84
|
+
:get, 'https://blockchain.info/ticker'
|
85
|
+
).to_return(status: 200, body: '{"USD" : {"15m" : 5160.04}}')
|
83
86
|
json = {
|
84
87
|
unspent_outputs: [
|
85
88
|
{
|
@@ -110,4 +113,44 @@ class TestSibit < Minitest::Test
|
|
110
113
|
assert(!tx.nil?)
|
111
114
|
assert(tx.length > 30, tx)
|
112
115
|
end
|
116
|
+
|
117
|
+
def test_fail_if_not_enough_funds
|
118
|
+
stub_request(
|
119
|
+
:get, 'https://blockchain.info/ticker'
|
120
|
+
).to_return(status: 200, body: '{"USD" : {"15m" : 5160.04}}')
|
121
|
+
json = {
|
122
|
+
unspent_outputs: []
|
123
|
+
}
|
124
|
+
stub_request(
|
125
|
+
:get,
|
126
|
+
'https://blockchain.info/unspent?active=1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi&limit=1000'
|
127
|
+
).to_return(status: 200, body: JSON.pretty_generate(json))
|
128
|
+
sibit = Sibit.new
|
129
|
+
target = sibit.create(sibit.generate)
|
130
|
+
change = sibit.create(sibit.generate)
|
131
|
+
assert_raises Sibit::Error do
|
132
|
+
sibit.pay(
|
133
|
+
'0.0001BTC', 'XL',
|
134
|
+
{
|
135
|
+
'1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi' =>
|
136
|
+
'fd2333686f49d8647e1ce8d5ef39c304520b08f3c756b67068b30a3db217dcb2'
|
137
|
+
},
|
138
|
+
target, change
|
139
|
+
)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_fake_object_works
|
144
|
+
sibit = Sibit::Fake.new
|
145
|
+
assert_equal(4_000, sibit.price)
|
146
|
+
assert_equal('fd2333686f49d8647e1ce8d5ef39c304520b08f3c756b67068b30a3db217dcb2', sibit.generate)
|
147
|
+
assert_equal('1JvCsJtLmCxEk7ddZFnVkGXpr9uhxZPmJi', sibit.create(''))
|
148
|
+
assert_equal(100_000_000, sibit.balance(''))
|
149
|
+
assert_equal(
|
150
|
+
'9dfe55a30b5ee732005158c589179a398117117a68d21531fb6c78b85b544c54',
|
151
|
+
sibit.pay(0, 'M', {}, '', '')
|
152
|
+
)
|
153
|
+
assert_equal('00000000000000000008df8a6e1b61d1136803ac9791b8725235c9f780b4ed71', sibit.latest)
|
154
|
+
assert_equal({}, sibit.get_json('/'))
|
155
|
+
end
|
113
156
|
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.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05-
|
11
|
+
date: 2019-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backtrace
|
@@ -240,6 +240,7 @@ files:
|
|
240
240
|
- features/support/env.rb
|
241
241
|
- lib/sibit.rb
|
242
242
|
- lib/sibit/version.rb
|
243
|
+
- logo.png
|
243
244
|
- sibit.gemspec
|
244
245
|
- test/test__helper.rb
|
245
246
|
- test/test_sibit.rb
|