sibit 0.30.6 → 0.31.0
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/Gemfile +1 -1
- data/Gemfile.lock +15 -14
- data/LICENSE.txt +1 -1
- data/LICENSES/MIT.txt +1 -1
- data/Rakefile +2 -2
- data/bin/sibit +109 -105
- data/cucumber.yml +1 -1
- data/features/cli.feature +7 -2
- data/features/dry.feature +1 -1
- data/features/gem_package.feature +1 -1
- data/features/step_definitions/steps.rb +1 -6
- data/features/support/env.rb +1 -1
- data/lib/sibit/base58.rb +2 -2
- data/lib/sibit/bech32.rb +48 -4
- data/lib/sibit/bestof.rb +2 -2
- data/lib/sibit/bitcoinchain.rb +2 -2
- data/lib/sibit/blockchain.rb +2 -2
- data/lib/sibit/blockchair.rb +2 -2
- data/lib/sibit/btc.rb +2 -2
- data/lib/sibit/cex.rb +2 -2
- data/lib/sibit/cryptoapis.rb +2 -2
- data/lib/sibit/dry.rb +2 -2
- data/lib/sibit/error.rb +2 -2
- data/lib/sibit/fake.rb +2 -2
- data/lib/sibit/firstof.rb +2 -2
- data/lib/sibit/http.rb +2 -2
- data/lib/sibit/httpproxy.rb +2 -2
- data/lib/sibit/json.rb +2 -2
- data/lib/sibit/key.rb +19 -8
- data/lib/sibit/script.rb +22 -5
- data/lib/sibit/tx.rb +88 -13
- data/lib/sibit/txbuilder.rb +12 -7
- data/lib/sibit/version.rb +3 -3
- data/lib/sibit.rb +9 -6
- data/sibit.gemspec +3 -2
- metadata +18 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d7d8d002bcff6bcb41fc9dcd1a4a4ebd2d622460a23777e36da39406e4de8684
|
|
4
|
+
data.tar.gz: 91d217414aec0258cd458dbbae530738e2efc211f3d259888413a0532554d203
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '099247f1d77cdb32d500e5798f7480b03ce48279d198c059e410f35ca9bb1fc345ee5b6f8342aa8b4ac9982079c9ec0848a26ae8201bb35af04f9bed67f9d2bc'
|
|
7
|
+
data.tar.gz: 16c9a7c880dc2bb401383bb5e0593fdfcafcdc7ebd77cfe19a7bc0509be14f8e7946b0a663bcd3e71826e60d93296533104a1d094bd25fb0955a1bdc181f6442
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -5,12 +5,13 @@ PATH
|
|
|
5
5
|
backtrace (~> 0.3)
|
|
6
6
|
decoor (~> 0.1)
|
|
7
7
|
elapsed (~> 0.2)
|
|
8
|
+
ellipsized (~> 0.3)
|
|
8
9
|
iri (~> 0.5)
|
|
9
10
|
json (~> 2.18)
|
|
10
11
|
loog (~> 0.6)
|
|
11
12
|
openssl (~> 3.0)
|
|
12
13
|
retriable_proxy (~> 1.0)
|
|
13
|
-
|
|
14
|
+
thor (~> 1.3)
|
|
14
15
|
|
|
15
16
|
GEM
|
|
16
17
|
remote: https://rubygems.org/
|
|
@@ -62,18 +63,19 @@ GEM
|
|
|
62
63
|
decoor (0.1.0)
|
|
63
64
|
diff-lcs (1.6.2)
|
|
64
65
|
docile (1.4.1)
|
|
65
|
-
donce (0.
|
|
66
|
+
donce (0.4.0)
|
|
66
67
|
backtrace (~> 0.3)
|
|
67
68
|
os (~> 1.1)
|
|
68
69
|
qbash (~> 0.3)
|
|
69
70
|
elapsed (0.2.1)
|
|
70
71
|
loog (~> 0.6)
|
|
71
72
|
tago (~> 0.1)
|
|
73
|
+
ellipsized (0.3.0)
|
|
72
74
|
erb (6.0.1)
|
|
73
|
-
ffi (1.17.
|
|
74
|
-
ffi (1.17.
|
|
75
|
+
ffi (1.17.3-arm64-darwin)
|
|
76
|
+
ffi (1.17.3-x86_64-linux-gnu)
|
|
75
77
|
hashdiff (1.2.1)
|
|
76
|
-
iri (0.11.
|
|
78
|
+
iri (0.11.6)
|
|
77
79
|
json (2.18.0)
|
|
78
80
|
language_server-protocol (3.17.0.5)
|
|
79
81
|
lint_roller (1.1.0)
|
|
@@ -82,7 +84,6 @@ GEM
|
|
|
82
84
|
logger (~> 1.0)
|
|
83
85
|
memoist3 (1.0.0)
|
|
84
86
|
mini_mime (1.1.5)
|
|
85
|
-
mini_portile2 (2.8.9)
|
|
86
87
|
minitest (6.0.1)
|
|
87
88
|
prism (~> 1.5)
|
|
88
89
|
minitest-reporters (1.7.1)
|
|
@@ -91,8 +92,9 @@ GEM
|
|
|
91
92
|
minitest (>= 5.0)
|
|
92
93
|
ruby-progressbar
|
|
93
94
|
multi_test (1.1.0)
|
|
94
|
-
nokogiri (1.
|
|
95
|
-
|
|
95
|
+
nokogiri (1.19.0-arm64-darwin)
|
|
96
|
+
racc (~> 1.4)
|
|
97
|
+
nokogiri (1.19.0-x86_64-linux-gnu)
|
|
96
98
|
racc (~> 1.4)
|
|
97
99
|
openssl (3.3.2)
|
|
98
100
|
os (1.1.4)
|
|
@@ -104,8 +106,8 @@ GEM
|
|
|
104
106
|
psych (5.3.1)
|
|
105
107
|
date
|
|
106
108
|
stringio
|
|
107
|
-
public_suffix (7.0.
|
|
108
|
-
qbash (0.
|
|
109
|
+
public_suffix (7.0.2)
|
|
110
|
+
qbash (0.5.0)
|
|
109
111
|
backtrace (> 0)
|
|
110
112
|
elapsed (> 0)
|
|
111
113
|
loog (> 0)
|
|
@@ -137,9 +139,9 @@ GEM
|
|
|
137
139
|
rubocop-ast (>= 1.48.0, < 2.0)
|
|
138
140
|
ruby-progressbar (~> 1.7)
|
|
139
141
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
140
|
-
rubocop-ast (1.
|
|
142
|
+
rubocop-ast (1.49.0)
|
|
141
143
|
parser (>= 3.3.7.2)
|
|
142
|
-
prism (~> 1.
|
|
144
|
+
prism (~> 1.7)
|
|
143
145
|
rubocop-minitest (0.38.2)
|
|
144
146
|
lint_roller (~> 1.1)
|
|
145
147
|
rubocop (>= 1.75.0, < 2.0)
|
|
@@ -161,13 +163,12 @@ GEM
|
|
|
161
163
|
simplecov (~> 0.19)
|
|
162
164
|
simplecov-html (0.13.2)
|
|
163
165
|
simplecov_json_formatter (0.1.4)
|
|
164
|
-
slop (4.10.1)
|
|
165
166
|
stringio (3.2.0)
|
|
166
167
|
sys-uname (1.4.1)
|
|
167
168
|
ffi (~> 1.1)
|
|
168
169
|
memoist3 (~> 1.0.0)
|
|
169
170
|
tago (0.6.0)
|
|
170
|
-
thor (1.
|
|
171
|
+
thor (1.5.0)
|
|
171
172
|
tsort (0.2.0)
|
|
172
173
|
unicode-display_width (3.2.0)
|
|
173
174
|
unicode-emoji (~> 4.1)
|
data/LICENSE.txt
CHANGED
data/LICENSES/MIT.txt
CHANGED
data/Rakefile
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require 'os'
|
|
@@ -33,7 +33,7 @@ end
|
|
|
33
33
|
desc 'Run them via Ruby, one by one'
|
|
34
34
|
task :picks do
|
|
35
35
|
next if OS.windows?
|
|
36
|
-
%w[
|
|
36
|
+
%w[lib].each do |d|
|
|
37
37
|
Dir["#{d}/**/*.rb"].each do |f|
|
|
38
38
|
qbash("bundle exec ruby #{Shellwords.escape(f)}", log: $stdout, env: { 'PICKS' => 'yes' })
|
|
39
39
|
end
|
data/bin/sibit
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
4
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
5
5
|
# SPDX-License-Identifier: MIT
|
|
6
6
|
|
|
7
7
|
$stdout.sync = true
|
|
8
8
|
|
|
9
9
|
require 'backtrace'
|
|
10
|
+
require 'ellipsized'
|
|
10
11
|
require 'loog'
|
|
11
12
|
require 'retriable_proxy'
|
|
12
|
-
require '
|
|
13
|
+
require 'thor'
|
|
13
14
|
require_relative '../lib/sibit'
|
|
14
15
|
require_relative '../lib/sibit/http'
|
|
15
16
|
require_relative '../lib/sibit/httpproxy'
|
|
@@ -23,79 +24,35 @@ require_relative '../lib/sibit/fake'
|
|
|
23
24
|
require_relative '../lib/sibit/firstof'
|
|
24
25
|
require_relative '../lib/sibit/version'
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Options are:"
|
|
41
|
-
o.string '--proxy', 'HTTPS proxy for all requests, e.g. "localhost:3128"'
|
|
42
|
-
o.integer(
|
|
43
|
-
'--attempts',
|
|
44
|
-
'How many times should we try before failing',
|
|
45
|
-
default: 1
|
|
46
|
-
)
|
|
47
|
-
o.bool '--dry', 'Don\'t send a real payment, run in a read-only mode'
|
|
48
|
-
o.bool '--help', 'Read this: https://github.com/yegor256/sibit' do
|
|
49
|
-
log.info(o)
|
|
50
|
-
exit
|
|
51
|
-
end
|
|
52
|
-
o.bool '--verbose', 'Print all possible debug messages'
|
|
53
|
-
o.array(
|
|
54
|
-
'--api',
|
|
55
|
-
'Ordered List of APIs to use, e.g. "eblockchain,btc,bitcoinchain"',
|
|
56
|
-
default: %w[blockchain btc bitcoinchain blockchair cex]
|
|
57
|
-
)
|
|
58
|
-
o.array(
|
|
59
|
-
'--skip-utxo',
|
|
60
|
-
'List of UTXTO that must be skipped while paying',
|
|
61
|
-
default: []
|
|
62
|
-
)
|
|
63
|
-
end
|
|
64
|
-
rescue Slop::Error => e
|
|
65
|
-
raise e.message
|
|
27
|
+
# Command-line interface for Sibit.
|
|
28
|
+
# Provides commands to interact with the Bitcoin network.
|
|
29
|
+
class Bin < Thor
|
|
30
|
+
class_option :proxy, type: :string, desc: 'HTTPS proxy for all requests, e.g. "localhost:3128"'
|
|
31
|
+
class_option :attempts, type: :numeric, default: 1,
|
|
32
|
+
desc: 'How many times should we try before failing'
|
|
33
|
+
class_option :dry, type: :boolean, default: false,
|
|
34
|
+
desc: "Don't send a real payment, run in a read-only mode"
|
|
35
|
+
class_option :verbose, type: :boolean, default: false, desc: 'Print all possible debug messages'
|
|
36
|
+
class_option :api, type: :array, default: %w[blockchain btc bitcoinchain blockchair cex],
|
|
37
|
+
desc: 'Ordered List of APIs to use, e.g. "blockchain,btc,bitcoinchain"'
|
|
38
|
+
|
|
39
|
+
def self.exit_on_failure?
|
|
40
|
+
true
|
|
66
41
|
end
|
|
67
42
|
|
|
68
|
-
|
|
43
|
+
def self.handle_argument_error(command, error, args, _arity)
|
|
44
|
+
raise error unless args.include?('--help') || args.include?('-h')
|
|
45
|
+
new.help(command.name)
|
|
46
|
+
end
|
|
69
47
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
apis = opts[:api].map(&:downcase).map do |a|
|
|
74
|
-
case a
|
|
75
|
-
when 'blockchain'
|
|
76
|
-
Sibit::Blockchain.new(http: http, log: log)
|
|
77
|
-
when 'btc'
|
|
78
|
-
Sibit::Btc.new(http: http, log: log)
|
|
79
|
-
when 'bitcoinchain'
|
|
80
|
-
Sibit::Bitcoinchain.new(http: http, log: log)
|
|
81
|
-
when 'blockchair'
|
|
82
|
-
Sibit::Blockchair.new(http: http, log: log)
|
|
83
|
-
when 'cex'
|
|
84
|
-
Sibit::Cex.new(http: http, log: log)
|
|
85
|
-
when 'fake'
|
|
86
|
-
Sibit::Fake.new
|
|
87
|
-
else
|
|
88
|
-
raise Sibit::Error, "Unknown API \"#{a}\""
|
|
89
|
-
end
|
|
48
|
+
desc 'price', 'Get current price of BTC in USD'
|
|
49
|
+
def price
|
|
50
|
+
log.info(client.price)
|
|
90
51
|
end
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
case opts.arguments[0]
|
|
96
|
-
when 'price'
|
|
97
|
-
log.info(sibit.price)
|
|
98
|
-
when 'fees'
|
|
52
|
+
|
|
53
|
+
desc 'fees', 'Get currently recommended transaction fees'
|
|
54
|
+
def fees
|
|
55
|
+
sibit = client
|
|
99
56
|
fees = sibit.fees
|
|
100
57
|
text = %i[S M L XL].map do |m|
|
|
101
58
|
sat = fees[m] * 250
|
|
@@ -103,44 +60,91 @@ begin
|
|
|
103
60
|
"#{m}: #{sat}sat / $#{format('%<usd>.02f', usd: usd)}"
|
|
104
61
|
end.join("\n")
|
|
105
62
|
log.info(text)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
desc 'latest', 'Get hash of the latest block'
|
|
66
|
+
def latest
|
|
67
|
+
log.info(client.latest)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
desc 'generate', 'Generate a new private key'
|
|
71
|
+
def generate
|
|
72
|
+
log.info(client.generate)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
desc 'create KEY', 'Create a public Bitcoin address from the private key'
|
|
76
|
+
def create(key)
|
|
77
|
+
log.debug("Private key provided: #{key.ellipsized(8).inspect}")
|
|
78
|
+
log.info(client.create(key))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
desc 'balance ADDRESS', 'Check the balance of the Bitcoin address'
|
|
82
|
+
def balance(address)
|
|
83
|
+
log.info(client.balance(address))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
desc 'pay AMOUNT FEE SOURCES TARGET CHANGE', 'Send a new Bitcoin transaction'
|
|
87
|
+
option :skip_utxo, type: :array, default: [],
|
|
88
|
+
desc: 'List of UTXO that must be skipped while paying'
|
|
89
|
+
option :yes, type: :boolean, default: false,
|
|
90
|
+
desc: 'Skip confirmation prompt and send the payment immediately'
|
|
91
|
+
def pay(amount, fee, sources, target, change)
|
|
121
92
|
amount = amount.to_i if /^[0-9]+$/.match?(amount)
|
|
122
|
-
fee = opts.arguments[2]
|
|
123
|
-
raise 'Miners fee argument is required' if fee.nil?
|
|
124
93
|
fee = fee.to_i if /^[0-9]+$/.match?(fee)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
|
|
94
|
+
args = [amount, fee, sources.split(','), target, change]
|
|
95
|
+
kwargs = { skip_utxo: options[:skip_utxo] }
|
|
96
|
+
unless options[:yes] || options[:dry]
|
|
97
|
+
client(dry: true).pay(*args, **kwargs)
|
|
98
|
+
print 'Do you confirm this payment? (yes/no): '
|
|
99
|
+
answer = $stdin.gets&.strip&.downcase
|
|
100
|
+
raise Sibit::Error, 'Payment cancelled by user' unless answer == 'yes'
|
|
101
|
+
end
|
|
102
|
+
log.info(client.pay(*args, **kwargs))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
desc 'version', 'Print program version'
|
|
106
|
+
def version
|
|
107
|
+
log.info(Sibit::VERSION)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
|
|
112
|
+
def log
|
|
113
|
+
@log ||= options[:verbose] ? Loog::VERBOSE : Loog::REGULAR
|
|
141
114
|
end
|
|
115
|
+
|
|
116
|
+
def client(dry: false)
|
|
117
|
+
http = options[:proxy] ? Sibit::HttpProxy.new(options[:proxy]) : Sibit::Http.new
|
|
118
|
+
apis = options[:api].flat_map { |a| a.split(',') }.map(&:downcase).map do |a|
|
|
119
|
+
case a
|
|
120
|
+
when 'blockchain'
|
|
121
|
+
Sibit::Blockchain.new(http: http, log: log)
|
|
122
|
+
when 'btc'
|
|
123
|
+
Sibit::Btc.new(http: http, log: log)
|
|
124
|
+
when 'bitcoinchain'
|
|
125
|
+
Sibit::Bitcoinchain.new(http: http, log: log)
|
|
126
|
+
when 'blockchair'
|
|
127
|
+
Sibit::Blockchair.new(http: http, log: log)
|
|
128
|
+
when 'cex'
|
|
129
|
+
Sibit::Cex.new(http: http, log: log)
|
|
130
|
+
when 'fake'
|
|
131
|
+
Sibit::Fake.new
|
|
132
|
+
else
|
|
133
|
+
raise Sibit::Error, "Unknown API \"#{a}\""
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
api = Sibit::FirstOf.new(apis, log: log, verbose: true)
|
|
137
|
+
api = Sibit::Dry.new(api, log: log) if options[:dry] || dry
|
|
138
|
+
api = RetriableProxy.for_object(api, on: Sibit::Error) if options[:attempts] > 1
|
|
139
|
+
Sibit.new(log: log, api: api)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
begin
|
|
144
|
+
Bin.start(ARGV)
|
|
142
145
|
rescue StandardError => e
|
|
143
|
-
|
|
146
|
+
log = ARGV.include?('--verbose') ? Loog::VERBOSE : Loog::REGULAR
|
|
147
|
+
if ARGV.include?('--verbose')
|
|
144
148
|
log.error(Backtrace.new(e))
|
|
145
149
|
else
|
|
146
150
|
log.error(e.message)
|
data/cucumber.yml
CHANGED
data/features/cli.feature
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
Feature: Command Line Processing
|
|
4
4
|
As a holder of BTC I want to be able to use sibit
|
|
@@ -6,7 +6,7 @@ Feature: Command Line Processing
|
|
|
6
6
|
Scenario: Help can be printed
|
|
7
7
|
When I run bin/sibit with "--help"
|
|
8
8
|
Then Exit code is zero
|
|
9
|
-
And Stdout contains "
|
|
9
|
+
And Stdout contains "Commands:"
|
|
10
10
|
|
|
11
11
|
Scenario: Bitcoin price can be retrieved
|
|
12
12
|
When I run bin/sibit with "price --attempts=4"
|
|
@@ -31,3 +31,8 @@ Feature: Command Line Processing
|
|
|
31
31
|
Scenario: Bitcoin fees can be printed
|
|
32
32
|
When I run bin/sibit with "fees --verbose --api=fake"
|
|
33
33
|
Then Exit code is zero
|
|
34
|
+
|
|
35
|
+
Scenario: Pay help shows all options
|
|
36
|
+
When I run bin/sibit with "pay --help"
|
|
37
|
+
Then Exit code is zero
|
|
38
|
+
And Stdout contains "--skip-utxo"
|
data/features/dry.feature
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require 'nokogiri'
|
|
7
7
|
require 'tmpdir'
|
|
8
|
-
require 'slop'
|
|
9
8
|
require 'English'
|
|
10
9
|
require_relative '../../lib/sibit'
|
|
11
10
|
|
|
@@ -14,10 +13,6 @@ Before do
|
|
|
14
13
|
@dir = Dir.mktmpdir('test')
|
|
15
14
|
FileUtils.mkdir_p(@dir)
|
|
16
15
|
Dir.chdir(@dir)
|
|
17
|
-
@opts = Slop.parse ['-v', '-s', @dir] do |o|
|
|
18
|
-
o.bool '-v', '--verbose'
|
|
19
|
-
o.string '-s', '--source'
|
|
20
|
-
end
|
|
21
16
|
end
|
|
22
17
|
|
|
23
18
|
After do
|
data/features/support/env.rb
CHANGED
data/lib/sibit/base58.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require 'digest'
|
|
@@ -13,7 +13,7 @@ class Sibit
|
|
|
13
13
|
# Encapsulates hex data and provides encoding/decoding functionality.
|
|
14
14
|
#
|
|
15
15
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
16
|
-
# Copyright:: Copyright (c) 2019-
|
|
16
|
+
# Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
17
17
|
# License:: MIT
|
|
18
18
|
class Base58
|
|
19
19
|
ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
data/lib/sibit/bech32.rb
CHANGED
|
@@ -1,23 +1,67 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require_relative 'error'
|
|
7
7
|
|
|
8
8
|
# Sibit main class.
|
|
9
9
|
class Sibit
|
|
10
|
-
# Bech32 decoding for SegWit addresses.
|
|
10
|
+
# Bech32 encoding and decoding for SegWit addresses.
|
|
11
11
|
#
|
|
12
|
-
#
|
|
12
|
+
# Encodes witness programs to Bech32 addresses (bc1...) and decodes them back.
|
|
13
13
|
#
|
|
14
14
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
15
|
-
# Copyright:: Copyright (c) 2019-
|
|
15
|
+
# Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
16
16
|
# License:: MIT
|
|
17
17
|
class Bech32
|
|
18
18
|
CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'
|
|
19
19
|
GENERATOR = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3].freeze
|
|
20
20
|
|
|
21
|
+
def self.encode(hrp, ver, prog)
|
|
22
|
+
bytes = [prog].pack('H*').bytes
|
|
23
|
+
data = [ver] + bits(bytes, 8, 5, true)
|
|
24
|
+
chk = checksum(hrp, data)
|
|
25
|
+
"#{hrp}1#{(data + chk).map { |d| CHARSET[d] }.join}"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.checksum(hrp, data)
|
|
29
|
+
values = expanded(hrp) + data + [0, 0, 0, 0, 0, 0]
|
|
30
|
+
poly = pm(values) ^ 1
|
|
31
|
+
(0..5).map { |i| (poly >> (5 * (5 - i))) & 31 }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.expanded(hrp)
|
|
35
|
+
hrp.chars.map { |c| c.ord >> 5 } + [0] + hrp.chars.map { |c| c.ord & 31 }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.pm(values)
|
|
39
|
+
chk = 1
|
|
40
|
+
values.each do |v|
|
|
41
|
+
top = chk >> 25
|
|
42
|
+
chk = ((chk & 0x1ffffff) << 5) ^ v
|
|
43
|
+
5.times { |i| chk ^= GENERATOR[i] if (top >> i).allbits?(1) }
|
|
44
|
+
end
|
|
45
|
+
chk
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.bits(data, frombits, tobits, pad)
|
|
49
|
+
acc = 0
|
|
50
|
+
num = 0
|
|
51
|
+
result = []
|
|
52
|
+
maxv = (1 << tobits) - 1
|
|
53
|
+
data.each do |v|
|
|
54
|
+
acc = (acc << frombits) | v
|
|
55
|
+
num += frombits
|
|
56
|
+
while num >= tobits
|
|
57
|
+
num -= tobits
|
|
58
|
+
result << ((acc >> num) & maxv)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
result << ((acc << (tobits - num)) & maxv) if pad && num.positive?
|
|
62
|
+
result
|
|
63
|
+
end
|
|
64
|
+
|
|
21
65
|
def initialize(addr)
|
|
22
66
|
@addr = addr.downcase
|
|
23
67
|
end
|
data/lib/sibit/bestof.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require 'backtrace'
|
|
@@ -10,7 +10,7 @@ require_relative 'error'
|
|
|
10
10
|
# API best of.
|
|
11
11
|
#
|
|
12
12
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
13
|
-
# Copyright:: Copyright (c) 2019-
|
|
13
|
+
# Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
14
14
|
# License:: MIT
|
|
15
15
|
class Sibit::BestOf
|
|
16
16
|
# Constructor.
|
data/lib/sibit/bitcoinchain.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require 'iri'
|
|
@@ -15,7 +15,7 @@ require_relative 'version'
|
|
|
15
15
|
# Bitcoinchain.com API.
|
|
16
16
|
#
|
|
17
17
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
18
|
-
# Copyright:: Copyright (c) 2019-
|
|
18
|
+
# Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
19
19
|
# License:: MIT
|
|
20
20
|
class Sibit::Bitcoinchain
|
|
21
21
|
# Constructor.
|
data/lib/sibit/blockchain.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require 'iri'
|
|
@@ -18,7 +18,7 @@ require_relative 'version'
|
|
|
18
18
|
# https://www.blockchain.com/api/blockchain_api
|
|
19
19
|
#
|
|
20
20
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
21
|
-
# Copyright:: Copyright (c) 2019-
|
|
21
|
+
# Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
22
22
|
# License:: MIT
|
|
23
23
|
class Sibit::Blockchain
|
|
24
24
|
# Constructor.
|
data/lib/sibit/blockchair.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require 'cgi'
|
|
@@ -16,7 +16,7 @@ require_relative 'version'
|
|
|
16
16
|
# Blockchair.com API.
|
|
17
17
|
#
|
|
18
18
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
19
|
-
# Copyright:: Copyright (c) 2019-
|
|
19
|
+
# Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
20
20
|
# License:: MIT
|
|
21
21
|
class Sibit::Blockchair
|
|
22
22
|
# Constructor.
|
data/lib/sibit/btc.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2019-
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require 'iri'
|
|
@@ -17,7 +17,7 @@ require_relative 'version'
|
|
|
17
17
|
# Here: https://btc.com/api-doc
|
|
18
18
|
#
|
|
19
19
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
20
|
-
# Copyright:: Copyright (c) 2019-
|
|
20
|
+
# Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
21
21
|
# License:: MIT
|
|
22
22
|
class Sibit::Btc
|
|
23
23
|
# Constructor.
|