sibit 0.28.0 → 0.29.1
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 +2 -0
- data/Gemfile.lock +15 -3
- data/README.md +14 -17
- data/Rakefile +16 -3
- data/bin/sibit +1 -4
- data/features/cli.feature +1 -1
- data/features/dry.feature +25 -0
- data/lib/sibit/bestof.rb +68 -71
- data/lib/sibit/bitcoin/base58.rb +32 -33
- data/lib/sibit/bitcoin/key.rb +64 -65
- data/lib/sibit/bitcoin/script.rb +45 -46
- data/lib/sibit/bitcoin/tx.rb +153 -144
- data/lib/sibit/bitcoin/txbuilder.rb +65 -54
- 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 +50 -47
- data/lib/sibit/firstof.rb +73 -76
- data/lib/sibit/http.rb +10 -6
- data/lib/sibit/json.rb +63 -66
- data/lib/sibit/version.rb +1 -1
- data/lib/sibit.rb +18 -18
- metadata +2 -1
data/lib/sibit/bitcoinchain.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
|
|
|
@@ -17,110 +17,107 @@ 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
|
-
#
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@dry = dry
|
|
28
|
-
end
|
|
20
|
+
class Sibit::Bitcoinchain
|
|
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
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
# Current price of BTC in USD (float returned).
|
|
29
|
+
def price(_currency = 'USD')
|
|
30
|
+
raise Sibit::NotSupportedError, 'Bitcoinchain API doesn\'t provide BTC price'
|
|
31
|
+
end
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
# The height of the block.
|
|
34
|
+
def height(_hash)
|
|
35
|
+
raise Sibit::NotSupportedError, 'Bitcoinchain API doesn\'t provide height()'
|
|
36
|
+
end
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
# Get hash of the block after this one.
|
|
39
|
+
def next_of(hash)
|
|
40
|
+
block = Sibit::Json.new(http: @http, log: @log).get(
|
|
41
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/block').append(hash)
|
|
42
|
+
)[0]
|
|
43
|
+
raise Sibit::Error, "Block #{hash} not found" if block.nil?
|
|
44
|
+
nxt = block['next_block']
|
|
45
|
+
nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
|
|
46
|
+
@log.info("The block #{hash} is the latest, there is no next block") if nxt.nil?
|
|
47
|
+
@log.info("The next block of #{hash} is #{nxt}") unless nxt.nil?
|
|
48
|
+
nxt
|
|
49
|
+
end
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
end
|
|
64
|
-
b *= 100_000_000
|
|
65
|
-
b = b.to_i
|
|
66
|
-
@log.info("The balance of #{address} is #{b} satoshi (#{json['transactions']} txns)")
|
|
67
|
-
b
|
|
51
|
+
# Gets the balance of the address, in satoshi.
|
|
52
|
+
def balance(address)
|
|
53
|
+
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
54
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/address').append(address),
|
|
55
|
+
accept: [200, 409]
|
|
56
|
+
)[0]
|
|
57
|
+
b = json['balance']
|
|
58
|
+
if b.nil?
|
|
59
|
+
@log.info("The balance of #{address} is not visible")
|
|
60
|
+
return 0
|
|
68
61
|
end
|
|
62
|
+
b *= 100_000_000
|
|
63
|
+
b = b.to_i
|
|
64
|
+
@log.info("The balance of #{address} is #{b} satoshi (#{json['transactions']} txns)")
|
|
65
|
+
b
|
|
66
|
+
end
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
# Get recommended fees, in satoshi per byte.
|
|
69
|
+
def fees
|
|
70
|
+
raise Sibit::NotSupportedError, 'Not implemented yet'
|
|
71
|
+
end
|
|
74
72
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
73
|
+
# Gets the hash of the latest block.
|
|
74
|
+
def latest
|
|
75
|
+
hash = Sibit::Json.new(http: @http, log: @log).get(
|
|
76
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/status')
|
|
77
|
+
)['hash']
|
|
78
|
+
@log.info("The latest block hash is #{hash}")
|
|
79
|
+
hash
|
|
80
|
+
end
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
# Fetch all unspent outputs per address.
|
|
83
|
+
def utxos(_sources)
|
|
84
|
+
raise Sibit::NotSupportedError, 'Not implemented yet'
|
|
85
|
+
end
|
|
88
86
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
# Push this transaction (in hex format) to the network.
|
|
88
|
+
def push(_hex)
|
|
89
|
+
raise Sibit::NotSupportedError, 'Not implemented yet'
|
|
90
|
+
end
|
|
93
91
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
end
|
|
92
|
+
# This method should fetch a Blockchain block and return as a hash. Raises
|
|
93
|
+
# an exception if the block is not found.
|
|
94
|
+
def block(hash)
|
|
95
|
+
head = Sibit::Json.new(http: @http, log: @log).get(
|
|
96
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/block').append(hash)
|
|
97
|
+
)[0]
|
|
98
|
+
raise Sibit::Error, "The block #{hash} is not found" if head.nil?
|
|
99
|
+
txs = Sibit::Json.new(http: @http, log: @log).get(
|
|
100
|
+
Iri.new('https://api-r.bitcoinchain.com/v1/block/txs').append(hash)
|
|
101
|
+
)
|
|
102
|
+
nxt = head['next_block']
|
|
103
|
+
nxt = nil if nxt == '0000000000000000000000000000000000000000000000000000000000000000'
|
|
104
|
+
{
|
|
105
|
+
provider: self.class.name,
|
|
106
|
+
hash: head['hash'],
|
|
107
|
+
orphan: !head['is_main'],
|
|
108
|
+
next: nxt,
|
|
109
|
+
previous: head['prev_block'],
|
|
110
|
+
txns: txs[0]['txs'].map do |t|
|
|
111
|
+
{
|
|
112
|
+
hash: t['self_hash'],
|
|
113
|
+
outputs: t['outputs'].map do |o|
|
|
114
|
+
{
|
|
115
|
+
address: o['receiver'],
|
|
116
|
+
value: o['value'] * 100_000_000
|
|
117
|
+
}
|
|
118
|
+
end
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
}
|
|
125
122
|
end
|
|
126
123
|
end
|
data/lib/sibit/blockchain.rb
CHANGED
|
@@ -20,135 +20,132 @@ require_relative 'version'
|
|
|
20
20
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
21
21
|
# Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
|
|
22
22
|
# License:: MIT
|
|
23
|
-
class Sibit
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@dry = dry
|
|
31
|
-
end
|
|
23
|
+
class Sibit::Blockchain
|
|
24
|
+
# Constructor.
|
|
25
|
+
def initialize(log: Loog::NULL, http: Sibit::Http.new, dry: false)
|
|
26
|
+
@http = http
|
|
27
|
+
@log = log
|
|
28
|
+
@dry = dry
|
|
29
|
+
end
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
# Current price of BTC in USD (float returned).
|
|
32
|
+
def price(currency = 'USD')
|
|
33
|
+
h = Sibit::Json.new(http: @http, log: @log).get(
|
|
34
|
+
Iri.new('https://blockchain.info/ticker')
|
|
35
|
+
)[currency]
|
|
36
|
+
raise Error, "Unrecognized currency #{currency}" if h.nil?
|
|
37
|
+
price = h['15m']
|
|
38
|
+
@log.info("The price of BTC is #{price} USD")
|
|
39
|
+
price
|
|
40
|
+
end
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
42
|
+
# Get hash of the block after this one.
|
|
43
|
+
def next_of(_hash)
|
|
44
|
+
raise Sibit::NotSupportedError, 'next_of() in Blockchain API is broken, always returns NULL'
|
|
45
|
+
# json = Sibit::Json.new(http: @http, log: @log).get(
|
|
46
|
+
# Iri.new('https://blockchain.info/rawblock').append(hash)
|
|
47
|
+
# )
|
|
48
|
+
# nxt = json['next_block'][0]
|
|
49
|
+
# if nxt.nil?
|
|
50
|
+
# @log.info("There is no block after #{hash}")
|
|
51
|
+
# else
|
|
52
|
+
# @log.info("The next block of #{hash} is #{nxt}")
|
|
53
|
+
# end
|
|
54
|
+
# nxt
|
|
55
|
+
end
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
57
|
+
# The height of the block.
|
|
58
|
+
def height(hash)
|
|
59
|
+
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
60
|
+
Iri.new('https://blockchain.info/rawblock').append(hash)
|
|
61
|
+
)
|
|
62
|
+
h = json['height']
|
|
63
|
+
@log.info("The height of #{hash} is #{h}")
|
|
64
|
+
h
|
|
65
|
+
end
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
67
|
+
# Gets the balance of the address, in satoshi.
|
|
68
|
+
def balance(address)
|
|
69
|
+
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
70
|
+
Iri.new('https://blockchain.info/rawaddr').append(address).add(limit: 0),
|
|
71
|
+
accept: [200, 500]
|
|
72
|
+
)
|
|
73
|
+
b = json['final_balance']
|
|
74
|
+
@log.info("The balance of #{address} is #{b} satoshi (#{json['n_tx']} txns)")
|
|
75
|
+
b
|
|
76
|
+
end
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
# Get recommended fees.
|
|
79
|
+
def fees
|
|
80
|
+
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
81
|
+
Iri.new('https://api.blockchain.info/mempool/fees')
|
|
82
|
+
)
|
|
83
|
+
@log.info("Current recommended Bitcoin fees: \
|
|
84
|
+
#{json['regular']}/#{json['priority']}/#{json['limits']['max']} sat/byte")
|
|
85
|
+
{
|
|
86
|
+
S: json['regular'] / 3,
|
|
87
|
+
M: json['regular'],
|
|
88
|
+
L: json['priority'],
|
|
89
|
+
XL: json['limits']['max']
|
|
90
|
+
}
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Fetch all unspent outputs per address. The argument is an array
|
|
94
|
+
# of Bitcoin addresses.
|
|
95
|
+
def utxos(sources)
|
|
96
|
+
Sibit::Json.new(http: @http, log: @log).get(
|
|
97
|
+
Iri.new('https://blockchain.info/unspent').add(active: sources.join('|'), limit: 1000)
|
|
98
|
+
)['unspent_outputs'].map do |u|
|
|
87
99
|
{
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
value: u['value'],
|
|
101
|
+
hash: u['tx_hash_big_endian'],
|
|
102
|
+
index: u['tx_output_n'],
|
|
103
|
+
confirmations: u['confirmations'],
|
|
104
|
+
script: [u['script']].pack('H*')
|
|
92
105
|
}
|
|
93
106
|
end
|
|
107
|
+
end
|
|
94
108
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
109
|
+
# Push this transaction (in hex format) to the network.
|
|
110
|
+
def push(hex)
|
|
111
|
+
return if @dry
|
|
112
|
+
Sibit::Json.new(http: @http, log: @log).post(
|
|
113
|
+
Iri.new('https://blockchain.info/pushtx'),
|
|
114
|
+
hex
|
|
115
|
+
)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Gets the hash of the latest block.
|
|
119
|
+
def latest
|
|
120
|
+
hash = Sibit::Json.new(http: @http, log: @log).get(
|
|
121
|
+
Iri.new('https://blockchain.info/latestblock')
|
|
122
|
+
)['hash']
|
|
123
|
+
@log.info("The latest block hash is #{hash}")
|
|
124
|
+
hash
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# This method should fetch a Blockchain block and return as a hash.
|
|
128
|
+
def block(hash)
|
|
129
|
+
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
130
|
+
Iri.new('https://blockchain.info/rawblock').append(hash)
|
|
131
|
+
)
|
|
132
|
+
{
|
|
133
|
+
provider: self.class.name,
|
|
134
|
+
hash: json['hash'],
|
|
135
|
+
orphan: !json['main_chain'],
|
|
136
|
+
next: json['next_block'][0],
|
|
137
|
+
previous: json['prev_block'],
|
|
138
|
+
txns: json['tx'].map do |t|
|
|
101
139
|
{
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
140
|
+
hash: t['hash'],
|
|
141
|
+
outputs: t['out'].map do |o|
|
|
142
|
+
{
|
|
143
|
+
address: o['addr'],
|
|
144
|
+
value: o['value']
|
|
145
|
+
}
|
|
146
|
+
end
|
|
107
147
|
}
|
|
108
148
|
end
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
# Push this transaction (in hex format) to the network.
|
|
112
|
-
def push(hex)
|
|
113
|
-
return if @dry
|
|
114
|
-
Sibit::Json.new(http: @http, log: @log).post(
|
|
115
|
-
Iri.new('https://blockchain.info/pushtx'),
|
|
116
|
-
hex
|
|
117
|
-
)
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
# Gets the hash of the latest block.
|
|
121
|
-
def latest
|
|
122
|
-
hash = Sibit::Json.new(http: @http, log: @log).get(
|
|
123
|
-
Iri.new('https://blockchain.info/latestblock')
|
|
124
|
-
)['hash']
|
|
125
|
-
@log.info("The latest block hash is #{hash}")
|
|
126
|
-
hash
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
# This method should fetch a Blockchain block and return as a hash.
|
|
130
|
-
def block(hash)
|
|
131
|
-
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
132
|
-
Iri.new('https://blockchain.info/rawblock').append(hash)
|
|
133
|
-
)
|
|
134
|
-
{
|
|
135
|
-
provider: self.class.name,
|
|
136
|
-
hash: json['hash'],
|
|
137
|
-
orphan: !json['main_chain'],
|
|
138
|
-
next: json['next_block'][0],
|
|
139
|
-
previous: json['prev_block'],
|
|
140
|
-
txns: json['tx'].map do |t|
|
|
141
|
-
{
|
|
142
|
-
hash: t['hash'],
|
|
143
|
-
outputs: t['out'].map do |o|
|
|
144
|
-
{
|
|
145
|
-
address: o['addr'],
|
|
146
|
-
value: o['value']
|
|
147
|
-
}
|
|
148
|
-
end
|
|
149
|
-
}
|
|
150
|
-
end
|
|
151
|
-
}
|
|
152
|
-
end
|
|
149
|
+
}
|
|
153
150
|
end
|
|
154
151
|
end
|
data/lib/sibit/blockchair.rb
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
require 'cgi'
|
|
7
7
|
require 'iri'
|
|
8
8
|
require 'json'
|
|
9
|
+
require 'loog'
|
|
9
10
|
require 'uri'
|
|
10
11
|
require_relative 'error'
|
|
11
12
|
require_relative 'http'
|
|
12
|
-
require 'loog'
|
|
13
13
|
require_relative 'json'
|
|
14
14
|
require_relative 'version'
|
|
15
15
|
|
|
@@ -18,81 +18,78 @@ require_relative 'version'
|
|
|
18
18
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
19
19
|
# Copyright:: Copyright (c) 2019-2025 Yegor Bugayenko
|
|
20
20
|
# License:: MIT
|
|
21
|
-
class Sibit
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@dry = dry
|
|
30
|
-
end
|
|
21
|
+
class Sibit::Blockchair
|
|
22
|
+
# Constructor.
|
|
23
|
+
def initialize(key: nil, log: Loog::NULL, http: Sibit::Http.new, dry: false)
|
|
24
|
+
@key = key
|
|
25
|
+
@http = http
|
|
26
|
+
@log = log
|
|
27
|
+
@dry = dry
|
|
28
|
+
end
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
# Current price of BTC in USD (float returned).
|
|
31
|
+
def price(_currency = 'USD')
|
|
32
|
+
raise Sibit::NotSupportedError, 'Blockchair doesn\'t provide BTC price'
|
|
33
|
+
end
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
# The height of the block.
|
|
36
|
+
def height(_hash)
|
|
37
|
+
raise Sibit::NotSupportedError, 'Blockchair API doesn\'t provide height()'
|
|
38
|
+
end
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
# Get hash of the block after this one.
|
|
41
|
+
def next_of(_hash)
|
|
42
|
+
# They don't provide next block hash
|
|
43
|
+
raise Sibit::NotSupportedError, 'Blockchair API doesn\'t provide next_of()'
|
|
44
|
+
end
|
|
47
45
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
end
|
|
57
|
-
a = json['address']
|
|
58
|
-
b = a['balance']
|
|
59
|
-
@log.info("The balance of #{address} is #{b} satoshi")
|
|
60
|
-
b
|
|
46
|
+
# Gets the balance of the address, in satoshi.
|
|
47
|
+
def balance(address)
|
|
48
|
+
json = Sibit::Json.new(http: @http, log: @log).get(
|
|
49
|
+
Iri.new('https://api.blockchair.com/bitcoin/dashboards/address').append(address).fragment(the_key)
|
|
50
|
+
)['data'][address]
|
|
51
|
+
if json.nil?
|
|
52
|
+
@log.info("Address #{address} not found")
|
|
53
|
+
return 0
|
|
61
54
|
end
|
|
55
|
+
a = json['address']
|
|
56
|
+
b = a['balance']
|
|
57
|
+
@log.info("The balance of #{address} is #{b} satoshi")
|
|
58
|
+
b
|
|
59
|
+
end
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
# Get recommended fees, in satoshi per byte.
|
|
62
|
+
def fees
|
|
63
|
+
raise Sibit::NotSupportedError, 'Blockchair doesn\'t implement fees()'
|
|
64
|
+
end
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
# Gets the hash of the latest block.
|
|
67
|
+
def latest
|
|
68
|
+
raise Sibit::NotSupportedError, 'Blockchair doesn\'t implement latest()'
|
|
69
|
+
end
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
# Fetch all unspent outputs per address.
|
|
72
|
+
def utxos(_sources)
|
|
73
|
+
raise Sibit::NotSupportedError, 'Blockchair doesn\'t implement utxos()'
|
|
74
|
+
end
|
|
77
75
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
76
|
+
# Push this transaction (in hex format) to the network.
|
|
77
|
+
def push(hex)
|
|
78
|
+
Sibit::Json.new(http: @http, log: @log).post(
|
|
79
|
+
Iri.new('https://api.blockchair.com/bitcoin/push/transaction').fragment(the_key),
|
|
80
|
+
"data=#{hex}"
|
|
81
|
+
)
|
|
82
|
+
@log.info("Transaction (#{hex.length} in hex) has been pushed to Blockchair")
|
|
83
|
+
end
|
|
86
84
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
# This method should fetch a Blockchain block and return as a hash.
|
|
86
|
+
def block(_hash)
|
|
87
|
+
raise Sibit::NotSupportedError, 'Blockchair doesn\'t implement block()'
|
|
88
|
+
end
|
|
91
89
|
|
|
92
|
-
|
|
90
|
+
private
|
|
93
91
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
end
|
|
92
|
+
def the_key
|
|
93
|
+
@key.nil? ? '' : "key=#{CGI.escape(@key)}"
|
|
97
94
|
end
|
|
98
95
|
end
|