-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathlookupDomains.ts
More file actions
128 lines (110 loc) · 3.29 KB
/
lookupDomains.ts
File metadata and controls
128 lines (110 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import snapshot from '@snapshot-labs/snapshot.js';
import { capture } from '@snapshot-labs/snapshot-sentry';
import { EMPTY_ADDRESS, isSilencedError } from './addressResolvers/utils';
import { Address, graphQlCall } from './utils';
import { provider as getProvider } from './addressResolvers/utils';
import { isAddress } from '@ethersproject/address';
import { namehash } from '@ethersproject/hash';
import constants from './constants.json';
const DEFAULT_CHAIN_ID = '1';
type Domain = {
name: string;
labelName?: string;
expiryDate?: number;
};
async function fetchDomainData(domain: Domain, chainId: string): Promise<Domain> {
const hash = domain.name.match(/\[(.*?)\]/)?.[1];
if (!hash) return domain;
const {
data: { data }
} = await graphQlCall(
constants.ensSubgraph[chainId],
`query Registration {
registration(id: "0x${hash}") {
domain {
name
labelName
}
}
}`
);
const labelName = data?.registration?.domain?.labelName;
return {
...domain,
name: labelName ? domain.name.replace(`[${hash}]`, labelName) : domain.name
};
}
/*
* see https://docs.ens.domains/registry/reverse
*/
async function getDomainFromReverseRegistrar(
address: Address,
chainId: string
): Promise<Domain | null> {
const provider = getProvider(chainId);
const abi = ['function name(bytes32 node) view returns (string r)'];
const reverseName = `${address.toLowerCase().substring(2)}.addr.reverse`;
const hash = namehash(reverseName);
const resolver = await provider.getResolver(reverseName);
if (!resolver) {
return null;
}
const resolverAddress = await resolver.address;
if (!resolverAddress || resolverAddress === EMPTY_ADDRESS) {
return null;
}
const domainName = await snapshot.utils.call(provider, abi, [resolverAddress, 'name', [hash]]);
return { name: domainName };
}
export default async function lookupDomains(
address: Address,
chainId = DEFAULT_CHAIN_ID
): Promise<Address[]> {
if (!isAddress(address) || !constants.ensSubgraph[chainId]) return [];
let domains: Domain[] = [];
try {
const {
data: {
data: { account }
}
} = await graphQlCall(
constants.ensSubgraph[chainId],
`query Domain {
account(id: "${address.toLowerCase()}") {
domains {
name
expiryDate
}
wrappedDomains {
name
expiryDate
}
}
}`
);
const now = (Date.now() / 1000).toFixed(0);
domains = [...(account?.domains || []), ...(account?.wrappedDomains || [])].filter(
domain =>
(!domain.expiryDate || domain.expiryDate === '0' || domain.expiryDate > now) &&
!domain.name.endsWith('.addr.reverse')
);
} catch (e) {
if (!isSilencedError(e)) {
capture(e, { input: { address } });
}
}
try {
const results = await Promise.allSettled([
...domains.map(domain => fetchDomainData(domain, chainId)),
getDomainFromReverseRegistrar(address, chainId)
]);
return results
.filter(result => result.status === 'fulfilled' && result.value !== null)
.map(result => (result as PromiseFulfilledResult<Domain>).value.name);
} catch (e) {
if (!isSilencedError(e)) {
capture(e, { input: { address } });
}
return [];
}
}