@ensdomains/ensjs 3.0.0-alpha.20 → 3.0.0-alpha.22

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 (66) hide show
  1. package/dist/cjs/{functions/renewName.js → contracts/bulkRenewal.js} +6 -14
  2. package/dist/cjs/contracts/getContractAddress.js +2 -1
  3. package/dist/cjs/contracts/index.js +5 -0
  4. package/dist/cjs/functions/deleteSubname.js +40 -8
  5. package/dist/cjs/functions/getPrice.js +55 -8
  6. package/dist/cjs/functions/getSubnames.js +30 -94
  7. package/dist/cjs/functions/renewNames.js +42 -0
  8. package/dist/cjs/generated/BulkRenewal.js +16 -0
  9. package/dist/cjs/generated/factories/BulkRenewal__factory.js +120 -0
  10. package/dist/cjs/generated/factories/index.js +2 -0
  11. package/dist/cjs/generated/index.js +2 -0
  12. package/dist/cjs/index.js +5 -4
  13. package/dist/cjs/utils/registerHelpers.js +2 -1
  14. package/dist/esm/contracts/bulkRenewal.mjs +6 -0
  15. package/dist/esm/contracts/getContractAddress.mjs +2 -1
  16. package/dist/esm/contracts/index.mjs +5 -0
  17. package/dist/esm/functions/deleteSubname.mjs +40 -8
  18. package/dist/esm/functions/getPrice.mjs +56 -9
  19. package/dist/esm/functions/getSubnames.mjs +30 -94
  20. package/dist/esm/functions/renewNames.mjs +23 -0
  21. package/dist/esm/generated/BulkRenewal.mjs +0 -0
  22. package/dist/esm/generated/factories/BulkRenewal__factory.mjs +108 -0
  23. package/dist/esm/generated/factories/index.mjs +2 -0
  24. package/dist/esm/generated/index.mjs +2 -0
  25. package/dist/esm/index.mjs +5 -4
  26. package/dist/esm/utils/registerHelpers.mjs +2 -1
  27. package/dist/types/contracts/bulkRenewal.d.ts +3 -0
  28. package/dist/types/contracts/index.d.ts +1 -0
  29. package/dist/types/contracts/types.d.ts +1 -1
  30. package/dist/types/functions/commitName.d.ts +1 -1
  31. package/dist/types/functions/deleteSubname.d.ts +5 -2
  32. package/dist/types/functions/getPrice.d.ts +2 -2
  33. package/dist/types/functions/getSubnames.d.ts +1 -1
  34. package/dist/types/functions/registerName.d.ts +2 -5
  35. package/dist/types/functions/{renewName.d.ts → renewNames.d.ts} +2 -2
  36. package/dist/types/generated/BulkRenewal.d.ts +76 -0
  37. package/dist/types/generated/factories/BulkRenewal__factory.d.ts +32 -0
  38. package/dist/types/generated/factories/index.d.ts +1 -0
  39. package/dist/types/generated/index.d.ts +2 -0
  40. package/dist/types/index.d.ts +5 -5
  41. package/dist/types/utils/fuses.d.ts +2 -0
  42. package/dist/types/utils/registerHelpers.d.ts +13 -9
  43. package/package.json +1 -1
  44. package/src/contracts/bulkRenewal.ts +6 -0
  45. package/src/contracts/getContractAddress.ts +1 -0
  46. package/src/contracts/index.ts +6 -0
  47. package/src/contracts/types.ts +1 -0
  48. package/src/functions/deleteSubname.ts +51 -11
  49. package/src/functions/getNames.test.ts +10 -1
  50. package/src/functions/getPrice.test.ts +52 -0
  51. package/src/functions/getPrice.ts +61 -9
  52. package/src/functions/getProfile.test.ts +5 -1
  53. package/src/functions/getSubnames.test.ts +669 -29
  54. package/src/functions/getSubnames.ts +39 -98
  55. package/src/functions/registerName.ts +2 -5
  56. package/src/functions/{renewName.test.ts → renewNames.test.ts} +22 -2
  57. package/src/functions/renewNames.ts +30 -0
  58. package/src/generated/BulkRenewal.ts +197 -0
  59. package/src/generated/factories/BulkRenewal__factory.ts +108 -0
  60. package/src/generated/factories/index.ts +1 -0
  61. package/src/generated/index.ts +2 -0
  62. package/src/index.ts +6 -5
  63. package/src/utils/fuses.ts +3 -1
  64. package/src/utils/registerHelpers.ts +18 -9
  65. package/dist/esm/functions/renewName.mjs +0 -14
  66. package/src/functions/renewName.ts +0 -22
