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.
data/lib/sibit/btc.rb CHANGED
@@ -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
 
@@ -19,171 +19,168 @@ require_relative 'version'
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
- # Btc.com API.
24
- class Btc
25
- # Constructor.
26
- def initialize(log: Loog::NULL, http: Sibit::Http.new, dry: false)
27
- @http = http
28
- @log = log
29
- @dry = dry
30
- end
22
+ class Sibit::Btc
23
+ # Constructor.
24
+ def initialize(log: Loog::NULL, http: Sibit::Http.new, dry: false)
25
+ @http = http
26
+ @log = log
27
+ @dry = dry
28
+ end
31
29
 
32
- # Current price of BTC in USD (float returned).
33
- def price(_currency = 'USD')
34
- raise Sibit::NotSupportedError, 'Btc.com API doesn\'t provide prices'
35
- end
30
+ # Current price of BTC in USD (float returned).
31
+ def price(_currency = 'USD')
32
+ raise Sibit::NotSupportedError, 'Btc.com API doesn\'t provide prices'
33
+ end
36
34
 
37
- # Gets the balance of the address, in satoshi.
38
- def balance(address)
39
- uri = Iri.new('https://chain.api.btc.com/v3/address').append(address).append('unspent')
40
- json = Sibit::Json.new(http: @http, log: @log).get(uri)
41
- if json['err_no'] == 1
42
- @log.info("The balance of #{address} is zero (not found)")
43
- return 0
44
- end
45
- data = json['data']
46
- if data.nil?
47
- @log.info("The balance of #{address} is probably zero (not found)")
48
- return 0
49
- end
50
- txns = data['list']
51
- if txns.nil?
52
- @log.info("The balance of #{address} is probably zero (not found)")
53
- return 0
54
- end
55
- balance = txns.sum { |tx| tx['value'] } || 0
56
- @log.info("The balance of #{address} is #{balance}, total txns: #{txns.count}")
57
- balance
35
+ # Gets the balance of the address, in satoshi.
36
+ def balance(address)
37
+ uri = Iri.new('https://chain.api.btc.com/v3/address').append(address).append('unspent')
38
+ json = Sibit::Json.new(http: @http, log: @log).get(uri)
39
+ if json['err_no'] == 1
40
+ @log.info("The balance of #{address} is zero (not found)")
41
+ return 0
58
42
  end
59
-
60
- # Get hash of the block after this one, or NIL if it's the last one in Blockchain.
61
- def next_of(hash)
62
- head = Sibit::Json.new(http: @http, log: @log).get(
63
- Iri.new('https://chain.api.btc.com/v3/block').append(hash)
64
- )
65
- data = head['data']
66
- raise Sibit::Error, "The block #{hash} not found" if data.nil?
67
- nxt = data['next_block_hash']
68
- nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
69
- @log.info("In BTC.com the block #{hash} is the latest, there is no next block") if nxt.nil?
70
- @log.info("The next block of #{hash} is #{nxt}") unless nxt.nil?
71
- nxt
43
+ data = json['data']
44
+ if data.nil?
45
+ @log.info("The balance of #{address} is probably zero (not found)")
46
+ return 0
72
47
  end
73
-
74
- # The height of the block.
75
- def height(hash)
76
- json = Sibit::Json.new(http: @http, log: @log).get(
77
- Iri.new('https://chain.api.btc.com/v3/block').append(hash)
78
- )
79
- data = json['data']
80
- raise Sibit::Error, "The block #{hash} not found" if data.nil?
81
- h = data['height']
82
- raise Sibit::Error, "The block #{hash} found but the height is absent" if h.nil?
83
- @log.info("The height of #{hash} is #{h}")
84
- h
48
+ txns = data['list']
49
+ if txns.nil?
50
+ @log.info("The balance of #{address} is probably zero (not found)")
51
+ return 0
85
52
  end
53
+ balance = txns.sum { |tx| tx['value'] } || 0
54
+ @log.info("The balance of #{address} is #{balance}, total txns: #{txns.count}")
55
+ balance
56
+ end
86
57
 
