@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
@@ -0,0 +1,122 @@
1
+ import * as packet from 'dns-packet'
2
+ import fetch from 'node-fetch'
3
+ import nock from 'nock'
4
+
5
+ import getDNSOwner, { encodeURLParams } from './getDNSOwner'
6
+
7
+ function hex_decode(string: string) {
8
+ let bytes: any[] = []
9
+ string.replace(/../g, function (pair) {
10
+ bytes.push(parseInt(pair, 16))
11
+ })
12
+ return new Uint8Array(bytes).buffer
13
+ }
14
+
15
+ describe('encodeURLParams', () => {
16
+ it('should encodeURLParams', () => {
17
+ const p: { [key: string]: string } = {
18
+ a: 'b',
19
+ c: 'd',
20
+ }
21
+ const expected = 'a=b&c=d'
22
+ const actual = encodeURLParams(p)
23
+ expect(actual).toEqual(expected)
24
+ })
25
+ })
26
+
27
+ describe('getDNSOwner', () => {
28
+ beforeAll(() => {
29
+ global.fetch = fetch
30
+ })
31
+ afterAll(() => {
32
+ global.fetch = undefined
33
+ })
34
+ it('should return the address from the result of a dnsQuery', async () => {
35
+ const dnsName = 'brantly.xyz'
36
+
37
+ const scope = nock('https://cloudflare-dns.com:443', {
38
+ encodedQueryParams: true,
39
+ })
40
+ .get('/dns-query')
41
+ .query((queryObject) => {
42
+ console.log('queryObject: ', queryObject)
43
+ return (
44
+ queryObject.ct === 'application/dns-udpwireformat' &&
45
+ queryObject.dns ===
46
+ 'AAEBAAABAAAAAAABBF9lbnMHYnJhbnRseQN4eXoAABAAAQAAKRAAAACAAAAA'
47
+ )
48
+ })
49
+ .reply(
50
+ 200,
51
+ Buffer.from(
52
+ hex_decode(
53
+ '000181a00001000200000001045f656e73076272616e746c790378797a0000100001c00c0010000100000e10002d2c613d307839383331313033303936323044393131373331416330393332323139616630363039316236373434c00c002e000100000e10009f0010080300000e1062df366962c23569d89d076272616e746c790378797a0039c894ca1d7a60c1356e478066d39961a78ec1edbe62e1eb0f13d7947bb72097654648dc79be075ca32625f02e60267f45e88d7c05e9c3ec0cf21ab2dca67a8fbeb8e995644726357628446b888a144cafef5cbfca120c6511fe36de9d3c62dee27680825190c5404ca503904b98dbf62d9122f6fda393dc04b14a89ceb68c7a00002904d0000080000000',
54
+ ),
55
+ ),
56
+ [
57
+ 'Server',
58
+ 'cloudflare',
59
+ 'Date',
60
+ 'Wed, 06 Jul 2022 23:37:28 GMT',
61
+ 'Content-Type',
62
+ 'application/dns-message',
63
+ 'Connection',
64
+ 'close',
65
+ 'Access-Control-Allow-Origin',
66
+ '*',
67
+ 'Content-Length',
68
+ '273',
69
+ 'CF-RAY',
70
+ '726c2b1d3bab6b74-TPE',
71
+ ],
72
+ )
73
+ expect(await getDNSOwner({}, dnsName)).toEqual(
74
+ '0x983110309620D911731Ac0932219af06091b6744',
75
+ )
76
+ })
77
+ it('should throw if there is an error in the DNS query', async () => {
78
+ const dnsName = 'nick.xyz'
79
+
80
+ const scope = nock('https://cloudflare-dns.com:443', {
81
+ encodedQueryParams: true,
82
+ })
83
+ .get('/dns-query')
84
+ .query((queryObject) => {
85
+ console.log('queryObject: ', queryObject)
86
+ return (
87
+ queryObject.ct === 'application/dns-udpwireformat' &&
88
+ queryObject.dns ===
89
+ 'AAEBAAABAAAAAAABBF9lbnMEbmljawN4eXoAABAAAQAAKRAAAACAAAAA'
90
+ )
91
+ })
92
+ .reply(
93
+ 200,
94
+ Buffer.from(
95
+ hex_decode(
96
+ '000181830001000000010001045f656e73046e69636b0378797a0000100001c0110006000100000258003b046e7337310d646f6d61696e636f6e74726f6c03636f6d0003646e73056a6f6d6178036e6574007876d1800000708000001c2000093a800000025800002904d0000080000000',
97
+ ),
98
+ ),
99
+ [
100
+ 'Server',
101
+ 'cloudflare',
102
+ 'Date',
103
+ 'Wed, 06 Jul 2022 23:37:28 GMT',
104
+ 'Content-Type',
105
+ 'application/dns-message',
106
+ 'Connection',
107
+ 'close',
108
+ 'Access-Control-Allow-Origin',
109
+ '*',
110
+ 'Content-Length',
111
+ '273',
112
+ 'CF-RAY',
113
+ '726c2b1d3bab6b74-TPE',
114
+ ],
115
+ )
116
+ try {
117
+ await getDNSOwner({}, dnsName)
118
+ } catch (error) {
119
+ expect(error.message).toEqual('DNS query failed: NXDOMAIN')
120
+ }
121
+ })
122
+ })
@@ -0,0 +1,61 @@
1
+ import * as packet from 'dns-packet'
2
+
3
+ export function encodeURLParams(p: { [key: string]: string }): string {
4
+ return Object.entries(p)
5
+ .map((kv) => kv.map(encodeURIComponent).join('='))
6
+ .join('&')
7
+ }
8
+
9
+ export const getDNS = async (q: packet.Packet): Promise<packet.Packet> => {
10
+ const response = await global.fetch(
11
+ `https://cloudflare-dns.com/dns-query?${encodeURLParams({
12
+ ct: 'application/dns-udpwireformat',
13
+ dns: packet.encode(q)?.toString('base64'),
14
+ ts: Date.now().toString(),
15
+ })}`,
16
+ )
17
+ const arrayBuffer = await response.arrayBuffer()
18
+ // @ts-ignore:next-line
19
+ const fromArrayBuffer = Buffer.from(arrayBuffer);
20
+ return packet.decode(fromArrayBuffer)
21
+ }
22
+
23
+ export const dnsQuery = async (
24
+ qtype: string,
25
+ qname: string,
26
+ ): Promise<packet.Packet> => {
27
+ const query: packet.Packet = {
28
+ type: 'query',
29
+ id: 1,
30
+ flags: packet.RECURSION_DESIRED,
31
+ questions: [
32
+ {
33
+ type: qtype,
34
+ class: 'IN',
35
+ name: qname,
36
+ },
37
+ ],
38
+ additionals: [
39
+ {
40
+ type: 'OPT',
41
+ class: 'IN',
42
+ name: '.',
43
+ udpPayloadSize: 4096,
44
+ flags: packet.DNSSEC_OK,
45
+ },
46
+ ],
47
+ answers: [],
48
+ }
49
+
50
+ const response = await getDNS(query)
51
+ if (response.rcode !== 'NOERROR') {
52
+ throw new Error(`DNS query failed: ${response.rcode}`)
53
+ }
54
+ return response
55
+ }
56
+
57
+ export default async function (_: any, dnsName: string) {
58
+ const result = await dnsQuery('TXT', `_ens.${dnsName}`)
59
+ const address = result?.answers?.[0]?.data?.[0]?.toString()?.split('=')?.[1]
60
+ return address
61
+ }
@@ -1,6 +1,6 @@
1
1
  import { ethers } from 'ethers'
