@ensdomains/ensjs 3.0.0 → 3.1.0

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 (110) hide show
  1. package/dist/cjs/clients/decorators/public.js.map +1 -1
  2. package/dist/cjs/contracts/consts.js +3 -3
  3. package/dist/cjs/contracts/universalResolver.js +92 -59
  4. package/dist/cjs/contracts/universalResolver.js.map +1 -1
  5. package/dist/cjs/errors/version.js +1 -1
  6. package/dist/cjs/functions/public/_getAbi.js +52 -45
  7. package/dist/cjs/functions/public/_getAbi.js.map +1 -1
  8. package/dist/cjs/functions/public/_getAddr.js +30 -23
  9. package/dist/cjs/functions/public/_getAddr.js.map +1 -1
  10. package/dist/cjs/functions/public/_getContentHash.js +14 -7
  11. package/dist/cjs/functions/public/_getContentHash.js.map +1 -1
  12. package/dist/cjs/functions/public/_getText.js +15 -8
  13. package/dist/cjs/functions/public/_getText.js.map +1 -1
  14. package/dist/cjs/functions/public/getAbiRecord.js +13 -5
  15. package/dist/cjs/functions/public/getAbiRecord.js.map +1 -1
  16. package/dist/cjs/functions/public/getAddressRecord.js +13 -5
  17. package/dist/cjs/functions/public/getAddressRecord.js.map +1 -1
  18. package/dist/cjs/functions/public/getContentHashRecord.js +13 -5
  19. package/dist/cjs/functions/public/getContentHashRecord.js.map +1 -1
  20. package/dist/cjs/functions/public/getName.js +53 -35
  21. package/dist/cjs/functions/public/getName.js.map +1 -1
  22. package/dist/cjs/functions/public/getRecords.js +164 -161
  23. package/dist/cjs/functions/public/getRecords.js.map +1 -1
  24. package/dist/cjs/functions/public/getTextRecord.js +13 -5
  25. package/dist/cjs/functions/public/getTextRecord.js.map +1 -1
  26. package/dist/cjs/functions/public/universalWrapper.js +45 -37
  27. package/dist/cjs/functions/public/universalWrapper.js.map +1 -1
  28. package/dist/cjs/utils/checkSafeUniversalResolverData.js +35 -0
  29. package/dist/cjs/utils/checkSafeUniversalResolverData.js.map +1 -0
  30. package/dist/esm/clients/decorators/public.js.map +1 -1
  31. package/dist/esm/contracts/consts.js +3 -3
  32. package/dist/esm/contracts/universalResolver.js +92 -59
  33. package/dist/esm/contracts/universalResolver.js.map +1 -1
  34. package/dist/esm/errors/version.js +1 -1
  35. package/dist/esm/functions/public/_getAbi.js +56 -49
  36. package/dist/esm/functions/public/_getAbi.js.map +1 -1
  37. package/dist/esm/functions/public/_getAddr.js +30 -23
  38. package/dist/esm/functions/public/_getAddr.js.map +1 -1
  39. package/dist/esm/functions/public/_getContentHash.js +14 -7
  40. package/dist/esm/functions/public/_getContentHash.js.map +1 -1
  41. package/dist/esm/functions/public/_getText.js +15 -8
  42. package/dist/esm/functions/public/_getText.js.map +1 -1
  43. package/dist/esm/functions/public/getAbiRecord.js +13 -5
  44. package/dist/esm/functions/public/getAbiRecord.js.map +1 -1
  45. package/dist/esm/functions/public/getAddressRecord.js +13 -5
  46. package/dist/esm/functions/public/getAddressRecord.js.map +1 -1
  47. package/dist/esm/functions/public/getContentHashRecord.js +13 -5
  48. package/dist/esm/functions/public/getContentHashRecord.js.map +1 -1
  49. package/dist/esm/functions/public/getName.js +54 -36
  50. package/dist/esm/functions/public/getName.js.map +1 -1
  51. package/dist/esm/functions/public/getRecords.js +168 -165
  52. package/dist/esm/functions/public/getRecords.js.map +1 -1
  53. package/dist/esm/functions/public/getTextRecord.js +13 -5
  54. package/dist/esm/functions/public/getTextRecord.js.map +1 -1
  55. package/dist/esm/functions/public/universalWrapper.js +46 -38
  56. package/dist/esm/functions/public/universalWrapper.js.map +1 -1
  57. package/dist/esm/utils/checkSafeUniversalResolverData.js +39 -0
  58. package/dist/esm/utils/checkSafeUniversalResolverData.js.map +1 -0
  59. package/dist/types/clients/decorators/public.d.ts +6 -6
  60. package/dist/types/clients/decorators/public.d.ts.map +1 -1
  61. package/dist/types/clients/public.d.ts +34 -8
  62. package/dist/types/clients/public.d.ts.map +1 -1
  63. package/dist/types/contracts/consts.d.ts +3 -3
  64. package/dist/types/contracts/universalResolver.d.ts +73 -0
  65. package/dist/types/contracts/universalResolver.d.ts.map +1 -1
  66. package/dist/types/errors/version.d.ts +1 -1
  67. package/dist/types/functions/public/_getAbi.d.ts +3 -1
  68. package/dist/types/functions/public/_getAbi.d.ts.map +1 -1
  69. package/dist/types/functions/public/_getAddr.d.ts +3 -1
  70. package/dist/types/functions/public/_getAddr.d.ts.map +1 -1
  71. package/dist/types/functions/public/_getContentHash.d.ts +3 -1
  72. package/dist/types/functions/public/_getContentHash.d.ts.map +1 -1
  73. package/dist/types/functions/public/_getText.d.ts +3 -1
  74. package/dist/types/functions/public/_getText.d.ts.map +1 -1
  75. package/dist/types/functions/public/getAbiRecord.d.ts +8 -5
  76. package/dist/types/functions/public/getAbiRecord.d.ts.map +1 -1
  77. package/dist/types/functions/public/getAddressRecord.d.ts +8 -5
  78. package/dist/types/functions/public/getAddressRecord.d.ts.map +1 -1
  79. package/dist/types/functions/public/getContentHashRecord.d.ts +7 -4
  80. package/dist/types/functions/public/getContentHashRecord.d.ts.map +1 -1
  81. package/dist/types/functions/public/getName.d.ts +9 -3
  82. package/dist/types/functions/public/getName.d.ts.map +1 -1
  83. package/dist/types/functions/public/getRecords.d.ts +53 -26
  84. package/dist/types/functions/public/getRecords.d.ts.map +1 -1
  85. package/dist/types/functions/public/getTextRecord.d.ts +7 -4
  86. package/dist/types/functions/public/getTextRecord.d.ts.map +1 -1
  87. package/dist/types/functions/public/universalWrapper.d.ts +4 -2
  88. package/dist/types/functions/public/universalWrapper.d.ts.map +1 -1
  89. package/dist/types/types.d.ts +2 -2
  90. package/dist/types/types.d.ts.map +1 -1
  91. package/dist/types/utils/checkSafeUniversalResolverData.d.ts +14 -0
  92. package/dist/types/utils/checkSafeUniversalResolverData.d.ts.map +1 -0
  93. package/package.json +4 -4
  94. package/src/clients/decorators/public.ts +31 -4
  95. package/src/contracts/consts.ts +3 -3
  96. package/src/contracts/universalResolver.ts +95 -59
  97. package/src/errors/version.ts +1 -1
  98. package/src/functions/public/_getAbi.ts +61 -53
  99. package/src/functions/public/_getAddr.ts +31 -24
  100. package/src/functions/public/_getContentHash.ts +15 -7
  101. package/src/functions/public/_getText.ts +16 -8
  102. package/src/functions/public/getAbiRecord.ts +21 -8
  103. package/src/functions/public/getAddressRecord.ts +25 -9
  104. package/src/functions/public/getContentHashRecord.ts +19 -7
  105. package/src/functions/public/getName.ts +58 -40
  106. package/src/functions/public/getRecords.ts +336 -235
  107. package/src/functions/public/getTextRecord.ts +19 -6
  108. package/src/functions/public/universalWrapper.ts +49 -43
  109. package/src/types.ts +4 -3
  110. package/src/utils/checkSafeUniversalResolverData.ts +62 -0
