Skip to content

Commit 0778704

Browse files
ValuedMammaltvpeter
authored andcommitted
feat(client): Add v28 module
1 parent b0731c1 commit 0778704

File tree

4 files changed

+132
-25
lines changed

4 files changed

+132
-25
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ corepc-types = { version = "0.11.0", features = ["default"]}
1616
jsonrpc = { version = "0.18.0", features = ["simple_http", "simple_tcp", "minreq_http", "simple_uds", "proxy"] }
1717

1818
[features]
19+
default = ["30_0"]
1920
30_0 = []
21+
28_0 = []

src/client.rs

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@ use corepc_types::{
1010
bitcoin::{
1111
block::Header, consensus::encode::deserialize_hex, Block, BlockHash, Transaction, Txid,
1212
},
13-
model::{GetBlockCount, GetBlockFilter, GetBlockVerboseOne, GetRawMempool},
13+
model::{GetBlockCount, GetBlockFilter, GetRawMempool},
1414
};
1515
use jsonrpc::{
1616
serde,
1717
serde_json::{self, json},
1818
Transport,
1919
};
2020

21+
#[cfg(feature = "28_0")]
22+
pub mod v28;
23+
2124
/// Client authentication methods for the Bitcoin Core JSON-RPC server
2225
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
2326
pub enum Auth {
@@ -34,6 +37,7 @@ impl Auth {
3437
/// required by JSON-RPC client transport.
3538
///
3639
/// # Errors
40+
///
3741
/// Returns an error if the `CookieFile` cannot be read or invalid
3842
pub fn get_user_pass(self) -> Result<(Option<String>, Option<String>), Error> {
3943
match self {
@@ -65,11 +69,14 @@ impl Client {
6569
///
6670
/// Requires authentication via username/password or cookie file.
6771
/// For connections without authentication, use `with_transport` instead.
72+
///
6873
/// # Arguments
74+
///
6975
/// * `url` - URL of the RPC server
7076
/// * `auth` - authentication method (`UserPass` or `CookieFile`).
7177
///
7278
/// # Errors
79+
///
7380
/// * Returns `Error::MissingAuthentication` if `Auth::None` is provided.
7481
/// * Returns `Error::InvalidResponse` if the URL is invalid.
7582
/// * Returns errors related to reading the cookie file.
@@ -132,34 +139,22 @@ impl Client {
132139
/// Retrieves the raw block data for a given block hash (verbosity 0)
133140
///
134141
/// # Arguments
142+
///
135143
/// * `block_hash`: The hash of the block to retrieve.
136144
///
137145
/// # Returns
146+
///
138147
/// The deserialized `Block` struct.
139148
pub fn get_block(&self, block_hash: &BlockHash) -> Result<Block, Error> {
140149
let block_string: String = self.call("getblock", &[json!(block_hash), json!(0)])?;
141150
let block = deserialize_hex(&block_string)?;
142151
Ok(block)
143152
}
144153

145-
/// Retrieves the verbose JSON representation of a block (verbosity 1)
146-
///
147-
/// # Arguments
148-
/// * `block_hash`: The hash of the block to retrieve.
149-
///
150-
/// # Returns
151-
/// The verbose block data as a `GetBlockVerboseOne` struct.
152-
pub fn get_block_verbose(&self, block_hash: &BlockHash) -> Result<GetBlockVerboseOne, Error> {
153-
let block: corepc_types::v30::GetBlockVerboseOne =
154-
self.call("getblock", &[json!(block_hash), json!(1)])?;
155-
let block_model = block.into_model()?;
156-
157-
Ok(block_model)
158-
}
159-
160154
/// Retrieves the hash of the tip of the best block chain.
161155
///
162156
/// # Returns
157+
///
163158
/// The `BlockHash` of the chain tip.
164159
pub fn get_best_block_hash(&self) -> Result<BlockHash, Error> {
165160
let best_block_hash: String = self.call("getbestblockhash", &[])?;
@@ -169,6 +164,7 @@ impl Client {
169164
/// Retrieves the number of blocks in the longest chain
170165
///
171166
/// # Returns
167+
///
172168
/// The block count as a `u32`
173169
pub fn get_block_count(&self) -> Result<u32, Error> {
174170
let block_count: GetBlockCount = self.call("getblockcount", &[])?;
@@ -180,9 +176,11 @@ impl Client {
180176
/// Retrieves the block hash at a given height
181177
///
182178
/// # Arguments
179+
///
183180
/// * `height`: The block height
184181
///
185182
/// # Returns
183+
///
186184
/// The `BlockHash` for the given height
187185
pub fn get_block_hash(&self, height: u32) -> Result<BlockHash, Error> {
188186
let block_hash: String = self.call("getblockhash", &[json!(height)])?;
@@ -192,9 +190,11 @@ impl Client {
192190
/// Retrieves the compact block filter for a given block
193191
///
194192
/// # Arguments
193+
///
195194
/// * `block_hash`: The hash of the block whose filter is requested
196195
///
197196
/// # Returns
197+
///
198198
/// The `GetBlockFilter` structure containing the filter data
199199
pub fn get_block_filter(&self, block_hash: &BlockHash) -> Result<GetBlockFilter, Error> {
200200
let block_filter: GetBlockFilter = self.call("getblockfilter", &[json!(block_hash)])?;
@@ -204,9 +204,11 @@ impl Client {
204204
/// Retrieves the raw block header for a given block hash.
205205
///
206206
/// # Arguments
207+
///
207208
/// * `block_hash`: The hash of the block whose header is requested.
208209
///
209210
/// # Returns
211+
///
210212
/// The deserialized `Header` struct
211213
pub fn get_block_header(&self, block_hash: &BlockHash) -> Result<Header, Error> {
212214
let header_string: String =
@@ -218,6 +220,7 @@ impl Client {
218220
/// Retrieves the transaction IDs of all transactions currently in the mempool
219221
///
220222
/// # Returns
223+
///
221224
/// A vector of `Txid`s in the raw mempool
222225
pub fn get_raw_mempool(&self) -> Result<Vec<Txid>, Error> {
223226
let txids: GetRawMempool = self.call("getrawmempool", &[])?;
@@ -227,9 +230,11 @@ impl Client {
227230
/// Retrieves the raw transaction data for a given transaction ID
228231
///
229232
/// # Arguments
233+
///
230234
/// * `txid`: The transaction ID to retrieve.
231235
///
232236
/// # Returns
237+
///
233238
/// The deserialized `Transaction` struct
234239
pub fn get_raw_transaction(&self, txid: &Txid) -> Result<Transaction, Error> {
235240
let hex_string: String = self.call("getrawtransaction", &[json!(txid)])?;
@@ -238,6 +243,52 @@ impl Client {
238243
}
239244
}
240245

246+
#[cfg(not(feature = "28_0"))]
247+
use corepc_types::{
248+
model::{GetBlockHeaderVerbose, GetBlockVerboseOne},
249+
v30,
250+
};
251+
252+
#[cfg(not(feature = "28_0"))]
253+
impl Client {
254+
/// Retrieves the verbose JSON representation of a block header (verbosity 1).
255+
///
256+
/// # Arguments
257+
///
258+
/// * `block_hash`: The hash of the block to retrieve.
259+
///
260+
/// # Returns
261+
///
262+
/// The verbose header as a `GetBlockHeaderVerbose` struct.
263+
pub fn get_block_header_verbose(
264+
&self,
265+
hash: &BlockHash,
266+
) -> Result<GetBlockHeaderVerbose, Error> {
267+
let header_info: v30::GetBlockHeaderVerbose =
268+
self.call("getblockheader", &[json!(hash)])?;
269+
header_info
270+
.into_model()
271+
.map_err(Error::GetBlockHeaderVerboseError)
272+
}
273+
274+
/// Retrieves the verbose JSON representation of a block (verbosity 1).
275+
///
276+
/// # Arguments
277+
///
278+
/// * `block_hash`: The hash of the block to retrieve.
279+
///
280+
/// # Returns
281+
///
282+
/// The verbose block data as a `GetBlockVerboseOne` struct.
283+
pub fn get_block_verbose(&self, hash: &BlockHash) -> Result<GetBlockVerboseOne, Error> {
284+
let block_info: v30::GetBlockVerboseOne =
285+
self.call("getblock", &[json!(hash), json!(1)])?;
286+
block_info
287+
.into_model()
288+
.map_err(Error::GetBlockVerboseOneError)
289+
}
290+
}
291+
241292
#[cfg(test)]
242293
mod test_auth {
243294
use super::*;

src/client/v28.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use bitcoin::BlockHash;
2+
use corepc_types::{
3+
bitcoin,
4+
model::{GetBlockHeaderVerbose, GetBlockVerboseOne},
5+
v28,
6+
};
7+
8+
use jsonrpc::serde_json::json;
9+
10+
use crate::{Client, Error};
11+
12+
impl Client {
13+
/// Retrieves the verbose JSON representation of a block header (verbosity 1).
14+
///
15+
/// # Arguments
16+
///
17+
/// * `block_hash`: The hash of the block to retrieve.
18+
///
19+
/// # Returns
20+
///
21+
/// The verbose header as a `GetBlockHeaderVerbose` struct.
22+
pub fn get_block_header_verbose(
23+
&self,
24+
hash: &BlockHash,
25+
) -> Result<GetBlockHeaderVerbose, Error> {
26+
let header_info: v28::GetBlockHeaderVerbose =
27+
self.call("getblockheader", &[json!(hash)])?;
28+
header_info
29+
.into_model()
30+
.map_err(Error::GetBlockHeaderVerboseError)
31+
}
32+
33+
/// Retrieves the verbose JSON representation of a block (verbosity 1).
34+
///
35+
/// # Arguments
36+
///
37+
/// * `block_hash`: The hash of the block to retrieve.
38+
///
39+
/// # Returns
40+
///
41+
/// The verbose block data as a `GetBlockVerboseOne` struct.
42+
pub fn get_block_verbose(&self, hash: &BlockHash) -> Result<GetBlockVerboseOne, Error> {
43+
let block_info: v28::GetBlockVerboseOne =
44+
self.call("getblock", &[json!(hash), json!(1)])?;
45+
block_info
46+
.into_model()
47+
.map_err(Error::GetBlockVerboseOneError)
48+
}
49+
}

src/error.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
//! Error types for the Bitcoin RPC client.
22
3-
use std::{fmt, io, num::TryFromIntError};
4-
5-
use corepc_types::{
6-
bitcoin::{
7-
consensus::{self, encode::FromHexError},
8-
hex::{HexToArrayError, HexToBytesError},
9-
},
10-
v30::GetBlockVerboseOneError,
3+
use bitcoin::{
4+
consensus::encode::FromHexError,
5+
hex::{HexToArrayError, HexToBytesError},
116
};
7+
use corepc_types::bitcoin;
8+
#[cfg(feature = "28_0")]
9+
use corepc_types::v17::{GetBlockHeaderVerboseError, GetBlockVerboseOneError};
10+
#[cfg(not(feature = "28_0"))]
11+
use corepc_types::v30::{GetBlockHeaderVerboseError, GetBlockVerboseOneError};
1212
use jsonrpc::serde_json;
13+
use std::{fmt, io, num::TryFromIntError};
1314

1415
/// Result type alias for the RPC client.
1516
pub type Result<T> = std::result::Result<T, Error>;
@@ -18,11 +19,14 @@ pub type Result<T> = std::result::Result<T, Error>;
1819
#[derive(Debug)]
1920
pub enum Error {
2021
/// Hex deserialization error
21-
DecodeHex(consensus::encode::FromHexError),
22+
DecodeHex(FromHexError),
2223

2324
/// Error converting `GetBlockVersboseOne` type into the model type
2425
GetBlockVerboseOneError(GetBlockVerboseOneError),
2526

27+
/// Error modeling [`GetBlockHeaderVerbose`](corepc_types::model::GetBlockHeaderVerbose).
28+
GetBlockHeaderVerboseError(GetBlockHeaderVerboseError),
29+
2630
/// Missing authentication credentials.
2731
MissingAuthentication,
2832

@@ -65,6 +69,7 @@ impl fmt::Display for Error {
6569
Error::Json(e) => write!(f, "JSON error: {e}"),
6670
Error::Io(e) => write!(f, "I/O error: {e}"),
6771
Error::DecodeHex(e) => write!(f, "Hex deserialization error: {e}"),
72+
Error::GetBlockHeaderVerboseError(e) => write!(f, "{e}"),
6873
Error::GetBlockVerboseOneError(e) => {
6974
write!(f, "Error converting getblockverboseone: {e}")
7075
}

0 commit comments

Comments
 (0)