This repository has been archived by the owner on Oct 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 794
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ENS avatar and TXT records resolution (#889)
* Add ENS avatar resolution As well as arbitrary fields. * Use try_join * Improve reqwest's error passing * Split avatar resolution in ERC token parsing and resolution * no_run examples * Rename token to NFT * A bit more documentation * Nightly cargo fmt * Use different ERC-721 test * Update CHANGELOG Co-authored-by: Georgios Konstantopoulos <[email protected]>
- Loading branch information
Showing
6 changed files
with
342 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
//! ERC related utilities. Only supporting NFTs for now. | ||
use ethers_core::types::{Address, Selector, U256}; | ||
|
||
use serde::Deserialize; | ||
use std::str::FromStr; | ||
use url::Url; | ||
|
||
/// ownerOf(uint256 tokenId) | ||
pub const ERC721_OWNER_SELECTOR: Selector = [0x63, 0x52, 0x21, 0x1e]; | ||
|
||
/// balanceOf(address owner, uint256 tokenId) | ||
pub const ERC1155_BALANCE_SELECTOR: Selector = [0x00, 0xfd, 0xd5, 0x8e]; | ||
|
||
const IPFS_GATEWAY: &str = "https://ipfs.io/ipfs/"; | ||
|
||
/// An ERC 721 or 1155 token | ||
pub struct ERCNFT { | ||
pub type_: ERCNFTType, | ||
pub contract: Address, | ||
pub id: [u8; 32], | ||
} | ||
|
||
impl FromStr for ERCNFT { | ||
type Err = String; | ||
fn from_str(input: &str) -> Result<ERCNFT, Self::Err> { | ||
let split: Vec<&str> = | ||
input.trim_start_matches("eip155:").trim_start_matches("1/").split(':').collect(); | ||
let (token_type, inner_path) = if split.len() == 2 { | ||
( | ||
ERCNFTType::from_str(split[0]) | ||
.map_err(|_| "Unsupported ERC token type".to_string())?, | ||
split[1], | ||
) | ||
} else { | ||
return Err("Unsupported ERC link".to_string()) | ||
}; | ||
|
||
let token_split: Vec<&str> = inner_path.split('/').collect(); | ||
let (contract_addr, token_id) = if token_split.len() == 2 { | ||
let token_id = U256::from_dec_str(token_split[1]) | ||
.map_err(|e| format!("Unsupported token id type: {} {}", token_split[1], e))?; | ||
let mut token_id_bytes = [0x0; 32]; | ||
token_id.to_big_endian(&mut token_id_bytes); | ||
( | ||
Address::from_str(token_split[0].trim_start_matches("0x")) | ||
.map_err(|e| format!("Invalid contract address: {} {}", token_split[0], e))?, | ||
token_id_bytes, | ||
) | ||
} else { | ||
return Err("Unsupported ERC link path".to_string()) | ||
}; | ||
Ok(ERCNFT { id: token_id, type_: token_type, contract: contract_addr }) | ||
} | ||
} | ||
|
||
/// Supported ERCs | ||
#[derive(PartialEq)] | ||
pub enum ERCNFTType { | ||
ERC721, | ||
ERC1155, | ||
} | ||
|
||
impl FromStr for ERCNFTType { | ||
type Err = (); | ||
fn from_str(input: &str) -> Result<ERCNFTType, Self::Err> { | ||
match input { | ||
"erc721" => Ok(ERCNFTType::ERC721), | ||
"erc1155" => Ok(ERCNFTType::ERC1155), | ||
_ => Err(()), | ||
} | ||
} | ||
} | ||
|
||
impl ERCNFTType { | ||
pub fn resolution_selector(&self) -> Selector { | ||
match self { | ||
// tokenURI(uint256) | ||
ERCNFTType::ERC721 => [0xc8, 0x7b, 0x56, 0xdd], | ||
// url(uint256) | ||
ERCNFTType::ERC1155 => [0x0e, 0x89, 0x34, 0x1c], | ||
} | ||
} | ||
} | ||
|
||
/// ERC-1155 and ERC-721 metadata document. | ||
#[derive(Deserialize)] | ||
pub struct Metadata { | ||
pub image: String, | ||
} | ||
|
||
/// Returns a HTTP url for an IPFS object. | ||
pub fn http_link_ipfs(url: Url) -> Result<Url, String> { | ||
Url::parse(IPFS_GATEWAY) | ||
.unwrap() | ||
.join(url.to_string().trim_start_matches("ipfs://").trim_start_matches("ipfs/")) | ||
.map_err(|e| e.to_string()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.