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.
@@ -5,10 +5,10 @@
5
5
 
6
6
  require 'iri'
7
7
  require 'json'
8
+ require 'loog'
8
9
  require 'uri'
9
10
  require_relative 'error'
10
11
  require_relative 'http'
11
- require 'loog'
12
12
  require_relative 'json'
13
13
  require_relative 'version'
14
14
 
@@ -17,134 +17,131 @@ require_relative 'version'
17
17
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
18
18
  # Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
19
19
  # License:: MIT
20
- class Sibit
21
- # Btc.com API.
22
- class Cryptoapis
23
- # Constructor.
24
- def initialize(key, log: Loog::NULL, http: Sibit::Http.new, dry: false)
25
- @key = key
26
- @http = http
27
- @log = log
28
- @dry = dry
29
- end
20
+ class Sibit::Cryptoapis
21
+ # Constructor.
22
+ def initialize(key, log: Loog::NULL, http: Sibit::Http.new, dry: false)
23
+ @key = key
24
+ @http = http
25
+ @log = log
26
+ @dry = dry
27
+ end
30
28
 
31
- # Current price of BTC in USD (float returned).
32
- def price(_currency = 'USD')
33
- raise Sibit::NotSupportedError, 'Cryptoapis doesn\'t provide BTC price'
34
- end
29
+ # Current price of BTC in USD (float returned).
30
+ def price(_currency = 'USD')
31
+ raise Sibit::NotSupportedError, 'Cryptoapis doesn\'t provide BTC price'
32
+ end
35
33
 
36
- # Get hash of the block after this one.
37
- def next_of(hash)
38
- nxt = Sibit::Json.new(http: @http, log: @log).get(
39
- Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks').append(hash),
40
- headers: headers
41
- )['payload']['hash']
42
- @log.info("The block #{hash} is the latest, there is no next block") if nxt.nil?
43
- @log.info("The next block of #{hash} is #{nxt}") unless nxt.nil?
44
- nxt
45
- end
34
+ # Get hash of the block after this one.
35
+ def next_of(hash)
36
+ nxt = Sibit::Json.new(http: @http, log: @log).get(
37
+ Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks').append(hash),
38
+ headers: headers
39
+ )['payload']['hash']
40
+ @log.info("The block #{hash} is the latest, there is no next block") if nxt.nil?
41
+ @log.info("The next block of #{hash} is #{nxt}") unless nxt.nil?
42
+ nxt
43
+ end
46
44
 
47
- # The height of the block.
48
- def height(hash)
49
- json = Sibit::Json.new(http: @http, log: @log).get(
50
- Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks').append(hash),
51
- headers: headers
52
- )['payload']
53
- h = json['height']
54
- @log.info("The height of #{hash} is #{h}")
55
- h
56
- end
45
+ # The height of the block.
46
+ def height(hash)
47
+ json = Sibit::Json.new(http: @http, log: @log).get(
48
+ Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks').append(hash),
49
+ headers: headers
50
+ )['payload']
51
+ h = json['height']
52
+ @log.info("The height of #{hash} is #{h}")
53
+ h
54
+ end
57
55
 
58
- # Gets the balance of the address, in satoshi.
59
- def balance(address)
60
- json = Sibit::Json.new(http: @http, log: @log).get(
61
- Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/address').append(address),
62
- headers: headers
63
- )['payload']
64
- b = (json['balance'].to_f * 100_000_000).to_i
65
- @log.info("The balance of #{address} is #{b} satoshi")
66
- b
67
- end
56
+ # Gets the balance of the address, in satoshi.
57
+ def balance(address)
58
+ json = Sibit::Json.new(http: @http, log: @log).get(
59
+ Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/address').append(address),
60
+ headers: headers
61
+ )['payload']
62
+ b = (json['balance'].to_f * 100_000_000).to_i
63
+ @log.info("The balance of #{address} is #{b} satoshi")
64
+ b
65
+ end
68
66
 
69
- # Get recommended fees, in satoshi per byte.
70
- def fees
71
- raise Sibit::NotSupportedError, 'Cryptoapis doesn\'t provide recommended fees'
72
- end
67
+ # Get recommended fees, in satoshi per byte.
68
+ def fees
69
+ raise Sibit::NotSupportedError, 'Cryptoapis doesn\'t provide recommended fees'
70
+ end
73
71
 
74
- # Gets the hash of the latest block.
75
- def latest
76
- hash = Sibit::Json.new(http: @http, log: @log).get(
77
- Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks/latest'),
78
- headers: headers
79
- )['payload']['hash']
80
- @log.info("The latest block hash is #{hash}")
81
- hash
82
- end
72
+ # Gets the hash of the latest block.
73
+ def latest
74
+ hash = Sibit::Json.new(http: @http, log: @log).get(
75
+ Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks/latest'),
76
+ headers: headers
77
+ )['payload']['hash']
78
+ @log.info("The latest block hash is #{hash}")
79
+ hash
80
+ end
83
81
 
