zebra_rpc/methods/types/
validate_address.rs
1use derive_getters::Getters;
4use derive_new::new;
5use jsonrpsee::core::RpcResult;
6use zebra_chain::{parameters::Network, primitives};
7
8#[derive(
10 Clone, Default, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Getters, new,
11)]
12pub struct ValidateAddressResponse {
13 #[serde(rename = "isvalid")]
17 pub(crate) is_valid: bool,
18
19 #[serde(skip_serializing_if = "Option::is_none")]
21 pub(crate) address: Option<String>,
22
23 #[serde(rename = "isscript")]
25 #[serde(skip_serializing_if = "Option::is_none")]
26 #[getter(copy)]
27 pub(crate) is_script: Option<bool>,
28}
29
30impl ValidateAddressResponse {
31 pub fn invalid() -> Self {
33 Self::default()
34 }
35}
36
37pub fn validate_address(
40 network: Network,
41 raw_address: String,
42) -> RpcResult<ValidateAddressResponse> {
43 let Ok(address) = raw_address.parse::<zcash_address::ZcashAddress>() else {
44 return Ok(ValidateAddressResponse::invalid());
45 };
46
47 let address = match address.convert::<primitives::Address>() {
48 Ok(address) => address,
49 Err(err) => {
50 tracing::debug!(?err, "conversion error");
51 return Ok(ValidateAddressResponse::invalid());
52 }
53 };
54
55 if !address.is_transparent() {
57 return Ok(ValidateAddressResponse::invalid());
58 }
59
60 if address.network() == network.kind() {
61 Ok(ValidateAddressResponse {
62 address: Some(raw_address),
63 is_valid: true,
64 is_script: Some(address.is_script_hash()),
65 })
66 } else {
67 tracing::info!(
68 ?network,
69 address_network = ?address.network(),
70 "invalid address in validateaddress RPC: Zebra's configured network must match address network"
71 );
72
73 Ok(ValidateAddressResponse::invalid())
74 }
75}