@@ -0,0 +1,76 @@
1
+ import type { BaseContract, BigNumber, BigNumberish, BytesLike, CallOverrides, ContractTransaction, PayableOverrides, PopulatedTransaction, Signer, utils } from "ethers";
2
+ import type { FunctionFragment, Result } from "@ethersproject/abi";
3
+ import type { Listener, Provider } from "@ethersproject/providers";
4
+ import type { TypedEventFilter, TypedEvent, TypedListener, OnEvent, PromiseOrValue } from "./common";
5
+ export interface BulkRenewalInterface extends utils.Interface {
6
+ functions: {
7
+ "ens()": FunctionFragment;
8
+ "renewAll(string[],uint256)": FunctionFragment;
9
+ "rentPrice(string[],uint256)": FunctionFragment;
10
+ "supportsInterface(bytes4)": FunctionFragment;
11
+ };
12
+ getFunction(nameOrSignatureOrTopic: "ens" | "renewAll" | "rentPrice" | "supportsInterface"): FunctionFragment;
13
+ encodeFunctionData(functionFragment: "ens", values?: undefined): string;
14
+ encodeFunctionData(functionFragment: "renewAll", values: [PromiseOrValue<string>[], PromiseOrValue<BigNumberish>]): string;
15
+ encodeFunctionData(functionFragment: "rentPrice", values: [PromiseOrValue<string>[], PromiseOrValue<BigNumberish>]): string;
16
+ encodeFunctionData(functionFragment: "supportsInterface", values: [PromiseOrValue<BytesLike>]): string;
17
+ decodeFunctionResult(functionFragment: "ens", data: BytesLike): Result;
18
+ decodeFunctionResult(functionFragment: "renewAll", data: BytesLike): Result;
19
+ decodeFunctionResult(functionFragment: "rentPrice", data: BytesLike): Result;
20
+ decodeFunctionResult(functionFragment: "supportsInterface", data: BytesLike): Result;
21
+ events: {};
22
+ }
23
+ export interface BulkRenewal extends BaseContract {
24
+ connect(signerOrProvider: Signer | Provider | string): this;
25
+ attach(addressOrName: string): this;
26
+ deployed(): Promise<this>;
27
+ interface: BulkRenewalInterface;
28
+ queryFilter<TEvent extends TypedEvent>(event: TypedEventFilter<TEvent>, fromBlockOrBlockhash?: string | number | undefined, toBlock?: string | number | undefined): Promise<Array<TEvent>>;
29
+ listeners<TEvent extends TypedEvent>(eventFilter?: TypedEventFilter<TEvent>): Array<TypedListener<TEvent>>;
30
+ listeners(eventName?: string): Array<Listener>;
31
+ removeAllListeners<TEvent extends TypedEvent>(eventFilter: TypedEventFilter<TEvent>): this;
32
+ removeAllListeners(eventName?: string): this;
33
+ off: OnEvent<this>;
34
+ on: OnEvent<this>;
35
+ once: OnEvent<this>;
36
+ removeListener: OnEvent<this>;
37
+ functions: {
38
+ ens(overrides?: CallOverrides): Promise<[string]>;
39
+ renewAll(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: PayableOverrides & {
40
+ from?: PromiseOrValue<string>;
41
+ }): Promise<ContractTransaction>;
42
+ rentPrice(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: CallOverrides): Promise<[BigNumber] & {
43
+ total: BigNumber;
44
+ }>;
45
+ supportsInterface(interfaceID: PromiseOrValue<BytesLike>, overrides?: CallOverrides): Promise<[boolean]>;
46
+ };
47
+ ens(overrides?: CallOverrides): Promise<string>;
48
+ renewAll(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: PayableOverrides & {
49
+ from?: PromiseOrValue<string>;
50
+ }): Promise<ContractTransaction>;
51
+ rentPrice(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: CallOverrides): Promise<BigNumber>;
52
+ supportsInterface(interfaceID: PromiseOrValue<BytesLike>, overrides?: CallOverrides): Promise<boolean>;
53
+ callStatic: {
54
+ ens(overrides?: CallOverrides): Promise<string>;
55
+ renewAll(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: CallOverrides): Promise<void>;
56
+ rentPrice(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: CallOverrides): Promise<BigNumber>;
57
+ supportsInterface(interfaceID: PromiseOrValue<BytesLike>, overrides?: CallOverrides): Promise<boolean>;
58
+ };
59
+ filters: {};
60
+ estimateGas: {
61
+ ens(overrides?: CallOverrides): Promise<BigNumber>;
62
+ renewAll(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: PayableOverrides & {
63
+ from?: PromiseOrValue<string>;
64
+ }): Promise<BigNumber>;
65
+ rentPrice(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: CallOverrides): Promise<BigNumber>;
66
+ supportsInterface(interfaceID: PromiseOrValue<BytesLike>, overrides?: CallOverrides): Promise<BigNumber>;
67
+ };
68
+ populateTransaction: {
69
+ ens(overrides?: CallOverrides): Promise<PopulatedTransaction>;
70
+ renewAll(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: PayableOverrides & {
71
+ from?: PromiseOrValue<string>;
72
+ }): Promise<PopulatedTransaction>;
73
+ rentPrice(names: PromiseOrValue<string>[], duration: PromiseOrValue<BigNumberish>, overrides?: CallOverrides): Promise<PopulatedTransaction>;
74
+ supportsInterface(interfaceID: PromiseOrValue<BytesLike>, overrides?: CallOverrides): Promise<PopulatedTransaction>;
75
+ };
76
+ }
@@ -0,0 +1,32 @@
1
+ import { Signer } from "ethers";
2
+ import type { Provider } from "@ethersproject/providers";
3
+ import type { BulkRenewal, BulkRenewalInterface } from "../BulkRenewal";
4
+ export declare class BulkRenewal__factory {
5
+ static readonly abi: ({
6
+ inputs: {
7
+ internalType: string;
8
+ name: string;
9
+ type: string;
10
+ }[];
11
+ stateMutability: string;
12
+ type: string;
13
+ name?: undefined;
14
+ outputs?: undefined;
15
+ } | {
16
+ inputs: {
17
+ internalType: string;
18
+ name: string;
19
+ type: string;
20
+ }[];
21
+ name: string;
22
+ outputs: {
23
+ internalType: string;
24
+ name: string;
25
+ type: string;
26
+ }[];
27
+ stateMutability: string;
28
+ type: string;
29
+ })[];
30
+ static createInterface(): BulkRenewalInterface;
31
+ static connect(address: string, signerOrProvider: Signer | Provider): BulkRenewal;
32
+ }
@@ -1,4 +1,5 @@
1
1
  export { BaseRegistrarImplementation__factory } from "./BaseRegistrarImplementation__factory";
