-
Notifications
You must be signed in to change notification settings - Fork 2
/
Node.js
executable file
·93 lines (91 loc) · 2.02 KB
/
Node.js
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
import {ethers} from 'ethers';
function split(s) {
return s ? s.split('.') : [];
}
export class Node extends Map {
static create(name) {
return name instanceof this ? name : this.root().create(name);
}
static root(tag = 'root') {
return new this(null, ethers.ZeroHash, `[${tag}]`);
}
constructor(parent, namehash, label, labelhash) {
super();
this.parent = parent;
this.namehash = namehash;
this.label = label;
this.labelhash = labelhash;
}
get dns() {
return ethers.getBytes(ethers.dnsEncode(this.name, 255));
}
get name() {
if (!this.parent) return '';
let v = [];
for (let x = this; x.parent; x = x.parent) v.push(x.label);
return v.join('.');
}
get depth() {
let n = 0;
for (let x = this; x.parent; x = x.parent) ++n;
return n;
}
get nodeCount() {
let n = 0;
this.scan(() => ++n);
return n;
}
get root() {
let x = this;
while (x.parent) x = x.parent;
return x;
}
get isETH2LD() {
return this.parent?.name === 'eth';
}
path(inc_root) {
// raffy.eth => [raffy.eth, eth, <root>?]
let v = [];
for (let x = this; inc_root ? x : x.parent; x = x.parent) v.push(x);
return v;
}
find(name) {
return split(name).reduceRight((n, s) => n?.get(s), this);
}
create(name) {
return split(name).reduceRight((n, s) => n.child(s), this);
}
child(label) {
let node = this.get(label);
if (!node) {
let labelhash = ethers.id(label)
let namehash = ethers.solidityPackedKeccak256(['bytes32', 'bytes32'], [this.namehash, labelhash]);
node = new this.constructor(this, namehash, label, labelhash);
this.set(label, node);
}
return node;
}
unique(prefix = 'u') {
for (let i = 1; ; i++) {
let label = prefix + i;
if (!this.has(label)) return this.child(label);
}
}
scan(fn, level = 0) {
fn(this, level++);
for (let x of this.values()) {
x.scan(fn, level);
}
}
flat() {
let v = [];
this.scan(x => v.push(x));
return v;
}
toString() {
return this.name;
}
print(format = x => x.label) {
this.scan((x, n) => console.log(' '.repeat(n) + format(x)));
}
}