@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
@@ -26,5 +26,8 @@ declare type ProfileOptions = {
26
26
  texts?: boolean | string[];
27
27
  coinTypes?: boolean | string[];
28
28
  };
29
- export default function ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }: ENSArgs<'contracts' | 'gqlInstance' | 'getName' | '_getText' | '_getAddr' | '_getContentHash' | 'resolverMulticallWrapper'>, nameOrAddress: string, options?: ProfileOptions): Promise<ResolvedProfile | undefined>;
29
+ declare type InputProfileOptions = ProfileOptions & {
30
+ resolverAddress?: string;
31
+ };
32
+ export default function ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }: ENSArgs<'contracts' | 'gqlInstance' | 'getName' | '_getText' | '_getAddr' | '_getContentHash' | 'resolverMulticallWrapper' | 'multicallWrapper'>, nameOrAddress: string, options?: InputProfileOptions): Promise<ResolvedProfile | undefined>;
30
33
  export {};
@@ -2,6 +2,7 @@ import { formatsByName } from '@ensdomains/address-encoder';
2
2
  import { ethers } from 'ethers';
3
3
  import { decodeContenthash } from '../utils/contentHash';
4
4
  import { hexEncodeName } from '../utils/hexEncodedName';
5
+ import { namehash } from '../utils/normalise';
5
6
  import { parseInputType } from '../utils/validation';
