eth_prices/token/
identity.rs1use std::fmt::Display;
2
3use alloy::primitives::Address;
4use serde::{Deserialize, Deserializer};
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8pub enum TokenIdentifier {
9 ERC20 { address: Address },
11 Fiat { symbol: String },
13 Native,
15}
16
17impl From<Address> for TokenIdentifier {
18 fn from(address: Address) -> Self {
19 TokenIdentifier::ERC20 { address }
20 }
21}
22
23impl TryFrom<String> for TokenIdentifier {
24 type Error = crate::error::EthPricesError;
25
26 fn try_from(input: String) -> Result<Self, Self::Error> {
28 if input == "native" {
29 Ok(TokenIdentifier::Native)
30 } else if input.starts_with("fiat:") {
31 let symbol = input
32 .split("fiat:")
33 .nth(1)
34 .ok_or(crate::error::EthPricesError::InvalidFiatSymbol)?
35 .to_string();
36
37 Ok(TokenIdentifier::Fiat { symbol })
38 } else if input.starts_with("0x") {
39 let address = input
40 .parse::<Address>()
41 .map_err(|e| crate::error::EthPricesError::InvalidAddress(e.to_string()))?;
42
43 Ok(TokenIdentifier::ERC20 { address })
44 } else {
45 Err(crate::error::EthPricesError::TokenNotFound(input))
46 }
47 }
48}
49
50impl Display for TokenIdentifier {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 match self {
53 TokenIdentifier::ERC20 { address } => write!(f, "{}", address),
54 TokenIdentifier::Fiat { symbol } => write!(f, "fiat:{}", symbol),
55 TokenIdentifier::Native => write!(f, "native"),
56 }
57 }
58}
59
60impl<'de> Deserialize<'de> for TokenIdentifier {
61 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
62 where
63 D: Deserializer<'de>,
64 {
65 let s = String::deserialize(deserializer)?;
66 TokenIdentifier::try_from(s).map_err(serde::de::Error::custom)
67 }
68}