87
- # Get recommended fees, in satoshi per byte.
88
- def fees
89
- raise Sibit::NotSupportedError, 'Btc.com doesn\'t provide recommended fees'
90
- end
58
+ # Get hash of the block after this one, or NIL if it's the last one in Blockchain.
59
+ def next_of(hash)
60
+ head = Sibit::Json.new(http: @http, log: @log).get(
61
+ Iri.new('https://chain.api.btc.com/v3/block').append(hash)
62
+ )
63
+ data = head['data']
64
+ raise Sibit::Error, "The block #{hash} not found" if data.nil?
65
+ nxt = data['next_block_hash']
66
+ nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
67
+ @log.info("In BTC.com the block #{hash} is the latest, there is no next block") if nxt.nil?
68
+ @log.info("The next block of #{hash} is #{nxt}") unless nxt.nil?
69
+ nxt
70
+ end
91
71
 
92
- # Gets the hash of the latest block.
93
- def latest
94
- uri = Iri.new('https://chain.api.btc.com/v3/block/latest')
95
- json = Sibit::Json.new(http: @http, log: @log).get(uri)
96
- data = json['data']
97
- raise Sibit::Error, 'The latest block not found' if data.nil?
98
- hash = data['hash']
99
- @log.info("The hash of the latest block is #{hash}")
100
- hash
101
- end
72
+ # The height of the block.
73
+ def height(hash)
74
+ json = Sibit::Json.new(http: @http, log: @log).get(
75
+ Iri.new('https://chain.api.btc.com/v3/block').append(hash)
76
+ )
77
+ data = json['data']
78
+ raise Sibit::Error, "The block #{hash} not found" if data.nil?
79
+ h = data['height']
80
+ raise Sibit::Error, "The block #{hash} found but the height is absent" if h.nil?
81
+ @log.info("The height of #{hash} is #{h}")
82
+ h
83
+ end
102
84
 
103
- # Fetch all unspent outputs per address.
104
- def utxos(sources)
105
- txns = []
106
- sources.each do |hash|
107
- json = Sibit::Json.new(http: @http, log: @log).get(
108
- Iri.new('https://chain.api.btc.com/v3/address').append(hash).append('unspent')
109
- )
110
- data = json['data']
111
- raise Sibit::Error, "The address #{hash} not found" if data.nil?
112
- txns = data['list']
113
- next if txns.nil?
114
- txns.each do |u|
115
- outs = Sibit::Json.new(http: @http, log: @log).get(
116
- Iri.new('https://chain.api.btc.com/v3/tx').append(u['tx_hash']).add(verbose: 3)
117
- )['data']['outputs']
118
- outs.each_with_index do |o, i|
119
- next unless o['addresses'].include?(hash)
120
- txns << {
121
- value: o['value'],
122
- hash: u['tx_hash'],
123
- index: i,
124
- confirmations: u['confirmations'],
125
- script: [o['script_hex']].pack('H*')
126
- }
127
- end
85
+ # Get recommended fees, in satoshi per byte.
86
+ def fees
87
+ raise Sibit::NotSupportedError, 'Btc.com doesn\'t provide recommended fees'
88
+ end
89
+
90
+ # Gets the hash of the latest block.
91
+ def latest
92
+ uri = Iri.new('https://chain.api.btc.com/v3/block/latest')
93
+ json = Sibit::Json.new(http: @http, log: @log).get(uri)
94
+ data = json['data']
95
+ raise Sibit::Error, 'The latest block not found' if data.nil?
96
+ hash = data['hash']
97
+ @log.info("The hash of the latest block is #{hash}")
98
+ hash
99
+ end
100
+
101
+ # Fetch all unspent outputs per address.
102
+ def utxos(sources)
103
+ txns = []
104
+ sources.each do |hash|
105
+ json = Sibit::Json.new(http: @http, log: @log).get(
106
+ Iri.new('https://chain.api.btc.com/v3/address').append(hash).append('unspent')
107
+ )
108
+ data = json['data']
109
+ raise Sibit::Error, "The address #{hash} not found" if data.nil?
110
+ txns = data['list']
111
+ next if txns.nil?
112
+ txns.each do |u|
113
+ outs = Sibit::Json.new(http: @http, log: @log).get(
114
+ Iri.new('https://chain.api.btc.com/v3/tx').append(u['tx_hash']).add(verbose: 3)
115
+ )['data']['outputs']
116
+ outs.each_with_index do |o, i|
117
+ next unless o['addresses'].include?(hash)
118
+ txns << {
119
+ value: o['value'],
120
+ hash: u['tx_hash'],
121
+ index: i,
122
+ confirmations: u['confirmations'],
123
+ script: [o['script_hex']].pack('H*')
124
+ }
128
125
  end