84
- # Fetch all unspent outputs per address.
85
- def utxos(_sources)
86
- raise Sibit::NotSupportedError, 'Not implemented yet'
87
- end
82
+ # Fetch all unspent outputs per address.
83
+ def utxos(_sources)
84
+ raise Sibit::NotSupportedError, 'Not implemented yet'
85
+ end
88
86
 
89
- # Push this transaction (in hex format) to the network.
90
- def push(hex)
91
- Sibit::Json.new(http: @http, log: @log).post(
92
- Iri.new('https://api.cryptoapis.io/v1/bc/btc/testnet/txs/send'),
93
- JSON.pretty_generate(hex: hex),
94
- headers: headers
95
- )
96
- end
87
+ # Push this transaction (in hex format) to the network.
88
+ def push(hex)
89
+ Sibit::Json.new(http: @http, log: @log).post(
90
+ Iri.new('https://api.cryptoapis.io/v1/bc/btc/testnet/txs/send'),
91
+ JSON.pretty_generate(hex: hex),
92
+ headers: headers
93
+ )
94
+ end
97
95
 
98
- # This method should fetch a Blockchain block and return as a hash.
99
- def block(hash)
100
- head = Sibit::Json.new(http: @http, log: @log).get(
101
- Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks').append(hash),
102
- headers: headers
103
- )['payload']
104
- {
105
- provider: self.class.name,
106
- hash: head['hash'],
107
- orphan: false,
108
- next: head['nextblockhash'],
109
- previous: head['previousblockhash'],
110
- txns: txns(hash)
111
- }
112
- end
96
+ # This method should fetch a Blockchain block and return as a hash.
97
+ def block(hash)
98
+ head = Sibit::Json.new(http: @http, log: @log).get(
99
+ Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/blocks').append(hash),
100
+ headers: headers
101
+ )['payload']
102
+ {
103
+ provider: self.class.name,
104
+ hash: head['hash'],
105
+ orphan: false,
106
+ next: head['nextblockhash'],
107
+ previous: head['previousblockhash'],
108
+ txns: txns(hash)
109
+ }
110
+ end
113
111
 
114
- private
112
+ private
115
113
 
116
- def headers
117
- return {} if @key.nil? || @key.empty?
118
- {
119
- 'X-API-Key': @key
120
- }
121
- end
114
+ def headers
115
+ return {} if @key.nil? || @key.empty?
116
+ {
117
+ 'X-API-Key': @key
118
+ }
119
+ end
122
120
 
123
- def txns(hash)
124
- index = 0
125
- limit = 200
126
- all = []
127
- loop do
128
- txns = Sibit::Json.new(http: @http, log: @log).get(
129
- Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/txs/block/')
130
- .append(hash).add(index: index, limit: limit),
131
- headers: headers
132
- )['payload'].map do |t|
133
- {
134
- hash: t['hash'],
135
- outputs: t['txouts'].map do |o|
136
- {
137
- address: o['addresses'][0],
138
- value: o['amount'].to_f * 100_000_000
139
- }
140
- end
141
- }
142
- end
143
- all += txns
144
- index += txns.length
145
- break if txns.length < limit
121
+ def txns(hash)
122
+ index = 0
123
+ limit = 200
124
+ all = []
125
+ loop do
126
+ txns = Sibit::Json.new(http: @http, log: @log).get(
127
+ Iri.new('https://api.cryptoapis.io/v1/bc/btc/mainnet/txs/block/')
128
+ .append(hash).add(index: index, limit: limit),
129
+ headers: headers
130
+ )['payload'].map do |t|
131
+ {
132
+ hash: t['hash'],
133
+ outputs: t['txouts'].map do |o|
134
+ {
135
+ address: o['addresses'][0],
136
+ value: o['amount'].to_f * 100_000_000
137
+ }
138
+ end
139
+ }
146
140
  end
147
- all
141
+ all += txns
142
+ index += txns.length
143
+ break if txns.length < limit
148
144
  end
145
+ all
149
146
  end
150
147
  end
data/lib/sibit/fake.rb CHANGED
@@ -10,60 +10,55 @@ require_relative 'version'
10
10
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
11
  # Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
12
12
  # License:: MIT
13
- class Sibit
14
- # Fake API
15
- class Fake
16
- def price(_cur = 'USD')
17
- 4_000
18
- end
13
+ class Sibit::Fake
14
+ def price(_cur = 'USD')
15
+ 4_000
16
+ end
19
17
 
