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 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: "utest1hzw7wyadutvzfgpna80yftsk5l7jeyu2p5me5quvp28tytxueta00cx4068wnlzcv7tx9n3t3gfhsy83pe4y6jrhxtzaq0hj6xtg5zrk2dn7zen3vns2a5pgs4fxdjlletmqrhfa42"
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: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9"
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)) return obj.map((item) => normalizeApiResponse(item));
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 > 35) return false;
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: { format: "UPDATE:<name>:<ua>:<nonce>", checks: ["name", "ua", "nonce"] },
104
- LIST: { format: "LIST:<name>:<price>:<pay_taddr>:<nonce>", checks: ["name", "price", "pay_taddr", "nonce"] },
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", { query: name });
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("invalid", action, `Expected ${rule.format}.`);
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 { memo, uri: this.buildZcashUri(this.registryAddress, LIST_COMMISSION, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, void 0, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, void 0, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, BUY_COMMISSION, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, void 0, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, void 0, memo) };
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: "utest1hzw7wyadutvzfgpna80yftsk5l7jeyu2p5me5quvp28tytxueta00cx4068wnlzcv7tx9n3t3gfhsy83pe4y6jrhxtzaq0hj6xtg5zrk2dn7zen3vns2a5pgs4fxdjlletmqrhfa42";
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: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9";
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, DEFAULT_URL, LIST_COMMISSION, NETWORKS, ZNS };
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: "utest1hzw7wyadutvzfgpna80yftsk5l7jeyu2p5me5quvp28tytxueta00cx4068wnlzcv7tx9n3t3gfhsy83pe4y6jrhxtzaq0hj6xtg5zrk2dn7zen3vns2a5pgs4fxdjlletmqrhfa42";
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: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9";
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, DEFAULT_URL, LIST_COMMISSION, NETWORKS, ZNS };
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: "utest1hzw7wyadutvzfgpna80yftsk5l7jeyu2p5me5quvp28tytxueta00cx4068wnlzcv7tx9n3t3gfhsy83pe4y6jrhxtzaq0hj6xtg5zrk2dn7zen3vns2a5pgs4fxdjlletmqrhfa42"
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: "u1k0evt0ahj5qdt6y9ftsxndl8lrkm4ff6rp00u04cjpmqj6hxl9t8hfsxftmn3ht34e03lljh89czn2h8qn67rwrs8x0hm3lsxsucp9q9"
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)) return obj.map((item) => normalizeApiResponse(item));
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 > 35) return false;
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: { format: "UPDATE:<name>:<ua>:<nonce>", checks: ["name", "ua", "nonce"] },
66
- LIST: { format: "LIST:<name>:<price>:<pay_taddr>:<nonce>", checks: ["name", "price", "pay_taddr", "nonce"] },
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", { query: name });
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("invalid", action, `Expected ${rule.format}.`);
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 { memo, uri: this.buildZcashUri(this.registryAddress, LIST_COMMISSION, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, void 0, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, void 0, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, BUY_COMMISSION, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, void 0, memo) };
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 { memo, uri: this.buildZcashUri(this.registryAddress, void 0, memo) };
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.5",
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"