@@ -19,6 +19,8 @@ import { namehash } from '../../utils/normalise.js'
19
19
  export type InternalGetAbiParameters = {
20
20
  /** Name to get ABI record for */
21
21
  name: string
22
+ /** Whether or not to throw decoding errors */
23
+ strict?: boolean
22
24
  }
23
25
 
24
26
  export type InternalGetAbiReturnType = Prettify<DecodedAbi | null>
@@ -28,11 +30,11 @@ export type InternalGetAbiReturnType = Prettify<DecodedAbi | null>
28
30
  // ID 2: zlib compressed JSON
29
31
  // ID 4: CBOR
30
32
  // ID 8: URI
31
- const supportedContentTypes = BigInt('0xf')
33
+ const supportedContentTypes = 0xfn
32
34
 
33
35
  const encode = (
34
36
  _client: ClientWithEns,
35
- { name }: InternalGetAbiParameters,
37
+ { name }: Omit<InternalGetAbiParameters, 'strict'>,
36
38
  ): SimpleTransactionRequest => {
37
39
  return {
38
40
  to: EMPTY_ADDRESS,
@@ -47,66 +49,72 @@ const encode = (
47
49
  const decode = async (
48
50
  _client: ClientWithEns,
49
51
  data: Hex,
52
+ { strict }: Pick<InternalGetAbiParameters, 'strict'>,
50
53
  ): Promise<InternalGetAbiReturnType> => {
51
54
  if (data === '0x') return null
52
55
 
53
- const [bigintContentType, encodedAbiData] = decodeFunctionResult({
54
- abi: publicResolverAbiSnippet,
55
- functionName: 'ABI',
56
- data,
57
- })
58
-
59
- if (!bigintContentType || !encodedAbiData) {
60
- return null
61
- }
62
-
63
- const contentType = Number(bigintContentType)
64
- if (!contentType) {
65
- return null
66
- }
56
+ try {
57
+ const [bigintContentType, encodedAbiData] = decodeFunctionResult({
58
+ abi: publicResolverAbiSnippet,
59
+ functionName: 'ABI',
60
+ data,
61
+ })
67
62
 
68
- let abiData: string | object
69
- let decoded = false
70
- switch (contentType) {
71
- // JSON
72
- case 1:
73
- abiData = JSON.parse(hexToString(encodedAbiData))
74
- decoded = true
75
- break
76
- // zlib compressed JSON
77
- case 2: {
78
- const { inflate } = await import('pako/dist/pako_inflate.min.js')
79
- abiData = JSON.parse(
80
- inflate(hexToBytes(encodedAbiData), { to: 'string' }),
81
- )
82
- decoded = true
83
- break
63
+ if (!bigintContentType || !encodedAbiData) {
64
+ return null
84
65
  }
85
- // CBOR
86
- case 4: {
87
- const { cborDecode } = await import('@ensdomains/address-encoder/utils')
88
- abiData = await cborDecode(hexToBytes(encodedAbiData).buffer)
89
- decoded = true
90
- break
66
+
67
+ const contentType = Number(bigintContentType)
68
+ if (!contentType) {
69
+ return null
91
70
  }
92
- // URI
93
- case 8:
94
- abiData = hexToString(encodedAbiData)
95
- decoded = true
96
- break
97
- default:
98
- try {
99
- abiData = hexToString(encodedAbiData)
71
+
72
+ let abiData: string | object
73
+ let decoded = false
74
+ switch (contentType) {
75
+ // JSON
76
+ case 1:
77
+ abiData = JSON.parse(hexToString(encodedAbiData))
100
78
  decoded = true
101
- } catch {
102
- abiData = encodedAbiData
79
+ break
80
+ // zlib compressed JSON
81
+ case 2: {
82
+ const { inflate } = await import('pako/dist/pako_inflate.min.js')
83
+ abiData = JSON.parse(
84
+ inflate(hexToBytes(encodedAbiData), { to: 'string' }),
85
+ )
86
+ decoded = true
87
+ break
103
88
  }
104
- }
89
+ // CBOR
90
+ case 4: {
91
+ const { cborDecode } = await import('@ensdomains/address-encoder/utils')
92
+ abiData = await cborDecode(hexToBytes(encodedAbiData).buffer)
93
+ decoded = true
94
+ break
95
+ }
96
+ // URI
97
+ case 8:
98
+ abiData = hexToString(encodedAbiData)
99
+ decoded = true
100
+ break
101
+ default:
102
+ try {
103
+ abiData = hexToString(encodedAbiData)
104
+ decoded = true
105
+ } catch {
106
+ abiData = encodedAbiData
107
+ }
108
+ }
105
109
 
106
- return {
107
- contentType,
108
- decoded,
109
- abi: abiData,
110
+ return {
111
+ contentType,
112
+ decoded,
113
+ abi: abiData,
114
+ }
115
+ } catch (error) {
116
+ if (strict) throw error
117
+ return null
110
118
  }
111
119
  }
112
120
 
@@ -28,13 +28,15 @@ export type InternalGetAddrParameters = {
28
28
  coin?: string | number
29
29
  /** Optionally return raw bytes value of address record (default: false) */
30
30
  bypassFormat?: boolean
31
+ /** Whether or not to throw decoding errors */
32
+ strict?: boolean
31
33
  }
32
34
 
33
35
  export type InternalGetAddrReturnType = Prettify<DecodedAddr | null>
34
36
 
35
37
  const encode = (
36
38
  _client: ClientWithEns,
37
- { name, coin = 60, bypassFormat }: InternalGetAddrParameters,
39
+ { name, coin = 60, bypassFormat }: Omit<InternalGetAddrParameters, 'strict'>,
38
40
  ): SimpleTransactionRequest => {
39
41
  const coder = getCoderFromCoin(coin)
40
42
  if (coder.coinType === 60) {
@@ -72,41 +74,46 @@ const encode = (
72
74
  const decode = async (
73
75
  _client: ClientWithEns,
74
76
  data: Hex,
75
- { coin = 60 }: InternalGetAddrParameters,
77
+ { coin = 60, strict }: Pick<InternalGetAddrParameters, 'coin' | 'strict'>,
76
78
  ): Promise<InternalGetAddrReturnType> => {
77
79
  if (data === '0x') return null
78
80
 
79
81
  const coder = getCoderFromCoin(coin)
80
82
  let response: Hex
81
83
 
82
- if (coder.coinType === 60) {
83
- response = decodeFunctionResult({
84
- abi: publicResolverSingleAddrSnippet,
85
- functionName: 'addr',
86
- data,
87
- })
88
- } else {
89
- response = decodeFunctionResult({
90
- abi: publicResolverMultiAddrSnippet,
91
- functionName: 'addr',
92
- data,
93
- })
94
- }
84
+ try {
85
+ if (coder.coinType === 60) {
86
+ response = decodeFunctionResult({
87
+ abi: publicResolverSingleAddrSnippet,
88
+ functionName: 'addr',
89
+ data,
90
+ })
91
+ } else {
92
+ response = decodeFunctionResult({
93
+ abi: publicResolverMultiAddrSnippet,
94
+ functionName: 'addr',
95
+ data,
96
+ })
97
+ }
95
98
 
96
- if (!response) return null
99
+ if (!response) return null
97
100
 
98
- const trimmed = trim(response)
99
- if (trimmed === '0x' || trimmed === '0x0' || trimmed === '0x00') {
100
- return null
101
- }
101
+ const trimmed = trim(response)
102
+ if (trimmed === '0x' || trimmed === '0x0' || trimmed === '0x00') {
103
+ return null
104
+ }
105
+
106
+ const decodedAddr = coder.encode(hexToBytes(response))
102
107
 
103
- const decodedAddr = coder.encode(hexToBytes(response))
108
+ if (!decodedAddr) {
109
+ return null
110
+ }
104
111
 
105
- if (!decodedAddr) {
112
+ return { id: coder.coinType, name: coder.name, value: decodedAddr }
113
+ } catch (error) {
114
+ if (strict) throw error
106
115
  return null
107
116
  }
108
-
109
- return { id: coder.coinType, name: coder.name, value: decodedAddr }
110
117
  }
111
118
 
112
119
  const _getAddr = generateFunction({ encode, decode })
@@ -13,6 +13,8 @@ import { namehash } from '../../utils/normalise.js'
13
13
  export type InternalGetContentHashParameters = {
14
14
  /** Name to get content hash record for */
15
15
  name: string
16
+ /** Whether or not to throw decoding errors */
17
+ strict?: boolean
16
18
  }
17
19
 
18
20
  export type InternalGetContentHashReturnType =
@@ -20,7 +22,7 @@ export type InternalGetContentHashReturnType =
20
22
 
21
23
  const encode = (
22
24
  _client: ClientWithEns,
23
- { name }: InternalGetContentHashParameters,
25
+ { name }: Omit<InternalGetContentHashParameters, 'strict'>,
24
26
  ): SimpleTransactionRequest => {
25
27
  return {
26
28
  to: EMPTY_ADDRESS,
@@ -35,16 +37,22 @@ const encode = (
35
37
  const decode = async (
36
38
  _client: ClientWithEns,
37
39
  data: Hex,
40
+ { strict }: Pick<InternalGetContentHashParameters, 'strict'>,
38
41
  ): Promise<InternalGetContentHashReturnType> => {
39
42
  if (data === '0x') return null
40
43
 
41
- const response = decodeFunctionResult({
42
- abi: publicResolverContenthashSnippet,
43
- functionName: 'contenthash',
44
- data,
45
- })
44
+ try {
45
+ const response = decodeFunctionResult({
46
+ abi: publicResolverContenthashSnippet,
47
+ functionName: 'contenthash',
48
+ data,
49
+ })
46
50
 
47
- return decodeContentHash(response)
51
+ return decodeContentHash(response)
52
+ } catch (error) {
53
+ if (strict) throw error
54
+ return null
55
+ }
48
56
  }
49
57
 
50
58
  const _getContentHash = generateFunction({ encode, decode })
@@ -11,13 +11,15 @@ export type InternalGetTextParameters = {
11
11
  name: string
12
12
  /** Text record key to get */
13
13
  key: string
14
+ /** Whether or not to throw decoding errors */
15
+ strict?: boolean
14
16
  }
15
17
 
16
18
  export type InternalGetTextReturnType = string | null
17
19
 
18
20
  const encode = (
19
21
  _client: ClientWithEns,
20
- { name, key }: InternalGetTextParameters,
22
+ { name, key }: Omit<InternalGetTextParameters, 'strict'>,
21
23
  ): SimpleTransactionRequest => {
22
24
  return {
23
25
  to: EMPTY_ADDRESS,
@@ -32,18 +34,24 @@ const encode = (
32
34
  const decode = async (
33
35
  _client: ClientWithEns,
34
36
  data: Hex,
37
+ { strict }: Pick<InternalGetTextParameters, 'strict'>,
35
38
  ): Promise<InternalGetTextReturnType> => {
36
39
  if (data === '0x') return null
37
40
 
38
- const response = decodeFunctionResult({
39
- abi: publicResolverTextSnippet,
40
- functionName: 'text',
41
- data,
42
- })
41
+ try {
42
+ const response = decodeFunctionResult({
43
+ abi: publicResolverTextSnippet,
44
+ functionName: 'text',
45
+ data,
46
+ })
43
47
 
44
- if (!response) return null
48
+ if (!response) return null
45
49
 
46
- return response
50
+ return response
51
+ } catch (error) {
52
+ if (strict) throw error
53
+ return null
54
+ }
47
55
  }
48
56
 
49
57
  const _getText = generateFunction({ encode, decode })
@@ -1,4 +1,4 @@
1
- import type { Hex } from 'viem'
1
+ import type { BaseError, Hex } from 'viem'
2
2
  import type { ClientWithEns } from '../../contracts/consts.js'
3
3
  import type {
4
4
  GenericPassthrough,
@@ -15,25 +15,38 @@ import _getAbi, {
15
15
  } from './_getAbi.js'
16
16
  import universalWrapper from './universalWrapper.js'
17
17
 
18
- export type GetAbiRecordParameters = Prettify<InternalGetAbiParameters>
18
+ export type GetAbiRecordParameters = Prettify<
19
+ InternalGetAbiParameters & {
20
+ /** Batch gateway URLs to use for resolving CCIP-read requests. */
21
+ gatewayUrls?: string[]
22
+ }
23
+ >
19
24
 
20
25
  export type GetAbiRecordReturnType = Prettify<InternalGetAbiReturnType>
21
26
 
22
27
  const encode = (
23
28
  client: ClientWithEns,
24
- { name }: GetAbiRecordParameters,
29
+ { name, gatewayUrls }: Omit<GetAbiRecordParameters, 'strict'>,
25
30
  ): SimpleTransactionRequest => {
26
31
  const prData = _getAbi.encode(client, { name })
27
- return universalWrapper.encode(client, { name, data: prData.data })
32
+ return universalWrapper.encode(client, {
33
+ name,
34
+ data: prData.data,
35
+ gatewayUrls,
36
+ })
28
37
  }
29
38
 
30
39
  const decode = async (
31
40
  client: ClientWithEns,
32
- data: Hex,
41
+ data: Hex | BaseError,
33
42
  passthrough: GenericPassthrough,
43
+ { strict }: Pick<GetAbiRecordParameters, 'strict'>,
34
44
  ): Promise<GetAbiRecordReturnType> => {
35
- const urData = await universalWrapper.decode(client, data, passthrough)
36
- return _getAbi.decode(client, urData.data)
45
+ const urData = await universalWrapper.decode(client, data, passthrough, {
46
+ strict,
47
+ })
48
+ if (!urData) return null
49
+ return _getAbi.decode(client, urData.data, { strict })
37
50
  }
38
51
 
39
52
  type BatchableFunctionObject = GeneratedFunction<typeof encode, typeof decode>
@@ -59,7 +72,7 @@ type BatchableFunctionObject = GeneratedFunction<typeof encode, typeof decode>
59
72
  */
60
73
  const getAbiRecord = generateFunction({ encode, decode }) as ((
61
74
  client: ClientWithEns,
62
- { name }: GetAbiRecordParameters,
75
+ { name, strict }: GetAbiRecordParameters,
63
76
  ) => Promise<GetAbiRecordReturnType>) &
64
77
  BatchableFunctionObject
65
78
 
@@ -1,4 +1,4 @@
1
- import type { Hex } from 'viem'
1
+ import type { BaseError, Hex } from 'viem'
2
2
  import type { ClientWithEns } from '../../contracts/consts.js'
3
3
  import type {
4
4
  GenericPassthrough,
@@ -15,26 +15,42 @@ import _getAddr, {
15
15
  } from './_getAddr.js'
16
16
  import universalWrapper from './universalWrapper.js'
17
17
 
18
- export type GetAddressRecordParameters = Prettify<InternalGetAddrParameters>
18
+ export type GetAddressRecordParameters = Prettify<
19
+ InternalGetAddrParameters & {
20
+ /** Batch gateway URLs to use for resolving CCIP-read requests. */
21
+ gatewayUrls?: string[]
22
+ }
23
+ >
19
24
 
20
25
  export type GetAddressRecordReturnType = Prettify<InternalGetAddrReturnType>
21
26
 
22
27
  const encode = (
23
28
  client: ClientWithEns,
24
- { name, coin }: GetAddressRecordParameters,
29
+ {
30
+ name,
31
+ coin,
32
+ gatewayUrls,
33
+ }: Omit<GetAddressRecordParameters, 'strict' | 'bypassFormat'>,
25
34
  ): SimpleTransactionRequest => {
26
35
  const prData = _getAddr.encode(client, { name, coin })
27
- return universalWrapper.encode(client, { name, data: prData.data })
36
+ return universalWrapper.encode(client, {
37
+ name,
38
+ data: prData.data,
39
+ gatewayUrls,
40
+ })
28
41
  }
29
42
 
30
43
  const decode = async (
31
44
  client: ClientWithEns,
32
- data: Hex,
45
+ data: Hex | BaseError,
33
46
  passthrough: GenericPassthrough,
34
- args: GetAddressRecordParameters,
47
+ { coin, strict }: Pick<GetAddressRecordParameters, 'coin' | 'strict'>,
35
48
  ): Promise<GetAddressRecordReturnType> => {
36
- const urData = await universalWrapper.decode(client, data, passthrough)
37
- return _getAddr.decode(client, urData.data, args)
49
+ const urData = await universalWrapper.decode(client, data, passthrough, {
50
+ strict,
51
+ })
52
+ if (!urData) return null
53
+ return _getAddr.decode(client, urData.data, { coin, strict })
38
54
  }
39
55
 
40
56
  type BatchableFunctionObject = GeneratedFunction<typeof encode, typeof decode>
@@ -60,7 +76,7 @@ type BatchableFunctionObject = GeneratedFunction<typeof encode, typeof decode>
60
76
  */
61
77
  const getAddressRecord = generateFunction({ encode, decode }) as ((
62
78
  client: ClientWithEns,
63
- { name, coin, bypassFormat }: GetAddressRecordParameters,
79
+ { name, coin, bypassFormat, strict }: GetAddressRecordParameters,
64
80
  ) => Promise<GetAddressRecordReturnType>) &
65
81
  BatchableFunctionObject
66
82
 
@@ -15,27 +15,39 @@ import _getContentHash, {
15
15
  } from './_getContentHash.js'
16
16
  import universalWrapper from './universalWrapper.js'
17
17
 
18
- export type GetContentHashRecordParameters =
19
- Prettify<InternalGetContentHashParameters>
18
+ export type GetContentHashRecordParameters = Prettify<
19
+ InternalGetContentHashParameters & {
20
+ /** Batch gateway URLs to use for resolving CCIP-read requests. */
21
+ gatewayUrls?: string[]
22
+ }
23
+ >
20
24
 
21
25
  export type GetContentHashRecordReturnType =
22
26
  Prettify<InternalGetContentHashReturnType>
23
27
 
24
28
  const encode = (
25
29
  client: ClientWithEns,
26
- { name }: GetContentHashRecordParameters,
30
+ { name, gatewayUrls }: Omit<GetContentHashRecordParameters, 'strict'>,
27
31
  ): TransactionRequestWithPassthrough => {
28
32
  const prData = _getContentHash.encode(client, { name })
29
- return universalWrapper.encode(client, { name, data: prData.data })
33
+ return universalWrapper.encode(client, {
34
+ name,
35
+ data: prData.data,
36
+ gatewayUrls,
37
+ })
30
38
  }
31
39
 
32
40
  const decode = async (
33
41
  client: ClientWithEns,
34
42
  data: Hex | BaseError,
35
43
  passthrough: GenericPassthrough,
44
+ { strict }: Pick<GetContentHashRecordParameters, 'strict'>,
36
45
  ): Promise<GetContentHashRecordReturnType> => {
37
- const urData = await universalWrapper.decode(client, data, passthrough)
38
- return _getContentHash.decode(client, urData.data)
46
+ const urData = await universalWrapper.decode(client, data, passthrough, {
47
+ strict,
48
+ })
49
+ if (!urData) return null
50
+ return _getContentHash.decode(client, urData.data, { strict })
39
51
  }
40
52
 
41
53
  type BatchableFunctionObject = GeneratedFunction<typeof encode, typeof decode>
@@ -61,7 +73,7 @@ type BatchableFunctionObject = GeneratedFunction<typeof encode, typeof decode>
61
73
  */
62
74
  const getContentHashRecord = generateFunction({ encode, decode }) as ((
63
75
  client: ClientWithEns,
64
- { name }: GetContentHashRecordParameters,
76
+ { name, strict }: GetContentHashRecordParameters,
65
77
  ) => Promise<GetContentHashRecordReturnType>) &
66
78
  BatchableFunctionObject
67
79
 
@@ -1,9 +1,7 @@
1
1
  import {
2
2
  BaseError,
3
- decodeErrorResult,
4
3
  decodeFunctionResult,
5
4
  encodeFunctionData,
6
- getContractError,
7
5
  toHex,
8
6
  type Address,
9
7
  type Hex,
@@ -15,16 +13,22 @@ import type {
15
13
  GenericPassthrough,
16
14
  TransactionRequestWithPassthrough,
17
15
  } from '../../types.js'
16
+ import { checkSafeUniversalResolverData } from '../../utils/checkSafeUniversalResolverData.js'
18
17
  import {
19
18
  generateFunction,
20
19
  type GeneratedFunction,
21
20
  } from '../../utils/generateFunction.js'
22
- import { getRevertErrorData } from '../../utils/getRevertErrorData.js'
23
21
  import { packetToBytes } from '../../utils/hexEncodedName.js'
24
22
 
25
23
  export type GetNameParameters = {
26
24
  /** Address to get name for */
27
25
  address: Address
26
+ /** Whether or not to allow mismatched forward resolution */
27
+ allowMismatch?: boolean
28
+ /** Whether or not to throw decoding errors */
29
+ strict?: boolean
30
+ /** Batch gateway URLs to use for resolving CCIP-read requests. */
31
+ gatewayUrls?: string[]
28
32
  }
29
33
 
30
34
  export type GetNameReturnType = {
@@ -40,7 +44,7 @@ export type GetNameReturnType = {
40
44
 
41
45
  const encode = (
42
46
  client: ClientWithEns,
43
- { address }: GetNameParameters,
47
+ { address, gatewayUrls }: Omit<GetNameParameters, 'allowMismatch' | 'strict'>,
44
48
  ): TransactionRequestWithPassthrough => {
45
49
  const reverseNode = `${address.toLowerCase().substring(2)}.addr.reverse`
46
50
  const to = getChainContractAddress({
@@ -48,14 +52,32 @@ const encode = (
48
52
  contract: 'ensUniversalResolver',
49
53
  })
50
54
  const args = [toHex(packetToBytes(reverseNode))] as const
55
+
51
56
  return {
52
57
  to,
53
- data: encodeFunctionData({
54
- abi: universalResolverReverseSnippet,
55
- functionName: 'reverse',
56
- args,
57
- }),
58
- passthrough: { address, args },
58
+ ...(gatewayUrls?.length
59
+ ? {
60
+ data: encodeFunctionData({
61
+ abi: universalResolverReverseSnippet,
62
+ functionName: 'reverse',
63
+ args: [...args, gatewayUrls] as const,
64
+ }),
65
+ passthrough: {
66
+ args: [...args, gatewayUrls],
67
+ address: to,
68
+ },
69
+ }
70
+ : {
71
+ data: encodeFunctionData({
72
+ abi: universalResolverReverseSnippet,
73
+ functionName: 'reverse',
74
+ args,
75
+ }),
76
+ passthrough: {
77
+ args,
78
+ address: to,
79
+ },
80
+ }),
59
81
  }
60
82
  }
61
83
 
@@ -63,39 +85,35 @@ const decode = async (
63
85
  _client: ClientWithEns,
64
86
  data: Hex | BaseError,
65
87
  passthrough: GenericPassthrough,
66
- { address }: GetNameParameters,
88
+ { address, allowMismatch, strict }: GetNameParameters,
67
89
  ): Promise<GetNameReturnType | null> => {
68
- if (typeof data === 'object') {
69
- const errorData = getRevertErrorData(data)
70
- if (errorData) {
71
- const decodedError = decodeErrorResult({
72
- abi: universalResolverReverseSnippet,
73
- data: errorData,
74
- })
75
- if (
76
- decodedError.errorName === 'ResolverNotFound' ||
77
- decodedError.errorName === 'ResolverWildcardNotSupported'
78
- )
79
- return null
80
- }
81
- throw getContractError(data, {
82
- abi: universalResolverReverseSnippet,
83
- functionName: 'reverse',
84
- args: passthrough.args,
85
- address: passthrough.address,
86
- }) as BaseError
87
- }
88
- const result = decodeFunctionResult({
90
+ const isSafe = checkSafeUniversalResolverData(data, {
91
+ strict,
89
92
  abi: universalResolverReverseSnippet,
93
+ args: passthrough.args,
90
94
  functionName: 'reverse',
91
- data,
95
+ address: passthrough.address,
92
96
  })
93
- if (!result[0]) return null
94
- return {
95
- name: result[0],
96
- match: result[1].toLowerCase() === address.toLowerCase(),
97
- reverseResolverAddress: result[2],
98
- resolverAddress: result[3],
97
+ if (!isSafe) return null
98
+
99
+ try {
100
+ const result = decodeFunctionResult({
101
+ abi: universalResolverReverseSnippet,
102
+ functionName: 'reverse',
103
+ data,
104
+ })
105
+ if (!result[0]) return null
106
+ const match = result[1].toLowerCase() === address.toLowerCase()
107
+ if (!match && !allowMismatch) return null
108
+ return {
109
+ name: result[0],
110
+ match: result[1].toLowerCase() === address.toLowerCase(),
111
+ reverseResolverAddress: result[2],
112
+ resolverAddress: result[3],
113
+ }
114
+ } catch (error) {
115
+ if (strict) throw error
116
+ return null
99
117
  }
100
118
  }
101
119
 
@@ -122,7 +140,7 @@ type BatchableFunctionObject = GeneratedFunction<typeof encode, typeof decode>
122
140
  */
123
141
  const getName = generateFunction({ encode, decode }) as ((
124
142
  client: ClientWithEns,
125
- { address }: GetNameParameters,
143
+ { address, allowMismatch, strict }: GetNameParameters,
126
144
  ) => Promise<GetNameReturnType>) &
127
145
  BatchableFunctionObject
128
146