129
126
  end
130
- txns
131
127
  end
128
+ txns
129
+ end
132
130
 
133
- # Push this transaction (in hex format) to the network.
134
- def push(_hex)
135
- raise Sibit::NotSupportedError, 'Btc.com doesn\'t provide payment gateway'
136
- end
131
+ # Push this transaction (in hex format) to the network.
132
+ def push(_hex)
133
+ raise Sibit::NotSupportedError, 'Btc.com doesn\'t provide payment gateway'
134
+ end
137
135
 
138
- # This method should fetch a Blockchain block and return as a hash.
139
- def block(hash)
140
- head = Sibit::Json.new(http: @http, log: @log).get(
141
- Iri.new('https://chain.api.btc.com/v3/block').append(hash)
142
- )
143
- data = head['data']
144
- raise Sibit::Error, "The block #{hash} not found" if data.nil?
145
- nxt = data['next_block_hash']
146
- nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
147
- {
148
- provider: self.class.name,
149
- hash: data['hash'],
150
- orphan: data['is_orphan'],
151
- next: nxt,
152
- previous: data['prev_block_hash'],
153
- txns: txns(hash)
154
- }
155
- end
136
+ # This method should fetch a Blockchain block and return as a hash.
137
+ def block(hash)
138
+ head = Sibit::Json.new(http: @http, log: @log).get(
139
+ Iri.new('https://chain.api.btc.com/v3/block').append(hash)
140
+ )
141
+ data = head['data']
142
+ raise Sibit::Error, "The block #{hash} not found" if data.nil?
143
+ nxt = data['next_block_hash']
144
+ nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
145
+ {
146
+ provider: self.class.name,
147
+ hash: data['hash'],
148
+ orphan: data['is_orphan'],
149
+ next: nxt,
150
+ previous: data['prev_block_hash'],
151
+ txns: txns(hash)
152
+ }
153
+ end
156
154
 
157
- private
155
+ private
158
156
 
159
- def txns(hash)
160
- page = 1
161
- psize = 50
162
- all = []
163
- loop do
164
- data = Sibit::Json.new(http: @http, log: @log).get(
165
- Iri.new('https://chain.api.btc.com/v3/block')
166
- .append(hash).append('tx').add(page: page, pagesize: psize)
167
- )['data']
168
- raise Sibit::Error, "The block #{hash} has no data at page #{page}" if data.nil?
169
- list = data['list']
170
- raise Sibit::Error, "The list is empty for block #{hash} at page #{page}" if list.nil?
171
- txns = list.map do |t|
172
- {
173
- hash: t['hash'],
174
- outputs: t['outputs'].reject { |o| o['spent_by_tx'] }.map do |o|
175
- {
176
- address: o['addresses'][0],
177
- value: o['value']
178
- }
179
- end
180
- }
181
- end
182
- all += txns
183
- page += 1
184
- break if txns.length < psize
157
+ def txns(hash)
158
+ page = 1
159
+ psize = 50
160
+ all = []
161
+ loop do
162
+ data = Sibit::Json.new(http: @http, log: @log).get(
163
+ Iri.new('https://chain.api.btc.com/v3/block')
164
+ .append(hash).append('tx').add(page: page, pagesize: psize)
165
+ )['data']
166
+ raise Sibit::Error, "The block #{hash} has no data at page #{page}" if data.nil?
167
+ list = data['list']
168
+ raise Sibit::Error, "The list is empty for block #{hash} at page #{page}" if list.nil?
169
+ txns = list.map do |t|
170
+ {
171
+ hash: t['hash'],
172
+ outputs: t['outputs'].reject { |o| o['spent_by_tx'] }.map do |o|
173
+ {
174
+ address: o['addresses'][0],
175
+ value: o['value']
176
+ }
177
+ end
178
+ }
185
179
  end
