1mod account_id;
9mod asset_id;
10mod chain_id;
11pub mod error;
12mod validation;
13
14pub use account_id::AccountId;
15pub use asset_id::AssetId;
16pub use chain_id::ChainId;
17pub use error::Error;
18pub use validation::{ValidationRegistry, ValidatorFn};
19
20use std::str::FromStr;
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum CaipId {
25 ChainId(ChainId),
27 AccountId(AccountId),
29 AssetId(AssetId),
31}
32
33pub fn parse(s: &str) -> Result<CaipId, error::Error> {
46 if let Ok(chain_id) = ChainId::from_str(s) {
47 return Ok(CaipId::ChainId(chain_id));
48 }
49
50 if let Ok(account_id) = AccountId::from_str(s) {
51 return Ok(CaipId::AccountId(account_id));
52 }
53
54 if let Ok(asset_id) = AssetId::from_str(s) {
55 return Ok(CaipId::AssetId(asset_id));
56 }
57
58 Err(error::Error::UnrecognizedFormat(s.to_string()))
59}
60
61impl std::fmt::Display for CaipId {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 match self {
64 CaipId::ChainId(id) => write!(f, "{}", id),
65 CaipId::AccountId(id) => write!(f, "{}", id),
66 CaipId::AssetId(id) => write!(f, "{}", id),
67 }
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn test_parse_chain_id() {
77 let id = parse("eip155:1").unwrap();
78 match id {
79 CaipId::ChainId(chain_id) => {
80 assert_eq!(chain_id.namespace(), "eip155");
81 assert_eq!(chain_id.reference(), "1");
82 }
83 _ => panic!("Expected ChainId"),
84 }
85 }
86
87 #[test]
88 fn test_parse_account_id() {
89 let id = parse("eip155:1:0x4b20993Bc481177ec7E8f571ceCaE8A9e22C02db").unwrap();
90 match id {
91 CaipId::AccountId(account_id) => {
92 assert_eq!(account_id.chain_id().namespace(), "eip155");
93 assert_eq!(account_id.chain_id().reference(), "1");
94 assert_eq!(
95 account_id.address(),
96 "0x4b20993Bc481177ec7E8f571ceCaE8A9e22C02db"
97 );
98 }
99 _ => panic!("Expected AccountId"),
100 }
101 }
102
103 #[test]
104 fn test_parse_asset_id() {
105 let id = parse("eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48").unwrap();
106 match id {
107 CaipId::AssetId(asset_id) => {
108 assert_eq!(asset_id.chain_id().namespace(), "eip155");
109 assert_eq!(asset_id.chain_id().reference(), "1");
110 assert_eq!(asset_id.namespace(), "erc20");
111 assert_eq!(
112 asset_id.reference(),
113 "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
114 );
115 }
116 _ => panic!("Expected AssetId"),
117 }
118 }
119
120 #[test]
121 fn test_parse_invalid() {
122 assert!(parse("").is_err());
123 assert!(parse("invalid").is_err());
124 assert!(parse("foo:bar:baz:qux").is_err());
125 }
126
127 #[test]
128 fn test_caip_id_to_string() {
129 let chain_id = ChainId::from_str("eip155:1").unwrap();
130 let account_id =
131 AccountId::from_str("eip155:1:0x4b20993Bc481177ec7E8f571ceCaE8A9e22C02db").unwrap();
132 let asset_id =
133 AssetId::from_str("eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48").unwrap();
134
135 let chain_caip = CaipId::ChainId(chain_id);
136 let account_caip = CaipId::AccountId(account_id);
137 let asset_caip = CaipId::AssetId(asset_id);
138
139 assert_eq!(chain_caip.to_string(), "eip155:1");
140 assert_eq!(
141 account_caip.to_string(),
142 "eip155:1:0x4b20993Bc481177ec7E8f571ceCaE8A9e22C02db"
143 );
144 assert_eq!(
145 asset_caip.to_string(),
146 "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
147 );
148 }
149}