Use Currency enum to refer to CAIP-2 namespaces instead of chain IDs

This commit is contained in:
silverpill 2022-08-29 14:33:00 +00:00
parent 8df8fd3c8c
commit 690a03946e
4 changed files with 29 additions and 28 deletions

View file

@ -19,13 +19,16 @@ pub const ETHEREUM_EIP191_PROOF: &str = "ethereum-eip191-00";
// https://github.com/w3c-ccg/did-pkh/blob/main/did-pkh-method-draft.md
#[derive(Clone, Debug, PartialEq)]
pub struct DidPkh {
chain_id: ChainId,
pub chain_id: ChainId,
pub address: String,
}
impl DidPkh {
pub fn from_address(currency: &Currency, address: &str) -> Self {
let chain_id = currency.chain_id();
let chain_id = match currency {
Currency::Ethereum => ChainId::ethereum_mainnet(),
Currency::Monero => unimplemented!(),
};
let address = currency.normalize_address(address);
Self { chain_id, address }
}

View file

@ -58,6 +58,7 @@ use crate::models::users::queries::{
get_user_by_did,
};
use crate::models::users::types::UserCreateData;
use crate::utils::caip2::ChainId;
use crate::utils::crypto::{
hash_password,
generate_private_key,
@ -238,7 +239,7 @@ async fn create_identity_proof(
let actor_id = current_user.profile.actor_id(&config.instance_url());
let did = proof_data.did.parse::<DidPkh>()
.map_err(|_| ValidationError("invalid DID"))?;
if did.currency() != Some(Currency::Ethereum) {
if did.chain_id != ChainId::ethereum_mainnet() {
// DID must point to Ethereum Mainnet because it is a valid
// identifier on any Ethereum chain
return Err(ValidationError("unsupported chain ID").into());

View file

@ -5,6 +5,8 @@ use regex::Regex;
use serde::{Deserialize, Deserializer, de::Error as DeserializerError};
const CAIP2_RE: &str = r"(?P<namespace>[-a-z0-9]{3,8}):(?P<reference>[-a-zA-Z0-9]{1,32})";
const CAIP2_ETHEREUM_NAMESPACE: &str = "eip155";
const ETHEREUM_MAINNET_ID: i32 = 1;
#[derive(Clone, Debug, PartialEq)]
pub struct ChainId {
@ -12,6 +14,15 @@ pub struct ChainId {
pub reference: String,
}
impl ChainId {
pub fn ethereum_mainnet() -> Self {
Self {
namespace: CAIP2_ETHEREUM_NAMESPACE.to_string(),
reference: ETHEREUM_MAINNET_ID.to_string(),
}
}
}
#[derive(thiserror::Error, Debug)]
#[error("Chain ID parse error")]
pub struct ChainIdError;

View file

@ -23,11 +23,6 @@ impl Currency {
format!("${}", self.code())
}
/// Returns CAIP-2 chain ID
pub fn chain_id(&self) -> ChainId {
self.into()
}
pub fn normalize_address(&self, address: &str) -> String {
match self {
Self::Ethereum => address.to_lowercase(),
@ -36,28 +31,13 @@ impl Currency {
}
}
impl From<&Currency> for ChainId {
fn from(value: &Currency) -> Self {
let (namespace, reference) = match value {
Currency::Ethereum => ("eip155", "1"),
Currency::Monero => unimplemented!(),
};
Self {
namespace: namespace.to_string(),
reference: reference.to_string(),
}
}
}
impl TryFrom<&ChainId> for Currency {
type Error = ConversionError;
fn try_from(value: &ChainId) -> Result<Self, Self::Error> {
let currency = match value.namespace.as_str() {
"eip155" => match value.reference.as_str() {
"1" => Self::Ethereum,
_ => return Err(ConversionError),
},
"eip155" => Self::Ethereum,
"monero" => Self::Monero, // not standard
_ => return Err(ConversionError),
};
Ok(currency)
@ -87,10 +67,16 @@ mod tests {
#[test]
fn test_chain_id_conversion() {
let ethereum = Currency::Ethereum;
let ethereum_chain_id = ChainId::from(&ethereum);
let ethereum_chain_id = ChainId::ethereum_mainnet();
let currency = Currency::try_from(&ethereum_chain_id).unwrap();
assert_eq!(currency, ethereum);
assert_eq!(currency, Currency::Ethereum);
let monero_chain_id = ChainId {
namespace: "monero".to_string(),
reference: "mainnet".to_string(),
};
let currency = Currency::try_from(&monero_chain_id).unwrap();
assert_eq!(currency, Currency::Monero);
}
#[test]