sos_core/
account.rs

1use crate::{Error, Result};
2use rand::Rng;
3use serde::{Deserialize, Serialize};
4use std::{fmt, str::FromStr};
5
6/// Account identifier.
7///
8/// String encoding starts with 0x and is followed with
9/// 20 bytes hex-encoded.
10#[derive(Debug, Serialize, Deserialize, Clone, Copy, Hash, Eq, PartialEq)]
11#[serde(try_from = "String", into = "String")]
12pub struct AccountId([u8; 20]);
13
14impl AccountId {
15    /// Create a random account identifier.
16    pub fn random() -> Self {
17        let mut rng = crate::csprng();
18        Self(rng.gen())
19    }
20}
21
22impl fmt::Display for AccountId {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        write!(f, "0x{}", hex::encode(self.0))
25    }
26}
27
28impl Default for AccountId {
29    fn default() -> Self {
30        Self([0u8; 20])
31    }
32}
33
34impl AsRef<[u8]> for AccountId {
35    fn as_ref(&self) -> &[u8] {
36        &self.0
37    }
38}
39
40impl From<[u8; 20]> for AccountId {
41    fn from(value: [u8; 20]) -> Self {
42        Self(value)
43    }
44}
45
46impl FromStr for AccountId {
47    type Err = Error;
48
49    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
50        if !s.starts_with("0x") {
51            return Err(Error::BadAccountIdPrefix);
52        }
53        let bytes = hex::decode(&s[2..])?;
54        let buffer: [u8; 20] = bytes.as_slice().try_into()?;
55        Ok(AccountId(buffer))
56    }
57}
58
59impl From<AccountId> for String {
60    fn from(value: AccountId) -> String {
61        value.to_string()
62    }
63}
64
65impl From<AccountId> for [u8; 20] {
66    fn from(value: AccountId) -> [u8; 20] {
67        value.0
68    }
69}
70
71impl TryFrom<String> for AccountId {
72    type Error = Error;
73    fn try_from(value: String) -> Result<Self> {
74        <AccountId as FromStr>::from_str(&value)
75    }
76}