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

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 (129) hide show
  1. package/dist/cjs/contracts/getContractAddress.js +4 -4
  2. package/dist/cjs/functions/commitName.js +2 -3
  3. package/dist/cjs/functions/createSubname.js +2 -8
  4. package/dist/cjs/functions/getHistory.js +14 -7
  5. package/dist/cjs/functions/getNames.js +10 -6
  6. package/dist/cjs/functions/getOwner.js +25 -12
  7. package/dist/cjs/functions/getSpecificRecord.js +83 -0
  8. package/dist/cjs/functions/getWrapperData.js +3 -4
  9. package/dist/cjs/functions/renewNames.js +13 -20
  10. package/dist/cjs/functions/{burnFuses.js → setFuses.js} +24 -6
  11. package/dist/cjs/functions/wrapName.js +7 -23
  12. package/dist/cjs/generated/factories/ETHRegistrarController__factory.js +6 -55
  13. package/dist/cjs/generated/factories/NameWrapper__factory.js +90 -69
  14. package/dist/cjs/generated/factories/PublicResolver__factory.js +83 -0
  15. package/dist/cjs/generated/factories/UniversalResolver__factory.js +67 -2
  16. package/dist/cjs/index.js +15 -4
  17. package/dist/cjs/utils/consts.js +3 -1
  18. package/dist/cjs/utils/fuses.js +218 -53
  19. package/dist/cjs/utils/normalise.js +2 -2
  20. package/dist/cjs/utils/recordHelpers.js +55 -0
  21. package/dist/cjs/utils/registerHelpers.js +9 -23
  22. package/dist/cjs/utils/subgraph-types.js +16 -0
  23. package/dist/cjs/utils/wrapper.js +2 -2
  24. package/dist/esm/contracts/getContractAddress.mjs +4 -4
  25. package/dist/esm/functions/commitName.mjs +2 -3
  26. package/dist/esm/functions/createSubname.mjs +2 -2
  27. package/dist/esm/functions/getHistory.mjs +14 -7
  28. package/dist/esm/functions/getNames.mjs +10 -6
  29. package/dist/esm/functions/getOwner.mjs +25 -12
  30. package/dist/esm/functions/getSpecificRecord.mjs +78 -1
  31. package/dist/esm/functions/getWrapperData.mjs +3 -4
  32. package/dist/esm/functions/renewNames.mjs +13 -20
  33. package/dist/esm/functions/setFuses.mjs +30 -0
  34. package/dist/esm/functions/wrapName.mjs +8 -18
  35. package/dist/esm/generated/factories/ETHRegistrarController__factory.mjs +6 -55
  36. package/dist/esm/generated/factories/NameWrapper__factory.mjs +90 -69
  37. package/dist/esm/generated/factories/PublicResolver__factory.mjs +83 -0
  38. package/dist/esm/generated/factories/UniversalResolver__factory.mjs +67 -2
  39. package/dist/esm/index.mjs +15 -4
  40. package/dist/esm/utils/consts.mjs +3 -1
  41. package/dist/esm/utils/fuses.mjs +218 -53
  42. package/dist/esm/utils/normalise.mjs +1 -1
  43. package/dist/esm/utils/recordHelpers.mjs +49 -0
  44. package/dist/esm/utils/registerHelpers.mjs +9 -17
  45. package/dist/esm/utils/subgraph-types.mjs +0 -0
  46. package/dist/esm/utils/wrapper.mjs +1 -1
  47. package/dist/types/functions/commitName.d.ts +5 -6
  48. package/dist/types/functions/createSubname.d.ts +3 -3
  49. package/dist/types/functions/deleteSubname.d.ts +1 -1
  50. package/dist/types/functions/getHistory.d.ts +1 -1
  51. package/dist/types/functions/getNames.d.ts +3 -3
  52. package/dist/types/functions/getOwner.d.ts +1 -0
  53. package/dist/types/functions/getSpecificRecord.d.ts +22 -0
  54. package/dist/types/functions/getWrapperData.d.ts +44 -5
  55. package/dist/types/functions/importDNSSECName.d.ts +1 -1
  56. package/dist/types/functions/registerName.d.ts +1 -1
  57. package/dist/types/functions/renewNames.d.ts +5 -6
  58. package/dist/types/functions/setFuses.d.ts +7 -0
  59. package/dist/types/functions/setName.d.ts +1 -1
  60. package/dist/types/functions/setRecord.d.ts +5 -1
  61. package/dist/types/functions/setRecords.d.ts +1 -1
  62. package/dist/types/functions/setResolver.d.ts +1 -1
  63. package/dist/types/functions/transferController.d.ts +1 -1
  64. package/dist/types/functions/transferName.d.ts +1 -1
  65. package/dist/types/functions/transferSubname.d.ts +1 -1
  66. package/dist/types/functions/types.d.ts +9 -5
  67. package/dist/types/functions/unwrapName.d.ts +1 -1
  68. package/dist/types/functions/wrapName.d.ts +4 -4
  69. package/dist/types/generated/ETHRegistrarController.d.ts +13 -36
  70. package/dist/types/generated/NameWrapper.d.ts +97 -52
  71. package/dist/types/generated/PublicResolver.d.ts +50 -1
  72. package/dist/types/generated/UniversalResolver.d.ts +79 -32
  73. package/dist/types/generated/factories/UniversalResolver__factory.d.ts +15 -0
  74. package/dist/types/index.d.ts +75 -11
  75. package/dist/types/utils/consts.d.ts +1 -0
  76. package/dist/types/utils/fuses.d.ts +115 -45
  77. package/dist/types/utils/recordHelpers.d.ts +14 -2
  78. package/dist/types/utils/registerHelpers.d.ts +7 -25
  79. package/dist/types/utils/subgraph-types.d.ts +284 -0
  80. package/dist/types/utils/writeTx.d.ts +5 -5
  81. package/package.json +8 -5
  82. package/src/@types/pako.d.ts +188 -0
  83. package/src/contracts/bulkRenewal.ts +1 -1
  84. package/src/contracts/getContractAddress.ts +4 -4
  85. package/src/functions/commitName.test.ts +0 -3
  86. package/src/functions/commitName.ts +1 -2
  87. package/src/functions/createSubname.ts +4 -5
  88. package/src/functions/getHistory.ts +59 -25
  89. package/src/functions/getNames.test.ts +1 -1
  90. package/src/functions/getNames.ts +26 -13
  91. package/src/functions/getOwner.test.ts +62 -3
  92. package/src/functions/getOwner.ts +31 -11
  93. package/src/functions/getSpecificRecord.test.ts +162 -0
  94. package/src/functions/getSpecificRecord.ts +95 -1
  95. package/src/functions/getWrapperData.test.ts +11 -45
  96. package/src/functions/getWrapperData.ts +7 -5
  97. package/src/functions/registerName.test.ts +3 -3
  98. package/src/functions/renewNames.ts +17 -23
  99. package/src/functions/setFuses.test.ts +240 -0
  100. package/src/functions/setFuses.ts +44 -0
  101. package/src/functions/setRecord.test.ts +147 -1
  102. package/src/functions/setRecord.ts +6 -1
  103. package/src/functions/types.ts +10 -4
  104. package/src/functions/wrapName.test.ts +8 -7
  105. package/src/functions/wrapName.ts +10 -24
  106. package/src/generated/ETHRegistrarController.ts +12 -79
  107. package/src/generated/NameWrapper.ts +155 -99
  108. package/src/generated/PublicResolver.ts +123 -0
  109. package/src/generated/UniversalResolver.ts +157 -16
  110. package/src/generated/factories/ETHRegistrarController__factory.ts +6 -55
  111. package/src/generated/factories/NameWrapper__factory.ts +90 -69
  112. package/src/generated/factories/PublicResolver__factory.ts +83 -0
  113. package/src/generated/factories/UniversalResolver__factory.ts +67 -2
  114. package/src/index.ts +23 -14
  115. package/src/utils/consts.ts +1 -0
  116. package/src/utils/fuses.ts +299 -102
  117. package/src/utils/normalise.ts +1 -1
  118. package/src/utils/recordHelpers.ts +64 -1
  119. package/src/utils/registerHelpers.ts +13 -41
  120. package/src/utils/subgraph-types.ts +312 -0
  121. package/src/utils/wrapper.ts +1 -1
  122. package/dist/cjs/utils/generateFuseInput.js +0 -40
  123. package/dist/esm/functions/burnFuses.mjs +0 -12
  124. package/dist/esm/utils/generateFuseInput.mjs +0 -15
  125. package/dist/types/functions/burnFuses.d.ts +0 -3
  126. package/dist/types/utils/generateFuseInput.d.ts +0 -3
  127. package/src/functions/burnFuses.test.ts +0 -148
  128. package/src/functions/burnFuses.ts +0 -16
  129. package/src/utils/generateFuseInput.ts +0 -13
