use std::convert::TryInto;
use crate::crypto::strkey;
use crate::error::{Error, Result};
use crate::xdr;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PublicKey(pub [u8; 32]);
impl PublicKey {
pub fn from_account_id(account_id: &str) -> Result<PublicKey> {
let bytes = strkey::decode_account_id(account_id)?;
Self::from_slice(&bytes)
}
pub fn from_slice(data: &[u8]) -> Result<PublicKey> {
Ok(PublicKey(
data.try_into().map_err(|_| Error::InvalidPublicKey)?,
))
}
pub fn account_id(&self) -> String {
strkey::encode_account_id(&self.0)
}
pub fn into_muxed_account(self, id: u64) -> MuxedAccount {
let inner = MuxedEd25519PublicKey { key: self, id };
MuxedAccount::MuxedEd25519(inner)
}
pub fn to_muxed_account(&self, id: u64) -> MuxedAccount {
(*self).into_muxed_account(id)
}
pub fn to_xdr_uint256(&self) -> Result<xdr::Uint256> {
Ok(xdr::Uint256(self.0))
}
pub fn to_xdr_public_key(&self) -> Result<xdr::PublicKey> {
let uint256 = self.to_xdr_uint256()?;
Ok(xdr::PublicKey::PublicKeyTypeEd25519(uint256))
}
pub fn to_xdr_account_id(&self) -> Result<xdr::AccountId> {
let public_key = self.to_xdr_public_key()?;
Ok(xdr::AccountId(public_key))
}
pub fn from_xdr_public_key(x: &xdr::PublicKey) -> Result<PublicKey> {
match x {
xdr::PublicKey::PublicKeyTypeEd25519(inner) => Self::from_slice(&inner.0),
}
}
pub fn from_xdr_account_id(x: &xdr::AccountId) -> Result<PublicKey> {
Self::from_xdr_public_key(&x.0)
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn to_xdr(&self) -> Result<xdr::MuxedAccount> {
let uint256 = self.to_xdr_uint256()?;
Ok(xdr::MuxedAccount::Ed25519(uint256))
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MuxedEd25519PublicKey {
key: PublicKey,
id: u64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum MuxedAccount {
Ed25519(PublicKey),
MuxedEd25519(MuxedEd25519PublicKey),
}
impl MuxedEd25519PublicKey {
pub fn new(key: PublicKey, id: u64) -> MuxedEd25519PublicKey {
MuxedEd25519PublicKey { key, id }
}
pub fn from_account_id(account_id: &str) -> Result<MuxedEd25519PublicKey> {
let (bytes, id) = strkey::decode_muxed_account(account_id)?;
Self::from_slice(&bytes, id)
}
pub fn from_slice(data: &[u8], id: u64) -> Result<MuxedEd25519PublicKey> {
let key = PublicKey::from_slice(data)?;
Ok(MuxedEd25519PublicKey { key, id })
}
pub fn public_key(&self) -> &PublicKey {
&self.key
}
pub fn account_id(&self) -> String {
strkey::encode_muxed_account(self.key.as_bytes(), self.id)
}
pub fn to_xdr(&self) -> Result<xdr::MuxedAccount> {
let uint256 = self.key.to_xdr_uint256()?;
let muxed = xdr::MuxedAccountMed25519 {
id: self.id,
ed25519: uint256,
};
Ok(xdr::MuxedAccount::MuxedEd25519(muxed))
}
}
impl MuxedAccount {
pub fn account_id(&self) -> String {
match self {
MuxedAccount::Ed25519(pk) => pk.account_id(),
MuxedAccount::MuxedEd25519(mx) => mx.account_id(),
}
}
pub fn to_xdr(&self) -> Result<xdr::MuxedAccount> {
match self {
MuxedAccount::Ed25519(pk) => pk.to_xdr(),
MuxedAccount::MuxedEd25519(mx) => mx.to_xdr(),
}
}
pub fn from_xdr(x: &xdr::MuxedAccount) -> Result<MuxedAccount> {
match x {
xdr::MuxedAccount::Ed25519(buf) => {
let inner = PublicKey::from_slice(&buf.0)?;
Ok(MuxedAccount::Ed25519(inner))
}
xdr::MuxedAccount::MuxedEd25519(mx) => {
let inner = MuxedEd25519PublicKey::from_slice(&mx.ed25519.0, mx.id)?;
Ok(MuxedAccount::MuxedEd25519(inner))
}
}
}
}
impl From<PublicKey> for MuxedAccount {
fn from(pk: PublicKey) -> Self {
MuxedAccount::Ed25519(pk)
}
}
impl From<MuxedEd25519PublicKey> for MuxedAccount {
fn from(muxed: MuxedEd25519PublicKey) -> Self {
MuxedAccount::MuxedEd25519(muxed)
}
}
impl std::str::FromStr for PublicKey {
type Err = crate::error::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let pk = PublicKey::from_account_id(s)?;
Ok(pk)
}
}
impl std::fmt::Display for PublicKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.account_id())
}
}