@ensdomains/ensjs 3.0.0-alpha.1 → 3.0.0-alpha.4

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.
Files changed (94) hide show
  1. package/README.md +2 -0
  2. package/dist/cjs/functions/burnFuses.d.ts +1 -2
  3. package/dist/cjs/functions/burnFuses.js +3 -3
  4. package/dist/cjs/functions/createSubname.js +2 -1
  5. package/dist/cjs/functions/getDNSOwner.d.ts +7 -0
  6. package/dist/cjs/functions/getDNSOwner.js +81 -0
  7. package/dist/cjs/functions/getFuses.js +3 -2
  8. package/dist/cjs/functions/getOwner.js +7 -6
  9. package/dist/cjs/functions/getProfile.d.ts +1 -1
  10. package/dist/cjs/functions/getProfile.js +49 -15
  11. package/dist/cjs/functions/getSpecificRecord.js +22 -5
  12. package/dist/cjs/functions/getSubnames.js +6 -6
  13. package/dist/cjs/functions/setRecords.d.ts +1 -2
  14. package/dist/cjs/functions/setRecords.js +3 -3
  15. package/dist/cjs/functions/setResolver.d.ts +1 -2
  16. package/dist/cjs/functions/setResolver.js +3 -3
  17. package/dist/cjs/functions/transferName.js +3 -2
  18. package/dist/cjs/functions/transferSubname.js +2 -1
  19. package/dist/cjs/functions/unwrapName.js +2 -1
  20. package/dist/cjs/index.d.ts +1 -0
  21. package/dist/cjs/index.js +2 -0
  22. package/dist/cjs/utils/makeHashIndexes.js +2 -2
  23. package/dist/cjs/utils/normalise.d.ts +1 -0
  24. package/dist/cjs/utils/normalise.js +20 -1
  25. package/dist/cjs/utils/registerHelpers.js +3 -4
  26. package/dist/esm/functions/burnFuses.d.ts +1 -2
  27. package/dist/esm/functions/burnFuses.js +3 -3
  28. package/dist/esm/functions/createSubname.js +2 -1
  29. package/dist/esm/functions/getDNSOwner.d.ts +7 -0
  30. package/dist/esm/functions/getDNSOwner.js +51 -0
  31. package/dist/esm/functions/getFuses.js +4 -3
  32. package/dist/esm/functions/getOwner.js +7 -6
  33. package/dist/esm/functions/getProfile.d.ts +1 -1
  34. package/dist/esm/functions/getProfile.js +49 -15
  35. package/dist/esm/functions/getSpecificRecord.js +22 -5
  36. package/dist/esm/functions/getSubnames.js +3 -3
  37. package/dist/esm/functions/setRecords.d.ts +1 -2
  38. package/dist/esm/functions/setRecords.js +3 -3
  39. package/dist/esm/functions/setResolver.d.ts +1 -2
  40. package/dist/esm/functions/setResolver.js +3 -3
  41. package/dist/esm/functions/transferName.js +3 -2
  42. package/dist/esm/functions/transferSubname.js +2 -1
  43. package/dist/esm/functions/unwrapName.js +2 -1
  44. package/dist/esm/index.d.ts +1 -0
  45. package/dist/esm/index.js +2 -0
  46. package/dist/esm/utils/makeHashIndexes.js +2 -2
  47. package/dist/esm/utils/normalise.d.ts +1 -0
  48. package/dist/esm/utils/normalise.js +18 -0
  49. package/dist/esm/utils/registerHelpers.js +3 -4
  50. package/package.json +11 -5
  51. package/src/@types/dns-packet/index.d.ts +114 -0
  52. package/src/{tests → functions}/batch.test.ts +1 -1
  53. package/src/{tests → functions}/batchWrappers.test.ts +1 -1
  54. package/src/{tests → functions}/burnFuses.test.ts +4 -3
  55. package/src/functions/burnFuses.ts +3 -3
  56. package/src/{tests → functions}/createSubname.test.ts +5 -6
  57. package/src/functions/createSubname.ts +2 -1
  58. package/src/{tests → functions}/deleteSubname.test.ts +5 -6
  59. package/src/functions/getDNSOwner.test.ts +122 -0
  60. package/src/functions/getDNSOwner.ts +61 -0
  61. package/src/{tests → functions}/getExpiry.test.ts +1 -1
  62. package/src/{tests → functions}/getFuses.test.ts +1 -1
  63. package/src/functions/getFuses.ts +4 -3
  64. package/src/{tests → functions}/getHistory.test.ts +1 -1
  65. package/src/{tests → functions}/getName.test.ts +1 -1
  66. package/src/{tests → functions}/getNames.test.ts +1 -1
  67. package/src/{tests → functions}/getOwner.test.ts +11 -1
  68. package/src/functions/getOwner.ts +7 -7
  69. package/src/{tests → functions}/getProfile.test.ts +29 -11
  70. package/src/functions/getProfile.ts +77 -13
  71. package/src/{tests → functions}/getResolver.test.ts +1 -1
  72. package/src/{tests → functions}/getSpecificRecord.test.ts +1 -1
  73. package/src/functions/getSpecificRecord.ts +28 -8
  74. package/src/{tests → functions}/getSubnames.test.ts +1 -1
  75. package/src/functions/getSubnames.ts +68 -66
  76. package/src/{tests → functions}/makeCommitment.test.ts +1 -1
  77. package/src/functions/normalise.test.ts +22 -0
  78. package/src/{tests → functions}/setName.test.ts +1 -1
  79. package/src/{tests → functions}/setRecords.test.ts +4 -4
  80. package/src/functions/setRecords.ts +3 -3
  81. package/src/{tests → functions}/setResolver.test.ts +1 -1
  82. package/src/functions/setResolver.ts +3 -3
  83. package/src/{tests → functions}/transferName.test.ts +4 -3
  84. package/src/functions/transferName.ts +3 -2
  85. package/src/{tests → functions}/transferSubname.test.ts +5 -6
  86. package/src/functions/transferSubname.ts +2 -1
  87. package/src/{tests → functions}/unwrapName.test.ts +3 -2
  88. package/src/functions/unwrapName.ts +2 -1
  89. package/src/{tests → functions}/wrapName.test.ts +5 -8
  90. package/src/index.ts +7 -0
  91. package/src/tests/withProvider.test.ts +1 -1
  92. package/src/utils/makeHashIndexes.ts +4 -4
  93. package/src/utils/normalise.ts +23 -0
  94. package/src/utils/registerHelpers.ts +3 -4
