namehash.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { keccak256 } from "../crypto/index.js";
  2. import { concat, hexlify, assertArgument, toUtf8Bytes } from "../utils/index.js";
  3. import { ens_normalize } from "@adraffy/ens-normalize";
  4. const Zeros = new Uint8Array(32);
  5. Zeros.fill(0);
  6. function checkComponent(comp) {
  7. assertArgument(comp.length !== 0, "invalid ENS name; empty component", "comp", comp);
  8. return comp;
  9. }
  10. function ensNameSplit(name) {
  11. const bytes = toUtf8Bytes(ensNormalize(name));
  12. const comps = [];
  13. if (name.length === 0) {
  14. return comps;
  15. }
  16. let last = 0;
  17. for (let i = 0; i < bytes.length; i++) {
  18. const d = bytes[i];
  19. // A separator (i.e. "."); copy this component
  20. if (d === 0x2e) {
  21. comps.push(checkComponent(bytes.slice(last, i)));
  22. last = i + 1;
  23. }
  24. }
  25. // There was a stray separator at the end of the name
  26. assertArgument(last < bytes.length, "invalid ENS name; empty component", "name", name);
  27. comps.push(checkComponent(bytes.slice(last)));
  28. return comps;
  29. }
  30. /**
  31. * Returns the ENS %%name%% normalized.
  32. */
  33. export function ensNormalize(name) {
  34. try {
  35. if (name.length === 0) {
  36. throw new Error("empty label");
  37. }
  38. return ens_normalize(name);
  39. }
  40. catch (error) {
  41. assertArgument(false, `invalid ENS name (${error.message})`, "name", name);
  42. }
  43. }
  44. /**
  45. * Returns ``true`` if %%name%% is a valid ENS name.
  46. */
  47. export function isValidName(name) {
  48. try {
  49. return (ensNameSplit(name).length !== 0);
  50. }
  51. catch (error) { }
  52. return false;
  53. }
  54. /**
  55. * Returns the [[link-namehash]] for %%name%%.
  56. */
  57. export function namehash(name) {
  58. assertArgument(typeof (name) === "string", "invalid ENS name; not a string", "name", name);
  59. assertArgument(name.length, `invalid ENS name (empty label)`, "name", name);
  60. let result = Zeros;
  61. const comps = ensNameSplit(name);
  62. while (comps.length) {
  63. result = keccak256(concat([result, keccak256((comps.pop()))]));
  64. }
  65. return hexlify(result);
  66. }
  67. /**
  68. * Returns the DNS encoded %%name%%.
  69. *
  70. * This is used for various parts of ENS name resolution, such
  71. * as the wildcard resolution.
  72. */
  73. export function dnsEncode(name, _maxLength) {
  74. const length = (_maxLength != null) ? _maxLength : 63;
  75. assertArgument(length <= 255, "DNS encoded label cannot exceed 255", "length", length);
  76. return hexlify(concat(ensNameSplit(name).map((comp) => {
  77. assertArgument(comp.length <= length, `label ${JSON.stringify(name)} exceeds ${length} bytes`, "name", name);
  78. const bytes = new Uint8Array(comp.length + 1);
  79. bytes.set(comp, 1);
  80. bytes[0] = bytes.length - 1;
  81. return bytes;
  82. }))) + "00";
  83. }
  84. //# sourceMappingURL=namehash.js.map