2
2
  import { ENS } from '..'
3
- import setup from './setup'
3
+ import setup from '../tests/setup'
4
4
 
5
5
  let ENSInstance: ENS
6
6
  let revert: Awaited<ReturnType<typeof setup>>['revert']
@@ -1,6 +1,6 @@
1
1
  import { ethers } from 'ethers'
2
2
  import { ENS } from '..'
3
- import setup from './setup'
3
+ import setup from '../tests/setup'
4
4
 
5
5
  let ENSInstance: ENS
6
6
  let revert: Awaited<ReturnType<typeof setup>>['revert']
@@ -12,7 +12,9 @@ let withWrappedSnapshot: any
12
12
  beforeAll(async () => {
13
13
  ;({ ENSInstance, revert, provider, createSnapshot } = await setup())
14
14
  accounts = await provider.listAccounts()
15
- const tx = await ENSInstance.wrapName('parthtejpal.eth', accounts[0])
15
+ const tx = await ENSInstance.wrapName('parthtejpal.eth', {
16
+ wrappedOwner: accounts[0],
17
+ })
16
18
  await tx.wait()
17
19
 
18
20
  withWrappedSnapshot = await createSnapshot()
@@ -33,11 +35,10 @@ describe('getFuses', () => {
33
35
  expect(result).toBeUndefined()
34
36
  })
35
37
  it('should return with canDoEverything set to true for a name with no fuses burned', async () => {
36
- const tx = await ENSInstance.createSubname({
38
+ const tx = await ENSInstance.createSubname('test.parthtejpal.eth', {
37
39
  contract: 'nameWrapper',
38
- name: 'test.parthtejpal.eth',
39
40
  owner: accounts[0],
40
- options: { addressOrIndex: 0 },
41
+ addressOrIndex: 0,
41
42
  })
42
43
  await tx.wait()
43
44
 
@@ -56,9 +57,11 @@ describe('getFuses', () => {
56
57
  })
57
58
  it('should return with other correct fuses', async () => {
58
59
  const tx = await ENSInstance.burnFuses('parthtejpal.eth', {
59
- cannotUnwrap: true,
60
- cannotSetTtl: true,
61
- cannotCreateSubdomain: true,
60
+ fusesToBurn: {
61
+ cannotUnwrap: true,
62
+ cannotSetTtl: true,
63
+ cannotCreateSubdomain: true,
64
+ },
62
65
  })
63
66
  await tx.wait()
64
67
  const result = await ENSInstance.getFuses('parthtejpal.eth')
@@ -86,8 +89,7 @@ describe('getFuses', () => {
86
89
  }
87
90
  })
88
91
  it('should return correct vulnerability data for a vulnerable node', async () => {
89
- const tx = await ENSInstance.createSubname({
90
- name: 'test.parthtejpal.eth',
92
+ const tx = await ENSInstance.createSubname('test.parthtejpal.eth', {
91
93
  owner: accounts[0],
92
94
  contract: 'nameWrapper',
93
95
  })
@@ -1,6 +1,7 @@
1
- import { BigNumber, ethers, utils } from 'ethers'
1
+ import { BigNumber, utils } from 'ethers'
2
2
  import { ENSArgs } from '..'
3
3
  import { testable as fuseEnums } from '../utils/fuses'
4
+ import { namehash } from '../utils/normalise'
4
5
 
5
6
  const NameSafety = [
6
7
  'Safe',
@@ -15,7 +16,7 @@ const raw = async ({ contracts }: ENSArgs<'contracts'>, name: string) => {
15
16
  return {
16
17
  to: nameWrapper.address,
17
18
  data: nameWrapper.interface.encodeFunctionData('getFuses', [
18
- ethers.utils.namehash(name),
19
+ namehash(name),
19
20
  ]),
20
21
  }
21
22
  }
@@ -51,7 +52,7 @@ const decode = async (
51
52
  if (utils.hexStripZeros(vulnerableNode) !== '0x') {
52
53
  name.split('.').forEach((label, index, arr) => {
53
54
  const node = arr.slice(index).join('.')
54
- const nodehash = utils.namehash(node)
55
+ const nodehash = namehash(node)
55
56
  if (nodehash === vulnerableNode) {
56
57
  returnVulnerableNode = node
57
58
  }
@@ -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,6 +1,6 @@
1
1
  import { ethers } from 'ethers'
2
2
  import { ENS } from '..'
3
- import setup from './setup'
3
+ import setup from '../tests/setup'
4
4
 
5
5
  let ENSInstance: ENS
6
6
  let revert: Awaited<ReturnType<typeof setup>>['revert']
@@ -1,6 +1,6 @@
1
1
  import { ENS } from '..'
2
2
  import { OwnedName, Registration } from '../functions/getNames'
3
- import setup from './setup'
3
+ import setup from '../tests/setup'
4
4
 
5
5
  let ENSInstance: ENS
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { ethers } from 'ethers'
2
2
  import { ENS } from '..'
3
- import setup from './setup'
3
+ import setup from '../tests/setup'
4
4
 
5
5
  let ENSInstance: ENS
6
6
  let revert: Awaited<ReturnType<typeof setup>>['revert']
@@ -10,7 +10,9 @@ let accounts: string[]
10
10
  beforeAll(async () => {
11
11
  ;({ ENSInstance, revert, provider } = await setup())
12
12
  accounts = await provider.listAccounts()
13
- const tx = await ENSInstance.wrapName('parthtejpal.eth', accounts[0])
13
+ const tx = await ENSInstance.wrapName('parthtejpal.eth', {
14
+ wrappedOwner: accounts[0],
15
+ })
14
16
  await tx.wait()
15
17
  })
16
18
 
@@ -42,6 +44,16 @@ describe('getOwner', () => {
42
44
  expect(result?.ownershipLevel).toBe('registrar')
43
45
  expect(result?.registrant).toBe(nameWrapperAddress)
44
46
  })
47
+ it('should return the owner of a TLD on the registry', async () => {
48
+ const result = await ENSInstance.getOwner('eth')
49
+ const baseRegistrarAddress = (
50
+ await ENSInstance.contracts!.getBaseRegistrar()
51
+ ).address
52
+ expect(result?.ownershipLevel).toBe('registry')
53
+ expect(result?.owner?.toLowerCase()).toBe(
54
+ baseRegistrarAddress.toLowerCase(),
55
+ )
56
+ })
45
57
  // it('should return registry as the ownership level for an unwrapped subname', async () => {
46
58
  // const result0 = await ENSInstance.getOwner('fleek.eth')
47
59
  // console.log(result0?.owner, accounts[2])
@@ -1,6 +1,7 @@
1
1
  import { ethers } from 'ethers'
2
2
  import { ENSArgs } from '..'
3
3
  import { labelhash } from '../utils/labels'
4
+ import { namehash as makeNamehash } from '../utils/normalise'
4
5
 
5
6
  type Owner = {
6
7
  registrant?: string
@@ -49,13 +50,13 @@ const raw = async (
49
50
  name: string,
50
51
  contract?: 'nameWrapper' | 'registry' | 'registrar',
51
52
  ) => {
52
- const namehash = ethers.utils.namehash(name)
53
+ const namehash = makeNamehash(name)
53
54
  const labels = name.split('.')
54
55
 
55
- if (contract) {
56
+ if (contract || labels.length === 1) {
56
57
  return await singleContractOwnerRaw(
57
58
  { contracts },
58
- contract,
59
+ contract || 'registry',
59
60
  namehash,
60
61
  labels,
61
62
  )
@@ -99,10 +100,11 @@ const decode = async (
99
100
  contract?: 'nameWrapper' | 'registry' | 'registrar',
100
101
  ): Promise<Owner | undefined> => {
101
102
  if (data === null) return
102
- if (contract) {
103
+ const labels = name.split('.')
104
+ if (contract || labels.length === 1) {
103
105
  const singleOwner = singleContractOwnerDecode(data)
104
106
  let obj = {
105
- ownershipLevel: contract,
107
+ ownershipLevel: contract || 'registry',
106
108
  }
107
109
  if (contract === 'registrar') {
108
110
  return {
@@ -133,8 +135,6 @@ const decode = async (
133
135
  decodedData[2] as ethers.utils.Result | undefined
134
136
  )?.[0]
135
137
 
136
- const labels = name.split('.')
137
-
138
138
  // check for only .eth names
139
139
  if (labels[labels.length - 1] === 'eth') {
140
140
  // if the owner on the registrar is the namewrapper, then the namewrapper owner is the owner
@@ -1,18 +1,23 @@
1
1
  import { ENS } from '..'
2
- import setup from './setup'
2
+ import setup from '../tests/setup'
3
3
 
4
4
  let ENSInstance: ENS
5
+ let revert: Awaited<ReturnType<typeof setup>>['revert']
5
6
 
6
7
  beforeAll(async () => {
7
- ;({ ENSInstance } = await setup())
8
+ ;({ ENSInstance, revert } = await setup())
9
+ })
10
+
11
+ afterAll(async () => {
12
+ await revert()
8
13
  })
9
14
 
10
15
  const checkRecords = (
11
- result: Record<string, any> | null,
16
+ result: Record<string, any> | undefined,
12
17
  textLength = 3,
13
18
  coinTypeLength = 5,
14
19
  ) => {
15
- expect(result).toBeTruthy()
20
+ expect(result).toBeDefined()
16
21
  if (result) {
17
22
  expect(result.records?.texts).toHaveLength(textLength)
18
23
  expect(result.records?.coinTypes).toHaveLength(coinTypeLength)
@@ -22,24 +27,32 @@ const checkRecords = (
22
27
  }
23
28
  }
24
29
 
30
+ jest.setTimeout(20000)
31
+
25
32
  describe('getProfile', () => {
26
33
  describe('with an address', () => {
27
34
  it('should return a profile object with no other args', async () => {
28
35
  const result = await ENSInstance.getProfile(
29
36
  '0x866B3c4994e1416B7C738B9818b31dC246b95eEE',
30
37
  )
31
- expect((result as any).name).toBe('jefflau.eth')
32
- expect((result as any).address).toBeUndefined()
33
- checkRecords(result)
38
+ expect(result).toBeDefined()
39
+ if (result) {
40
+ expect((result as any).name).toBe('jefflau.eth')
41
+ expect((result as any).address).toBeUndefined()
42
+ checkRecords(result)
43
+ }
34
44
  })
35
45
  it('should return a profile object with specified records', async () => {
36
46
  const result = await ENSInstance.getProfile(
37
47
  '0x866B3c4994e1416B7C738B9818b31dC246b95eEE',
38
48
  { texts: ['description', 'url'], coinTypes: ['ETC', '0'] },
39
49
  )
40
- expect((result as any).name).toBe('jefflau.eth')
41
- expect((result as any).address).toBeUndefined()
42
- checkRecords(result, 2, 3)
50
+ expect(result).toBeDefined()
51
+ if (result) {
52
+ expect((result as any).name).toBe('jefflau.eth')
53
+ expect((result as any).address).toBeUndefined()
54
+ checkRecords(result, 2, 3)
55
+ }
43
56
  })
44
57
  it('should return a profile object with all of each specified record type', async () => {
45
58
  const result = await ENSInstance.getProfile(
@@ -80,11 +93,32 @@ describe('getProfile', () => {
80
93
  })
81
94
  checkRecords(result)
82
95
  })
83
- it('should return null for an unregistered name', async () => {
96
+ it('should return a profile object for a specified resolver', async () => {
97
+ const result = await ENSInstance.getProfile('saganaki.xyz', {
98
+ resolverAddress: '0x12299799a50340fb860d276805e78550cbad3de3',
99
+ })
100
+ expect(result).toBeDefined()
101
+ expect(result?.address).toBe('0x157545BfD441453921049998128Ff090c1c11230')
102
+ expect(result?.resolverAddress).toBe(
103
+ '0x12299799a50340fb860d276805e78550cbad3de3',
104
+ )
105
+ })
106
+ it('should return undefined for an unregistered name', async () => {
84
107
  const result = await ENSInstance.getProfile('test123123123cool.eth')
85
108
  expect(result).toBeUndefined()
86
109
  })
87
110
  })
111
+ describe('with an old resolver', () => {
112
+ it('should use fallback methods for a name with an older resolver (no multicall)', async () => {
113
+ const result = await ENSInstance.getProfile('pepeq6.eth')
114
+ expect(result).toBeDefined()
115
+ if (result) {
116
+ expect(result.address).toBe(
117
+ '0x6308F1c6f283583C8bf8E31Da793B87718b051eD',
118
+ )
119
+ }
120
+ })
121
+ })
88
122
  describe('with an unmigrated name', () => {
89
123
  beforeAll(async () => {
90
124
  ;({ ENSInstance } = await setup(true))
@@ -95,7 +129,6 @@ describe('getProfile', () => {
95
129
  expect(result).toBeTruthy()
96
130
  if (result) {
97
131
  expect(result.isMigrated).toBe(false)
98
- expect(result.message).toBe("Records fetch didn't complete")
99
132
  }
100
133
  })
101
134
  })