rusk_wallet/wallet/
address.rs1use std::fmt;
8use std::hash::Hasher;
9use std::str::FromStr;
10
11use dusk_bytes::{DeserializableSlice, Serializable};
12
13use super::*;
14use crate::Error;
15
16#[derive(Clone, Eq)]
18#[allow(missing_docs)]
19pub enum Address {
20 Shielded(PhoenixPublicKey),
22 Public(BlsPublicKey),
25}
26
27impl Address {
28 pub fn same_transaction_model(&self, other: &Address) -> Result<(), Error> {
30 match (self, other) {
31 (Address::Shielded(_), Address::Shielded(_)) => Ok(()),
32 (Address::Public(_), Address::Public(_)) => Ok(()),
33 _ => Err(Error::DifferentTransactionModels),
34 }
35 }
36
37 pub fn shielded_key(&self) -> Result<&PhoenixPublicKey, Error> {
42 if let Self::Shielded(addr) = self {
43 Ok(addr)
44 } else {
45 Err(Error::ExpectedPhoenixPublicKey)
46 }
47 }
48
49 pub fn public_key(&self) -> Result<&BlsPublicKey, Error> {
54 if let Self::Public(addr) = self {
55 Ok(addr)
56 } else {
57 Err(Error::ExpectedBlsPublicKey)
58 }
59 }
60
61 pub(crate) fn to_bytes(&self) -> Vec<u8> {
62 match self {
63 Self::Shielded(addr) => addr.to_bytes().to_vec(),
64 Self::Public(addr) => addr.to_bytes().to_vec(),
65 }
66 }
67
68 pub fn preview(&self) -> String {
70 let addr_key_str = String::from(self);
71 format!(
72 "{}...{}",
73 &addr_key_str[..5],
74 &addr_key_str[addr_key_str.len() - 5..]
75 )
76 }
77}
78
79impl From<BlsPublicKey> for Address {
80 fn from(value: BlsPublicKey) -> Self {
81 Self::Public(value)
82 }
83}
84
85impl From<PhoenixPublicKey> for Address {
86 fn from(value: PhoenixPublicKey) -> Self {
87 Self::Shielded(value)
88 }
89}
90
91impl FromStr for Address {
92 type Err = Error;
93
94 fn from_str(s: &str) -> Result<Self, Self::Err> {
95 let address_bytes = bs58::decode(s).into_vec()?;
96
97 let address = match address_bytes.len() {
98 PhoenixPublicKey::SIZE => {
99 PhoenixPublicKey::from_slice(&address_bytes)?.into()
100 }
101 BlsPublicKey::SIZE => {
102 BlsPublicKey::from_slice(&address_bytes)?.into()
103 }
104 _ => return Err(Error::Bytes(dusk_bytes::Error::InvalidData)),
105 };
106 Ok(address)
107 }
108}
109
110impl From<&Address> for String {
111 fn from(address: &Address) -> Self {
112 match address {
113 Address::Shielded(addr) => {
114 bs58::encode(addr.to_bytes()).into_string()
115 }
116 Address::Public(addr) => {
117 bs58::encode(addr.to_bytes()).into_string()
118 }
119 }
120 }
121}
122
123impl PartialEq for Address {
124 fn eq(&self, other: &Self) -> bool {
125 match (self, other) {
126 (Address::Shielded(self_pk), Address::Shielded(other_pk)) => {
127 self_pk == other_pk
128 }
129 (Address::Public(self_pk), Address::Public(other_pk)) => {
130 self_pk == other_pk
131 }
132 _ => false,
133 }
134 }
135}
136
137impl std::hash::Hash for Address {
138 fn hash<H: Hasher>(&self, state: &mut H) {
139 self.to_bytes().hash(state);
140 }
141}
142
143impl fmt::Display for Address {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 write!(f, "{}", String::from(self))
146 }
147}
148
149impl fmt::Debug for Address {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 write!(f, "{}", String::from(self))
152 }
153}
154
155#[derive(Debug, PartialEq, Eq)]
158pub struct Profile {
159 pub shielded_addr: PhoenixPublicKey,
161 pub public_addr: BlsPublicKey,
163}
164
165impl Profile {
166 pub fn shielded_account_string(&self) -> String {
168 format!(
169 "{} - {}",
170 shielded_account_prefix(),
171 Address::Shielded(self.shielded_addr)
172 )
173 }
174
175 pub fn public_account_string(&self) -> String {
177 format!(
178 "{} - {}",
179 public_account_prefix(),
180 Address::Public(self.public_addr)
181 )
182 }
183
184 pub fn staking_account_string(&self) -> String {
186 format!(
187 "{} - {}",
188 staking_account_prefix(),
189 Address::Public(self.public_addr)
190 )
191 }
192
193 pub fn shielded_account_preview(&self) -> String {
195 format!(
196 "{} - {}",
197 shielded_account_prefix(),
198 Address::Shielded(self.shielded_addr).preview(),
199 )
200 }
201
202 pub fn public_account_preview(&self) -> String {
204 format!(
205 "{} - {}",
206 public_account_prefix(),
207 Address::Public(self.public_addr).preview()
208 )
209 }
210
211 pub fn staking_account_preview(&self) -> String {
213 format!(
214 "{} - {}",
215 staking_account_prefix(),
216 Address::Public(self.public_addr).preview()
217 )
218 }
219
220 pub fn index_string(profile_idx: u8) -> String {
222 let mut index_string = format!("Profile {:2}", profile_idx + 1);
223 if profile_idx == 0 {
224 index_string.push_str(" (Default)");
225 }
226
227 index_string
228 }
229}
230
231fn shielded_account_prefix() -> String {
232 format!("{:<16}", "Shielded account")
233}
234
235fn public_account_prefix() -> String {
236 format!("{:<16}", "Public account")
237}
238
239fn staking_account_prefix() -> String {
240 format!("{:<16}", "Staking account")
241}