2
+ export { BulkRenewal__factory } from "./BulkRenewal__factory";
2
3
  export { DNSRegistrar__factory } from "./DNSRegistrar__factory";
3
4
  export { DNSSECImpl__factory } from "./DNSSECImpl__factory";
4
5
  export { DefaultReverseResolver__factory } from "./DefaultReverseResolver__factory";
@@ -1,4 +1,5 @@
1
1
  export type { BaseRegistrarImplementation } from "./BaseRegistrarImplementation";
2
+ export type { BulkRenewal } from "./BulkRenewal";
2
3
  export type { DNSRegistrar } from "./DNSRegistrar";
3
4
  export type { DNSSECImpl } from "./DNSSECImpl";
4
5
  export type { DefaultReverseResolver } from "./DefaultReverseResolver";
@@ -39,3 +40,4 @@ export { Multicall__factory } from "./factories/Multicall__factory";
39
40
  export { NameWrapper__factory } from "./factories/NameWrapper__factory";
40
41
  export { StaticMetadataService__factory } from "./factories/StaticMetadataService__factory";
41
42
  export { UniversalResolver__factory } from "./factories/UniversalResolver__factory";
43
+ export { BulkRenewal__factory } from "./factories/BulkRenewal__factory";
@@ -8,7 +8,7 @@ import type commitName from './functions/commitName';
8
8
  import type createSubname from './functions/createSubname';
