fathom_web3/contract/ens/
registry.rs

1//! ENS Registry contract interface.
2
3use crate::{
4    api::Eth,
5    contract::{Contract, Options},
6    signing::NameHash,
7    types::{Address, TransactionId},
8    Transport,
9};
10
11type ContractError = crate::contract::Error;
12
13const ENS_REGISTRY_ADDRESS: &str = "00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
14
15/// The ENS registry is the core contract that lies at the heart of ENS resolution.
16///
17/// All ENS lookups start by querying the registry.
18/// The registry maintains a list of domains, recording the owner, resolver, and TTL for each, and allows the owner of a domain to make changes to that data.
19///
20/// The ENS registry is specified in [EIP 137](https://eips.ethereum.org/EIPS/eip-137).
21///
22/// [Source](https://github.com/ensdomains/ens/blob/master/contracts/ENS.sol)
23#[derive(Debug, Clone)]
24pub struct Registry<T: Transport> {
25    contract: Contract<T>,
26}
27
28impl<T: Transport> Registry<T> {
29    /// Creates new instance of [`Registry`].
30    pub fn new(eth: Eth<T>) -> Self {
31        let address = ENS_REGISTRY_ADDRESS.parse().expect("Parsing Address");
32
33        // See https://github.com/ensdomains/ens-contracts for up to date contracts.
34        let json = include_bytes!("ENSRegistry.json");
35
36        let contract = Contract::from_json(eth, address, json).expect("Contract Creation");
37
38        Self { contract }
39    }
40}
41
42impl<T: Transport> Registry<T> {
43    /// Returns the owner of the name specified by node.
44    ///
45    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#get-owner)
46    pub async fn owner(&self, node: NameHash) -> Result<Address, ContractError> {
47        let options = Options::default();
48
49        self.contract.query("owner", node, None, options, None).await
50    }
51
52    /// Returns the address of the resolver responsible for the name specified by node.
53    ///
54    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#get-resolver)
55    pub async fn resolver(&self, node: NameHash) -> Result<Address, ContractError> {
56        let options = Options::default();
57
58        self.contract.query("resolver", node, None, options, None).await
59    }
60
61    /// Returns the caching time-to-live of the name specified by node.
62    ///
63    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#get-ttl)
64    pub async fn ttl(&self, node: NameHash) -> Result<u64, ContractError> {
65        let options = Options::default();
66
67        self.contract.query("ttl", node, None, options, None).await
68    }
69
70    /// Reassigns ownership of the name identified by node to owner.
71    ///
72    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#set-owner)
73    pub async fn set_owner(
74        &self,
75        from: Address,
76        node: NameHash,
77        owner: Address,
78    ) -> Result<TransactionId, ContractError> {
79        let options = Options::default();
80
81        let id = self.contract.call("setOwner", (node, owner), from, options).await?;
82
83        Ok(TransactionId::Hash(id))
84    }
85
86    /// Updates the resolver associated with the name identified by node to resolver.
87    ///
88    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#set-resolver)
89    pub async fn set_resolver(
90        &self,
91        from: Address,
92        node: NameHash,
93        resolver: Address,
94    ) -> Result<TransactionId, ContractError> {
95        let options = Options::default();
96
97        let id = self
98            .contract
99            .call("setResolver", (node, resolver), from, options)
100            .await?;
101
102        Ok(TransactionId::Hash(id))
103    }
104
105    /// Updates the caching time-to-live of the name identified by node.
106    ///
107    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#set-ttl)
108    pub async fn set_ttl(&self, from: Address, node: NameHash, ttl: u64) -> Result<TransactionId, ContractError> {
109        let options = Options::default();
110
111        let id = self.contract.call("setTTL", (node, ttl), from, options).await?;
112
113        Ok(TransactionId::Hash(id))
114    }
115
116    /// Creates a new subdomain of node, assigning ownership of it to the specified owner.
117    ///
118    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#set-subdomain-owner)
119    pub async fn set_subnode_owner(
120        &self,
121        from: Address,
122        node: NameHash,
123        label: [u8; 32],
124        owner: Address,
125    ) -> Result<TransactionId, ContractError> {
126        let options = Options::default();
127
128        let id = self
129            .contract
130            .call("setSubnodeOwner", (node, label, owner), from, options)
131            .await?;
132
133        Ok(TransactionId::Hash(id))
134    }
135
136    /// Sets the owner, resolver, and TTL for an ENS record in a single operation.
137    ///
138    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#set-record)
139    pub async fn set_record(
140        &self,
141        from: Address,
142        node: NameHash,
143        owner: Address,
144        resolver: Address,
145        ttl: u64,
146    ) -> Result<TransactionId, ContractError> {
147        let options = Options::default();
148
149        let id = self
150            .contract
151            .call("setRecord", (node, owner, resolver, ttl), from, options)
152            .await?;
153
154        Ok(TransactionId::Hash(id))
155    }
156
157    /// Sets the owner, resolver and TTL for a subdomain, creating it if necessary.
158    ///
159    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#set-subdomain-record)
160    pub async fn set_subnode_record(
161        &self,
162        from: Address,
163        node: NameHash,
164        label: [u8; 32],
165        owner: Address,
166        resolver: Address,
167        ttl: u64,
168    ) -> Result<TransactionId, ContractError> {
169        let options = Options::default();
170
171        let id = self
172            .contract
173            .call("setSubnodeRecord", (node, label, owner, resolver, ttl), from, options)
174            .await?;
175
176        Ok(TransactionId::Hash(id))
177    }
178
179    /// Sets or clears an approval.
180    ///
181    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#set-approval)
182    pub async fn set_approval_for_all(
183        &self,
184        from: Address,
185        operator: Address,
186        approved: bool,
187    ) -> Result<TransactionId, ContractError> {
188        let options = Options::default();
189
190        let id = self
191            .contract
192            .call("setApprovalForAll", (operator, approved), from, options)
193            .await?;
194
195        Ok(TransactionId::Hash(id))
196    }
197
198    /// Returns true if operator is approved to make ENS registry operations on behalf of owner.
199    ///
200    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#check-approval)
201    pub async fn check_approval(&self, owner: Address, operator: Address) -> Result<bool, ContractError> {
202        let options = Options::default();
203
204        self.contract
205            .query("isApprovedForAll", (owner, operator), None, options, None)
206            .await
207    }
208
209    /// Returns true if node exists in this ENS registry.
210    ///
211    /// [Specification](https://docs.ens.domains/contract-api-reference/ens#check-record-existence)
212    pub async fn check_record_existence(&self, node: NameHash) -> Result<bool, ContractError> {
213        let options = Options::default();
214
215        self.contract.query("recordExists", node, None, options, None).await
216    }
217}