20
- def next_of(_hash)
21
- nil
22
- end
18
+ def next_of(_hash)
19
+ nil
20
+ end
23
21
 
24
- def height(_hash)
25
- 1
26
- end
22
+ def height(_hash)
23
+ 1
24
+ end
27
25
 
28
- def fees
29
- { S: 12, M: 45, L: 100, XL: 200 }
30
- end
26
+ def fees
27
+ { S: 12, M: 45, L: 100, XL: 200 }
28
+ end
31
29
 
32
- def balance(_address)
33
- 100_000_000
34
- end
30
+ def balance(_address)
31
+ 100_000_000
32
+ end
35
33
 
36
- def utxos(_sources)
37
- []
38
- end
34
+ def utxos(_sources)
35
+ []
36
+ end
39
37
 
40
- def push(hex)
41
- # Nothing to do here
42
- end
38
+ def push(_hex); end
43
39
 
44
- def latest
45
- '00000000000000000008df8a6e1b61d1136803ac9791b8725235c9f780b4ed71'
46
- end
40
+ def latest
41
+ '00000000000000000008df8a6e1b61d1136803ac9791b8725235c9f780b4ed71'
42
+ end
47
43
 
48
- def block(hash)
49
- {
50
- provider: self.class.name,
51
- hash: hash,
52
- orphan: false,
53
- next: hash,
54
- previous: hash,
55
- txns: [
56
- {
57
- hash: hash,
58
- outputs: [
59
- {
60
- address: '1HqhZx8U18TYS5paraTM1MzUQWb7ZbcG9u',
61
- value: 1000
62
- }
63
- ]
64
- }
65
- ]
66
- }
67
- end
44
+ def block(hash)
45
+ {
46
+ provider: self.class.name,
47
+ hash: hash,
48
+ orphan: false,
49
+ next: hash,
50
+ previous: hash,
51
+ txns: [
52
+ {
53
+ hash: hash,
54
+ outputs: [
55
+ {
56
+ address: '1HqhZx8U18TYS5paraTM1MzUQWb7ZbcG9u',
57
+ value: 1000
58
+ }
59
+ ]
60
+ }
61
+ ]
62
+ }
68
63
  end
69
64
  end
data/lib/sibit/firstof.rb CHANGED
@@ -12,102 +12,99 @@ require_relative 'error'
12
12
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
13
13
  # Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
14
14
  # License:: MIT
15
- class Sibit
16
- # First of API.
17
- class FirstOf
18
- # Constructor.
19
- def initialize(list, log: Loog::NULL, verbose: false)
20
- @list = list
21
- @log = log
22
- @verbose = verbose
23
- end
15
+ class Sibit::FirstOf
16
+ # Constructor.
17
+ def initialize(list, log: Loog::NULL, verbose: false)
18
+ @list = list
19
+ @log = log
20
+ @verbose = verbose
21
+ end
24
22
 
25
- # Current price of BTC in USD (float returned).
26
- def price(currency = 'USD')
27
- first_of('price') do |api|
28
- api.price(currency)
29
- end
23
+ # Current price of BTC in USD (float returned).
24
+ def price(currency = 'USD')
25
+ first_of('price') do |api|
26
+ api.price(currency)
30
27
  end
28
+ end
31
29
 
32
- # Gets the balance of the address, in satoshi.
33
- def balance(address)
34
- first_of('balance') do |api|
35
- api.balance(address)
36
- end
30
+ # Gets the balance of the address, in satoshi.
31
+ def balance(address)
32
+ first_of('balance') do |api|
33
+ api.balance(address)
37
34
  end
35
+ end
38
36
 
39
- # Get the height of the block.
40
- def height(hash)
41
- first_of('height') do |api|
42
- api.height(hash)
43
- end
37
+ # Get the height of the block.
38
+ def height(hash)
39
+ first_of('height') do |api|
40
+ api.height(hash)
44
41
  end
42
+ end
45
43
 
46
- # Get the hash of the next block.
47
- def next_of(hash)
48
- first_of('next_of') do |api|
49
- api.next_of(hash)
50
- end
44
+ # Get the hash of the next block.
45
+ def next_of(hash)
46
+ first_of('next_of') do |api|
47
+ api.next_of(hash)
51
48
  end
49
+ end
52
50
 
53
- # Get recommended fees, in satoshi per byte. The method returns
54
- # a hash: { S: 12, M: 45, L: 100, XL: 200 }
55
- def fees
56
- first_of('fees', &:fees)
57
- end
51
+ # Get recommended fees, in satoshi per byte. The method returns
52
+ # a hash: { S: 12, M: 45, L: 100, XL: 200 }
53
+ def fees
54
+ first_of('fees', &:fees)
55
+ end
58
56
 