6
7
  const makeMulticallData = async ({ _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }, name, options) => {
7
8
  let calls = [];
@@ -40,23 +41,51 @@ const makeMulticallData = async ({ _getAddr, _getContentHash, _getText, resolver
40
41
  const prRawData = await resolverMulticallWrapper.raw(calls.map((x) => x.data));
41
42
  return { data: prRawData.data, calls };
42
43
  };
43
- const makeHashIndexes = (data, name) => [...data.matchAll(ethers.utils.namehash(name).substring(2))].map((x) => x.index / 2 - 1);
44
- const getDataForName = async ({ contracts, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }, name, options) => {
44
+ const fetchWithoutResolverMulticall = async ({ multicallWrapper }, calls, resolverAddress) => {
45
+ const callsWithResolver = calls.map((call) => ({
46
+ to: resolverAddress,
47
+ data: call.data.data,
48
+ }));
49
+ return (await multicallWrapper(callsWithResolver)).map((x) => x[1]);
50
+ };
51
+ const getDataForName = async ({ contracts, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }, name, options, fallbackResolver, specificResolver) => {
45
52
  const universalResolver = await contracts?.getUniversalResolver();
46
53
  const { data, calls } = await makeMulticallData({ _getAddr, _getContentHash, _getText, resolverMulticallWrapper }, name, options);
47
- let resolver;
54
+ let resolvedData;
55
+ let useFallbackResolver = false;
48
56
  try {
49
- resolver = await universalResolver?.resolve(hexEncodeName(name), data);
57
+ if (specificResolver) {
58
+ const publicResolver = await contracts?.getPublicResolver(undefined, specificResolver);
59
+ resolvedData = await publicResolver?.callStatic.multicall(calls.map((x) => x.data));
60
+ }
61
+ else {
62
+ resolvedData = await universalResolver?.resolve(hexEncodeName(name), data);
63
+ }
50
64
  }
51
65
  catch {
52
- return;
66
+ useFallbackResolver = true;
67
+ }
68
+ let resolverAddress;
69
+ let recordData;
70
+ if (useFallbackResolver) {
71
+ resolverAddress = specificResolver || fallbackResolver;
72
+ recordData = await fetchWithoutResolverMulticall({ multicallWrapper }, calls, resolverAddress);
73
+ }
74
+ else {
75
+ resolverAddress = specificResolver || resolvedData['1'];
76
+ if (specificResolver) {
77
+ recordData = resolvedData;
78
+ }
79
+ else {
80
+ ;
81
+ [recordData] = await resolverMulticallWrapper.decode(resolvedData['0']);
82
+ }
53
83
  }
54
- const [recordData] = await resolverMulticallWrapper.decode(resolver['0']);
55
84
  const matchAddress = recordData[calls.findIndex((x) => x.key === '60')];
56
85
  return {
57
86
  address: matchAddress && (await _getAddr.decode(matchAddress)),
58
87
  records: await formatRecords({ _getAddr, _getContentHash, _getText }, recordData, calls, options),
59
- resolverAddress: resolver['1'],
88
+ resolverAddress,
60
89
  };
61
90
  };
62
91
  const formatRecords = async ({ _getText, _getAddr, _getContentHash, }, data, calls, options) => {
@@ -66,7 +95,7 @@ const formatRecords = async ({ _getText, _getAddr, _getContentHash, }, data, cal
66
95
  key: calls[i].key,
67
96
  type: calls[i].type,
68
97
  };
69
- if (itemRet.type === 'addr' || itemRet.type === 'contenthash') {
98
+ if (itemRet.type === 'contenthash') {
70
99
  decodedFromAbi = ethers.utils.defaultAbiCoder.decode(['bytes'], item)[0];
71
100
  if (ethers.utils.hexStripZeros(decodedFromAbi) === '0x') {
72
101
  return;
@@ -142,10 +171,10 @@ const formatRecords = async ({ _getText, _getAddr, _getContentHash, }, data, cal
142
171
  }
143
172
  return returnedResponse;
144
173
  };
145
- const graphFetch = async ({ gqlInstance }, name, wantedRecords) => {
174
+ const graphFetch = async ({ gqlInstance }, name, wantedRecords, resolverAddress) => {
146
175
  const query = gqlInstance.gql `
147
- query getRecords($name: String!) {
148
- domains(where: { name: $name }) {
176
+ query getRecords($id: String!) {
177
+ domain(id: $id) {
149
178
  isMigrated
150
179
  createdAt
151
180
  resolver {
@@ -155,18 +184,52 @@ const graphFetch = async ({ gqlInstance }, name, wantedRecords) => {
155
184
  addr {
156
185
  id
157
186
  }
187
+ address
188
+ }
189
+ }
190
+ }
191
+ `;
192
+ const customResolverQuery = gqlInstance.gql `
193
+ query getRecordsWithCustomResolver($id: String!, $resolverId: String!) {
194
+ domain(id: $id) {
195
+ isMigrated
196
+ createdAt
197
+ }
198
+ resolver(id: $resolverId) {
199
+ texts
200
+ coinTypes
201
+ contentHash
202
+ addr {
203
+ id
158
204
  }
159
205
  }
160
206
  }
161
207
  `;
162
208
  const client = gqlInstance.client;
163
- const { domains } = await client.request(query, { name });
164
- if (!domains || domains.length === 0)
209
+ const id = namehash(name);
210
+ let domain;
211
+ let resolverResponse;
212
+ if (!resolverAddress) {
213
+ ;
214
+ ({ domain } = await client.request(query, { id }));
215
+ resolverResponse = domain?.resolver;
216
+ }
217
+ else {
218
+ const resolverId = `${resolverAddress}-${id}`;
219
+ ({ resolver: resolverResponse, domain } = await client.request(customResolverQuery, { id, resolverId }));
220
+ }
221
+ if (!domain)
165
222
  return;
166
- const [{ resolver: resolverResponse, isMigrated, createdAt }] = domains;
223
+ const { isMigrated, createdAt } = domain;
167
224
  let returnedRecords = {};
168
- if (!wantedRecords)
225
+ if (!resolverResponse)
169
226
  return { isMigrated, createdAt };
227
+ if (!wantedRecords)
228
+ return {
229
+ isMigrated,
230
+ createdAt,
231
+ graphResolverAddress: resolverResponse.address || resolverAddress,
232
+ };
170
233
  Object.keys(wantedRecords).forEach((key) => {
171
234
  const data = wantedRecords[key];
172
235
  if (typeof data === 'boolean' && data) {
@@ -178,28 +241,40 @@ const graphFetch = async ({ gqlInstance }, name, wantedRecords) => {
178
241
  }
179
242
  }
180
243
  });
181
- return { ...returnedRecords, isMigrated, createdAt };
244
+ return {
245
+ ...returnedRecords,
246
+ isMigrated,
247
+ createdAt,
248
+ graphResolverAddress: resolverResponse.address || resolverAddress,
249
+ };
182
250
  };
183
- const getProfileFromName = async ({ contracts, gqlInstance, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }, name, options) => {
184
- const usingOptions = !options || options?.texts === true || options?.coinTypes === true
185
- ? options || { contentHash: true, texts: true, coinTypes: true }
251
+ const getProfileFromName = async ({ contracts, gqlInstance, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }, name, options) => {
252
+ const { resolverAddress, ..._options } = options || {};
253
+ const optsLength = Object.keys(_options).length;
254
+ const usingOptions = !optsLength || _options?.texts === true || _options?.coinTypes === true
255
+ ? optsLength
256
+ ? _options
257
+ : { contentHash: true, texts: true, coinTypes: true }
186
258
  : undefined;
187
- const graphResult = await graphFetch({ gqlInstance }, name, usingOptions);
259
+ const graphResult = await graphFetch({ gqlInstance }, name, usingOptions, resolverAddress);
188
260
  if (!graphResult)
189
261
  return;
190
- const { isMigrated, createdAt, ...wantedRecords } = graphResult;
262
+ const { isMigrated, createdAt, graphResolverAddress, ...wantedRecords } = graphResult;
263
+ if (!graphResolverAddress && !options?.resolverAddress)
264
+ return { isMigrated, createdAt, message: "Name doesn't have a resolver" };
191
265
  const result = await getDataForName({
192
266
  contracts,
193
267
  _getAddr,
194
268
  _getContentHash,
195
269
  _getText,
196
270
  resolverMulticallWrapper,
197
- }, name, usingOptions ? wantedRecords : options);
271
+ multicallWrapper,
272
+ }, name, usingOptions ? wantedRecords : options, graphResolverAddress, options?.resolverAddress);
198
273
  if (!result)
199
274
  return { isMigrated, createdAt, message: "Records fetch didn't complete" };
200
275
  return { ...result, isMigrated, createdAt, message: undefined };
201
276
  };
202
- const getProfileFromAddress = async ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }, address, options) => {
277
+ const getProfileFromAddress = async ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }, address, options) => {
203
278
  let name;
204
279
  try {
205
280
  name = await getName(address);
@@ -218,6 +293,7 @@ const getProfileFromAddress = async ({ contracts, gqlInstance, getName, _getAddr
218
293
  _getContentHash,
219
294
  _getText,
220
295
  resolverMulticallWrapper,
296
+ multicallWrapper,
221
297
  }, name.name, options);
222
298
  if (!result || result.message)
223
299
  return;
@@ -228,7 +304,7 @@ const getProfileFromAddress = async ({ contracts, gqlInstance, getName, _getAddr
228
304
  message: undefined,
229
305
  };
230
306
  };
231
- export default async function ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, }, nameOrAddress, options) {
307
+ export default async function ({ contracts, gqlInstance, getName, _getAddr, _getContentHash, _getText, resolverMulticallWrapper, multicallWrapper, }, nameOrAddress, options) {
232
308
  if (options && options.coinTypes && typeof options.coinTypes !== 'boolean') {
233
309
  options.coinTypes = options.coinTypes.map((coin) => {
234
310
  if (!isNaN(parseInt(coin))) {
@@ -252,6 +328,7 @@ export default async function ({ contracts, gqlInstance, getName, _getAddr, _get
252
328
  _getContentHash,
253
329
  _getText,
254
330
  resolverMulticallWrapper,
331
+ multicallWrapper,
255
332
  }, nameOrAddress, options);
256
333
  }
257
334
  return getProfileFromName({
@@ -261,5 +338,6 @@ export default async function ({ contracts, gqlInstance, getName, _getAddr, _get
261
338
  _getContentHash,
262
339
  _getText,
263
340
  resolverMulticallWrapper,
341
+ multicallWrapper,
264
342
  }, nameOrAddress, options);
265
343
  }
@@ -3,6 +3,7 @@ declare type ProfileOptions = {
3
3
  contentHash?: boolean;
4
4
  texts?: boolean | string[];
5
5
  coinTypes?: boolean | string[];
6
+ resolverAddress?: string;
6
7
  };
7
8
  export default function ({ getProfile }: ENSArgs<'getProfile'>, name: string, options?: ProfileOptions): Promise<{
8
9
  isMigrated: boolean | null;
@@ -1,13 +1,14 @@
1
1
  import { formatsByCoinType, formatsByName } from '@ensdomains/address-encoder';
2
2
  import { ethers } from 'ethers';
3
3
  import { decodeContenthash } from '../utils/contentHash';
4
+ import { namehash } from '../utils/normalise';
4
5
  export const _getContentHash = {
5
6
  raw: async ({ contracts }, name) => {
6
7
  const publicResolver = await contracts?.getPublicResolver();
7
8
  return {
8
9
  to: '0x0000000000000000000000000000000000000000',
9
10
  data: publicResolver.interface.encodeFunctionData('contenthash', [
10
- ethers.utils.namehash(name),
11
+ namehash(name),
11
12
  ]),
12
13
  };
13
14
  },
@@ -45,7 +46,7 @@ export const _getText = {
45
46
  return {
46
47
  to: '0x0000000000000000000000000000000000000000',
47
48
  data: publicResolver.interface.encodeFunctionData('text', [
48
- ethers.utils.namehash(name),
49
+ namehash(name),
49
50
  key,
50
51
  ]),
51
52
  };
@@ -77,10 +78,18 @@ export const _getAddr = {
77
78
  coinType = 60;
78
79
  }
79
80
  const publicResolver = await contracts?.getPublicResolver();
81
+ if (coinType === 60 || coinType === '60') {
82
+ return {
83
+ to: '0x0000000000000000000000000000000000000000',
84
+ data: publicResolver.interface.encodeFunctionData('addr(bytes32)', [
85
+ namehash(name),
86
+ ]),
87
+ };
88
+ }
80
89
  if (bypassFormat) {
81
90
  return {
82
91
  to: '0x0000000000000000000000000000000000000000',
83
- data: publicResolver.interface.encodeFunctionData('addr(bytes32,uint256)', [ethers.utils.namehash(name), coinType]),
92
+ data: publicResolver.interface.encodeFunctionData('addr(bytes32,uint256)', [namehash(name), coinType]),
84
93
  };
85
94
  }
86
95
  const formatter = typeof coinType === 'string' && isNaN(parseInt(coinType))
@@ -91,7 +100,7 @@ export const _getAddr = {
91
100
  }
92
101
  return {
93
102
  to: '0x0000000000000000000000000000000000000000',
94
- data: publicResolver.interface.encodeFunctionData('addr(bytes32,uint256)', [ethers.utils.namehash(name), formatter.coinType]),
103
+ data: publicResolver.interface.encodeFunctionData('addr(bytes32,uint256)', [namehash(name), formatter.coinType]),
95
104
  };
96
105
  },
97
106
  decode: async ({ contracts }, data, _name, coinType) => {
@@ -104,7 +113,15 @@ export const _getAddr = {
104
113
  const formatter = typeof coinType === 'string' && isNaN(parseInt(coinType))
105
114
  ? formatsByName[coinType]
106
115
  : formatsByCoinType[typeof coinType === 'number' ? coinType : parseInt(coinType)];
107
- const [response] = publicResolver.interface.decodeFunctionResult('addr(bytes32,uint256)', data);
116
+ let response;
117
+ if (coinType === 60 || coinType === '60') {
118
+ ;
119
+ [response] = publicResolver.interface.decodeFunctionResult('addr(bytes32)', data);
120
+ }
121
+ else {
122
+ ;
123
+ [response] = publicResolver.interface.decodeFunctionResult('addr(bytes32,uint256)', data);
124
+ }
108
125
  if (!response)
109
126
  return;
110
127
  if (ethers.utils.hexStripZeros(response) === '0x') {
@@ -1,6 +1,6 @@
1
- import { namehash } from 'ethers/lib/utils';
2
1
  import { truncateFormat } from '../utils/format';
3
2
  import { decryptName } from '../utils/labels';
3
+ import { namehash } from '../utils/normalise';
4
4
  const largeQuery = async ({ gqlInstance }, { name, page, pageSize = 10, orderDirection, orderBy, lastSubnames }) => {
5
5
  const client = gqlInstance.client;
6
6
  let finalQuery = gqlInstance.gql `
@@ -53,7 +53,7 @@ const largeQuery = async ({ gqlInstance }, { name, page, pageSize = 10, orderDir
53
53
  });
54
54
  return {
55
55
  subnames: subdomains,
56
- subnameCount: domain.subdomainCount
56
+ subnameCount: domain.subdomainCount,
57
57
  };
58
58
  };
59
59
  const smallQuery = async ({ gqlInstance }, { name, page, pageSize = 10, orderDirection, orderBy }) => {
@@ -140,7 +140,7 @@ const smallQuery = async ({ gqlInstance }, { name, page, pageSize = 10, orderDir
140
140
  });
141
141
  return {
142
142
  subnames: subdomains,
143
- subnameCount: domain.subdomainCount
143
+ subnameCount: domain.subdomainCount,
144
144
  };
145
145
  };
146
146
  const getSubnames = (injected, functionArgs) => {
@@ -1,4 +1,5 @@
1
1
  import { ENSArgs } from '..';
2
- export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, name: string, address?: string, resolver?: string, options?: {
3
- addressOrIndex?: string | number;
4
- }): Promise<import("ethers").ContractTransaction | undefined>;
2
+ export default function ({ contracts, signer }: ENSArgs<'contracts' | 'signer'>, name: string, { address, resolver, }?: {
3
+ address?: string;
4
+ resolver?: string;
5
+ }): Promise<import("ethers").PopulatedTransaction>;
@@ -1,14 +1,9 @@
1
- export default async function ({ contracts, provider }, name, address, resolver, options) {
2
- const signerAddress = await provider
3
- ?.getSigner(options?.addressOrIndex)
4
- .getAddress();
5
- if (!signerAddress) {
6
- throw new Error('No signer found');
7
- }
8
- const reverseRegistrar = (await contracts?.getReverseRegistrar())?.connect(provider?.getSigner());
1
+ export default async function ({ contracts, signer }, name, { address, resolver, } = {}) {
2
+ const signerAddress = await signer.getAddress();
3
+ const reverseRegistrar = (await contracts?.getReverseRegistrar())?.connect(signer);
9
4
  if (address) {
10
5
  const publicResolver = await contracts?.getPublicResolver();
11
- return reverseRegistrar?.setNameForAddr(address, signerAddress, resolver || publicResolver.address, name);
6
+ return reverseRegistrar.populateTransaction.setNameForAddr(address, signerAddress, resolver || publicResolver.address, name);
12
7
  }
13
- return reverseRegistrar?.setName(name);
8
+ return reverseRegistrar.populateTransaction.setName(name);
14
9
  }
@@ -0,0 +1,18 @@
1
+ import { ENSArgs } from '..';
2
+ import { RecordInput, RecordTypes } from '../utils/recordHelpers';
3
+ declare type BaseInput = {
4
+ resolverAddress?: string;
5
+ };
6
+ declare type ContentHashInput = {
7
+ record: RecordInput<'contentHash'>;
8
+ type: 'contentHash';
9
+ };
10
+ declare type AddrOrTextInput = {
11
+ record: RecordInput<'addr' | 'text'>;
12
+ type: 'addr' | 'text';
13
+ };
14
+ export default function <T extends RecordTypes>({ contracts, provider, getResolver, signer, }: ENSArgs<'contracts' | 'provider' | 'getResolver' | 'signer'>, name: string, { record, type, resolverAddress, }: BaseInput & (ContentHashInput | AddrOrTextInput)): Promise<{
15
+ to: string;
16
+ data: string;
17
+ }>;
18
+ export {};
@@ -0,0 +1,24 @@
1
+ import { namehash } from '../utils/normalise';
2
+ import { generateSingleRecordCall, } from '../utils/recordHelpers';
3
+ export default async function ({ contracts, provider, getResolver, signer, }, name, { record, type, resolverAddress, }) {
4
+ if (!name.includes('.')) {
5
+ throw new Error('Input is not an ENS name');
6
+ }
7
+ let resolverToUse;
8
+ if (resolverAddress) {
9
+ resolverToUse = resolverAddress;
10
+ }
11
+ else {
12
+ resolverToUse = await getResolver(name);
13
+ }
14
+ if (!resolverToUse) {
15
+ throw new Error('No resolver found for input address');
16
+ }
17
+ const resolver = (await contracts?.getPublicResolver(provider, resolverToUse))?.connect(signer);
18
+ const hash = namehash(name);
19
+ const call = generateSingleRecordCall(hash, resolver, type)(record);
20
+ return {
21
+ to: resolver.address,
22
+ data: call,
23
+ };
24
+ }
@@ -1,4 +1,6 @@
1
- import { ethers } from 'ethers';
2
1
  import { ENSArgs } from '..';
3
2
  import { RecordOptions } from '../utils/recordHelpers';
4
- export default function ({ contracts, provider, getResolver, }: ENSArgs<'contracts' | 'provider' | 'getResolver'>, name: string, records: RecordOptions): Promise<ethers.ContractTransaction | undefined>;
3
+ export default function ({ contracts, provider, getResolver, signer, }: ENSArgs<'contracts' | 'provider' | 'getResolver' | 'signer'>, name: string, { records, resolverAddress, }: {
4
+ records: RecordOptions;
5
+ resolverAddress?: string;
6
+ }): Promise<import("ethers").PopulatedTransaction>;
@@ -1,19 +1,21 @@
1
- import { ethers } from 'ethers';
1
+ import { namehash } from '../utils/normalise';
2
2
  import { generateRecordCallArray } from '../utils/recordHelpers';
3
- export default async function ({ contracts, provider, getResolver, }, name, records) {
3
+ export default async function ({ contracts, provider, getResolver, signer, }, name, { records, resolverAddress, }) {
4
4
  if (!name.includes('.')) {
5
5
  throw new Error('Input is not an ENS name');
6
6
  }
7
- const resolverAddress = await getResolver(name);
8
- if (!resolverAddress) {
9
- throw new Error('No resolver found for input address');
7
+ let resolverToUse;
8
+ if (resolverAddress) {
9
+ resolverToUse = resolverAddress;
10
+ }
11
+ else {
12
+ resolverToUse = await getResolver(name);
10
13
  }
11
- const address = await provider?.getSigner().getAddress();
12
- if (!address) {
13
- throw new Error('No signer found');
14
+ if (!resolverToUse) {
15
+ throw new Error('No resolver found for input address');
14
16
  }
15
- const resolver = (await contracts?.getPublicResolver(provider, resolverAddress))?.connect(provider?.getSigner());
16
- const namehash = ethers.utils.namehash(name);
17
- const calls = generateRecordCallArray(namehash, records, resolver);
18
- return resolver?.multicall(calls);
17
+ const resolver = (await contracts?.getPublicResolver(provider, resolverToUse))?.connect(signer);
18
+ const hash = namehash(name);
19
+ const calls = generateRecordCallArray(hash, records, resolver);
20
+ return resolver.populateTransaction.multicall(calls);
19
21
  }
@@ -1,5 +1,5 @@
1
- import { ethers } from 'ethers';
2
1
  import { ENSArgs } from '..';
3
- export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, name: string, contract: 'registry' | 'nameWrapper', resolver?: string, options?: {
4
- addressOrIndex?: string | number;
5
- }): Promise<ethers.ContractTransaction>;
2
+ export default function ({ contracts, signer }: ENSArgs<'contracts' | 'signer'>, name: string, { contract, resolver, }: {
3
+ contract: 'registry' | 'nameWrapper';
4
+ resolver?: string;
5
+ }): Promise<import("ethers").PopulatedTransaction>;
@@ -1,22 +1,16 @@
1
- import { ethers } from 'ethers';
2
- export default async function ({ contracts, provider }, name, contract, resolver, options) {
3
- const address = await provider
4
- ?.getSigner(options?.addressOrIndex)
5
- .getAddress();
6
- if (!address) {
7
- throw new Error('No signer found');
8
- }
1
+ import { namehash } from '../utils/normalise';
2
+ export default async function ({ contracts, signer }, name, { contract, resolver, }) {
9
3
  if (!resolver) {
10
4
  resolver = (await contracts?.getPublicResolver()).address;
11
5
  }
12
6
  switch (contract) {
13
7
  case 'registry': {
14
- const registry = (await contracts?.getRegistry()).connect(provider?.getSigner(options?.addressOrIndex));
15
- return registry.setResolver(ethers.utils.namehash(name), resolver);
8
+ const registry = (await contracts?.getRegistry()).connect(signer);
9
+ return registry.populateTransaction.setResolver(namehash(name), resolver);
16
10
  }
17
11
  case 'nameWrapper': {
18
- const nameWrapper = (await contracts?.getNameWrapper()).connect(provider?.getSigner(options?.addressOrIndex));
19
- return nameWrapper.setResolver(ethers.utils.namehash(name), resolver);
12
+ const nameWrapper = (await contracts?.getNameWrapper()).connect(signer);
13
+ return nameWrapper.populateTransaction.setResolver(namehash(name), resolver);
20
14
  }
21
15
  default: {
22
16
  throw new Error(`Unknown contract: ${contract}`);
@@ -1,5 +1,6 @@
1
1
  import { ethers } from 'ethers';
2
2
  import { ENSArgs } from '..';
3
- export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, name: string, newOwner: string, contract: 'registry' | 'nameWrapper' | 'baseRegistrar', options?: {
4
- addressOrIndex?: string | number;
5
- }): Promise<ethers.ContractTransaction>;
3
+ export default function ({ contracts, signer }: ENSArgs<'contracts' | 'signer'>, name: string, { newOwner, contract, }: {
4
+ newOwner: string;
5
+ contract: 'registry' | 'nameWrapper' | 'baseRegistrar';
6
+ }): Promise<ethers.PopulatedTransaction>;
@@ -1,27 +1,23 @@
1
1
  import { ethers } from 'ethers';
2
- export default async function ({ contracts, provider }, name, newOwner, contract, options) {
3
- const address = await provider
4
- ?.getSigner(options?.addressOrIndex)
5
- .getAddress();
6
- if (!address) {
7
- throw new Error('No signer found');
8
- }
2
+ import { namehash } from '../utils/normalise';
3
+ export default async function ({ contracts, signer }, name, { newOwner, contract, }) {
4
+ const address = await signer.getAddress();
9
5
  switch (contract) {
10
6
  case 'registry': {
11
- const registry = (await contracts?.getRegistry()).connect(provider?.getSigner(options?.addressOrIndex));
12
- return registry.setOwner(ethers.utils.namehash(name), newOwner);
7
+ const registry = (await contracts?.getRegistry()).connect(signer);
8
+ return registry.populateTransaction.setOwner(namehash(name), newOwner);
13
9
  }
14
10
  case 'baseRegistrar': {
15
- const baseRegistrar = (await contracts?.getBaseRegistrar()).connect(provider?.getSigner(options?.addressOrIndex));
11
+ const baseRegistrar = (await contracts?.getBaseRegistrar()).connect(signer);
16
12
  const labels = name.split('.');
17
13
  if (labels.length > 2 || labels[labels.length - 1] !== 'eth') {
18
14
  throw new Error('Invalid name for baseRegistrar');
19
15
  }
20
- return baseRegistrar['safeTransferFrom(address,address,uint256)'](address, newOwner, ethers.utils.solidityKeccak256(['string'], [labels[0]]));
16
+ return baseRegistrar.populateTransaction['safeTransferFrom(address,address,uint256)'](address, newOwner, ethers.utils.solidityKeccak256(['string'], [labels[0]]));
21
17
  }
22
18
  case 'nameWrapper': {
23
- const nameWrapper = (await contracts?.getNameWrapper()).connect(provider?.getSigner(options?.addressOrIndex));
24
- return nameWrapper.safeTransferFrom(address, newOwner, ethers.utils.namehash(name), 1, '0x');
19
+ const nameWrapper = (await contracts?.getNameWrapper()).connect(signer);
20
+ return nameWrapper.populateTransaction.safeTransferFrom(address, newOwner, namehash(name), 1, '0x');
25
21
  }
26
22
  default: {
27
23
  throw new Error(`Unknown contract: ${contract}`);
@@ -1,5 +1,6 @@
1
1
  import { ethers } from 'ethers';
2
2
  import { ENSArgs } from '..';
3
- export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, name: string, contract: 'registry' | 'nameWrapper', address: string, options?: {
4
- addressOrIndex?: string | number;
5
- }): Promise<ethers.ContractTransaction>;
3
+ export default function ({ contracts, signer }: ENSArgs<'contracts' | 'signer'>, name: string, { contract, address, }: {
4
+ contract: 'registry' | 'nameWrapper';
5
+ address: string;
6
+ }): Promise<ethers.PopulatedTransaction>;
@@ -1,21 +1,18 @@
1
1
  import { ethers } from 'ethers';
2
- export default async function ({ contracts, provider }, name, contract, address, options) {
3
- const signer = provider?.getSigner(options?.addressOrIndex);
4
- if (!signer) {
5
- throw new Error('No signer found');
6
- }
2
+ import { namehash } from '../utils/normalise';
3
+ export default async function ({ contracts, signer }, name, { contract, address, }) {
7
4
  const labels = name.split('.');
8
5
  const label = labels.shift();
9
6
  const labelhash = ethers.utils.solidityKeccak256(['string'], [label]);
10
- const parentNodehash = ethers.utils.namehash(labels.join('.'));
7
+ const parentNodehash = namehash(labels.join('.'));
11
8
  switch (contract) {
12
9
  case 'registry': {
13
10
  const registry = (await contracts?.getRegistry()).connect(signer);
14
- return registry.setSubnodeOwner(parentNodehash, labelhash, address);
11
+ return registry.populateTransaction.setSubnodeOwner(parentNodehash, labelhash, address);
15
12
  }
16
13
  case 'nameWrapper': {
17
14
  const nameWrapper = (await contracts?.getNameWrapper()).connect(signer);
18
- return nameWrapper.setSubnodeOwner(parentNodehash, label, address, '0');
15
+ return nameWrapper.populateTransaction.setSubnodeOwner(parentNodehash, label, address, '0');
19
16
  }
20
17
  default: {
21
18
  throw new Error(`Unknown contract: ${contract}`);
@@ -1,4 +1,5 @@
1
1
  import { ENSArgs } from '..';
2
- export default function ({ contracts, provider }: ENSArgs<'contracts' | 'provider'>, name: string, newController: string, newRegistrant?: string, options?: {
3
- addressOrIndex?: string | number;
4
- }): Promise<import("ethers").ContractTransaction>;
2
+ export default function ({ contracts, signer }: ENSArgs<'contracts' | 'signer'>, name: string, { newController, newRegistrant, }: {
3
+ newController: string;
4
+ newRegistrant?: string;
5
+ }): Promise<import("ethers").PopulatedTransaction>;
@@ -1,24 +1,20 @@
1
1
  import { utils } from 'ethers';
2
- export default async function ({ contracts, provider }, name, newController, newRegistrant, options) {
3
- const signer = provider?.getSigner(options?.addressOrIndex);
4
- const address = await signer?.getAddress();
5
- if (!signer || !address) {
6
- throw new Error('No signer found');
7
- }
2
+ import { namehash } from '../utils/normalise';
3
+ export default async function ({ contracts, signer }, name, { newController, newRegistrant, }) {
8
4
  const labels = name.split('.');
9
5
  const labelhash = utils.solidityKeccak256(['string'], [labels[0]]);
10
- const parentNodehash = utils.namehash(labels.slice(1).join('.'));
6
+ const parentNodehash = namehash(labels.slice(1).join('.'));
11
7
  const nameWrapper = (await contracts?.getNameWrapper()).connect(signer);
12
8
  if (labels.length === 2 && labels[1] === 'eth') {
13
9
  if (!newRegistrant) {
14
10
  throw new Error('newRegistrant must be specified for .eth names');
15
11
  }
16
- return nameWrapper.unwrapETH2LD(labelhash, newRegistrant, newController);
12
+ return nameWrapper.populateTransaction.unwrapETH2LD(labelhash, newRegistrant, newController);
17
13
  }
18
14
  else {
19
15
  if (newRegistrant) {
20
16
  throw new Error('newRegistrant can only be specified for .eth names');
21
17
  }
22
- return nameWrapper.unwrap(parentNodehash, labelhash, newController);
18
+ return nameWrapper.populateTransaction.unwrap(parentNodehash, labelhash, newController);
23
19
  }
24
20
  }