@ensdomains/ensjs 3.1.0 → 3.2.1

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 (170) hide show
  1. package/dist/cjs/clients/public.js.map +1 -1
  2. package/dist/cjs/clients/subgraph.js.map +1 -1
  3. package/dist/cjs/clients/wallet.js.map +1 -1
  4. package/dist/cjs/contracts/addEnsContracts.js.map +1 -1
  5. package/dist/cjs/contracts/consts.js +74 -32
  6. package/dist/cjs/contracts/consts.js.map +1 -1
  7. package/dist/cjs/contracts/dnsRegistrar.js +65 -9
  8. package/dist/cjs/contracts/dnsRegistrar.js.map +1 -1
  9. package/dist/cjs/contracts/dnssecImpl.js +18 -16
  10. package/dist/cjs/contracts/dnssecImpl.js.map +1 -1
  11. package/dist/cjs/contracts/getChainContractAddress.js +5 -1
  12. package/dist/cjs/contracts/getChainContractAddress.js.map +1 -1
  13. package/dist/cjs/contracts/index.js +4 -3
  14. package/dist/cjs/contracts/index.js.map +1 -1
  15. package/dist/cjs/errors/version.js +1 -1
  16. package/dist/cjs/functions/dns/getDnsImportData.js +22 -45
  17. package/dist/cjs/functions/dns/getDnsImportData.js.map +1 -1
  18. package/dist/cjs/functions/dns/importDnsName.js +2 -12
  19. package/dist/cjs/functions/dns/importDnsName.js.map +1 -1
  20. package/dist/cjs/functions/public/_getAbi.js +1 -2
  21. package/dist/cjs/functions/public/_getAbi.js.map +1 -1
  22. package/dist/cjs/functions/public/getAbiRecord.js +2 -2
  23. package/dist/cjs/functions/public/getAbiRecord.js.map +1 -1
  24. package/dist/cjs/functions/public/getRecords.js +2 -2
  25. package/dist/cjs/functions/public/getRecords.js.map +1 -1
  26. package/dist/cjs/functions/wallet/setAbiRecord.js +1 -2
  27. package/dist/cjs/functions/wallet/setAbiRecord.js.map +1 -1
  28. package/dist/cjs/utils/encoders/encodeAbi.js +13 -7
  29. package/dist/cjs/utils/encoders/encodeAbi.js.map +1 -1
  30. package/dist/cjs/utils/encoders/encodeSetAbi.js +1 -1
  31. package/dist/cjs/utils/encoders/encodeSetAbi.js.map +1 -1
  32. package/dist/cjs/utils/generateRecordCallArray.js +6 -4
  33. package/dist/cjs/utils/generateRecordCallArray.js.map +1 -1
  34. package/dist/cjs/utils/generateSupportedContentTypes.js +22 -0
  35. package/dist/cjs/utils/generateSupportedContentTypes.js.map +1 -0
  36. package/dist/cjs/utils/generateSupportedContentTypes.test.ts.js +20 -0
  37. package/dist/cjs/utils/generateSupportedContentTypes.test.ts.js.map +1 -0
  38. package/dist/cjs/utils/index.js +3 -1
  39. package/dist/cjs/utils/index.js.map +1 -1
  40. package/dist/cjs/utils/registerHelpers.js +1 -1
  41. package/dist/cjs/utils/registerHelpers.js.map +1 -1
  42. package/dist/esm/clients/public.js.map +1 -1
  43. package/dist/esm/clients/subgraph.js.map +1 -1
  44. package/dist/esm/clients/wallet.js.map +1 -1
  45. package/dist/esm/contracts/addEnsContracts.js.map +1 -1
  46. package/dist/esm/contracts/consts.js +74 -32
  47. package/dist/esm/contracts/consts.js.map +1 -1
  48. package/dist/esm/contracts/dnsRegistrar.js +64 -8
  49. package/dist/esm/contracts/dnsRegistrar.js.map +1 -1
  50. package/dist/esm/contracts/dnssecImpl.js +17 -15
  51. package/dist/esm/contracts/dnssecImpl.js.map +1 -1
  52. package/dist/esm/contracts/getChainContractAddress.js +5 -1
  53. package/dist/esm/contracts/getChainContractAddress.js.map +1 -1
  54. package/dist/esm/contracts/index.js +2 -2
  55. package/dist/esm/contracts/index.js.map +1 -1
  56. package/dist/esm/errors/version.js +1 -1
  57. package/dist/esm/functions/dns/getDnsImportData.js +25 -48
  58. package/dist/esm/functions/dns/getDnsImportData.js.map +1 -1
  59. package/dist/esm/functions/dns/importDnsName.js +3 -13
  60. package/dist/esm/functions/dns/importDnsName.js.map +1 -1
  61. package/dist/esm/functions/public/_getAbi.js +1 -7
  62. package/dist/esm/functions/public/_getAbi.js.map +1 -1
  63. package/dist/esm/functions/public/getAbiRecord.js +2 -2
  64. package/dist/esm/functions/public/getAbiRecord.js.map +1 -1
  65. package/dist/esm/functions/public/getRecords.js +2 -2
  66. package/dist/esm/functions/public/getRecords.js.map +1 -1
  67. package/dist/esm/functions/wallet/setAbiRecord.js +1 -2
  68. package/dist/esm/functions/wallet/setAbiRecord.js.map +1 -1
  69. package/dist/esm/utils/encoders/encodeAbi.js +13 -7
  70. package/dist/esm/utils/encoders/encodeAbi.js.map +1 -1
  71. package/dist/esm/utils/encoders/encodeSetAbi.js +1 -1
  72. package/dist/esm/utils/encoders/encodeSetAbi.js.map +1 -1
  73. package/dist/esm/utils/generateRecordCallArray.js +6 -4
  74. package/dist/esm/utils/generateRecordCallArray.js.map +1 -1
  75. package/dist/esm/utils/generateSupportedContentTypes.js +18 -0
  76. package/dist/esm/utils/generateSupportedContentTypes.js.map +1 -0
  77. package/dist/esm/utils/generateSupportedContentTypes.test.ts.js +18 -0
  78. package/dist/esm/utils/generateSupportedContentTypes.test.ts.js.map +1 -0
  79. package/dist/esm/utils/index.js +1 -0
  80. package/dist/esm/utils/index.js.map +1 -1
  81. package/dist/esm/utils/registerHelpers.js +1 -1
  82. package/dist/esm/utils/registerHelpers.js.map +1 -1
  83. package/dist/types/clients/decorators/wallet.d.ts +12 -12
  84. package/dist/types/clients/public.d.ts +9 -8
  85. package/dist/types/clients/public.d.ts.map +1 -1
  86. package/dist/types/clients/subgraph.d.ts +4 -4
  87. package/dist/types/clients/subgraph.d.ts.map +1 -1
  88. package/dist/types/clients/wallet.d.ts +117 -117
  89. package/dist/types/clients/wallet.d.ts.map +1 -1
  90. package/dist/types/contracts/addEnsContracts.d.ts +2 -2
  91. package/dist/types/contracts/addEnsContracts.d.ts.map +1 -1
  92. package/dist/types/contracts/consts.d.ts +75 -34
  93. package/dist/types/contracts/consts.d.ts.map +1 -1
  94. package/dist/types/contracts/dnsRegistrar.d.ts +135 -6
  95. package/dist/types/contracts/dnsRegistrar.d.ts.map +1 -1
  96. package/dist/types/contracts/dnssecImpl.d.ts +14 -13
  97. package/dist/types/contracts/dnssecImpl.d.ts.map +1 -1
  98. package/dist/types/contracts/getChainContractAddress.d.ts +15 -7
  99. package/dist/types/contracts/getChainContractAddress.d.ts.map +1 -1
  100. package/dist/types/contracts/index.d.ts +2 -2
  101. package/dist/types/contracts/index.d.ts.map +1 -1
  102. package/dist/types/errors/version.d.ts +1 -1
  103. package/dist/types/functions/dns/getDnsImportData.d.ts +6 -8
  104. package/dist/types/functions/dns/getDnsImportData.d.ts.map +1 -1
  105. package/dist/types/functions/dns/importDnsName.d.ts +25 -25
  106. package/dist/types/functions/dns/importDnsName.d.ts.map +1 -1
  107. package/dist/types/functions/public/_getAbi.d.ts +8 -1
  108. package/dist/types/functions/public/_getAbi.d.ts.map +1 -1
  109. package/dist/types/functions/public/getAbiRecord.d.ts +1 -1
  110. package/dist/types/functions/public/getAbiRecord.d.ts.map +1 -1
  111. package/dist/types/functions/public/getRecords.d.ts +6 -9
  112. package/dist/types/functions/public/getRecords.d.ts.map +1 -1
  113. package/dist/types/functions/wallet/clearRecords.d.ts +24 -24
  114. package/dist/types/functions/wallet/commitName.d.ts +24 -24
  115. package/dist/types/functions/wallet/createSubname.d.ts +24 -24
  116. package/dist/types/functions/wallet/deleteSubname.d.ts +24 -24
  117. package/dist/types/functions/wallet/registerName.d.ts +24 -24
  118. package/dist/types/functions/wallet/renewNames.d.ts +24 -24
  119. package/dist/types/functions/wallet/setAbiRecord.d.ts +25 -25
  120. package/dist/types/functions/wallet/setAbiRecord.d.ts.map +1 -1
  121. package/dist/types/functions/wallet/setAddressRecord.d.ts +24 -24
  122. package/dist/types/functions/wallet/setChildFuses.d.ts +24 -24
  123. package/dist/types/functions/wallet/setContentHashRecord.d.ts +24 -24
  124. package/dist/types/functions/wallet/setFuses.d.ts +24 -24
  125. package/dist/types/functions/wallet/setPrimaryName.d.ts +24 -24
  126. package/dist/types/functions/wallet/setRecords.d.ts +24 -24
  127. package/dist/types/functions/wallet/setResolver.d.ts +24 -24
  128. package/dist/types/functions/wallet/setTextRecord.d.ts +24 -24
  129. package/dist/types/functions/wallet/transferName.d.ts +24 -24
  130. package/dist/types/functions/wallet/unwrapName.d.ts +24 -24
  131. package/dist/types/functions/wallet/wrapName.d.ts +24 -24
  132. package/dist/types/types.d.ts +4 -0
  133. package/dist/types/types.d.ts.map +1 -1
  134. package/dist/types/utils/encoders/encodeAbi.d.ts +3 -3
  135. package/dist/types/utils/encoders/encodeAbi.d.ts.map +1 -1
  136. package/dist/types/utils/encoders/encodeSetAbi.d.ts +1 -4
  137. package/dist/types/utils/encoders/encodeSetAbi.d.ts.map +1 -1
  138. package/dist/types/utils/generateRecordCallArray.d.ts +2 -2
  139. package/dist/types/utils/generateRecordCallArray.d.ts.map +1 -1
  140. package/dist/types/utils/generateSupportedContentTypes.d.ts +3 -0
  141. package/dist/types/utils/generateSupportedContentTypes.d.ts.map +1 -0
  142. package/dist/types/utils/generateSupportedContentTypes.test.ts.d.ts +2 -0
  143. package/dist/types/utils/generateSupportedContentTypes.test.ts.d.ts.map +1 -0
  144. package/dist/types/utils/index.d.ts +1 -0
  145. package/dist/types/utils/index.d.ts.map +1 -1
  146. package/package.json +1 -1
  147. package/src/clients/public.ts +6 -4
  148. package/src/clients/subgraph.ts +6 -4
  149. package/src/clients/wallet.ts +19 -13
  150. package/src/contracts/addEnsContracts.ts +3 -3
  151. package/src/contracts/consts.ts +92 -37
  152. package/src/contracts/dnsRegistrar.ts +65 -8
  153. package/src/contracts/dnssecImpl.ts +17 -15
  154. package/src/contracts/getChainContractAddress.ts +22 -7
  155. package/src/contracts/index.ts +2 -1
  156. package/src/errors/version.ts +1 -1
  157. package/src/functions/dns/getDnsImportData.ts +32 -62
  158. package/src/functions/dns/importDnsName.ts +4 -14
  159. package/src/functions/public/_getAbi.ts +11 -8
  160. package/src/functions/public/getAbiRecord.ts +6 -2
  161. package/src/functions/public/getRecords.ts +23 -31
  162. package/src/functions/wallet/setAbiRecord.ts +2 -3
  163. package/src/types.ts +10 -0
  164. package/src/utils/encoders/encodeAbi.ts +14 -10
  165. package/src/utils/encoders/encodeSetAbi.ts +2 -2
  166. package/src/utils/generateRecordCallArray.ts +6 -4
  167. package/src/utils/generateSupportedContentTypes.test.ts.ts +24 -0
  168. package/src/utils/generateSupportedContentTypes.ts +21 -0
  169. package/src/utils/index.ts +1 -0
  170. package/src/utils/registerHelpers.ts +1 -1