@@ -1,160 +1,357 @@
1
- import { BigNumber, BigNumberish } from '@ethersproject/bignumber/lib/bignumber'
2
-
1
+ // child named fuses
3
2
  const CANNOT_UNWRAP = 1
4
3
  const CANNOT_BURN_FUSES = 2
5
4
  const CANNOT_TRANSFER = 4
6
5
  const CANNOT_SET_RESOLVER = 8
7
6
  const CANNOT_SET_TTL = 16
8
7
  const CANNOT_CREATE_SUBDOMAIN = 32
9
- const PARENT_CANNOT_CONTROL = 64
8
+
9
+ // parent named fuses
10
+ const PARENT_CANNOT_CONTROL = 0x10000
11
+ const IS_DOT_ETH = 0x20000
12
+ const CAN_EXTEND_EXPIRY = 0x40000
13
+
14
+ // fuse ranges
15
+ export const CHILD_CONTROLLED_FUSES = 0x0000ffff
16
+ export const PARENT_CONTROLLED_FUSES = 0xffff0000
17
+ export const USER_SETTABLE_FUSES = 0xfffdffff
18
+
19
+ // empty fuse
10
20
  const CAN_DO_EVERYTHING = 0
11
21
 
12
- export const fuseEnum = {
22
+ export const childFuseEnum = {
13
23
  CANNOT_UNWRAP,
14
24
  CANNOT_BURN_FUSES,
15
25
  CANNOT_TRANSFER,
16
26
  CANNOT_SET_RESOLVER,
17
27
  CANNOT_SET_TTL,
18
28
  CANNOT_CREATE_SUBDOMAIN,
19
- PARENT_CANNOT_CONTROL,
20
29
  } as const
21
30
 
22
- export type FuseOptions = { -readonly [K in keyof typeof fuseEnum]?: boolean }
31
+ export const parentFuseEnum = {
32
+ PARENT_CANNOT_CONTROL,
33
+ CAN_EXTEND_EXPIRY,
34
+ }
23
35
 
24
- export const unnamedFuses = [
25
- 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,
26
- 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864,
27
- 134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296,
28
- ] as const
36
+ export const fullParentFuseEnum = {
37
+ ...parentFuseEnum,
38
+ IS_DOT_ETH,
39
+ } as const
40
+
41
+ export const userSettableFuseEnum = {
42
+ ...childFuseEnum,
43
+ ...parentFuseEnum,
44
+ } as const
29
45
 
30
- const fullFuseEnum = {
31
- ...fuseEnum,
46
+ export const fullFuseEnum = {
47
+ ...userSettableFuseEnum,
32
48
  CAN_DO_EVERYTHING,
33
49
  }
34
50
 
35
- export type FuseObj = typeof fuseEnum
36
- export type CurrentFuses = { [f in keyof FuseObj]: boolean } & {
37
- CAN_DO_EVERYTHING: boolean
51
+ export const unnamedChildFuses = [
52
+ 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768,
53
+ ] as const
54
+
55
+ export const unnamedParentFuses = [
56
+ 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000,
57
+ 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000,
58
+ ] as const
59
+
60
+ export const unnamedUserSettableFuses = [
61
+ ...unnamedChildFuses,
62
+ ...unnamedParentFuses,
63
+ ] as const
64
+
65
+ export const childFuseKeys = Object.keys(
66
+ childFuseEnum,
67
+ ) as (keyof typeof childFuseEnum)[]
68
+ export const parentFuseKeys = Object.keys(
69
+ parentFuseEnum,
70
+ ) as (keyof typeof parentFuseEnum)[]
71
+ export const fullParentFuseKeys = Object.keys(
72
+ fullParentFuseEnum,
73
+ ) as (keyof typeof fullParentFuseEnum)[]
74
+ export const userSettableFuseKeys = Object.keys(
75
+ userSettableFuseEnum,
76
+ ) as (keyof typeof userSettableFuseEnum)[]
77
+
78
+ type FuseType<
79
+ Enum extends Record<string, number>,
80
+ UnnamedTuple extends readonly number[],
81
+ CustomFuses extends string = never,
82
+ > = {
83
+ fuse: keyof Enum
84
+ options: { -readonly [K in keyof Enum]?: boolean }
85
+ current: { [K in keyof Enum]: boolean } & {
86
+ readonly [K in CustomFuses]: boolean
87
+ }
88
+ unnamed: UnnamedTuple
89
+ unnamedValues: UnnamedTuple[number]
90
+ unnamedObject: { [K in UnnamedTuple[number]]: boolean }
38
91
  }
39
- export type UnnamedFuseType = typeof unnamedFuses
40
- export type Fuse = keyof FuseObj
41
- export type UnnamedFuseValues = UnnamedFuseType[number]
42
-
43
- // We need this type so that the following type isn't infinite. This type limits the max length of the fuse array to 7.
44
- export type FuseArrayPossibilities =
45
- | [Fuse]
46
- | [Fuse, Fuse]
47
- | [Fuse, Fuse, Fuse]
48
- | [Fuse, Fuse, Fuse, Fuse]
49
- | [Fuse, Fuse, Fuse, Fuse, Fuse]
50
- | [Fuse, Fuse, Fuse, Fuse, Fuse, Fuse]
51
- | [Fuse, Fuse, Fuse, Fuse, Fuse, Fuse, Fuse]
52
-
53
- /**
54
- * This type creates a type error if there are any duplicate fuses.
55
- * It effectively works like a reduce function, starting with 0 included types, adding a type each time, and then checking for duplicates.
56
- *
57
- * @template A The array to check for duplicates.
58
- * @template B The union of all checked existing types.
59
- */
60
- // CLAUSE A: This extension unwraps the type as a fuse tuple.
61
- type FusesWithoutDuplicates<A, B = never> = A extends FuseArrayPossibilities
62
- ? // CLAUSE A > TRUE: CLAUSE B: Pick out the first item in the current array, separating the current item from the rest.
63
- A extends [infer Head, ...infer Tail]
64
- ? // CLAUSE B > TRUE: CLAUSE C: Check if the current item is a duplicate based on the input union.
65
- Head extends B
66
- ? // CLAUSE C > TRUE: Duplicate found, return an empty array to throw a type error.
67
- []
68
- : // CLAUSE C > FALSE: Return a new array to continue the recursion, adds the current item type to the union.
69
- [Head, ...FusesWithoutDuplicates<Tail, Head | B>]
70
- : // CLAUSE B > FALSE: Return the input array as there is no more array elements to check.
71
- A
72
- : // CLAUSE A > FALSE: Return an empty array as it isn't a fuse tuple.
73
- []
74
-
75
- export type NamedFusesToBurn = FusesWithoutDuplicates<FuseArrayPossibilities>
76
-
77
- export type FusePropsNamedArray = {
78
- namedFusesToBurn: NamedFusesToBurn
92
+
93
+ export type ChildFuses = FuseType<
94
+ typeof childFuseEnum,
95
+ typeof unnamedChildFuses,
96
+ 'CAN_DO_EVERYTHING'
97
+ >
98
+ export type ParentFuses = FuseType<
99
+ typeof parentFuseEnum,
100
+ typeof unnamedParentFuses
101
+ >
102
+ export type FullParentFuses = FuseType<
103
+ typeof fullParentFuseEnum,
104
+ typeof unnamedParentFuses
105
+ >
106
+ export type UserSettableFuses = FuseType<
107
+ typeof userSettableFuseEnum,
108
+ typeof unnamedUserSettableFuses
109
+ >
110
+
111
+ type InputFuses<NamedFuse extends string, UnnamedFuse extends number> =
112
+ | {
113
+ named: readonly NamedFuse[]
114
+ }
115
+ | {
116
+ unnamed: readonly UnnamedFuse[]
117
+ }
118
+ | {
119
+ named: readonly NamedFuse[]
120
+ unnamed: readonly UnnamedFuse[]
121
+ }
122
+ | {
123
+ number: number
124
+ }
125
+
126
+ export type CombinedFuseInput = {
127
+ child: InputFuses<ChildFuses['fuse'], ChildFuses['unnamedValues']>
128
+ parent: InputFuses<ParentFuses['fuse'], ParentFuses['unnamedValues']>
79
129
  }
80
130
 
81
- export type FusePropsUnnamedArray = {
82
- unnamedFusesToBurn: UnnamedFuseValues[]
131
+ type FuseRestriction = 'parent' | 'child'
132
+
133
+ const checkNumber = (fuses: number) => {
134
+ if (fuses > 2 ** 32 || fuses < 1) {
135
+ throw new Error(
136
+ `Fuse number must be limited to uint32, ${fuses} was too ${
137
+ fuses < 1 ? 'low' : 'high'
138
+ }.`,
139
+ )
140
+ } else if (fuses % 1 !== 0) {
141
+ throw new Error(`Fuse number must be an integer, ${fuses} was not.`)
142
+ } else if ((fuses & USER_SETTABLE_FUSES) !== fuses) {
143
+ throw new Error(
144
+ `Fuse number must be limited to user settable fuses, ${fuses} was not.`,
145
+ )
146
+ }
83
147
  }
84
148
 
85
- export type FusePropsNumber = {
86
- fuseNumberToBurn: number
149
+ const testFuses = (fuses: any) => {
150
+ if ('named' in fuses && fuses.named.length > 0) {
151
+ return true
152
+ }
153
+ if ('unnamed' in fuses && fuses.unnamed.length > 0) {
154
+ return true
155
+ }
156
+ if ('number' in fuses && fuses.number !== 0) {
157
+ return true
158
+ }
159
+ return false
87
160
  }
88
161
 
89
- export type FuseProps =
90
- | (Partial<FusePropsNamedArray> & FusePropsUnnamedArray)
91
- | (FusePropsNamedArray & Partial<FusePropsUnnamedArray>)
92
- | FusePropsNumber
162
+ export const hasFuses = (fuses: any) => {
163
+ if (typeof fuses === 'number') {
164
+ return fuses !== 0
165
+ }
93
166
 
94
- export const validateFuses = (fuses: FuseProps) => {
95
- const isNumber = 'fuseNumberToBurn' in fuses
96
- const hasNamedArray = 'namedFusesToBurn' in fuses
97
- const hasUnnamedArray = 'unnamedFusesToBurn' in fuses
167
+ if (typeof fuses === 'object') {
168
+ if ('child' in fuses && testFuses(fuses.child)) {
169
+ return true
170
+ }
171
+ if ('parent' in fuses && testFuses(fuses.parent)) {
172
+ return true
173
+ }
174
+ if (testFuses(fuses)) {
175
+ return true
176
+ }
177
+ }
178
+ return false
179
+ }
98
180
 
181
+ export function encodeFuses(fuses: Partial<CombinedFuseInput> | number): number
182
+ export function encodeFuses(
183
+ fuses: CombinedFuseInput['child'],
184
+ restrictTo: 'child',
185
+ ): number
186
+ export function encodeFuses(
187
+ fuses: CombinedFuseInput['parent'],
188
+ restrictTo: 'parent',
189
+ ): number
190
+ export function encodeFuses<T extends FuseRestriction>(
191
+ fuses: CombinedFuseInput[T],
192
+ restrictTo?: T,
193
+ ) {
99
194
  let encodedFuses: number = 0
100
195
 
101
- if (isNumber) {
102
- if (fuses.fuseNumberToBurn > 2 ** 32 || fuses.fuseNumberToBurn < 1) {
103
- throw new Error(
104
- `Fuse number must be limited to uint32, ${
105
- fuses.fuseNumberToBurn
106
- } was too ${fuses.fuseNumberToBurn < 1 ? 'low' : 'high'}.`,
107
- )
108
- } else if (fuses.fuseNumberToBurn % 1 !== 0) {
109
- throw new Error(
110
- `Fuse number must be an integer, ${fuses.fuseNumberToBurn} was not.`,
111
- )
196
+ if (typeof fuses === 'number') {
197
+ if (restrictTo) {
198
+ throw new Error('Cannot specify an exact fuse value when restricted.')
112
199
  }
113
- encodedFuses = fuses.fuseNumberToBurn
200
+ checkNumber(fuses)
201
+
202
+ encodedFuses = fuses
114
203
  } else {
115
- if (!hasNamedArray && !hasUnnamedArray) {
116
- throw new Error('Please provide fuses to burn')
204
+ let fusesRef = fuses as unknown as CombinedFuseInput
205
+ let allowedNamed: readonly UserSettableFuses['fuse'][] = []
206
+ let allowedUnnamed: readonly UserSettableFuses['unnamedValues'][] = []
207
+
208
+ let namedArray: readonly UserSettableFuses['fuse'][] = []
209
+ let unnamedArray: readonly UserSettableFuses['unnamedValues'][] = []
210
+
211
+ if (restrictTo) {
212
+ if ('parent' in fuses || 'child' in fuses) {
213
+ throw new Error("Can't specify fuse category when restricted.")
214
+ }
215
+ allowedNamed = restrictTo === 'child' ? childFuseKeys : parentFuseKeys
216
+ allowedUnnamed =
217
+ restrictTo === 'child' ? unnamedChildFuses : unnamedParentFuses
218
+
219
+ fusesRef = { [restrictTo]: fuses } as unknown as CombinedFuseInput
220
+ } else {
221
+ allowedNamed = userSettableFuseKeys
222
+ allowedUnnamed = unnamedUserSettableFuses
223
+ }
224
+ if ('parent' in fusesRef) {
225
+ if ('named' in fusesRef.parent) namedArray = fusesRef.parent.named
226
+ if ('unnamed' in fusesRef.parent) unnamedArray = fusesRef.parent.unnamed
227
+ if ('number' in fusesRef.parent) {
228
+ if ('named' in fusesRef.parent || 'unnamed' in fusesRef.parent) {
229
+ throw new Error(
230
+ 'Cannot specify both a fuse number and named/unnamed fuses.',
231
+ )
232
+ }
233
+ checkNumber(fusesRef.parent.number)
234
+
235
+ if (
236
+ (fusesRef.parent.number & PARENT_CONTROLLED_FUSES) !==
237
+ fusesRef.parent.number
238
+ ) {
239
+ throw new Error(
240
+ "Cannot specify a fuse value to set that is outside of the parent's control.",
241
+ )
242
+ }
243
+
244
+ encodedFuses |= fusesRef.parent.number
245
+ }
117
246
  }
118
- if (hasNamedArray) {
119
- for (const fuse of fuses.namedFusesToBurn!) {
120
- if (!(fuse in fuseEnum)) {
247
+ if ('child' in fusesRef) {
248
+ if ('named' in fusesRef.child)
249
+ namedArray = [...namedArray, ...fusesRef.child.named]
250
+ if ('unnamed' in fusesRef.child)
251
+ unnamedArray = [...unnamedArray, ...fusesRef.child.unnamed]
252
+ if ('number' in fusesRef.child) {
253
+ if ('named' in fusesRef.child || 'unnamed' in fusesRef.child) {
254
+ throw new Error(
255
+ 'Cannot specify both a fuse number and named/unnamed fuses.',
256
+ )
257
+ }
258
+ checkNumber(fusesRef.child.number)
259
+
260
+ if (
261
+ (fusesRef.child.number & CHILD_CONTROLLED_FUSES) !==
262
+ fusesRef.child.number
263
+ ) {
264
+ throw new Error(
265
+ "Cannot specify a fuse value to set that is outside of the owner's control.",
266
+ )
267
+ }
268
+
269
+ encodedFuses |= fusesRef.child.number
270
+ }
271
+ }
272
+
273
+ if (!namedArray.length && !unnamedArray.length && !encodedFuses) {
274
+ throw new Error('Must specify at least one fuse.')
275
+ }
276
+
277
+ for (const fuse of namedArray) {
278
+ if (!allowedNamed.includes(fuse)) {
279
+ if (!userSettableFuseKeys.includes(fuse)) {
121
280
  throw new Error(`${fuse} is not a valid named fuse.`)
122
281
  }
123
- encodedFuses |= fuseEnum[fuse]
282
+ throw new Error(`Fuse ${fuse} is not allowed for this operation.`)
124
283
  }
284
+ encodedFuses |= userSettableFuseEnum[fuse]
125
285
  }
126
- if (hasUnnamedArray) {
127
- for (const fuse of fuses.unnamedFusesToBurn!) {
128
- if (!unnamedFuses.includes(fuse)) {
286
+ for (const fuse of unnamedArray) {
287
+ if (!allowedUnnamed.includes(fuse)) {
288
+ if (!unnamedUserSettableFuses.includes(fuse)) {
129
289
  throw new Error(
130
- `${fuse} is not a valid unnamed fuse. If you are trying to burn a named fuse, use the namedFusesToBurn property.`,
290
+ `${fuse} is not a valid unnamed fuse. If you are trying to set a named fuse, use the named property.`,
131
291
  )
132
292
  }
133
- encodedFuses |= fuse
293
+ throw new Error(`Fuse ${fuse} is not allowed for this operation.`)
134
294
  }
295
+ encodedFuses |= fuse
135
296
  }
136
297
  }
137
298
 
138
299
  return encodedFuses
139
300
  }
140
301
 
141
- export const decodeFuses = (fuses: BigNumberish) => {
142
- const bnFuses = BigNumber.from(fuses)
143
-
302
+ const decodeNamedFuses = (fuses: number, arr: readonly string[]) => {
144
303
  const fuseObj = Object.fromEntries(
145
- Object.keys(fuseEnum).map((fuse) => [
304
+ arr.map((fuse) => [
146
305
  fuse,
147
- bnFuses.and(fuseEnum[fuse as keyof typeof fuseEnum]).gt(0),
306
+ (fuses &
307
+ userSettableFuseEnum[fuse as keyof typeof userSettableFuseEnum]) >
308
+ 0,
148
309
  ]),
149
310
  )
150
311
 
151
- if (bnFuses.eq(0)) {
152
- fuseObj.CAN_DO_EVERYTHING = true
153
- } else {
154
- fuseObj.CAN_DO_EVERYTHING = false
155
- }
312
+ return fuseObj
313
+ }
156
314
 
157
- return fuseObj as CurrentFuses
315
+ const decodeUnnamedFuses = (fuses: number, arr: readonly number[]) => {
316
+ const fuseObj = Object.fromEntries(
317
+ arr.map((fuse) => [fuse, (fuses & fuse) > 0]),
318
+ )
319
+
320
+ return fuseObj
158
321
  }
159
322
 
323
+ export const decodeFuses = (fuses: number) => {
324
+ const parentNamedFuses = decodeNamedFuses(
325
+ fuses,
326
+ fullParentFuseKeys,
327
+ ) as FullParentFuses['current']
328
+ const parentUnnamedFuses = decodeUnnamedFuses(
329
+ fuses,
330
+ unnamedParentFuses,
331
+ ) as ParentFuses['unnamedObject']
332
+
333
+ const childNamedFuses = decodeNamedFuses(
334
+ fuses,
335
+ childFuseKeys,
336
+ ) as ChildFuses['current']
337
+ const childUnnamedFuses = decodeUnnamedFuses(
338
+ fuses,
339
+ unnamedChildFuses,
340
+ ) as ChildFuses['unnamedObject']
341
+
342
+ return {
343
+ parent: {
344
+ ...parentNamedFuses,
345
+ unnamed: parentUnnamedFuses,
346
+ },
347
+ child: {
348
+ ...childNamedFuses,
349
+ CAN_DO_EVERYTHING: (fuses & CHILD_CONTROLLED_FUSES) === 0,
350
+ unnamed: childUnnamedFuses,
351
+ },
352
+ }
353
+ }
354
+
355
+ export type AllCurrentFuses = ReturnType<typeof decodeFuses>
356
+
160
357
  export default fullFuseEnum
@@ -1,6 +1,6 @@
1
1
  import { concat, hexlify } from '@ethersproject/bytes'
2
2
  import { keccak256 } from '@ethersproject/keccak256'
3
- import { toUtf8Bytes } from '@ethersproject/strings/lib/utf8'
3
+ import { toUtf8Bytes } from '@ethersproject/strings'
4
4
  import uts46 from 'idna-uts46-hx/uts46bundle.js'
5
5
  import { decodeLabelhash, isEncodedLabelhash } from './labels'
6
6
 
@@ -1,4 +1,7 @@
1
1
  import { formatsByCoinType, formatsByName } from '@ensdomains/address-encoder'
2
+ import { isBytesLike } from '@ethersproject/bytes'
3
+ import { toUtf8Bytes } from '@ethersproject/strings'
4
+ import type { BigNumberish } from 'ethers'
2
5
  import type { PublicResolver } from '../generated'
3
6
  import { encodeContenthash } from './contentHash'
4
7
 
@@ -7,11 +10,19 @@ type RecordItem = {
7
10
  value: string
8
11
  }
9
12
 
13
+ type ABIEncodeAs = 'json' | 'zlib' | 'cbor' | 'uri'
14
+
15
+ type ABIItem = {
16
+ contentType?: BigNumberish
17
+ data: object | string
18
+ }
19
+
10
20
  export type RecordOptions = {
11
21
  clearRecords?: boolean
12
22
  contentHash?: string
13
23
  texts?: RecordItem[]
14
24
  coinTypes?: RecordItem[]
25
+ abi?: ABIItem
15
26
  }
16
27
 
17
28
  export const generateSetAddr = (
@@ -34,10 +45,44 @@ export const generateSetAddr = (
34
45
  )
35
46
  }
36
47
 
37
- export type RecordTypes = 'contentHash' | 'text' | 'addr'
48
+ export const generateABIInput = async (
49
+ encodeAs: ABIEncodeAs,
50
+ data: object | string,
51
+ ) => {
52
+ let contentType: number
53
+ let encodedData: string | Buffer | Uint8Array
54
+ switch (encodeAs) {
55
+ case 'json':
56
+ contentType = 1
57
+ encodedData = JSON.stringify(data)
58
+ break
59
+ case 'zlib': {
60
+ contentType = 2
61
+ const { deflate } = await import('pako/dist/pako_deflate.min.js')
62
+ encodedData = deflate(JSON.stringify(data))
63
+ break
64
+ }
65
+ case 'cbor': {
66
+ contentType = 4
67
+ const { encode } = await import('cbor')
68
+ encodedData = encode(data)
69
+ break
70
+ }
71
+ default: {
72
+ contentType = 8
73
+ encodedData = data as string
74
+ break
75
+ }
76
+ }
77
+ return { contentType, data: encodedData }
78
+ }
79
+
80
+ export type RecordTypes = 'contentHash' | 'text' | 'addr' | 'abi'
38
81
 
39
82
  export type RecordInput<T extends RecordTypes> = T extends 'contentHash'
40
83
  ? string
84
+ : T extends 'abi'
85
+ ? ABIItem
41
86
  : RecordItem
42
87
 
43
88
  export function generateSingleRecordCall<T extends RecordTypes>(
@@ -60,6 +105,24 @@ export function generateSingleRecordCall<T extends RecordTypes>(
60
105
  ])
61
106
  }
62
107
  }
108
+ if (type === 'abi') {
109
+ return (_r: RecordInput<T>) => {
110
+ const record = _r as ABIItem
111
+ const { contentType = 1, data } = record
112
+ let encodedData = data as string | Uint8Array | Buffer
113
+ if (!isBytesLike(encodedData)) {
114
+ if (typeof encodedData === 'object') {
115
+ encodedData = JSON.stringify(encodedData)
116
+ }
117
+ encodedData = toUtf8Bytes(encodedData)
118
+ }
119
+ return resolver.interface.encodeFunctionData('setABI', [
120
+ namehash,
121
+ contentType,
122
+ encodedData,
123
+ ])
124
+ }
125
+ }
63
126
  return (_r: RecordInput<T>) => {
64
127
  const record = _r as RecordItem
65
128
  if (type === 'text') {