59
- # Fetch all unspent outputs per address.
60
- def utxos(keys)
61
- first_of('utxos') do |api|
62
- api.utxos(keys)
63
- end
57
+ # Fetch all unspent outputs per address.
58
+ def utxos(keys)
59
+ first_of('utxos') do |api|
60
+ api.utxos(keys)
64
61
  end
62
+ end
65
63
 
66
- # Latest block hash.
67
- def latest
68
- first_of('latest', &:latest)
69
- end
64
+ # Latest block hash.
65
+ def latest
66
+ first_of('latest', &:latest)
67
+ end
70
68
 
71
- # Push this transaction (in hex format) to the network.
72
- def push(hex)
73
- first_of('push') do |api|
74
- api.push(hex)
75
- end
69
+ # Push this transaction (in hex format) to the network.
70
+ def push(hex)
71
+ first_of('push') do |api|
72
+ api.push(hex)
76
73
  end
74
+ end
77
75
 
78
- # This method should fetch a block and return as a hash.
79
- def block(hash)
80
- first_of('block') do |api|
81
- api.block(hash)
82
- end
76
+ # This method should fetch a block and return as a hash.
77
+ def block(hash)
78
+ first_of('block') do |api|
79
+ api.block(hash)
83
80
  end
81
+ end
84
82
 
85
- private
83
+ private
86
84
 
87
- def first_of(method)
88
- return yield @list unless @list.is_a?(Array)
89
- errors = []
90
- done = false
91
- result = nil
92
- @list.each do |api|
93
- @log.info("Calling #{api.class.name}##{method}()...")
94
- begin
95
- result = yield api
96
- done = true
97
- break
98
- rescue Sibit::NotSupportedError
99
- # Just ignore it
100
- rescue Sibit::Error => e
101
- errors << e
102
- @log.info("The API #{api.class.name} failed at #{method}(): #{e.message}") if @verbose
103
- end
85
+ def first_of(method)
86
+ return yield @list unless @list.is_a?(Array)
87
+ errors = []
88
+ done = false
89
+ result = nil
90
+ @list.each do |api|
91
+ @log.info("Calling #{api.class.name}##{method}()...")
92
+ begin
93
+ result = yield api
94
+ done = true
95
+ break
96
+ rescue Sibit::NotSupportedError
97
+ # Just ignore it
98
+ rescue Sibit::Error => e
99
+ errors << e
100
+ @log.info("The API #{api.class.name} failed at #{method}(): #{e.message}") if @verbose
104
101
  end
105
- unless done
106
- errors.each { |e| @log.info(Backtrace.new(e).to_s) }
107
- raise Sibit::Error, "No APIs out of #{@list.length} managed to succeed at #{method}(): \
102
+ end
103
+ unless done
104
+ errors.each { |e| @log.info(Backtrace.new(e).to_s) }
105
+ raise Sibit::Error, "No APIs out of #{@list.length} managed to succeed at #{method}(): \
108
106
  #{@list.map { |a| a.class.name }.join(', ')}"
109
- end
110
- result
111
107
  end
108
+ result
112
109
  end
113
110
  end
data/lib/sibit/http.rb CHANGED
@@ -10,28 +10,25 @@ require 'net/http'
10
10
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
11
  # Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
12
12
  # License:: MIT
13
- class Sibit
14
- # This HTTP client will be used by default.
15
- class Http
16
- def client(uri)
17
- http = Net::HTTP.new(uri.host, uri.port)
18
- http.use_ssl = true
19
- http.read_timeout = 240
20
- http
21
- end
13
+ class Sibit::Http
14
+ def client(uri)
15
+ http = Net::HTTP.new(uri.host, uri.port)
16
+ http.use_ssl = true
17
+ http.read_timeout = 240
18
+ http
22
19
  end
20
+ end
23
21
 
24
- # This HTTP client with proxy.
25
- class HttpProxy
26
- def initialize(addr)
27
- @host, @port = addr.split(':')
28
- end
22
+ # This HTTP client with proxy.
23
+ class HttpProxy
24
+ def initialize(addr)
25
+ @host, @port = addr.split(':')
26
+ end
29
27
 
30
- def client(uri)
31
- http = Net::HTTP.new(uri.host, uri.port, @host, @port.to_i)
32
- http.use_ssl = true
33
- http.read_timeout = 240
34
- http
35
- end
28
+ def client(uri)
29
+ http = Net::HTTP.new(uri.host, uri.port, @host, @port.to_i)
30
+ http.use_ssl = true
31
+ http.read_timeout = 240
32
+ http
36
33
  end
37
34
  end