1
1
import { concat , hexlify } from "@ethersproject/bytes" ;
2
- import { toUtf8Bytes } from "@ethersproject/strings" ;
2
+ import { toUtf8Bytes , toUtf8String } from "@ethersproject/strings" ;
3
3
import { keccak256 } from "@ethersproject/keccak256" ;
4
4
5
5
import { Logger } from "@ethersproject/logger" ;
@@ -11,11 +11,59 @@ import { ens_normalize } from "./ens-normalize/lib";
11
11
const Zeros = new Uint8Array ( 32 ) ;
12
12
Zeros . fill ( 0 ) ;
13
13
14
- const Partition = new RegExp ( "^((.*)\\.)?([^.]+)$" ) ;
14
+ function checkComponent ( comp : Uint8Array ) : Uint8Array {
15
+ if ( comp . length === 0 ) { throw new Error ( "invalid ENS name; empty component" ) ; }
16
+ let nonUnder = false ;
17
+ let last = - 1 ;
18
+ for ( let i = 0 ; i < comp . length ; i ++ ) {
19
+ const c = comp [ i ] ;
20
+
21
+ // An underscore (i.e. "_"); only allows at the beginning
22
+ if ( c === 0x5f ) {
23
+ if ( nonUnder ) { throw new Error ( "invalid ENS name; non-prefix underscore" ) ; }
24
+ } else {
25
+ // A hyphen (i.e. "-"); only allows a single in a row
26
+ if ( c === 0x2d && last === c ) {
27
+ throw new Error ( "invalid ENS name; double-hyphen" ) ;
28
+ }
29
+ nonUnder = true ;
30
+ }
31
+ last = c ;
32
+ }
33
+ return comp ;
34
+ }
35
+
36
+ function ensNameSplit ( name : string ) : Array < Uint8Array > {
37
+ const bytes = toUtf8Bytes ( ens_normalize ( name ) ) ;
38
+ const comps : Array < Uint8Array > = [ ] ;
39
+
40
+ if ( name . length === 0 ) { return comps ; }
41
+
42
+ let last = 0 ;
43
+ for ( let i = 0 ; i < bytes . length ; i ++ ) {
44
+ const d = bytes [ i ] ;
45
+
46
+ // A separator (i.e. "."); copy this component
47
+ if ( d === 0x2e ) {
48
+ comps . push ( checkComponent ( bytes . slice ( last , i ) ) ) ;
49
+ last = i + 1 ;
50
+ }
51
+ }
52
+
53
+ // There was a stray separator at the end of the name
54
+ if ( last >= bytes . length ) { throw new Error ( "invalid ENS name; empty component" ) ; }
55
+
56
+ comps . push ( checkComponent ( bytes . slice ( last ) ) ) ;
57
+ return comps ;
58
+ }
59
+
60
+ export function ensNormalize ( name : string ) : string {
61
+ return ensNameSplit ( name ) . map ( ( comp ) => toUtf8String ( comp ) ) . join ( "." ) ;
62
+ }
15
63
16
64
export function isValidName ( name : string ) : boolean {
17
65
try {
18
- return ens_normalize ( name ) . length !== 0 ;
66
+ return ( ensNameSplit ( name ) . length !== 0 ) ;
19
67
} catch ( error ) { }
20
68
return false ;
21
69
}
@@ -26,34 +74,28 @@ export function namehash(name: string): string {
26
74
logger . throwArgumentError ( "invalid ENS name; not a string" , "name" , name ) ;
27
75
}
28
76
29
- let current = ens_normalize ( name ) ;
30
77
let result : string | Uint8Array = Zeros ;
31
- while ( current . length ) {
32
- const partition = current . match ( Partition ) ;
33
- if ( partition == null || partition [ 2 ] === "" ) {
34
- logger . throwArgumentError ( "invalid ENS address; missing component" , "name" , name ) ;
35
- }
36
- const label = toUtf8Bytes ( partition [ 3 ] ) ;
37
- result = keccak256 ( concat ( [ result , keccak256 ( label ) ] ) ) ;
38
78
39
- current = partition [ 2 ] || "" ;
79
+ const comps = ensNameSplit ( name ) ;
80
+ while ( comps . length ) {
81
+ result = keccak256 ( concat ( [ result , keccak256 ( comps . pop ( ) ) ] ) ) ;
40
82
}
41
83
42
84
return hexlify ( result ) ;
43
85
}
44
86
45
87
export function dnsEncode ( name : string ) : string {
46
- name = ens_normalize ( name )
47
- return hexlify ( concat ( name . split ( "." ) . map ( ( comp ) => {
48
-
88
+ return hexlify ( concat ( ensNameSplit ( name ) . map ( ( comp ) => {
49
89
// DNS does not allow components over 63 bytes in length
50
- if ( toUtf8Bytes ( comp ) . length > 63 ) {
90
+ if ( comp . length > 63 ) {
51
91
throw new Error ( "invalid DNS encoded entry; length exceeds 63 bytes" ) ;
52
92
}
53
93
54
- // We jam in an _ prefix to fill in with the length later
55
- const bytes = toUtf8Bytes ( "_" + comp ) ;
94
+ const bytes = new Uint8Array ( comp . length + 1 ) ;
95
+ bytes . set ( comp , 1 ) ;
56
96
bytes [ 0 ] = bytes . length - 1 ;
57
97
return bytes ;
98
+
58
99
} ) ) ) + "00" ;
59
100
}
101
+
0 commit comments