eth_avatars/modules/ethereum/
resolver.rs1use async_trait::async_trait;
2
3use super::{
4 ContractType, Ethereum,
5 abi::{IERC721, IERC1155},
6};
7use crate::{FetchError, Fetcher, Resource, modules::ethereum::nft::NftMetadataDecoder};
8
9use alloy::{primitives::ChainId, providers::DynProvider};
10
11pub struct EthereumResolver {
16 provider: DynProvider,
17 network_id: ChainId,
18}
19
20impl EthereumResolver {
21 pub fn new(network_id: ChainId, provider: DynProvider) -> Self {
22 Self {
23 network_id,
24 provider,
25 }
26 }
27}
28
29#[async_trait]
30impl Fetcher for EthereumResolver {
31 type Locator = Ethereum;
32
33 fn accepts(&self, locator: &Ethereum) -> bool {
34 locator.network_id == self.network_id
35 }
36
37 async fn fetch(&self, locator: &Ethereum) -> Result<Resource, FetchError> {
38 let url = match locator.contract_type {
39 ContractType::ERC721 => {
40 IERC721::new(locator.contract, &self.provider)
41 .tokenURI(locator.token_id)
42 .call()
43 .await
44 }
45 ContractType::ERC1155 => {
46 IERC1155::new(locator.contract, &self.provider)
47 .uri(locator.token_id)
48 .call()
49 .await
50 }
51 }?;
52 let url = url.replace("{id}", &locator.token_id.to_string());
53
54 Ok(url.parse::<Resource>()?.decoded_by(NftMetadataDecoder))
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use std::str::FromStr;
61
62 use crate::{modules::http::Http, utils::test::get_test_provider};
63
64 use super::*;
65
66 #[tokio::test]
67 async fn eip155_opensea() {
68 let input: Ethereum = "eip155:1/erc1155:0x495f947276749ce646f68ac8c248420045cb7b5e/109791375735522898048150917964456965919994596086232976516654423066184641413121"
69 .parse()
70 .unwrap();
71 let provider = get_test_provider().await;
72
73 let gateway = EthereumResolver::new(1, provider);
74 let Resource::Decode { source, .. } = gateway.fetch(&input).await.unwrap() else {
75 panic!("expected a decode step");
76 };
77 let Resource::Http(url) = *source else {
78 panic!("expected an http metadata source");
79 };
80
81 assert_eq!(
82 url,
83 Http::from_str(
84 "https://api.opensea.io/api/v1/metadata/0x495f947276749Ce646f68AC8c248420045cb7b5e/0x109791375735522898048150917964456965919994596086232976516654423066184641413121"
85 )
86 .unwrap()
87 );
88 }
89}