use bitcoin::hex::DisplayHex;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{AddrBytes, OutputType};
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AddrValidation {
pub isvalid: bool,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "address")]
pub addr: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "scriptPubKey")]
pub script_pub_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub isscript: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub iswitness: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub witness_version: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub witness_program: Option<String>,
}
impl AddrValidation {
pub fn invalid() -> Self {
Self {
isvalid: false,
addr: None,
script_pub_key: None,
isscript: None,
iswitness: None,
witness_version: None,
witness_program: None,
}
}
pub fn from_addr(addr: &str) -> Self {
let Ok(script) = AddrBytes::addr_to_script(addr) else {
return Self::invalid();
};
let output_type = OutputType::from(&script);
let script_hex = script.as_bytes().to_lower_hex_string();
let is_script = matches!(output_type, OutputType::P2SH);
let is_witness = matches!(
output_type,
OutputType::P2WPKH | OutputType::P2WSH | OutputType::P2TR | OutputType::P2A
);
let (witness_version, witness_program) = if is_witness {
let version = script.witness_version().map(|v| v.to_num());
let program = if script.len() > 2 {
Some(script.as_bytes()[2..].to_lower_hex_string())
} else {
None
};
(version, program)
} else {
(None, None)
};
Self {
isvalid: true,
addr: Some(addr.to_string()),
script_pub_key: Some(script_hex),
isscript: Some(is_script),
iswitness: Some(is_witness),
witness_version,
witness_program,
}
}
}