@ensdomains/ensjs 3.0.0-alpha.30 → 3.0.0-alpha.32

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/README.md CHANGED
@@ -253,6 +253,11 @@ It allows `withProvider` to act as a new ENS instance without having to await a
253
253
 
254
254
  ## Individual Functions
255
255
 
256
+ ### Utils
257
+
258
+ Utils can be imported at follows
259
+ `import { encodeContenthash } from '@ensdomains/ensjs/utils/contentHash'`
260
+
256
261
  ### getFuses
257
262
 
258
263
  Gets the fuses for a specified wrapped name.
@@ -36,6 +36,12 @@ const mapDomain = (domain) => {
36
36
  };
37
37
  const mapWrappedDomain = (wrappedDomain) => {
38
38
  const domain = mapDomain(wrappedDomain.domain);
39
+ if (domain.registration) {
40
+ domain.registration = {
41
+ expiryDate: new Date(parseInt(domain.registration.expiryDate) * 1e3),
42
+ registrationDate: new Date(domain.registration.registrationDate * 1e3)
43
+ };
44
+ }
39
45
  return {
40
46
  expiryDate: new Date(parseInt(wrappedDomain.expiryDate) * 1e3),
41
47
  fuses: (0, import_fuses.decodeFuses)(wrappedDomain.fuses),
@@ -86,8 +86,23 @@ const raw = async ({ contracts, multicallWrapper }, name, contract) => {
86
86
  }
87
87
  return multicallWrapper.raw(data);
88
88
  };
89
+ const registrantQuery = `
90
+ query GetRegistrant($namehash: String!) {
91
+ domain(id: $namehash) {
92
+ registration {
93
+ registrant {
94
+ id
95
+ }
96
+ }
97
+ }
98
+ }
99
+ `;
89
100
  const singleContractOwnerDecode = (data) => import_ethers.ethers.utils.defaultAbiCoder.decode(["address"], data)[0];
90
- const decode = async ({ contracts, multicallWrapper }, data, name, contract) => {
101
+ const decode = async ({
102
+ contracts,
103
+ multicallWrapper,
104
+ gqlInstance
105
+ }, data, name, contract) => {
91
106
  if (!data)
92
107
  return;
93
108
  const labels = name.split(".");
@@ -116,8 +131,17 @@ const decode = async ({ contracts, multicallWrapper }, data, name, contract) =>
116
131
  );
117
132
  const registryOwner = decodedData[0][0];
118
133
  const nameWrapperOwner = decodedData[1][0];
119
- const registrarOwner = decodedData[2]?.[0];
134
+ let registrarOwner = decodedData[2]?.[0];
120
135
  if (labels[labels.length - 1] === "eth") {
136
+ if (!registrarOwner && labels.length === 2) {
137
+ const graphRegistrantResult = await gqlInstance?.request(
138
+ registrantQuery,
139
+ {
140
+ namehash: (0, import_normalise.namehash)(name)
141
+ }
142
+ );
143
+ registrarOwner = graphRegistrantResult.domain?.registration?.registrant?.id;
144
+ }
121
145
  if (registrarOwner === nameWrapper.address) {
122
146
  return {
123
147
  owner: nameWrapperOwner,
@@ -131,7 +155,14 @@ const decode = async ({ contracts, multicallWrapper }, data, name, contract) =>
131
155
  ownershipLevel: "registrar"
132
156
  };
133
157
  }
134
- if (labels.length > 2 && import_ethers.ethers.utils.hexStripZeros(registryOwner) !== "0x") {
158
+ if (import_ethers.ethers.utils.hexStripZeros(registryOwner) !== "0x") {
159
+ if (labels.length === 2) {
160
+ return {
161
+ registrant: void 0,
162
+ owner: registryOwner,
163
+ ownershipLevel: "registrar"
164
+ };
165
+ }
135
166
  if (registryOwner === nameWrapper.address && nameWrapperOwner && import_ethers.ethers.utils.hexStripZeros(nameWrapperOwner) !== "0x") {
136
167
  return {
137
168
  owner: nameWrapperOwner,
package/dist/cjs/index.js CHANGED
@@ -234,7 +234,7 @@ class ENS {
234
234
  );
235
235
  getOwner = this.generateRawFunction(
236
236
  "initialGetters",
237
- ["contracts", "multicallWrapper"],
237
+ ["contracts", "multicallWrapper", "gqlInstance"],
238
238
  "getOwner"
239
239
  );
240
240
  getExpiry = this.generateRawFunction(
@@ -14,6 +14,12 @@ var mapDomain = (domain) => {
14
14
  };
15
15
  var mapWrappedDomain = (wrappedDomain) => {
16
16
  const domain = mapDomain(wrappedDomain.domain);
17
+ if (domain.registration) {
18
+ domain.registration = {
19
+ expiryDate: new Date(parseInt(domain.registration.expiryDate) * 1e3),
20
+ registrationDate: new Date(domain.registration.registrationDate * 1e3)
21
+ };
22
+ }
17
23
  return {
18
24
  expiryDate: new Date(parseInt(wrappedDomain.expiryDate) * 1e3),
19
25
  fuses: decodeFuses(wrappedDomain.fuses),
@@ -64,8 +64,23 @@ var raw = async ({ contracts, multicallWrapper }, name, contract) => {
64
64
  }
65
65
  return multicallWrapper.raw(data);
66
66
  };
67
+ var registrantQuery = `
68
+ query GetRegistrant($namehash: String!) {
69
+ domain(id: $namehash) {
70
+ registration {
71
+ registrant {
72
+ id
73
+ }
74
+ }
75
+ }
76
+ }
77
+ `;
67
78
  var singleContractOwnerDecode = (data) => ethers.utils.defaultAbiCoder.decode(["address"], data)[0];
68
- var decode = async ({ contracts, multicallWrapper }, data, name, contract) => {
79
+ var decode = async ({
80
+ contracts,
81
+ multicallWrapper,
82
+ gqlInstance
83
+ }, data, name, contract) => {
69
84
  if (!data)
70
85
  return;
71
86
  const labels = name.split(".");
@@ -94,8 +109,17 @@ var decode = async ({ contracts, multicallWrapper }, data, name, contract) => {
94
109
  );
95
110
  const registryOwner = decodedData[0][0];
96
111
  const nameWrapperOwner = decodedData[1][0];
97
- const registrarOwner = decodedData[2]?.[0];
112
+ let registrarOwner = decodedData[2]?.[0];
98
113
  if (labels[labels.length - 1] === "eth") {
114
+ if (!registrarOwner && labels.length === 2) {
115
+ const graphRegistrantResult = await gqlInstance?.request(
116
+ registrantQuery,
117
+ {
118
+ namehash: makeNamehash(name)
119
+ }
120
+ );
121
+ registrarOwner = graphRegistrantResult.domain?.registration?.registrant?.id;
122
+ }
99
123
  if (registrarOwner === nameWrapper.address) {
100
124
  return {
101
125
  owner: nameWrapperOwner,
@@ -109,7 +133,14 @@ var decode = async ({ contracts, multicallWrapper }, data, name, contract) => {
109
133
  ownershipLevel: "registrar"
110
134
  };
111
135
  }
112
- if (labels.length > 2 && ethers.utils.hexStripZeros(registryOwner) !== "0x") {
136
+ if (ethers.utils.hexStripZeros(registryOwner) !== "0x") {
137
+ if (labels.length === 2) {
138
+ return {
139
+ registrant: void 0,
140
+ owner: registryOwner,
141
+ ownershipLevel: "registrar"
142
+ };
143
+ }
113
144
  if (registryOwner === nameWrapper.address && nameWrapperOwner && ethers.utils.hexStripZeros(nameWrapperOwner) !== "0x") {
114
145
  return {
115
146
  owner: nameWrapperOwner,
@@ -206,7 +206,7 @@ var ENS = class {
206
206
  );
207
207
  getOwner = this.generateRawFunction(
208
208
  "initialGetters",
209
- ["contracts", "multicallWrapper"],
209
+ ["contracts", "multicallWrapper", "gqlInstance"],
210
210
  "getOwner"
211
211
  );
212
212
  getExpiry = this.generateRawFunction(
@@ -1,6 +1,6 @@
1
1
  import { ethers } from 'ethers';
2
2
  import { ENSArgs } from '..';
3
- import { FuseOptions } from '../@types/FuseOptions';
3
+ import { FuseOptions } from '../utils/fuses';
4
4
  import { Expiry } from '../utils/wrapper';
5
5
  declare type BaseArgs = {
6
6
  owner: string;
@@ -14,6 +14,10 @@ export declare type Name = {
14
14
  registrationDate?: Date;
15
15
  expiryDate?: Date;
16
16
  fuses?: CurrentFuses;
17
+ registration?: {
18
+ expiryDate: Date;
19
+ registrationDate: Date;
20
+ };
17
21
  type: 'domain' | 'registration' | 'wrappedDomain';
18
22
  };
19
23
  declare type BaseParams = {
@@ -9,6 +9,6 @@ declare const _default: {
9
9
  to: string;
10
10
  data: string;
11
11
  }>;
12
- decode: ({ contracts, multicallWrapper }: ENSArgs<"contracts" | "multicallWrapper">, data: string, name: string, contract?: "nameWrapper" | "registrar" | "registry" | undefined) => Promise<Owner | undefined>;
12
+ decode: ({ contracts, multicallWrapper, gqlInstance, }: ENSArgs<"contracts" | "gqlInstance" | "multicallWrapper">, data: string, name: string, contract?: "nameWrapper" | "registrar" | "registry" | undefined) => Promise<Owner | undefined>;
13
13
  };
14
14
  export default _default;
@@ -1,6 +1,6 @@
1
1
  import { ethers } from 'ethers';
2
2
  import { ENSArgs } from '..';
3
- import type { FuseOptions } from '../@types/FuseOptions';
3
+ import { FuseOptions } from '../utils/fuses';
4
4
  import { Expiry } from '../utils/wrapper';
5
5
  export default function ({ contracts, signer, getExpiry, }: ENSArgs<'contracts' | 'signer' | 'getExpiry'>, name: string, { wrappedOwner, fuseOptions, expiry, resolverAddress, }: {
6
6
  wrappedOwner: string;
@@ -7,6 +7,7 @@ import type burnFuses from './functions/burnFuses';
7
7
  import type commitName from './functions/commitName';
8
8
  import type createSubname from './functions/createSubname';
9
9
  import type deleteSubname from './functions/deleteSubname';
10
+ import importDNSSECName from './functions/importDNSSECName';
10
11
  import type registerName from './functions/registerName';
11
12
  import type { default as renewNames, renewNameWithData } from './functions/renewNames';
12
13
  import type setName from './functions/setName';
@@ -19,7 +20,6 @@ import type transferSubname from './functions/transferSubname';
19
20
  import type unwrapName from './functions/unwrapName';
20
21
  import type wrapName from './functions/wrapName';
21
22
  import GqlManager from './GqlManager';
22
- import importDNSSECName from './functions/importDNSSECName';
23
23
  export type { Fuse, FuseArrayPossibilities, FuseObj, NamedFusesToBurn, UnnamedFuseType, UnnamedFuseValues, } from './utils/fuses';
24
24
  declare type ENSOptions = {
25
25
  graphURI?: string | null;
@@ -344,7 +344,7 @@ export declare class ENS {
344
344
  to: string;
345
345
  data: string;
346
346
  }>;
347
- decode: ({ contracts, multicallWrapper }: ENSArgs<"contracts" | "multicallWrapper">, data: string, name: string, contract?: "nameWrapper" | "registrar" | "registry" | undefined) => Promise<{
347
+ decode: ({ contracts, multicallWrapper, gqlInstance, }: ENSArgs<"contracts" | "gqlInstance" | "multicallWrapper">, data: string, name: string, contract?: "nameWrapper" | "registrar" | "registry" | undefined) => Promise<{
348
348
  registrant?: string | undefined;
349
349
  owner?: string | undefined;
350
350
  ownershipLevel: "nameWrapper" | "registrar" | "registry";
@@ -8,6 +8,9 @@ export declare const fuseEnum: {
8
8
  readonly CANNOT_CREATE_SUBDOMAIN: 32;
9
9
  readonly PARENT_CANNOT_CONTROL: 64;
10
10
  };
11
+ export declare type FuseOptions = {
12
+ -readonly [K in keyof typeof fuseEnum]?: boolean;
13
+ };
11
14
  export declare const unnamedFuses: readonly [128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296];
12
15
  declare const fullFuseEnum: {
13
16
  CAN_DO_EVERYTHING: number;
@@ -1,3 +1,3 @@
1
- import { FuseOptions } from '../@types/FuseOptions';
1
+ import { FuseOptions } from './fuses';
2
2
  declare const _default: (fuseOptions: FuseOptions) => string;
3
3
  export default _default;
@@ -1,6 +1,6 @@
1
1
  import { BigNumberish } from 'ethers';
2
- import type { FuseOptions } from '../@types/FuseOptions';
3
2
  import type { PublicResolver } from '../generated';
3
+ import { FuseOptions } from './fuses';
4
4
  import { RecordOptions } from './recordHelpers';
5
5
  export declare const MAX_INT_64: bigint;
6
6
  export declare type BaseRegistrationParams = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ensdomains/ensjs",
3
- "version": "3.0.0-alpha.30",
3
+ "version": "3.0.0-alpha.32",
4
4
  "description": "ENS javascript library for contract interaction",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.mjs",
@@ -66,7 +66,7 @@
66
66
  "devDependencies": {
67
67
  "@ensdomains/buffer": "^0.0.13",
68
68
  "@ensdomains/ens-contracts": "^0.0.15",
69
- "@ensdomains/ens-test-env": "0.3.2",
69
+ "@ensdomains/ens-test-env": "0.3.3",
70
70
  "@ethersproject/abi": "^5.6.0",
71
71
  "@ethersproject/providers": "^5.6.2",
72
72
  "@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers",
@@ -1,6 +1,6 @@
1
1
  import { BigNumber, ethers } from 'ethers'
2
2
  import { ENSArgs } from '..'
3
- import { FuseOptions } from '../@types/FuseOptions'
3
+ import { FuseOptions } from '../utils/fuses'
4
4
  import generateFuseInput from '../utils/generateFuseInput'
5
5
  import { namehash } from '../utils/normalise'
6
6
  import { Expiry, makeExpiry, wrappedLabelLengthCheck } from '../utils/wrapper'
@@ -17,6 +17,10 @@ export type Name = {
17
17
  registrationDate?: Date
18
18
  expiryDate?: Date
19
19
  fuses?: CurrentFuses
20
+ registration?: {
21
+ expiryDate: Date
22
+ registrationDate: Date
23
+ }
20
24
  type: 'domain' | 'registration' | 'wrappedDomain'
21
25
  }
22
26
 
@@ -66,6 +70,12 @@ const mapDomain = (domain: any) => {
66
70
 
67
71
  const mapWrappedDomain = (wrappedDomain: any) => {
68
72
  const domain = mapDomain(wrappedDomain.domain)
73
+ if (domain.registration) {
74
+ domain.registration = {
75
+ expiryDate: new Date(parseInt(domain.registration.expiryDate) * 1000),
76
+ registrationDate: new Date(domain.registration.registrationDate * 1000),
77
+ }
78
+ }
69
79
  return {
70
80
  expiryDate: new Date(parseInt(wrappedDomain.expiryDate) * 1000),
71
81
  fuses: decodeFuses(wrappedDomain.fuses),
@@ -91,11 +91,27 @@ const raw = async (
91
91
  return multicallWrapper.raw(data)
92
92
  }
93
93
 
94
+ const registrantQuery = `
95
+ query GetRegistrant($namehash: String!) {
96
+ domain(id: $namehash) {
97
+ registration {
98
+ registrant {
99
+ id
100
+ }
101
+ }
102
+ }
103
+ }
104
+ `
105
+
94
106
  const singleContractOwnerDecode = (data: string) =>
95
107
  ethers.utils.defaultAbiCoder.decode(['address'], data)[0]
96
108
 
97
109
  const decode = async (
98
- { contracts, multicallWrapper }: ENSArgs<'contracts' | 'multicallWrapper'>,
110
+ {
111
+ contracts,
112
+ multicallWrapper,
113
+ gqlInstance,
114
+ }: ENSArgs<'contracts' | 'multicallWrapper' | 'gqlInstance'>,
99
115
  data: string,
100
116
  name: string,
101
117
  contract?: 'nameWrapper' | 'registry' | 'registrar',
@@ -131,12 +147,20 @@ const decode = async (
131
147
 
132
148
  const registryOwner = (decodedData[0] as ethers.utils.Result)[0]
133
149
  const nameWrapperOwner = (decodedData[1] as ethers.utils.Result)[0]
134
- const registrarOwner = (
135
- decodedData[2] as ethers.utils.Result | undefined
136
- )?.[0]
150
+ let registrarOwner = (decodedData[2] as ethers.utils.Result | undefined)?.[0]
137
151
 
138
152
  // check for only .eth names
139
153
  if (labels[labels.length - 1] === 'eth') {
154
+ if (!registrarOwner && labels.length === 2) {
155
+ const graphRegistrantResult = await gqlInstance?.request(
156
+ registrantQuery,
157
+ {
158
+ namehash: makeNamehash(name),
159
+ },
160
+ )
161
+ registrarOwner =
162
+ graphRegistrantResult.domain?.registration?.registrant?.id
163
+ }
140
164
  // if the owner on the registrar is the namewrapper, then the namewrapper owner is the owner
141
165
  // there is no "registrant" for wrapped names
142
166
  if (registrarOwner === nameWrapper.address) {
@@ -156,10 +180,16 @@ const decode = async (
156
180
  ownershipLevel: 'registrar',
157
181
  }
158
182
  }
159
- if (
160
- labels.length > 2 &&
161
- ethers.utils.hexStripZeros(registryOwner) !== '0x'
162
- ) {
183
+ if (ethers.utils.hexStripZeros(registryOwner) !== '0x') {
184
+ // if there is no registrar owner, but the label length is two, then the domain is an expired 2LD .eth
185
+ // so we still want to return the ownership values
186
+ if (labels.length === 2) {
187
+ return {
188
+ registrant: undefined,
189
+ owner: registryOwner,
190
+ ownershipLevel: 'registrar',
191
+ }
192
+ }
163
193
  // this means that the subname is wrapped
164
194
  if (
165
195
  registryOwner === nameWrapper.address &&
@@ -53,8 +53,8 @@ describe('wrapName', () => {
53
53
  const tx = await ensInstance.wrapName('test123.eth', {
54
54
  wrappedOwner: accounts[2],
55
55
  fuseOptions: {
56
- cannotUnwrap: true,
57
- cannotSetTtl: true,
56
+ CANNOT_UNWRAP: true,
57
+ CANNOT_SET_TTL: true,
58
58
  },
59
59
  addressOrIndex: 1,
60
60
  })
@@ -1,6 +1,6 @@
1
1
  import { BigNumber, ethers } from 'ethers'
2
2
  import { ENSArgs } from '..'
3
- import type { FuseOptions } from '../@types/FuseOptions'
3
+ import { FuseOptions } from '../utils/fuses'
4
4
  import generateFuseInput from '../utils/generateFuseInput'
5
5
  import { hexEncodeName } from '../utils/hexEncodedName'
6
6
  import { Expiry, makeExpiry, wrappedLabelLengthCheck } from '../utils/wrapper'
package/src/index.ts CHANGED
@@ -33,6 +33,7 @@ import type {
33
33
  } from './functions/getSpecificRecord'
34
34
  import type getSubnames from './functions/getSubnames'
35
35
  import type getWrapperData from './functions/getWrapperData'
36
+ import importDNSSECName from './functions/importDNSSECName'
36
37
  import type registerName from './functions/registerName'
37
38
  import type {
38
39
  // eslint-disable-next-line import/no-named-default
@@ -51,7 +52,6 @@ import type wrapName from './functions/wrapName'
51
52
  import GqlManager from './GqlManager'
52
53
  import singleCall from './utils/singleCall'
53
54
  import writeTx from './utils/writeTx'
54
- import importDNSSECName from './functions/importDNSSECName'
55
55
 
56
56
  export type {
57
57
  Fuse,
@@ -500,7 +500,7 @@ export class ENS {
500
500
 
501
501
  public getOwner = this.generateRawFunction<typeof getOwner>(
502
502
  'initialGetters',
503
- ['contracts', 'multicallWrapper'],
503
+ ['contracts', 'multicallWrapper', 'gqlInstance'],
504
504
  'getOwner',
505
505
  )
506
506
 
@@ -19,6 +19,8 @@ export const fuseEnum = {
19
19
  PARENT_CANNOT_CONTROL,
20
20
  } as const
21
21
 
22
+ export type FuseOptions = { -readonly [K in keyof typeof fuseEnum]?: boolean }
23
+
22
24
  export const unnamedFuses = [
23
25
  128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,
24
26
  524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864,
@@ -1,6 +1,5 @@
1
1
  import { ethers } from 'ethers'
2
- import { FuseOptions } from '../@types/FuseOptions'
3
- import fuses from './fuses'
2
+ import fuses, { FuseOptions } from './fuses'
4
3
 
5
4
  export default (fuseOptions: FuseOptions) => {
6
5
  const fuseKeys = Object.keys(fuseOptions).filter(
@@ -1,6 +1,6 @@
1
1
  import { BigNumberish, utils } from 'ethers'
2
- import type { FuseOptions } from '../@types/FuseOptions'
3
2
  import type { PublicResolver } from '../generated'
3
+ import { FuseOptions } from './fuses'
4
4
  import generateFuseInput from './generateFuseInput'
5
5
  import { labelhash } from './labels'
6
6
  import { namehash } from './normalise'
@@ -1,9 +0,0 @@
1
- export type FuseOptions = {
2
- cannotUnwrap: true
3
- cannotBurnFuses?: boolean
4
- cannotTransfer?: boolean
5
- cannotSetResolver?: boolean
6
- cannotSetTtl?: boolean
7
- cannotCreateSubdomain?: boolean
8
- parentCannotControl?: boolean
9
- }