@@ -1,29 +1,31 @@
1
- export const dnssecImplRrDataSnippet = [
1
+ export const dnssecImplVerifyRrSetSnippet = [
2
2
  {
3
3
  inputs: [
4
4
  {
5
- name: 'dnstype',
6
- type: 'uint16',
7
- },
8
- {
9
- name: 'name',
10
- type: 'bytes',
5
+ components: [
6
+ {
7
+ name: 'rrset',
8
+ type: 'bytes',
9
+ },
10
+ {
11
+ name: 'sig',
12
+ type: 'bytes',
13
+ },
14
+ ],
15
+ name: 'input',
16
+ type: 'tuple[]',
11
17
  },
12
18
  ],
13
- name: 'rrdata',
19
+ name: 'verifyRRSet',
14
20
  outputs: [
15
21
  {
16
- name: '',
17
- type: 'uint32',
22
+ name: 'rrs',
23
+ type: 'bytes',
18
24
  },
19
25
  {
20
- name: '',
26
+ name: 'inception',
21
27
  type: 'uint32',
22
28
  },
23
- {
24
- name: '',
25
- type: 'bytes20',
26
- },
27
29
  ],
28
30
  stateMutability: 'view',
29
31
  type: 'function',
@@ -1,13 +1,19 @@
1
+ import type { Address, Chain } from 'viem'
1
2
  import { getChainContractAddress as _getChainContractAddress } from 'viem/utils'
2
- import type { ChainWithEns } from './consts.js'
3
3
 
4
- type ChainClient<TChain extends ChainWithEns> = {
5
- chain: TChain
4
+ type ExtractContract<TClient> = TClient extends {
5
+ chain: { contracts: infer C }
6
6
  }
7
+ ? C extends Record<string, { address: string }>
8
+ ? C
9
+ : never
10
+ : never
7
11
 
8
12
  export const getChainContractAddress = <
9
- TChain extends ChainWithEns,
10
- TClient extends ChainClient<TChain>,
13
+ const TClient extends { chain: Chain },
14
+ TContracts extends ExtractContract<TClient> = ExtractContract<TClient>,
15
+ TContractName extends keyof TContracts = keyof TContracts,
16
+ TContract extends TContracts[TContractName] = TContracts[TContractName],
11
17
  >({
12
18
  blockNumber,
13
19
  client,
@@ -15,5 +21,14 @@ export const getChainContractAddress = <
15
21
  }: {
16
22
  blockNumber?: bigint
17
23
  client: TClient
18
- contract: Extract<keyof TChain['contracts'], string>
19
- }) => _getChainContractAddress({ blockNumber, chain: client.chain, contract })
24
+ contract: TContractName
25
+ }) =>
26
+ _getChainContractAddress({
27
+ blockNumber,
28
+ chain: client.chain,
29
+ contract: contract as string,
30
+ }) as TContract extends { address: infer A }
31
+ ? A extends Address
32
+ ? A
33
+ : never
34
+ : Address
@@ -24,12 +24,13 @@ export {
24
24
  type WalletWithEns,
25
25
  } from './consts.js'
26
26
  export {
27
+ dnsRegistrarErrors,
27
28
  dnsRegistrarProveAndClaimSnippet,
28
29
  dnsRegistrarProveAndClaimWithResolverSnippet,
29
30
  } from './dnsRegistrar.js'
30
31
  export {
31
32
  dnssecImplAnchorsSnippet,
32
- dnssecImplRrDataSnippet,
33
+ dnssecImplVerifyRrSetSnippet,
33
34
  } from './dnssecImpl.js'
34
35
  export { erc165SupportsInterfaceSnippet } from './erc165.js'
35
36
  export {
@@ -1 +1 @@
1
- export const version = 'v3.1.0'
1
+ export const version = 'v3.2.1'
@@ -1,16 +1,11 @@
1
- import type { ProvableAnswer, SignedSet } from '@ensdomains/dnsprovejs'
1
+ import { SignedSet, type ProvableAnswer } from '@ensdomains/dnsprovejs'
2
2
  import type * as packet from 'dns-packet'
3
- import { toType } from 'dns-packet/types.js'
4
- import { keccak256, toBytes, toHex } from 'viem'
3
+ import { toHex, type Client, type Hex, type Transport } from 'viem'
5
4
  import { readContract } from 'viem/actions'
6
- import type { ClientWithEns } from '../../contracts/consts.js'
7
- import {
8
- dnssecImplAnchorsSnippet,
9
- dnssecImplRrDataSnippet,
10
- } from '../../contracts/dnssecImpl.js'
5
+ import type { ChainWithEns } from '../../contracts/consts.js'
6
+ import { dnssecImplVerifyRrSetSnippet } from '../../contracts/dnssecImpl.js'
11
7
  import { getChainContractAddress } from '../../contracts/getChainContractAddress.js'
12
- import { DnsNewerRecordTypeAvailableError } from '../../errors/dns.js'
13
- import { packetToBytes } from '../../utils/hexEncodedName.js'
8
+ import { DnsNewerRecordTypeAvailableError } from '../../index.js'
14
9
  import type { Endpoint } from './types.js'
15
10
 
16
11
  export type GetDnsImportDataParameters = {
@@ -21,14 +16,11 @@ export type GetDnsImportDataParameters = {
21
16
  }
22
17
 
23
18
  export type RrSetWithSig = {
24
- rrset: Uint8Array
25
- sig: Uint8Array
19
+ rrset: Hex
20
+ sig: Hex
26
21
  }
27
22
 
28
- export type GetDnsImportDataReturnType = {
29
- rrsets: RrSetWithSig[]
30
- proof: Uint8Array
31
- }
23
+ export type GetDnsImportDataReturnType = RrSetWithSig[]
32
24
 
33
25
  // Compares two serial numbers using RFC1982 serial number math.
34
26
  const serialNumberGt = (i1: number, i2: number): boolean =>
@@ -38,8 +30,8 @@ const encodeProofs = (
38
30
  proofs: SignedSet<packet.Ds | packet.Dnskey | packet.Rtxt>[],
39
31
  ): RrSetWithSig[] =>
40
32
  proofs.map((proof) => ({
41
- rrset: proof.toWire(true),
42
- sig: proof.signature.data.signature,
33
+ rrset: toHex(proof.toWire(true)),
34
+ sig: toHex(proof.signature.data.signature),
43
35
  }))
44
36
 
45
37
  /**
@@ -63,7 +55,7 @@ const encodeProofs = (
63
55
  * })
64
56
  */
65
57
  const getDnsImportData = async (
66
- client: ClientWithEns,
58
+ client: Client<Transport, ChainWithEns>,
67
59
  {
68
60
  name,
69
61
  endpoint = 'https://cloudflare-dns.com/dns-query',
@@ -81,53 +73,31 @@ const getDnsImportData = async (
81
73
  result.proofs as SignedSet<packet.Ds | packet.Dnskey | packet.Rtxt>[]
82
74
  ).concat([result.answer])
83
75
 
84
- const ensDnssecImplAddress = getChainContractAddress({
85
- client,
86
- contract: 'ensDnssecImpl',
76
+ const rrsets = encodeProofs(allProofs)
77
+
78
+ const [onchainRrData, inception] = await readContract(client, {
79
+ abi: dnssecImplVerifyRrSetSnippet,
80
+ address: getChainContractAddress({
81
+ client,
82
+ contract: 'ensDnssecImpl',
83
+ }),
84
+ functionName: 'verifyRRSet',
85
+ args: [rrsets],
87
86
  })
88
87
 
89
- for (let i = allProofs.length - 1; i >= 0; i -= 1) {
90
- const proof = allProofs[i]
91
- const hexEncodedName = toHex(packetToBytes(proof.signature.name))
92
- const type = toType(proof.signature.data.typeCovered)
93
- // eslint-disable-next-line no-await-in-loop
94
- const [inception, expiration, hash] = await readContract(client, {
95
- abi: dnssecImplRrDataSnippet,
96
- address: ensDnssecImplAddress,
97
- functionName: 'rrdata',
98
- args: [type, hexEncodedName],
88
+ const lastProof = allProofs[allProofs.length - 1]
89
+ if (serialNumberGt(inception, lastProof.signature.data.inception))
90
+ throw new DnsNewerRecordTypeAvailableError({
91
+ typeCovered: lastProof.signature.data.typeCovered,
92
+ signatureName: lastProof.signature.name,
93
+ onchainInception: inception,
94
+ dnsInception: lastProof.signature.data.inception,
99
95
  })
100
- if (serialNumberGt(inception, proof.signature.data.inception))
101
- throw new DnsNewerRecordTypeAvailableError({
102
- typeCovered: proof.signature.data.typeCovered,
103
- signatureName: proof.signature.name,
104
- onchainInception: inception,
105
- dnsInception: proof.signature.data.inception,
106
- })
107
- const expired = serialNumberGt(Date.now() / 1000, expiration)
108
- const proofHash = keccak256(proof.toWire(false)).slice(0, 42)
109
- const isKnownProof = hash === proofHash && !expired
110
- if (isKnownProof) {
111
- if (i === allProofs.length - 1) {
112
- return { rrsets: [], proof: proof.toWire(false) }
113
- }
114
- return {
115
- rrsets: encodeProofs(allProofs.slice(i + 1, allProofs.length)),
116
- proof: proof.toWire(false),
117
- }
118
- }
119
- }
120
96
 
121
- return {
122
- rrsets: encodeProofs(allProofs),
123
- proof: toBytes(
124
- await readContract(client, {
125
- abi: dnssecImplAnchorsSnippet,
126
- address: ensDnssecImplAddress,
127
- functionName: 'anchors',
128
- }),
129
- ),
130
- }
97
+ if (toHex(lastProof.toWire(false)) !== onchainRrData)
98
+ throw new Error('Mismatched proof data')
99
+
100
+ return rrsets
131
101
  }
132
102
 
133
103
  export default getDnsImportData
@@ -1,5 +1,4 @@
1
1
  import {
2
- bytesToHex,
3
2
  encodeFunctionData,
4
3
  toHex,
5
4
  type Account,
@@ -7,6 +6,7 @@ import {
7
6
  type Hash,
8
7
  type SendTransactionParameters,
9
8
  type Transport,
9
+ type WalletClient,
10
10
  } from 'viem'
11
11
  import type { ChainWithEns, WalletWithEns } from '../../contracts/consts.js'
12
12
  import {
@@ -64,7 +64,7 @@ export const makeFunctionData = <
64
64
  TChain extends ChainWithEns,
65
65
  TAccount extends Account | undefined,
66
66
  >(
67
- wallet: WalletWithEns<Transport, TChain, TAccount>,
67
+ wallet: WalletClient<Transport, TChain, TAccount>,
68
68
  {
69
69
  name,
70
70
  dnsImportData,
@@ -72,10 +72,6 @@ export const makeFunctionData = <
72
72
  resolverAddress,
73
73
  }: ImportDnsNameDataParameters,
74
74
  ): ImportDnsNameDataReturnType => {
75
- const data = dnsImportData.rrsets.map((rrset) => ({
76
- rrset: bytesToHex(rrset.rrset),
77
- sig: bytesToHex(rrset.sig),
78
- }))
79
75
  const hexEncodedName = toHex(packetToBytes(name))
80
76
  const dnsRegistrarAddress = getChainContractAddress({
81
77
  client: wallet,
@@ -95,7 +91,7 @@ export const makeFunctionData = <
95
91
  data: encodeFunctionData({
96
92
  abi: dnsRegistrarProveAndClaimSnippet,
97
93
  functionName: 'proveAndClaim',
98
- args: [hexEncodedName, data, bytesToHex(dnsImportData.proof)],
94
+ args: [hexEncodedName, dnsImportData],
99
95
  }),
100
96
  }
101
97
  }
@@ -109,13 +105,7 @@ export const makeFunctionData = <
109
105
  data: encodeFunctionData({
110
106
  abi: dnsRegistrarProveAndClaimWithResolverSnippet,
111
107
  functionName: 'proveAndClaimWithResolver',
112
- args: [
113
- hexEncodedName,
114
- data,
115
- bytesToHex(dnsImportData.proof),
116
- resolverAddress_,
117
- address,
118
- ],
108
+ args: [hexEncodedName, dnsImportData, resolverAddress_, address],
119
109
  }),
120
110
  }
121
111
  }
@@ -19,22 +19,25 @@ import { namehash } from '../../utils/normalise.js'
19
19
  export type InternalGetAbiParameters = {
20
20
  /** Name to get ABI record for */
21
21
  name: string
22
+ /** Supported content types as bitwise
23
+ * ID 1: JSON
24
+ * ID 2: zlib compressed JSON
25
+ * ID 4: CBOR
26
+ * ID 8: URI
27
+ */
28
+ supportedContentTypes?: bigint
22
29
  /** Whether or not to throw decoding errors */
23
30
  strict?: boolean
24
31
  }
25
32
 
26
33
  export type InternalGetAbiReturnType = Prettify<DecodedAbi | null>
27
34
 
28
- // Supported content types as bitwise OR
29
- // ID 1: JSON
30
- // ID 2: zlib compressed JSON
31
- // ID 4: CBOR
32
- // ID 8: URI
33
- const supportedContentTypes = 0xfn
34
-
35
35
  const encode = (
36
36
  _client: ClientWithEns,
37
- { name }: Omit<InternalGetAbiParameters, 'strict'>,
37
+ {
38
+ name,
39
+ supportedContentTypes = 0xfn,
40
+ }: Omit<InternalGetAbiParameters, 'strict'>,
38
41
  ): SimpleTransactionRequest => {
39
42
  return {
40
43
  to: EMPTY_ADDRESS,
@@ -26,9 +26,13 @@ export type GetAbiRecordReturnType = Prettify<InternalGetAbiReturnType>
26
26
 
27
27
  const encode = (
28
28
  client: ClientWithEns,
29
- { name, gatewayUrls }: Omit<GetAbiRecordParameters, 'strict'>,
29
+ {
30
+ name,
31
+ supportedContentTypes,
32
+ gatewayUrls,
33
+ }: Omit<GetAbiRecordParameters, 'strict'>,
30
34
  ): SimpleTransactionRequest => {
31
- const prData = _getAbi.encode(client, { name })
35
+ const prData = _getAbi.encode(client, { name, supportedContentTypes })
32
36
  return universalWrapper.encode(client, {
33
37
  name,
34
38
  data: prData.data,
@@ -81,20 +81,18 @@ type WithCoinsResult = {
81
81
  }
82
82
 
83
83
  export type GetRecordsReturnType<
84
- TTexts extends readonly string[] = readonly [string, ...string[]],
85
- TCoins extends readonly (string | number)[] = readonly [
86
- string | number,
87
- ...(string | number)[],
88
- ],
89
- TContentHash extends boolean = true,
90
- TAbi extends boolean = true,
84
+ TTexts extends readonly string[] | undefined = readonly string[],
85
+ TCoins extends readonly (string | number)[] | undefined = readonly (
86
+ | string
87
+ | number
88
+ )[],
89
+ TContentHash extends boolean | undefined = true,
90
+ TAbi extends boolean | undefined = true,
91
91
  > = Prettify<
92
92
  (TContentHash extends true ? WithContentHashResult : {}) &
93
93
  (TAbi extends true ? WithAbiResult : {}) &
94
- (TTexts extends readonly [string, ...string[]] ? WithTextsResult : {}) &
95
- (TCoins extends readonly [string | number, ...(string | number)[]]
96
- ? WithCoinsResult
97
- : {}) & {
94
+ (TTexts extends readonly string[] ? WithTextsResult : {}) &
95
+ (TCoins extends readonly (string | number)[] ? WithCoinsResult : {}) & {
98
96
  /** Resolver address used for fetch */
99
97
  resolverAddress: Address
100
98
  }
@@ -261,8 +259,8 @@ const createEmptyResult = <
261
259
  GetRecordsParameters<TTexts, TCoins, TContentHash, TAbi>,
262
260
  'texts' | 'coins' | 'abi' | 'contentHash'
263
261
  >) => ({
264
- ...(texts && texts.length > 0 ? { texts: [] as DecodedText[] } : {}),
265
- ...(coins && coins.length > 0 ? { coins: [] as DecodedAddr[] } : {}),
262
+ ...(texts ? { texts: [] as DecodedText[] } : {}),
263
+ ...(coins ? { coins: [] as DecodedAddr[] } : {}),
266
264
  ...(contentHash ? { contentHash: null } : {}),
267
265
  ...(abi ? { abi: null } : {}),
268
266
  })
@@ -347,13 +345,13 @@ const createRecordResult = (
347
345
  }
348
346
 
349
347
  const decode = async <
350
- const TTexts extends readonly string[] = readonly string[],
351
- const TCoins extends readonly (string | number)[] = readonly (
348
+ const TTexts extends readonly string[] | undefined = readonly string[],
349
+ const TCoins extends readonly (string | number)[] | undefined = readonly (
352
350
  | string
353
351
  | number
354
352
  )[],
355
- const TContentHash extends boolean = true,
356
- const TAbi extends boolean = true,
353
+ const TContentHash extends boolean | undefined = undefined,
354
+ const TAbi extends boolean | undefined = undefined,
357
355
  >(
358
356
  client: ClientWithEns,
359
357
  data: Hex | BaseError,
@@ -434,13 +432,10 @@ type BatchableFunctionObject = {
434
432
  encode: EncoderFunction
435
433
  decode: DecoderFunction
436
434
  batch: <
437
- const TTexts extends readonly string[] = readonly string[],
438
- const TCoins extends readonly (string | number)[] = readonly (
439
- | string
440
- | number
441
- )[],
442
- const TContentHash extends boolean = true,
443
- const TAbi extends boolean = true,
435
+ const TTexts extends readonly string[] | undefined = undefined,
436
+ const TCoins extends readonly (string | number)[] | undefined = undefined,
437
+ const TContentHash extends boolean | undefined = undefined,
438
+ const TAbi extends boolean | undefined = undefined,
444
439
  >(
445
440
  args: GetRecordsParameters<TTexts, TCoins, TContentHash, TAbi>,
446
441
  ) => {
@@ -477,13 +472,10 @@ type BatchableFunctionObject = {
477
472
  * // { texts: [{ key: 'com.twitter', value: 'ensdomains' }, { key: 'com.github', value: 'ensdomains' }], coins: [{ id: 60, name: 'ETH', value: '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7' }], contentHash: { protocolType: 'ipns', decoded: 'k51qzi5uqu5djdczd6zw0grmo23j2vkj9uzvujencg15s5rlkq0ss4ivll8wqw' } }
478
473
  */
479
474
  const getRecords = generateFunction({ encode, decode }) as (<
480
- const TTexts extends readonly string[] = readonly string[],
481
- const TCoins extends readonly (string | number)[] = readonly (
482
- | string
483
- | number
484
- )[],
485
- const TContentHash extends boolean = true,
486
- const TAbi extends boolean = true,
475
+ const TTexts extends readonly string[] | undefined = undefined,
476
+ const TCoins extends readonly (string | number)[] | undefined = undefined,
477
+ const TContentHash extends boolean | undefined = undefined,
478
+ const TAbi extends boolean | undefined = undefined,
487
479
  >(
488
480
  client: ClientWithEns,
489
481
  {
@@ -22,7 +22,7 @@ export type SetAbiRecordDataParameters = {
22
22
  /** Name to set ABI for */
23
23
  name: string
24
24
  /** Encoded ABI data to set */
25
- encodedAbi: EncodedAbi | null
25
+ encodedAbi: EncodedAbi
26
26
  /** Resolver address to set ABI on */
27
27
  resolverAddress: Address
28
28
  }
@@ -47,12 +47,11 @@ export const makeFunctionData = <
47
47
  _wallet: WalletWithEns<Transport, TChain, TAccount>,
48
48
  { name, encodedAbi, resolverAddress }: SetAbiRecordDataParameters,
49
49
  ): SetAbiRecordDataReturnType => {
50
- const encodedAbi_ = encodedAbi || { contentType: 0, encodedData: null }
51
50
  return {
52
51
  to: resolverAddress,
53
52
  data: encodeSetAbi({
54
53
  namehash: namehash(name),
55
- ...encodedAbi_,
54
+ ...encodedAbi,
56
55
  } as EncodeSetAbiParameters),
57
56
  }
58
57
  }
package/src/types.ts CHANGED
@@ -11,6 +11,16 @@ export type Prettify<T> = {
11
11
  [K in keyof T]: T[K]
12
12
  } & {}
13
13
 
14
+ type AssignI<T, U> = {
15
+ [K in keyof T as K extends keyof U
16
+ ? U[K] extends void
17
+ ? never
18
+ : K
19
+ : K]: K extends keyof U ? U[K] : T[K]
20
+ }
21
+
22
+ export type Assign<T, U> = AssignI<T, U> & U
23
+
14
24
  export type SimpleTransactionRequest = {
15
25
  [P in keyof Pick<TransactionRequest, 'to' | 'data'>]-?: Exclude<
16
26
  TransactionRequest[P],
@@ -2,7 +2,7 @@ import { bytesToHex, stringToHex, type Hex } from 'viem'
2
2
  import { UnknownContentTypeError } from '../../errors/utils.js'
3
3
  import type { Prettify } from '../../types.js'
4
4
 
5
- type AbiEncodeAs = 'json' | 'zlib' | 'cbor' | 'uri'
5
+ export type AbiEncodeAs = 'json' | 'zlib' | 'cbor' | 'uri'
6
6
 
7
7
  type AbiContentType = 1 | 2 | 4 | 8
8
8
 
@@ -20,11 +20,11 @@ export type EncodeAbiParameters<TEncodeAs extends AbiEncodeAs = AbiEncodeAs> =
20
20
  TEncodeAs extends 'uri'
21
21
  ? {
22
22
  encodeAs: TEncodeAs
23
- data: string
23
+ data: string | null
24
24
  }
25
25
  : {
26
26
  encodeAs: TEncodeAs
27
- data: Record<any, any>
27
+ data: Record<any, any> | null
28
28
  }
29
29
 
30
30
  export type EncodedAbi<TContentType extends AbiContentType = AbiContentType> = {
@@ -72,27 +72,31 @@ export const encodeAbi = async <
72
72
  Prettify<EncodeAbiReturnType<TContentType>>
73
73
  > => {
74
74
  let contentType: AbiContentType
75
- let encodedData: Hex
75
+ let encodedData: Hex = '0x'
76
76
  switch (encodeAs) {
77
77
  case 'json':
78
78
  contentType = 1
79
- encodedData = stringToHex(JSON.stringify(data))
79
+ if (data) encodedData = stringToHex(JSON.stringify(data))
80
80
  break
81
81
  case 'zlib': {
82
82
  contentType = 2
83
- const { deflate } = await import('pako/dist/pako_deflate.min.js')
84
- encodedData = bytesToHex(deflate(JSON.stringify(data)))
83
+ if (data) {
84
+ const { deflate } = await import('pako/dist/pako_deflate.min.js')
85
+ encodedData = bytesToHex(deflate(JSON.stringify(data)))
86
+ }
85
87
  break
86
88
  }
87
89
  case 'cbor': {
88
90
  contentType = 4
89
- const { cborEncode } = await import('@ensdomains/address-encoder/utils')
90
- encodedData = bytesToHex(new Uint8Array(cborEncode(data)))
91
+ if (data) {
92
+ const { cborEncode } = await import('@ensdomains/address-encoder/utils')
93
+ encodedData = bytesToHex(new Uint8Array(cborEncode(data)))
94
+ }
91
95
  break
92
96
  }
93
97
  default: {
94
98
  contentType = 8
95
- encodedData = stringToHex(data as string)
99
+ if (data) encodedData = stringToHex(data as string)
96
100
  break
97
101
  }
98
102
  }
@@ -4,7 +4,7 @@ import type { EncodedAbi } from './encodeAbi.js'
4
4
 
5
5
  export type EncodeSetAbiParameters = {
6
6
  namehash: Hex
7
- } & (EncodedAbi | { contentType: 0; encodedData: null })
7
+ } & EncodedAbi
8
8
 
9
9
  export type EncodeSetAbiReturnType = Hex
10
10
 
@@ -16,6 +16,6 @@ export const encodeSetAbi = ({
16
16
  return encodeFunctionData({
17
17
  abi: publicResolverSetAbiSnippet,
18
18
  functionName: 'setABI',
19
- args: [namehash, BigInt(contentType), encodedData ?? '0x'],
19
+ args: [namehash, BigInt(contentType), encodedData],
20
20
  })
21
21
  }
@@ -26,7 +26,7 @@ export type RecordOptions = Prettify<{
26
26
  /** Array of coin records */
27
27
  coins?: Omit<EncodeSetAddrParameters, 'namehash'>[]
28
28
  /** ABI value */
29
- abi?: EncodedAbi | null
29
+ abi?: EncodedAbi | EncodedAbi[]
30
30
  }>
31
31
 
32
32
  export const generateRecordCallArray = ({
@@ -49,9 +49,11 @@ export const generateRecordCallArray = ({
49
49
  }
50
50
 
51
51
  if (abi !== undefined) {
52
- const abi_ = abi ?? { contentType: 0, encodedData: null }
53
- const data = encodeSetAbi({ namehash, ...abi_ } as EncodeSetAbiParameters)
54
- if (data) calls.push(data)
52
+ const abis = Array.isArray(abi) ? abi : [abi]
53
+ for (const abi_ of abis) {
54
+ const data = encodeSetAbi({ namehash, ...abi_ } as EncodeSetAbiParameters)
55
+ if (data) calls.push(data)
56
+ }
55
57
  }
56
58
 
57
59
  if (texts && texts.length > 0) {
@@ -0,0 +1,24 @@
1
+ import { generateSupportedContentTypes } from './generateSupportedContentTypes.js'
2
+
3
+ type FunctionParameters = Parameters<typeof generateSupportedContentTypes>
4
+ type EncodeAsParameter = FunctionParameters[0]
5
+
6
+ describe('generateSupportedContentTypes', () => {
7
+ it.each([
8
+ ['json', 1n],
9
+ ['zlib', 2n],
10
+ ['cbor', 4n],
11
+ ['uri', 8n],
12
+ ['unknown', 0n],
13
+ [['json', 'zlib'], 3n],
14
+ [['zlib', 'cbor'], 6n],
15
+ [['cbor', 'uri'], 12n],
16
+ [['json', 'zlib', 'cbor', 'uri'], 15n],
17
+ ] as [EncodeAsParameter, bigint][])(
18
+ 'should return the correct bitwise value supportedContentTypes %p (%p)',
19
+ (encodedAs, expected) => {
20
+ const result = generateSupportedContentTypes(encodedAs)
21
+ expect(result).toEqual(expected)
22
+ },
23
+ )
24
+ })
@@ -0,0 +1,21 @@
1
+ import type { AbiEncodeAs } from './encoders/encodeAbi.js'
2
+
3
+ const abiEncodeAsMap: { [key in AbiEncodeAs]: bigint } = {
4
+ json: 1n,
5
+ zlib: 2n,
6
+ cbor: 4n,
7
+ uri: 8n,
8
+ } as const
9
+
10
+ export const generateSupportedContentTypes = (
11
+ encodeAsItemOrList: AbiEncodeAs | AbiEncodeAs[],
12
+ ): bigint => {
13
+ const encodeAsList = Array.isArray(encodeAsItemOrList)
14
+ ? encodeAsItemOrList
15
+ : [encodeAsItemOrList]
16
+ return encodeAsList.reduce<bigint>((result, encodeAs) => {
17
+ const contentType = abiEncodeAsMap[encodeAs]
18
+ if (contentType) result |= contentType
19
+ return result
20
+ }, 0n)
21
+ }
@@ -133,3 +133,4 @@ export {
133
133
  expiryToBigInt,
134
134
  wrappedLabelLengthCheck,
135
135
  } from './wrapper.js'
136
+ export { generateSupportedContentTypes } from './generateSupportedContentTypes.js'
@@ -103,7 +103,7 @@ export const makeCommitmentTuple = ({
103
103
  reverseRecord &&
104
104
  !coins.find(
105
105
  (c) =>
106
- c.coin === 'ETH' ||
106
+ (typeof c.coin === 'string' && c.coin.toLowerCase() === 'eth') ||
107
107
  (typeof c.coin === 'string' ? parseInt(c.coin) === 60 : c.coin === 60),
108
108
  )
109
109
  ) {