@@ -1,5 +1,5 @@
1
1
  import { ENS } from '..'
2
- import setup from './setup'
2
+ import setup from '../tests/setup'
3
3
 
4
4
  let ENSInstance: ENS
5
5
 
@@ -8,11 +8,11 @@ beforeAll(async () => {
8
8
  })
9
9
 
10
10
  const checkRecords = (
11
- result: Record<string, any> | null,
11
+ result: Record<string, any> | undefined,
12
12
  textLength = 3,
13
13
  coinTypeLength = 5,
14
14
  ) => {
15
- expect(result).toBeTruthy()
15
+ expect(result).toBeDefined()
16
16
  if (result) {
17
17
  expect(result.records?.texts).toHaveLength(textLength)
18
18
  expect(result.records?.coinTypes).toHaveLength(coinTypeLength)
@@ -22,24 +22,32 @@ const checkRecords = (
22
22
  }
23
23
  }
24
24
 
25
+ jest.setTimeout(20000)
26
+
25
27
  describe('getProfile', () => {
26
28
  describe('with an address', () => {
27
29
  it('should return a profile object with no other args', async () => {
28
30
  const result = await ENSInstance.getProfile(
29
31
  '0x866B3c4994e1416B7C738B9818b31dC246b95eEE',
30
32
  )
31
- expect((result as any).name).toBe('jefflau.eth')
32
- expect((result as any).address).toBeUndefined()
33
- checkRecords(result)
33
+ expect(result).toBeDefined()
34
+ if (result) {
35
+ expect((result as any).name).toBe('jefflau.eth')
36
+ expect((result as any).address).toBeUndefined()
37
+ checkRecords(result)
38
+ }
34
39
  })
35
40
  it('should return a profile object with specified records', async () => {
36
41
  const result = await ENSInstance.getProfile(
37
42
  '0x866B3c4994e1416B7C738B9818b31dC246b95eEE',
38
43
  { texts: ['description', 'url'], coinTypes: ['ETC', '0'] },
39
44
  )
40
- expect((result as any).name).toBe('jefflau.eth')
41
- expect((result as any).address).toBeUndefined()
42
- checkRecords(result, 2, 3)
45
+ expect(result).toBeDefined()
46
+ if (result) {
47
+ expect((result as any).name).toBe('jefflau.eth')
48
+ expect((result as any).address).toBeUndefined()
49
+ checkRecords(result, 2, 3)
50
+ }
43
51
  })
44
52
  it('should return a profile object with all of each specified record type', async () => {
45
53
  const result = await ENSInstance.getProfile(
@@ -80,11 +88,22 @@ describe('getProfile', () => {
80
88
  })
81
89
  checkRecords(result)
82
90
  })
83
- it('should return null for an unregistered name', async () => {
91
+ it('should return undefined for an unregistered name', async () => {
84
92
  const result = await ENSInstance.getProfile('test123123123cool.eth')
85
93
  expect(result).toBeUndefined()
86
94
  })
87
95
  })
96
+ describe('with an old resolver', () => {
97
+ it('should use fallback methods for a name with an older resolver (no multicall)', async () => {
98
+ const result = await ENSInstance.getProfile('pepeq6.eth')
99
+ expect(result).toBeDefined()
100
+ if (result) {
101
+ expect(result.address).toBe(
102
+ '0x6308F1c6f283583C8bf8E31Da793B87718b051eD',
103
+ )
104
+ }
105
+ })
106
+ })
88
107
  describe('with an unmigrated name', () => {
89
108
  beforeAll(async () => {
90
109
  ;({ ENSInstance } = await setup(true))
@@ -95,7 +114,6 @@ describe('getProfile', () => {
95
114
  expect(result).toBeTruthy()
96
115
  if (result) {
97
116
  expect(result.isMigrated).toBe(false)
98
- expect(result.message).toBe("Records fetch didn't complete")
99
117
  }
100
118
  })
101
119
  })
@@ -96,10 +96,27 @@ const makeMulticallData = async (
96
96
  return { data: prRawData.data, calls }
97
97
  }
98
98
 
99
- const makeHashIndexes = (data: string, name: string) =>
100
- [...data.matchAll(ethers.utils.namehash(name).substring(2) as any)].map(
101
- (x: any) => x.index / 2 - 1,
99
+ const fetchWithoutResolverMulticall = async (
100
+ { multicallWrapper }: ENSArgs<'multicallWrapper'>,
101
+ calls: {
102
+ key: string | number
103
+ data: {
104
+ to: string
105
+ data: string
106
+ }
107
+ type: 'addr' | 'text' | 'contentHash'
108
+ }[],
109
+ resolverAddress: string,
110
+ ) => {
111
+ const callsWithResolver = calls.map((call) => ({
112
+ to: resolverAddress,
113
+ data: call.data.data,
114
+ }))
115
+
116
+ return (await multicallWrapper(callsWithResolver)).map(
117
+ (x: [boolean, string]) => x[1],
102
118
  )
119
+ }
103
120
 
104
121
  const getDataForName = async (
105
122
  {
@@ -108,15 +125,18 @@ const getDataForName = async (
108
125
  _getContentHash,
109
126
  _getText,
110
127
  resolverMulticallWrapper,
128
+ multicallWrapper,
111
129
  }: ENSArgs<
112
130
  | 'contracts'
113
131
  | '_getText'
114
132
  | '_getAddr'
115
133
  | '_getContentHash'
116
134
  | 'resolverMulticallWrapper'
135
+ | 'multicallWrapper'
117
136
  >,
118
137
  name: string,
119
138
  options: InternalProfileOptions,
139
+ fallbackResolver: string,
120
140
  ) => {
121
141
  const universalResolver = await contracts?.getUniversalResolver()
122
142
 
@@ -126,14 +146,28 @@ const getDataForName = async (
126
146
  options,
127
147
  )
128
148
 
129
- let resolver: any
149
+ let resolvedData: any
150
+ let useFallbackResolver = false
130
151
  try {
131
- resolver = await universalResolver?.resolve(hexEncodeName(name), data)
152
+ resolvedData = await universalResolver?.resolve(hexEncodeName(name), data)
132
153
  } catch {
133
- return
154
+ useFallbackResolver = true
134
155
  }
135
156
 
136
- const [recordData] = await resolverMulticallWrapper.decode(resolver['0'])
157
+ let resolverAddress: string
158
+ let recordData: any
159
+
160
+ if (useFallbackResolver) {
161
+ resolverAddress = fallbackResolver
162
+ recordData = await fetchWithoutResolverMulticall(
163
+ { multicallWrapper },
164
+ calls,
165
+ resolverAddress,
166
+ )
167
+ } else {
168
+ resolverAddress = resolvedData['1']
169
+ ;[recordData] = await resolverMulticallWrapper.decode(resolvedData['0'])
170
+ }
137
171
 
138
172
  const matchAddress = recordData[calls.findIndex((x) => x.key === '60')]
139
173
 
@@ -145,7 +179,7 @@ const getDataForName = async (
145
179
  calls,
146
180
  options,
147
181
  ),
148
- resolverAddress: resolver['1'],
182
+ resolverAddress,
149
183
  }
150
184
  }
151
185
 
@@ -167,7 +201,7 @@ const formatRecords = async (
167
201
  key: calls[i].key,
168
202
  type: calls[i].type,
169
203
  }
170
- if (itemRet.type === 'addr' || itemRet.type === 'contenthash') {
204
+ if (itemRet.type === 'contenthash') {
171
205
  decodedFromAbi = ethers.utils.defaultAbiCoder.decode(
172
206
  ['bytes'],
173
207
  item,
@@ -277,6 +311,7 @@ const graphFetch = async (
277
311
  addr {
278
312
  id
279
313
  }
314
+ address
280
315
  }
281
316
  }
282
317
  }
@@ -292,7 +327,14 @@ const graphFetch = async (
292
327
 
293
328
  let returnedRecords: ProfileResponse = {}
294
329
 
295
- if (!wantedRecords) return { isMigrated, createdAt }
330
+ if (!resolverResponse) return { isMigrated, createdAt }
331
+
332
+ if (!wantedRecords)
333
+ return {
334
+ isMigrated,
335
+ createdAt,
336
+ graphResolverAddress: resolverResponse.address,
337
+ }
296
338
 
297
339
  Object.keys(wantedRecords).forEach((key: string) => {
298
340
  const data = wantedRecords[key as keyof ProfileOptions]
@@ -305,7 +347,12 @@ const graphFetch = async (
305
347
  }
306
348
  })
307
349
 
308
- return { ...returnedRecords, isMigrated, createdAt }
350
+ return {
351
+ ...returnedRecords,
352
+ isMigrated,
353
+ createdAt,
354
+ graphResolverAddress: resolverResponse.address,
355
+ }
309
356
  }
310
357
 
311
358
  type ProfileOptions = {
@@ -322,6 +369,7 @@ const getProfileFromName = async (
322
369
  _getContentHash,
323
370
  _getText,
324
371
  resolverMulticallWrapper,
372
+ multicallWrapper,
325
373
  }: ENSArgs<
326
374
  | 'contracts'
327
375
  | 'gqlInstance'
@@ -329,6 +377,7 @@ const getProfileFromName = async (
329
377
  | '_getAddr'
330
378
  | '_getContentHash'
331
379
  | 'resolverMulticallWrapper'
380
+ | 'multicallWrapper'
332
381
  >,
333
382
  name: string,
334
383
  options?: ProfileOptions,
@@ -342,9 +391,15 @@ const getProfileFromName = async (
342
391
  const {
343
392
  isMigrated,
344
393
  createdAt,
394
+ graphResolverAddress,
345
395
  ...wantedRecords
346
- }: { isMigrated: boolean; createdAt: string } & InternalProfileOptions =
347
- graphResult
396
+ }: {
397
+ isMigrated: boolean
398
+ createdAt: string
399
+ graphResolverAddress?: string
400
+ } & InternalProfileOptions = graphResult
401
+ if (!graphResolverAddress)
402
+ return { isMigrated, createdAt, message: "Name doesn't have a resolver" }
348
403
  const result = await getDataForName(
349
404
  {
350
405
  contracts,
@@ -352,9 +407,11 @@ const getProfileFromName = async (
352
407
  _getContentHash,
353
408
  _getText,
354
409
  resolverMulticallWrapper,
410
+ multicallWrapper,
355
411
  },
356
412
  name,
357
413
  usingOptions ? wantedRecords : (options as InternalProfileOptions),
414
+ graphResolverAddress,
358
415
  )
359
416
  if (!result)
360
417
  return { isMigrated, createdAt, message: "Records fetch didn't complete" }
@@ -370,6 +427,7 @@ const getProfileFromAddress = async (
370
427
  _getContentHash,
371
428
  _getText,
372
429
  resolverMulticallWrapper,
430
+ multicallWrapper,
373
431
  }: ENSArgs<
374
432
  | 'contracts'
375
433
  | 'gqlInstance'
@@ -378,6 +436,7 @@ const getProfileFromAddress = async (
378
436
  | '_getAddr'
379
437
  | '_getContentHash'
380
438
  | 'resolverMulticallWrapper'
439
+ | 'multicallWrapper'
381
440
  >,
382
441
  address: string,
383
442
  options?: ProfileOptions,
@@ -398,6 +457,7 @@ const getProfileFromAddress = async (
398
457
  _getContentHash,
399
458
  _getText,
400
459
  resolverMulticallWrapper,
460
+ multicallWrapper,
401
461
  },
402
462
  name.name,
403
463
  options,
@@ -420,6 +480,7 @@ export default async function (
420
480
  _getContentHash,
421
481
  _getText,
422
482
  resolverMulticallWrapper,
483
+ multicallWrapper,
423
484
  }: ENSArgs<
424
485
  | 'contracts'
425
486
  | 'gqlInstance'
@@ -428,6 +489,7 @@ export default async function (
428
489
  | '_getAddr'
429
490
  | '_getContentHash'
430
491
  | 'resolverMulticallWrapper'
492
+ | 'multicallWrapper'
431
493
  >,
432
494
  nameOrAddress: string,
433
495
  options?: ProfileOptions,
@@ -458,6 +520,7 @@ export default async function (
458
520
  _getContentHash,
459
521
  _getText,
460
522
  resolverMulticallWrapper,
523
+ multicallWrapper,
461
524
  },
462
525
  nameOrAddress,
463
526
  options,
@@ -472,6 +535,7 @@ export default async function (
472
535
  _getContentHash,
473
536
  _getText,
474
537
  resolverMulticallWrapper,
538
+ multicallWrapper,
475
539
  },
476
540
  nameOrAddress,
477
541
  options,
@@ -1,5 +1,5 @@
1
1
  import { ENS } from '..'
2
- import setup from './setup'
2
+ import setup from '../tests/setup'
3
3
 
4
4
  let ENSInstance: ENS
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { ENS } from '..'
2
- import setup from './setup'
2
+ import setup from '../tests/setup'
3
3
 
4
4
  let ENSInstance: ENS
5
5
 
@@ -2,6 +2,7 @@ import { formatsByCoinType, formatsByName } from '@ensdomains/address-encoder'
2
2
  import { ethers } from 'ethers'
3
3
  import { ENSArgs } from '..'
4
4
  import { decodeContenthash } from '../utils/contentHash'
5
+ import { namehash } from '../utils/normalise'
5
6
 
6
7
  export const _getContentHash = {
7
8
  raw: async ({ contracts }: ENSArgs<'contracts'>, name: string) => {
@@ -9,7 +10,7 @@ export const _getContentHash = {
9
10
  return {
10
11
  to: '0x0000000000000000000000000000000000000000',
11
12
  data: publicResolver.interface.encodeFunctionData('contenthash', [
12
- ethers.utils.namehash(name),
13
+ namehash(name),
13
14
  ]),
14
15
  }
15
16
  },
@@ -66,7 +67,7 @@ export const _getText = {
66
67
  return {
67
68
  to: '0x0000000000000000000000000000000000000000',
68
69
  data: publicResolver.interface.encodeFunctionData('text', [
69
- ethers.utils.namehash(name),
70
+ namehash(name),
70
71
  key,
71
72
  ]),
72
73
  }
@@ -115,12 +116,22 @@ export const _getAddr = {
115
116
  }
116
117
 
117
118
  const publicResolver = await contracts?.getPublicResolver()!
119
+
120
+ if (coinType === 60 || coinType === '60') {
121
+ return {
122
+ to: '0x0000000000000000000000000000000000000000',
123
+ data: publicResolver.interface.encodeFunctionData('addr(bytes32)', [
124
+ namehash(name),
125
+ ]),
126
+ }
127
+ }
128
+
118
129
  if (bypassFormat) {
119
130
  return {
120
131
  to: '0x0000000000000000000000000000000000000000',
121
132
  data: publicResolver.interface.encodeFunctionData(
122
133
  'addr(bytes32,uint256)',
123
- [ethers.utils.namehash(name), coinType],
134
+ [namehash(name), coinType],
124
135
  ),
125
136
  }
126
137
  }
@@ -139,7 +150,7 @@ export const _getAddr = {
139
150
  to: '0x0000000000000000000000000000000000000000',
140
151
  data: publicResolver.interface.encodeFunctionData(
141
152
  'addr(bytes32,uint256)',
142
- [ethers.utils.namehash(name), formatter.coinType],
153
+ [namehash(name), formatter.coinType],
143
154
  ),
144
155
  }
145
156
  },
@@ -163,10 +174,19 @@ export const _getAddr = {
163
174
  typeof coinType === 'number' ? coinType : parseInt(coinType)
164
175
  ]
165
176
 
166
- const [response] = publicResolver.interface.decodeFunctionResult(
167
- 'addr(bytes32,uint256)',
168
- data,
169
- )
177
+ let response: string
178
+
179
+ if (coinType === 60 || coinType === '60') {
180
+ ;[response] = publicResolver.interface.decodeFunctionResult(
181
+ 'addr(bytes32)',
182
+ data,
183
+ )
184
+ } else {
185
+ ;[response] = publicResolver.interface.decodeFunctionResult(
186
+ 'addr(bytes32,uint256)',
187
+ data,
188
+ )
189
+ }
170
190
 
171
191
  if (!response) return
172
192
 
@@ -1,5 +1,5 @@
1
1
  import { ENS } from '..'
2
- import setup from './setup'
2
+ import setup from '../tests/setup'
3
3
 
4
4
  let ENSInstance: ENS
5
5
 
@@ -1,7 +1,7 @@
1
- import { namehash } from 'ethers/lib/utils';
2
1
  import { ENSArgs } from '..'
3
- import { truncateFormat } from '../utils/format';
4
- import { decryptName } from '../utils/labels';
2
+ import { truncateFormat } from '../utils/format'
3
+ import { decryptName } from '../utils/labels'
4
+ import { namehash } from '../utils/normalise'
5
5
 
6
6
  type Subname = {
7
7
  id: string
@@ -26,12 +26,12 @@ type Params = {
26
26
  }
27
27
 
28
28
  const largeQuery = async (
29
- { gqlInstance } : ENSArgs<'gqlInstance'>,
30
- { name, page, pageSize = 10, orderDirection, orderBy, lastSubnames }: Params
31
- ) => {
32
- const client = gqlInstance.client;
29
+ { gqlInstance }: ENSArgs<'gqlInstance'>,
30
+ { name, page, pageSize = 10, orderDirection, orderBy, lastSubnames }: Params,
31
+ ) => {
32
+ const client = gqlInstance.client
33
33
 
34
- let finalQuery = gqlInstance.gql `
34
+ let finalQuery = gqlInstance.gql`
35
35
  query getSubnames(
36
36
  $id: ID!
37
37
  $first: Int
@@ -62,35 +62,35 @@ const largeQuery = async (
62
62
  }
63
63
  }
64
64
  }
65
- `;
66
- let queryVars = {
67
- id: namehash(name),
68
- first: pageSize,
69
- lastCreatedAt: lastSubnames[lastSubnames.length - 1]?.createdAt,
70
- orderBy,
71
- orderDirection,
72
- };
73
- const { domain } = await client.request(finalQuery, queryVars);
65
+ `
66
+ let queryVars = {
67
+ id: namehash(name),
68
+ first: pageSize,
69
+ lastCreatedAt: lastSubnames[lastSubnames.length - 1]?.createdAt,
70
+ orderBy,
71
+ orderDirection,
72
+ }
73
+ const { domain } = await client.request(finalQuery, queryVars)
74
74
  const subdomains = domain.subdomains.map((subname: any) => {
75
- const decrypted = decryptName(subname.name);
76
- return {
77
- ...subname,
78
- name: decrypted,
79
- truncatedName: truncateFormat(decrypted),
80
- };
81
- });
75
+ const decrypted = decryptName(subname.name)
76
+ return {
77
+ ...subname,
78
+ name: decrypted,
79
+ truncatedName: truncateFormat(decrypted),
80
+ }
81
+ })
82
82
 
83
83
  return {
84
84
  subnames: subdomains,
85
- subnameCount: domain.subdomainCount
85
+ subnameCount: domain.subdomainCount,
86
86
  }
87
- };
87
+ }
88
88
 
89
- const smallQuery = async (
90
- { gqlInstance } : ENSArgs<'gqlInstance'>,
91
- { name, page, pageSize = 10, orderDirection, orderBy } : Params
92
- ) => {
93
- const client = gqlInstance.client;
89
+ const smallQuery = async (
90
+ { gqlInstance }: ENSArgs<'gqlInstance'>,
91
+ { name, page, pageSize = 10, orderDirection, orderBy }: Params,
92
+ ) => {
93
+ const client = gqlInstance.client
94
94
  const subdomainsGql = `
95
95
  id
96
96
  labelName
@@ -102,11 +102,11 @@ const smallQuery = async (
102
102
  owner {
103
103
  id
104
104
  }
105
- `;
106
- let queryVars = {};
107
- let finalQuery = '';
105
+ `
106
+ let queryVars = {}
107
+ let finalQuery = ''
108
108
  if (typeof page !== 'number') {
109
- finalQuery = gqlInstance.gql `
109
+ finalQuery = gqlInstance.gql`
110
110
  query getSubnames(
111
111
  $id: ID!
112
112
  $orderBy: Domain_orderBy
@@ -123,15 +123,14 @@ const smallQuery = async (
123
123
  }
124
124
  }
125
125
  }
126
- `;
127
- queryVars = {
128
- id: namehash(name),
129
- orderBy,
130
- orderDirection,
131
- };
132
- }
133
- else {
134
- finalQuery = gqlInstance.gql `
126
+ `
127
+ queryVars = {
128
+ id: namehash(name),
129
+ orderBy,
130
+ orderDirection,
131
+ }
132
+ } else {
133
+ finalQuery = gqlInstance.gql`
135
134
  query getSubnames(
136
135
  $id: ID!
137
136
  $first: Int
@@ -153,36 +152,39 @@ const smallQuery = async (
153
152
  }
154
153
  }
155
154
  }
156
- `;
157
- queryVars = {
158
- id: namehash(name),
159
- first: pageSize,
160
- skip: (page || 0) * pageSize,
161
- orderBy,
162
- orderDirection,
163
- };
155
+ `
156
+ queryVars = {
157
+ id: namehash(name),
158
+ first: pageSize,
159
+ skip: (page || 0) * pageSize,
160
+ orderBy,
161
+ orderDirection,
162
+ }
164
163
  }
165
- const { domain } = await client.request(finalQuery, queryVars);
164
+ const { domain } = await client.request(finalQuery, queryVars)
166
165
  const subdomains = domain.subdomains.map((subname: any) => {
167
- const decrypted = decryptName(subname.name);
168
- return {
169
- ...subname,
170
- name: decrypted,
171
- truncatedName: truncateFormat(decrypted),
172
- };
173
- });
166
+ const decrypted = decryptName(subname.name)
167
+ return {
168
+ ...subname,
169
+ name: decrypted,
170
+ truncatedName: truncateFormat(decrypted),
171
+ }
172
+ })
174
173
 
175
174
  return {
176
175
  subnames: subdomains,
177
- subnameCount: domain.subdomainCount
176
+ subnameCount: domain.subdomainCount,
178
177
  }
179
- };
178
+ }
180
179
 
181
- const getSubnames = (injected : ENSArgs<'gqlInstance'>, functionArgs: Params): Promise<{ subnames: Subname[], subnameCount: number}> => {
182
- if(functionArgs.isLargeQuery) {
180
+ const getSubnames = (
181
+ injected: ENSArgs<'gqlInstance'>,
182
+ functionArgs: Params,
183
+ ): Promise<{ subnames: Subname[]; subnameCount: number }> => {
184
+ if (functionArgs.isLargeQuery) {
183
185
  return largeQuery(injected, functionArgs)
184
- }
186
+ }
185
187
  return smallQuery(injected, functionArgs)
186
188
  }
187
189
 
188
- export default getSubnames;
190
+ export default getSubnames
@@ -1,6 +1,6 @@
1
1
  import { ENS } from '..'
2
2
  import { makeCommitment } from '../utils/registerHelpers'
3
- import setup from './setup'
3
+ import setup from '../tests/setup'
4
4
 
5
5
  let ENSInstance: ENS
6
6
 
@@ -0,0 +1,22 @@
1
+ import { namehash } from '../utils/normalise'
2
+
3
+ describe('normalise', () => {
4
+ it('should namehash an empty string', () => {
5
+ const hash = namehash('')
6
+ expect(hash).toEqual(
7
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
8
+ )
9
+ })
10
+ it('should namehash a TLD', () => {
11
+ const hash = namehash('eth')
12
+ expect(hash).toEqual(
13
+ '0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae',
14
+ )
15
+ })
16
+ it('should namehash a 2LD', () => {
17
+ const hash = namehash('foo.eth')
18
+ expect(hash).toEqual(
19
+ '0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f',
20
+ )
21
+ })
22
+ })
@@ -1,7 +1,7 @@
1
1
  import { ethers } from 'ethers'
2
2
  import { ENS } from '..'
3
3
  import { hexEncodeName } from '../utils/hexEncodedName'
4
- import setup from './setup'
4
+ import setup from '../tests/setup'
5
5
 
6
6
  let ENSInstance: ENS
7
7
  let revert: Awaited<ReturnType<typeof setup>>['revert']
@@ -1,7 +1,7 @@
1
- import { utils } from 'ethers'
2
1
  import { ENS } from '..'
3
2
  import { hexEncodeName } from '../utils/hexEncodedName'
4
- import setup from './setup'
3
+ import { namehash } from '../utils/normalise'
4
+ import setup from '../tests/setup'
5
5
 
6
6
  let ENSInstance: ENS
7
7
  let revert: Awaited<ReturnType<typeof setup>>['revert']
@@ -31,14 +31,14 @@ describe('setRecords', () => {
31
31
  const encodedText = await universalResolver.resolve(
32
32
  hexEncodeName('parthtejpal.eth'),
33
33
  publicResolver.interface.encodeFunctionData('text(bytes32,string)', [
34
- utils.namehash('parthtejpal.eth'),
34
+ namehash('parthtejpal.eth'),
35
35
  'foo',
36
36
  ]),
37
37
  )
38
38
  const encodedAddr = await universalResolver.resolve(
39
39
  hexEncodeName('parthtejpal.eth'),
40
40
  publicResolver.interface.encodeFunctionData('addr(bytes32,uint256)', [
41
- utils.namehash('parthtejpal.eth'),
41
+ namehash('parthtejpal.eth'),
42
42
  '61',
43
43
  ]),
44
44
  )