@ensdomains/ensjs 3.0.0-alpha.55 → 3.0.0-alpha.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -63,8 +63,8 @@ const addresses = {
63
63
  "5": "0x4f7A657451358a22dc397d5eE7981FfC526cd856"
64
64
  },
65
65
  UniversalResolver: {
66
- "1": "0xE4Acdd618deED4e6d2f03b9bf62dc6118FC9A4da",
67
- "5": "0xA292E2E58d4ddEb29C33c63173d0E8B7a2A4c62e"
66
+ "1": "0xc0497e381f536be9ce14b0dd3817cbcae57d2f62",
67
+ "5": "0x56522d00c410a43bffdf00a9a569489297385790"
68
68
  },
69
69
  BulkRenewal: {
70
70
  "1": "0xfF252725f6122A92551A5FA9a6b6bf10eb0Be035",
@@ -24,8 +24,10 @@ module.exports = __toCommonJS(getNames_exports);
24
24
  var import_format = require("../utils/format");
25
25
  var import_fuses = require("../utils/fuses");
26
26
  var import_labels = require("../utils/labels");
27
- const mapDomain = ({ name, ...domain }) => {
28
- const decrypted = name ? (0, import_labels.decryptName)(name) : void 0;
27
+ const mapDomain = (domain) => {
28
+ if (!domain)
29
+ return {};
30
+ const decrypted = domain.name ? (0, import_labels.decryptName)(domain.name) : void 0;
29
31
  return {
30
32
  ...domain,
31
33
  ...domain.registration ? {
@@ -59,15 +61,44 @@ const mapWrappedDomain = (wrappedDomain) => {
59
61
  };
60
62
  const mapRegistration = (registration) => {
61
63
  const decrypted = (0, import_labels.decryptName)(registration.domain.name);
64
+ const domain = mapDomain(registration.domain);
62
65
  return {
63
66
  expiryDate: new Date(parseInt(registration.expiryDate) * 1e3),
64
67
  registrationDate: new Date(parseInt(registration.registrationDate) * 1e3),
65
- ...registration.domain,
68
+ ...domain,
66
69
  name: decrypted,
67
70
  truncatedName: (0, import_format.truncateFormat)(decrypted),
68
71
  type: "registration"
69
72
  };
70
73
  };
74
+ const mapResolvedAddress = ({
75
+ wrappedDomain,
76
+ registration,
77
+ ...domain
78
+ }) => {
79
+ const mappedDomain = mapDomain(domain);
80
+ if (wrappedDomain) {
81
+ const mappedWrappedDomain = mapWrappedDomain(wrappedDomain);
82
+ if (!mappedWrappedDomain)
83
+ return null;
84
+ return {
85
+ ...mappedDomain,
86
+ ...mappedWrappedDomain,
87
+ owner: wrappedDomain.owner.id
88
+ };
89
+ }
90
+ return {
91
+ ...mappedDomain,
92
+ ...registration ? {
93
+ expiryDate: new Date(parseInt(registration.expiryDate) * 1e3),
94
+ registrationDate: new Date(
95
+ parseInt(registration.registrationDate) * 1e3
96
+ ),
97
+ owner: registration.registrant.id
98
+ } : {},
99
+ manager: domain.owner.id
100
+ };
101
+ };
71
102
  const getNames = async ({ gqlInstance }, {
72
103
  address: _address,
73
104
  type,
@@ -133,6 +164,46 @@ const getNames = async ({ gqlInstance }, {
133
164
  id: address,
134
165
  expiryDate: Math.floor(Date.now() / 1e3) - 90 * 24 * 60 * 60
135
166
  };
167
+ } else if (type === "resolvedAddress") {
168
+ finalQuery = gqlInstance.gql`
169
+ query getNames(
170
+ $id: String!
171
+ $orderBy: Domain_orderBy
172
+ $orderDirection: OrderDirection
173
+ ) {
174
+ domains(
175
+ first: 1000
176
+ where: {
177
+ resolvedAddress: $id
178
+ }
179
+ orderBy: $orderBy
180
+ orderDirection: $orderDirection
181
+ ) {
182
+ ${domainQueryData}
183
+ owner {
184
+ id
185
+ }
186
+ registration {
187
+ registrationDate
188
+ expiryDate
189
+ registrant {
190
+ id
191
+ }
192
+ }
193
+ wrappedDomain {
194
+ expiryDate
195
+ fuses
196
+ owner {
197
+ id
198
+ }
199
+ }
200
+ }
201
+ }`;
202
+ queryVars = {
203
+ id: address,
204
+ orderBy: orderBy === "labelName" ? "labelName" : "createdAt",
205
+ orderDirection: orderDirection === "asc" ? "asc" : "desc"
206
+ };
136
207
  } else if (type === "owner") {
137
208
  if (typeof page !== "number") {
138
209
  finalQuery = gqlInstance.gql`
@@ -332,6 +403,9 @@ const getNames = async ({ gqlInstance }, {
332
403
  return a.createdAt.getTime() - b.createdAt.getTime();
333
404
  });
334
405
  }
406
+ if (type === "resolvedAddress") {
407
+ return (response == null ? void 0 : response.domains.map(mapResolvedAddress).filter((d) => d)) || [];
408
+ }
335
409
  if (type === "owner") {
336
410
  return (account == null ? void 0 : account.domains.map(mapDomain)) || [];
337
411
  }
@@ -21,7 +21,7 @@ __export(getWrapperData_exports, {
21
21
  default: () => getWrapperData_default
22
22
  });
23
23
  module.exports = __toCommonJS(getWrapperData_exports);
24
- var import_bignumber = require("@ethersproject/bignumber");
24
+ var import_consts = require("../utils/consts");
25
25
  var import_fuses = require("../utils/fuses");
26
26
  var import_normalise = require("../utils/normalise");
27
27
  const raw = async ({ contracts }, name) => {
@@ -39,7 +39,15 @@ const decode = async ({ contracts }, data) => {
39
39
  data
40
40
  );
41
41
  const fuseObj = (0, import_fuses.decodeFuses)(fuses);
42
- const expiryDate = expiry.gt(0) && expiry.lt(import_bignumber.BigNumber.from(2).pow(32)) ? new Date(expiry.mul(1e3).toNumber()) : void 0;
42
+ let expiryDate;
43
+ if (expiry.gt(0)) {
44
+ const msBigNumber = expiry.mul(1e3);
45
+ if (msBigNumber.gte(import_consts.MAX_DATE_INT)) {
46
+ expiryDate = new Date(import_consts.MAX_DATE_INT);
47
+ } else {
48
+ expiryDate = new Date(msBigNumber.toNumber());
49
+ }
50
+ }
43
51
  return {
44
52
  ...fuseObj,
45
53
  expiryDate,
@@ -19,10 +19,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var consts_exports = {};
20
20
  __export(consts_exports, {
21
21
  EMPTY_ADDRESS: () => EMPTY_ADDRESS,
22
+ MAX_DATE_INT: () => MAX_DATE_INT,
22
23
  MAX_INT_64: () => MAX_INT_64,
23
24
  MINIMUM_DOT_ETH_CHARS: () => MINIMUM_DOT_ETH_CHARS
24
25
  });
25
26
  module.exports = __toCommonJS(consts_exports);
26
27
  const EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000";
27
28
  const MAX_INT_64 = BigInt("18446744073709551615");
29
+ const MAX_DATE_INT = 864e13;
28
30
  const MINIMUM_DOT_ETH_CHARS = 3;
@@ -41,8 +41,8 @@ var addresses = {
41
41
  "5": "0x4f7A657451358a22dc397d5eE7981FfC526cd856"
42
42
  },
43
43
  UniversalResolver: {
44
- "1": "0xE4Acdd618deED4e6d2f03b9bf62dc6118FC9A4da",
45
- "5": "0xA292E2E58d4ddEb29C33c63173d0E8B7a2A4c62e"
44
+ "1": "0xc0497e381f536be9ce14b0dd3817cbcae57d2f62",
45
+ "5": "0x56522d00c410a43bffdf00a9a569489297385790"
46
46
  },
47
47
  BulkRenewal: {
48
48
  "1": "0xfF252725f6122A92551A5FA9a6b6bf10eb0Be035",
@@ -2,8 +2,10 @@
2
2
  import { truncateFormat } from "../utils/format.mjs";
3
3
  import { checkPCCBurned, decodeFuses } from "../utils/fuses.mjs";
4
4
  import { decryptName } from "../utils/labels.mjs";
5
- var mapDomain = ({ name, ...domain }) => {
6
- const decrypted = name ? decryptName(name) : void 0;
5
+ var mapDomain = (domain) => {
6
+ if (!domain)
7
+ return {};
8
+ const decrypted = domain.name ? decryptName(domain.name) : void 0;
7
9
  return {
8
10
  ...domain,
9
11
  ...domain.registration ? {
@@ -37,15 +39,44 @@ var mapWrappedDomain = (wrappedDomain) => {
37
39
  };
38
40
  var mapRegistration = (registration) => {
39
41
  const decrypted = decryptName(registration.domain.name);
42
+ const domain = mapDomain(registration.domain);
40
43
  return {
41
44
  expiryDate: new Date(parseInt(registration.expiryDate) * 1e3),
42
45
  registrationDate: new Date(parseInt(registration.registrationDate) * 1e3),
43
- ...registration.domain,
46
+ ...domain,
44
47
  name: decrypted,
45
48
  truncatedName: truncateFormat(decrypted),
46
49
  type: "registration"
47
50
  };
48
51
  };
52
+ var mapResolvedAddress = ({
53
+ wrappedDomain,
54
+ registration,
55
+ ...domain
56
+ }) => {
57
+ const mappedDomain = mapDomain(domain);
58
+ if (wrappedDomain) {
59
+ const mappedWrappedDomain = mapWrappedDomain(wrappedDomain);
60
+ if (!mappedWrappedDomain)
61
+ return null;
62
+ return {
63
+ ...mappedDomain,
64
+ ...mappedWrappedDomain,
65
+ owner: wrappedDomain.owner.id
66
+ };
67
+ }
68
+ return {
69
+ ...mappedDomain,
70
+ ...registration ? {
71
+ expiryDate: new Date(parseInt(registration.expiryDate) * 1e3),
72
+ registrationDate: new Date(
73
+ parseInt(registration.registrationDate) * 1e3
74
+ ),
75
+ owner: registration.registrant.id
76
+ } : {},
77
+ manager: domain.owner.id
78
+ };
79
+ };
49
80
  var getNames = async ({ gqlInstance }, {
50
81
  address: _address,
51
82
  type,
@@ -111,6 +142,46 @@ var getNames = async ({ gqlInstance }, {
111
142
  id: address,
112
143
  expiryDate: Math.floor(Date.now() / 1e3) - 90 * 24 * 60 * 60
113
144
  };
145
+ } else if (type === "resolvedAddress") {
146
+ finalQuery = gqlInstance.gql`
147
+ query getNames(
148
+ $id: String!
149
+ $orderBy: Domain_orderBy
150
+ $orderDirection: OrderDirection
151
+ ) {
152
+ domains(
153
+ first: 1000
154
+ where: {
155
+ resolvedAddress: $id
156
+ }
157
+ orderBy: $orderBy
158
+ orderDirection: $orderDirection
159
+ ) {
160
+ ${domainQueryData}
161
+ owner {
162
+ id
163
+ }
164
+ registration {
165
+ registrationDate
166
+ expiryDate
167
+ registrant {
168
+ id
169
+ }
170
+ }
171
+ wrappedDomain {
172
+ expiryDate
173
+ fuses
174
+ owner {
175
+ id
176
+ }
177
+ }
178
+ }
179
+ }`;
180
+ queryVars = {
181
+ id: address,
182
+ orderBy: orderBy === "labelName" ? "labelName" : "createdAt",
183
+ orderDirection: orderDirection === "asc" ? "asc" : "desc"
184
+ };
114
185
  } else if (type === "owner") {
115
186
  if (typeof page !== "number") {
116
187
  finalQuery = gqlInstance.gql`
@@ -310,6 +381,9 @@ var getNames = async ({ gqlInstance }, {
310
381
  return a.createdAt.getTime() - b.createdAt.getTime();
311
382
  });
312
383
  }
384
+ if (type === "resolvedAddress") {
385
+ return response?.domains.map(mapResolvedAddress).filter((d) => d) || [];
386
+ }
313
387
  if (type === "owner") {
314
388
  return account?.domains.map(mapDomain) || [];
315
389
  }
@@ -1,5 +1,5 @@
1
1
  // src/functions/getWrapperData.ts
2
- import { BigNumber } from "@ethersproject/bignumber";
2
+ import { MAX_DATE_INT } from "../utils/consts.mjs";
3
3
  import { decodeFuses } from "../utils/fuses.mjs";
4
4
  import { namehash } from "../utils/normalise.mjs";
5
5
  var raw = async ({ contracts }, name) => {
@@ -17,7 +17,15 @@ var decode = async ({ contracts }, data) => {
17
17
  data
18
18
  );
19
19
  const fuseObj = decodeFuses(fuses);
20
- const expiryDate = expiry.gt(0) && expiry.lt(BigNumber.from(2).pow(32)) ? new Date(expiry.mul(1e3).toNumber()) : void 0;
20
+ let expiryDate;
21
+ if (expiry.gt(0)) {
22
+ const msBigNumber = expiry.mul(1e3);
23
+ if (msBigNumber.gte(MAX_DATE_INT)) {
24
+ expiryDate = new Date(MAX_DATE_INT);
25
+ } else {
26
+ expiryDate = new Date(msBigNumber.toNumber());
27
+ }
28
+ }
21
29
  return {
22
30
  ...fuseObj,
23
31
  expiryDate,
@@ -1,9 +1,11 @@
1
1
  // src/utils/consts.ts
2
2
  var EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000";
3
3
  var MAX_INT_64 = BigInt("18446744073709551615");
4
+ var MAX_DATE_INT = 864e13;
4
5
  var MINIMUM_DOT_ETH_CHARS = 3;
5
6
  export {
6
7
  EMPTY_ADDRESS,
8
+ MAX_DATE_INT,
7
9
  MAX_INT_64,
8
10
  MINIMUM_DOT_ETH_CHARS
9
11
  };
@@ -18,11 +18,13 @@ export declare type Name = {
18
18
  expiryDate: Date;
19
19
  registrationDate: Date;
20
20
  };
21
+ owner?: string;
22
+ manager?: string;
21
23
  type: 'domain' | 'registration' | 'wrappedDomain';
22
24
  };
23
25
  declare type BaseParams = {
24
26
  address: string;
25
- type: 'registrant' | 'owner' | 'wrappedOwner' | 'all';
27
+ type: 'registrant' | 'owner' | 'wrappedOwner' | 'all' | 'resolvedAddress';
26
28
  page?: number;
27
29
  pageSize?: number;
28
30
  orderDirection?: 'asc' | 'desc';
@@ -45,6 +47,12 @@ declare type AllParams = {
45
47
  page?: never;
46
48
  pageSize?: never;
47
49
  };
48
- declare type Params = BaseParams & (RegistrantParams | OwnerParams | WrappedOwnerParams | AllParams);
50
+ declare type ResolvedAddressParams = {
51
+ type: 'resolvedAddress';
52
+ orderBy?: 'labelName' | 'createdAt';
53
+ page?: never;
54
+ pageSize?: never;
55
+ };
56
+ declare type Params = BaseParams & (RegistrantParams | OwnerParams | WrappedOwnerParams | AllParams | ResolvedAddressParams);
49
57
  declare const getNames: ({ gqlInstance }: ENSArgs<'gqlInstance'>, { address: _address, type, page, pageSize, orderDirection, orderBy, }: Params) => Promise<Name[]>;
50
58
  export default getNames;
@@ -502,7 +502,7 @@ export declare class ENS {
502
502
  }>;
503
503
  getNames: (args_0: {
504
504
  address: string;
505
- type: "owner" | "wrappedOwner" | "registrant" | "all";
505
+ type: "owner" | "wrappedOwner" | "registrant" | "all" | "resolvedAddress";
506
506
  page?: number | undefined;
507
507
  pageSize?: number | undefined;
508
508
  orderDirection?: "asc" | "desc" | undefined;
@@ -520,6 +520,11 @@ export declare class ENS {
520
520
  orderBy?: "labelName" | "creationDate" | undefined;
521
521
  page?: undefined;
522
522
  pageSize?: undefined;
523
+ } | {
524
+ type: "resolvedAddress";
525
+ orderBy?: "labelName" | "createdAt" | undefined;
526
+ page?: undefined;
527
+ pageSize?: undefined;
523
528
  })) => Promise<import("./functions/getNames").Name[]>;
524
529
  getPrice: GeneratedRawFunction<{
525
530
  raw: ({ contracts, multicallWrapper }: ENSArgs<"contracts" | "multicallWrapper">, nameOrNames: string | string[], duration: number, legacy?: boolean | undefined) => Promise<{
@@ -1,3 +1,4 @@
1
1
  export declare const EMPTY_ADDRESS = "0x0000000000000000000000000000000000000000";
2
2
  export declare const MAX_INT_64: bigint;
3
+ export declare const MAX_DATE_INT = 8640000000000000;
3
4
  export declare const MINIMUM_DOT_ETH_CHARS = 3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ensdomains/ensjs",
3
- "version": "3.0.0-alpha.55",
3
+ "version": "3.0.0-alpha.57",
4
4
  "description": "ENS javascript library for contract interaction",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.mjs",
@@ -46,8 +46,8 @@ const addresses: Record<
46
46
  '5': '0x4f7A657451358a22dc397d5eE7981FfC526cd856',
47
47
  },
48
48
  UniversalResolver: {
49
- '1': '0xE4Acdd618deED4e6d2f03b9bf62dc6118FC9A4da',
50
- '5': '0xA292E2E58d4ddEb29C33c63173d0E8B7a2A4c62e',
49
+ '1': '0xc0497e381f536be9ce14b0dd3817cbcae57d2f62',
50
+ '5': '0x56522d00c410a43bffdf00a9a569489297385790',
51
51
  },
52
52
  BulkRenewal: {
53
53
  '1': '0xfF252725f6122A92551A5FA9a6b6bf10eb0Be035',
@@ -1,12 +1,17 @@
1
+ /* eslint-disable no-await-in-loop */
2
+ import { ethers } from 'ethers'
1
3
  import { ENS } from '..'
2
4
  import setup from '../tests/setup'
3
5
  import { Name } from './getNames'
4
6
  import { names as wrappedNames } from '../../deploy/00_register_wrapped'
5
7
 
6
8
  let ensInstance: ENS
9
+ let provider: ethers.providers.JsonRpcProvider
10
+ let accounts: string[]
7
11
 
8
12
  beforeAll(async () => {
9
- ;({ ensInstance } = await setup())
13
+ ;({ ensInstance, provider } = await setup())
14
+ accounts = await provider.listAccounts()
10
15
  })
11
16
 
12
17
  const testProperties = (obj: object, ...properties: string[]) =>
@@ -187,6 +192,70 @@ describe('getNames', () => {
187
192
  // the result here implies that the PCC expired name is not returned
188
193
  expect(pageOne).toHaveLength(nameCout - 1)
189
194
  })
195
+
196
+ describe('resolved addresses', () => {
197
+ /* eslint-disable @typescript-eslint/naming-convention */
198
+ const RESOLVED_ADDRESS_COUNT: { [key: string]: number } = {
199
+ '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266': 2,
200
+ '0x70997970C51812dc3A010C7d01b50e0d17dc79C8': 16,
201
+ '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC': 35,
202
+ }
203
+ /* eslint-enable @typescript-eslint/naming-convention */
204
+
205
+ it('should get the names that resolve to an address by labelName', async () => {
206
+ const ADDRESSES = [accounts[0], accounts[1], accounts[2]]
207
+ for (const ADDRESS of ADDRESSES) {
208
+ const pageOne = await ensInstance.getNames({
209
+ address: ADDRESS,
210
+ type: 'resolvedAddress',
211
+ orderBy: 'labelName',
212
+ orderDirection: 'asc',
213
+ })
214
+ expect(pageOne.length).toBe(RESOLVED_ADDRESS_COUNT[ADDRESS])
215
+ let prevLabelName = pageOne[0].labelName
216
+ for (const name of pageOne) {
217
+ expect(
218
+ !!name.labelName &&
219
+ prevLabelName &&
220
+ name.labelName >= prevLabelName,
221
+ ).toBe(true)
222
+ prevLabelName = name.labelName
223
+ const profile = await ensInstance.getProfile(name.name)
224
+ const eth = profile?.records?.coinTypes?.find(
225
+ (coin) => coin.coin === 'ETH',
226
+ )
227
+ expect((eth as any).addr).toBe(ADDRESS)
228
+ }
229
+ }
230
+ })
231
+
232
+ it('should get the names that resolve to an address by creationDate', async () => {
233
+ const ADDRESSES = [accounts[0], accounts[1], accounts[2]]
234
+ for (const ADDRESS of ADDRESSES) {
235
+ const pageOne = await ensInstance.getNames({
236
+ address: ADDRESS,
237
+ type: 'resolvedAddress',
238
+ orderBy: 'createdAt',
239
+ orderDirection: 'desc',
240
+ })
241
+ expect(pageOne.length).toBe(RESOLVED_ADDRESS_COUNT[ADDRESS])
242
+ let prevCreatedAt = pageOne[0].createdAt?.getTime()
243
+ for (const name of pageOne) {
244
+ expect(
245
+ !!name.createdAt &&
246
+ !!prevCreatedAt &&
247
+ name.createdAt.getTime() <= prevCreatedAt,
248
+ ).toBe(true)
249
+ prevCreatedAt = name.createdAt?.getTime()
250
+ const profile = await ensInstance.getProfile(name.name)
251
+ const eth = profile?.records?.coinTypes?.find(
252
+ (coin) => coin.coin === 'ETH',
253
+ )
254
+ expect((eth as any).addr).toBe(ADDRESS)
255
+ }
256
+ }
257
+ })
258
+ })
190
259
  describe('orderBy', () => {
191
260
  describe('registrations', () => {
192
261
  it('descending registrationDate', async () => {
@@ -22,12 +22,14 @@ export type Name = {
22
22
  expiryDate: Date
23
23
  registrationDate: Date
24
24
  }
25
+ owner?: string
26
+ manager?: string
25
27
  type: 'domain' | 'registration' | 'wrappedDomain'
26
28
  }
27
29
 
28
30
  type BaseParams = {
29
31
  address: string
30
- type: 'registrant' | 'owner' | 'wrappedOwner' | 'all'
32
+ type: 'registrant' | 'owner' | 'wrappedOwner' | 'all' | 'resolvedAddress'
31
33
  page?: number
32
34
  pageSize?: number
33
35
  orderDirection?: 'asc' | 'desc'
@@ -55,12 +57,26 @@ type AllParams = {
55
57
  pageSize?: never
56
58
  }
57
59
 
60
+ type ResolvedAddressParams = {
61
+ type: 'resolvedAddress'
62
+ orderBy?: 'labelName' | 'createdAt'
63
+ page?: never
64
+ pageSize?: never
65
+ }
66
+
58
67
  type Params = BaseParams &
59
- (RegistrantParams | OwnerParams | WrappedOwnerParams | AllParams)
68
+ (
69
+ | RegistrantParams
70
+ | OwnerParams
71
+ | WrappedOwnerParams
72
+ | AllParams
73
+ | ResolvedAddressParams
74
+ )
60
75
 
61
- const mapDomain = ({ name, ...domain }: Domain) => {
62
- const decrypted = name ? decryptName(name) : undefined
76
+ const mapDomain = (domain?: Domain) => {
77
+ if (!domain) return {}
63
78
 
79
+ const decrypted = domain.name ? decryptName(domain.name) : undefined
64
80
  return {
65
81
  ...domain,
66
82
  ...(domain.registration
@@ -112,16 +128,48 @@ const mapWrappedDomain = (wrappedDomain: WrappedDomain) => {
112
128
 
113
129
  const mapRegistration = (registration: Registration) => {
114
130
  const decrypted = decryptName(registration.domain.name!)
131
+ const domain = mapDomain(registration.domain)
115
132
  return {
116
133
  expiryDate: new Date(parseInt(registration.expiryDate) * 1000),
117
134
  registrationDate: new Date(parseInt(registration.registrationDate) * 1000),
118
- ...registration.domain,
135
+ ...domain,
119
136
  name: decrypted,
120
137
  truncatedName: truncateFormat(decrypted),
121
138
  type: 'registration',
122
139
  }
123
140
  }
124
141
 
142
+ const mapResolvedAddress = ({
143
+ wrappedDomain,
144
+ registration,
145
+ ...domain
146
+ }: Domain) => {
147
+ const mappedDomain = mapDomain(domain)
148
+ if (wrappedDomain) {
149
+ const mappedWrappedDomain = mapWrappedDomain(wrappedDomain)
150
+ // If wrapped domain is expired then filter it out.
151
+ if (!mappedWrappedDomain) return null
152
+ return {
153
+ ...mappedDomain,
154
+ ...mappedWrappedDomain,
155
+ owner: wrappedDomain.owner.id,
156
+ }
157
+ }
158
+ return {
159
+ ...mappedDomain,
160
+ ...(registration
161
+ ? {
162
+ expiryDate: new Date(parseInt(registration.expiryDate) * 1000),
163
+ registrationDate: new Date(
164
+ parseInt(registration.registrationDate) * 1000,
165
+ ),
166
+ owner: registration.registrant.id,
167
+ }
168
+ : {}),
169
+ manager: domain.owner.id,
170
+ }
171
+ }
172
+
125
173
  const getNames = async (
126
174
  { gqlInstance }: ENSArgs<'gqlInstance'>,
127
175
  {
@@ -192,6 +240,47 @@ const getNames = async (
192
240
  id: address,
193
241
  expiryDate: Math.floor(Date.now() / 1000) - 90 * 24 * 60 * 60,
194
242
  }
243
+ } else if (type === 'resolvedAddress') {
244
+ finalQuery = gqlInstance.gql`
245
+ query getNames(
246
+ $id: String!
247
+ $orderBy: Domain_orderBy
248
+ $orderDirection: OrderDirection
249
+ ) {
250
+ domains(
251
+ first: 1000
252
+ where: {
253
+ resolvedAddress: $id
254
+ }
255
+ orderBy: $orderBy
256
+ orderDirection: $orderDirection
257
+ ) {
258
+ ${domainQueryData}
259
+ owner {
260
+ id
261
+ }
262
+ registration {
263
+ registrationDate
264
+ expiryDate
265
+ registrant {
266
+ id
267
+ }
268
+ }
269
+ wrappedDomain {
270
+ expiryDate
271
+ fuses
272
+ owner {
273
+ id
274
+ }
275
+ }
276
+ }
277
+ }`
278
+
279
+ queryVars = {
280
+ id: address,
281
+ orderBy: orderBy === 'labelName' ? 'labelName' : 'createdAt',
282
+ orderDirection: orderDirection === 'asc' ? 'asc' : 'desc',
283
+ }
195
284
  } else if (type === 'owner') {
196
285
  if (typeof page !== 'number') {
197
286
  finalQuery = gqlInstance.gql`
@@ -398,6 +487,10 @@ const getNames = async (
398
487
  return a.createdAt.getTime() - b.createdAt.getTime()
399
488
  }) as Name[]
400
489
  }
490
+ if (type === 'resolvedAddress') {
491
+ return (response?.domains.map(mapResolvedAddress).filter((d: any) => d) ||
492
+ []) as Name[]
493
+ }
401
494
  if (type === 'owner') {
402
495
  return (account?.domains.map(mapDomain) || []) as Name[]
403
496
  }
@@ -69,4 +69,22 @@ describe('getWrapperData', () => {
69
69
  expect(Number.isNaN(result.expiryDate?.getTime())).toBe(false)
70
70
  }
71
71
  })
72
+ it('should return correct expiry for large expiry', async () => {
73
+ const result = await ensInstance.getWrapperData('wrapped-big-duration.eth')
74
+ expect(result).toBeTruthy()
75
+ if (result) {
76
+ expect(result.expiryDate).toBeInstanceOf(Date)
77
+ expect(result.expiryDate!.getFullYear()).toBe(275760)
78
+ expect(Number.isNaN(result.expiryDate?.getTime())).toBe(false)
79
+ }
80
+ })
81
+ it('should return correct max expiry for expiry larger than maximum for date', async () => {
82
+ const result = await ensInstance.getWrapperData('wrapped-max-duration.eth')
83
+ expect(result).toBeTruthy()
84
+ if (result) {
85
+ expect(result.expiryDate).toBeInstanceOf(Date)
86
+ expect(result.expiryDate!.getFullYear()).toBe(275760)
87
+ expect(Number.isNaN(result.expiryDate?.getTime())).toBe(false)
88
+ }
89
+ })
72
90
  })
@@ -1,5 +1,6 @@
1
1
  import { BigNumber } from '@ethersproject/bignumber'
2
2
  import { ENSArgs } from '../index'
3
+ import { MAX_DATE_INT } from '../utils/consts'
3
4
  import { decodeFuses } from '../utils/fuses'
4
5
  import { namehash } from '../utils/normalise'
5
6
 
@@ -21,10 +22,16 @@ const decode = async ({ contracts }: ENSArgs<'contracts'>, data: string) => {
21
22
 
22
23
  const fuseObj = decodeFuses(fuses)
23
24
 
24
- const expiryDate =
25
- expiry.gt(0) && expiry.lt(BigNumber.from(2).pow(32))
26
- ? new Date(expiry.mul(1000).toNumber())
27
- : undefined
25
+ let expiryDate: Date | undefined
26
+
27
+ if (expiry.gt(0)) {
28
+ const msBigNumber = expiry.mul(1000)
29
+ if (msBigNumber.gte(MAX_DATE_INT)) {
30
+ expiryDate = new Date(MAX_DATE_INT)
31
+ } else {
32
+ expiryDate = new Date(msBigNumber.toNumber())
33
+ }
34
+ }
28
35
 
29
36
  return {
30
37
  ...fuseObj,
@@ -1,3 +1,4 @@
1
1
  export const EMPTY_ADDRESS = '0x0000000000000000000000000000000000000000'
2
2
  export const MAX_INT_64 = BigInt('18446744073709551615')
3
+ export const MAX_DATE_INT = 8640000000000000
3
4
  export const MINIMUM_DOT_ETH_CHARS = 3