dusk_wallet/wallet/
address.rs1use crate::Error;
8use dusk_bytes::{DeserializableSlice, Error as BytesError, Serializable};
9use dusk_pki::PublicSpendKey;
10use std::fmt;
11use std::hash::Hasher;
12use std::str::FromStr;
13
14#[derive(Clone, Eq)]
15pub struct Address {
17 pub(crate) index: Option<u8>,
18 pub(crate) psk: PublicSpendKey,
19}
20
21impl Address {
22 pub(crate) fn new(index: u8, psk: PublicSpendKey) -> Self {
23 Self {
24 index: Some(index),
25 psk,
26 }
27 }
28
29 pub fn is_owned(&self) -> bool {
31 self.index.is_some()
32 }
33
34 pub(crate) fn psk(&self) -> &PublicSpendKey {
35 &self.psk
36 }
37
38 pub(crate) fn index(&self) -> Result<u8, Error> {
39 self.index.ok_or(Error::AddressNotOwned)
40 }
41
42 pub fn preview(&self) -> String {
44 let addr = bs58::encode(self.psk.to_bytes()).into_string();
45 format!("{}...{}", &addr[..7], &addr[addr.len() - 7..])
46 }
47}
48
49impl FromStr for Address {
50 type Err = Error;
51
52 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 let bytes = bs58::decode(s).into_vec()?;
54
55 let psk = PublicSpendKey::from_reader(&mut &bytes[..])
56 .map_err(|_| Error::BadAddress)?;
57
58 let addr = Address { index: None, psk };
59
60 Ok(addr)
61 }
62}
63
64impl TryFrom<String> for Address {
65 type Error = Error;
66
67 fn try_from(s: String) -> Result<Self, Self::Error> {
68 Address::from_str(s.as_str())
69 }
70}
71
72impl TryFrom<&[u8; PublicSpendKey::SIZE]> for Address {
73 type Error = Error;
74
75 fn try_from(
76 bytes: &[u8; PublicSpendKey::SIZE],
77 ) -> Result<Self, Self::Error> {
78 let addr = Address {
79 index: None,
80 psk: dusk_pki::PublicSpendKey::from_bytes(bytes)?,
81 };
82 Ok(addr)
83 }
84}
85
86impl PartialEq for Address {
87 fn eq(&self, other: &Self) -> bool {
88 self.index == other.index && self.psk == other.psk
89 }
90}
91
92impl std::hash::Hash for Address {
93 fn hash<H: Hasher>(&self, state: &mut H) {
94 self.index.hash(state);
95 self.psk.to_bytes().hash(state);
96 }
97}
98
99impl fmt::Display for Address {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 write!(f, "{}", bs58::encode(self.psk.to_bytes()).into_string())
102 }
103}
104
105impl fmt::Debug for Address {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 write!(f, "{}", bs58::encode(self.psk.to_bytes()).into_string())
108 }
109}
110
111pub(crate) struct Addresses {
114 pub(crate) count: u8,
115}
116
117impl Default for Addresses {
118 fn default() -> Self {
119 Self { count: 1 }
120 }
121}
122
123impl Serializable<1> for Addresses {
124 type Error = BytesError;
125
126 fn from_bytes(buf: &[u8; Addresses::SIZE]) -> Result<Self, Self::Error>
127 where
128 Self: Sized,
129 {
130 Ok(Self { count: buf[0] })
131 }
132
133 fn to_bytes(&self) -> [u8; Addresses::SIZE] {
134 [self.count]
135 }
136}
137
138#[test]
139fn addresses_serde() -> Result<(), Box<dyn std::error::Error>> {
140 let addrs = Addresses { count: 6 };
141 let read = Addresses::from_bytes(&addrs.to_bytes())
142 .map_err(|_| Error::WalletFileCorrupted)?;
143 assert!(read.count == addrs.count);
144 Ok(())
145}