zcashname-sdk 0.8.5 → 0.8.7
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 +68 -19
- package/dist/zns.d.cts +25 -5
- package/dist/zns.d.ts +25 -5
- package/dist/zns.js +68 -18
- package/package.json +2 -1
package/dist/zns.cjs
CHANGED
|
@@ -31,7 +31,6 @@ 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
35
|
NETWORKS: () => NETWORKS,
|
|
37
36
|
ZNS: () => ZNS
|
|
@@ -44,19 +43,18 @@ var import_bech32 = require("bech32");
|
|
|
44
43
|
var ZNS_ACTIONS = ["CLAIM", "BUY", "UPDATE", "LIST", "DELIST", "RELEASE"];
|
|
45
44
|
|
|
46
45
|
// src/zns.ts
|
|
47
|
-
var DEFAULT_URL = "https://light.zcash.me/zns-testnet";
|
|
48
46
|
var BUY_COMMISSION = 1e4;
|
|
49
47
|
var LIST_COMMISSION = 1e6;
|
|
50
48
|
var NETWORKS = {
|
|
51
49
|
testnet: {
|
|
52
50
|
url: "https://light.zcash.me/zns-testnet",
|
|
53
51
|
registryAddress: "utest1f32kn6c4zvn54xr8wfsnxmj9hzpu2mwgtxzpzwcw34906tdccdvzs0z2dx38lly7tpan77x6udt8pjczqm22ymsdhlz9j0tk5yq664nl",
|
|
54
|
-
uivk: "
|
|
52
|
+
uivk: "uivktest1hzw7wyadutvzfgpna80yftsk5l7jeyu2p5me5quvp28tytxueta00cx4068wnlzcv7tx9n3t3gfhsy83pe4y6jrhxtzaq0hj6xtg5zrk2dn7zen3vns2a5pgs4fxdjlletmqrhfa42"
|
|
55
53
|
},
|
|
56
54
|
mainnet: {
|
|
57
|
-
url: "https://light.zcash.me/zns",
|
|
55
|
+
url: "https://light.zcash.me/zns-mainnet",
|
|
58
56
|
registryAddress: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9",
|
|
59
|
-
uivk: "
|
|
57
|
+
uivk: "uivk1gl26qy0xjja7lqhyg3pf0x4j4j66kqwewrjkdcg28eqq4wgtzjmujpee7x9cs2ec9xhnlgrm8ptlw8z80j2aryw8nqtssser2ys778a0s00uvgkdjnfr58sndhfvc3f4zqjs6ywva6"
|
|
60
58
|
}
|
|
61
59
|
};
|
|
62
60
|
var NAME_RE = /^[a-z0-9]{1,62}$/;
|
|
@@ -64,7 +62,8 @@ function isValidName(name) {
|
|
|
64
62
|
return NAME_RE.test(name);
|
|
65
63
|
}
|
|
66
64
|
function normalizeApiResponse(obj) {
|
|
67
|
-
if (Array.isArray(obj))
|
|
65
|
+
if (Array.isArray(obj))
|
|
66
|
+
return obj.map((item) => normalizeApiResponse(item));
|
|
68
67
|
if (obj && typeof obj === "object") {
|
|
69
68
|
return Object.fromEntries(
|
|
70
69
|
Object.entries(obj).map(([k, v]) => [
|
|
@@ -93,15 +92,21 @@ function isValidTransparentAddress(address) {
|
|
|
93
92
|
if (!address) return false;
|
|
94
93
|
const validPrefixes = ["t1", "t3", "tm", "tn"];
|
|
95
94
|
if (!validPrefixes.some((p) => address.startsWith(p))) return false;
|
|
96
|
-
if (address.length < 26 || address.length >
|
|
95
|
+
if (address.length < 26 || address.length > 36) return false;
|
|
97
96
|
const base58Regex = /^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/;
|
|
98
97
|
return base58Regex.test(address);
|
|
99
98
|
}
|
|
100
99
|
var PAYLOAD_RULES = {
|
|
101
100
|
CLAIM: { format: "CLAIM:<name>:<ua>", checks: ["name", "ua"] },
|
|
102
101
|
BUY: { format: "BUY:<name>:<ua>", checks: ["name", "ua"] },
|
|
103
|
-
UPDATE: {
|
|
104
|
-
|
|
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
|
+
},
|
|
105
110
|
DELIST: { format: "DELIST:<name>:<nonce>", checks: ["name", "nonce"] },
|
|
106
111
|
RELEASE: { format: "RELEASE:<name>:<nonce>", checks: ["name", "nonce"] }
|
|
107
112
|
};
|
|
@@ -136,12 +141,13 @@ var ZNS = class {
|
|
|
136
141
|
* Accepts both mainnet ('u') and testnet ('utest') prefixes.
|
|
137
142
|
* Performs basic format validation but NOT full bech32m checksum verification.
|
|
138
143
|
* Returns true if the address looks like a unified address, false otherwise.
|
|
139
|
-
*
|
|
144
|
+
*
|
|
140
145
|
* @todo(F4Jumble) Upgrade to full ZIP-316 decoding with F4Jumble to:
|
|
141
146
|
* - Parse actual typecodes from address items
|
|
142
147
|
* - Validate F4Jumble checksum (not just bech32m)
|
|
143
148
|
* - Optionally enforce: address must contain at least one Orchard receiver (typecode 0x03)
|
|
144
149
|
* Requires @noble/hashes (blake2b) implementation of F4Jumble inverse. */
|
|
150
|
+
this.isValidName = isValidName;
|
|
145
151
|
this.isValidUnifiedAddress = isValidUnifiedAddress;
|
|
146
152
|
this.isValidTransparentAddress = isValidTransparentAddress;
|
|
147
153
|
this.network = options?.network ?? "testnet";
|
|
@@ -175,7 +181,9 @@ var ZNS = class {
|
|
|
175
181
|
}
|
|
176
182
|
/** Resolve a ZNS name to its registration. Returns null if not registered. */
|
|
177
183
|
async resolveName(name) {
|
|
178
|
-
const raw = await this.rpc("resolve", {
|
|
184
|
+
const raw = await this.rpc("resolve", {
|
|
185
|
+
query: name
|
|
186
|
+
});
|
|
179
187
|
return raw ? normalizeApiResponse(raw) : null;
|
|
180
188
|
}
|
|
181
189
|
/** Resolve a Zcash Unified Address to all names pointing to it. Returns empty array if none.
|
|
@@ -246,6 +254,26 @@ var ZNS = class {
|
|
|
246
254
|
if (!payload) return false;
|
|
247
255
|
return this.verifyEd25519(payload, reg.signature, pubkey);
|
|
248
256
|
}
|
|
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);
|
|
276
|
+
}
|
|
249
277
|
/**
|
|
250
278
|
* Validate a signing payload string against the ZNS memo format spec.
|
|
251
279
|
*
|
|
@@ -298,7 +326,11 @@ var ZNS = class {
|
|
|
298
326
|
}
|
|
299
327
|
const rule = PAYLOAD_RULES[action];
|
|
300
328
|
if (parts.length !== rule.checks.length)
|
|
301
|
-
return buildValidationResult(
|
|
329
|
+
return buildValidationResult(
|
|
330
|
+
"invalid",
|
|
331
|
+
action,
|
|
332
|
+
`Expected ${rule.format}.`
|
|
333
|
+
);
|
|
302
334
|
for (let i = 0; i < rule.checks.length; i++) {
|
|
303
335
|
const err = validateField(parts[i], rule.checks[i]);
|
|
304
336
|
if (err) return buildValidationResult("invalid", action, err);
|
|
@@ -371,7 +403,10 @@ var ZNS = class {
|
|
|
371
403
|
payload: `LIST:${name}:${price}:${payTaddr}:${nonce}`,
|
|
372
404
|
complete: (signature, userPubkey) => {
|
|
373
405
|
const memo = userPubkey ? `ZNS:LIST:${name}:${price}:${payTaddr}:${nonce}:${signature}:${userPubkey}` : `ZNS:LIST:${name}:${price}:${payTaddr}:${nonce}:${signature}`;
|
|
374
|
-
return {
|
|
406
|
+
return {
|
|
407
|
+
memo,
|
|
408
|
+
uri: this.buildZcashUri(this.registryAddress, LIST_COMMISSION, memo)
|
|
409
|
+
};
|
|
375
410
|
}
|
|
376
411
|
};
|
|
377
412
|
}
|
|
@@ -383,7 +418,10 @@ var ZNS = class {
|
|
|
383
418
|
payload: `DELIST:${name}:${nonce}`,
|
|
384
419
|
complete: (signature, userPubkey) => {
|
|
385
420
|
const memo = userPubkey ? `ZNS:DELIST:${name}:${nonce}:${signature}:${userPubkey}` : `ZNS:DELIST:${name}:${nonce}:${signature}`;
|
|
386
|
-
return {
|
|
421
|
+
return {
|
|
422
|
+
memo,
|
|
423
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
424
|
+
};
|
|
387
425
|
}
|
|
388
426
|
};
|
|
389
427
|
}
|
|
@@ -399,7 +437,10 @@ var ZNS = class {
|
|
|
399
437
|
payload: `UPDATE:${name}:${newAddress}:${nonce}`,
|
|
400
438
|
complete: (signature, userPubkey) => {
|
|
401
439
|
const memo = userPubkey ? `ZNS:UPDATE:${name}:${newAddress}:${nonce}:${signature}:${userPubkey}` : `ZNS:UPDATE:${name}:${newAddress}:${nonce}:${signature}`;
|
|
402
|
-
return {
|
|
440
|
+
return {
|
|
441
|
+
memo,
|
|
442
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
443
|
+
};
|
|
403
444
|
}
|
|
404
445
|
};
|
|
405
446
|
}
|
|
@@ -415,7 +456,10 @@ var ZNS = class {
|
|
|
415
456
|
payload: `BUY:${name}:${buyerAddress}`,
|
|
416
457
|
complete: (signature, userPubkey) => {
|
|
417
458
|
const memo = userPubkey ? `ZNS:BUY:${name}:${buyerAddress}:${price}:${signature}:${userPubkey}` : `ZNS:BUY:${name}:${buyerAddress}:${price}:${signature}`;
|
|
418
|
-
return {
|
|
459
|
+
return {
|
|
460
|
+
memo,
|
|
461
|
+
uri: this.buildZcashUri(this.registryAddress, BUY_COMMISSION, memo)
|
|
462
|
+
};
|
|
419
463
|
}
|
|
420
464
|
};
|
|
421
465
|
}
|
|
@@ -427,7 +471,10 @@ var ZNS = class {
|
|
|
427
471
|
payload: `RELEASE:${name}:${nonce}`,
|
|
428
472
|
complete: (signature, userPubkey) => {
|
|
429
473
|
const memo = userPubkey ? `ZNS:RELEASE:${name}:${nonce}:${signature}:${userPubkey}` : `ZNS:RELEASE:${name}:${nonce}:${signature}`;
|
|
430
|
-
return {
|
|
474
|
+
return {
|
|
475
|
+
memo,
|
|
476
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
477
|
+
};
|
|
431
478
|
}
|
|
432
479
|
};
|
|
433
480
|
}
|
|
@@ -438,7 +485,10 @@ var ZNS = class {
|
|
|
438
485
|
payload: `SETPRICE:${prices.length}:${prices.join(":")}:${nonce}`,
|
|
439
486
|
complete: (signature) => {
|
|
440
487
|
const memo = `ZNS:SETPRICE:${prices.length}:${prices.join(":")}:${nonce}:${signature}`;
|
|
441
|
-
return {
|
|
488
|
+
return {
|
|
489
|
+
memo,
|
|
490
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
491
|
+
};
|
|
442
492
|
}
|
|
443
493
|
};
|
|
444
494
|
}
|
|
@@ -535,7 +585,6 @@ var ZNS = class {
|
|
|
535
585
|
// Annotate the CommonJS export names for ESM import in node:
|
|
536
586
|
0 && (module.exports = {
|
|
537
587
|
BUY_COMMISSION,
|
|
538
|
-
DEFAULT_URL,
|
|
539
588
|
LIST_COMMISSION,
|
|
540
589
|
NETWORKS,
|
|
541
590
|
ZNS
|
package/dist/zns.d.cts
CHANGED
|
@@ -161,7 +161,6 @@ interface PayloadValidationResult {
|
|
|
161
161
|
readonly level: PayloadValidationLevel;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
declare const DEFAULT_URL = "https://light.zcash.me/zns-testnet";
|
|
165
164
|
/** Commission sent with a BUY claim memo (0.0001 ZEC = 10,000 zats). */
|
|
166
165
|
declare const BUY_COMMISSION: Zats;
|
|
167
166
|
/** Listing commission sent with a LIST memo (0.01 ZEC = 1,000,000 zats).
|
|
@@ -172,14 +171,16 @@ declare const NETWORKS: {
|
|
|
172
171
|
readonly testnet: {
|
|
173
172
|
readonly url: "https://light.zcash.me/zns-testnet";
|
|
174
173
|
readonly registryAddress: "utest1f32kn6c4zvn54xr8wfsnxmj9hzpu2mwgtxzpzwcw34906tdccdvzs0z2dx38lly7tpan77x6udt8pjczqm22ymsdhlz9j0tk5yq664nl";
|
|
175
|
-
readonly uivk: "
|
|
174
|
+
readonly uivk: "uivktest1hzw7wyadutvzfgpna80yftsk5l7jeyu2p5me5quvp28tytxueta00cx4068wnlzcv7tx9n3t3gfhsy83pe4y6jrhxtzaq0hj6xtg5zrk2dn7zen3vns2a5pgs4fxdjlletmqrhfa42";
|
|
176
175
|
};
|
|
177
176
|
readonly mainnet: {
|
|
178
|
-
readonly url: "https://light.zcash.me/zns";
|
|
177
|
+
readonly url: "https://light.zcash.me/zns-mainnet";
|
|
179
178
|
readonly registryAddress: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9";
|
|
180
|
-
readonly uivk: "
|
|
179
|
+
readonly uivk: "uivk1gl26qy0xjja7lqhyg3pf0x4j4j66kqwewrjkdcg28eqq4wgtzjmujpee7x9cs2ec9xhnlgrm8ptlw8z80j2aryw8nqtssser2ys778a0s00uvgkdjnfr58sndhfvc3f4zqjs6ywva6";
|
|
181
180
|
};
|
|
182
181
|
};
|
|
182
|
+
/** Validates a ZNS name format (lowercase alphanumeric, 1-62 chars). */
|
|
183
|
+
declare function isValidName(name: string): boolean;
|
|
183
184
|
/** Validates a Zcash unified (u-) address. */
|
|
184
185
|
declare function isValidUnifiedAddress(address: string): boolean;
|
|
185
186
|
/** Validates a Zcash transparent (t-) address. */
|
|
@@ -231,6 +232,7 @@ declare class ZNS {
|
|
|
231
232
|
* - Validate F4Jumble checksum (not just bech32m)
|
|
232
233
|
* - Optionally enforce: address must contain at least one Orchard receiver (typecode 0x03)
|
|
233
234
|
* Requires @noble/hashes (blake2b) implementation of F4Jumble inverse. */
|
|
235
|
+
isValidName: typeof isValidName;
|
|
234
236
|
isValidUnifiedAddress: typeof isValidUnifiedAddress;
|
|
235
237
|
isValidTransparentAddress: typeof isValidTransparentAddress;
|
|
236
238
|
listings(limit?: number, offset?: number): Promise<{
|
|
@@ -252,6 +254,24 @@ declare class ZNS {
|
|
|
252
254
|
* @returns true if the signature is valid
|
|
253
255
|
*/
|
|
254
256
|
verifyRegistration(reg: Registration, adminPubkey: string): Promise<boolean>;
|
|
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
|
+
verifySoverignSignature(payload: string, signature: string, pubkey: string): Promise<boolean>;
|
|
255
275
|
/**
|
|
256
276
|
* Validate a signing payload string against the ZNS memo format spec.
|
|
257
277
|
*
|
|
@@ -318,4 +338,4 @@ declare class ZNS {
|
|
|
318
338
|
private rpc;
|
|
319
339
|
}
|
|
320
340
|
|
|
321
|
-
export { BUY_COMMISSION,
|
|
341
|
+
export { BUY_COMMISSION, LIST_COMMISSION, NETWORKS, ZNS };
|
package/dist/zns.d.ts
CHANGED
|
@@ -161,7 +161,6 @@ interface PayloadValidationResult {
|
|
|
161
161
|
readonly level: PayloadValidationLevel;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
declare const DEFAULT_URL = "https://light.zcash.me/zns-testnet";
|
|
165
164
|
/** Commission sent with a BUY claim memo (0.0001 ZEC = 10,000 zats). */
|
|
166
165
|
declare const BUY_COMMISSION: Zats;
|
|
167
166
|
/** Listing commission sent with a LIST memo (0.01 ZEC = 1,000,000 zats).
|
|
@@ -172,14 +171,16 @@ declare const NETWORKS: {
|
|
|
172
171
|
readonly testnet: {
|
|
173
172
|
readonly url: "https://light.zcash.me/zns-testnet";
|
|
174
173
|
readonly registryAddress: "utest1f32kn6c4zvn54xr8wfsnxmj9hzpu2mwgtxzpzwcw34906tdccdvzs0z2dx38lly7tpan77x6udt8pjczqm22ymsdhlz9j0tk5yq664nl";
|
|
175
|
-
readonly uivk: "
|
|
174
|
+
readonly uivk: "uivktest1hzw7wyadutvzfgpna80yftsk5l7jeyu2p5me5quvp28tytxueta00cx4068wnlzcv7tx9n3t3gfhsy83pe4y6jrhxtzaq0hj6xtg5zrk2dn7zen3vns2a5pgs4fxdjlletmqrhfa42";
|
|
176
175
|
};
|
|
177
176
|
readonly mainnet: {
|
|
178
|
-
readonly url: "https://light.zcash.me/zns";
|
|
177
|
+
readonly url: "https://light.zcash.me/zns-mainnet";
|
|
179
178
|
readonly registryAddress: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9";
|
|
180
|
-
readonly uivk: "
|
|
179
|
+
readonly uivk: "uivk1gl26qy0xjja7lqhyg3pf0x4j4j66kqwewrjkdcg28eqq4wgtzjmujpee7x9cs2ec9xhnlgrm8ptlw8z80j2aryw8nqtssser2ys778a0s00uvgkdjnfr58sndhfvc3f4zqjs6ywva6";
|
|
181
180
|
};
|
|
182
181
|
};
|
|
182
|
+
/** Validates a ZNS name format (lowercase alphanumeric, 1-62 chars). */
|
|
183
|
+
declare function isValidName(name: string): boolean;
|
|
183
184
|
/** Validates a Zcash unified (u-) address. */
|
|
184
185
|
declare function isValidUnifiedAddress(address: string): boolean;
|
|
185
186
|
/** Validates a Zcash transparent (t-) address. */
|
|
@@ -231,6 +232,7 @@ declare class ZNS {
|
|
|
231
232
|
* - Validate F4Jumble checksum (not just bech32m)
|
|
232
233
|
* - Optionally enforce: address must contain at least one Orchard receiver (typecode 0x03)
|
|
233
234
|
* Requires @noble/hashes (blake2b) implementation of F4Jumble inverse. */
|
|
235
|
+
isValidName: typeof isValidName;
|
|
234
236
|
isValidUnifiedAddress: typeof isValidUnifiedAddress;
|
|
235
237
|
isValidTransparentAddress: typeof isValidTransparentAddress;
|
|
236
238
|
listings(limit?: number, offset?: number): Promise<{
|
|
@@ -252,6 +254,24 @@ declare class ZNS {
|
|
|
252
254
|
* @returns true if the signature is valid
|
|
253
255
|
*/
|
|
254
256
|
verifyRegistration(reg: Registration, adminPubkey: string): Promise<boolean>;
|
|
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
|
+
verifySoverignSignature(payload: string, signature: string, pubkey: string): Promise<boolean>;
|
|
255
275
|
/**
|
|
256
276
|
* Validate a signing payload string against the ZNS memo format spec.
|
|
257
277
|
*
|
|
@@ -318,4 +338,4 @@ declare class ZNS {
|
|
|
318
338
|
private rpc;
|
|
319
339
|
}
|
|
320
340
|
|
|
321
|
-
export { BUY_COMMISSION,
|
|
341
|
+
export { BUY_COMMISSION, LIST_COMMISSION, NETWORKS, ZNS };
|
package/dist/zns.js
CHANGED
|
@@ -6,19 +6,18 @@ import { bech32m } from "bech32";
|
|
|
6
6
|
var ZNS_ACTIONS = ["CLAIM", "BUY", "UPDATE", "LIST", "DELIST", "RELEASE"];
|
|
7
7
|
|
|
8
8
|
// src/zns.ts
|
|
9
|
-
var DEFAULT_URL = "https://light.zcash.me/zns-testnet";
|
|
10
9
|
var BUY_COMMISSION = 1e4;
|
|
11
10
|
var LIST_COMMISSION = 1e6;
|
|
12
11
|
var NETWORKS = {
|
|
13
12
|
testnet: {
|
|
14
13
|
url: "https://light.zcash.me/zns-testnet",
|
|
15
14
|
registryAddress: "utest1f32kn6c4zvn54xr8wfsnxmj9hzpu2mwgtxzpzwcw34906tdccdvzs0z2dx38lly7tpan77x6udt8pjczqm22ymsdhlz9j0tk5yq664nl",
|
|
16
|
-
uivk: "
|
|
15
|
+
uivk: "uivktest1hzw7wyadutvzfgpna80yftsk5l7jeyu2p5me5quvp28tytxueta00cx4068wnlzcv7tx9n3t3gfhsy83pe4y6jrhxtzaq0hj6xtg5zrk2dn7zen3vns2a5pgs4fxdjlletmqrhfa42"
|
|
17
16
|
},
|
|
18
17
|
mainnet: {
|
|
19
|
-
url: "https://light.zcash.me/zns",
|
|
18
|
+
url: "https://light.zcash.me/zns-mainnet",
|
|
20
19
|
registryAddress: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9",
|
|
21
|
-
uivk: "
|
|
20
|
+
uivk: "uivk1gl26qy0xjja7lqhyg3pf0x4j4j66kqwewrjkdcg28eqq4wgtzjmujpee7x9cs2ec9xhnlgrm8ptlw8z80j2aryw8nqtssser2ys778a0s00uvgkdjnfr58sndhfvc3f4zqjs6ywva6"
|
|
22
21
|
}
|
|
23
22
|
};
|
|
24
23
|
var NAME_RE = /^[a-z0-9]{1,62}$/;
|
|
@@ -26,7 +25,8 @@ function isValidName(name) {
|
|
|
26
25
|
return NAME_RE.test(name);
|
|
27
26
|
}
|
|
28
27
|
function normalizeApiResponse(obj) {
|
|
29
|
-
if (Array.isArray(obj))
|
|
28
|
+
if (Array.isArray(obj))
|
|
29
|
+
return obj.map((item) => normalizeApiResponse(item));
|
|
30
30
|
if (obj && typeof obj === "object") {
|
|
31
31
|
return Object.fromEntries(
|
|
32
32
|
Object.entries(obj).map(([k, v]) => [
|
|
@@ -55,15 +55,21 @@ function isValidTransparentAddress(address) {
|
|
|
55
55
|
if (!address) return false;
|
|
56
56
|
const validPrefixes = ["t1", "t3", "tm", "tn"];
|
|
57
57
|
if (!validPrefixes.some((p) => address.startsWith(p))) return false;
|
|
58
|
-
if (address.length < 26 || address.length >
|
|
58
|
+
if (address.length < 26 || address.length > 36) return false;
|
|
59
59
|
const base58Regex = /^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/;
|
|
60
60
|
return base58Regex.test(address);
|
|
61
61
|
}
|
|
62
62
|
var PAYLOAD_RULES = {
|
|
63
63
|
CLAIM: { format: "CLAIM:<name>:<ua>", checks: ["name", "ua"] },
|
|
64
64
|
BUY: { format: "BUY:<name>:<ua>", checks: ["name", "ua"] },
|
|
65
|
-
UPDATE: {
|
|
66
|
-
|
|
65
|
+
UPDATE: {
|
|
66
|
+
format: "UPDATE:<name>:<ua>:<nonce>",
|
|
67
|
+
checks: ["name", "ua", "nonce"]
|
|
68
|
+
},
|
|
69
|
+
LIST: {
|
|
70
|
+
format: "LIST:<name>:<price>:<pay_taddr>:<nonce>",
|
|
71
|
+
checks: ["name", "price", "pay_taddr", "nonce"]
|
|
72
|
+
},
|
|
67
73
|
DELIST: { format: "DELIST:<name>:<nonce>", checks: ["name", "nonce"] },
|
|
68
74
|
RELEASE: { format: "RELEASE:<name>:<nonce>", checks: ["name", "nonce"] }
|
|
69
75
|
};
|
|
@@ -98,12 +104,13 @@ var ZNS = class {
|
|
|
98
104
|
* Accepts both mainnet ('u') and testnet ('utest') prefixes.
|
|
99
105
|
* Performs basic format validation but NOT full bech32m checksum verification.
|
|
100
106
|
* Returns true if the address looks like a unified address, false otherwise.
|
|
101
|
-
*
|
|
107
|
+
*
|
|
102
108
|
* @todo(F4Jumble) Upgrade to full ZIP-316 decoding with F4Jumble to:
|
|
103
109
|
* - Parse actual typecodes from address items
|
|
104
110
|
* - Validate F4Jumble checksum (not just bech32m)
|
|
105
111
|
* - Optionally enforce: address must contain at least one Orchard receiver (typecode 0x03)
|
|
106
112
|
* Requires @noble/hashes (blake2b) implementation of F4Jumble inverse. */
|
|
113
|
+
this.isValidName = isValidName;
|
|
107
114
|
this.isValidUnifiedAddress = isValidUnifiedAddress;
|
|
108
115
|
this.isValidTransparentAddress = isValidTransparentAddress;
|
|
109
116
|
this.network = options?.network ?? "testnet";
|
|
@@ -137,7 +144,9 @@ var ZNS = class {
|
|
|
137
144
|
}
|
|
138
145
|
/** Resolve a ZNS name to its registration. Returns null if not registered. */
|
|
139
146
|
async resolveName(name) {
|
|
140
|
-
const raw = await this.rpc("resolve", {
|
|
147
|
+
const raw = await this.rpc("resolve", {
|
|
148
|
+
query: name
|
|
149
|
+
});
|
|
141
150
|
return raw ? normalizeApiResponse(raw) : null;
|
|
142
151
|
}
|
|
143
152
|
/** Resolve a Zcash Unified Address to all names pointing to it. Returns empty array if none.
|
|
@@ -208,6 +217,26 @@ var ZNS = class {
|
|
|
208
217
|
if (!payload) return false;
|
|
209
218
|
return this.verifyEd25519(payload, reg.signature, pubkey);
|
|
210
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Verify a sovereign Ed25519 signature before sending a transaction.
|
|
222
|
+
* Call this after signing but before calling `complete()` to catch invalid signatures early.
|
|
223
|
+
*
|
|
224
|
+
* @param payload The signing payload string (e.g. `CLAIM:foo:u1abc`)
|
|
225
|
+
* @param signature The Ed25519 signature (base64)
|
|
226
|
+
* @param pubkey The Ed25519 public key (base64)
|
|
227
|
+
* @returns true if the signature is valid for the given payload and pubkey
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```ts
|
|
231
|
+
* const claim = zns.prepareClaim(name, address, cost);
|
|
232
|
+
* const isValid = await zns.verifySoverignSignature(claim.payload, signature, userPubkey);
|
|
233
|
+
* if (!isValid) throw new Error("Invalid signature");
|
|
234
|
+
* const { memo, uri } = claim.complete(signature, userPubkey);
|
|
235
|
+
* ```
|
|
236
|
+
*/
|
|
237
|
+
async verifySoverignSignature(payload, signature, pubkey) {
|
|
238
|
+
return this.verifyEd25519(payload, signature, pubkey);
|
|
239
|
+
}
|
|
211
240
|
/**
|
|
212
241
|
* Validate a signing payload string against the ZNS memo format spec.
|
|
213
242
|
*
|
|
@@ -260,7 +289,11 @@ var ZNS = class {
|
|
|
260
289
|
}
|
|
261
290
|
const rule = PAYLOAD_RULES[action];
|
|
262
291
|
if (parts.length !== rule.checks.length)
|
|
263
|
-
return buildValidationResult(
|
|
292
|
+
return buildValidationResult(
|
|
293
|
+
"invalid",
|
|
294
|
+
action,
|
|
295
|
+
`Expected ${rule.format}.`
|
|
296
|
+
);
|
|
264
297
|
for (let i = 0; i < rule.checks.length; i++) {
|
|
265
298
|
const err = validateField(parts[i], rule.checks[i]);
|
|
266
299
|
if (err) return buildValidationResult("invalid", action, err);
|
|
@@ -333,7 +366,10 @@ var ZNS = class {
|
|
|
333
366
|
payload: `LIST:${name}:${price}:${payTaddr}:${nonce}`,
|
|
334
367
|
complete: (signature, userPubkey) => {
|
|
335
368
|
const memo = userPubkey ? `ZNS:LIST:${name}:${price}:${payTaddr}:${nonce}:${signature}:${userPubkey}` : `ZNS:LIST:${name}:${price}:${payTaddr}:${nonce}:${signature}`;
|
|
336
|
-
return {
|
|
369
|
+
return {
|
|
370
|
+
memo,
|
|
371
|
+
uri: this.buildZcashUri(this.registryAddress, LIST_COMMISSION, memo)
|
|
372
|
+
};
|
|
337
373
|
}
|
|
338
374
|
};
|
|
339
375
|
}
|
|
@@ -345,7 +381,10 @@ var ZNS = class {
|
|
|
345
381
|
payload: `DELIST:${name}:${nonce}`,
|
|
346
382
|
complete: (signature, userPubkey) => {
|
|
347
383
|
const memo = userPubkey ? `ZNS:DELIST:${name}:${nonce}:${signature}:${userPubkey}` : `ZNS:DELIST:${name}:${nonce}:${signature}`;
|
|
348
|
-
return {
|
|
384
|
+
return {
|
|
385
|
+
memo,
|
|
386
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
387
|
+
};
|
|
349
388
|
}
|
|
350
389
|
};
|
|
351
390
|
}
|
|
@@ -361,7 +400,10 @@ var ZNS = class {
|
|
|
361
400
|
payload: `UPDATE:${name}:${newAddress}:${nonce}`,
|
|
362
401
|
complete: (signature, userPubkey) => {
|
|
363
402
|
const memo = userPubkey ? `ZNS:UPDATE:${name}:${newAddress}:${nonce}:${signature}:${userPubkey}` : `ZNS:UPDATE:${name}:${newAddress}:${nonce}:${signature}`;
|
|
364
|
-
return {
|
|
403
|
+
return {
|
|
404
|
+
memo,
|
|
405
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
406
|
+
};
|
|
365
407
|
}
|
|
366
408
|
};
|
|
367
409
|
}
|
|
@@ -377,7 +419,10 @@ var ZNS = class {
|
|
|
377
419
|
payload: `BUY:${name}:${buyerAddress}`,
|
|
378
420
|
complete: (signature, userPubkey) => {
|
|
379
421
|
const memo = userPubkey ? `ZNS:BUY:${name}:${buyerAddress}:${price}:${signature}:${userPubkey}` : `ZNS:BUY:${name}:${buyerAddress}:${price}:${signature}`;
|
|
380
|
-
return {
|
|
422
|
+
return {
|
|
423
|
+
memo,
|
|
424
|
+
uri: this.buildZcashUri(this.registryAddress, BUY_COMMISSION, memo)
|
|
425
|
+
};
|
|
381
426
|
}
|
|
382
427
|
};
|
|
383
428
|
}
|
|
@@ -389,7 +434,10 @@ var ZNS = class {
|
|
|
389
434
|
payload: `RELEASE:${name}:${nonce}`,
|
|
390
435
|
complete: (signature, userPubkey) => {
|
|
391
436
|
const memo = userPubkey ? `ZNS:RELEASE:${name}:${nonce}:${signature}:${userPubkey}` : `ZNS:RELEASE:${name}:${nonce}:${signature}`;
|
|
392
|
-
return {
|
|
437
|
+
return {
|
|
438
|
+
memo,
|
|
439
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
440
|
+
};
|
|
393
441
|
}
|
|
394
442
|
};
|
|
395
443
|
}
|
|
@@ -400,7 +448,10 @@ var ZNS = class {
|
|
|
400
448
|
payload: `SETPRICE:${prices.length}:${prices.join(":")}:${nonce}`,
|
|
401
449
|
complete: (signature) => {
|
|
402
450
|
const memo = `ZNS:SETPRICE:${prices.length}:${prices.join(":")}:${nonce}:${signature}`;
|
|
403
|
-
return {
|
|
451
|
+
return {
|
|
452
|
+
memo,
|
|
453
|
+
uri: this.buildZcashUri(this.registryAddress, void 0, memo)
|
|
454
|
+
};
|
|
404
455
|
}
|
|
405
456
|
};
|
|
406
457
|
}
|
|
@@ -496,7 +547,6 @@ var ZNS = class {
|
|
|
496
547
|
};
|
|
497
548
|
export {
|
|
498
549
|
BUY_COMMISSION,
|
|
499
|
-
DEFAULT_URL,
|
|
500
550
|
LIST_COMMISSION,
|
|
501
551
|
NETWORKS,
|
|
502
552
|
ZNS
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zcashname-sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "TypeScript SDK for the Zcash Name System (ZNS).",
|
|
6
6
|
"main": "dist/zns.cjs",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"bech32": "^2.0.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
+
"@noble/hashes": "^2.2.0",
|
|
36
37
|
"tsup": "^8.0.0",
|
|
37
38
|
"typescript": "^5.4.0",
|
|
38
39
|
"vitest": "^2.0.0"
|