186
- all
180
+ all += txns
181
+ page += 1
182
+ break if txns.length < psize
187
183
  end
184
+ all
188
185
  end
189
186
  end
data/lib/sibit/cex.rb CHANGED
@@ -3,9 +3,10 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2019-2025 Yegor Bugayenko
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
- require 'uri'
6
+ require 'iri'
7
7
  require 'json'
8
8
  require 'loog'
9
+ require 'uri'
9
10
  require_relative 'error'
10
11
  require_relative 'http'
11
12
  require_relative 'json'
@@ -15,63 +16,61 @@ require_relative 'json'
15
16
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
16
17
  # Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
17
18
  # License:: MIT
18
- class Sibit
19
- # Btc.com API.
20
- class Cex
21
- # Constructor.
22
- def initialize(log: Loog::NULL, http: Sibit::Http.new, dry: false)
23
- @http = http
24
- @log = log
25
- @dry = dry
26
- end
19
+ class Sibit::Cex
20
+ # Constructor.
21
+ def initialize(log: Loog::NULL, http: Sibit::Http.new, dry: false)
22
+ @http = http
23
+ @log = log
24
+ @dry = dry
25
+ end
27
26
 
28
- # Current price of BTC in USD (float returned).
29
- def price(currency = 'USD')
30
- json = Sibit::Json.new(http: @http, log: @log).get(
31
- Iri.new('https://cex.io/api/last_price/BTC').append(currency)
32
- )
33
- p = json['lprice'].to_f
34
- @log.info("The price of BTC is #{p} #{currency}")
35
- p
36
- end
27
+ # Current price of BTC in USD (float returned).
28
+ def price(currency = 'USD')
29
+ json = Sibit::Json.new(http: @http, log: @log).get(
30
+ Iri.new('https://cex.io/api/last_price/BTC').append(currency)
31
+ )
32
+ p = json['lprice'].to_f
33
+ @log.info("The price of BTC is #{p} #{currency}")
34
+ p
35
+ end
37
36
 
38
- # Get hash of the block after this one.
39
- def next_of(_hash)
40
- raise Sibit::NotSupportedError, 'Cex.io API doesn\'t provide next_of()'
41
- end
37
+ # Get hash of the block after this one.
38
+ def next_of(_hash)
39
+ raise Sibit::NotSupportedError, 'Cex.io API doesn\'t provide next_of()'
40
+ end
42
41
 
43
- # Gets the balance of the address, in satoshi.
44
- def balance(_address)
45
- raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement balance()'
46
- end
42
+ # Gets the balance of the address, in satoshi.
43
+ def balance(_address)
44
+ raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement balance()'
45
+ end
47
46
 
48
- # The height of the block.
49
- def height(_hash)
50
- raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement height()'
51
- end
47
+ # The height of the block.
48
+ def height(_hash)
49
+ raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement height()'
50
+ end
52
51
 
53
- # Get recommended fees, in satoshi per byte.
54
- def fees
55
- raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement fees()'
56
- end
52
+ # Get recommended fees, in satoshi per byte.
53
+ def fees
54
+ raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement fees()'
55
+ end
57
56
 
58
- # Gets the hash of the latest block.
59
- def latest
60
- raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement latest()'
61
- end
57
+ # Gets the hash of the latest block.
58
+ def latest
59
+ raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement latest()'
60
+ end
62
61
 
63
- # Fetch all unspent outputs per address.
64
- def utxos(_sources)
65
- raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement utxos()'
66
- end
62
+ # Fetch all unspent outputs per address.
63
+ def utxos(_sources)
64
+ raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement utxos()'
65
+ end
67
66
 
68
- # Push this transaction (in hex format) to the network.
69
- def push(_hex)
70
- raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement push()'
71
- end
67
+ # Push this transaction (in hex format) to the network.
68
+ def push(_hex)
69
+ raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement push()'
70
+ end
72
71
 
73
- def block(_hash)
74
- raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement block()'
75
- end
72
+ # This method should fetch a Blockchain block and return as a hash.
73
+ def block(_hash)
74
+ raise Sibit::NotSupportedError, 'Cex.io doesn\'t implement block()'
76
75
  end
77
76
  end