@ensdomains/ensjs 3.0.0-alpha.1 → 3.0.0-alpha.2
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/functions/burnFuses.d.ts +1 -2
- package/dist/cjs/functions/burnFuses.js +3 -3
- package/dist/cjs/functions/createSubname.js +2 -1
- package/dist/cjs/functions/getFuses.js +3 -2
- package/dist/cjs/functions/getOwner.js +7 -6
- package/dist/cjs/functions/getProfile.d.ts +1 -1
- package/dist/cjs/functions/getProfile.js +49 -15
- package/dist/cjs/functions/getSpecificRecord.js +22 -5
- package/dist/cjs/functions/getSubnames.js +6 -6
- package/dist/cjs/functions/setRecords.d.ts +1 -2
- package/dist/cjs/functions/setRecords.js +3 -3
- package/dist/cjs/functions/setResolver.d.ts +1 -2
- package/dist/cjs/functions/setResolver.js +3 -3
- package/dist/cjs/functions/transferName.js +3 -2
- package/dist/cjs/functions/transferSubname.js +2 -1
- package/dist/cjs/functions/unwrapName.js +2 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/utils/makeHashIndexes.js +2 -2
- package/dist/cjs/utils/normalise.d.ts +1 -0
- package/dist/cjs/utils/normalise.js +20 -1
- package/dist/cjs/utils/registerHelpers.js +3 -4
- package/dist/esm/functions/burnFuses.d.ts +1 -2
- package/dist/esm/functions/burnFuses.js +3 -3
- package/dist/esm/functions/createSubname.js +2 -1
- package/dist/esm/functions/getFuses.js +4 -3
- package/dist/esm/functions/getOwner.js +7 -6
- package/dist/esm/functions/getProfile.d.ts +1 -1
- package/dist/esm/functions/getProfile.js +49 -15
- package/dist/esm/functions/getSpecificRecord.js +22 -5
- package/dist/esm/functions/getSubnames.js +3 -3
- package/dist/esm/functions/setRecords.d.ts +1 -2
- package/dist/esm/functions/setRecords.js +3 -3
- package/dist/esm/functions/setResolver.d.ts +1 -2
- package/dist/esm/functions/setResolver.js +3 -3
- package/dist/esm/functions/transferName.js +3 -2
- package/dist/esm/functions/transferSubname.js +2 -1
- package/dist/esm/functions/unwrapName.js +2 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/utils/makeHashIndexes.js +2 -2
- package/dist/esm/utils/normalise.d.ts +1 -0
- package/dist/esm/utils/normalise.js +18 -0
- package/dist/esm/utils/registerHelpers.js +3 -4
- package/package.json +3 -2
- package/src/functions/burnFuses.ts +3 -3
- package/src/functions/createSubname.ts +2 -1
- package/src/functions/getFuses.ts +4 -3
- package/src/functions/getOwner.ts +7 -7
- package/src/functions/getProfile.ts +77 -13
- package/src/functions/getSpecificRecord.ts +28 -8
- package/src/functions/getSubnames.ts +68 -66
- package/src/functions/setRecords.ts +3 -3
- package/src/functions/setResolver.ts +3 -3
- package/src/functions/transferName.ts +3 -2
- package/src/functions/transferSubname.ts +2 -1
- package/src/functions/unwrapName.ts +2 -1
- package/src/index.ts +1 -0
- package/src/tests/burnFuses.test.ts +3 -2
- package/src/tests/createSubname.test.ts +4 -5
- package/src/tests/deleteSubname.test.ts +4 -5
- package/src/tests/getOwner.test.ts +10 -0
- package/src/tests/getProfile.test.ts +28 -10
- package/src/tests/normalise.test.ts +22 -0
- package/src/tests/setRecords.test.ts +3 -3
- package/src/tests/transferName.test.ts +3 -2
- package/src/tests/transferSubname.test.ts +4 -5
- package/src/tests/unwrapName.test.ts +2 -1
- package/src/tests/wrapName.test.ts +4 -7
- package/src/utils/makeHashIndexes.ts +4 -4
- package/src/utils/normalise.ts +23 -0
- package/src/utils/registerHelpers.ts +3 -4
|
@@ -42,6 +42,16 @@ describe('getOwner', () => {
|
|
|
42
42
|
expect(result?.ownershipLevel).toBe('registrar')
|
|
43
43
|
expect(result?.registrant).toBe(nameWrapperAddress)
|
|
44
44
|
})
|
|
45
|
+
it('should return the owner of a TLD on the registry', async () => {
|
|
46
|
+
const result = await ENSInstance.getOwner('eth')
|
|
47
|
+
const baseRegistrarAddress = (
|
|
48
|
+
await ENSInstance.contracts!.getBaseRegistrar()
|
|
49
|
+
).address
|
|
50
|
+
expect(result?.ownershipLevel).toBe('registry')
|
|
51
|
+
expect(result?.owner?.toLowerCase()).toBe(
|
|
52
|
+
baseRegistrarAddress.toLowerCase(),
|
|
53
|
+
)
|
|
54
|
+
})
|
|
45
55
|
// it('should return registry as the ownership level for an unwrapped subname', async () => {
|
|
46
56
|
// const result0 = await ENSInstance.getOwner('fleek.eth')
|
|
47
57
|
// console.log(result0?.owner, accounts[2])
|
|
@@ -8,11 +8,11 @@ beforeAll(async () => {
|
|
|
8
8
|
})
|
|
9
9
|
|
|
10
10
|
const checkRecords = (
|
|
11
|
-
result: Record<string, any> |
|
|
11
|
+
result: Record<string, any> | undefined,
|
|
12
12
|
textLength = 3,
|
|
13
13
|
coinTypeLength = 5,
|
|
14
14
|
) => {
|
|
15
|
-
expect(result).
|
|
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(
|
|
32
|
-
|
|
33
|
-
|
|
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(
|
|
41
|
-
|
|
42
|
-
|
|
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
|
|
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
|
})
|
|
@@ -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,6 +1,6 @@
|
|
|
1
|
-
import { utils } from 'ethers'
|
|
2
1
|
import { ENS } from '..'
|
|
3
2
|
import { hexEncodeName } from '../utils/hexEncodedName'
|
|
3
|
+
import { namehash } from '../utils/normalise'
|
|
4
4
|
import setup from './setup'
|
|
5
5
|
|
|
6
6
|
let ENSInstance: ENS
|
|
@@ -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
|
-
|
|
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
|
-
|
|
41
|
+
namehash('parthtejpal.eth'),
|
|
42
42
|
'61',
|
|
43
43
|
]),
|
|
44
44
|
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ethers, utils } from 'ethers'
|
|
2
2
|
import { ENS } from '..'
|
|
3
|
+
import { namehash } from '../utils/normalise'
|
|
3
4
|
import setup from './setup'
|
|
4
5
|
|
|
5
6
|
let ENSInstance: ENS
|
|
@@ -52,7 +53,7 @@ describe('transferName', () => {
|
|
|
52
53
|
await tx.wait()
|
|
53
54
|
|
|
54
55
|
const nameWrapper = await ENSInstance.contracts!.getNameWrapper()!
|
|
55
|
-
const result = await nameWrapper.ownerOf(
|
|
56
|
+
const result = await nameWrapper.ownerOf(namehash('parthtejpal.eth'))
|
|
56
57
|
expect(result).toBe(accounts[1])
|
|
57
58
|
})
|
|
58
59
|
it('should allow a transfer on the registry', async () => {
|
|
@@ -74,7 +75,7 @@ describe('transferName', () => {
|
|
|
74
75
|
await tx.wait()
|
|
75
76
|
|
|
76
77
|
const registry = await ENSInstance.contracts!.getRegistry()!
|
|
77
|
-
const result = await registry.owner(
|
|
78
|
+
const result = await registry.owner(namehash('test.parthtejpal.eth'))
|
|
78
79
|
expect(result).toBe(accounts[1])
|
|
79
80
|
})
|
|
80
81
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ethers
|
|
1
|
+
import { ethers } from 'ethers'
|
|
2
2
|
import { ENS } from '..'
|
|
3
|
+
import { namehash } from '../utils/normalise'
|
|
3
4
|
import setup from './setup'
|
|
4
5
|
|
|
5
6
|
let ENSInstance: ENS
|
|
@@ -39,7 +40,7 @@ describe('transferSubname', () => {
|
|
|
39
40
|
await tx.wait()
|
|
40
41
|
|
|
41
42
|
const registry = await ENSInstance.contracts!.getRegistry()!
|
|
42
|
-
const result = await registry.owner(
|
|
43
|
+
const result = await registry.owner(namehash('test.parthtejpal.eth'))
|
|
43
44
|
expect(result).toBe(accounts[1])
|
|
44
45
|
})
|
|
45
46
|
it('should allow transferring a subname on the nameWrapper', async () => {
|
|
@@ -66,9 +67,7 @@ describe('transferSubname', () => {
|
|
|
66
67
|
await tx.wait()
|
|
67
68
|
|
|
68
69
|
const nameWrapper = await ENSInstance.contracts!.getNameWrapper()!
|
|
69
|
-
const result = await nameWrapper.ownerOf(
|
|
70
|
-
utils.namehash('test.parthtejpal.eth'),
|
|
71
|
-
)
|
|
70
|
+
const result = await nameWrapper.ownerOf(namehash('test.parthtejpal.eth'))
|
|
72
71
|
expect(result).toBe(accounts[1])
|
|
73
72
|
})
|
|
74
73
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ethers, utils } from 'ethers'
|
|
2
2
|
import { ENS } from '..'
|
|
3
|
+
import { namehash } from '../utils/normalise'
|
|
3
4
|
import setup from './setup'
|
|
4
5
|
|
|
5
6
|
let ENSInstance: ENS
|
|
@@ -61,7 +62,7 @@ describe('unwrapName', () => {
|
|
|
61
62
|
await tx.wait()
|
|
62
63
|
|
|
63
64
|
const registry = await ENSInstance.contracts!.getRegistry()!
|
|
64
|
-
const result = await registry.owner(
|
|
65
|
+
const result = await registry.owner(namehash('test.parthtejpal.eth'))
|
|
65
66
|
expect(result).toBe(accounts[0])
|
|
66
67
|
})
|
|
67
68
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { BigNumber, ethers
|
|
1
|
+
import { BigNumber, ethers } from 'ethers'
|
|
2
2
|
import { ENS } from '..'
|
|
3
3
|
import { hexEncodeName } from '../utils/hexEncodedName'
|
|
4
|
+
import { namehash } from '../utils/normalise'
|
|
4
5
|
import setup from './setup'
|
|
5
6
|
|
|
6
7
|
let ENSInstance: ENS
|
|
@@ -28,9 +29,7 @@ describe('wrapName', () => {
|
|
|
28
29
|
await tx.wait()
|
|
29
30
|
|
|
30
31
|
const nameWrapper = await ENSInstance.contracts!.getNameWrapper()!
|
|
31
|
-
const [result] = await nameWrapper.getFuses(
|
|
32
|
-
utils.namehash('parthtejpal.eth'),
|
|
33
|
-
)
|
|
32
|
+
const [result] = await nameWrapper.getFuses(namehash('parthtejpal.eth'))
|
|
34
33
|
expect((result as BigNumber).toHexString()).toBe('0x40')
|
|
35
34
|
})
|
|
36
35
|
it('should allow initial fuses', async () => {
|
|
@@ -42,9 +41,7 @@ describe('wrapName', () => {
|
|
|
42
41
|
await tx.wait()
|
|
43
42
|
|
|
44
43
|
const nameWrapper = await ENSInstance.contracts!.getNameWrapper()!
|
|
45
|
-
const [result] = await nameWrapper.getFuses(
|
|
46
|
-
utils.namehash('parthtejpal.eth'),
|
|
47
|
-
)
|
|
44
|
+
const [result] = await nameWrapper.getFuses(namehash('parthtejpal.eth'))
|
|
48
45
|
expect((result as BigNumber).toHexString()).toBe('0x51')
|
|
49
46
|
})
|
|
50
47
|
it('should allow an initial resolver address', async () => {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { namehash } from './normalise'
|
|
2
2
|
|
|
3
3
|
export const makeOtherIndexes = (data: string, findStr: string) =>
|
|
4
4
|
Array.from(data.matchAll(findStr as any)).map((x: any) => x.index / 2 - 1)
|
|
5
5
|
|
|
6
6
|
export const makeNamehashIndexes = (data: string, name: string) =>
|
|
7
|
-
Array.from(
|
|
8
|
-
|
|
9
|
-
)
|
|
7
|
+
Array.from(data.matchAll(namehash(name).substring(2) as any)).map(
|
|
8
|
+
(x: any) => x.index / 2 - 1,
|
|
9
|
+
)
|
package/src/utils/normalise.ts
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
|
+
import { concat, hexlify, keccak256, toUtf8Bytes } from 'ethers/lib/utils'
|
|
1
2
|
import uts46 from 'idna-uts46-hx/uts46bundle.js'
|
|
2
3
|
|
|
4
|
+
const zeros = new Uint8Array(32)
|
|
5
|
+
zeros.fill(0)
|
|
6
|
+
|
|
3
7
|
export const normalise = (name: string) =>
|
|
4
8
|
name ? uts46.toUnicode(name, { useStd3ASCII: true }) : name
|
|
9
|
+
|
|
10
|
+
export const namehash = (inputName: string): string => {
|
|
11
|
+
let result: string | Uint8Array = zeros
|
|
12
|
+
|
|
13
|
+
const name = normalise(inputName)
|
|
14
|
+
|
|
15
|
+
if (name) {
|
|
16
|
+
const labels = name.split('.')
|
|
17
|
+
|
|
18
|
+
for (var i = labels.length - 1; i >= 0; i--) {
|
|
19
|
+
const labelSha = keccak256(toUtf8Bytes(labels[i]))
|
|
20
|
+
result = keccak256(concat([result, labelSha]))
|
|
21
|
+
}
|
|
22
|
+
} else {
|
|
23
|
+
result = hexlify(zeros)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return result as string
|
|
27
|
+
}
|
|
@@ -3,6 +3,7 @@ import type { FuseOptions } from '../@types/FuseOptions'
|
|
|
3
3
|
import type { PublicResolver } from '../generated'
|
|
4
4
|
import generateFuseInput from './generateFuseInput'
|
|
5
5
|
import { labelhash } from './labels'
|
|
6
|
+
import { namehash } from './normalise'
|
|
6
7
|
import { generateRecordCallArray, RecordOptions } from './recordHelpers'
|
|
7
8
|
|
|
8
9
|
export const randomSecret = () => {
|
|
@@ -28,11 +29,9 @@ export const makeCommitment = ({
|
|
|
28
29
|
fuses?: FuseOptions
|
|
29
30
|
}) => {
|
|
30
31
|
const label = labelhash(name.split('.')[0])
|
|
31
|
-
const
|
|
32
|
+
const hash = namehash(name)
|
|
32
33
|
const resolverAddress = resolver.address
|
|
33
|
-
const data = records
|
|
34
|
-
? generateRecordCallArray(namehash, records, resolver)
|
|
35
|
-
: []
|
|
34
|
+
const data = records ? generateRecordCallArray(hash, records, resolver) : []
|
|
36
35
|
const secret = randomSecret()
|
|
37
36
|
const fuseData = fuses ? generateFuseInput(fuses) : '0'
|
|
38
37
|
|