use serde::{Deserialize, Serialize};
use sui_sdk_types::bcs::{FromBcs, ToBcs};
use sui_sdk_types::{Address, MultisigMemberPublicKey, SimpleSignature, UserSignature};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct PublicKey(MultisigMemberPublicKey);
impl From<MultisigMemberPublicKey> for PublicKey {
fn from(pk: MultisigMemberPublicKey) -> Self {
Self(pk)
}
}
impl TryFrom<&UserSignature> for PublicKey {
type Error = anyhow::Error;
fn try_from(signature: &UserSignature) -> Result<Self, anyhow::Error> {
Ok(match signature {
UserSignature::Simple(SimpleSignature::Ed25519 { public_key, .. }) => {
Self(MultisigMemberPublicKey::Ed25519(*public_key))
}
UserSignature::Simple(SimpleSignature::Secp256k1 { public_key, .. }) => {
Self(MultisigMemberPublicKey::Secp256k1(*public_key))
}
UserSignature::Simple(SimpleSignature::Secp256r1 { public_key, .. }) => {
Self(MultisigMemberPublicKey::Secp256r1(*public_key))
}
UserSignature::ZkLogin(zk_login_authenticator) => {
Self(MultisigMemberPublicKey::ZkLogin(
zk_login_authenticator.inputs.public_identifier().clone(),
))
}
UserSignature::Passkey(passkey_authenticator) => Self(
MultisigMemberPublicKey::Passkey(passkey_authenticator.public_key()),
),
s => anyhow::bail!(
"unable to extract public key from signature with scheme {}",
s.scheme().name(),
),
})
}
}
impl PublicKey {
pub fn from_base64(base64: &str) -> Result<Self, anyhow::Error> {
let pk = MultisigMemberPublicKey::from_bcs_base64(base64)?;
Ok(Self(pk))
}
pub fn to_base64(&self) -> String {
self.0
.to_bcs_base64()
.expect("serializing PublicKey to BCS should not fail")
}
pub fn address(&self) -> Result<Address, anyhow::Error> {
Ok(match self.0 {
MultisigMemberPublicKey::Ed25519(public_key) => public_key.derive_address(),
MultisigMemberPublicKey::Secp256k1(public_key) => public_key.derive_address(),
MultisigMemberPublicKey::Secp256r1(public_key) => public_key.derive_address(),
MultisigMemberPublicKey::Passkey(public_key) => public_key.derive_address(),
_ => anyhow::bail!("unable to extract single address from public key {self:?}"),
})
}
}