9
9
  import type deleteSubname from './functions/deleteSubname';
10
10
  import type registerName from './functions/registerName';
11
- import type renewName from './functions/renewName';
11
+ import type renewNames from './functions/renewNames';
12
12
  import type setName from './functions/setName';
13
13
  import type setRecord from './functions/setRecord';
14
14
  import type setRecords from './functions/setRecords';
@@ -367,7 +367,7 @@ export declare class ENS {
367
367
  orderDirection?: "asc" | "desc" | undefined;
368
368
  orderBy?: "labelName" | "createdAt" | undefined;
369
369
  lastSubnames?: any[] | undefined;
370
- isLargeQuery?: boolean | undefined;
370
+ search?: string | undefined;
371
371
  }) => Promise<{
372
372
  subnames: {
373
373
  id: string;
@@ -401,11 +401,11 @@ export declare class ENS {
401
401
  pageSize?: undefined;
402
402
  })) => Promise<import("./functions/getNames").Name[]>;
403
403
  getPrice: GeneratedRawFunction<{
404
- raw: ({ contracts, multicallWrapper }: ENSArgs<"contracts" | "multicallWrapper">, name: string, duration: number, legacy?: boolean | undefined) => Promise<{
404
+ raw: ({ contracts, multicallWrapper }: ENSArgs<"contracts" | "multicallWrapper">, nameOrNames: string | string[], duration: number, legacy?: boolean | undefined) => Promise<{
405
405
  to: string;
406
406
  data: string;
407
407
  }>;
408
- decode: ({ contracts, multicallWrapper }: ENSArgs<"contracts" | "multicallWrapper">, data: string, _name: string, _number: number, legacy?: boolean | undefined) => Promise<{
408
+ decode: ({ contracts, multicallWrapper }: ENSArgs<"contracts" | "multicallWrapper">, data: string, _nameOrNames: string | string[], _duration: number, legacy?: boolean | undefined) => Promise<{
409
409
  base: ethers.BigNumber;
410
410
  premium: ethers.BigNumber;
411
411
  } | undefined>;
@@ -451,5 +451,5 @@ export declare class ENS {
451
451
  transferSubname: WriteFunction<typeof transferSubname>;
452
452
  commitName: WriteFunction<typeof commitName>;
453
453
  registerName: WriteFunction<typeof registerName>;
454
- renewName: WriteFunction<typeof renewName>;
454
+ renewNames: WriteFunction<typeof renewNames>;
455
455
  }
@@ -21,6 +21,8 @@ declare const fullFuseEnum: {
21
21
  export declare type FuseObj = typeof fuseEnum;
22
22
  export declare type CurrentFuses = {
23
23
  [f in keyof FuseObj]: boolean;
24
+ } & {
25
+ CAN_DO_EVERYTHING: boolean;
24
26
  };
25
27
  export declare type UnnamedFuseType = typeof unnamedFuses;
26
28
  export declare type Fuse = keyof FuseObj;
@@ -1,20 +1,24 @@
1
+ import { BigNumberish } from 'ethers';
1
2
  import type { FuseOptions } from '../@types/FuseOptions';
2
3
  import type { PublicResolver } from '../generated';
3
4
  import { RecordOptions } from './recordHelpers';
4
- export declare type RegistrationParams = {
5
- name: string;
5
+ export declare type BaseRegistrationParams = {
6
6
  owner: string;
7
7
  duration: number;
8
8
  secret: string;
9
- resolver: PublicResolver;
9
+ resolverAddress?: string;
10
10
  records?: RecordOptions;
11
11
  reverseRecord?: boolean;
12
12
  fuses?: FuseOptions;
13
- wrapperExpiry: number;
13
+ wrapperExpiry?: BigNumberish;
14
+ };
15
+ export declare type RegistrationParams = Omit<BaseRegistrationParams, 'resolverAddress'> & {
16
+ name: string;
17
+ resolver: PublicResolver;
14
18
  };
15
19
  export declare type CommitmentParams = Omit<RegistrationParams, 'secret' | 'wrapperExpiry'> & {
16
20
  secret?: string;
17
- wrapperExpiry?: number;
21
+ wrapperExpiry?: BigNumberish;
18
22
  };
19
23
  export declare type RegistrationTuple = [
20
24
  name: string,
@@ -25,7 +29,7 @@ export declare type RegistrationTuple = [
25
29
  data: string[],
26
30
  reverseRecord: boolean,
27
31
  fuses: string,
28
- wrapperExpiry: number
32
+ wrapperExpiry: BigNumberish
29
33
  ];
30
34
  export declare type CommitmentTuple = [
31
35
  labelhash: string,
@@ -36,12 +40,12 @@ export declare type CommitmentTuple = [
36
40
  secret: string,
37
41
  reverseRecord: boolean,
38
42
  fuses: string,
39
- wrapperExpiry: number
43
+ wrapperExpiry: BigNumberish
40
44
  ];
41
45
  export declare const randomSecret: () => string;
42
46
  export declare const makeCommitmentData: ({ name, owner, duration, resolver, records, reverseRecord, fuses, wrapperExpiry, secret, }: Omit<RegistrationParams, "secret" | "wrapperExpiry"> & {
43
47
  secret?: string | undefined;
44
- wrapperExpiry?: number | undefined;
48
+ wrapperExpiry?: BigNumberish | undefined;
45
49
  } & {
46
50
  secret: string;
47
51
  }) => CommitmentTuple;
@@ -50,5 +54,5 @@ export declare const _makeCommitment: (params: CommitmentTuple) => string;
50
54
  export declare const makeCommitment: ({ secret, ...inputParams }: CommitmentParams) => {
51
55
  secret: string;
52
56
  commitment: string;
53
- wrapperExpiry: number;
57
+ wrapperExpiry: BigNumberish;
54
58
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ensdomains/ensjs",
3
- "version": "3.0.0-alpha.20",
3
+ "version": "3.0.0-alpha.22",
4
4
  "description": "ENS javascript library for contract interaction",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.mjs",
@@ -0,0 +1,6 @@
1
+ import { ethers } from 'ethers'
2
+ import { BulkRenewal__factory } from '../generated/factories/BulkRenewal__factory'
3
+
4
+ // Use a higher-order function to overide the address that is passed in from getContractAddress()
5
+ export default (provider: ethers.providers.JsonRpcProvider, address: string) =>
6
+ BulkRenewal__factory.connect(address, provider)
@@ -35,6 +35,7 @@ const addresses: Record<
35
35
  '1': '0x580AF46E06DaaD47eb5940526FD64d95b815Cb70',
36
36
  '4': '0x74e20bd2a1fe0cdbe45b9a1d89cb7e0a45b36376',
37
37
  },
38
+ BulkRenewal: '0xfF252725f6122A92551A5FA9a6b6bf10eb0Be035',
38
39
  /* eslint-enable @typescript-eslint/naming-convention */
39
40
  }
40
41
 
@@ -9,6 +9,7 @@ import getRegistry from './registry'
9
9
  import getReverseRegistrar from './reverseRegistrar'
10
10
  import { ContractName } from './types'
11
11
  import getUniversalResolver from './universalResolver'
12
+ import getBulkRenewal from './bulkRenewal'
12
13
 
13
14
  export default class ContractManager {
14
15
  private provider: ethers.providers.Provider
@@ -73,4 +74,9 @@ export default class ContractManager {
73
74
  )
74
75
 
75
76
  public getMulticall = this.generateContractGetter('Multicall', getMulticall)
77
+
78
+ public getBulkRenewal = this.generateContractGetter(
79
+ 'BulkRenewal',
80
+ getBulkRenewal,
81
+ )
76
82
  }
@@ -9,3 +9,4 @@ export type ContractName =
9
9
  | 'ENSRegistryWithFallback'
10
10
  | 'ReverseRegistrar'
11
11
  | 'UniversalResolver'
12
+ | 'BulkRenewal'
@@ -1,17 +1,57 @@
1
+ import { ethers } from 'ethers'
1
2
  import { ENSArgs } from '..'
3
+ import { namehash } from '../utils/normalise'
4
+
5
+ type Args = {
6
+ contract: 'registry' | 'nameWrapper'
7
+ }
2
8
 
3
9
  export default async function (
4
- { transferSubname, signer }: ENSArgs<'transferSubname' | 'signer'>,
10
+ { contracts, signer }: ENSArgs<'contracts' | 'signer' | 'getExpiry'>,
5
11
  name: string,
6
- {
7
- contract,
8
- }: {
9
- contract: 'registry' | 'nameWrapper'
10
- },
12
+ { contract }: Args,
11
13
  ) {
12
- return transferSubname.populateTransaction(name, {
13
- contract,
14
- owner: '0x0000000000000000000000000000000000000000',
15
- signer,
16
- })
14
+ const labels = name.split('.')
15
+
16
+ if (labels.length !== 3) {
17
+ throw new Error('ENS.js currently only supports deleting 2LDs, not TLDs')
18
+ }
19
+
20
+ if (labels[2] !== 'eth') {
21
+ throw new Error('ENS.js currently only supports deleting .eth 2LDs')
22
+ }
23
+
24
+ const label = labels.shift() as string
25
+ const labelhash = ethers.utils.solidityKeccak256(['string'], [label])
26
+ const parentNodehash = namehash(labels.join('.'))
27
+
28
+ switch (contract) {
29
+ case 'registry': {
30
+ const registry = (await contracts!.getRegistry()!).connect(signer)
31
+
32
+ return registry.populateTransaction.setSubnodeRecord(
33
+ parentNodehash,
34
+ labelhash,
35
+ '0x0000000000000000000000000000000000000000',
36
+ '0x0000000000000000000000000000000000000000',
37
+ 0,
38
+ )
39
+ }
40
+ case 'nameWrapper': {
41
+ const nameWrapper = (await contracts!.getNameWrapper()!).connect(signer)
42
+
43
+ return nameWrapper.populateTransaction.setSubnodeRecord(
44
+ parentNodehash,
45
+ label,
46
+ '0x0000000000000000000000000000000000000000',
47
+ '0x0000000000000000000000000000000000000000',
48
+ 0,
49
+ 0,
50
+ 0,
51
+ )
52
+ }
53
+ default: {
54
+ throw new Error(`Unknown contract: ${contract}`)
55
+ }
56
+ }
17
57
  }
@@ -30,9 +30,12 @@ const letterItems = [
30
30
 
31
31
  const domainLetterItems = [
32
32
  '[',
33
+ 'x',
33
34
  'w',
34
35
  't',
35
36
  't',
37
+ 'l',
38
+ 'a',
36
39
  '9',
37
40
  '8',
38
41
  '7',
@@ -137,7 +140,13 @@ describe('getNames', () => {
137
140
  type: 'owner',
138
141
  page: 3,
139
142
  })
140
- expect(pageFour).toHaveLength(totalOwnedNames % 10)
143
+ expect(pageFour).toHaveLength(10)
144
+ const pageFive = await ensInstance.getNames({
145
+ address: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
146
+ type: 'owner',
147
+ page: 4,
148
+ })
149
+ expect(pageFive).toHaveLength(totalOwnedNames % 10)
141
150
  })
142
151
  describe('orderBy', () => {
143
152
  describe('registrations', () => {
@@ -0,0 +1,52 @@
1
+ import { ENS } from '..'
2
+ import setup from '../tests/setup'
3
+
4
+ let ensInstance: ENS
5
+
6
+ beforeAll(async () => {
7
+ ;({ ensInstance } = await setup())
8
+ })
9
+
10
+ describe('getPrice', () => {
11
+ it('should return a base and premium price for an address', async () => {
12
+ const { base, premium } = (await ensInstance.getPrice(
13
+ 'test123',
14
+ 86400,
15
+ false,
16
+ ))!
17
+ expect(base.toNumber()).toBe(86400)
18
+ expect(premium.toNumber()).toBe(0)
19
+ })
20
+
21
+ it('should return a base and premium price for an array of names', async () => {
22
+ const { base, premium } = (await ensInstance.getPrice(
23
+ ['test123', 'to-be-renewed'],
24
+ 86400,
25
+ false,
26
+ ))!
27
+ expect(base.toNumber()).toBe(86400 * 2)
28
+ expect(premium.toNumber()).toBe(0)
29
+ })
30
+
31
+ describe('legacy mode', () => {
32
+ it('should return a base and premium price for an address', async () => {
33
+ const { base, premium } = (await ensInstance.getPrice(
34
+ 'test123',
35
+ 86400,
36
+ true,
37
+ ))!
38
+ expect(base.toNumber()).toBe(86400)
39
+ expect(premium.toNumber()).toBe(0)
40
+ })
41
+
42
+ it('should return a base and premium price for an array of names', async () => {
43
+ const { base, premium } = (await ensInstance.getPrice(
44
+ ['test123', 'to-be-renewed'],
45
+ 86400,
46
+ true,
47
+ ))!
48
+ expect(base.toNumber()).toBe(86400 * 2)
49
+ expect(premium.toNumber()).toBe(0)
50
+ })
51
+ })
52
+ })
@@ -3,16 +3,44 @@ import { ENSArgs } from '..'
3
3
 
4
4
  const raw = async (
5
5
  { contracts, multicallWrapper }: ENSArgs<'contracts' | 'multicallWrapper'>,
6
- name: string,
6
+ nameOrNames: string | string[],
7
7
  duration: number,
8
8
  legacy?: boolean,
9
9
  ) => {
10
+ const names = Array.isArray(nameOrNames) ? nameOrNames : [nameOrNames]
11
+
12
+ if (names.length > 1) {
13
+ const bulkRenewal = await contracts?.getBulkRenewal()!
14
+ const baseCall = {
15
+ to: bulkRenewal.address,
16
+ data: bulkRenewal.interface.encodeFunctionData('rentPrice', [
17
+ names,
18
+ duration,
19
+ ]),
20
+ }
21
+
22
+ if (legacy) {
23
+ return multicallWrapper.raw([
24
+ baseCall,
25
+ {
26
+ to: bulkRenewal.address,
27
+ data: bulkRenewal.interface.encodeFunctionData('rentPrice', [
28
+ names,
29
+ 0,
30
+ ]),
31
+ },
32
+ ])
33
+ }
34
+
35
+ return baseCall
36
+ }
37
+
10
38
  const controller = await contracts?.getEthRegistrarController()!
11
39
 
12
40
  const baseCall = {
13
41
  to: controller.address,
14
42
  data: controller.interface.encodeFunctionData('rentPrice', [
15
- name,
43
+ names[0],
16
44
  duration,
17
45
  ]),
18
46
  }
@@ -22,27 +50,49 @@ const raw = async (
22
50
  baseCall,
23
51
  {
24
52
  to: controller.address,
25
- data: controller.interface.encodeFunctionData('rentPrice', [name, 0]),
53
+ data: controller.interface.encodeFunctionData('rentPrice', [
54
+ names[0],
55
+ 0,
56
+ ]),
26
57
  },
27
58
  ])
28
59
  }
29
-
30
60
  return baseCall
31
61
  }
32
62
 
33
63
  const decode = async (
34
64
  { contracts, multicallWrapper }: ENSArgs<'contracts' | 'multicallWrapper'>,
35
65
  data: string,
36
- _name: string,
37
- _number: number,
66
+ _nameOrNames: string | string[],
67
+ _duration: number,
38
68
  legacy?: boolean,
39
69
  ) => {
40
70
  if (data === null) return
41
- const controller = await contracts?.getEthRegistrarController()!
42
71
  try {
43
72
  let base: BigNumber
44
73
  let premium: BigNumber
45
- if (legacy) {
74
+
75
+ const isBulkRenewal = Array.isArray(_nameOrNames) && _nameOrNames.length > 1
76
+ if (isBulkRenewal && legacy) {
77
+ const result = await multicallWrapper.decode(data)
78
+ const [price] = utils.defaultAbiCoder.decode(
79
+ ['uint256'],
80
+ result[0].returnData,
81
+ ) as [BigNumber]
82
+ ;[premium] = utils.defaultAbiCoder.decode(
83
+ ['uint256'],
84
+ result[1].returnData,
85
+ ) as [BigNumber]
86
+ base = price.sub(premium)
87
+ } else if (isBulkRenewal) {
88
+ const bulkRenewal = await contracts?.getBulkRenewal()!
89
+ const result = bulkRenewal.interface.decodeFunctionResult(
90
+ 'rentPrice',
91
+ data,
92
+ )
93
+ ;[base] = result
94
+ premium = BigNumber.from(0)
95
+ } else if (!isBulkRenewal && legacy) {
46
96
  const result = await multicallWrapper.decode(data)
47
97
  const [price] = utils.defaultAbiCoder.decode(
48
98
  ['uint256'],
@@ -54,10 +104,12 @@ const decode = async (
54
104
  ) as [BigNumber]
55
105
  base = price.sub(premium)
56
106
  } else {
57
- ;[[base, premium]] = controller.interface.decodeFunctionResult(
107
+ const controller = await contracts?.getEthRegistrarController()!
108
+ const result = controller.interface.decodeFunctionResult(
58
109
  'rentPrice',
59
110
  data,
60
111
  )
112
+ ;[base, premium] = result[0] as [BigNumber, BigNumber]
61
113
  }
62
114
  return {
63
115
  base,
@@ -1,7 +1,10 @@
1
1
  import { ethers } from 'ethers'
2
+ import dotenv from 'dotenv'
2
3
  import { ENS } from '..'
3
4
  import setup from '../tests/setup'
4
5
 
6
+ dotenv.config()
7
+
5
8
  let ensInstance: ENS
6
9
  let revert: Awaited<ReturnType<typeof setup>>['revert']
7
10
  let provider: ethers.providers.JsonRpcProvider
@@ -120,13 +123,14 @@ describe('getProfile', () => {
120
123
  describe('with an old resolver', () => {
121
124
  it('should use fallback methods for a name with an older resolver (no multicall)', async () => {
122
125
  const result = await ensInstance.getProfile('with-legacy-resolver.eth')
126
+ const deploymentAddresses = JSON.parse(process.env.DEPLOYMENT_ADDRESSES!)
123
127
  expect(result).toBeDefined()
124
128
  if (result) {
125
129
  expect(result.address).toBe(
126
130
  '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
127
131
  )
128
132
  expect(result.resolverAddress).toBe(
129
- '0x5f3f1dbd7b74c6b46e8c44f98792a1daf8d69154',
133
+ deploymentAddresses.NoMulticallResolver.toLowerCase(),
130
134
  )
131
135
  }
132
136
  })