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