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

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 (147) hide show
  1. package/README.md +2 -0
  2. package/dist/cjs/GqlManager.d.ts +3 -0
  3. package/dist/cjs/GqlManager.js +62 -2
  4. package/dist/cjs/functions/burnFuses.d.ts +3 -2
  5. package/dist/cjs/functions/burnFuses.js +4 -8
  6. package/dist/cjs/functions/createSubname.d.ts +1 -5
  7. package/dist/cjs/functions/createSubname.js +5 -8
  8. package/dist/cjs/functions/deleteSubname.d.ts +3 -3
  9. package/dist/cjs/functions/deleteSubname.js +5 -2
  10. package/dist/cjs/functions/getDNSOwner.d.ts +7 -0
  11. package/dist/cjs/functions/getDNSOwner.js +81 -0
  12. package/dist/cjs/functions/getFuses.js +3 -2
  13. package/dist/cjs/functions/getOwner.js +7 -6
  14. package/dist/cjs/functions/getProfile.d.ts +4 -1
  15. package/dist/cjs/functions/getProfile.js +102 -24
  16. package/dist/cjs/functions/getRecords.d.ts +1 -0
  17. package/dist/cjs/functions/getSpecificRecord.js +22 -5
  18. package/dist/cjs/functions/getSubnames.js +6 -6
  19. package/dist/cjs/functions/setName.d.ts +4 -3
  20. package/dist/cjs/functions/setName.js +5 -10
  21. package/dist/cjs/functions/setRecord.d.ts +18 -0
  22. package/dist/cjs/functions/setRecord.js +27 -0
  23. package/dist/cjs/functions/setRecords.d.ts +4 -2
  24. package/dist/cjs/functions/setRecords.js +14 -12
  25. package/dist/cjs/functions/setResolver.d.ts +4 -4
  26. package/dist/cjs/functions/setResolver.js +6 -12
  27. package/dist/cjs/functions/transferName.d.ts +4 -3
  28. package/dist/cjs/functions/transferName.js +9 -13
  29. package/dist/cjs/functions/transferSubname.d.ts +4 -3
  30. package/dist/cjs/functions/transferSubname.js +5 -8
  31. package/dist/cjs/functions/unwrapName.d.ts +4 -3
  32. package/dist/cjs/functions/unwrapName.js +5 -9
  33. package/dist/cjs/functions/wrapName.d.ts +5 -3
  34. package/dist/cjs/functions/wrapName.js +8 -12
  35. package/dist/cjs/index.d.ts +48 -46
  36. package/dist/cjs/index.js +43 -19
  37. package/dist/cjs/utils/labels.js +5 -4
  38. package/dist/cjs/utils/makeHashIndexes.js +2 -2
  39. package/dist/cjs/utils/normalise.d.ts +1 -0
  40. package/dist/cjs/utils/normalise.js +27 -1
  41. package/dist/cjs/utils/recordHelpers.d.ts +3 -0
  42. package/dist/cjs/utils/recordHelpers.js +42 -15
  43. package/dist/cjs/utils/registerHelpers.js +3 -4
  44. package/dist/cjs/utils/writeTx.d.ts +4 -0
  45. package/dist/cjs/utils/writeTx.js +3 -0
  46. package/dist/esm/GqlManager.d.ts +3 -0
  47. package/dist/esm/GqlManager.js +58 -2
  48. package/dist/esm/functions/burnFuses.d.ts +3 -2
  49. package/dist/esm/functions/burnFuses.js +4 -8
  50. package/dist/esm/functions/createSubname.d.ts +1 -5
  51. package/dist/esm/functions/createSubname.js +5 -8
  52. package/dist/esm/functions/deleteSubname.d.ts +3 -3
  53. package/dist/esm/functions/deleteSubname.js +5 -2
  54. package/dist/esm/functions/getDNSOwner.d.ts +7 -0
  55. package/dist/esm/functions/getDNSOwner.js +51 -0
  56. package/dist/esm/functions/getFuses.js +4 -3
  57. package/dist/esm/functions/getOwner.js +7 -6
  58. package/dist/esm/functions/getProfile.d.ts +4 -1
  59. package/dist/esm/functions/getProfile.js +102 -24
  60. package/dist/esm/functions/getRecords.d.ts +1 -0
  61. package/dist/esm/functions/getSpecificRecord.js +22 -5
  62. package/dist/esm/functions/getSubnames.js +3 -3
  63. package/dist/esm/functions/setName.d.ts +4 -3
  64. package/dist/esm/functions/setName.js +5 -10
  65. package/dist/esm/functions/setRecord.d.ts +18 -0
  66. package/dist/esm/functions/setRecord.js +24 -0
  67. package/dist/esm/functions/setRecords.d.ts +4 -2
  68. package/dist/esm/functions/setRecords.js +14 -12
  69. package/dist/esm/functions/setResolver.d.ts +4 -4
  70. package/dist/esm/functions/setResolver.js +6 -12
  71. package/dist/esm/functions/transferName.d.ts +4 -3
  72. package/dist/esm/functions/transferName.js +9 -13
  73. package/dist/esm/functions/transferSubname.d.ts +4 -3
  74. package/dist/esm/functions/transferSubname.js +5 -8
  75. package/dist/esm/functions/unwrapName.d.ts +4 -3
  76. package/dist/esm/functions/unwrapName.js +5 -9
  77. package/dist/esm/functions/wrapName.d.ts +5 -3
  78. package/dist/esm/functions/wrapName.js +8 -12
  79. package/dist/esm/index.d.ts +48 -46
  80. package/dist/esm/index.js +43 -19
  81. package/dist/esm/utils/labels.js +5 -4
  82. package/dist/esm/utils/makeHashIndexes.js +2 -2
  83. package/dist/esm/utils/normalise.d.ts +1 -0
  84. package/dist/esm/utils/normalise.js +25 -0
  85. package/dist/esm/utils/recordHelpers.d.ts +3 -0
  86. package/dist/esm/utils/recordHelpers.js +40 -14
  87. package/dist/esm/utils/registerHelpers.js +3 -4
  88. package/dist/esm/utils/writeTx.d.ts +4 -0
  89. package/dist/esm/utils/writeTx.js +1 -0
  90. package/package.json +15 -7
  91. package/src/@types/dns-packet/index.d.ts +114 -0
  92. package/src/GqlManager.test.ts +170 -0
  93. package/src/GqlManager.ts +67 -2
  94. package/src/{tests → functions}/batch.test.ts +1 -1
  95. package/src/{tests → functions}/batchWrappers.test.ts +1 -1
  96. package/src/{tests → functions}/burnFuses.test.ts +12 -10
  97. package/src/functions/burnFuses.ts +9 -11
  98. package/src/{tests → functions}/createSubname.test.ts +12 -16
  99. package/src/functions/createSubname.ts +7 -13
  100. package/src/{tests → functions}/deleteSubname.test.ts +32 -32
  101. package/src/functions/deleteSubname.ts +9 -12
  102. package/src/functions/getDNSOwner.test.ts +122 -0
  103. package/src/functions/getDNSOwner.ts +61 -0
  104. package/src/{tests → functions}/getExpiry.test.ts +1 -1
  105. package/src/{tests → functions}/getFuses.test.ts +12 -10
  106. package/src/functions/getFuses.ts +4 -3
  107. package/src/{tests → functions}/getHistory.test.ts +1 -1
  108. package/src/{tests → functions}/getName.test.ts +1 -1
  109. package/src/{tests → functions}/getNames.test.ts +1 -1
  110. package/src/{tests → functions}/getOwner.test.ts +14 -2
  111. package/src/functions/getOwner.ts +7 -7
  112. package/src/{tests → functions}/getProfile.test.ts +45 -12
  113. package/src/functions/getProfile.ts +151 -24
  114. package/src/functions/getRecords.ts +1 -0
  115. package/src/{tests → functions}/getResolver.test.ts +1 -1
  116. package/src/{tests → functions}/getSpecificRecord.test.ts +1 -1
  117. package/src/functions/getSpecificRecord.ts +28 -8
  118. package/src/{tests → functions}/getSubnames.test.ts +1 -1
  119. package/src/functions/getSubnames.ts +68 -66
  120. package/src/{tests → functions}/makeCommitment.test.ts +1 -1
  121. package/src/functions/normalise.test.ts +22 -0
  122. package/src/{tests → functions}/setName.test.ts +3 -2
  123. package/src/functions/setName.ts +15 -17
  124. package/src/functions/setRecord.test.ts +100 -0
  125. package/src/functions/setRecord.ts +63 -0
  126. package/src/{tests → functions}/setRecords.test.ts +12 -10
  127. package/src/functions/setRecords.ts +22 -16
  128. package/src/{tests → functions}/setResolver.test.ts +12 -15
  129. package/src/functions/setResolver.ts +15 -20
  130. package/src/{tests → functions}/transferName.test.ts +30 -31
  131. package/src/functions/transferName.ts +19 -22
  132. package/src/{tests → functions}/transferSubname.test.ts +34 -34
  133. package/src/functions/transferSubname.ts +21 -13
  134. package/src/{tests → functions}/unwrapName.test.ts +24 -23
  135. package/src/functions/unwrapName.ts +20 -15
  136. package/src/{tests → functions}/wrapName.test.ts +19 -19
  137. package/src/functions/wrapName.ts +20 -22
  138. package/src/index.ts +115 -26
  139. package/src/tests/populateTransaction.test.ts +40 -0
  140. package/src/tests/signerInjection.test.ts +46 -0
  141. package/src/tests/withProvider.test.ts +1 -1
  142. package/src/utils/labels.ts +6 -4
  143. package/src/utils/makeHashIndexes.ts +4 -4
  144. package/src/utils/normalise.ts +29 -0
  145. package/src/utils/recordHelpers.ts +52 -18
  146. package/src/utils/registerHelpers.ts +3 -4
  147. package/src/utils/writeTx.ts +6 -0
