@ensdomains/ensjs 3.0.0-alpha.1 → 3.0.0-alpha.10

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.
Files changed (147) hide show
  1. package/README.md +2 -0
  2. package/dist/cjs/GqlManager.d.ts +3 -0
  3. package/dist/cjs/GqlManager.js +62 -2
  4. package/dist/cjs/functions/burnFuses.d.ts +3 -2
  5. package/dist/cjs/functions/burnFuses.js +4 -8
  6. package/dist/cjs/functions/createSubname.d.ts +1 -5
  7. package/dist/cjs/functions/createSubname.js +5 -8
  8. package/dist/cjs/functions/deleteSubname.d.ts +3 -3
  9. package/dist/cjs/functions/deleteSubname.js +5 -2
  10. package/dist/cjs/functions/getDNSOwner.d.ts +7 -0
  11. package/dist/cjs/functions/getDNSOwner.js +81 -0
  12. package/dist/cjs/functions/getFuses.js +3 -2
  13. package/dist/cjs/functions/getOwner.js +7 -6
  14. package/dist/cjs/functions/getProfile.d.ts +4 -1
  15. package/dist/cjs/functions/getProfile.js +102 -24
  16. package/dist/cjs/functions/getRecords.d.ts +1 -0
  17. package/dist/cjs/functions/getSpecificRecord.js +22 -5
  18. package/dist/cjs/functions/getSubnames.js +6 -6
  19. package/dist/cjs/functions/setName.d.ts +4 -3
  20. package/dist/cjs/functions/setName.js +5 -10
  21. package/dist/cjs/functions/setRecord.d.ts +18 -0
  22. package/dist/cjs/functions/setRecord.js +27 -0
  23. package/dist/cjs/functions/setRecords.d.ts +4 -2
  24. package/dist/cjs/functions/setRecords.js +14 -12
  25. package/dist/cjs/functions/setResolver.d.ts +4 -4
  26. package/dist/cjs/functions/setResolver.js +6 -12
  27. package/dist/cjs/functions/transferName.d.ts +4 -3
  28. package/dist/cjs/functions/transferName.js +9 -13
  29. package/dist/cjs/functions/transferSubname.d.ts +4 -3
  30. package/dist/cjs/functions/transferSubname.js +5 -8
  31. package/dist/cjs/functions/unwrapName.d.ts +4 -3
  32. package/dist/cjs/functions/unwrapName.js +5 -9
  33. package/dist/cjs/functions/wrapName.d.ts +5 -3
  34. package/dist/cjs/functions/wrapName.js +8 -12
  35. package/dist/cjs/index.d.ts +48 -46
  36. package/dist/cjs/index.js +43 -19
  37. package/dist/cjs/utils/labels.js +5 -4
  38. package/dist/cjs/utils/makeHashIndexes.js +2 -2
  39. package/dist/cjs/utils/normalise.d.ts +1 -0
  40. package/dist/cjs/utils/normalise.js +27 -1
  41. package/dist/cjs/utils/recordHelpers.d.ts +3 -0
  42. package/dist/cjs/utils/recordHelpers.js +42 -15
  43. package/dist/cjs/utils/registerHelpers.js +3 -4
  44. package/dist/cjs/utils/writeTx.d.ts +4 -0
  45. package/dist/cjs/utils/writeTx.js +3 -0
  46. package/dist/esm/GqlManager.d.ts +3 -0
  47. package/dist/esm/GqlManager.js +58 -2
  48. package/dist/esm/functions/burnFuses.d.ts +3 -2
  49. package/dist/esm/functions/burnFuses.js +4 -8
  50. package/dist/esm/functions/createSubname.d.ts +1 -5
  51. package/dist/esm/functions/createSubname.js +5 -8
  52. package/dist/esm/functions/deleteSubname.d.ts +3 -3
  53. package/dist/esm/functions/deleteSubname.js +5 -2
  54. package/dist/esm/functions/getDNSOwner.d.ts +7 -0
  55. package/dist/esm/functions/getDNSOwner.js +51 -0
  56. package/dist/esm/functions/getFuses.js +4 -3
  57. package/dist/esm/functions/getOwner.js +7 -6
  58. package/dist/esm/functions/getProfile.d.ts +4 -1
  59. package/dist/esm/functions/getProfile.js +102 -24
  60. package/dist/esm/functions/getRecords.d.ts +1 -0
  61. package/dist/esm/functions/getSpecificRecord.js +22 -5
  62. package/dist/esm/functions/getSubnames.js +3 -3
  63. package/dist/esm/functions/setName.d.ts +4 -3
  64. package/dist/esm/functions/setName.js +5 -10
  65. package/dist/esm/functions/setRecord.d.ts +18 -0
  66. package/dist/esm/functions/setRecord.js +24 -0
  67. package/dist/esm/functions/setRecords.d.ts +4 -2
  68. package/dist/esm/functions/setRecords.js +14 -12
  69. package/dist/esm/functions/setResolver.d.ts +4 -4
  70. package/dist/esm/functions/setResolver.js +6 -12
  71. package/dist/esm/functions/transferName.d.ts +4 -3
  72. package/dist/esm/functions/transferName.js +9 -13
  73. package/dist/esm/functions/transferSubname.d.ts +4 -3
  74. package/dist/esm/functions/transferSubname.js +5 -8
  75. package/dist/esm/functions/unwrapName.d.ts +4 -3
  76. package/dist/esm/functions/unwrapName.js +5 -9
  77. package/dist/esm/functions/wrapName.d.ts +5 -3
  78. package/dist/esm/functions/wrapName.js +8 -12
  79. package/dist/esm/index.d.ts +48 -46
  80. package/dist/esm/index.js +43 -19
  81. package/dist/esm/utils/labels.js +5 -4
  82. package/dist/esm/utils/makeHashIndexes.js +2 -2
  83. package/dist/esm/utils/normalise.d.ts +1 -0
  84. package/dist/esm/utils/normalise.js +25 -0
  85. package/dist/esm/utils/recordHelpers.d.ts +3 -0
  86. package/dist/esm/utils/recordHelpers.js +40 -14
  87. package/dist/esm/utils/registerHelpers.js +3 -4
  88. package/dist/esm/utils/writeTx.d.ts +4 -0
  89. package/dist/esm/utils/writeTx.js +1 -0
  90. package/package.json +15 -7
  91. package/src/@types/dns-packet/index.d.ts +114 -0
  92. package/src/GqlManager.test.ts +170 -0
  93. package/src/GqlManager.ts +67 -2
  94. package/src/{tests → functions}/batch.test.ts +1 -1
  95. package/src/{tests → functions}/batchWrappers.test.ts +1 -1
  96. package/src/{tests → functions}/burnFuses.test.ts +12 -10
  97. package/src/functions/burnFuses.ts +9 -11
  98. package/src/{tests → functions}/createSubname.test.ts +12 -16
  99. package/src/functions/createSubname.ts +7 -13
  100. package/src/{tests → functions}/deleteSubname.test.ts +32 -32
  101. package/src/functions/deleteSubname.ts +9 -12
  102. package/src/functions/getDNSOwner.test.ts +122 -0
  103. package/src/functions/getDNSOwner.ts +61 -0
  104. package/src/{tests → functions}/getExpiry.test.ts +1 -1
  105. package/src/{tests → functions}/getFuses.test.ts +12 -10
  106. package/src/functions/getFuses.ts +4 -3
  107. package/src/{tests → functions}/getHistory.test.ts +1 -1
  108. package/src/{tests → functions}/getName.test.ts +1 -1
  109. package/src/{tests → functions}/getNames.test.ts +1 -1
  110. package/src/{tests → functions}/getOwner.test.ts +14 -2
  111. package/src/functions/getOwner.ts +7 -7
  112. package/src/{tests → functions}/getProfile.test.ts +45 -12
  113. package/src/functions/getProfile.ts +151 -24
  114. package/src/functions/getRecords.ts +1 -0
  115. package/src/{tests → functions}/getResolver.test.ts +1 -1
  116. package/src/{tests → functions}/getSpecificRecord.test.ts +1 -1
  117. package/src/functions/getSpecificRecord.ts +28 -8
  118. package/src/{tests → functions}/getSubnames.test.ts +1 -1
  119. package/src/functions/getSubnames.ts +68 -66
  120. package/src/{tests → functions}/makeCommitment.test.ts +1 -1
  121. package/src/functions/normalise.test.ts +22 -0
  122. package/src/{tests → functions}/setName.test.ts +3 -2
  123. package/src/functions/setName.ts +15 -17
  124. package/src/functions/setRecord.test.ts +100 -0
  125. package/src/functions/setRecord.ts +63 -0
  126. package/src/{tests → functions}/setRecords.test.ts +12 -10
  127. package/src/functions/setRecords.ts +22 -16
  128. package/src/{tests → functions}/setResolver.test.ts +12 -15
  129. package/src/functions/setResolver.ts +15 -20
  130. package/src/{tests → functions}/transferName.test.ts +30 -31
  131. package/src/functions/transferName.ts +19 -22
  132. package/src/{tests → functions}/transferSubname.test.ts +34 -34
  133. package/src/functions/transferSubname.ts +21 -13
  134. package/src/{tests → functions}/unwrapName.test.ts +24 -23
  135. package/src/functions/unwrapName.ts +20 -15
  136. package/src/{tests → functions}/wrapName.test.ts +19 -19
  137. package/src/functions/wrapName.ts +20 -22
  138. package/src/index.ts +115 -26
  139. package/src/tests/populateTransaction.test.ts +40 -0
  140. package/src/tests/signerInjection.test.ts +46 -0
  141. package/src/tests/withProvider.test.ts +1 -1
  142. package/src/utils/labels.ts +6 -4
  143. package/src/utils/makeHashIndexes.ts +4 -4
  144. package/src/utils/normalise.ts +29 -0
  145. package/src/utils/recordHelpers.ts +52 -18
  146. package/src/utils/registerHelpers.ts +3 -4
  147. package/src/utils/writeTx.ts +6 -0
