Use Currency enum to refer to CAIP-2 namespaces instead of chain IDs
This commit is contained in:
parent
8df8fd3c8c
commit
690a03946e
4 changed files with 29 additions and 28 deletions
|
@ -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
|
// https://github.com/w3c-ccg/did-pkh/blob/main/did-pkh-method-draft.md
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct DidPkh {
|
pub struct DidPkh {
|
||||||
chain_id: ChainId,
|
pub chain_id: ChainId,
|
||||||
pub address: String,
|
pub address: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DidPkh {
|
impl DidPkh {
|
||||||
pub fn from_address(currency: &Currency, address: &str) -> Self {
|
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);
|
let address = currency.normalize_address(address);
|
||||||
Self { chain_id, address }
|
Self { chain_id, address }
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ use crate::models::users::queries::{
|
||||||
get_user_by_did,
|
get_user_by_did,
|
||||||
};
|
};
|
||||||
use crate::models::users::types::UserCreateData;
|
use crate::models::users::types::UserCreateData;
|
||||||
|
use crate::utils::caip2::ChainId;
|
||||||
use crate::utils::crypto::{
|
use crate::utils::crypto::{
|
||||||
hash_password,
|
hash_password,
|
||||||
generate_private_key,
|
generate_private_key,
|
||||||
|
@ -238,7 +239,7 @@ async fn create_identity_proof(
|
||||||
let actor_id = current_user.profile.actor_id(&config.instance_url());
|
let actor_id = current_user.profile.actor_id(&config.instance_url());
|
||||||
let did = proof_data.did.parse::<DidPkh>()
|
let did = proof_data.did.parse::<DidPkh>()
|
||||||
.map_err(|_| ValidationError("invalid DID"))?;
|
.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
|
// DID must point to Ethereum Mainnet because it is a valid
|
||||||
// identifier on any Ethereum chain
|
// identifier on any Ethereum chain
|
||||||
return Err(ValidationError("unsupported chain ID").into());
|
return Err(ValidationError("unsupported chain ID").into());
|
||||||
|
|
|
@ -5,6 +5,8 @@ use regex::Regex;
|
||||||
use serde::{Deserialize, Deserializer, de::Error as DeserializerError};
|
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_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)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct ChainId {
|
pub struct ChainId {
|
||||||
|
@ -12,6 +14,15 @@ pub struct ChainId {
|
||||||
pub reference: String,
|
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)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
#[error("Chain ID parse error")]
|
#[error("Chain ID parse error")]
|
||||||
pub struct ChainIdError;
|
pub struct ChainIdError;
|
||||||
|
|
|
@ -23,11 +23,6 @@ impl Currency {
|
||||||
format!("${}", self.code())
|
format!("${}", self.code())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns CAIP-2 chain ID
|
|
||||||
pub fn chain_id(&self) -> ChainId {
|
|
||||||
self.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn normalize_address(&self, address: &str) -> String {
|
pub fn normalize_address(&self, address: &str) -> String {
|
||||||
match self {
|
match self {
|
||||||
Self::Ethereum => address.to_lowercase(),
|
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 {
|
impl TryFrom<&ChainId> for Currency {
|
||||||
type Error = ConversionError;
|
type Error = ConversionError;
|
||||||
|
|
||||||
fn try_from(value: &ChainId) -> Result<Self, Self::Error> {
|
fn try_from(value: &ChainId) -> Result<Self, Self::Error> {
|
||||||
let currency = match value.namespace.as_str() {
|
let currency = match value.namespace.as_str() {
|
||||||
"eip155" => match value.reference.as_str() {
|
"eip155" => Self::Ethereum,
|
||||||
"1" => Self::Ethereum,
|
"monero" => Self::Monero, // not standard
|
||||||
_ => return Err(ConversionError),
|
|
||||||
},
|
|
||||||
_ => return Err(ConversionError),
|
_ => return Err(ConversionError),
|
||||||
};
|
};
|
||||||
Ok(currency)
|
Ok(currency)
|
||||||
|
@ -87,10 +67,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_chain_id_conversion() {
|
fn test_chain_id_conversion() {
|
||||||
let ethereum = Currency::Ethereum;
|
let ethereum_chain_id = ChainId::ethereum_mainnet();
|
||||||
let ethereum_chain_id = ChainId::from(ðereum);
|
|
||||||
let currency = Currency::try_from(ðereum_chain_id).unwrap();
|
let currency = Currency::try_from(ðereum_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]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue