@ensdomains/ensjs 3.0.0-alpha.42 → 3.0.0-alpha.44

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 (153) hide show
  1. package/dist/cjs/contracts/getContractAddress.js +3 -3
  2. package/dist/cjs/functions/batch.js +14 -6
  3. package/dist/cjs/functions/getDecryptedName.js +111 -0
  4. package/dist/cjs/functions/getExpiry.js +2 -1
  5. package/dist/cjs/functions/getHistory.js +16 -9
  6. package/dist/cjs/functions/getOwner.js +5 -4
  7. package/dist/cjs/functions/getPrice.js +6 -6
  8. package/dist/cjs/functions/getProfile.js +11 -5
  9. package/dist/cjs/functions/getWrapperData.js +2 -2
  10. package/dist/cjs/functions/unwrapName.js +2 -1
  11. package/dist/cjs/functions/wrapName.js +4 -3
  12. package/dist/cjs/generated/factories/BaseRegistrarImplementation__factory.js +2 -2
  13. package/dist/cjs/generated/factories/BulkRenewal__factory.js +2 -2
  14. package/dist/cjs/generated/factories/DNSRegistrar__factory.js +2 -2
  15. package/dist/cjs/generated/factories/DNSSECImpl__factory.js +2 -2
  16. package/dist/cjs/generated/factories/DefaultReverseResolver__factory.js +2 -2
  17. package/dist/cjs/generated/factories/ENSRegistry__factory.js +2 -2
  18. package/dist/cjs/generated/factories/ETHRegistrarController__factory.js +2 -2
  19. package/dist/cjs/generated/factories/Multicall__factory.js +2 -2
  20. package/dist/cjs/generated/factories/NameWrapper__factory.js +2 -2
  21. package/dist/cjs/generated/factories/P256SHA256Algorithm__factory.js +2 -2
  22. package/dist/cjs/generated/factories/PublicResolver__factory.js +2 -2
  23. package/dist/cjs/generated/factories/RSASHA1Algorithm__factory.js +2 -2
  24. package/dist/cjs/generated/factories/RSASHA256Algorithm__factory.js +2 -2
  25. package/dist/cjs/generated/factories/ReverseRegistrar__factory.js +2 -2
  26. package/dist/cjs/generated/factories/Root__factory.js +2 -2
  27. package/dist/cjs/generated/factories/SHA1Digest__factory.js +2 -2
  28. package/dist/cjs/generated/factories/SHA1NSEC3Digest__factory.js +2 -2
  29. package/dist/cjs/generated/factories/SHA256Digest__factory.js +2 -2
  30. package/dist/cjs/generated/factories/StaticMetadataService__factory.js +2 -2
  31. package/dist/cjs/generated/factories/TLDPublicSuffixList__factory.js +2 -2
  32. package/dist/cjs/generated/factories/UniversalResolver__factory.js +2 -2
  33. package/dist/cjs/index.js +2 -1
  34. package/dist/cjs/utils/ccip.js +4 -4
  35. package/dist/cjs/utils/fuses.js +3 -2
  36. package/dist/cjs/utils/hexEncodedName.js +2 -0
  37. package/dist/cjs/utils/labels.js +14 -8
  38. package/dist/cjs/utils/registerHelpers.js +2 -2
  39. package/dist/cjs/utils/singleCall.js +9 -1
  40. package/dist/cjs/utils/validation.js +2 -0
  41. package/dist/cjs/utils/wrapper.js +1 -1
  42. package/dist/esm/contracts/getContractAddress.mjs +3 -3
  43. package/dist/esm/functions/batch.mjs +14 -6
  44. package/dist/esm/functions/getDecryptedName.mjs +96 -0
  45. package/dist/esm/functions/getExpiry.mjs +2 -1
  46. package/dist/esm/functions/getHistory.mjs +16 -9
  47. package/dist/esm/functions/getOwner.mjs +3 -2
  48. package/dist/esm/functions/getPrice.mjs +2 -2
  49. package/dist/esm/functions/getProfile.mjs +10 -4
  50. package/dist/esm/functions/getWrapperData.mjs +2 -2
  51. package/dist/esm/functions/unwrapName.mjs +2 -1
  52. package/dist/esm/functions/wrapName.mjs +3 -2
  53. package/dist/esm/generated/factories/BaseRegistrarImplementation__factory.mjs +1 -1
  54. package/dist/esm/generated/factories/BulkRenewal__factory.mjs +1 -1
  55. package/dist/esm/generated/factories/DNSRegistrar__factory.mjs +1 -1
  56. package/dist/esm/generated/factories/DNSSECImpl__factory.mjs +1 -1
  57. package/dist/esm/generated/factories/DefaultReverseResolver__factory.mjs +1 -1
  58. package/dist/esm/generated/factories/ENSRegistry__factory.mjs +1 -1
  59. package/dist/esm/generated/factories/ETHRegistrarController__factory.mjs +1 -1
  60. package/dist/esm/generated/factories/Multicall__factory.mjs +1 -1
  61. package/dist/esm/generated/factories/NameWrapper__factory.mjs +1 -1
  62. package/dist/esm/generated/factories/P256SHA256Algorithm__factory.mjs +1 -1
  63. package/dist/esm/generated/factories/PublicResolver__factory.mjs +1 -1
  64. package/dist/esm/generated/factories/RSASHA1Algorithm__factory.mjs +1 -1
  65. package/dist/esm/generated/factories/RSASHA256Algorithm__factory.mjs +1 -1
  66. package/dist/esm/generated/factories/ReverseRegistrar__factory.mjs +1 -1
  67. package/dist/esm/generated/factories/Root__factory.mjs +1 -1
  68. package/dist/esm/generated/factories/SHA1Digest__factory.mjs +1 -1
  69. package/dist/esm/generated/factories/SHA1NSEC3Digest__factory.mjs +1 -1
  70. package/dist/esm/generated/factories/SHA256Digest__factory.mjs +1 -1
  71. package/dist/esm/generated/factories/StaticMetadataService__factory.mjs +1 -1
  72. package/dist/esm/generated/factories/TLDPublicSuffixList__factory.mjs +1 -1
  73. package/dist/esm/generated/factories/UniversalResolver__factory.mjs +1 -1
  74. package/dist/esm/index.mjs +2 -1
  75. package/dist/esm/utils/ccip.mjs +3 -3
  76. package/dist/esm/utils/fuses.mjs +3 -2
  77. package/dist/esm/utils/hexEncodedName.mjs +2 -0
  78. package/dist/esm/utils/labels.mjs +11 -8
  79. package/dist/esm/utils/registerHelpers.mjs +1 -1
  80. package/dist/esm/utils/singleCall.mjs +9 -1
  81. package/dist/esm/utils/validation.mjs +2 -0
  82. package/dist/esm/utils/wrapper.mjs +1 -1
  83. package/dist/types/functions/batch.d.ts +8 -1
  84. package/dist/types/functions/getDecryptedName.d.ts +9 -0
  85. package/dist/types/functions/getHistory.d.ts +16 -0
  86. package/dist/types/functions/getPrice.d.ts +1 -1
  87. package/dist/types/functions/getProfile.d.ts +1 -0
  88. package/dist/types/functions/getRecords.d.ts +1 -0
  89. package/dist/types/functions/registerName.d.ts +1 -1
  90. package/dist/types/functions/renewNames.d.ts +1 -1
  91. package/dist/types/functions/types.d.ts +2 -0
  92. package/dist/types/index.d.ts +32 -1
  93. package/dist/types/static.d.ts +1 -1
  94. package/dist/types/utils/fuses.d.ts +1 -0
  95. package/dist/types/utils/hexEncodedName.d.ts +1 -0
  96. package/dist/types/utils/labels.d.ts +2 -1
  97. package/dist/types/utils/singleCall.d.ts +1 -0
  98. package/dist/types/utils/validation.d.ts +1 -0
  99. package/dist/types/utils/wrapper.d.ts +1 -1
  100. package/package.json +2 -2
  101. package/src/contracts/getContractAddress.ts +3 -3
  102. package/src/functions/batch.ts +15 -5
  103. package/src/functions/ccip.test.ts +62 -0
  104. package/src/functions/createSubname.ts +1 -1
  105. package/src/functions/getDecryptedName.test.ts +49 -0
  106. package/src/functions/getDecryptedName.ts +119 -0
  107. package/src/functions/getExpiry.ts +3 -2
  108. package/src/functions/getHistory.test.ts +11 -0
  109. package/src/functions/getHistory.ts +16 -9
  110. package/src/functions/getNames.test.ts +1 -1
  111. package/src/functions/getOwner.ts +4 -3
  112. package/src/functions/getPrice.ts +2 -2
  113. package/src/functions/getProfile.test.ts +7 -0
  114. package/src/functions/getProfile.ts +13 -4
  115. package/src/functions/getWrapperData.test.ts +3 -0
  116. package/src/functions/getWrapperData.ts +2 -2
  117. package/src/functions/registerName.ts +1 -1
  118. package/src/functions/renewNames.ts +1 -1
  119. package/src/functions/types.ts +2 -0
  120. package/src/functions/unwrapName.ts +2 -1
  121. package/src/functions/wrapName.ts +3 -2
  122. package/src/generated/factories/BaseRegistrarImplementation__factory.ts +1 -1
  123. package/src/generated/factories/BulkRenewal__factory.ts +1 -1
  124. package/src/generated/factories/DNSRegistrar__factory.ts +1 -1
  125. package/src/generated/factories/DNSSECImpl__factory.ts +1 -1
  126. package/src/generated/factories/DefaultReverseResolver__factory.ts +1 -1
  127. package/src/generated/factories/ENSRegistry__factory.ts +1 -1
  128. package/src/generated/factories/ETHRegistrarController__factory.ts +1 -1
  129. package/src/generated/factories/Multicall__factory.ts +1 -1
  130. package/src/generated/factories/NameWrapper__factory.ts +1 -1
  131. package/src/generated/factories/P256SHA256Algorithm__factory.ts +1 -1
  132. package/src/generated/factories/PublicResolver__factory.ts +1 -1
  133. package/src/generated/factories/RSASHA1Algorithm__factory.ts +1 -1
  134. package/src/generated/factories/RSASHA256Algorithm__factory.ts +1 -1
  135. package/src/generated/factories/ReverseRegistrar__factory.ts +1 -1
  136. package/src/generated/factories/Root__factory.ts +1 -1
  137. package/src/generated/factories/SHA1Digest__factory.ts +1 -1
  138. package/src/generated/factories/SHA1NSEC3Digest__factory.ts +1 -1
  139. package/src/generated/factories/SHA256Digest__factory.ts +1 -1
  140. package/src/generated/factories/StaticMetadataService__factory.ts +1 -1
  141. package/src/generated/factories/TLDPublicSuffixList__factory.ts +1 -1
  142. package/src/generated/factories/UniversalResolver__factory.ts +1 -1
  143. package/src/index.ts +5 -1
  144. package/src/static.ts +1 -1
  145. package/src/utils/ccip.ts +3 -3
  146. package/src/utils/fuses.ts +4 -4
  147. package/src/utils/hexEncodedName.ts +3 -0
  148. package/src/utils/labels.ts +13 -11
  149. package/src/utils/registerHelpers.ts +1 -1
  150. package/src/utils/singleCall.ts +11 -6
  151. package/src/utils/validation.ts +3 -0
  152. package/src/utils/wrapper.ts +1 -1
  153. package/src/functions/getProfile-ccip.test.ts +0 -29
@@ -4,6 +4,7 @@ import type commitName from './commitName';
4
4
  import type createSubname from './createSubname';
5
5
  import type deleteSubname from './deleteSubname';
6
6
  import type getAvailable from './getAvailable';
7
+ import type getDecryptedName from './getDecryptedName';
7
8
  import type getDNSOwner from './getDNSOwner';
8
9
  import type getExpiry from './getExpiry';
9
10
  import type { getHistory } from './getHistory';
@@ -43,6 +44,7 @@ declare type Function = {
43
44
  createSubname: typeof createSubname;
44
45
  deleteSubname: typeof deleteSubname;
45
46
  getAvailable: typeof getAvailable;
47
+ getDecryptedName: typeof getDecryptedName;
46
48
  getDNSOwner: typeof getDNSOwner;
47
49
  getExpiry: typeof getExpiry;
48
50
  getHistory: typeof getHistory;
@@ -133,10 +133,16 @@ export declare class ENS {
133
133
  withProvider: (provider: JsonRpcProvider) => ENS;
134
134
  batch: GeneratedBatchFunction<{
135
135
  raw: ({ multicallWrapper }: ENSArgs<"multicallWrapper">, ...items: BatchFunctionResult<RawFunction>[]) => Promise<{
136
+ passthrough: {
137
+ to: string;
138
+ data: string;
139
+ }[];
136
140
  to: string;
137
141
  data: string;
138
142
  }>;
139
- decode: ({ multicallWrapper }: ENSArgs<"multicallWrapper">, data: string, ...items: BatchFunctionResult<RawFunction>[]) => Promise<any[] | undefined>;
143
+ decode: ({ multicallWrapper }: ENSArgs<"multicallWrapper">, data: string, passthrough: import("@ethersproject/abstract-provider").TransactionRequest & {
144
+ passthrough?: any;
145
+ }[], ...items: BatchFunctionResult<RawFunction>[]) => Promise<any[] | undefined>;
140
146
  }>;
141
147
  getProfile: (nameOrAddress: string, options?: ({
142
148
  contentHash?: boolean | undefined;
@@ -154,6 +160,7 @@ export declare class ENS {
154
160
  createdAt: string | null;
155
161
  address?: string | undefined;
156
162
  name?: string | null | undefined;
163
+ decryptedName?: string | null | undefined;
157
164
  match?: boolean | undefined;
158
165
  message?: string | undefined;
159
166
  records?: {
@@ -185,6 +192,7 @@ export declare class ENS {
185
192
  createdAt: string | null;
186
193
  address?: string | undefined;
187
194
  name?: string | null | undefined;
195
+ decryptedName?: string | null | undefined;
188
196
  match?: boolean | undefined;
189
197
  message?: string | undefined;
190
198
  records?: {
@@ -304,6 +312,22 @@ export declare class ENS {
304
312
  id: string;
305
313
  data: object;
306
314
  }[];
315
+ } | {
316
+ domain: {
317
+ type: "Transfer" | "NewOwner" | "NewResolver" | "NewTTL" | "ExpiryExtended" | "FusesSet" | "NameUnwrapped" | "NameWrapped" | "WrappedTransfer";
318
+ blockNumber: number;
319
+ transactionHash: string;
320
+ id: string;
321
+ data: object;
322
+ }[];
323
+ resolver: {
324
+ type: "AddrChanged" | "ContenthashChanged" | "InterfaceChanged" | "NameChanged" | "PubkeyChanged" | "TextChanged" | "VersionChanged" | "MulticoinAddrChanged" | "AbiChanged" | "AuthorisationChanged";
325
+ blockNumber: number;
326
+ transactionHash: string;
327
+ id: string;
328
+ data: object;
329
+ }[];
330
+ registration?: undefined;
307
331
  } | undefined>;
308
332
  getContentHash: GeneratedRawFunction<{
309
333
  raw: ({ contracts, universalWrapper }: ENSArgs<"contracts" | "universalWrapper">, name: string) => Promise<{
@@ -490,6 +514,13 @@ export declare class ENS {
490
514
  }>;
491
515
  decode: ({ contracts }: ENSArgs<"contracts">, data: string) => Promise<boolean | undefined>;
492
516
  }>;
517
+ getDecryptedName: GeneratedRawFunction<{
518
+ raw: ({ contracts }: ENSArgs<"contracts">, name: string, allowIncomplete?: boolean | undefined) => Promise<{
519
+ to: string;
520
+ data: string;
521
+ }>;
522
+ decode: ({ contracts, gqlInstance }: ENSArgs<"contracts" | "gqlInstance">, data: string, name: string, allowIncomplete?: boolean) => Promise<any>;
523
+ }>;
493
524
  universalWrapper: GeneratedRawFunction<{
494
525
  raw: ({ contracts }: ENSArgs<"contracts">, name: string, data: string) => Promise<{
495
526
  to: string;
@@ -1,4 +1,4 @@
1
- import type { StaticJsonRpcProvider } from '@ethersproject/providers/lib/url-json-rpc-provider';
1
+ import type { StaticJsonRpcProvider } from '@ethersproject/providers';
2
2
  import { gql, GraphQLClient } from 'graphql-request';
3
3
  import { ENS, FunctionSubtype } from './index';
4
4
  import type Factories from './contracts/factories';
@@ -30,6 +30,7 @@ export declare const userSettableFuseEnum: {
30
30
  };
31
31
  export declare const fullFuseEnum: {
32
32
  CAN_DO_EVERYTHING: number;
33
+ IS_DOT_ETH: 131072;
33
34
  PARENT_CANNOT_CONTROL: number;
34
35
  CAN_EXTEND_EXPIRY: number;
35
36
  CANNOT_UNWRAP: 1;
@@ -1 +1,2 @@
1
1
  export declare const hexEncodeName: (name: string) => string;
2
+ export declare const hexDecodeName: (hex: string) => string;
@@ -5,10 +5,11 @@ export declare function encodeLabelhash(hash: string): string;
5
5
  export declare function isEncodedLabelhash(hash: string): boolean;
6
6
  export declare function saveLabel(label: string): string;
7
7
  export declare function saveName(name: string): void;
8
- export declare function checkLabel(hash: string): string | undefined;
8
+ export declare function checkLabel(hash: string): string;
9
9
  export declare function encodeLabel(label: any): any;
10
10
  export declare function parseName(name: string): string;
11
11
  export declare function checkIsDecrypted(string: string | string[]): boolean;
12
12
  export declare function decryptName(name: string): string;
13
13
  export declare const truncateUndecryptedName: (name: string) => string;
14
14
  export declare function checkLocalStorageSize(): string;
15
+ export declare const getEncryptedLabelAmount: (name: string) => number;
@@ -3,6 +3,7 @@ declare const _default: (provider: Provider, ensData: any, func: {
3
3
  raw: (...args: any[]) => Promise<{
4
4
  to: string;
5
5
  data: string;
6
+ passthrough?: any;
6
7
  }>;
7
8
  decode: (...args: any[]) => Promise<any>;
8
9
  }, ...data: any[]) => Promise<any>;
@@ -5,4 +5,5 @@ declare type InputType = {
5
5
  info?: 'short' | 'supported' | 'unsupported';
6
6
  };
7
7
  export declare const parseInputType: (input: string) => InputType;
8
+ export declare const checkIsDotEth: (labels: string[]) => boolean;
8
9
  export {};
@@ -1,4 +1,4 @@
1
- import { BigNumber } from '@ethersproject/bignumber/lib/bignumber';
1
+ import { BigNumber } from '@ethersproject/bignumber';
2
2
  import { ENSArgs } from '../index';
3
3
  export declare type Expiry = string | number | Date | BigNumber;
4
4
  export declare const MAX_EXPIRY: BigNumber;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ensdomains/ensjs",
3
- "version": "3.0.0-alpha.42",
3
+ "version": "3.0.0-alpha.44",
4
4
  "description": "ENS javascript library for contract interaction",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.mjs",
@@ -69,7 +69,7 @@
69
69
  },
70
70
  "devDependencies": {
71
71
  "@ensdomains/buffer": "^0.0.13",
72
- "@ensdomains/ens-contracts": "^0.0.16",
72
+ "@ensdomains/ens-contracts": "^0.0.17",
73
73
  "@ensdomains/ens-test-env": "0.3.7",
74
74
  "@ethersproject/abi": "^5.6.4",
75
75
  "@ethersproject/abstract-provider": "^5.7.0",
@@ -20,19 +20,19 @@ const addresses: Record<
20
20
  '1': '0x283af0b28c62c092c9727f1ee09c02ca627eb7f5',
21
21
  '3': '0xa5627AB7Ae47063B533622C34FEBDb52d3281dF8',
22
22
  '4': '0x283af0b28c62c092c9727f1ee09c02ca627eb7f5',
23
- '5': '0xb7A1f9e633fdeaAa2ec44bE00a61a7Db9a733D70',
23
+ '5': '0x603A4F2e7615d0099244496883062bA2eFBbeaf0',
24
24
  },
25
25
  Multicall: '0xcA11bde05977b3631167028862bE2a173976CA11',
26
26
  NameWrapper: {
27
27
  '1': '0x0000000000000000000000000000000000000000',
28
28
  '3': '0xF82155e2a43Be0871821E9654Fc8Ae894FB8307C',
29
29
  '4': '0x0000000000000000000000000000000000000000',
30
- '5': '0xEe1F756aCde7E81B2D8cC6aB3c8A1E2cE6db0F39',
30
+ '5': '0x060f1546642E67c485D56248201feA2f9AB1803C',
31
31
  },
32
32
  PublicResolver: {
33
33
  '1': '0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41',
34
34
  '3': '0x13F0659Ee6bb7484C884FEeFb7F75C93951ef837',
35
- '5': '0x2800Ec5BAB9CE9226d19E0ad5BC607e3cfC4347E',
35
+ '5': '0x19c2d5D0f035563344dBB7bE5fD09c8dad62b001',
36
36
  },
37
37
  ENSRegistry: {
38
38
  '1': '0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e',
@@ -1,3 +1,4 @@
1
+ import { TransactionRequest } from '@ethersproject/abstract-provider'
1
2
  import { BatchFunctionResult, ENSArgs, RawFunction } from '..'
2
3
 
3
4
  const raw = async (
@@ -12,21 +13,30 @@ const raw = async (
12
13
  return rawRef(...args)
13
14
  }),
14
15
  )
15
- return multicallWrapper.raw(rawDataArr)
16
+ const response = await multicallWrapper.raw(rawDataArr)
17
+ return { ...response, passthrough: rawDataArr }
16
18
  }
17
19
 
18
20
  const decode = async (
19
21
  { multicallWrapper }: ENSArgs<'multicallWrapper'>,
20
22
  data: string,
23
+ passthrough: TransactionRequest & { passthrough?: any }[],
21
24
  ...items: BatchFunctionResult<RawFunction>[]
22
25
  ): Promise<any[] | undefined> => {
23
- const response = await multicallWrapper.decode(data)
26
+ const response = await multicallWrapper.decode(data, passthrough)
24
27
  if (!response) return
25
28
 
26
29
  return Promise.all(
27
- response.map((ret: any, i: number) =>
28
- items[i].decode(ret.returnData, ...items[i].args),
29
- ),
30
+ response.map((ret: any, i: number) => {
31
+ if (passthrough[i].passthrough) {
32
+ return items[i].decode(
33
+ ret.returnData,
34
+ passthrough[i].passthrough,
35
+ ...items[i].args,
36
+ )
37
+ }
38
+ return items[i].decode(ret.returnData, ...items[i].args)
39
+ }),
30
40
  )
31
41
  }
32
42
 
@@ -0,0 +1,62 @@
1
+ import dotenv from 'dotenv'
2
+ import { ENS } from '..'
3
+ import setup from '../tests/setup'
4
+
5
+ dotenv.config()
6
+
7
+ let ensInstance: ENS
8
+
9
+ beforeAll(async () => {
10
+ ;({ ensInstance } = await setup(true))
11
+ })
12
+
13
+ jest.setTimeout(20000)
14
+
15
+ describe('CCIP', () => {
16
+ describe('getProfile', () => {
17
+ it('should return a profile from a ccip-read name', async () => {
18
+ const result = await ensInstance.getProfile('1.offchainexample.eth', {
19
+ fallback: {
20
+ texts: ['email', 'description'],
21
+ contentHash: true,
22
+ coinTypes: ['LTC', '60'],
23
+ },
24
+ })
25
+ expect(result).toBeTruthy()
26
+ if (result) {
27
+ expect(result.address).toBe(
28
+ '0x41563129cDbbD0c5D3e1c86cf9563926b243834d',
29
+ )
30
+ }
31
+ })
32
+ })
33
+ describe('batch', () => {
34
+ it('allows batch ccip', async () => {
35
+ const result = await ensInstance.batch(
36
+ ensInstance.getAddr.batch('1.offchainexample.eth'),
37
+ ensInstance.getAddr.batch('1.offchainexample.eth', 'LTC'),
38
+ ensInstance.getText.batch('1.offchainexample.eth', 'email'),
39
+ )
40
+ expect(result).toBeTruthy()
41
+ if (result) {
42
+ expect(result[0]).toBe('0x41563129cDbbD0c5D3e1c86cf9563926b243834d')
43
+ expect(result[1]).toStrictEqual({
44
+ coin: 'LTC',
45
+ addr: 'MQMcJhpWHYVeQArcZR3sBgyPZxxRtnH441',
46
+ })
47
+ expect(result[2]).toBe('nick@ens.domains')
48
+ }
49
+ })
50
+ it('allows nested batch ccip', async () => {
51
+ const result = await ensInstance.batch(
52
+ ensInstance.batch.batch(
53
+ ensInstance.getAddr.batch('1.offchainexample.eth'),
54
+ ),
55
+ )
56
+ expect(result).toBeTruthy()
57
+ if (result) {
58
+ expect(result[0]![0]).toBe('0x41563129cDbbD0c5D3e1c86cf9563926b243834d')
59
+ }
60
+ })
61
+ })
62
+ })
@@ -1,4 +1,4 @@
1
- import { BigNumber } from '@ethersproject/bignumber/lib/bignumber'
1
+ import { BigNumber } from '@ethersproject/bignumber'
2
2
  import { keccak256 as solidityKeccak256 } from '@ethersproject/solidity'
3
3
  import { ENSArgs } from '..'
4
4
  import { CombinedFuseInput, encodeFuses } from '../utils/fuses'
@@ -0,0 +1,49 @@
1
+ import { ENS } from '../index'
2
+ import setup from '../tests/setup'
3
+
4
+ let ensInstance: ENS
5
+
6
+ beforeAll(async () => {
7
+ ;({ ensInstance } = await setup())
8
+ })
9
+
10
+ describe('getDecryptedName', () => {
11
+ it('should decrypt a wrapped name with on-chain data', async () => {
12
+ const result = await ensInstance.getDecryptedName(
13
+ '[9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658].wrapped-with-subnames.eth',
14
+ )
15
+ expect(result).toBeDefined()
16
+ expect(result).toBe('test.wrapped-with-subnames.eth')
17
+ })
18
+ it('should decrypt a name via namehash lookup', async () => {
19
+ const result = await ensInstance.getDecryptedName(
20
+ '[f81b517a242b218999ec8eec0ea6e2ddbef2a367a14e93f4a32a39e260f686ad].eth',
21
+ )
22
+ expect(result).toBeDefined()
23
+ expect(result).toBe('test123.eth')
24
+ })
25
+ it('should decrypt a name via labelhash lookup', async () => {
26
+ const result = await ensInstance.getDecryptedName(
27
+ '[4d2920c35d976f8478bee89292ba85074d1bbea73f1571363b41a1629e1bac68].with-unknown-subnames.eth',
28
+ )
29
+ expect(result).toBeDefined()
30
+ expect(result).toBe('aaa123.with-unknown-subnames.eth')
31
+ })
32
+ it('should partially decrypt a name when allowIncomplete is true', async () => {
33
+ const result = await ensInstance.getDecryptedName(
34
+ '[7bffb6e3ebf801bbc438fea5c11d957ba49978bdc8d52b71cba974139d22edea].[6c14e1739568670447af1d5af8a571008f7a582068af18bcd7ac2dbc13bb37c1].eth',
35
+ true,
36
+ )
37
+ expect(result).toBeDefined()
38
+ expect(result).toBe(
39
+ '[7bffb6e3ebf801bbc438fea5c11d957ba49978bdc8d52b71cba974139d22edea].with-unknown-subnames.eth',
40
+ )
41
+ })
42
+ it('should not partially decrypt a name when allowIncomplete is false', async () => {
43
+ const result = await ensInstance.getDecryptedName(
44
+ '[7bffb6e3ebf801bbc438fea5c11d957ba49978bdc8d52b71cba974139d22edea].[6c14e1739568670447af1d5af8a571008f7a582068af18bcd7ac2dbc13bb37c1].eth',
45
+ false,
46
+ )
47
+ expect(result).toBeUndefined()
48
+ })
49
+ })
@@ -0,0 +1,119 @@
1
+ import { hexStripZeros } from '@ethersproject/bytes'
2
+ import { ENSArgs } from '../index'
3
+ import { hexDecodeName } from '../utils/hexEncodedName'
4
+ import {
5
+ checkIsDecrypted,
6
+ decodeLabelhash,
7
+ getEncryptedLabelAmount,
8
+ isEncodedLabelhash,
9
+ } from '../utils/labels'
10
+ import { namehash } from '../utils/normalise'
11
+
12
+ const raw = async (
13
+ { contracts }: ENSArgs<'contracts'>,
14
+ name: string,
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ allowIncomplete?: boolean,
17
+ ) => {
18
+ const nameWrapper = await contracts?.getNameWrapper()!
19
+
20
+ return {
21
+ to: nameWrapper.address,
22
+ data: nameWrapper.interface.encodeFunctionData('names', [namehash(name)]),
23
+ }
24
+ }
25
+
26
+ const generateNameQuery = (labels: string[]) => {
27
+ let query = ''
28
+
29
+ for (let i = 0; i < labels.length; i += 1) {
30
+ const label = labels[i]
31
+ if (isEncodedLabelhash(label)) {
32
+ query += `
33
+ label${i}: domains(where: { labelhash: "${decodeLabelhash(
34
+ label,
35
+ ).toLowerCase()}", labelName_not: null }) {
36
+ labelName
37
+ }
38
+ `
39
+ }
40
+ }
41
+
42
+ return query
43
+ }
44
+
45
+ const decode = async (
46
+ { contracts, gqlInstance }: ENSArgs<'contracts' | 'gqlInstance'>,
47
+ data: string,
48
+ name: string,
49
+ allowIncomplete: boolean = false,
50
+ ) => {
51
+ if (data !== null) {
52
+ const nameWrapper = await contracts?.getNameWrapper()!
53
+ try {
54
+ const result = nameWrapper.interface.decodeFunctionResult('names', data)
55
+ if (hexStripZeros(result['0']) !== '0x') {
56
+ const decoded = hexDecodeName(result['0'])
57
+ if (decoded && decoded !== '.') return decoded
58
+ }
59
+ } catch (e: any) {
60
+ console.error('Error decoding name: ', e)
61
+ return
62
+ }
63
+ }
64
+
65
+ if (checkIsDecrypted(name)) return name
66
+ // if the name isn't wrapped, try to fetch the name from an existing Domain entity
67
+ // also try to fetch the label names from any Domain entities that have a corresponding labelhash
68
+ const labels = name.split('.')
69
+ const decryptedNameQuery = gqlInstance.gql`
70
+ query decodedName($id: String!) {
71
+ namehashLookup: domains(where: { id: $id }) {
72
+ name
73
+ }
74
+ ${generateNameQuery(labels)}
75
+ }
76
+ `
77
+
78
+ const decryptedNameResult = await gqlInstance.client.request(
79
+ decryptedNameQuery,
80
+ {
81
+ id: namehash(name),
82
+ },
83
+ )
84
+
85
+ if (!decryptedNameResult) return
86
+
87
+ const namehashLookupResult = decryptedNameResult?.namehashLookup[0]?.name
88
+ let bestResult: string | undefined = namehashLookupResult
89
+ if (namehashLookupResult && checkIsDecrypted(namehashLookupResult)) {
90
+ return namehashLookupResult
91
+ }
92
+
93
+ const { namehashLookup: _, ...labelNames } = decryptedNameResult
94
+ if (Object.keys(labelNames).length !== 0) {
95
+ for (const [key, value] of Object.entries<[{ labelName?: string }]>(
96
+ labelNames,
97
+ )) {
98
+ if (value.length && value[0].labelName) {
99
+ labels[parseInt(key.replace('label', ''))] = value[0].labelName
100
+ }
101
+ }
102
+ const labelLookupResult = labels.join('.')
103
+ if (
104
+ !namehashLookupResult ||
105
+ getEncryptedLabelAmount(namehashLookupResult) >
106
+ getEncryptedLabelAmount(labelLookupResult)
107
+ )
108
+ bestResult = labelLookupResult
109
+ }
110
+
111
+ if (!bestResult || (!allowIncomplete && !checkIsDecrypted(bestResult))) return
112
+
113
+ return bestResult
114
+ }
115
+
116
+ export default {
117
+ raw,
118
+ decode,
119
+ }
@@ -1,7 +1,8 @@
1
- import { BigNumber } from '@ethersproject/bignumber/lib/bignumber'
1
+ import { BigNumber } from '@ethersproject/bignumber'
2
2
  import { keccak256 as solidityKeccak256 } from '@ethersproject/solidity'
3
3
  import { ENSArgs } from '..'
4
4
  import { namehash } from '../utils/normalise'
5
+ import { checkIsDotEth } from '../utils/validation'
5
6
 
6
7
  type ContractOption = 'registrar' | 'nameWrapper'
7
8
 
@@ -56,7 +57,7 @@ const getContractToUse = (
56
57
  labels: string[],
57
58
  ) => {
58
59
  if (contract) return contract
59
- if (labels.length === 2 && labels[1] === 'eth') {
60
+ if (checkIsDotEth(labels)) {
60
61
  return 'registrar'
61
62
  }
62
63
  return 'nameWrapper'
@@ -35,4 +35,15 @@ describe('getHistory', () => {
35
35
  expect(result).toHaveProperty('registration')
36
36
  }
37
37
  })
38
+ it('should return the history of a subname', async () => {
39
+ const result = await ensInstance.getHistory(
40
+ 'test.wrapped-with-subnames.eth',
41
+ )
42
+ expect(result).toBeTruthy()
43
+ if (result) {
44
+ expect(result).toHaveProperty('domain')
45
+ expect(result).toHaveProperty('resolver')
46
+ expect(result).not.toHaveProperty('registration')
47
+ }
48
+ })
38
49
  })
@@ -2,7 +2,6 @@ import { formatsByCoinType } from '@ensdomains/address-encoder'
2
2
  import { hexStripZeros } from '@ethersproject/bytes'
3
3
  import { ENSArgs } from '..'
4
4
  import { decodeContenthash } from '../utils/contentHash'
5
- import { labelhash } from '../utils/labels'
6
5
  import { namehash } from '../utils/normalise'
7
6
  import {
8
7
  AbiChanged,
@@ -28,6 +27,7 @@ import {
28
27
  VersionChanged,
29
28
  WrappedTransfer,
30
29
  } from '../utils/subgraph-types'
30
+ import { checkIsDotEth } from '../utils/validation'
31
31
 
32
32
  type DomainEvent =
33
33
  | 'NewOwner'
@@ -154,7 +154,7 @@ export async function getHistory(
154
154
  ) {
155
155
  const { client } = gqlInstance
156
156
  const query = gqlInstance.gql`
157
- query getHistory($namehash: String!, $labelhash: String!) {
157
+ query getHistory($namehash: String!) {
158
158
  domain(id: $namehash) {
159
159
  events {
160
160
  id
@@ -275,14 +275,12 @@ export async function getHistory(
275
275
  }
276
276
  `
277
277
 
278
- const label = name.split('.')[0]
279
-
280
278
  const nameHash = namehash(name)
281
- const labelHash = labelhash(label)
279
+ const labels = name.split('.')
280
+ const is2ldEth = checkIsDotEth(labels)
282
281
 
283
282
  const response = await client.request(query, {
284
283
  namehash: nameHash,
285
- labelhash: labelHash,
286
284
  })
287
285
  const domain = response?.domain
288
286
 
@@ -290,12 +288,10 @@ export async function getHistory(
290
288
 
291
289
  const {
292
290
  events: domainEvents,
293
- registration: { events: registrationEvents },
294
291
  resolver: { events: resolverEvents },
295
292
  } = domain
296
293
 
297
294
  const domainHistory = mapEvents(domainEvents, 'Domain')
298
- const registrationHistory = mapEvents(registrationEvents, 'Registration')
299
295
  const resolverHistory = mapEvents(
300
296
  // remove duplicate events for ETH cointype
301
297
  resolverEvents.filter(
@@ -304,9 +300,20 @@ export async function getHistory(
304
300
  'Resolver',
305
301
  )
306
302
 
303
+ if (is2ldEth) {
304
+ const {
305
+ registration: { events: registrationEvents },
306
+ } = domain
307
+ const registrationHistory = mapEvents(registrationEvents, 'Registration')
308
+ return {
309
+ domain: domainHistory,
310
+ registration: registrationHistory,
311
+ resolver: resolverHistory,
312
+ }
313
+ }
314
+
307
315
  return {
308
316
  domain: domainHistory,
309
- registration: registrationHistory,
310
317
  resolver: resolverHistory,
311
318
  }
312
319
  }
@@ -29,7 +29,7 @@ const letterItems = [
29
29
  ]
30
30
 
31
31
  const domainLetterItems = [
32
- '[',
32
+ ...Array(3).fill('['),
33
33
  'x',
34
34
  'w',
35
35
  't',
@@ -1,9 +1,10 @@
1
- import { defaultAbiCoder } from '@ethersproject/abi/lib/abi-coder'
2
- import type { Result } from '@ethersproject/abi/lib/coders/abstract-coder'
1
+ import type { Result } from '@ethersproject/abi'
2
+ import { defaultAbiCoder } from '@ethersproject/abi'
3
3
  import { hexStripZeros } from '@ethersproject/bytes'
4
4
  import { ENSArgs } from '..'
5
5
  import { labelhash } from '../utils/labels'
6
6
  import { namehash as makeNamehash } from '../utils/normalise'
7
+ import { checkIsDotEth } from '../utils/validation'
7
8
 
8
9
  type Owner = {
9
10
  registrant?: string
@@ -87,7 +88,7 @@ const raw = async (
87
88
 
88
89
  const data: { to: string; data: string }[] = [registryData, nameWrapperData]
89
90
 
90
- if (labels.length === 2 && labels[1] === 'eth') {
91
+ if (checkIsDotEth(labels)) {
91
92
  data.push(registrarData)
92
93
  }
93
94
 
@@ -1,5 +1,5 @@
1
- import { defaultAbiCoder } from '@ethersproject/abi/lib/abi-coder'
2
- import { BigNumber } from '@ethersproject/bignumber/lib/bignumber'
1
+ import { defaultAbiCoder } from '@ethersproject/abi'
2
+ import { BigNumber } from '@ethersproject/bignumber'
3
3
  import { ENSArgs } from '..'
4
4
 
5
5
  const raw = async (
@@ -119,6 +119,13 @@ describe('getProfile', () => {
119
119
  deploymentAddresses.LegacyPublicResolver,
120
120
  )
121
121
  })
122
+ it('should return the decoded name for a name with encoded labels', async () => {
123
+ const result = await ensInstance.getProfile(
124
+ '[9dd2c369a187b4e6b9c402f030e50743e619301ea62aa4c0737d4ef7e10a3d49].with-subnames.eth',
125
+ )
126
+ expect(result).toBeDefined()
127
+ expect(result?.decryptedName).toBe('xyz.with-subnames.eth')
128
+ })
122
129
  it('should return undefined for an unregistered name', async () => {
123
130
  const result = await ensInstance.getProfile('test123123123cool.eth')
124
131
  expect(result).toBeUndefined()