ethers_providers/ext/
erc.rs1use ethers_core::types::{Address, Selector, U256};
3
4use serde::Deserialize;
5use std::str::FromStr;
6use url::Url;
7
8pub const ERC721_OWNER_SELECTOR: Selector = [0x63, 0x52, 0x21, 0x1e];
10
11pub const ERC1155_BALANCE_SELECTOR: Selector = [0x00, 0xfd, 0xd5, 0x8e];
13
14const IPFS_GATEWAY: &str = "https://ipfs.io/ipfs/";
15
16pub struct ERCNFT {
18 pub type_: ERCNFTType,
20 pub contract: Address,
22 pub id: [u8; 32],
24}
25
26impl FromStr for ERCNFT {
27 type Err = String;
28 fn from_str(input: &str) -> Result<ERCNFT, Self::Err> {
29 let split: Vec<&str> =
30 input.trim_start_matches("eip155:").trim_start_matches("1/").split(':').collect();
31 let (token_type, inner_path) = if split.len() == 2 {
32 (
33 ERCNFTType::from_str(split[0])
34 .map_err(|_| "Unsupported ERC token type".to_string())?,
35 split[1],
36 )
37 } else {
38 return Err("Unsupported ERC link".to_string())
39 };
40
41 let token_split: Vec<&str> = inner_path.split('/').collect();
42 let (contract_addr, token_id) = if token_split.len() == 2 {
43 let token_id = U256::from_dec_str(token_split[1])
44 .map_err(|e| format!("Unsupported token id type: {} {e}", token_split[1]))?;
45 let mut token_id_bytes = [0x0; 32];
46 token_id.to_big_endian(&mut token_id_bytes);
47 (
48 Address::from_str(token_split[0].trim_start_matches("0x"))
49 .map_err(|e| format!("Invalid contract address: {} {e}", token_split[0]))?,
50 token_id_bytes,
51 )
52 } else {
53 return Err("Unsupported ERC link path".to_string())
54 };
55 Ok(ERCNFT { id: token_id, type_: token_type, contract: contract_addr })
56 }
57}
58
59#[derive(PartialEq, Eq)]
61pub enum ERCNFTType {
62 ERC721,
64 ERC1155,
66}
67
68impl FromStr for ERCNFTType {
69 type Err = ();
70 fn from_str(input: &str) -> Result<ERCNFTType, Self::Err> {
71 match input {
72 "erc721" => Ok(ERCNFTType::ERC721),
73 "erc1155" => Ok(ERCNFTType::ERC1155),
74 _ => Err(()),
75 }
76 }
77}
78
79impl ERCNFTType {
80 pub const fn resolution_selector(&self) -> Selector {
82 match self {
83 ERCNFTType::ERC721 => [0xc8, 0x7b, 0x56, 0xdd],
85 ERCNFTType::ERC1155 => [0x0e, 0x89, 0x34, 0x1c],
87 }
88 }
89}
90
91#[derive(Deserialize)]
93pub struct Metadata {
94 pub image: String,
96}
97
98pub fn http_link_ipfs(url: Url) -> Result<Url, String> {
100 Url::parse(IPFS_GATEWAY)
101 .unwrap()
102 .join(url.to_string().trim_start_matches("ipfs://").trim_start_matches("ipfs/"))
103 .map_err(|e| e.to_string())
104}