zcashname-sdk 0.8.4 → 0.8.6
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/zns.cjs +176 -234
- package/dist/zns.d.cts +68 -26
- package/dist/zns.d.ts +68 -26
- package/dist/zns.js +174 -229
- package/package.json +2 -1
package/dist/zns.cjs
CHANGED
|
@@ -31,119 +31,101 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var zns_exports = {};
|
|
32
32
|
__export(zns_exports, {
|
|
33
33
|
BUY_COMMISSION: () => BUY_COMMISSION,
|
|
34
|
-
DEFAULT_URL: () => DEFAULT_URL,
|
|
35
34
|
LIST_COMMISSION: () => LIST_COMMISSION,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
ZNS: () => ZNS,
|
|
39
|
-
ZNS_ACTIONS: () => ZNS_ACTIONS
|
|
35
|
+
NETWORKS: () => NETWORKS,
|
|
36
|
+
ZNS: () => ZNS
|
|
40
37
|
});
|
|
41
38
|
module.exports = __toCommonJS(zns_exports);
|
|
42
39
|
var ed25519 = __toESM(require("@noble/ed25519"), 1);
|
|
43
40
|
var import_bech32 = require("bech32");
|
|
44
41
|
|
|
45
42
|
// src/types.ts
|
|
43
|
+
var ZNS_ACTIONS = ["CLAIM", "BUY", "UPDATE", "LIST", "DELIST", "RELEASE"];
|
|
44
|
+
|
|
45
|
+
// src/zns.ts
|
|
46
46
|
var BUY_COMMISSION = 1e4;
|
|
47
47
|
var LIST_COMMISSION = 1e6;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
txid: raw.txid,
|
|
64
|
-
height: raw.height,
|
|
65
|
-
signature: raw.signature,
|
|
66
|
-
pubkey: raw.pubkey,
|
|
67
|
-
pendingBuy: raw.pending_buy ? toPendingBuy(raw.pending_buy) : void 0
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
function toRegistration(raw) {
|
|
71
|
-
return {
|
|
72
|
-
name: raw.name,
|
|
73
|
-
address: raw.address,
|
|
74
|
-
txid: raw.txid,
|
|
75
|
-
height: raw.height,
|
|
76
|
-
nonce: raw.nonce,
|
|
77
|
-
signature: raw.signature,
|
|
78
|
-
lastAction: raw.last_action,
|
|
79
|
-
pubkey: raw.pubkey,
|
|
80
|
-
listing: raw.listing ? toListing(raw.listing) : null
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function toPricing(raw) {
|
|
84
|
-
return {
|
|
85
|
-
nonce: raw.nonce,
|
|
86
|
-
height: raw.height,
|
|
87
|
-
tiers: raw.tiers
|
|
88
|
-
};
|
|
48
|
+
var NETWORKS = {
|
|
49
|
+
testnet: {
|
|
50
|
+
url: "https://light.zcash.me/zns-testnet",
|
|
51
|
+
registryAddress: "utest1f32kn6c4zvn54xr8wfsnxmj9hzpu2mwgtxzpzwcw34906tdccdvzs0z2dx38lly7tpan77x6udt8pjczqm22ymsdhlz9j0tk5yq664nl",
|
|
52
|
+
uivk: "utest1hzw7wyadutvzfgpna80yftsk5l7jeyu2p5me5quvp28tytxueta00cx4068wnlzcv7tx9n3t3gfhsy83pe4y6jrhxtzaq0hj6xtg5zrk2dn7zen3vns2a5pgs4fxdjlletmqrhfa42"
|
|
53
|
+
},
|
|
54
|
+
mainnet: {
|
|
55
|
+
url: "https://light.zcash.me/zns-mainnet",
|
|
56
|
+
registryAddress: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9",
|
|
57
|
+
uivk: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9"
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var NAME_RE = /^[a-z0-9]{1,62}$/;
|
|
61
|
+
function isValidName(name) {
|
|
62
|
+
return NAME_RE.test(name);
|
|
89
63
|
}
|
|
90
|
-
function
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
64
|
+
function normalizeApiResponse(obj) {
|
|
65
|
+
if (Array.isArray(obj))
|
|
66
|
+
return obj.map((item) => normalizeApiResponse(item));
|
|
67
|
+
if (obj && typeof obj === "object") {
|
|
68
|
+
return Object.fromEntries(
|
|
69
|
+
Object.entries(obj).map(([k, v]) => [
|
|
70
|
+
k.replace(/_([a-z])/g, (_, c) => c.toUpperCase()),
|
|
71
|
+
normalizeApiResponse(v)
|
|
72
|
+
])
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return obj;
|
|
100
76
|
}
|
|
101
|
-
function
|
|
102
|
-
return
|
|
103
|
-
id: raw.id,
|
|
104
|
-
name: raw.name,
|
|
105
|
-
action: raw.action,
|
|
106
|
-
txid: raw.txid,
|
|
107
|
-
height: raw.height,
|
|
108
|
-
ua: raw.ua,
|
|
109
|
-
price: raw.price,
|
|
110
|
-
nonce: raw.nonce,
|
|
111
|
-
signature: raw.signature,
|
|
112
|
-
pubkey: raw.pubkey
|
|
113
|
-
};
|
|
77
|
+
function isWholeNumber(value) {
|
|
78
|
+
return /^\d+$/.test(value) && !value.startsWith("0") || value === "0";
|
|
114
79
|
}
|
|
115
|
-
function
|
|
116
|
-
return
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
80
|
+
function isValidUnifiedAddress(address) {
|
|
81
|
+
if (!address) return false;
|
|
82
|
+
if (address.startsWith("utest1")) return true;
|
|
83
|
+
if (address.startsWith("u1")) return true;
|
|
84
|
+
try {
|
|
85
|
+
const decoded = import_bech32.bech32m.decode(address);
|
|
86
|
+
return decoded.prefix === "u" || decoded.prefix === "utest";
|
|
87
|
+
} catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
123
90
|
}
|
|
124
|
-
function
|
|
125
|
-
return
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
91
|
+
function isValidTransparentAddress(address) {
|
|
92
|
+
if (!address) return false;
|
|
93
|
+
const validPrefixes = ["t1", "t3", "tm", "tn"];
|
|
94
|
+
if (!validPrefixes.some((p) => address.startsWith(p))) return false;
|
|
95
|
+
if (address.length < 26 || address.length > 36) return false;
|
|
96
|
+
const base58Regex = /^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/;
|
|
97
|
+
return base58Regex.test(address);
|
|
129
98
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
99
|
+
var PAYLOAD_RULES = {
|
|
100
|
+
CLAIM: { format: "CLAIM:<name>:<ua>", checks: ["name", "ua"] },
|
|
101
|
+
BUY: { format: "BUY:<name>:<ua>", checks: ["name", "ua"] },
|
|
102
|
+
UPDATE: {
|
|
103
|
+
format: "UPDATE:<name>:<ua>:<nonce>",
|
|
104
|
+
checks: ["name", "ua", "nonce"]
|
|
105
|
+
},
|
|
106
|
+
LIST: {
|
|
107
|
+
format: "LIST:<name>:<price>:<pay_taddr>:<nonce>",
|
|
108
|
+
checks: ["name", "price", "pay_taddr", "nonce"]
|
|
109
|
+
},
|
|
110
|
+
DELIST: { format: "DELIST:<name>:<nonce>", checks: ["name", "nonce"] },
|
|
111
|
+
RELEASE: { format: "RELEASE:<name>:<nonce>", checks: ["name", "nonce"] }
|
|
139
112
|
};
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
113
|
+
function validateField(value, type) {
|
|
114
|
+
switch (type) {
|
|
115
|
+
case "name":
|
|
116
|
+
return NAME_RE.test(value) ? null : "Invalid name. Use lowercase a-z and 0-9, 1 to 62 chars.";
|
|
117
|
+
case "ua":
|
|
118
|
+
return isValidUnifiedAddress(value) ? null : `Invalid unified address: "${value}".`;
|
|
119
|
+
case "price":
|
|
120
|
+
return isWholeNumber(value) && Number(value) > 0 ? null : "Price must be a positive whole number in zats.";
|
|
121
|
+
case "nonce":
|
|
122
|
+
return isWholeNumber(value) ? null : "Nonce must be a whole number.";
|
|
123
|
+
case "pay_taddr":
|
|
124
|
+
return isValidTransparentAddress(value) ? null : `Invalid transparent address: "${value}".`;
|
|
125
|
+
}
|
|
144
126
|
}
|
|
145
|
-
function
|
|
146
|
-
return { valid: level === "valid", action,
|
|
127
|
+
function buildValidationResult(level, action, message) {
|
|
128
|
+
return { valid: level === "valid", action, message, level };
|
|
147
129
|
}
|
|
148
130
|
var ZNS = class {
|
|
149
131
|
/**
|
|
@@ -155,8 +137,21 @@ var ZNS = class {
|
|
|
155
137
|
constructor(options) {
|
|
156
138
|
this.rpcId = 0;
|
|
157
139
|
this._verified = false;
|
|
140
|
+
/** Validate a Zcash Unified Address format.
|
|
141
|
+
* Accepts both mainnet ('u') and testnet ('utest') prefixes.
|
|
142
|
+
* Performs basic format validation but NOT full bech32m checksum verification.
|
|
143
|
+
* Returns true if the address looks like a unified address, false otherwise.
|
|
144
|
+
*
|
|
145
|
+
* @todo(F4Jumble) Upgrade to full ZIP-316 decoding with F4Jumble to:
|
|
146
|
+
* - Parse actual typecodes from address items
|
|
147
|
+
* - Validate F4Jumble checksum (not just bech32m)
|
|
148
|
+
* - Optionally enforce: address must contain at least one Orchard receiver (typecode 0x03)
|
|
149
|
+
* Requires @noble/hashes (blake2b) implementation of F4Jumble inverse. */
|
|
150
|
+
this.isValidName = isValidName;
|
|
151
|
+
this.isValidUnifiedAddress = isValidUnifiedAddress;
|
|
152
|
+
this.isValidTransparentAddress = isValidTransparentAddress;
|
|
158
153
|
this.network = options?.network ?? "testnet";
|
|
159
|
-
this.url = options?.url ??
|
|
154
|
+
this.url = options?.url ?? NETWORKS[this.network].url;
|
|
160
155
|
}
|
|
161
156
|
/**
|
|
162
157
|
* Verifies that the connected server is a known ZNS instance.
|
|
@@ -164,7 +159,7 @@ var ZNS = class {
|
|
|
164
159
|
*/
|
|
165
160
|
async verify() {
|
|
166
161
|
const status = await this.status();
|
|
167
|
-
if (
|
|
162
|
+
if (status.uivk !== NETWORKS[this.network].uivk) {
|
|
168
163
|
throw new Error(
|
|
169
164
|
`UIVK mismatch: indexer returned "${status.uivk.slice(0, 20)}..." which is not a known ZNS instance`
|
|
170
165
|
);
|
|
@@ -177,21 +172,19 @@ var ZNS = class {
|
|
|
177
172
|
}
|
|
178
173
|
/** Get the registry address for the current network. */
|
|
179
174
|
get registryAddress() {
|
|
180
|
-
|
|
181
|
-
if (!addr) {
|
|
182
|
-
throw new Error(`Unknown network: ${this.network}`);
|
|
183
|
-
}
|
|
184
|
-
return addr;
|
|
175
|
+
return NETWORKS[this.network].registryAddress;
|
|
185
176
|
}
|
|
186
177
|
/** Fetch current server status including pricing and configuration. */
|
|
187
178
|
async status() {
|
|
188
179
|
const raw = await this.rpc("status");
|
|
189
|
-
return
|
|
180
|
+
return normalizeApiResponse(raw);
|
|
190
181
|
}
|
|
191
182
|
/** Resolve a ZNS name to its registration. Returns null if not registered. */
|
|
192
183
|
async resolveName(name) {
|
|
193
|
-
const raw = await this.rpc("resolve", {
|
|
194
|
-
|
|
184
|
+
const raw = await this.rpc("resolve", {
|
|
185
|
+
query: name
|
|
186
|
+
});
|
|
187
|
+
return raw ? normalizeApiResponse(raw) : null;
|
|
195
188
|
}
|
|
196
189
|
/** Resolve a Zcash Unified Address to all names pointing to it. Returns empty array if none.
|
|
197
190
|
* Supports pagination with limit (default 50, max 500) and offset (default 0). */
|
|
@@ -201,7 +194,7 @@ var ZNS = class {
|
|
|
201
194
|
limit,
|
|
202
195
|
offset
|
|
203
196
|
});
|
|
204
|
-
return raw.map(
|
|
197
|
+
return raw.map((r) => normalizeApiResponse(r));
|
|
205
198
|
}
|
|
206
199
|
/** List all registered names. Useful for explorers or browsers.
|
|
207
200
|
* Supports pagination with limit (default 50, max 500) and offset (default 0). */
|
|
@@ -211,62 +204,31 @@ var ZNS = class {
|
|
|
211
204
|
limit,
|
|
212
205
|
offset
|
|
213
206
|
});
|
|
214
|
-
return raw.map(
|
|
207
|
+
return raw.map((r) => normalizeApiResponse(r));
|
|
215
208
|
}
|
|
216
209
|
/** Check if a name is available for registration.
|
|
217
210
|
* Returns false immediately for invalid names without hitting the server. */
|
|
218
211
|
async isAvailable(name) {
|
|
219
|
-
if (!
|
|
212
|
+
if (!isValidName(name)) return false;
|
|
220
213
|
const result = await this.resolveName(name);
|
|
221
214
|
return result === null;
|
|
222
215
|
}
|
|
223
|
-
/** Validate a Zcash Unified Address format.
|
|
224
|
-
* Accepts both mainnet ('u') and testnet ('utest') prefixes.
|
|
225
|
-
* Performs basic format validation but NOT full bech32m checksum verification.
|
|
226
|
-
* Returns true if the address looks like a unified address, false otherwise. */
|
|
227
|
-
isValidUnifiedAddress(address) {
|
|
228
|
-
if (!address) return false;
|
|
229
|
-
if (address.startsWith("utest1")) return true;
|
|
230
|
-
if (address.startsWith("u1")) return true;
|
|
231
|
-
try {
|
|
232
|
-
const decoded = import_bech32.bech32m.decode(address);
|
|
233
|
-
return decoded.prefix === "u" || decoded.prefix === "utest";
|
|
234
|
-
} catch {
|
|
235
|
-
return false;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
216
|
async listings(limit, offset) {
|
|
239
|
-
const
|
|
217
|
+
const raw = await this.rpc("listings", {
|
|
240
218
|
limit,
|
|
241
219
|
offset
|
|
242
220
|
});
|
|
243
221
|
return {
|
|
244
|
-
listings:
|
|
245
|
-
|
|
246
|
-
price: l.price,
|
|
247
|
-
payTaddr: l.pay_taddr,
|
|
248
|
-
nonce: l.nonce,
|
|
249
|
-
txid: l.txid,
|
|
250
|
-
height: l.height,
|
|
251
|
-
signature: l.signature,
|
|
252
|
-
pubkey: l.pubkey,
|
|
253
|
-
pendingBuy: l.pending_buy ? {
|
|
254
|
-
buyer: l.pending_buy.buyer_ua,
|
|
255
|
-
price: l.pending_buy.price,
|
|
256
|
-
claimHeight: l.pending_buy.claim_height,
|
|
257
|
-
expiresAt: l.pending_buy.expires_at,
|
|
258
|
-
txid: l.pending_buy.txid
|
|
259
|
-
} : void 0
|
|
260
|
-
})),
|
|
261
|
-
total: result.total
|
|
222
|
+
listings: raw.listings.map((l) => normalizeApiResponse(l)),
|
|
223
|
+
total: raw.total
|
|
262
224
|
};
|
|
263
225
|
}
|
|
264
226
|
async events(filter) {
|
|
265
227
|
const raw = await this.rpc(
|
|
266
228
|
"events",
|
|
267
|
-
|
|
229
|
+
normalizeApiResponse(filter ?? {})
|
|
268
230
|
);
|
|
269
|
-
return
|
|
231
|
+
return normalizeApiResponse(raw);
|
|
270
232
|
}
|
|
271
233
|
/**
|
|
272
234
|
* Verify a listing's signature.
|
|
@@ -292,9 +254,25 @@ var ZNS = class {
|
|
|
292
254
|
if (!payload) return false;
|
|
293
255
|
return this.verifyEd25519(payload, reg.signature, pubkey);
|
|
294
256
|
}
|
|
295
|
-
/**
|
|
296
|
-
|
|
297
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Verify a sovereign Ed25519 signature before sending a transaction.
|
|
259
|
+
* Call this after signing but before calling `complete()` to catch invalid signatures early.
|
|
260
|
+
*
|
|
261
|
+
* @param payload The signing payload string (e.g. `CLAIM:foo:u1abc`)
|
|
262
|
+
* @param signature The Ed25519 signature (base64)
|
|
263
|
+
* @param pubkey The Ed25519 public key (base64)
|
|
264
|
+
* @returns true if the signature is valid for the given payload and pubkey
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```ts
|
|
268
|
+
* const claim = zns.prepareClaim(name, address, cost);
|
|
269
|
+
* const isValid = await zns.verifySoverignSignature(claim.payload, signature, userPubkey);
|
|
270
|
+
* if (!isValid) throw new Error("Invalid signature");
|
|
271
|
+
* const { memo, uri } = claim.complete(signature, userPubkey);
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
async verifySoverignSignature(payload, signature, pubkey) {
|
|
275
|
+
return this.verifyEd25519(payload, signature, pubkey);
|
|
298
276
|
}
|
|
299
277
|
/**
|
|
300
278
|
* Validate a signing payload string against the ZNS memo format spec.
|
|
@@ -322,7 +300,6 @@ var ZNS = class {
|
|
|
322
300
|
return {
|
|
323
301
|
valid: false,
|
|
324
302
|
action: "",
|
|
325
|
-
canonicalAction: null,
|
|
326
303
|
message: "Empty payload.",
|
|
327
304
|
level: "invalid"
|
|
328
305
|
};
|
|
@@ -332,83 +309,33 @@ var ZNS = class {
|
|
|
332
309
|
return {
|
|
333
310
|
valid: false,
|
|
334
311
|
action: raw.toUpperCase(),
|
|
335
|
-
canonicalAction: null,
|
|
336
312
|
message: "Missing colon separator. Expected format: ACTION:field1:field2:...",
|
|
337
313
|
level: "invalid"
|
|
338
314
|
};
|
|
339
315
|
}
|
|
340
|
-
const
|
|
341
|
-
const actionLower = raw.slice(0, colonIdx).toLowerCase();
|
|
316
|
+
const action = raw.slice(0, colonIdx).toUpperCase();
|
|
342
317
|
const rest = raw.slice(colonIdx + 1);
|
|
343
318
|
const parts = rest.split(":");
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
case "update": {
|
|
364
|
-
if (parts.length !== 3)
|
|
365
|
-
return mk("invalid", actionUpper, "update", `Expected UPDATE:<name>:<ua>:<nonce>.`);
|
|
366
|
-
if (!NAME_RE.test(parts[0]))
|
|
367
|
-
return mk("invalid", actionUpper, "update", `Invalid name. Use lowercase a-z and 0-9, 1 to 62 chars.`);
|
|
368
|
-
if (!this.isValidUnifiedAddress(parts[1]))
|
|
369
|
-
return mk("invalid", actionUpper, "update", `Invalid unified address: "${parts[1]}".`);
|
|
370
|
-
if (!isWholeNumber(parts[2]))
|
|
371
|
-
return mk("invalid", actionUpper, "update", `Nonce must be a whole number.`);
|
|
372
|
-
return mk("valid", actionUpper, "update", "Valid UPDATE payload.");
|
|
373
|
-
}
|
|
374
|
-
case "list": {
|
|
375
|
-
if (parts.length !== 4)
|
|
376
|
-
return mk("invalid", actionUpper, "list", `Expected LIST:<name>:<price_zats>:<pay_taddr>:<nonce>.`);
|
|
377
|
-
if (!NAME_RE.test(parts[0]))
|
|
378
|
-
return mk("invalid", actionUpper, "list", `Invalid name. Use lowercase a-z and 0-9, 1 to 62 chars.`);
|
|
379
|
-
if (!isWholeNumber(parts[1]) || Number(parts[1]) <= 0)
|
|
380
|
-
return mk("invalid", actionUpper, "list", `Price must be a positive whole number in zats.`);
|
|
381
|
-
if (!isWholeNumber(parts[3]))
|
|
382
|
-
return mk("invalid", actionUpper, "list", `Nonce must be a whole number.`);
|
|
383
|
-
return mk("valid", actionUpper, "list", "Valid LIST payload.");
|
|
384
|
-
}
|
|
385
|
-
case "delist": {
|
|
386
|
-
if (parts.length !== 2)
|
|
387
|
-
return mk("invalid", actionUpper, "delist", `Expected DELIST:<name>:<nonce>.`);
|
|
388
|
-
if (!NAME_RE.test(parts[0]))
|
|
389
|
-
return mk("invalid", actionUpper, "delist", `Invalid name. Use lowercase a-z and 0-9, 1 to 62 chars.`);
|
|
390
|
-
if (!isWholeNumber(parts[1]))
|
|
391
|
-
return mk("invalid", actionUpper, "delist", `Nonce must be a whole number.`);
|
|
392
|
-
return mk("valid", actionUpper, "delist", "Valid DELIST payload.");
|
|
393
|
-
}
|
|
394
|
-
case "release": {
|
|
395
|
-
if (parts.length !== 2)
|
|
396
|
-
return mk("invalid", actionUpper, "release", `Expected RELEASE:<name>:<nonce>.`);
|
|
397
|
-
if (!NAME_RE.test(parts[0]))
|
|
398
|
-
return mk("invalid", actionUpper, "release", `Invalid name. Use lowercase a-z and 0-9, 1 to 62 chars.`);
|
|
399
|
-
if (!isWholeNumber(parts[1]))
|
|
400
|
-
return mk("invalid", actionUpper, "release", `Nonce must be a whole number.`);
|
|
401
|
-
return mk("valid", actionUpper, "release", "Valid RELEASE payload.");
|
|
402
|
-
}
|
|
403
|
-
default:
|
|
404
|
-
return {
|
|
405
|
-
valid: false,
|
|
406
|
-
action: actionUpper,
|
|
407
|
-
canonicalAction: null,
|
|
408
|
-
message: `Unrecognized action "${actionUpper}". Valid actions: ${ZNS_ACTIONS.join(", ")}.`,
|
|
409
|
-
level: "unrecognized"
|
|
410
|
-
};
|
|
319
|
+
if (!ZNS_ACTIONS.includes(action)) {
|
|
320
|
+
return {
|
|
321
|
+
valid: false,
|
|
322
|
+
action,
|
|
323
|
+
message: `Unrecognized action "${action}". Valid actions: ${ZNS_ACTIONS.join(", ")}.`,
|
|
324
|
+
level: "unrecognized"
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
const rule = PAYLOAD_RULES[action];
|
|
328
|
+
if (parts.length !== rule.checks.length)
|
|
329
|
+
return buildValidationResult(
|
|
330
|
+
"invalid",
|
|
331
|
+
action,
|
|
332
|
+
`Expected ${rule.format}.`
|
|
333
|
+
);
|
|
334
|
+
for (let i = 0; i < rule.checks.length; i++) {
|
|
335
|
+
const err = validateField(parts[i], rule.checks[i]);
|
|
336
|
+
if (err) return buildValidationResult("invalid", action, err);
|
|
411
337
|
}
|
|
338
|
+
return buildValidationResult("valid", action, `Valid ${action} payload.`);
|
|
412
339
|
}
|
|
413
340
|
/**
|
|
414
341
|
* Get the claim cost in zatoshis for a name of given length.
|
|
@@ -451,7 +378,7 @@ var ZNS = class {
|
|
|
451
378
|
*/
|
|
452
379
|
prepareClaim(name, address, cost) {
|
|
453
380
|
this.requireValidName(name);
|
|
454
|
-
if (!
|
|
381
|
+
if (!isValidUnifiedAddress(address)) {
|
|
455
382
|
throw new Error(`Invalid Zcash Unified Address: ${address}`);
|
|
456
383
|
}
|
|
457
384
|
return {
|
|
@@ -476,7 +403,10 @@ var ZNS = class {
|
|
|
476
403
|
payload: `LIST:${name}:${price}:${payTaddr}:${nonce}`,
|
|
477
404
|
complete: (signature, userPubkey) => {
|
|
478
405
|
const memo = userPubkey ? `ZNS:LIST:${name}:${price}:${payTaddr}:${nonce}:${signature}:${userPubkey}` : `ZNS:LIST:${name}:${price}:${payTaddr}:${nonce}:${signature}`;
|
|
479
|
-
return {
|
|
406
|
+
return {
|
|
407
|
+
memo,
|
|
408
|
+
uri: this.buildZcashUri(this.registryAddress, LIST_COMMISSION, memo)
|
|
409
|
+
};
|
|
480
410
|
}
|
|
481
411
|
};
|
|
482
412
|
}
|
|
@@ -488,13 +418,16 @@ var ZNS = class {
|
|
|
488
418
|
payload: `DELIST:${name}:${nonce}`,
|
|
489
419
|
complete: (signature, userPubkey) => {
|
|
490
420
|
const memo = userPubkey ? `ZNS:DELIST:${name}:${nonce}:${signature}:${userPubkey}` : `ZNS:DELIST:${name}:${nonce}:${signature}`;
|
|
491
|
-
return {
|
|
421
|
+
return {
|
|
422
|
+
memo,
|
|
423
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
424
|
+
};
|
|
492
425
|
}
|
|
493
426
|
};
|
|
494
427
|
}
|
|
495
428
|
prepareUpdate(name, newAddress, nonce) {
|
|
496
429
|
this.requireValidName(name);
|
|
497
|
-
if (!
|
|
430
|
+
if (!isValidUnifiedAddress(newAddress)) {
|
|
498
431
|
throw new Error(`Invalid Zcash Unified Address: ${newAddress}`);
|
|
499
432
|
}
|
|
500
433
|
return {
|
|
@@ -504,7 +437,10 @@ var ZNS = class {
|
|
|
504
437
|
payload: `UPDATE:${name}:${newAddress}:${nonce}`,
|
|
505
438
|
complete: (signature, userPubkey) => {
|
|
506
439
|
const memo = userPubkey ? `ZNS:UPDATE:${name}:${newAddress}:${nonce}:${signature}:${userPubkey}` : `ZNS:UPDATE:${name}:${newAddress}:${nonce}:${signature}`;
|
|
507
|
-
return {
|
|
440
|
+
return {
|
|
441
|
+
memo,
|
|
442
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
443
|
+
};
|
|
508
444
|
}
|
|
509
445
|
};
|
|
510
446
|
}
|
|
@@ -520,7 +456,10 @@ var ZNS = class {
|
|
|
520
456
|
payload: `BUY:${name}:${buyerAddress}`,
|
|
521
457
|
complete: (signature, userPubkey) => {
|
|
522
458
|
const memo = userPubkey ? `ZNS:BUY:${name}:${buyerAddress}:${price}:${signature}:${userPubkey}` : `ZNS:BUY:${name}:${buyerAddress}:${price}:${signature}`;
|
|
523
|
-
return {
|
|
459
|
+
return {
|
|
460
|
+
memo,
|
|
461
|
+
uri: this.buildZcashUri(this.registryAddress, BUY_COMMISSION, memo)
|
|
462
|
+
};
|
|
524
463
|
}
|
|
525
464
|
};
|
|
526
465
|
}
|
|
@@ -532,7 +471,10 @@ var ZNS = class {
|
|
|
532
471
|
payload: `RELEASE:${name}:${nonce}`,
|
|
533
472
|
complete: (signature, userPubkey) => {
|
|
534
473
|
const memo = userPubkey ? `ZNS:RELEASE:${name}:${nonce}:${signature}:${userPubkey}` : `ZNS:RELEASE:${name}:${nonce}:${signature}`;
|
|
535
|
-
return {
|
|
474
|
+
return {
|
|
475
|
+
memo,
|
|
476
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
477
|
+
};
|
|
536
478
|
}
|
|
537
479
|
};
|
|
538
480
|
}
|
|
@@ -543,7 +485,10 @@ var ZNS = class {
|
|
|
543
485
|
payload: `SETPRICE:${prices.length}:${prices.join(":")}:${nonce}`,
|
|
544
486
|
complete: (signature) => {
|
|
545
487
|
const memo = `ZNS:SETPRICE:${prices.length}:${prices.join(":")}:${nonce}:${signature}`;
|
|
546
|
-
return {
|
|
488
|
+
return {
|
|
489
|
+
memo,
|
|
490
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
491
|
+
};
|
|
547
492
|
}
|
|
548
493
|
};
|
|
549
494
|
}
|
|
@@ -576,7 +521,7 @@ var ZNS = class {
|
|
|
576
521
|
}
|
|
577
522
|
}
|
|
578
523
|
requireValidName(name) {
|
|
579
|
-
if (!
|
|
524
|
+
if (!isValidName(name)) throw new Error(`Invalid ZNS name: ${name}`);
|
|
580
525
|
}
|
|
581
526
|
/** Build a ZIP-321 URI. Amount is in zatoshis and will be converted to ZEC for the URI. */
|
|
582
527
|
buildZcashUri(address, amountZats, memo) {
|
|
@@ -640,10 +585,7 @@ var ZNS = class {
|
|
|
640
585
|
// Annotate the CommonJS export names for ESM import in node:
|
|
641
586
|
0 && (module.exports = {
|
|
642
587
|
BUY_COMMISSION,
|
|
643
|
-
DEFAULT_URL,
|
|
644
588
|
LIST_COMMISSION,
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
ZNS,
|
|
648
|
-
ZNS_ACTIONS
|
|
589
|
+
NETWORKS,
|
|
590
|
+
ZNS
|
|
649
591
|
});
|