diff --git a/src/error.rs b/src/error.rs index d8ac455..0db954b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -43,6 +43,8 @@ pub enum Error { HexError(#[from] FromHexError), #[error("unsupported operation: {0}")] UnsupportedOperation(String), + #[error("failed to convert vector {0:?} to array")] + VectorToArrayConversionError(Vec), #[error("alias must be {min_length:?} to {max_length:?} length of {alphabet:?} and may have a prefix \"{max_length:?}{chain_id:?}:\"")] InvalidAliasName { min_length: u8, diff --git a/src/model/account/address.rs b/src/model/account/address.rs index e284ef3..ca19579 100644 --- a/src/model/account/address.rs +++ b/src/model/account/address.rs @@ -17,6 +17,16 @@ impl fmt::Debug for Address { } } +impl std::str::FromStr for Address { + type Err = Error; + + fn from_str(base58string: &str) -> Result
{ + Ok(Address { + bytes: Base58::decode(base58string)?, + }) + } +} + impl Address { pub fn from_public_key(chain_id: u8, public_key: &PublicKey) -> Result
{ Ok(Address { @@ -72,6 +82,7 @@ mod tests { use crate::model::{ByteString, ChainId}; use serde_json::Value; use std::borrow::Borrow; + use std::str::FromStr; #[test] fn test_address_from_public_key() { @@ -97,6 +108,14 @@ mod tests { assert_eq!(expected_address, address.encoded()) } + #[test] + fn test_address_std_from_str() { + let expected_address = "3MtQQX9NwYH5URGGcS2e6ptEgV7wTFesaRW"; + let address = + Address::from_str(expected_address).expect("failed to get address from string"); + assert_eq!(expected_address, address.encoded()) + } + #[test] fn test_address_from_json() -> Result<()> { let expected_address = "3MtQQX9NwYH5URGGcS2e6ptEgV7wTFesaRW"; diff --git a/src/model/account/private_key.rs b/src/model/account/private_key.rs index 126f92a..ea3cd72 100644 --- a/src/model/account/private_key.rs +++ b/src/model/account/private_key.rs @@ -12,6 +12,18 @@ pub struct PrivateKey { public_key: PublicKey, } +impl std::str::FromStr for PrivateKey { + type Err = Error; + + fn from_str(base58string: &str) -> Result { + let bytes = Base58::decode(base58string)?; + let bytes_array: [u8; 32] = bytes + .try_into() + .map_err(Error::VectorToArrayConversionError)?; + PrivateKey::from_bytes(bytes_array) + } +} + impl PrivateKey { pub fn from_seed(seed_phrase: &str, nonce: u8) -> Result { let hash_seed = Crypto::get_account_seed(seed_phrase.as_bytes(), nonce)?; @@ -79,6 +91,8 @@ impl PrivateKey { #[cfg(test)] mod tests { + use std::str::FromStr; + use crate::error::Error::InvalidBytesLength; use crate::error::Result; use crate::model::account::PrivateKey; @@ -149,4 +163,13 @@ mod tests { assert_eq!(private_key.bytes(), [0_u8; 32]); Ok(()) } + + #[test] + fn test_private_key_std_from_str() -> Result<()> { + let seed_phrase = "blame vacant regret company chase trip grant funny brisk innocent"; + let private_key_from_seed = PrivateKey::from_seed(seed_phrase, 0)?; + let private_key_from_str = PrivateKey::from_str(&private_key_from_seed.encoded())?; + assert_eq!(private_key_from_seed.bytes(), private_key_from_str.bytes()); + Ok(()) + } } diff --git a/src/model/account/public_key.rs b/src/model/account/public_key.rs index 899bd74..a4ba707 100644 --- a/src/model/account/public_key.rs +++ b/src/model/account/public_key.rs @@ -16,6 +16,15 @@ impl fmt::Debug for PublicKey { } } +impl std::str::FromStr for PublicKey { + type Err = Error; + + fn from_str(base58string: &str) -> Result { + let bytes = Base58::decode(base58string)?; + Ok(PublicKey { bytes }) + } +} + impl PublicKey { pub fn from_bytes(bytes: &[u8]) -> Result { if bytes.len() != 32 { @@ -71,6 +80,8 @@ impl TryFrom for PublicKey { #[cfg(test)] mod tests { + use std::str::FromStr; + use crate::error::Error::InvalidBytesLength; use crate::error::Result; use crate::model::account::{PrivateKey, PublicKey}; @@ -136,6 +147,14 @@ mod tests { Ok(()) } + #[test] + fn test_public_key_std_from_str() -> Result<()> { + let expected_string = "8cj6YzvQPhSHGvnjupNTW8zrADTT8CMAAd2xTuej84gB".to_owned(); + let public_key = PublicKey::from_str(&expected_string)?; + assert_eq!(expected_string, public_key.encoded()); + Ok(()) + } + #[test] fn test_byte_string_for_public_key() -> Result<()> { let public_key: PublicKey = "8cj6YzvQPhSHGvnjupNTW8zrADTT8CMAAd2xTuej84gB".try_into()?;