@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.
- package/README.md +2 -0
- package/dist/cjs/GqlManager.d.ts +3 -0
- package/dist/cjs/GqlManager.js +62 -2
- package/dist/cjs/functions/burnFuses.d.ts +3 -2
- package/dist/cjs/functions/burnFuses.js +4 -8
- package/dist/cjs/functions/createSubname.d.ts +1 -5
- package/dist/cjs/functions/createSubname.js +5 -8
- package/dist/cjs/functions/deleteSubname.d.ts +3 -3
- package/dist/cjs/functions/deleteSubname.js +5 -2
- package/dist/cjs/functions/getDNSOwner.d.ts +7 -0
- package/dist/cjs/functions/getDNSOwner.js +81 -0
- package/dist/cjs/functions/getFuses.js +3 -2
- package/dist/cjs/functions/getOwner.js +7 -6
- package/dist/cjs/functions/getProfile.d.ts +4 -1
- package/dist/cjs/functions/getProfile.js +102 -24
- package/dist/cjs/functions/getRecords.d.ts +1 -0
- package/dist/cjs/functions/getSpecificRecord.js +22 -5
- package/dist/cjs/functions/getSubnames.js +6 -6
- package/dist/cjs/functions/setName.d.ts +4 -3
- package/dist/cjs/functions/setName.js +5 -10
- package/dist/cjs/functions/setRecord.d.ts +18 -0
- package/dist/cjs/functions/setRecord.js +27 -0
- package/dist/cjs/functions/setRecords.d.ts +4 -2
- package/dist/cjs/functions/setRecords.js +14 -12
- package/dist/cjs/functions/setResolver.d.ts +4 -4
- package/dist/cjs/functions/setResolver.js +6 -12
- package/dist/cjs/functions/transferName.d.ts +4 -3
- package/dist/cjs/functions/transferName.js +9 -13
- package/dist/cjs/functions/transferSubname.d.ts +4 -3
- package/dist/cjs/functions/transferSubname.js +5 -8
- package/dist/cjs/functions/unwrapName.d.ts +4 -3
- package/dist/cjs/functions/unwrapName.js +5 -9
- package/dist/cjs/functions/wrapName.d.ts +5 -3
- package/dist/cjs/functions/wrapName.js +8 -12
- package/dist/cjs/index.d.ts +48 -46
- package/dist/cjs/index.js +43 -19
- package/dist/cjs/utils/labels.js +5 -4
- package/dist/cjs/utils/makeHashIndexes.js +2 -2
- package/dist/cjs/utils/normalise.d.ts +1 -0
- package/dist/cjs/utils/normalise.js +27 -1
- package/dist/cjs/utils/recordHelpers.d.ts +3 -0
- package/dist/cjs/utils/recordHelpers.js +42 -15
- package/dist/cjs/utils/registerHelpers.js +3 -4
- package/dist/cjs/utils/writeTx.d.ts +4 -0
- package/dist/cjs/utils/writeTx.js +3 -0
- package/dist/esm/GqlManager.d.ts +3 -0
- package/dist/esm/GqlManager.js +58 -2
- package/dist/esm/functions/burnFuses.d.ts +3 -2
- package/dist/esm/functions/burnFuses.js +4 -8
- package/dist/esm/functions/createSubname.d.ts +1 -5
- package/dist/esm/functions/createSubname.js +5 -8
- package/dist/esm/functions/deleteSubname.d.ts +3 -3
- package/dist/esm/functions/deleteSubname.js +5 -2
- package/dist/esm/functions/getDNSOwner.d.ts +7 -0
- package/dist/esm/functions/getDNSOwner.js +51 -0
- package/dist/esm/functions/getFuses.js +4 -3
- package/dist/esm/functions/getOwner.js +7 -6
- package/dist/esm/functions/getProfile.d.ts +4 -1
- package/dist/esm/functions/getProfile.js +102 -24
- package/dist/esm/functions/getRecords.d.ts +1 -0
- package/dist/esm/functions/getSpecificRecord.js +22 -5
- package/dist/esm/functions/getSubnames.js +3 -3
- package/dist/esm/functions/setName.d.ts +4 -3
- package/dist/esm/functions/setName.js +5 -10
- package/dist/esm/functions/setRecord.d.ts +18 -0
- package/dist/esm/functions/setRecord.js +24 -0
- package/dist/esm/functions/setRecords.d.ts +4 -2
- package/dist/esm/functions/setRecords.js +14 -12
- package/dist/esm/functions/setResolver.d.ts +4 -4
- package/dist/esm/functions/setResolver.js +6 -12
- package/dist/esm/functions/transferName.d.ts +4 -3
- package/dist/esm/functions/transferName.js +9 -13
- package/dist/esm/functions/transferSubname.d.ts +4 -3
- package/dist/esm/functions/transferSubname.js +5 -8
- package/dist/esm/functions/unwrapName.d.ts +4 -3
- package/dist/esm/functions/unwrapName.js +5 -9
- package/dist/esm/functions/wrapName.d.ts +5 -3
- package/dist/esm/functions/wrapName.js +8 -12
- package/dist/esm/index.d.ts +48 -46
- package/dist/esm/index.js +43 -19
- package/dist/esm/utils/labels.js +5 -4
- package/dist/esm/utils/makeHashIndexes.js +2 -2
- package/dist/esm/utils/normalise.d.ts +1 -0
- package/dist/esm/utils/normalise.js +25 -0
- package/dist/esm/utils/recordHelpers.d.ts +3 -0
- package/dist/esm/utils/recordHelpers.js +40 -14
- package/dist/esm/utils/registerHelpers.js +3 -4
- package/dist/esm/utils/writeTx.d.ts +4 -0
- package/dist/esm/utils/writeTx.js +1 -0
- package/package.json +15 -7
- package/src/@types/dns-packet/index.d.ts +114 -0
- package/src/GqlManager.test.ts +170 -0
- package/src/GqlManager.ts +67 -2
- package/src/{tests → functions}/batch.test.ts +1 -1
- package/src/{tests → functions}/batchWrappers.test.ts +1 -1
- package/src/{tests → functions}/burnFuses.test.ts +12 -10
- package/src/functions/burnFuses.ts +9 -11
- package/src/{tests → functions}/createSubname.test.ts +12 -16
- package/src/functions/createSubname.ts +7 -13
- package/src/{tests → functions}/deleteSubname.test.ts +32 -32
- package/src/functions/deleteSubname.ts +9 -12
- package/src/functions/getDNSOwner.test.ts +122 -0
- package/src/functions/getDNSOwner.ts +61 -0
- package/src/{tests → functions}/getExpiry.test.ts +1 -1
- package/src/{tests → functions}/getFuses.test.ts +12 -10
- package/src/functions/getFuses.ts +4 -3
- package/src/{tests → functions}/getHistory.test.ts +1 -1
- package/src/{tests → functions}/getName.test.ts +1 -1
- package/src/{tests → functions}/getNames.test.ts +1 -1
- package/src/{tests → functions}/getOwner.test.ts +14 -2
- package/src/functions/getOwner.ts +7 -7
- package/src/{tests → functions}/getProfile.test.ts +45 -12
- package/src/functions/getProfile.ts +151 -24
- package/src/functions/getRecords.ts +1 -0
- package/src/{tests → functions}/getResolver.test.ts +1 -1
- package/src/{tests → functions}/getSpecificRecord.test.ts +1 -1
- package/src/functions/getSpecificRecord.ts +28 -8
- package/src/{tests → functions}/getSubnames.test.ts +1 -1
- package/src/functions/getSubnames.ts +68 -66
- package/src/{tests → functions}/makeCommitment.test.ts +1 -1
- package/src/functions/normalise.test.ts +22 -0
- package/src/{tests → functions}/setName.test.ts +3 -2
- package/src/functions/setName.ts +15 -17
- package/src/functions/setRecord.test.ts +100 -0
- package/src/functions/setRecord.ts +63 -0
- package/src/{tests → functions}/setRecords.test.ts +12 -10
- package/src/functions/setRecords.ts +22 -16
- package/src/{tests → functions}/setResolver.test.ts +12 -15
- package/src/functions/setResolver.ts +15 -20
- package/src/{tests → functions}/transferName.test.ts +30 -31
- package/src/functions/transferName.ts +19 -22
- package/src/{tests → functions}/transferSubname.test.ts +34 -34
- package/src/functions/transferSubname.ts +21 -13
- package/src/{tests → functions}/unwrapName.test.ts +24 -23
- package/src/functions/unwrapName.ts +20 -15
- package/src/{tests → functions}/wrapName.test.ts +19 -19
- package/src/functions/wrapName.ts +20 -22
- package/src/index.ts +115 -26
- package/src/tests/populateTransaction.test.ts +40 -0
- package/src/tests/signerInjection.test.ts +46 -0
- package/src/tests/withProvider.test.ts +1 -1
- package/src/utils/labels.ts +6 -4
- package/src/utils/makeHashIndexes.ts +4 -4
- package/src/utils/normalise.ts +29 -0
- package/src/utils/recordHelpers.ts +52 -18
- package/src/utils/registerHelpers.ts +3 -4
- 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 '
|
|
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',
|
|
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
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
55
|
+
const nodehash = namehash(node)
|
|
55
56
|
if (nodehash === vulnerableNode) {
|
|
56
57
|
returnVulnerableNode = node
|
|
57
58
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ethers } from 'ethers'
|
|
2
2
|
import { ENS } from '..'
|
|
3
|
-
import setup from '
|
|
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',
|
|
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 =
|
|
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
|
-
|
|
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 '
|
|
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> |
|
|
16
|
+
result: Record<string, any> | undefined,
|
|
12
17
|
textLength = 3,
|
|
13
18
|
coinTypeLength = 5,
|
|
14
19
|
) => {
|
|
15
|
-
expect(result).
|
|
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(
|
|
32
|
-
|
|
33
|
-
|
|
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(
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
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
|
})
|