sibit 0.28.0 → 0.29.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.lock +3 -3
- data/README.md +14 -17
- data/bin/sibit +0 -4
- data/lib/sibit/bestof.rb +68 -71
- data/lib/sibit/bitcoin/base58.rb +33 -35
- data/lib/sibit/bitcoin/key.rb +64 -66
- data/lib/sibit/bitcoin/script.rb +45 -47
- data/lib/sibit/bitcoin/tx.rb +162 -164
- data/lib/sibit/bitcoin/txbuilder.rb +1 -1
- data/lib/sibit/bitcoinchain.rb +93 -96
- data/lib/sibit/blockchain.rb +115 -118
- data/lib/sibit/blockchair.rb +62 -65
- data/lib/sibit/btc.rb +147 -150
- data/lib/sibit/cex.rb +49 -50
- data/lib/sibit/cryptoapis.rb +113 -116
- data/lib/sibit/fake.rb +42 -47
- data/lib/sibit/firstof.rb +73 -76
- data/lib/sibit/http.rb +17 -20
- data/lib/sibit/json.rb +63 -66
- data/lib/sibit/version.rb +1 -1
- data/lib/sibit.rb +7 -9
- metadata +1 -1
data/lib/sibit/json.rb
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2019-2025 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
|
+
require 'cgi'
|
|
6
7
|
require 'json'
|
|
8
|
+
require 'loog'
|
|
7
9
|
require 'uri'
|
|
8
|
-
require 'cgi'
|
|
9
|
-
require_relative 'version'
|
|
10
10
|
require_relative 'error'
|
|
11
|
-
require 'loog'
|
|
12
11
|
require_relative 'http'
|
|
12
|
+
require_relative 'version'
|
|
13
13
|
|
|
14
14
|
# Json SDK.
|
|
15
15
|
#
|
|
@@ -19,77 +19,74 @@ require_relative 'http'
|
|
|
19
19
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
20
20
|
# Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
|
|
21
21
|
# License:: MIT
|
|
22
|
-
class Sibit
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@log = log
|
|
29
|
-
end
|
|
22
|
+
class Sibit::Json
|
|
23
|
+
# Constructor.
|
|
24
|
+
def initialize(log: Loog::NULL, http: Sibit::Http.new)
|
|
25
|
+
@http = http
|
|
26
|
+
@log = log
|
|
27
|
+
end
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
end
|
|
49
|
-
@log.info("GET #{uri}: #{res.code}/#{length(res.body.length)} in #{age(start)}")
|
|
50
|
-
JSON.parse(res.body)
|
|
51
|
-
rescue JSON::ParserError => e
|
|
52
|
-
raise Sibit::Error, "Can't parse JSON: #{e.message}"
|
|
29
|
+
# Send GET request to the HTTP and return JSON response.
|
|
30
|
+
# This method will also log the process and will validate the
|
|
31
|
+
# response for correctness.
|
|
32
|
+
def get(address, headers: {}, accept: [200])
|
|
33
|
+
start = Time.now
|
|
34
|
+
uri = URI(address.to_s)
|
|
35
|
+
res = @http.client(uri).get(
|
|
36
|
+
"#{uri.path.empty? ? '/' : uri.path}#{"?#{uri.query}" if uri.query}",
|
|
37
|
+
{
|
|
38
|
+
'Accept' => 'application/json',
|
|
39
|
+
'User-Agent' => user_agent,
|
|
40
|
+
'Accept-Charset' => 'UTF-8',
|
|
41
|
+
'Accept-Encoding' => ''
|
|
42
|
+
}.merge(headers)
|
|
43
|
+
)
|
|
44
|
+
unless accept.include?(res.code.to_i)
|
|
45
|
+
raise Sibit::Error, "Failed to retrieve #{uri} (#{res.code}): #{res.body}"
|
|
53
46
|
end
|
|
47
|
+
@log.info("GET #{uri}: #{res.code}/#{length(res.body.length)} in #{age(start)}")
|
|
48
|
+
JSON.parse(res.body)
|
|
49
|
+
rescue JSON::ParserError => e
|
|
50
|
+
raise Sibit::Error, "Can't parse JSON: #{e.message}"
|
|
51
|
+
end
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
end
|
|
72
|
-
@log.info("POST #{uri}: #{res.code} in #{age(start)}")
|
|
53
|
+
def post(address, body, headers: {})
|
|
54
|
+
start = Time.now
|
|
55
|
+
uri = URI(address.to_s)
|
|
56
|
+
res = @http.client(uri).post(
|
|
57
|
+
"#{uri.path}?#{uri.query}",
|
|
58
|
+
"tx=#{CGI.escape(body)}",
|
|
59
|
+
{
|
|
60
|
+
'Accept' => 'text/plain',
|
|
61
|
+
'User-Agent' => user_agent,
|
|
62
|
+
'Accept-Charset' => 'UTF-8',
|
|
63
|
+
'Accept-Encoding' => '',
|
|
64
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
|
65
|
+
}.merge(headers)
|
|
66
|
+
)
|
|
67
|
+
unless res.code == '200'
|
|
68
|
+
raise Sibit::Error, "Failed to post tx to #{uri}: #{res.code}\n#{res.body}"
|
|
73
69
|
end
|
|
70
|
+
@log.info("POST #{uri}: #{res.code} in #{age(start)}")
|
|
71
|
+
end
|
|
74
72
|
|
|
75
|
-
|
|
73
|
+
private
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
def age(start)
|
|
76
|
+
"#{((Time.now - start) * 1000).round}ms"
|
|
77
|
+
end
|
|
80
78
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
end
|
|
79
|
+
def length(bytes)
|
|
80
|
+
if bytes > 1024 * 1024
|
|
81
|
+
"#{bytes / (1024 * 1024)}mb"
|
|
82
|
+
elsif bytes > 1024
|
|
83
|
+
"#{bytes / 1024}kb"
|
|
84
|
+
else
|
|
85
|
+
"#{bytes}b"
|
|
89
86
|
end
|
|
87
|
+
end
|
|
90
88
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
end
|
|
89
|
+
def user_agent
|
|
90
|
+
"Anonymous/#{Sibit::VERSION}"
|
|
94
91
|
end
|
|
95
92
|
end
|
data/lib/sibit/version.rb
CHANGED
data/lib/sibit.rb
CHANGED
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
6
|
require 'loog'
|
|
7
|
-
require_relative 'sibit/version'
|
|
8
|
-
require_relative 'sibit/blockchain'
|
|
9
7
|
require_relative 'sibit/bitcoin/base58'
|
|
10
8
|
require_relative 'sibit/bitcoin/key'
|
|
11
9
|
require_relative 'sibit/bitcoin/script'
|
|
12
10
|
require_relative 'sibit/bitcoin/tx'
|
|
13
11
|
require_relative 'sibit/bitcoin/txbuilder'
|
|
12
|
+
require_relative 'sibit/blockchain'
|
|
13
|
+
require_relative 'sibit/version'
|
|
14
|
+
|
|
14
15
|
# Sibit main class.
|
|
15
16
|
#
|
|
16
17
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
@@ -178,17 +179,14 @@ class Sibit
|
|
|
178
179
|
raise Error, "The max number must be above zero: #{max}" if max < 1
|
|
179
180
|
block = start
|
|
180
181
|
count = 0
|
|
181
|
-
wrong = []
|
|
182
182
|
json = {}
|
|
183
183
|
loop do
|
|
184
184
|
json = @api.block(block)
|
|
185
185
|
if json[:orphan]
|
|
186
186
|
steps = 4
|
|
187
187
|
@log.info("Orphan block found at #{block}, moving #{steps} steps back...")
|
|
188
|
-
wrong << block
|
|
189
188
|
steps.times do
|
|
190
189
|
block = json[:previous]
|
|
191
|
-
wrong << block
|
|
192
190
|
@log.info("Moved back to #{block}")
|
|
193
191
|
json = @api.block(block)
|
|
194
192
|
end
|
|
@@ -225,7 +223,7 @@ in block #{block} (by #{json[:provider]})")
|
|
|
225
223
|
@log.info("The block #{json[:hash]} is definitely the end of Blockchain, we stop.")
|
|
226
224
|
break
|
|
227
225
|
end
|
|
228
|
-
if count
|
|
226
|
+
if count >= max
|
|
229
227
|
@log.info("Too many blocks (#{count}) in one go, let's get back to it next time")
|
|
230
228
|
break
|
|
231
229
|
end
|
|
@@ -263,9 +261,9 @@ in block #{block} (by #{json[:provider]})")
|
|
|
263
261
|
return fee.to_i if fee.is_a?(Integer)
|
|
264
262
|
raise Error, 'Fee should either be a String or Integer' unless fee.is_a?(String)
|
|
265
263
|
mul = 1
|
|
266
|
-
if fee.
|
|
267
|
-
mul = -1 if fee.
|
|
268
|
-
fee = fee[
|
|
264
|
+
if fee.end_with?('+', '-')
|
|
265
|
+
mul = -1 if fee.end_with?('-')
|
|
266
|
+
fee = fee[0..-2]
|
|
269
267
|
end
|
|
270
268
|
sat = fees[fee.to_sym]
|
|
271
269
|
raise Error, "Can't understand the fee: #{fee.inspect}" if sat.nil?
|