package/dist/cjs/index.js CHANGED
@@ -31,6 +31,7 @@ const contracts_1 = __importDefault(require("./contracts"));
31
31
  const getContractAddress_1 = require("./contracts/getContractAddress");
32
32
  const GqlManager_1 = __importDefault(require("./GqlManager"));
33
33
  const singleCall_1 = __importDefault(require("./utils/singleCall"));
34
+ const writeTx_1 = __importDefault(require("./utils/writeTx"));
34
35
  const graphURIEndpoints = {
35
36
  1: 'https://api.thegraph.com/subgraphs/name/ensdomains/ens',
36
37
  3: 'https://api.thegraph.com/subgraphs/name/ensdomains/ensropsten',
@@ -89,15 +90,30 @@ class ENS {
89
90
  await thisRef.checkInitialProvider();
90
91
  // import the module dynamically
91
92
  const mod = await Promise.resolve().then(() => __importStar(require(
92
- /* webpackMode: "lazy", webpackChunkName: "[request]", webpackPreload: true */
93
+ /* webpackMode: "lazy", webpackChunkName: "[request]", webpackPreload: true, webpackExclude: /.*\.ts$/ */
93
94
  `./functions/${path}`)));
94
95
  // if combine isn't specified, run normally
95
96
  // otherwise, create a function from the raw and decode functions
96
97
  if (subFunc !== 'combine') {
98
+ const writeable = subFunc === 'write' || subFunc === 'populateTransaction';
97
99
  // get the function to call
98
- const func = subFunc ? mod[exportName][subFunc] : mod[exportName];
100
+ const func = subFunc && !writeable ? mod[exportName][subFunc] : mod[exportName];
99
101
  // get the dependencies to forward to the function as the first arg
100
- const dependenciesToForward = thisRef.forwardDependenciesFromArray(dependencies);
102
+ let dependenciesToForward = thisRef.forwardDependenciesFromArray(dependencies);
103
+ // if func is write func, inject signer into dependencies
104
+ if (writeable) {
105
+ const options = (args[1] || {});
106
+ const signer = options.signer ||
107
+ thisRef.provider?.getSigner(options.addressOrIndex);
108
+ const populate = subFunc === 'populateTransaction';
109
+ if (!signer) {
110
+ throw new Error('No signer specified');
111
+ }
112
+ delete options.addressOrIndex;
113
+ delete options.signer;
114
+ dependenciesToForward = { ...dependenciesToForward, signer };
115
+ return func(dependenciesToForward, args[0], options).then((0, writeTx_1.default)(signer, populate));
116
+ }
101
117
  // return the function with the dependencies forwarded
102
118
  return func(dependenciesToForward, ...args);
103
119
  }
@@ -114,6 +130,9 @@ class ENS {
114
130
  mainFunc.decode = this.importGenerator(path, dependencies, exportName, 'decode');
115
131
  mainFunc.batch = this.importGenerator(path, dependencies, exportName, 'batch', { raw: mainFunc.raw, decode: mainFunc.decode });
116
132
  }
133
+ else if (subFunc === 'write') {
134
+ mainFunc.populateTransaction = this.importGenerator(path, dependencies, exportName, 'populateTransaction');
135
+ }
117
136
  return mainFunc;
118
137
  };
119
138
  /**
@@ -124,6 +143,14 @@ class ENS {
124
143
  * @returns {OmitFirstArg} - The generated wrapped function
125
144
  */
126
145
  generateFunction = (path, dependencies, exportName = 'default') => this.importGenerator(path, dependencies, exportName);
146
+ /**
147
+ * Generates a write wrapped function
148
+ * @param {string} path - The path of the exported function
149
+ * @param {FunctionDeps} dependencies - An array of ENS properties
150
+ * @param {string} exportName - The export name of the target function
151
+ * @returns {OmitFirstArg} - The generated wrapped function
152
+ */
153
+ generateWriteFunction = (path, dependencies, exportName = 'default') => this.importGenerator(path, dependencies, exportName, 'write');
127
154
  /**
128
155
  * Generates a wrapped function from raw and decode exports
129
156
  * @param {string} path - The path of the exported function
@@ -166,6 +193,7 @@ class ENS {
166
193
  'gqlInstance',
167
194
  'getName',
168
195
  'resolverMulticallWrapper',
196
+ 'multicallWrapper',
169
197
  '_getAddr',
170
198
  '_getContentHash',
171
199
  '_getText',
@@ -193,31 +221,27 @@ class ENS {
193
221
  universalWrapper = this.generateRawFunction('initialGetters', ['contracts'], 'universalWrapper');
194
222
  resolverMulticallWrapper = this.generateRawFunction('initialGetters', ['contracts'], 'resolverMulticallWrapper');
195
223
  multicallWrapper = this.generateRawFunction('initialGetters', ['contracts'], 'multicallWrapper');
196
- setName = this.generateFunction('setName', [
224
+ setName = this.generateWriteFunction('setName', [
197
225
  'contracts',
198
- 'provider',
199
226
  ]);
200
- setRecords = this.generateFunction('setRecords', [
227
+ setRecords = this.generateWriteFunction('setRecords', ['contracts', 'provider', 'getResolver']);
228
+ setRecord = this.generateWriteFunction('setRecord', [
201
229
  'contracts',
202
230
  'provider',
203
231
  'getResolver',
204
232
  ]);
205
- setResolver = this.generateFunction('setResolver', ['contracts', 'provider']);
206
- transferName = this.generateFunction('transferName', ['contracts', 'provider']);
207
- wrapName = this.generateFunction('wrapName', [
233
+ setResolver = this.generateWriteFunction('setResolver', ['contracts']);
234
+ transferName = this.generateWriteFunction('transferName', ['contracts']);
235
+ wrapName = this.generateWriteFunction('wrapName', [
208
236
  'contracts',
209
- 'provider',
210
237
  ]);
211
- unwrapName = this.generateFunction('unwrapName', [
238
+ unwrapName = this.generateWriteFunction('unwrapName', ['contracts']);
239
+ burnFuses = this.generateWriteFunction('burnFuses', [
212
240
  'contracts',
213
- 'provider',
214
- ]);
215
- burnFuses = this.generateFunction('burnFuses', [
216
- 'contracts',
217
- 'provider',
218
241
  ]);
219
- createSubname = this.generateFunction('createSubname', ['contracts', 'provider']);
220
- deleteSubname = this.generateFunction('deleteSubname', ['contracts', 'provider', 'transferSubname']);
221
- transferSubname = this.generateFunction('transferSubname', ['contracts', 'provider']);
242
+ createSubname = this.generateWriteFunction('createSubname', ['contracts']);
243
+ deleteSubname = this.generateWriteFunction('deleteSubname', ['transferSubname']);
244
+ transferSubname = this.generateWriteFunction('transferSubname', ['contracts']);
245
+ getDNSOwner = this.generateFunction('getDNSOwner', []);
222
246
  }
223
247
  exports.ENS = ENS;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.checkLocalStorageSize = exports.truncateUndecryptedName = exports.decryptName = exports.checkIsDecrypted = exports.parseName = exports.encodeLabel = exports.checkLabel = exports.saveName = exports.saveLabel = exports.isEncodedLabelhash = exports.encodeLabelhash = exports.decodeLabelhash = exports.keccakFromString = exports.labelhash = void 0;
4
4
  const utils_1 = require("ethers/lib/utils");
5
5
  const format_1 = require("./format");
6
+ const hasLocalStorage = typeof localStorage !== 'undefined';
6
7
  const labelhash = (input) => (0, utils_1.solidityKeccak256)(['string'], [input]);
7
8
  exports.labelhash = labelhash;
8
9
  const keccakFromString = (input) => (0, exports.labelhash)(input);
@@ -14,7 +15,7 @@ function decodeLabelhash(hash) {
14
15
  if (hash.length !== 66) {
15
16
  throw Error('Expected encoded labelhash to have a length of 66');
16
17
  }
17
- return `${hash.slice(1, -1)}`;
18
+ return `0x${hash.slice(1, -1)}`;
18
19
  }
19
20
  exports.decodeLabelhash = decodeLabelhash;
20
21
  function encodeLabelhash(hash) {
@@ -32,12 +33,12 @@ function isEncodedLabelhash(hash) {
32
33
  }
33
34
  exports.isEncodedLabelhash = isEncodedLabelhash;
34
35
  function getLabels() {
35
- return localStorage
36
+ return hasLocalStorage
36
37
  ? JSON.parse(localStorage.getItem('ensjs:labels')) || {}
37
38
  : {};
38
39
  }
39
40
  function _saveLabel(hash, label) {
40
- if (!localStorage)
41
+ if (!hasLocalStorage)
41
42
  return hash;
42
43
  const labels = getLabels();
43
44
  localStorage.setItem('ensjs:labels', JSON.stringify({
@@ -97,7 +98,7 @@ exports.decryptName = decryptName;
97
98
  const truncateUndecryptedName = (name) => (0, format_1.truncateFormat)(name);
98
99
  exports.truncateUndecryptedName = truncateUndecryptedName;
99
100
  function checkLocalStorageSize() {
100
- if (!localStorage)
101
+ if (!hasLocalStorage)
101
102
  return 'Empty (0 KB)';
102
103
  let allStrings = '';
103
104
  for (const key in window.localStorage) {
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.makeNamehashIndexes = exports.makeOtherIndexes = void 0;
4
- const ethers_1 = require("ethers");
4
+ const normalise_1 = require("./normalise");
5
5
  const makeOtherIndexes = (data, findStr) => Array.from(data.matchAll(findStr)).map((x) => x.index / 2 - 1);
6
6
  exports.makeOtherIndexes = makeOtherIndexes;
7
- const makeNamehashIndexes = (data, name) => Array.from(data.matchAll(ethers_1.ethers.utils.namehash(name).substring(2))).map((x) => x.index / 2 - 1);
7
+ const makeNamehashIndexes = (data, name) => Array.from(data.matchAll((0, normalise_1.namehash)(name).substring(2))).map((x) => x.index / 2 - 1);
8
8
  exports.makeNamehashIndexes = makeNamehashIndexes;
@@ -1 +1,2 @@
1
1
  export declare const normalise: (name: string) => any;
2
+ export declare const namehash: (name: string) => string;
@@ -3,7 +3,33 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.normalise = void 0;
6
+ exports.namehash = exports.normalise = void 0;
7
+ const utils_1 = require("ethers/lib/utils");
7
8
  const uts46bundle_js_1 = __importDefault(require("idna-uts46-hx/uts46bundle.js"));
9
+ const labels_1 = require("./labels");
10
+ const zeros = new Uint8Array(32);
11
+ zeros.fill(0);
8
12
  const normalise = (name) => name ? uts46bundle_js_1.default.toUnicode(name, { useStd3ASCII: true }) : name;
9
13
  exports.normalise = normalise;
14
+ const namehash = (name) => {
15
+ let result = zeros;
16
+ if (name) {
17
+ const labels = name.split('.');
18
+ for (var i = labels.length - 1; i >= 0; i--) {
19
+ let labelSha;
20
+ if ((0, labels_1.isEncodedLabelhash)(labels[i])) {
21
+ labelSha = (0, labels_1.decodeLabelhash)(labels[i]);
22
+ }
23
+ else {
24
+ const normalised = (0, exports.normalise)(labels[i]);
25
+ labelSha = (0, utils_1.keccak256)((0, utils_1.toUtf8Bytes)(normalised));
26
+ }
27
+ result = (0, utils_1.keccak256)((0, utils_1.concat)([result, labelSha]));
28
+ }
29
+ }
30
+ else {
31
+ result = (0, utils_1.hexlify)(zeros);
32
+ }
33
+ return result;
34
+ };
35
+ exports.namehash = namehash;
@@ -9,5 +9,8 @@ export declare type RecordOptions = {
9
9
  coinTypes?: RecordItem[];
10
10
  };
11
11
  export declare const generateSetAddr: (namehash: string, coinType: string, address: string, resolver: PublicResolver) => string;
12
+ export declare type RecordTypes = 'contentHash' | 'text' | 'addr';
13
+ export declare type RecordInput<T extends RecordTypes> = T extends 'contentHash' ? string : RecordItem;
14
+ export declare function generateSingleRecordCall<T extends RecordTypes>(namehash: string, resolver: PublicResolver, type: T): (record: RecordInput<T>) => string;
12
15
  export declare const generateRecordCallArray: (namehash: string, records: RecordOptions, resolver: PublicResolver) => string[];
13
16
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateRecordCallArray = exports.generateSetAddr = void 0;
3
+ exports.generateRecordCallArray = exports.generateSingleRecordCall = exports.generateSetAddr = void 0;
4
4
  const address_encoder_1 = require("@ensdomains/address-encoder");
5
5
  const contentHash_1 = require("./contentHash");
6
6
  const generateSetAddr = (namehash, coinType, address, resolver) => {
@@ -16,28 +16,55 @@ const generateSetAddr = (namehash, coinType, address, resolver) => {
16
16
  return resolver?.interface.encodeFunctionData('setAddr(bytes32,uint256,bytes)', [namehash, inputCoinType, encodedAddress]);
17
17
  };
18
18
  exports.generateSetAddr = generateSetAddr;
19
+ function generateSingleRecordCall(namehash, resolver, type) {
20
+ if (type === 'contentHash') {
21
+ return (_r) => {
22
+ const record = _r;
23
+ let _contentHash = '';
24
+ if (record !== _contentHash) {
25
+ const encoded = (0, contentHash_1.encodeContenthash)(record);
26
+ if (encoded.error)
27
+ throw new Error(encoded.error);
28
+ _contentHash = encoded.encoded;
29
+ }
30
+ return resolver.interface.encodeFunctionData('setContenthash', [
31
+ namehash,
32
+ _contentHash,
33
+ ]);
34
+ };
35
+ }
36
+ else {
37
+ return (_r) => {
38
+ const record = _r;
39
+ if (type === 'text') {
40
+ return resolver.interface.encodeFunctionData('setText', [
41
+ namehash,
42
+ record.key,
43
+ record.value,
44
+ ]);
45
+ }
46
+ else {
47
+ return (0, exports.generateSetAddr)(namehash, record.key, record.value, resolver);
48
+ }
49
+ };
50
+ }
51
+ }
52
+ exports.generateSingleRecordCall = generateSingleRecordCall;
19
53
  const generateRecordCallArray = (namehash, records, resolver) => {
20
54
  const calls = [];
21
55
  if (records.contentHash) {
22
- const contentHash = records.contentHash === '' ? '' : (0, contentHash_1.encodeContenthash)(records.contentHash);
23
- const data = resolver?.interface.encodeFunctionData('setContenthash', [namehash, contentHash]);
56
+ const data = generateSingleRecordCall(namehash, resolver, 'contentHash')(records.contentHash);
24
57
  data && calls.push(data);
25
58
  }
26
59
  if (records.texts && records.texts.length > 0) {
27
- records.texts.forEach(({ key, value }) => {
28
- const data = resolver?.interface.encodeFunctionData('setText', [
29
- namehash,
30
- key,
31
- value,
32
- ]);
33
- data && calls.push(data);
34
- });
60
+ records.texts
61
+ .map(generateSingleRecordCall(namehash, resolver, 'text'))
62
+ .forEach((call) => calls.push(call));
35
63
  }
36
64
  if (records.coinTypes && records.coinTypes.length > 0) {
37
- records.coinTypes.forEach(({ key, value }) => {
38
- const data = (0, exports.generateSetAddr)(namehash, key, value, resolver);
39
- data && calls.push(data);
40
- });
65
+ records.coinTypes
66
+ .map(generateSingleRecordCall(namehash, resolver, 'addr'))
67
+ .forEach((call) => calls.push(call));
41
68
  }
42
69
  return calls;
43
70
  };
@@ -7,6 +7,7 @@ exports._makeCommitment = exports.makeCommitment = exports.randomSecret = void 0
7
7
  const ethers_1 = require("ethers");
8
8
  const generateFuseInput_1 = __importDefault(require("./generateFuseInput"));
9
9
  const labels_1 = require("./labels");
10
+ const normalise_1 = require("./normalise");
10
11
  const recordHelpers_1 = require("./recordHelpers");
11
12
  const randomSecret = () => {
12
13
  const bytes = Buffer.allocUnsafe(32);
@@ -15,11 +16,9 @@ const randomSecret = () => {
15
16
  exports.randomSecret = randomSecret;
16
17
  const makeCommitment = ({ name, owner, duration, resolver, records, reverseRecord, fuses, }) => {
17
18
  const label = (0, labels_1.labelhash)(name.split('.')[0]);
18
- const namehash = ethers_1.utils.namehash(name);
19
+ const hash = (0, normalise_1.namehash)(name);
19
20
  const resolverAddress = resolver.address;
20
- const data = records
21
- ? (0, recordHelpers_1.generateRecordCallArray)(namehash, records, resolver)
22
- : [];
21
+ const data = records ? (0, recordHelpers_1.generateRecordCallArray)(hash, records, resolver) : [];
23
22
  const secret = (0, exports.randomSecret)();
24
23
  const fuseData = fuses ? (0, generateFuseInput_1.default)(fuses) : '0';
25
24
  const commitment = (0, exports._makeCommitment)({
@@ -0,0 +1,4 @@
1
+ import { JsonRpcSigner } from '@ethersproject/providers';
2
+ import type { PopulatedTransaction } from 'ethers';
3
+ declare const _default: (signer: JsonRpcSigner, populate: boolean) => (tx: PopulatedTransaction) => PopulatedTransaction | Promise<import("@ethersproject/abstract-provider").TransactionResponse>;
4
+ export default _default;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = (signer, populate) => (tx) => populate ? tx : signer.sendTransaction(tx);
@@ -1,3 +1,6 @@
1
+ export declare const enter: (node: any) => any;
2
+ export declare const requestMiddleware: (visit: any, parse: any) => (request: any) => any;
3
+ export declare const responseMiddleware: (traverse: any) => (response: any) => any;
1
4
  export default class GqlManager {
2
5
  gql: any;
3
6
  client?: any | null;
@@ -1,11 +1,67 @@
1
+ // @ts-nocheck
2
+ import { namehash } from './utils/normalise';
3
+ const generateSelection = (selection) => ({
4
+ kind: 'Field',
5
+ name: {
6
+ kind: 'Name',
7
+ value: selection,
8
+ },
9
+ arguments: [],
10
+ directives: [],
11
+ alias: undefined,
12
+ selectionSet: undefined,
13
+ });
14
+ export const enter = (node) => {
15
+ if (node.kind === 'SelectionSet') {
16
+ const id = node.selections.find((x) => x.name && x.name.value === 'id');
17
+ const name = node.selections.find((x) => x.name && x.name.value === 'name');
18
+ if (!id && name) {
19
+ node.selections = [...node.selections, generateSelection('id')];
20
+ return node;
21
+ }
22
+ }
23
+ };
24
+ export const requestMiddleware = (visit, parse) => (request) => {
25
+ const requestBody = JSON.parse(request.body);
26
+ const rawQuery = requestBody.query;
27
+ const parsedQuery = parse(rawQuery);
28
+ const updatedQuery = visit(parsedQuery, { enter });
29
+ const updatedBody = { ...requestBody, query: updatedQuery.loc.source.body };
30
+ return {
31
+ ...request,
32
+ body: JSON.stringify(updatedBody),
33
+ };
34
+ };
35
+ export const responseMiddleware = (traverse) => (response) => {
36
+ traverse(response).forEach(function (responseItem) {
37
+ if (responseItem instanceof Object && responseItem.name) {
38
+ //Name already in hashed form
39
+ if (responseItem.name && responseItem.name.includes('[')) {
40
+ return;
41
+ }
42
+ const hashedName = namehash(responseItem.name);
43
+ if (responseItem.id !== hashedName) {
44
+ this.update({ ...responseItem, name: hashedName, invalidName: true });
45
+ }
46
+ }
47
+ });
48
+ return response;
49
+ };
1
50
  export default class GqlManager {
2
51
  constructor() {
3
52
  this.gql = () => null;
4
53
  this.client = null;
5
54
  this.setUrl = async (url) => {
6
55
  if (url) {
7
- const imported = await import('graphql-request');
8
- this.client = new imported.GraphQLClient(url);
56
+ const [imported, traverse, { visit, parse }] = await Promise.all([
57
+ import('graphql-request'),
58
+ import('traverse'),
59
+ import('graphql/language'),
60
+ ]);
61
+ this.client = new imported.GraphQLClient(url, {
62
+ requestMiddleware: requestMiddleware(visit, parse),
63
+ responseMiddleware: responseMiddleware(traverse.default),
64
+ });
9
65
  this.gql = imported.gql;
10
66
  }
11
67
  else {
@@ -1,4 +1,5 @@
1
- import { ethers } from 'ethers';
2
1
  import { ENSArgs } from '..';
3
2
  import { FuseOptions } from '../@types/FuseOptions';
4
- export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, name: string, fusesToBurn: FuseOptions): Promise<ethers.ContractTransaction>;
3
+ export default function ({ contracts, signer }: ENSArgs<'contracts' | 'signer'>, name: string, { fusesToBurn, }: {
4
+ fusesToBurn: FuseOptions;
5
+ }): Promise<import("ethers").PopulatedTransaction>;
@@ -1,12 +1,8 @@
1
- import { ethers } from 'ethers';
2
1
  import generateFuseInput from '../utils/generateFuseInput';
3
- export default async function ({ contracts, provider }, name, fusesToBurn) {
4
- const signer = provider?.getSigner();
5
- if (!signer) {
6
- throw new Error('No signer found');
7
- }
2
+ import { namehash } from '../utils/normalise';
3
+ export default async function ({ contracts, signer }, name, { fusesToBurn, }) {
8
4
  const nameWrapper = (await contracts?.getNameWrapper()).connect(signer);
9
- const namehash = ethers.utils.namehash(name);
5
+ const hash = namehash(name);
10
6
  const encodedFuses = generateFuseInput(fusesToBurn);
11
- return nameWrapper.burnFuses(namehash, encodedFuses);
7
+ return nameWrapper.populateTransaction.burnFuses(hash, encodedFuses);
12
8
  }
@@ -2,18 +2,14 @@ import { ethers } from 'ethers';
2
2
  import { ENSArgs } from '..';
3
3
  import { FuseOptions } from '../@types/FuseOptions';
4
4
  declare type BaseArgs = {
5
- name: string;
6
5
  owner: string;
7
6
  resolverAddress?: string;
8
7
  contract: 'registry' | 'nameWrapper';
9
- options?: {
10
- addressOrIndex?: string | number;
11
- };
12
8
  };
13
9
  declare type NameWrapperArgs = {
14
10
  contract: 'nameWrapper';
15
11
  fuses?: FuseOptions;
16
12
  } & BaseArgs;
17
13
  declare type Args = BaseArgs | NameWrapperArgs;
18
- export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, { name, owner, resolverAddress, contract, options, ...wrapperArgs }: Args): Promise<ethers.ContractTransaction>;
14
+ export default function ({ contracts, signer }: ENSArgs<'contracts' | 'signer'>, name: string, { owner, resolverAddress, contract, ...wrapperArgs }: Args): Promise<ethers.PopulatedTransaction>;
19
15
  export {};
@@ -1,10 +1,7 @@
1
1
  import { ethers } from 'ethers';
2
2
  import generateFuseInput from '../utils/generateFuseInput';
3
- export default async function ({ contracts, provider }, { name, owner, resolverAddress, contract, options, ...wrapperArgs }) {
4
- const signer = provider?.getSigner(options?.addressOrIndex);
5
- if (!signer) {
6
- throw new Error('No signer found');
7
- }
3
+ import { namehash } from '../utils/normalise';
4
+ export default async function ({ contracts, signer }, name, { owner, resolverAddress, contract, ...wrapperArgs }) {
8
5
  const labels = name.split('.');
9
6
  if (labels.length === 1) {
10
7
  throw new Error('Subnames in ENS.js can only be created for 2LDs, not TLDs');
@@ -17,18 +14,18 @@ export default async function ({ contracts, provider }, { name, owner, resolverA
17
14
  }
18
15
  const label = labels.shift();
19
16
  const labelhash = ethers.utils.solidityKeccak256(['string'], [label]);
20
- const parentNodehash = ethers.utils.namehash(labels.join('.'));
17
+ const parentNodehash = namehash(labels.join('.'));
21
18
  switch (contract) {
22
19
  case 'registry': {
23
20
  const registry = (await contracts?.getRegistry()).connect(signer);
24
- return registry.setSubnodeRecord(parentNodehash, labelhash, owner, resolverAddress, 0);
21
+ return registry.populateTransaction.setSubnodeRecord(parentNodehash, labelhash, owner, resolverAddress, 0);
25
22
  }
26
23
  case 'nameWrapper': {
27
24
  const nameWrapper = (await contracts?.getNameWrapper()).connect(signer);
28
25
  const generatedFuses = 'fuses' in wrapperArgs && wrapperArgs.fuses
29
26
  ? generateFuseInput(wrapperArgs.fuses)
30
27
  : '0';
31
- return nameWrapper.setSubnodeRecord(parentNodehash, label, owner, resolverAddress, 0, generatedFuses);
28
+ return nameWrapper.populateTransaction.setSubnodeRecord(parentNodehash, label, owner, resolverAddress, 0, generatedFuses);
32
29
  }
33
30
  default: {
34
31
  throw new Error(`Unknown contract: ${contract}`);
@@ -1,4 +1,4 @@
1
1
  import { ENSArgs } from '..';
2
- export default function ({ contracts, provider, transferSubname, }: ENSArgs<'contracts' | 'provider' | 'transferSubname'>, name: string, contract: 'registry' | 'nameWrapper', options?: {
3
- addressOrIndex?: string | number;
4
- }): Promise<import("ethers").ContractTransaction>;
2
+ export default function ({ transferSubname }: ENSArgs<'transferSubname'>, name: string, { contract, }: {
3
+ contract: 'registry' | 'nameWrapper';
4
+ }): Promise<import("ethers").PopulatedTransaction>;
@@ -1,3 +1,6 @@
1
- export default async function ({ contracts, provider, transferSubname, }, name, contract, options) {
2
- return transferSubname(name, contract, '0x0000000000000000000000000000000000000000', options);
1
+ export default async function ({ transferSubname }, name, { contract, }) {
2
+ return transferSubname.populateTransaction(name, {
3
+ contract,
4
+ address: '0x0000000000000000000000000000000000000000',
5
+ });
3
6
  }
@@ -0,0 +1,7 @@
1
+ import * as packet from 'dns-packet';
2
+ export declare function encodeURLParams(p: {
3
+ [key: string]: string;
4
+ }): string;
5
+ export declare const getDNS: (q: packet.Packet) => Promise<packet.Packet>;
6
+ export declare const dnsQuery: (qtype: string, qname: string) => Promise<packet.Packet>;
7
+ export default function (_: any, dnsName: string): Promise<any>;
@@ -0,0 +1,51 @@
1
+ import * as packet from 'dns-packet';
2
+ export function encodeURLParams(p) {
3
+ return Object.entries(p)
4
+ .map((kv) => kv.map(encodeURIComponent).join('='))
5
+ .join('&');
6
+ }
7
+ export const getDNS = async (q) => {
8
+ const response = await global.fetch(`https://cloudflare-dns.com/dns-query?${encodeURLParams({
9
+ ct: 'application/dns-udpwireformat',
10
+ dns: packet.encode(q)?.toString('base64'),
11
+ ts: Date.now().toString(),
12
+ })}`);
13
+ const arrayBuffer = await response.arrayBuffer();
14
+ // @ts-ignore:next-line
15
+ const fromArrayBuffer = Buffer.from(arrayBuffer);
16
+ return packet.decode(fromArrayBuffer);
17
+ };
18
+ export const dnsQuery = async (qtype, qname) => {
19
+ const query = {
20
+ type: 'query',
21
+ id: 1,
22
+ flags: packet.RECURSION_DESIRED,
23
+ questions: [
24
+ {
25
+ type: qtype,
26
+ class: 'IN',
27
+ name: qname,
28
+ },
29
+ ],
30
+ additionals: [
31
+ {
32
+ type: 'OPT',
33
+ class: 'IN',
34
+ name: '.',
35
+ udpPayloadSize: 4096,
36
+ flags: packet.DNSSEC_OK,
37
+ },
38
+ ],
39
+ answers: [],
40
+ };
41
+ const response = await getDNS(query);
42
+ if (response.rcode !== 'NOERROR') {
43
+ throw new Error(`DNS query failed: ${response.rcode}`);
44
+ }
45
+ return response;
46
+ };
47
+ export default async function (_, dnsName) {
48
+ const result = await dnsQuery('TXT', `_ens.${dnsName}`);
49
+ const address = result?.answers?.[0]?.data?.[0]?.toString()?.split('=')?.[1];
50
+ return address;
51
+ }
@@ -1,5 +1,6 @@
1
- import { ethers, utils } from 'ethers';
1
+ import { utils } from 'ethers';
2
2
  import { testable as fuseEnums } from '../utils/fuses';
3
+ import { namehash } from '../utils/normalise';
3
4
  const NameSafety = [
4
5
  'Safe',
5
6
  'RegistrantNotWrapped',
@@ -12,7 +13,7 @@ const raw = async ({ contracts }, name) => {
12
13
  return {
13
14
  to: nameWrapper.address,
14
15
  data: nameWrapper.interface.encodeFunctionData('getFuses', [
15
- ethers.utils.namehash(name),
16
+ namehash(name),
16
17
  ]),
17
18
  };
18
19
  };
@@ -36,7 +37,7 @@ const decode = async ({ contracts }, data, name) => {
36
37
  if (utils.hexStripZeros(vulnerableNode) !== '0x') {
37
38
  name.split('.').forEach((label, index, arr) => {
38
39
  const node = arr.slice(index).join('.');
39
- const nodehash = utils.namehash(node);
40
+ const nodehash = namehash(node);
40
41
  if (nodehash === vulnerableNode) {
41
42
  returnVulnerableNode = node;
42
43
  }
@@ -1,5 +1,6 @@
1
1
  import { ethers } from 'ethers';
2
2
  import { labelhash } from '../utils/labels';
3
+ import { namehash as makeNamehash } from '../utils/normalise';
3
4
  const singleContractOwnerRaw = async ({ contracts }, contract, namehash, labels) => {
4
5
  switch (contract) {
5
6
  case 'nameWrapper': {
@@ -28,10 +29,10 @@ const singleContractOwnerRaw = async ({ contracts }, contract, namehash, labels)
28
29
  }
29
30
  };
30
31
  const raw = async ({ contracts, multicallWrapper }, name, contract) => {
31
- const namehash = ethers.utils.namehash(name);
32
+ const namehash = makeNamehash(name);
32
33
  const labels = name.split('.');
33
- if (contract) {
34
- return await singleContractOwnerRaw({ contracts }, contract, namehash, labels);
34
+ if (contract || labels.length === 1) {
35
+ return await singleContractOwnerRaw({ contracts }, contract || 'registry', namehash, labels);
35
36
  }
36
37
  const registryData = await singleContractOwnerRaw({ contracts }, 'registry', namehash, labels);
37
38
  const nameWrapperData = await singleContractOwnerRaw({ contracts }, 'nameWrapper', namehash, labels);
@@ -46,10 +47,11 @@ const singleContractOwnerDecode = (data) => ethers.utils.defaultAbiCoder.decode(
46
47
  const decode = async ({ contracts, multicallWrapper }, data, name, contract) => {
47
48
  if (data === null)
48
49
  return;
49
- if (contract) {
50
+ const labels = name.split('.');
51
+ if (contract || labels.length === 1) {
50
52
  const singleOwner = singleContractOwnerDecode(data);
51
53
  let obj = {
52
- ownershipLevel: contract,
54
+ ownershipLevel: contract || 'registry',
53
55
  };
54
56
  if (contract === 'registrar') {
55
57
  return {
@@ -74,7 +76,6 @@ const decode = async ({ contracts, multicallWrapper }, data, name, contract) =>
74
76
  const registryOwner = decodedData[0][0];
75
77
  const nameWrapperOwner = decodedData[1][0];
76
78
  const registrarOwner = decodedData[2]?.[0];
77
- const labels = name.split('.');
78
79
  // check for only .eth names
79
80
  if (labels[labels.length - 1] === 'eth') {
80
81
  // if the owner on the registrar is the namewrapper, then the namewrapper owner is the owner