@@ -3,6 +3,7 @@ import { ethers } from 'ethers'
3
3
  import { ENSArgs } from '..'
4
4
  import { decodeContenthash, DecodedContentHash } from '../utils/contentHash'
5
5
  import { hexEncodeName } from '../utils/hexEncodedName'
6
+ import { namehash } from '../utils/normalise'
6
7
  import { parseInputType } from '../utils/validation'
7
8
 
8
9
  type InternalProfileOptions = {
@@ -96,10 +97,27 @@ const makeMulticallData = async (
96
97
  return { data: prRawData.data, calls }
97
98
  }
98
99
 
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,
100
+ const fetchWithoutResolverMulticall = async (
101
+ { multicallWrapper }: ENSArgs<'multicallWrapper'>,
102
+ calls: {
103
+ key: string | number
104
+ data: {
105
+ to: string
106
+ data: string
107
+ }
108
+ type: 'addr' | 'text' | 'contentHash'
109
+ }[],
110
+ resolverAddress: string,
111
+ ) => {
112
+ const callsWithResolver = calls.map((call) => ({
113
+ to: resolverAddress,
114
+ data: call.data.data,
115
+ }))
116
+
117
+ return (await multicallWrapper(callsWithResolver)).map(
118
+ (x: [boolean, string]) => x[1],
102
119
  )
120
+ }
103
121
 
104
122
  const getDataForName = async (
105
123
  {
@@ -108,15 +126,19 @@ const getDataForName = async (
108
126
  _getContentHash,
109
127
  _getText,
110
128
  resolverMulticallWrapper,
129
+ multicallWrapper,
111
130
  }: ENSArgs<
112
131
  | 'contracts'
113
132
  | '_getText'
114
133
  | '_getAddr'
115
134
  | '_getContentHash'
116
135
  | 'resolverMulticallWrapper'
136
+ | 'multicallWrapper'
117
137
  >,
118
138
  name: string,
119
139
  options: InternalProfileOptions,
140
+ fallbackResolver?: string,
141
+ specificResolver?: string,
120
142
  ) => {
121
143
  const universalResolver = await contracts?.getUniversalResolver()
122
144
 
@@ -126,14 +148,42 @@ const getDataForName = async (
126
148
  options,
127
149
  )
128
150
 
129
- let resolver: any
151
+ let resolvedData: any
152
+ let useFallbackResolver = false
130
153
  try {
131
- resolver = await universalResolver?.resolve(hexEncodeName(name), data)
154
+ if (specificResolver) {
155
+ const publicResolver = await contracts?.getPublicResolver(
156
+ undefined,
157
+ specificResolver,
158
+ )
159
+ resolvedData = await publicResolver?.callStatic.multicall(
160
+ calls.map((x) => x.data),
161
+ )
162
+ } else {
163
+ resolvedData = await universalResolver?.resolve(hexEncodeName(name), data)
164
+ }
132
165
  } catch {
133
- return
166
+ useFallbackResolver = true
134
167
  }
135
168
 
136
- const [recordData] = await resolverMulticallWrapper.decode(resolver['0'])
169
+ let resolverAddress: string
170
+ let recordData: any
171
+
172
+ if (useFallbackResolver) {
173
+ resolverAddress = specificResolver || fallbackResolver!
174
+ recordData = await fetchWithoutResolverMulticall(
175
+ { multicallWrapper },
176
+ calls,
177
+ resolverAddress,
178
+ )
179
+ } else {
180
+ resolverAddress = specificResolver || resolvedData['1']
181
+ if (specificResolver) {
182
+ recordData = resolvedData
183
+ } else {
184
+ ;[recordData] = await resolverMulticallWrapper.decode(resolvedData['0'])
185
+ }
186
+ }
137
187
 
138
188
  const matchAddress = recordData[calls.findIndex((x) => x.key === '60')]
139
189
 
@@ -145,7 +195,7 @@ const getDataForName = async (
145
195
  calls,
146
196
  options,
147
197
  ),
148
- resolverAddress: resolver['1'],
198
+ resolverAddress,
149
199
  }
150
200
  }
151
201
 
@@ -167,7 +217,7 @@ const formatRecords = async (
167
217
  key: calls[i].key,
168
218
  type: calls[i].type,
169
219
  }
170
- if (itemRet.type === 'addr' || itemRet.type === 'contenthash') {
220
+ if (itemRet.type === 'contenthash') {
171
221
  decodedFromAbi = ethers.utils.defaultAbiCoder.decode(
172
222
  ['bytes'],
173
223
  item,
@@ -264,10 +314,11 @@ const graphFetch = async (
264
314
  { gqlInstance }: ENSArgs<'gqlInstance'>,
265
315
  name: string,
266
316
  wantedRecords?: ProfileOptions,
317
+ resolverAddress?: string,
267
318
  ) => {
268
319
  const query = gqlInstance.gql`
269
- query getRecords($name: String!) {
270
- domains(where: { name: $name }) {
320
+ query getRecords($id: String!) {
321
+ domain(id: $id) {
271
322
  isMigrated
272
323
  createdAt
273
324
  resolver {
@@ -277,6 +328,24 @@ const graphFetch = async (
277
328
  addr {
278
329
  id
279
330
  }
331
+ address
332
+ }
333
+ }
334
+ }
335
+ `
336
+
337
+ const customResolverQuery = gqlInstance.gql`
338
+ query getRecordsWithCustomResolver($id: String!, $resolverId: String!) {
339
+ domain(id: $id) {
340
+ isMigrated
341
+ createdAt
342
+ }
343
+ resolver(id: $resolverId) {
344
+ texts
345
+ coinTypes
346
+ contentHash
347
+ addr {
348
+ id
280
349
  }
281
350
  }
282
351
  }
@@ -284,15 +353,36 @@ const graphFetch = async (
284
353
 
285
354
  const client = gqlInstance.client
286
355
 
287
- const { domains } = await client.request(query, { name })
356
+ const id = namehash(name)
288
357
 
289
- if (!domains || domains.length === 0) return
358
+ let domain: any
359
+ let resolverResponse: any
360
+
361
+ if (!resolverAddress) {
362
+ ;({ domain } = await client.request(query, { id }))
363
+ resolverResponse = domain?.resolver
364
+ } else {
365
+ const resolverId = `${resolverAddress}-${id}`
366
+ ;({ resolver: resolverResponse, domain } = await client.request(
367
+ customResolverQuery,
368
+ { id, resolverId },
369
+ ))
370
+ }
290
371
 
291
- const [{ resolver: resolverResponse, isMigrated, createdAt }] = domains
372
+ if (!domain) return
373
+
374
+ const { isMigrated, createdAt } = domain
292
375
 
293
376
  let returnedRecords: ProfileResponse = {}
294
377
 
295
- if (!wantedRecords) return { isMigrated, createdAt }
378
+ if (!resolverResponse) return { isMigrated, createdAt }
379
+
380
+ if (!wantedRecords)
381
+ return {
382
+ isMigrated,
383
+ createdAt,
384
+ graphResolverAddress: resolverResponse.address || resolverAddress,
385
+ }
296
386
 
297
387
  Object.keys(wantedRecords).forEach((key: string) => {
298
388
  const data = wantedRecords[key as keyof ProfileOptions]
@@ -305,7 +395,12 @@ const graphFetch = async (
305
395
  }
306
396
  })
307
397
 
308
- return { ...returnedRecords, isMigrated, createdAt }
398
+ return {
399
+ ...returnedRecords,
400
+ isMigrated,
401
+ createdAt,
402
+ graphResolverAddress: resolverResponse.address || resolverAddress,
403
+ }
309
404
  }
310
405
 
311
406
  type ProfileOptions = {
@@ -314,6 +409,10 @@ type ProfileOptions = {
314
409
  coinTypes?: boolean | string[]
315
410
  }
316
411
 
412
+ type InputProfileOptions = ProfileOptions & {
413
+ resolverAddress?: string
414
+ }
415
+
317
416
  const getProfileFromName = async (
318
417
  {
319
418
  contracts,
@@ -322,6 +421,7 @@ const getProfileFromName = async (
322
421
  _getContentHash,
323
422
  _getText,
324
423
  resolverMulticallWrapper,
424
+ multicallWrapper,
325
425
  }: ENSArgs<
326
426
  | 'contracts'
327
427
  | 'gqlInstance'
@@ -329,22 +429,39 @@ const getProfileFromName = async (
329
429
  | '_getAddr'
330
430
  | '_getContentHash'
331
431
  | 'resolverMulticallWrapper'
432
+ | 'multicallWrapper'
332
433
  >,
333
434
  name: string,
334
- options?: ProfileOptions,
435
+ options?: InputProfileOptions,
335
436
  ) => {
437
+ const { resolverAddress, ..._options } = options || {}
438
+ const optsLength = Object.keys(_options).length
336
439
  const usingOptions =
337
- !options || options?.texts === true || options?.coinTypes === true
338
- ? options || { contentHash: true, texts: true, coinTypes: true }
440
+ !optsLength || _options?.texts === true || _options?.coinTypes === true
441
+ ? optsLength
442
+ ? _options
443
+ : { contentHash: true, texts: true, coinTypes: true }
339
444
  : undefined
340
- const graphResult = await graphFetch({ gqlInstance }, name, usingOptions)
445
+
446
+ const graphResult = await graphFetch(
447
+ { gqlInstance },
448
+ name,
449
+ usingOptions,
450
+ resolverAddress,
451
+ )
341
452
  if (!graphResult) return
342
453
  const {
343
454
  isMigrated,
344
455
  createdAt,
456
+ graphResolverAddress,
345
457
  ...wantedRecords
346
- }: { isMigrated: boolean; createdAt: string } & InternalProfileOptions =
347
- graphResult
458
+ }: {
459
+ isMigrated: boolean
460
+ createdAt: string
461
+ graphResolverAddress?: string
462
+ } & InternalProfileOptions = graphResult
463
+ if (!graphResolverAddress && !options?.resolverAddress)
464
+ return { isMigrated, createdAt, message: "Name doesn't have a resolver" }
348
465
  const result = await getDataForName(
349
466
  {
350
467
  contracts,
@@ -352,9 +469,12 @@ const getProfileFromName = async (
352
469
  _getContentHash,
353
470
  _getText,
354
471
  resolverMulticallWrapper,
472
+ multicallWrapper,
355
473
  },
356
474
  name,
357
475
  usingOptions ? wantedRecords : (options as InternalProfileOptions),
476
+ graphResolverAddress,
477
+ options?.resolverAddress!,
358
478
  )
359
479
  if (!result)
360
480
  return { isMigrated, createdAt, message: "Records fetch didn't complete" }
@@ -370,6 +490,7 @@ const getProfileFromAddress = async (
370
490
  _getContentHash,
371
491
  _getText,
372
492
  resolverMulticallWrapper,
493
+ multicallWrapper,
373
494
  }: ENSArgs<
374
495
  | 'contracts'
375
496
  | 'gqlInstance'
@@ -378,9 +499,10 @@ const getProfileFromAddress = async (
378
499
  | '_getAddr'
379
500
  | '_getContentHash'
380
501
  | 'resolverMulticallWrapper'
502
+ | 'multicallWrapper'
381
503
  >,
382
504
  address: string,
383
- options?: ProfileOptions,
505
+ options?: InputProfileOptions,
384
506
  ) => {
385
507
  let name
386
508
  try {
@@ -398,6 +520,7 @@ const getProfileFromAddress = async (
398
520
  _getContentHash,
399
521
  _getText,
400
522
  resolverMulticallWrapper,
523
+ multicallWrapper,
401
524
  },
402
525
  name.name,
403
526
  options,
@@ -420,6 +543,7 @@ export default async function (
420
543
  _getContentHash,
421
544
  _getText,
422
545
  resolverMulticallWrapper,
546
+ multicallWrapper,
423
547
  }: ENSArgs<
424
548
  | 'contracts'
425
549
  | 'gqlInstance'
@@ -428,9 +552,10 @@ export default async function (
428
552
  | '_getAddr'
429
553
  | '_getContentHash'
430
554
  | 'resolverMulticallWrapper'
555
+ | 'multicallWrapper'
431
556
  >,
432
557
  nameOrAddress: string,
433
- options?: ProfileOptions,
558
+ options?: InputProfileOptions,
434
559
  ): Promise<ResolvedProfile | undefined> {
435
560
  if (options && options.coinTypes && typeof options.coinTypes !== 'boolean') {
436
561
  options.coinTypes = options.coinTypes.map((coin: string) => {
@@ -458,6 +583,7 @@ export default async function (
458
583
  _getContentHash,
459
584
  _getText,
460
585
  resolverMulticallWrapper,
586
+ multicallWrapper,
461
587
  },
462
588
  nameOrAddress,
463
589
  options,
@@ -472,6 +598,7 @@ export default async function (
472
598
  _getContentHash,
473
599
  _getText,
474
600
  resolverMulticallWrapper,
601
+ multicallWrapper,
475
602
  },
476
603
  nameOrAddress,
477
604
  options,
@@ -5,6 +5,7 @@ type ProfileOptions = {
5
5
  contentHash?: boolean
6
6
  texts?: boolean | string[]
7
7
  coinTypes?: boolean | string[]
8
+ resolverAddress?: string
8
9
  }
9
10
 
10
11
  export default async function (
@@ -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
+ })