@@ -42,6 +42,8 @@ use bitcoin::hex::{self, FromHex as _};
4242use bitcoin:: { Amount , FeeRate , ScriptBuf , Witness } ;
4343use serde:: { Deserialize , Serialize } ;
4444
45+ use crate :: error:: write_err;
46+
4547/// Converts an `i64` numeric type to a `u32`.
4648///
4749/// The Bitcoin Core JSONRPC API has fields marked as 'numeric'. It is not obvious what Rust
@@ -191,7 +193,7 @@ pub struct ScriptPubkey {
191193 pub hex : String ,
192194 /// Number of required signatures - deprecated in Core v22.
193195 ///
194- /// Only returned before in versions prior to 22 or for version 22 onwards if
196+ /// Only returned in versions prior to 22 or for version 22 onwards if
195197 /// config option `-deprecatedrpc=addresses` is passed.
196198 #[ serde( rename = "reqSigs" ) ]
197199 pub required_signatures : Option < i64 > ,
@@ -202,11 +204,45 @@ pub struct ScriptPubkey {
202204 pub address : Option < String > ,
203205 /// Array of bitcoin addresses - deprecated in Core v22.
204206 ///
205- /// Only returned before in versions prior to 22 or for version 22 onwards if
207+ /// Only returned in versions prior to 22 or for version 22 onwards if
206208 /// config option `-deprecatedrpc=addresses` is passed.
207209 pub addresses : Option < Vec < String > > ,
208210}
209211
212+ /// Error when converting a `ScriptPubkey` type into the model type.
213+ #[ derive( Debug ) ]
214+ pub enum ScriptPubkeyError {
215+ /// Conversion of the `hex` field failed.
216+ Hex ( hex:: HexToBytesError ) ,
217+ /// Conversion of the `address` field failed.
218+ Address ( address:: ParseError ) ,
219+ /// Conversion of the `addresses` field failed.
220+ Addresses ( address:: ParseError ) ,
221+ }
222+
223+ impl fmt:: Display for ScriptPubkeyError {
224+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
225+ use ScriptPubkeyError :: * ;
226+ match * self {
227+ Hex ( ref e) => write_err ! ( f, "conversion of the `hex` field failed" ; e) ,
228+ Address ( ref e) => write_err ! ( f, "conversion of the `address` field failed" ; e) ,
229+ Addresses ( ref e) => write_err ! ( f, "conversion of the `addresses` field failed" ; e) ,
230+ }
231+ }
232+ }
233+
234+ #[ cfg( feature = "std" ) ]
235+ impl std:: error:: Error for ScriptPubkeyError {
236+ fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
237+ use ScriptPubkeyError :: * ;
238+ match * self {
239+ Hex ( ref e) => Some ( e) ,
240+ Address ( ref e) => Some ( e) ,
241+ Addresses ( ref e) => Some ( e) ,
242+ }
243+ }
244+ }
245+
210246impl ScriptPubkey {
211247 fn script_buf ( & self ) -> Result < ScriptBuf , hex:: HexToBytesError > {
212248 ScriptBuf :: from_hex ( & self . hex )
@@ -215,6 +251,32 @@ impl ScriptPubkey {
215251 fn address ( & self ) -> Option < Result < Address < NetworkUnchecked > , address:: ParseError > > {
216252 self . address . as_ref ( ) . map ( |addr| addr. parse :: < Address < _ > > ( ) )
217253 }
254+
255+ /// Converts version specific type to a version nonspecific, more strongly typed type.
256+ pub fn into_model ( self ) -> Result < model:: ScriptPubkey , ScriptPubkeyError > {
257+ use ScriptPubkeyError as E ;
258+
259+ let script_pubkey = ScriptBuf :: from_hex ( & self . hex ) . map_err ( E :: Hex ) ?;
260+
261+ let address =
262+ self . address . map ( |s| s. parse :: < Address < _ > > ( ) . map_err ( E :: Address ) ) . transpose ( ) ?;
263+
264+ let addresses = self
265+ . addresses
266+ . map ( |v| {
267+ v. into_iter ( )
268+ . map ( |s| s. parse :: < Address < _ > > ( ) . map_err ( E :: Addresses ) )
269+ . collect :: < Result < Vec < _ > , _ > > ( )
270+ } )
271+ . transpose ( ) ?;
272+
273+ Ok ( model:: ScriptPubkey {
274+ script_pubkey,
275+ required_signatures : self . required_signatures ,
276+ address,
277+ addresses,
278+ } )
279+ }
218280}
219281
220282/// Data returned by Core for a script signature.
0 commit comments