1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
use crate::error::Error; use crate::service::{Service, ServiceParseError}; use crate::{Identity, IdentityClient}; use sp_core::crypto::Ss58Codec; use std::str::FromStr; use substrate_subxt::{sp_core, system::System, Runtime}; use sunshine_core::{ChainClient, Ss58}; pub async fn resolve<T, C>( client: &C, identifier: Option<Identifier<T>>, ) -> Result<T::Uid, C::Error> where T: Runtime + Identity, C: IdentityClient<T>, <C as ChainClient<T>>::Error: From<Error>, { let identifier = if let Some(identifier) = identifier { identifier } else { Identifier::Account(client.chain_signer()?.account_id().clone()) }; let uid = match identifier { Identifier::Uid(uid) => uid, Identifier::Account(account_id) => client .fetch_uid(&account_id) .await? .ok_or(Error::NoAccount)?, Identifier::Service(service) => client.resolve(&service).await?, }; Ok(uid) } #[derive(Clone, Debug, Eq, PartialEq)] pub enum Identifier<T: Identity> { Uid(T::Uid), Account(T::AccountId), Service(Service), } impl<T: Identity> core::fmt::Display for Identifier<T> { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match self { Self::Uid(uid) => write!(f, "{}", uid), Self::Account(account_id) => write!(f, "{}", account_id.to_string()), Self::Service(service) => write!(f, "{}", service), } } } impl<T: Identity> FromStr for Identifier<T> where <T as System>::AccountId: Ss58Codec, { type Err = ServiceParseError; fn from_str(string: &str) -> core::result::Result<Self, Self::Err> { if let Ok(uid) = T::Uid::from_str(string) { Ok(Self::Uid(uid)) } else if let Ok(Ss58(account_id)) = Ss58::<T>::from_str(string) { Ok(Self::Account(account_id)) } else { Ok(Self::Service(Service::from_str(string)?)) } } } #[cfg(test)] mod tests { use core::str::FromStr; use test_client::identity::{Identifier, Service, ServiceParseError}; use test_client::mock::AccountKeyring; use test_client::Runtime; #[test] fn parse_identifer() { assert_eq!( Identifier::from_str("dvc94ch@github"), Ok(Identifier::<Runtime>::Service(Service::Github( "dvc94ch".into() ))) ); assert_eq!( Identifier::<Runtime>::from_str("dvc94ch@twitter"), Err(ServiceParseError::Unknown("twitter".into())) ); assert_eq!( Identifier::<Runtime>::from_str("@dvc94ch"), Err(ServiceParseError::Invalid) ); let alice = AccountKeyring::Alice.to_account_id(); assert_eq!( Identifier::<Runtime>::from_str(&alice.to_string()), Ok(Identifier::Account(alice)) ); } }