@parity/product-sdk 0.22.0 → 0.23.0
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/dist/chunk-BRZNHTLQ.js +89 -0
- package/dist/chunk-BRZNHTLQ.js.map +1 -0
- package/dist/{chunk-6BI66XUJ.js → chunk-DHRCWMY5.js} +9 -10
- package/dist/chunk-DHRCWMY5.js.map +1 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +2 -2
- package/dist/dotns-bswWAmR2.d.ts +136 -0
- package/dist/identity/index.d.ts +502 -45
- package/dist/identity/index.js +800 -32
- package/dist/identity/index.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +2 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/{types-DTgyMIi0.d.ts → types-B5Zx4RNq.d.ts} +1 -1
- package/package.json +10 -10
- package/src/core/createApp.ts +10 -8
- package/src/identity/dotns-abis.test.ts +43 -0
- package/src/identity/dotns-abis.ts +309 -0
- package/src/identity/dotns-addresses.test.ts +536 -0
- package/src/identity/dotns-addresses.ts +320 -0
- package/src/identity/dotns-errors.ts +36 -0
- package/src/identity/dotns-namehash.test.ts +155 -0
- package/src/identity/dotns-namehash.ts +149 -0
- package/src/identity/dotns-owner.test.ts +92 -0
- package/src/identity/dotns-registry.test.ts +1309 -0
- package/src/identity/dotns-registry.ts +868 -0
- package/src/identity/dotns.test.ts +128 -0
- package/src/identity/dotns.ts +91 -78
- package/src/identity/index.test.ts +43 -0
- package/src/identity/index.ts +40 -10
- package/src/identity/types.ts +29 -25
- package/src/individuality/contract.test.ts +272 -2
- package/dist/chunk-6BI66XUJ.js.map +0 -1
- package/dist/chunk-BIKT6X54.js +0 -70
- package/dist/chunk-BIKT6X54.js.map +0 -1
- package/dist/dotns-DIaptENj.d.ts +0 -167
- package/src/identity/product-account.test.ts +0 -129
- package/src/identity/product-account.ts +0 -115
package/dist/identity/index.js
CHANGED
|
@@ -1,45 +1,813 @@
|
|
|
1
|
-
|
|
1
|
+
import { normalizeDotNsName, isResolvableDotNsName, namehash, isValidDotNsName, stripSuffix, isConsistentDotNsTld, DOT_TLD, dotNsTld } from '../chunk-BRZNHTLQ.js';
|
|
2
|
+
export { DOT_NODE, DOT_TLD, accountIdHexToBytes, accountIdToHex, dotNsTld, isConsistentDotNsTld, isResolvableDotNsName, isValidDotNsName, namehash, normalizeDotNsName, resolvePeopleUsernameOwner, stripSuffix } from '../chunk-BRZNHTLQ.js';
|
|
3
|
+
import { ok, err } from '@parity/result';
|
|
4
|
+
import { bytesToHex, randomBytes } from '@parity/product-sdk-crypto';
|
|
5
|
+
import { ss58ToH160 } from '@parity/product-sdk-address';
|
|
2
6
|
import { createLogger } from '@parity/product-sdk-logger';
|
|
3
|
-
import {
|
|
4
|
-
import { ss58Decode, ss58Encode, deriveH160 } from '@parity/product-sdk-address';
|
|
7
|
+
import { QUERY_FALLBACK_ORIGIN, createContract } from '@parity/product-sdk-contracts';
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
address
|
|
9
|
+
// src/identity/dotns-abis.ts
|
|
10
|
+
var DOTNS_REGISTRY_ABI = [
|
|
11
|
+
{
|
|
12
|
+
type: "function",
|
|
13
|
+
name: "resolver",
|
|
14
|
+
inputs: [{ name: "node", type: "bytes32" }],
|
|
15
|
+
outputs: [{ name: "", type: "address" }],
|
|
16
|
+
stateMutability: "view"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
type: "function",
|
|
20
|
+
name: "owner",
|
|
21
|
+
inputs: [{ name: "node", type: "bytes32" }],
|
|
22
|
+
outputs: [{ name: "", type: "address" }],
|
|
23
|
+
stateMutability: "view"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: "function",
|
|
27
|
+
name: "setResolver",
|
|
28
|
+
inputs: [
|
|
29
|
+
{ name: "node", type: "bytes32" },
|
|
30
|
+
{ name: "resolverAddr", type: "address" }
|
|
31
|
+
],
|
|
32
|
+
outputs: [],
|
|
33
|
+
stateMutability: "nonpayable"
|
|
34
|
+
}
|
|
35
|
+
];
|
|
36
|
+
var DOTNS_RESOLVER_ABI = [
|
|
37
|
+
{
|
|
38
|
+
type: "function",
|
|
39
|
+
name: "addressOf",
|
|
40
|
+
inputs: [{ name: "node", type: "bytes32" }],
|
|
41
|
+
outputs: [{ name: "value", type: "address" }],
|
|
42
|
+
stateMutability: "view"
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
var DOTNS_REVERSE_RESOLVER_ABI = [
|
|
46
|
+
{
|
|
47
|
+
type: "function",
|
|
48
|
+
name: "nameOf",
|
|
49
|
+
inputs: [{ name: "addr", type: "address" }],
|
|
50
|
+
outputs: [{ name: "name", type: "string" }],
|
|
51
|
+
stateMutability: "view"
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
var DOTNS_RESOLVER_WRITE_ABI = [
|
|
55
|
+
{
|
|
56
|
+
type: "function",
|
|
57
|
+
name: "setAddress",
|
|
58
|
+
inputs: [
|
|
59
|
+
{ name: "node", type: "bytes32" },
|
|
60
|
+
{ name: "value", type: "address" }
|
|
61
|
+
],
|
|
62
|
+
outputs: [],
|
|
63
|
+
stateMutability: "nonpayable"
|
|
64
|
+
}
|
|
65
|
+
];
|
|
66
|
+
var DOTNS_REGISTRAR_CONTROLLER_ABI = [
|
|
67
|
+
{
|
|
68
|
+
type: "function",
|
|
69
|
+
name: "available",
|
|
70
|
+
inputs: [{ name: "label", type: "string" }],
|
|
71
|
+
outputs: [{ name: "isAvailable", type: "bool" }],
|
|
72
|
+
stateMutability: "view"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
type: "function",
|
|
76
|
+
name: "minCommitmentAge",
|
|
77
|
+
inputs: [],
|
|
78
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
79
|
+
stateMutability: "view"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: "function",
|
|
83
|
+
name: "maxCommitmentAge",
|
|
84
|
+
inputs: [],
|
|
85
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
86
|
+
stateMutability: "view"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
type: "function",
|
|
90
|
+
name: "makeCommitment",
|
|
91
|
+
inputs: [
|
|
92
|
+
{
|
|
93
|
+
name: "registration",
|
|
94
|
+
type: "tuple",
|
|
95
|
+
components: [
|
|
96
|
+
{ name: "label", type: "string" },
|
|
97
|
+
{ name: "owner", type: "address" },
|
|
98
|
+
{ name: "secret", type: "bytes32" },
|
|
99
|
+
{ name: "reserved", type: "bool" }
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
outputs: [{ name: "commitment", type: "bytes32" }],
|
|
104
|
+
stateMutability: "pure"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
type: "function",
|
|
108
|
+
name: "commit",
|
|
109
|
+
inputs: [{ name: "commitment", type: "bytes32" }],
|
|
110
|
+
outputs: [],
|
|
111
|
+
stateMutability: "nonpayable"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: "function",
|
|
115
|
+
name: "register",
|
|
116
|
+
inputs: [
|
|
117
|
+
{
|
|
118
|
+
name: "registration",
|
|
119
|
+
type: "tuple",
|
|
120
|
+
components: [
|
|
121
|
+
{ name: "label", type: "string" },
|
|
122
|
+
{ name: "owner", type: "address" },
|
|
123
|
+
{ name: "secret", type: "bytes32" },
|
|
124
|
+
{ name: "reserved", type: "bool" }
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
outputs: [],
|
|
129
|
+
stateMutability: "payable"
|
|
130
|
+
}
|
|
131
|
+
];
|
|
132
|
+
var DOTNS_POP_RULES_ABI = [
|
|
133
|
+
{
|
|
134
|
+
type: "function",
|
|
135
|
+
name: "price",
|
|
136
|
+
inputs: [{ name: "name", type: "string" }],
|
|
137
|
+
outputs: [{ name: "cost", type: "uint256" }],
|
|
138
|
+
stateMutability: "view"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: "function",
|
|
142
|
+
name: "priceWithoutCheck",
|
|
143
|
+
inputs: [
|
|
144
|
+
{ name: "name", type: "string" },
|
|
145
|
+
{ name: "userAddress", type: "address" }
|
|
146
|
+
],
|
|
147
|
+
outputs: [
|
|
148
|
+
{
|
|
149
|
+
name: "metadata",
|
|
150
|
+
type: "tuple",
|
|
151
|
+
components: [
|
|
152
|
+
{ name: "price", type: "uint256" },
|
|
153
|
+
{ name: "status", type: "uint8" },
|
|
154
|
+
{ name: "userStatus", type: "uint8" },
|
|
155
|
+
{ name: "message", type: "string" }
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
stateMutability: "view"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
type: "function",
|
|
163
|
+
name: "classifyName",
|
|
164
|
+
inputs: [{ name: "name", type: "string" }],
|
|
165
|
+
outputs: [
|
|
166
|
+
{ name: "requirement", type: "uint8" },
|
|
167
|
+
{ name: "message", type: "string" }
|
|
168
|
+
],
|
|
169
|
+
stateMutability: "pure"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
type: "function",
|
|
173
|
+
name: "transferFloor",
|
|
174
|
+
inputs: [
|
|
175
|
+
{ name: "name", type: "string" },
|
|
176
|
+
{ name: "from", type: "address" },
|
|
177
|
+
{ name: "to", type: "address" }
|
|
178
|
+
],
|
|
179
|
+
outputs: [{ name: "floor", type: "uint256" }],
|
|
180
|
+
stateMutability: "view"
|
|
181
|
+
}
|
|
182
|
+
];
|
|
183
|
+
var DOTNS_PROTOCOL_REGISTRY_ABI = [
|
|
184
|
+
{
|
|
185
|
+
type: "function",
|
|
186
|
+
name: "tld",
|
|
187
|
+
inputs: [],
|
|
188
|
+
outputs: [{ name: "suffix", type: "string" }],
|
|
189
|
+
stateMutability: "view"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
type: "function",
|
|
193
|
+
name: "tldNode",
|
|
194
|
+
inputs: [],
|
|
195
|
+
outputs: [{ name: "node", type: "bytes32" }],
|
|
196
|
+
stateMutability: "view"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
type: "function",
|
|
200
|
+
name: "get",
|
|
201
|
+
inputs: [{ name: "key", type: "bytes32" }],
|
|
202
|
+
outputs: [{ name: "addr", type: "address" }],
|
|
203
|
+
stateMutability: "view"
|
|
204
|
+
}
|
|
205
|
+
];
|
|
206
|
+
var DOTNS_ROOT_GATEWAY_DISPATCHER_ABI = [
|
|
207
|
+
{
|
|
208
|
+
type: "function",
|
|
209
|
+
name: "TARGET",
|
|
210
|
+
inputs: [],
|
|
211
|
+
outputs: [{ name: "", type: "address" }],
|
|
212
|
+
stateMutability: "view"
|
|
213
|
+
}
|
|
214
|
+
];
|
|
215
|
+
var DOTNS_POP_CONTROLLER_ABI = [
|
|
216
|
+
{
|
|
217
|
+
type: "function",
|
|
218
|
+
name: "protocolRegistry",
|
|
219
|
+
inputs: [],
|
|
220
|
+
outputs: [{ name: "", type: "address" }],
|
|
221
|
+
stateMutability: "view"
|
|
222
|
+
}
|
|
223
|
+
];
|
|
224
|
+
var POP_STATUS = { NoStatus: 0, PopLite: 1, PopFull: 2, Reserved: 3 };
|
|
225
|
+
var DOTNS_ADDRESSES = {
|
|
226
|
+
registry: "0xf34054fd76BbF85f216cf9908226D5f0A72E50CA",
|
|
227
|
+
reverseResolver: "0xee3883d7eB60Ee9BCD7F3bcD8f2f05302A9Cc035",
|
|
228
|
+
resolver: "0xbd1165E549DF96F083c0A16f61590927bC187009",
|
|
229
|
+
registrarController: "0xBdaA01bD1bA67d709F2b1fF286Da0d854977EA30",
|
|
230
|
+
popRules: "0x747B456bE03aec0b42bd85C51513730FBD45DA31",
|
|
231
|
+
protocolRegistry: "0xD19e3D0C97CF501125a04A97405e3e6592fa846E"
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// src/identity/dotns-errors.ts
|
|
235
|
+
var DotNsError = class extends Error {
|
|
236
|
+
isSdkError = true;
|
|
237
|
+
source = "dotns";
|
|
238
|
+
reason;
|
|
239
|
+
constructor(reason, message, options) {
|
|
240
|
+
super(message, options);
|
|
241
|
+
this.name = "DotNsError";
|
|
242
|
+
this.reason = reason;
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
var DOTNS_REGISTRY_KEYS = {
|
|
246
|
+
registry: "0x7265676973747279000000000000000000000000000000000000000000000000",
|
|
247
|
+
registrarController: "0x636f6e74726f6c6c657200000000000000000000000000000000000000000000",
|
|
248
|
+
reverseResolver: "0x726576657273655265736f6c7665720000000000000000000000000000000000",
|
|
249
|
+
resolver: "0x7265736f6c766572000000000000000000000000000000000000000000000000",
|
|
250
|
+
popRules: "0x706f7052756c6573000000000000000000000000000000000000000000000000"
|
|
251
|
+
};
|
|
252
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
253
|
+
function isZero(addr) {
|
|
254
|
+
return typeof addr === "string" && addr.toLowerCase() === ZERO_ADDRESS;
|
|
255
|
+
}
|
|
256
|
+
function sameAddress(a, b) {
|
|
257
|
+
return typeof a === "string" && typeof b === "string" && a.toLowerCase() === b.toLowerCase();
|
|
258
|
+
}
|
|
259
|
+
function cachedPerRuntime(cache, runtime, key, load) {
|
|
260
|
+
let byKey = cache.get(runtime);
|
|
261
|
+
if (!byKey) {
|
|
262
|
+
byKey = /* @__PURE__ */ new Map();
|
|
263
|
+
cache.set(runtime, byKey);
|
|
264
|
+
}
|
|
265
|
+
const cached = byKey.get(key);
|
|
266
|
+
if (cached) return cached;
|
|
267
|
+
const pending = load();
|
|
268
|
+
byKey.set(key, pending);
|
|
269
|
+
pending.then((result) => {
|
|
270
|
+
if (!result.ok) byKey?.delete(key);
|
|
20
271
|
});
|
|
272
|
+
return pending;
|
|
273
|
+
}
|
|
274
|
+
function withOverrides(base, opts) {
|
|
21
275
|
return {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
276
|
+
registry: opts.registryAddress ?? base.registry,
|
|
277
|
+
reverseResolver: opts.reverseResolverAddress ?? base.reverseResolver,
|
|
278
|
+
resolver: opts.resolverAddress ?? base.resolver,
|
|
279
|
+
registrarController: opts.registrarControllerAddress ?? base.registrarController,
|
|
280
|
+
popRules: opts.popRulesAddress ?? base.popRules,
|
|
281
|
+
protocolRegistry: opts.protocolRegistryAddress ?? base.protocolRegistry
|
|
26
282
|
};
|
|
27
283
|
}
|
|
28
|
-
|
|
284
|
+
var walkCache = /* @__PURE__ */ new WeakMap();
|
|
285
|
+
var WALK_KEY = "discovered";
|
|
286
|
+
async function resolveDotNsAddresses(opts) {
|
|
287
|
+
if (opts.addressSource !== "discovered") return ok(withOverrides(DOTNS_ADDRESSES, opts));
|
|
288
|
+
const walked = await cachedPerRuntime(
|
|
289
|
+
walkCache,
|
|
290
|
+
opts.runtime,
|
|
291
|
+
WALK_KEY,
|
|
292
|
+
() => discoverDotNsAddresses(opts)
|
|
293
|
+
);
|
|
294
|
+
return walked.ok ? ok(withOverrides(walked.value, opts)) : walked;
|
|
295
|
+
}
|
|
296
|
+
var discoveryFailed = (step, cause) => err(new DotNsError("AddressDiscovery", `DotNS address discovery failed: ${step}`, { cause }));
|
|
297
|
+
function contractOf(runtime, address, abi) {
|
|
298
|
+
return createContract(runtime, address, abi);
|
|
299
|
+
}
|
|
300
|
+
function readOrigin(opts) {
|
|
301
|
+
return opts.origin ?? QUERY_FALLBACK_ORIGIN;
|
|
302
|
+
}
|
|
303
|
+
async function readAddress(contract, method, origin) {
|
|
304
|
+
const res = await contract[method].query({ origin });
|
|
305
|
+
if (!res.success) return discoveryFailed(`${method}() failed`, res.value);
|
|
306
|
+
const value = res.value;
|
|
307
|
+
if (typeof value !== "string" || isZero(value)) {
|
|
308
|
+
return discoveryFailed(`${method}() returned no address`);
|
|
309
|
+
}
|
|
310
|
+
return ok(value);
|
|
311
|
+
}
|
|
312
|
+
function asH160(value) {
|
|
313
|
+
if (typeof value === "string") return value;
|
|
314
|
+
if (value && typeof value.asHex === "function") {
|
|
315
|
+
return value.asHex();
|
|
316
|
+
}
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
function gatewayOf(opts) {
|
|
320
|
+
if (opts.gatewayApi) return opts.gatewayApi;
|
|
321
|
+
const api = opts.runtime?.api;
|
|
322
|
+
const getValue = api?.query?.DotnsGateway?.DispatcherAddress?.getValue;
|
|
323
|
+
return typeof getValue === "function" ? api : null;
|
|
324
|
+
}
|
|
325
|
+
async function discoverDotNsAddresses(opts) {
|
|
326
|
+
try {
|
|
327
|
+
const gateway = gatewayOf(opts);
|
|
328
|
+
if (!gateway) {
|
|
329
|
+
return discoveryFailed(
|
|
330
|
+
"no DotnsGateway.DispatcherAddress storage on this runtime; pass opts.gatewayApi"
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
const dispatcher = asH160(await gateway.query.DotnsGateway.DispatcherAddress.getValue());
|
|
334
|
+
if (!dispatcher || isZero(dispatcher)) {
|
|
335
|
+
return discoveryFailed("DotnsGateway.DispatcherAddress is unset");
|
|
336
|
+
}
|
|
337
|
+
const origin = readOrigin(opts);
|
|
338
|
+
const target = await readAddress(
|
|
339
|
+
contractOf(opts.runtime, dispatcher, DOTNS_ROOT_GATEWAY_DISPATCHER_ABI),
|
|
340
|
+
"TARGET",
|
|
341
|
+
origin
|
|
342
|
+
);
|
|
343
|
+
if (!target.ok) return target;
|
|
344
|
+
const protocolRegistry = await readAddress(
|
|
345
|
+
contractOf(opts.runtime, target.value, DOTNS_POP_CONTROLLER_ABI),
|
|
346
|
+
"protocolRegistry",
|
|
347
|
+
origin
|
|
348
|
+
);
|
|
349
|
+
if (!protocolRegistry.ok) return protocolRegistry;
|
|
350
|
+
const registry = contractOf(
|
|
351
|
+
opts.runtime,
|
|
352
|
+
protocolRegistry.value,
|
|
353
|
+
DOTNS_PROTOCOL_REGISTRY_ABI
|
|
354
|
+
);
|
|
355
|
+
const roles = Object.entries(DOTNS_REGISTRY_KEYS);
|
|
356
|
+
const found = await Promise.all(
|
|
357
|
+
roles.map(async ([role, key]) => {
|
|
358
|
+
const res = await registry.get.query(key, { origin });
|
|
359
|
+
if (!res.success) return discoveryFailed(`get(${role}) failed`, res.value);
|
|
360
|
+
const value = res.value;
|
|
361
|
+
if (typeof value !== "string" || isZero(value)) {
|
|
362
|
+
return discoveryFailed(`${role} is unset on the protocol registry`);
|
|
363
|
+
}
|
|
364
|
+
return ok([role, value]);
|
|
365
|
+
})
|
|
366
|
+
);
|
|
367
|
+
const failed = found.find((r) => !r.ok);
|
|
368
|
+
if (failed && !failed.ok) return failed;
|
|
369
|
+
const byRole = Object.fromEntries(found.flatMap((r) => r.ok ? [r.value] : []));
|
|
370
|
+
return ok({ ...byRole, protocolRegistry: protocolRegistry.value });
|
|
371
|
+
} catch (cause) {
|
|
372
|
+
return discoveryFailed("unexpected error", cause);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
async function verifyDotNsAddresses(opts) {
|
|
376
|
+
const discovered = await cachedPerRuntime(
|
|
377
|
+
walkCache,
|
|
378
|
+
opts.runtime,
|
|
379
|
+
WALK_KEY,
|
|
380
|
+
() => discoverDotNsAddresses(opts)
|
|
381
|
+
);
|
|
382
|
+
if (!discovered.ok) return discovered;
|
|
383
|
+
const inUse = withOverrides(
|
|
384
|
+
opts.addressSource === "discovered" ? discovered.value : DOTNS_ADDRESSES,
|
|
385
|
+
opts
|
|
386
|
+
);
|
|
387
|
+
const drift = Object.keys(inUse).filter((role) => !sameAddress(inUse[role], discovered.value[role])).map((role) => `${role}: using ${inUse[role]}, chain says ${discovered.value[role]}`);
|
|
388
|
+
return drift.length ? err(
|
|
389
|
+
new DotNsError(
|
|
390
|
+
"AddressMismatch",
|
|
391
|
+
`DotNS addresses disagree with the deployment \u2014 ${drift.join("; ")}`
|
|
392
|
+
)
|
|
393
|
+
) : ok(inUse);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// src/identity/dotns-registry.ts
|
|
397
|
+
var log = createLogger("identity:dotns");
|
|
398
|
+
var tldCache = /* @__PURE__ */ new WeakMap();
|
|
399
|
+
function isEmptyRevert(value) {
|
|
400
|
+
return typeof value === "object" && value !== null && value.type === "ContractRevertedWithPayload" && value.data === "0x";
|
|
401
|
+
}
|
|
402
|
+
async function resolveTld(opts) {
|
|
403
|
+
if (opts.tld) {
|
|
404
|
+
return isConsistentDotNsTld(opts.tld) ? ok(opts.tld) : err(
|
|
405
|
+
new DotNsError(
|
|
406
|
+
"InvalidTld",
|
|
407
|
+
`opts.tld is inconsistent: "${opts.tld.suffix}" does not hash to ${opts.tld.node}`
|
|
408
|
+
)
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
const addresses = await resolveDotNsAddresses(opts);
|
|
412
|
+
if (!addresses.ok) return addresses;
|
|
413
|
+
const address = addresses.value.protocolRegistry;
|
|
414
|
+
return cachedPerRuntime(tldCache, opts.runtime, address, () => readTld(opts, address));
|
|
415
|
+
}
|
|
416
|
+
async function readTld(opts, address) {
|
|
417
|
+
try {
|
|
418
|
+
const registry = contractOf(opts.runtime, address, DOTNS_PROTOCOL_REGISTRY_ABI);
|
|
419
|
+
const origin = readOrigin(opts);
|
|
420
|
+
const suffixRes = await registry.tld.query({ origin });
|
|
421
|
+
if (!suffixRes.success) {
|
|
422
|
+
if (isEmptyRevert(suffixRes.value)) {
|
|
423
|
+
log.warn(
|
|
424
|
+
"DotNS protocol registry has no tld() getter; treating this as a pre-b4096968 deployment, whose TLD was the compile-time .dot",
|
|
425
|
+
{ protocolRegistry: address }
|
|
426
|
+
);
|
|
427
|
+
return ok(DOT_TLD);
|
|
428
|
+
}
|
|
429
|
+
return err(
|
|
430
|
+
new DotNsError("RegistryCall", "protocolRegistry.tld call failed", {
|
|
431
|
+
cause: suffixRes.value
|
|
432
|
+
})
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
const suffix = suffixRes.value;
|
|
436
|
+
const tld = dotNsTld(suffix);
|
|
437
|
+
if (!isConsistentDotNsTld(tld)) {
|
|
438
|
+
return err(
|
|
439
|
+
new DotNsError(
|
|
440
|
+
"InvalidTld",
|
|
441
|
+
`protocolRegistry.tld returned an unusable TLD: ${JSON.stringify(suffix)}`
|
|
442
|
+
)
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
const nodeRes = await registry.tldNode.query({ origin });
|
|
446
|
+
if (nodeRes.success && isNode(nodeRes.value) && !sameNode(nodeRes.value, tld.node)) {
|
|
447
|
+
return err(
|
|
448
|
+
new DotNsError(
|
|
449
|
+
"InvalidTld",
|
|
450
|
+
`protocolRegistry disagrees with itself: tld() ${suffix} derives ${tld.node} but tldNode() reports ${String(nodeRes.value)}`
|
|
451
|
+
)
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
log.debug("resolveTld", { protocolRegistry: address, suffix: tld.suffix, node: tld.node });
|
|
455
|
+
return ok(tld);
|
|
456
|
+
} catch (cause) {
|
|
457
|
+
return err(new DotNsError("RegistryCall", "DotNS TLD read failed", { cause }));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function nameError(input, normalized, tld) {
|
|
461
|
+
if (!normalized.endsWith(tld.suffix)) {
|
|
462
|
+
return new DotNsError(
|
|
463
|
+
"TldMismatch",
|
|
464
|
+
`DotNS name "${input}" is not on this deployment, which uses "${tld.suffix}"`
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
return new DotNsError("InvalidName", `Invalid DotNS name: "${input}"`);
|
|
468
|
+
}
|
|
469
|
+
function isNode(value) {
|
|
470
|
+
return typeof value === "string" && /^0x[0-9a-fA-F]{64}$/.test(value);
|
|
471
|
+
}
|
|
472
|
+
function sameNode(a, b) {
|
|
473
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
474
|
+
}
|
|
475
|
+
async function resolveDotNs(name, opts) {
|
|
476
|
+
const tldRes = await resolveTld(opts);
|
|
477
|
+
if (!tldRes.ok) return tldRes;
|
|
478
|
+
const tld = tldRes.value;
|
|
479
|
+
const normalized = normalizeDotNsName(name, tld.suffix);
|
|
480
|
+
if (!isResolvableDotNsName(normalized, tld.suffix)) {
|
|
481
|
+
return err(nameError(name, normalized, tld));
|
|
482
|
+
}
|
|
483
|
+
const node = namehash(normalized, tld);
|
|
484
|
+
const addrs = await resolveDotNsAddresses(opts);
|
|
485
|
+
if (!addrs.ok) return addrs;
|
|
486
|
+
const registryAddr = addrs.value.registry;
|
|
487
|
+
const origin = readOrigin(opts);
|
|
488
|
+
log.debug("resolveDotNs", { name: normalized, node, registry: registryAddr });
|
|
29
489
|
try {
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
490
|
+
const registry = contractOf(opts.runtime, registryAddr, DOTNS_REGISTRY_ABI);
|
|
491
|
+
const [ownerRes, resolverRes] = await Promise.all([
|
|
492
|
+
registry.owner.query(node, { origin }),
|
|
493
|
+
registry.resolver.query(node, { origin })
|
|
494
|
+
]);
|
|
495
|
+
if (!ownerRes.success) {
|
|
496
|
+
return err(
|
|
497
|
+
new DotNsError("RegistryCall", "registry.owner call failed", {
|
|
498
|
+
cause: ownerRes.value
|
|
499
|
+
})
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
if (!resolverRes.success) {
|
|
503
|
+
return err(
|
|
504
|
+
new DotNsError("RegistryCall", "registry.resolver call failed", {
|
|
505
|
+
cause: resolverRes.value
|
|
506
|
+
})
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
const owner = ownerRes.value;
|
|
510
|
+
if (isZero(owner)) return ok(null);
|
|
511
|
+
const resolverAddr = resolverRes.value;
|
|
512
|
+
const forwardAddr = addrs.value.resolver;
|
|
513
|
+
if (!sameAddress(resolverAddr, forwardAddr)) {
|
|
514
|
+
return ok({ name: normalized, owner });
|
|
515
|
+
}
|
|
516
|
+
const resolver = contractOf(opts.runtime, resolverAddr, DOTNS_RESOLVER_ABI);
|
|
517
|
+
const addrRes = await resolver.addressOf.query(node, { origin });
|
|
518
|
+
if (!addrRes.success) {
|
|
519
|
+
return err(
|
|
520
|
+
new DotNsError("RegistryCall", "resolver.addressOf call failed", {
|
|
521
|
+
cause: addrRes.value
|
|
522
|
+
})
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
const address = addrRes.value;
|
|
526
|
+
if (isZero(address)) return ok({ name: normalized, owner });
|
|
527
|
+
return ok({ address, name: normalized, owner });
|
|
528
|
+
} catch (cause) {
|
|
529
|
+
return err(
|
|
530
|
+
new DotNsError("RegistryCall", `DotNS resolve failed for "${normalized}"`, { cause })
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
async function reverseDotNs(address, opts) {
|
|
535
|
+
const addrs = await resolveDotNsAddresses(opts);
|
|
536
|
+
if (!addrs.ok) return addrs;
|
|
537
|
+
const reverseAddr = addrs.value.reverseResolver;
|
|
538
|
+
log.debug("reverseDotNs", { address, reverseResolver: reverseAddr });
|
|
539
|
+
try {
|
|
540
|
+
const reverse = contractOf(
|
|
541
|
+
opts.runtime,
|
|
542
|
+
reverseAddr,
|
|
543
|
+
DOTNS_REVERSE_RESOLVER_ABI
|
|
544
|
+
);
|
|
545
|
+
const res = await reverse.nameOf.query(address, { origin: readOrigin(opts) });
|
|
546
|
+
if (!res.success) {
|
|
547
|
+
return err(
|
|
548
|
+
new DotNsError("RegistryCall", "reverseResolver.nameOf call failed", {
|
|
549
|
+
cause: res.value
|
|
550
|
+
})
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
const name = res.value;
|
|
554
|
+
return ok(name && name.length > 0 ? name : null);
|
|
555
|
+
} catch (cause) {
|
|
556
|
+
return err(
|
|
557
|
+
new DotNsError("RegistryCall", `DotNS reverse failed for "${address}"`, { cause })
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
async function isDotNsAvailable(name, opts) {
|
|
562
|
+
const tldRes = await resolveTld(opts);
|
|
563
|
+
if (!tldRes.ok) return tldRes;
|
|
564
|
+
const tld = tldRes.value;
|
|
565
|
+
const normalized = normalizeDotNsName(name, tld.suffix);
|
|
566
|
+
if (!isValidDotNsName(normalized, tld.suffix)) {
|
|
567
|
+
return err(nameError(name, normalized, tld));
|
|
568
|
+
}
|
|
569
|
+
const label = stripSuffix(normalized, tld.suffix);
|
|
570
|
+
const addrs = await resolveDotNsAddresses(opts);
|
|
571
|
+
if (!addrs.ok) return addrs;
|
|
572
|
+
const controllerAddr = addrs.value.registrarController;
|
|
573
|
+
log.debug("isDotNsAvailable", { name: normalized, label, controller: controllerAddr });
|
|
574
|
+
try {
|
|
575
|
+
const controller = contractOf(
|
|
576
|
+
opts.runtime,
|
|
577
|
+
controllerAddr,
|
|
578
|
+
DOTNS_REGISTRAR_CONTROLLER_ABI
|
|
579
|
+
);
|
|
580
|
+
const popRules = contractOf(opts.runtime, addrs.value.popRules, DOTNS_POP_RULES_ABI);
|
|
581
|
+
const origin = readOrigin(opts);
|
|
582
|
+
const [res, classified] = await Promise.all([
|
|
583
|
+
controller.available.query(label, { origin }),
|
|
584
|
+
popRules.classifyName.query(label, { origin })
|
|
585
|
+
]);
|
|
586
|
+
if (!res.success) {
|
|
587
|
+
return err(
|
|
588
|
+
new DotNsError("RegistryCall", "registrarController.available call failed", {
|
|
589
|
+
cause: res.value
|
|
590
|
+
})
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
if (res.value !== true) return ok(false);
|
|
594
|
+
if (!classified.success) {
|
|
595
|
+
return err(
|
|
596
|
+
new DotNsError("RegistryCall", "PopRules.classifyName call failed", {
|
|
597
|
+
cause: classified.value
|
|
598
|
+
})
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
const { requirement } = classified.value;
|
|
602
|
+
return ok(requirement !== POP_STATUS.Reserved);
|
|
603
|
+
} catch (cause) {
|
|
604
|
+
return err(
|
|
605
|
+
new DotNsError("RegistryCall", `DotNS availability check failed for "${normalized}"`, {
|
|
606
|
+
cause
|
|
607
|
+
})
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
async function setDotNsRecord(args, opts) {
|
|
612
|
+
const tldRes = await resolveTld(opts);
|
|
613
|
+
if (!tldRes.ok) return tldRes;
|
|
614
|
+
const tld = tldRes.value;
|
|
615
|
+
const normalized = normalizeDotNsName(args.name, tld.suffix);
|
|
616
|
+
if (!isResolvableDotNsName(normalized, tld.suffix)) {
|
|
617
|
+
return err(nameError(args.name, normalized, tld));
|
|
618
|
+
}
|
|
619
|
+
const origin = opts.origin;
|
|
620
|
+
if (!origin) {
|
|
621
|
+
return err(new DotNsError("MissingOrigin", "setDotNsRecord needs opts.origin (SS58)"));
|
|
622
|
+
}
|
|
623
|
+
const node = namehash(normalized, tld);
|
|
624
|
+
const addrs = await resolveDotNsAddresses(opts);
|
|
625
|
+
if (!addrs.ok) return addrs;
|
|
626
|
+
const registryAddr = addrs.value.registry;
|
|
627
|
+
const resolverAddr = addrs.value.resolver;
|
|
628
|
+
try {
|
|
629
|
+
const registry = contractOf(opts.runtime, registryAddr, DOTNS_REGISTRY_ABI);
|
|
630
|
+
const currentRes = await registry.resolver.query(node, { origin });
|
|
631
|
+
if (!currentRes.success) {
|
|
632
|
+
return err(
|
|
633
|
+
new DotNsError("RegistryCall", "registry.resolver call failed", {
|
|
634
|
+
cause: currentRes.value
|
|
635
|
+
})
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
const calls = [];
|
|
639
|
+
if (!sameAddress(currentRes.value, resolverAddr)) {
|
|
640
|
+
const pointer = await registry.setResolver.prepare(node, resolverAddr, { origin });
|
|
641
|
+
if (!pointer.ok) {
|
|
642
|
+
return err(
|
|
643
|
+
new DotNsError("RegistryCall", "registry.setResolver prepare failed", {
|
|
644
|
+
cause: pointer.error
|
|
645
|
+
})
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
calls.push(pointer.value);
|
|
649
|
+
}
|
|
650
|
+
const resolver = contractOf(
|
|
651
|
+
opts.runtime,
|
|
652
|
+
resolverAddr,
|
|
653
|
+
DOTNS_RESOLVER_WRITE_ABI
|
|
654
|
+
);
|
|
655
|
+
const prepared = await resolver.setAddress.prepare(node, args.address, { origin });
|
|
656
|
+
if (!prepared.ok) {
|
|
657
|
+
return err(
|
|
658
|
+
new DotNsError("RegistryCall", "resolver.setAddress prepare failed", {
|
|
659
|
+
cause: prepared.error
|
|
660
|
+
})
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
calls.push(prepared.value);
|
|
664
|
+
return ok(calls);
|
|
665
|
+
} catch (cause) {
|
|
666
|
+
return err(new DotNsError("RegistryCall", "DotNS setRecord failed", { cause }));
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
async function quoteRegistration(popRules, label, owner, payer, origin) {
|
|
670
|
+
const quote = await popRules.priceWithoutCheck.query(label, owner, { origin });
|
|
671
|
+
if (!quote.success) {
|
|
672
|
+
return err(
|
|
673
|
+
new DotNsError("RegistryCall", "PopRules.priceWithoutCheck failed", {
|
|
674
|
+
cause: quote.value
|
|
675
|
+
})
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
const { price, status, userStatus, message } = quote.value;
|
|
679
|
+
if (status === POP_STATUS.Reserved) {
|
|
680
|
+
return err(new DotNsError("NameReserved", `"${label}" is reserved: ${message}`));
|
|
681
|
+
}
|
|
682
|
+
if (userStatus < status) {
|
|
683
|
+
return err(
|
|
684
|
+
new DotNsError(
|
|
685
|
+
"OwnerStatusInsufficient",
|
|
686
|
+
`"${label}" requires personhood tier ${status}, owner has ${userStatus}: ${message}`
|
|
687
|
+
)
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
if (sameAddress(payer, owner)) return ok(BigInt(price));
|
|
691
|
+
const floor = await popRules.transferFloor.query(label, payer, owner, { origin });
|
|
692
|
+
if (!floor.success) {
|
|
693
|
+
return err(
|
|
694
|
+
new DotNsError("RegistryCall", "PopRules.transferFloor failed", {
|
|
695
|
+
cause: floor.value
|
|
696
|
+
})
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
const friction = BigInt(floor.value);
|
|
700
|
+
const base = BigInt(price);
|
|
701
|
+
return ok(base > friction ? base : friction);
|
|
702
|
+
}
|
|
703
|
+
async function prepareDotNsRegistration(args, opts) {
|
|
704
|
+
const tldRes = await resolveTld(opts);
|
|
705
|
+
if (!tldRes.ok) return tldRes;
|
|
706
|
+
const tld = tldRes.value;
|
|
707
|
+
const normalized = normalizeDotNsName(args.name, tld.suffix);
|
|
708
|
+
if (!isValidDotNsName(normalized, tld.suffix)) {
|
|
709
|
+
return err(nameError(args.name, normalized, tld));
|
|
710
|
+
}
|
|
711
|
+
const origin = opts.origin;
|
|
712
|
+
if (!origin) {
|
|
713
|
+
return err(
|
|
714
|
+
new DotNsError("MissingOrigin", "prepareDotNsRegistration needs opts.origin (SS58)")
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
const label = stripSuffix(normalized, tld.suffix);
|
|
718
|
+
const addrs = await resolveDotNsAddresses(opts);
|
|
719
|
+
if (!addrs.ok) return addrs;
|
|
720
|
+
const controllerAddr = addrs.value.registrarController;
|
|
721
|
+
const popRulesAddr = addrs.value.popRules;
|
|
722
|
+
const secret = `0x${bytesToHex(randomBytes(32))}`;
|
|
723
|
+
const registration = { label, owner: args.owner, secret, reserved: args.reserved ?? false };
|
|
724
|
+
let payer;
|
|
725
|
+
try {
|
|
726
|
+
payer = ss58ToH160(origin);
|
|
727
|
+
} catch (cause) {
|
|
728
|
+
return err(
|
|
729
|
+
new DotNsError("InvalidOrigin", `opts.origin is not a valid SS58 address: ${origin}`, {
|
|
730
|
+
cause
|
|
731
|
+
})
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
try {
|
|
735
|
+
const controller = contractOf(
|
|
736
|
+
opts.runtime,
|
|
737
|
+
controllerAddr,
|
|
738
|
+
DOTNS_REGISTRAR_CONTROLLER_ABI
|
|
739
|
+
);
|
|
740
|
+
const popRules = contractOf(opts.runtime, popRulesAddr, DOTNS_POP_RULES_ABI);
|
|
741
|
+
const [commitmentRes, availableRes, quote, minRes, maxRes] = await Promise.all([
|
|
742
|
+
controller.makeCommitment.query(registration, { origin }),
|
|
743
|
+
controller.available.query(label, { origin }),
|
|
744
|
+
quoteRegistration(popRules, label, args.owner, payer, origin),
|
|
745
|
+
controller.minCommitmentAge.query({ origin }),
|
|
746
|
+
controller.maxCommitmentAge.query({ origin })
|
|
747
|
+
]);
|
|
748
|
+
if (!availableRes.success) {
|
|
749
|
+
return err(
|
|
750
|
+
new DotNsError("RegistryCall", "registrarController.available call failed", {
|
|
751
|
+
cause: availableRes.value
|
|
752
|
+
})
|
|
753
|
+
);
|
|
754
|
+
}
|
|
755
|
+
if (availableRes.value !== true) {
|
|
756
|
+
return err(new DotNsError("NameUnavailable", `"${label}" is already registered`));
|
|
757
|
+
}
|
|
758
|
+
if (!commitmentRes.success) {
|
|
759
|
+
return err(
|
|
760
|
+
new DotNsError("RegistryCall", "makeCommitment failed", {
|
|
761
|
+
cause: commitmentRes.value
|
|
762
|
+
})
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
if (!quote.ok) return quote;
|
|
766
|
+
if (!minRes.success || !maxRes.success) {
|
|
767
|
+
return err(
|
|
768
|
+
new DotNsError("RegistryCall", "commitment window read failed", {
|
|
769
|
+
cause: minRes.success ? maxRes.value : minRes.value
|
|
770
|
+
})
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
const commitment = commitmentRes.value;
|
|
774
|
+
const commitPrep = await controller.commit.prepare(commitment, { origin });
|
|
775
|
+
if (!commitPrep.ok) {
|
|
776
|
+
return err(
|
|
777
|
+
new DotNsError("RegistryCall", "controller.commit prepare failed", {
|
|
778
|
+
cause: commitPrep.error
|
|
779
|
+
})
|
|
780
|
+
);
|
|
36
781
|
}
|
|
37
|
-
return
|
|
38
|
-
|
|
39
|
-
|
|
782
|
+
return ok({
|
|
783
|
+
secret,
|
|
784
|
+
commitment,
|
|
785
|
+
commitCall: commitPrep.value,
|
|
786
|
+
minCommitmentAge: BigInt(minRes.value),
|
|
787
|
+
maxCommitmentAge: BigInt(maxRes.value),
|
|
788
|
+
price: quote.value,
|
|
789
|
+
prepareRegisterCall: async () => {
|
|
790
|
+
const current = await quoteRegistration(popRules, label, args.owner, payer, origin);
|
|
791
|
+
if (!current.ok) return current;
|
|
792
|
+
const prep = await controller.register.prepare(registration, {
|
|
793
|
+
value: current.value,
|
|
794
|
+
origin
|
|
795
|
+
});
|
|
796
|
+
if (!prep.ok) {
|
|
797
|
+
return err(
|
|
798
|
+
new DotNsError("RegistryCall", "controller.register prepare failed", {
|
|
799
|
+
cause: prep.error
|
|
800
|
+
})
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
return ok(prep.value);
|
|
804
|
+
}
|
|
805
|
+
});
|
|
806
|
+
} catch (cause) {
|
|
807
|
+
return err(new DotNsError("RegistryCall", "DotNS registration prepare failed", { cause }));
|
|
40
808
|
}
|
|
41
809
|
}
|
|
42
810
|
|
|
43
|
-
export {
|
|
811
|
+
export { DOTNS_ADDRESSES, DOTNS_REGISTRY_KEYS, DotNsError, POP_STATUS, discoverDotNsAddresses, isDotNsAvailable, prepareDotNsRegistration, resolveDotNs, resolveDotNsAddresses, reverseDotNs, setDotNsRecord, verifyDotNsAddresses };
|
|
44
812
|
//# sourceMappingURL=index.js.map
|
|
45
813
|
//# sourceMappingURL=index.js.map
|