forked from wealdtech/go-ens
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmisc.go
136 lines (123 loc) · 3.36 KB
/
misc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package ens
import (
"fmt"
"strings"
)
// DomainLevel calculates the level of the domain presented.
// A top-level domain (e.g. 'eth') will be 0, a domain (e.g.
// 'foo.eth') will be 1, a subdomain (e.g. 'bar.foo.eth' will
// be 2, etc.
func DomainLevel(name string) (level int) {
return len(strings.Split(name, ".")) - 1
}
// NormaliseDomain turns ENS domain in to normal form
func NormaliseDomain(domain string) (string, error) {
wildcard := false
if strings.HasPrefix(domain, "*.") {
wildcard = true
domain = domain[2:]
}
output, err := p.ToUnicode(strings.ToLower(domain))
if err != nil {
return "", err
}
// ToUnicode() removes leading periods. Replace them
if strings.HasPrefix(domain, ".") && !strings.HasPrefix(output, ".") {
output = "." + output
}
// If we removed a wildcard then add it back
if wildcard {
output = "*." + output
}
return output, nil
}
// NormaliseDomainStrict turns ENS domain in to normal form, using strict DNS
// rules (e.g. no underscores)
func NormaliseDomainStrict(domain string) (string, error) {
wildcard := false
if strings.HasPrefix(domain, "*.") {
wildcard = true
domain = domain[2:]
}
output, err := pStrict.ToUnicode(strings.ToLower(domain))
if err != nil {
return "", err
}
// ToUnicode() removes leading periods. Replace them
if strings.HasPrefix(domain, ".") && !strings.HasPrefix(output, ".") {
output = "." + output
}
// If we removed a wildcard then add it back
if wildcard {
output = "*." + output
}
return output, nil
}
// Tld obtains the top-level domain of an ENS name
func Tld(domain string) string {
domain, err := NormaliseDomain(domain)
if err != nil {
return domain
}
tld, err := DomainPart(domain, -1)
if err != nil {
return domain
}
return tld
}
// Domain obtains the domain of an ENS name, including subdomains. It does this
// by removing everything up to and including the first period.
// For example, 'eth' will return ''
// 'foo.eth' will return 'eth'
// 'bar.foo.eth' will return 'foo.eth'
func Domain(domain string) string {
if idx := strings.IndexByte(domain, '.'); idx >= 0 {
return domain[idx+1:]
}
return ""
}
// DomainPart obtains a part of a name
// Positive parts start at the lowest-level of the domain and work towards the
// top-level domain. Negative parts start at the top-level domain and work
// towards the lowest-level domain.
// For example, with a domain bar.foo.com the following parts will be returned:
// Number | part
// 1 | bar
// 2 | foo
// 3 | com
// -1 | com
// -2 | foo
// -3 | bar
func DomainPart(domain string, part int) (string, error) {
if part == 0 {
return "", fmt.Errorf("invalid part")
}
domain, err := NormaliseDomain(domain)
if err != nil {
return "", err
}
parts := strings.Split(domain, ".")
if len(parts) < abs(part) {
return "", fmt.Errorf("not enough parts")
}
if part < 0 {
return parts[len(parts)+part], nil
}
return parts[part-1], nil
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
// UnqualifiedName strips the root from the domain and ensures the result is
// suitable as a name
func UnqualifiedName(domain string, root string) (string, error) {
suffix := fmt.Sprintf(".%s", root)
name := strings.TrimSuffix(domain, suffix)
if strings.Contains(name, ".") {
return "", fmt.Errorf("%s not a direct child of %s", domain, root)
}
return name, nil
}