use super::{SaplingExtendedFullViewingKey, SaplingExtendedSpendingKey, SaplingIncomingViewingKey};
use crate::{Blob, NoQuotesDebugOption, test_envelope_roundtrip};
use anyhow::Context;
use bc_envelope::prelude::*;
#[derive(Clone, PartialEq)]
pub struct Address {
address: String,
incoming_viewing_key: Option<SaplingIncomingViewingKey>,
full_viewing_key: Option<SaplingExtendedFullViewingKey>,
spending_key: Option<SaplingExtendedSpendingKey>,
hd_derivation_path: Option<String>,
diversifier_index: Option<Blob<11>>,
}
impl std::fmt::Debug for Address {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SaplingAddress")
.field("address", &self.address)
.field(
"incoming_viewing_key",
&NoQuotesDebugOption(&self.incoming_viewing_key),
)
.field("spending_key", &self.spending_key)
.field("diversifier_index", &self.diversifier_index)
.field("hd_derivation_path", &self.hd_derivation_path)
.finish()
}
}
impl Address {
pub fn new(address: String) -> Self {
Address {
address,
incoming_viewing_key: None,
full_viewing_key: None,
spending_key: None,
diversifier_index: None,
hd_derivation_path: None,
}
}
pub fn address(&self) -> &str {
&self.address
}
pub fn set_address(&mut self, address: String) {
self.address = address;
}
pub fn incoming_viewing_key(&self) -> Option<&SaplingIncomingViewingKey> {
self.incoming_viewing_key.as_ref()
}
pub fn set_incoming_viewing_key(&mut self, ivk: SaplingIncomingViewingKey) {
self.incoming_viewing_key = Some(ivk);
}
pub fn full_viewing_key(&self) -> Option<&SaplingExtendedFullViewingKey> {
self.full_viewing_key.as_ref()
}
pub fn set_full_viewing_key(&mut self, key: SaplingExtendedFullViewingKey) {
self.full_viewing_key = Some(key);
}
pub fn spending_key(&self) -> Option<&SaplingExtendedSpendingKey> {
self.spending_key.as_ref()
}
pub fn set_spending_key(&mut self, key: SaplingExtendedSpendingKey) {
self.spending_key = Some(key);
}
pub fn diversifier_index(&self) -> Option<&Blob<11>> {
self.diversifier_index.as_ref()
}
pub fn set_diversifier_index(&mut self, d: Blob<11>) {
self.diversifier_index = Some(d);
}
pub fn hd_derivation_path(&self) -> Option<&str> {
self.hd_derivation_path.as_deref()
}
pub fn set_hd_derivation_path(&mut self, path: String) {
self.hd_derivation_path = Some(path);
}
}
impl From<Address> for Envelope {
fn from(value: Address) -> Self {
Envelope::new(value.address)
.add_type("SaplingAddress")
.add_optional_assertion("incoming_viewing_key", value.incoming_viewing_key)
.add_optional_assertion("full_viewing_key", value.full_viewing_key)
.add_optional_assertion("spending_key", value.spending_key)
.add_optional_assertion("diversifier_index", value.diversifier_index)
.add_optional_assertion("hd_derivation_path", value.hd_derivation_path)
}
}
impl TryFrom<Envelope> for Address {
type Error = anyhow::Error;
fn try_from(envelope: Envelope) -> Result<Self, Self::Error> {
envelope
.check_type_envelope("SaplingAddress")
.context("SaplingAddress")?;
let address = envelope.extract_subject().context("address")?;
let incoming_viewing_key = envelope
.try_optional_object_for_predicate("incoming_viewing_key")
.context("incoming_viewing_key")?;
let full_viewing_key = envelope
.try_optional_object_for_predicate("full_viewing_key")
.context("full_viewing_key")?;
let spending_key = envelope
.try_optional_object_for_predicate("spending_key")
.context("spending_key")?;
let diversifier_index = envelope
.try_optional_object_for_predicate("diversifier_index")
.context("diversifier_index")?;
let hd_derivation_path = envelope
.try_optional_object_for_predicate("hd_derivation_path")
.context("hd_derivation_path")?;
Ok(Address {
address,
incoming_viewing_key,
full_viewing_key,
spending_key,
diversifier_index,
hd_derivation_path,
})
}
}
#[cfg(test)]
impl crate::RandomInstance for Address {
fn random() -> Self {
Self {
address: String::random(),
incoming_viewing_key: SaplingIncomingViewingKey::opt_random(),
full_viewing_key: SaplingExtendedFullViewingKey::opt_random(),
spending_key: SaplingExtendedSpendingKey::opt_random(),
diversifier_index: Blob::<11>::opt_random(),
hd_derivation_path: String::opt_random(),
}
}
}
test_envelope_roundtrip!(Address);