@ensdomains/ensjs 3.0.1 → 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.
- package/dist/cjs/clients/decorators/public.js.map +1 -1
- package/dist/cjs/contracts/consts.js +3 -3
- package/dist/cjs/contracts/universalResolver.js +92 -59
- package/dist/cjs/contracts/universalResolver.js.map +1 -1
- package/dist/cjs/errors/version.js +1 -1
- package/dist/cjs/functions/public/_getAbi.js +52 -45
- package/dist/cjs/functions/public/_getAbi.js.map +1 -1
- package/dist/cjs/functions/public/_getAddr.js +30 -23
- package/dist/cjs/functions/public/_getAddr.js.map +1 -1
- package/dist/cjs/functions/public/_getContentHash.js +14 -7
- package/dist/cjs/functions/public/_getContentHash.js.map +1 -1
- package/dist/cjs/functions/public/_getText.js +15 -8
- package/dist/cjs/functions/public/_getText.js.map +1 -1
- package/dist/cjs/functions/public/getAbiRecord.js +13 -5
- package/dist/cjs/functions/public/getAbiRecord.js.map +1 -1
- package/dist/cjs/functions/public/getAddressRecord.js +13 -5
- package/dist/cjs/functions/public/getAddressRecord.js.map +1 -1
- package/dist/cjs/functions/public/getContentHashRecord.js +13 -5
- package/dist/cjs/functions/public/getContentHashRecord.js.map +1 -1
- package/dist/cjs/functions/public/getName.js +53 -35
- package/dist/cjs/functions/public/getName.js.map +1 -1
- package/dist/cjs/functions/public/getRecords.js +164 -161
- package/dist/cjs/functions/public/getRecords.js.map +1 -1
- package/dist/cjs/functions/public/getTextRecord.js +13 -5
- package/dist/cjs/functions/public/getTextRecord.js.map +1 -1
- package/dist/cjs/functions/public/universalWrapper.js +45 -37
- package/dist/cjs/functions/public/universalWrapper.js.map +1 -1
- package/dist/cjs/utils/checkSafeUniversalResolverData.js +35 -0
- package/dist/cjs/utils/checkSafeUniversalResolverData.js.map +1 -0
- package/dist/esm/clients/decorators/public.js.map +1 -1
- package/dist/esm/contracts/consts.js +3 -3
- package/dist/esm/contracts/universalResolver.js +92 -59
- package/dist/esm/contracts/universalResolver.js.map +1 -1
- package/dist/esm/errors/version.js +1 -1
- package/dist/esm/functions/public/_getAbi.js +56 -49
- package/dist/esm/functions/public/_getAbi.js.map +1 -1
- package/dist/esm/functions/public/_getAddr.js +30 -23
- package/dist/esm/functions/public/_getAddr.js.map +1 -1
- package/dist/esm/functions/public/_getContentHash.js +14 -7
- package/dist/esm/functions/public/_getContentHash.js.map +1 -1
- package/dist/esm/functions/public/_getText.js +15 -8
- package/dist/esm/functions/public/_getText.js.map +1 -1
- package/dist/esm/functions/public/getAbiRecord.js +13 -5
- package/dist/esm/functions/public/getAbiRecord.js.map +1 -1
- package/dist/esm/functions/public/getAddressRecord.js +13 -5
- package/dist/esm/functions/public/getAddressRecord.js.map +1 -1
- package/dist/esm/functions/public/getContentHashRecord.js +13 -5
- package/dist/esm/functions/public/getContentHashRecord.js.map +1 -1
- package/dist/esm/functions/public/getName.js +54 -36
- package/dist/esm/functions/public/getName.js.map +1 -1
- package/dist/esm/functions/public/getRecords.js +168 -165
- package/dist/esm/functions/public/getRecords.js.map +1 -1
- package/dist/esm/functions/public/getTextRecord.js +13 -5
- package/dist/esm/functions/public/getTextRecord.js.map +1 -1
- package/dist/esm/functions/public/universalWrapper.js +46 -38
- package/dist/esm/functions/public/universalWrapper.js.map +1 -1
- package/dist/esm/utils/checkSafeUniversalResolverData.js +39 -0
- package/dist/esm/utils/checkSafeUniversalResolverData.js.map +1 -0
- package/dist/types/clients/decorators/public.d.ts +6 -6
- package/dist/types/clients/decorators/public.d.ts.map +1 -1
- package/dist/types/clients/public.d.ts +34 -8
- package/dist/types/clients/public.d.ts.map +1 -1
- package/dist/types/contracts/consts.d.ts +3 -3
- package/dist/types/contracts/universalResolver.d.ts +73 -0
- package/dist/types/contracts/universalResolver.d.ts.map +1 -1
- package/dist/types/errors/version.d.ts +1 -1
- package/dist/types/functions/public/_getAbi.d.ts +3 -1
- package/dist/types/functions/public/_getAbi.d.ts.map +1 -1
- package/dist/types/functions/public/_getAddr.d.ts +3 -1
- package/dist/types/functions/public/_getAddr.d.ts.map +1 -1
- package/dist/types/functions/public/_getContentHash.d.ts +3 -1
- package/dist/types/functions/public/_getContentHash.d.ts.map +1 -1
- package/dist/types/functions/public/_getText.d.ts +3 -1
- package/dist/types/functions/public/_getText.d.ts.map +1 -1
- package/dist/types/functions/public/getAbiRecord.d.ts +8 -5
- package/dist/types/functions/public/getAbiRecord.d.ts.map +1 -1
- package/dist/types/functions/public/getAddressRecord.d.ts +8 -5
- package/dist/types/functions/public/getAddressRecord.d.ts.map +1 -1
- package/dist/types/functions/public/getContentHashRecord.d.ts +7 -4
- package/dist/types/functions/public/getContentHashRecord.d.ts.map +1 -1
- package/dist/types/functions/public/getName.d.ts +9 -3
- package/dist/types/functions/public/getName.d.ts.map +1 -1
- package/dist/types/functions/public/getRecords.d.ts +53 -26
- package/dist/types/functions/public/getRecords.d.ts.map +1 -1
- package/dist/types/functions/public/getTextRecord.d.ts +7 -4
- package/dist/types/functions/public/getTextRecord.d.ts.map +1 -1
- package/dist/types/functions/public/universalWrapper.d.ts +4 -2
- package/dist/types/functions/public/universalWrapper.d.ts.map +1 -1
- package/dist/types/types.d.ts +2 -2
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/checkSafeUniversalResolverData.d.ts +14 -0
- package/dist/types/utils/checkSafeUniversalResolverData.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/clients/decorators/public.ts +31 -4
- package/src/contracts/consts.ts +3 -3
- package/src/contracts/universalResolver.ts +95 -59
- package/src/errors/version.ts +1 -1
- package/src/functions/public/_getAbi.ts +61 -53
- package/src/functions/public/_getAddr.ts +31 -24
- package/src/functions/public/_getContentHash.ts +15 -7
- package/src/functions/public/_getText.ts +16 -8
- package/src/functions/public/getAbiRecord.ts +21 -8
- package/src/functions/public/getAddressRecord.ts +25 -9
- package/src/functions/public/getContentHashRecord.ts +19 -7
- package/src/functions/public/getName.ts +58 -40
- package/src/functions/public/getRecords.ts +336 -235
- package/src/functions/public/getTextRecord.ts +19 -6
- package/src/functions/public/universalWrapper.ts +49 -43
- package/src/types.ts +4 -3
- package/src/utils/checkSafeUniversalResolverData.ts +62 -0
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BaseError,
|
|
3
3
|
decodeAbiParameters,
|
|
4
|
-
decodeErrorResult,
|
|
5
4
|
decodeFunctionResult,
|
|
6
5
|
encodeFunctionData,
|
|
7
|
-
getContractError,
|
|
8
6
|
hexToBigInt,
|
|
9
7
|
toHex,
|
|
10
8
|
type Address,
|
|
@@ -16,12 +14,13 @@ import { universalResolverResolveArraySnippet } from '../../contracts/universalR
|
|
|
16
14
|
import type {
|
|
17
15
|
DecodedAddr,
|
|
18
16
|
DecodedText,
|
|
17
|
+
Prettify,
|
|
19
18
|
SimpleTransactionRequest,
|
|
20
19
|
TransactionRequestWithPassthrough,
|
|
21
20
|
} from '../../types.js'
|
|
21
|
+
import { checkSafeUniversalResolverData } from '../../utils/checkSafeUniversalResolverData.js'
|
|
22
22
|
import { EMPTY_ADDRESS } from '../../utils/consts.js'
|
|
23
23
|
import { generateFunction } from '../../utils/generateFunction.js'
|
|
24
|
-
import { getRevertErrorData } from '../../utils/getRevertErrorData.js'
|
|
25
24
|
import { packetToBytes } from '../../utils/hexEncodedName.js'
|
|
26
25
|
import _getAbi, { type InternalGetAbiReturnType } from './_getAbi.js'
|
|
27
26
|
import _getAddr from './_getAddr.js'
|
|
@@ -31,9 +30,25 @@ import _getContentHash, {
|
|
|
31
30
|
import _getText from './_getText.js'
|
|
32
31
|
import multicallWrapper from './multicallWrapper.js'
|
|
33
32
|
|
|
34
|
-
export type GetRecordsParameters
|
|
33
|
+
export type GetRecordsParameters<
|
|
34
|
+
TTexts extends readonly string[] | undefined = readonly string[],
|
|
35
|
+
TCoins extends readonly (string | number)[] | undefined = readonly (
|
|
36
|
+
| string
|
|
37
|
+
| number
|
|
38
|
+
)[],
|
|
39
|
+
TContentHash extends boolean | undefined = true,
|
|
40
|
+
TAbi extends boolean | undefined = true,
|
|
41
|
+
> = {
|
|
35
42
|
/** Name to get records for */
|
|
36
43
|
name: string
|
|
44
|
+
/** Text record key array */
|
|
45
|
+
texts?: TTexts
|
|
46
|
+
/** Coin record id/symbol array */
|
|
47
|
+
coins?: TCoins
|
|
48
|
+
/** If true, will fetch content hash */
|
|
49
|
+
contentHash?: TContentHash
|
|
50
|
+
/** If true, will fetch ABI */
|
|
51
|
+
abi?: TAbi
|
|
37
52
|
/** Optional specific resolver address, for fallback or for all results */
|
|
38
53
|
resolver?: {
|
|
39
54
|
/** Resolver address */
|
|
@@ -41,17 +56,8 @@ export type GetRecordsParameters = {
|
|
|
41
56
|
/** If true, will only use resolver if main fetch fails */
|
|
42
57
|
fallbackOnly?: boolean
|
|
43
58
|
}
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
/** Text record key array */
|
|
47
|
-
texts?: string[]
|
|
48
|
-
/** Coin record id/symbol array */
|
|
49
|
-
coins?: (string | number)[]
|
|
50
|
-
/** If true, will fetch content hash */
|
|
51
|
-
contentHash?: boolean
|
|
52
|
-
/** If true, will fetch ABI */
|
|
53
|
-
abi?: boolean
|
|
54
|
-
}
|
|
59
|
+
/** Batch gateway URLs to use for resolving CCIP-read requests. */
|
|
60
|
+
gatewayUrls?: string[]
|
|
55
61
|
}
|
|
56
62
|
|
|
57
63
|
type WithContentHashResult = {
|
|
@@ -74,182 +80,321 @@ type WithCoinsResult = {
|
|
|
74
80
|
coins: DecodedAddr[]
|
|
75
81
|
}
|
|
76
82
|
|
|
77
|
-
type BaseGetRecordsReturnType = Partial<
|
|
78
|
-
WithContentHashResult & WithAbiResult & WithTextsResult & WithCoinsResult
|
|
79
|
-
> & {
|
|
80
|
-
/** Resolver address used for fetch */
|
|
81
|
-
resolverAddress: Address
|
|
82
|
-
}
|
|
83
|
-
|
|
84
83
|
export type GetRecordsReturnType<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
type: 'coin' | 'text' | 'contentHash' | 'abi'
|
|
104
|
-
}
|
|
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,
|
|
91
|
+
> = Prettify<
|
|
92
|
+
(TContentHash extends true ? WithContentHashResult : {}) &
|
|
93
|
+
(TAbi extends true ? WithAbiResult : {}) &
|
|
94
|
+
(TTexts extends readonly [string, ...string[]] ? WithTextsResult : {}) &
|
|
95
|
+
(TCoins extends readonly [string | number, ...(string | number)[]]
|
|
96
|
+
? WithCoinsResult
|
|
97
|
+
: {}) & {
|
|
98
|
+
/** Resolver address used for fetch */
|
|
99
|
+
resolverAddress: Address
|
|
100
|
+
}
|
|
101
|
+
>
|
|
105
102
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
({
|
|
117
|
-
key: text,
|
|
118
|
-
call: _getText.encode(client, { name, key: text }),
|
|
119
|
-
type: 'text',
|
|
120
|
-
} as const),
|
|
121
|
-
),
|
|
122
|
-
]
|
|
103
|
+
type CallObj =
|
|
104
|
+
| {
|
|
105
|
+
key: string
|
|
106
|
+
call: SimpleTransactionRequest
|
|
107
|
+
type: 'text'
|
|
108
|
+
}
|
|
109
|
+
| {
|
|
110
|
+
key: string | number
|
|
111
|
+
call: SimpleTransactionRequest
|
|
112
|
+
type: 'coin'
|
|
123
113
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
(coin) =>
|
|
129
|
-
({
|
|
130
|
-
key: coin,
|
|
131
|
-
call: _getAddr.encode(client, { name, coin }),
|
|
132
|
-
type: 'coin',
|
|
133
|
-
} as const),
|
|
134
|
-
),
|
|
135
|
-
]
|
|
114
|
+
| {
|
|
115
|
+
key: 'contentHash'
|
|
116
|
+
call: SimpleTransactionRequest
|
|
117
|
+
type: 'contentHash'
|
|
136
118
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
119
|
+
| {
|
|
120
|
+
key: 'abi'
|
|
121
|
+
call: SimpleTransactionRequest
|
|
122
|
+
type: 'abi'
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
type EncodeReturnType = Required<
|
|
126
|
+
TransactionRequestWithPassthrough<{
|
|
127
|
+
calls: (CallObj | null)[]
|
|
128
|
+
address?: Address
|
|
129
|
+
args?: any
|
|
130
|
+
}>
|
|
131
|
+
>
|
|
132
|
+
|
|
133
|
+
const createCalls = (
|
|
134
|
+
client: ClientWithEns,
|
|
135
|
+
{
|
|
136
|
+
name,
|
|
137
|
+
texts,
|
|
138
|
+
coins,
|
|
139
|
+
abi,
|
|
140
|
+
contentHash,
|
|
141
|
+
}: Pick<
|
|
142
|
+
GetRecordsParameters,
|
|
143
|
+
'name' | 'texts' | 'coins' | 'abi' | 'contentHash'
|
|
144
|
+
>,
|
|
145
|
+
) => [
|
|
146
|
+
...(texts ?? []).map(
|
|
147
|
+
(text) =>
|
|
148
|
+
({
|
|
149
|
+
key: text,
|
|
150
|
+
call: _getText.encode(client, { name, key: text }),
|
|
151
|
+
type: 'text',
|
|
152
|
+
} as const),
|
|
153
|
+
),
|
|
154
|
+
...(coins ?? []).map(
|
|
155
|
+
(coin) =>
|
|
156
|
+
({
|
|
157
|
+
key: coin,
|
|
158
|
+
call: _getAddr.encode(client, { name, coin }),
|
|
159
|
+
type: 'coin',
|
|
160
|
+
} as const),
|
|
161
|
+
),
|
|
162
|
+
...(contentHash
|
|
163
|
+
? ([
|
|
140
164
|
{
|
|
141
165
|
key: 'contentHash',
|
|
142
166
|
call: _getContentHash.encode(client, { name }),
|
|
143
167
|
type: 'contentHash',
|
|
144
|
-
}
|
|
145
|
-
]
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
type: 'abi',
|
|
154
|
-
} as const,
|
|
155
|
-
]
|
|
156
|
-
}
|
|
157
|
-
return prev
|
|
158
|
-
}, [] as (CallObj | null)[])
|
|
168
|
+
},
|
|
169
|
+
] as const)
|
|
170
|
+
: []),
|
|
171
|
+
...(abi
|
|
172
|
+
? ([
|
|
173
|
+
{ key: 'abi', call: _getAbi.encode(client, { name }), type: 'abi' },
|
|
174
|
+
] as const)
|
|
175
|
+
: []),
|
|
176
|
+
]
|
|
159
177
|
|
|
160
|
-
|
|
178
|
+
const encode = (
|
|
179
|
+
client: ClientWithEns,
|
|
180
|
+
{
|
|
181
|
+
name,
|
|
182
|
+
resolver,
|
|
183
|
+
texts,
|
|
184
|
+
coins,
|
|
185
|
+
contentHash,
|
|
186
|
+
abi,
|
|
187
|
+
gatewayUrls,
|
|
188
|
+
}: GetRecordsParameters,
|
|
189
|
+
): EncodeReturnType => {
|
|
190
|
+
const calls = createCalls(client, {
|
|
191
|
+
name,
|
|
192
|
+
texts,
|
|
193
|
+
coins,
|
|
194
|
+
contentHash,
|
|
195
|
+
abi,
|
|
196
|
+
})
|
|
161
197
|
|
|
162
198
|
if (resolver?.address && !resolver.fallbackOnly) {
|
|
163
199
|
const encoded = multicallWrapper.encode(client, {
|
|
164
|
-
transactions: calls
|
|
165
|
-
.
|
|
166
|
-
|
|
200
|
+
transactions: calls.map((c) => ({
|
|
201
|
+
to: resolver.address,
|
|
202
|
+
data: c.call.data,
|
|
203
|
+
})),
|
|
167
204
|
})
|
|
168
205
|
return {
|
|
169
206
|
...encoded,
|
|
170
|
-
passthrough,
|
|
207
|
+
passthrough: { calls },
|
|
171
208
|
}
|
|
172
209
|
}
|
|
173
210
|
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
args: [
|
|
178
|
-
toHex(packetToBytes(name)),
|
|
179
|
-
calls.filter((c) => c).map((c) => c!.call.data),
|
|
180
|
-
],
|
|
211
|
+
const to = getChainContractAddress({
|
|
212
|
+
client,
|
|
213
|
+
contract: 'ensUniversalResolver',
|
|
181
214
|
})
|
|
215
|
+
const args = [
|
|
216
|
+
toHex(packetToBytes(name)),
|
|
217
|
+
calls.map((c) => c.call.data),
|
|
218
|
+
] as const
|
|
182
219
|
|
|
183
220
|
return {
|
|
184
|
-
to
|
|
185
|
-
|
|
186
|
-
|
|
221
|
+
to,
|
|
222
|
+
...(gatewayUrls?.length
|
|
223
|
+
? {
|
|
224
|
+
data: encodeFunctionData({
|
|
225
|
+
abi: universalResolverResolveArraySnippet,
|
|
226
|
+
functionName: 'resolve',
|
|
227
|
+
args: [...args, gatewayUrls] as const,
|
|
228
|
+
}),
|
|
229
|
+
passthrough: {
|
|
230
|
+
calls,
|
|
231
|
+
args: [...args, gatewayUrls],
|
|
232
|
+
address: to,
|
|
233
|
+
},
|
|
234
|
+
}
|
|
235
|
+
: {
|
|
236
|
+
data: encodeFunctionData({
|
|
237
|
+
abi: universalResolverResolveArraySnippet,
|
|
238
|
+
functionName: 'resolve',
|
|
239
|
+
args,
|
|
240
|
+
}),
|
|
241
|
+
passthrough: {
|
|
242
|
+
calls,
|
|
243
|
+
args,
|
|
244
|
+
address: to,
|
|
245
|
+
},
|
|
246
|
+
}),
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const createEmptyResult = <
|
|
251
|
+
TTexts extends readonly string[] | undefined,
|
|
252
|
+
TCoins extends readonly (string | number)[] | undefined,
|
|
253
|
+
TContentHash extends boolean | undefined,
|
|
254
|
+
TAbi extends boolean | undefined,
|
|
255
|
+
>({
|
|
256
|
+
texts,
|
|
257
|
+
coins,
|
|
258
|
+
abi,
|
|
259
|
+
contentHash,
|
|
260
|
+
}: Pick<
|
|
261
|
+
GetRecordsParameters<TTexts, TCoins, TContentHash, TAbi>,
|
|
262
|
+
'texts' | 'coins' | 'abi' | 'contentHash'
|
|
263
|
+
>) => ({
|
|
264
|
+
...(texts && texts.length > 0 ? { texts: [] as DecodedText[] } : {}),
|
|
265
|
+
...(coins && coins.length > 0 ? { coins: [] as DecodedAddr[] } : {}),
|
|
266
|
+
...(contentHash ? { contentHash: null } : {}),
|
|
267
|
+
...(abi ? { abi: null } : {}),
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
const decodeRecord = async (
|
|
271
|
+
client: ClientWithEns,
|
|
272
|
+
{ item, call }: { item: Hex; call: CallObj },
|
|
273
|
+
) => {
|
|
274
|
+
const { key, type } = call
|
|
275
|
+
const baseItem = { key, type }
|
|
276
|
+
if (type === 'contentHash') {
|
|
277
|
+
try {
|
|
278
|
+
const decodedFromAbi = decodeAbiParameters(
|
|
279
|
+
[{ type: 'bytes' }] as const,
|
|
280
|
+
item,
|
|
281
|
+
)[0]
|
|
282
|
+
if (decodedFromAbi === '0x' || hexToBigInt(decodedFromAbi) === 0n) {
|
|
283
|
+
return { ...baseItem, value: null }
|
|
284
|
+
}
|
|
285
|
+
} catch {
|
|
286
|
+
// ignore
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (type === 'text') {
|
|
290
|
+
const decodedFromAbi = await _getText.decode(client, item, {
|
|
291
|
+
strict: false,
|
|
292
|
+
})
|
|
293
|
+
return { ...baseItem, value: decodedFromAbi }
|
|
294
|
+
}
|
|
295
|
+
if (type === 'coin') {
|
|
296
|
+
const decodedFromAbi = await _getAddr.decode(client, item, {
|
|
297
|
+
coin: key,
|
|
298
|
+
strict: false,
|
|
299
|
+
})
|
|
300
|
+
return { ...baseItem, value: decodedFromAbi }
|
|
301
|
+
}
|
|
302
|
+
if (type === 'contentHash') {
|
|
303
|
+
const decodedFromAbi = await _getContentHash.decode(client, item, {
|
|
304
|
+
strict: false,
|
|
305
|
+
})
|
|
306
|
+
return { ...baseItem, value: decodedFromAbi }
|
|
307
|
+
}
|
|
308
|
+
// abi
|
|
309
|
+
const decodedFromAbi = await _getAbi.decode(client, item, {
|
|
310
|
+
strict: false,
|
|
311
|
+
})
|
|
312
|
+
return { ...baseItem, value: decodedFromAbi }
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const createRecordResult = (
|
|
316
|
+
prev: GetRecordsReturnType,
|
|
317
|
+
curr: Awaited<ReturnType<typeof decodeRecord>>,
|
|
318
|
+
) => {
|
|
319
|
+
if (curr.type === 'text' || curr.type === 'coin') {
|
|
320
|
+
if (!curr.value) {
|
|
321
|
+
return prev
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (curr.type === 'text') {
|
|
325
|
+
return {
|
|
326
|
+
...prev,
|
|
327
|
+
texts: [
|
|
328
|
+
...(prev.texts || []),
|
|
329
|
+
{ key: curr.key, value: curr.value } as DecodedText,
|
|
330
|
+
],
|
|
331
|
+
}
|
|
187
332
|
}
|
|
333
|
+
if (curr.type === 'coin') {
|
|
334
|
+
return {
|
|
335
|
+
...prev,
|
|
336
|
+
coins: [...(prev.coins || []), curr.value as DecodedAddr],
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (curr.type === 'contentHash') {
|
|
340
|
+
return {
|
|
341
|
+
...prev,
|
|
342
|
+
contentHash: curr.value as InternalGetContentHashReturnType,
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// abi
|
|
346
|
+
return { ...prev, abi: curr.value as InternalGetAbiReturnType }
|
|
188
347
|
}
|
|
189
348
|
|
|
190
|
-
const decode = async <
|
|
349
|
+
const decode = async <
|
|
350
|
+
const TTexts extends readonly string[] = readonly string[],
|
|
351
|
+
const TCoins extends readonly (string | number)[] = readonly (
|
|
352
|
+
| string
|
|
353
|
+
| number
|
|
354
|
+
)[],
|
|
355
|
+
const TContentHash extends boolean = true,
|
|
356
|
+
const TAbi extends boolean = true,
|
|
357
|
+
>(
|
|
191
358
|
client: ClientWithEns,
|
|
192
359
|
data: Hex | BaseError,
|
|
193
|
-
passthrough:
|
|
194
|
-
{
|
|
195
|
-
|
|
196
|
-
|
|
360
|
+
passthrough: EncodeReturnType['passthrough'],
|
|
361
|
+
{
|
|
362
|
+
resolver,
|
|
363
|
+
texts,
|
|
364
|
+
coins,
|
|
365
|
+
contentHash,
|
|
366
|
+
abi,
|
|
367
|
+
}: GetRecordsParameters<TTexts, TCoins, TContentHash, TAbi>,
|
|
368
|
+
): Promise<GetRecordsReturnType<TTexts, TCoins, TContentHash, TAbi>> => {
|
|
369
|
+
const { calls } = passthrough
|
|
197
370
|
let recordData: (Hex | null)[] = []
|
|
198
371
|
let resolverAddress: Address
|
|
199
372
|
|
|
373
|
+
const emptyResult = createEmptyResult({ texts, coins, contentHash, abi })
|
|
374
|
+
|
|
200
375
|
if (resolver?.address && !resolver.fallbackOnly) {
|
|
201
376
|
const result = await multicallWrapper.decode(
|
|
202
377
|
client,
|
|
203
378
|
data,
|
|
204
|
-
passthrough.filter((c) => c).map((c) => c!.call),
|
|
379
|
+
passthrough.calls.filter((c) => c).map((c) => c!.call),
|
|
205
380
|
)
|
|
206
381
|
resolverAddress = resolver.address
|
|
207
382
|
recordData = result.map((r) => r.returnData)
|
|
208
383
|
} else {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (curr.type === 'coin' && !('coin' in prev)) {
|
|
224
|
-
return { ...prev, coins: [] }
|
|
225
|
-
}
|
|
226
|
-
if (curr.type === 'text' && !('texts' in prev)) {
|
|
227
|
-
return { ...prev, texts: [] }
|
|
228
|
-
}
|
|
229
|
-
if (curr.type === 'contentHash' && !('contentHash' in prev)) {
|
|
230
|
-
return { ...prev, contentHash: null }
|
|
231
|
-
}
|
|
232
|
-
// abi
|
|
233
|
-
return { ...prev, abi: null }
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
resolverAddress: EMPTY_ADDRESS,
|
|
237
|
-
} as unknown as GetRecordsReturnType<TParams>,
|
|
238
|
-
)
|
|
239
|
-
}
|
|
240
|
-
throw getContractError(data, {
|
|
241
|
-
abi: universalResolverResolveArraySnippet,
|
|
242
|
-
functionName: 'resolve',
|
|
243
|
-
args: [
|
|
244
|
-
toHex(packetToBytes(name)),
|
|
245
|
-
calls.filter((c) => c).map((c) => c!.call.data),
|
|
246
|
-
],
|
|
247
|
-
address: getChainContractAddress({
|
|
248
|
-
client,
|
|
249
|
-
contract: 'ensUniversalResolver',
|
|
250
|
-
}),
|
|
251
|
-
}) as BaseError
|
|
252
|
-
}
|
|
384
|
+
const isSafe = checkSafeUniversalResolverData(data, {
|
|
385
|
+
strict: false,
|
|
386
|
+
abi: universalResolverResolveArraySnippet,
|
|
387
|
+
args: passthrough.args,
|
|
388
|
+
functionName: 'resolve',
|
|
389
|
+
address: passthrough.address,
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
if (!isSafe)
|
|
393
|
+
return {
|
|
394
|
+
...emptyResult,
|
|
395
|
+
resolverAddress: EMPTY_ADDRESS,
|
|
396
|
+
} as GetRecordsReturnType<TTexts, TCoins, TContentHash, TAbi>
|
|
397
|
+
|
|
253
398
|
const result = decodeFunctionResult({
|
|
254
399
|
abi: universalResolverResolveArraySnippet,
|
|
255
400
|
functionName: 'resolve',
|
|
@@ -269,83 +414,17 @@ const decode = async <TParams extends GetRecordsParameters>(
|
|
|
269
414
|
const filteredRecordData = recordData.filter((x) => x) as Hex[]
|
|
270
415
|
|
|
271
416
|
const decodedRecords = await Promise.all(
|
|
272
|
-
filteredRecordData.map(async (item, i) =>
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (type === 'contentHash') {
|
|
276
|
-
const decodedFromAbi = decodeAbiParameters(
|
|
277
|
-
[{ type: 'bytes' }] as const,
|
|
278
|
-
item,
|
|
279
|
-
)[0]
|
|
280
|
-
if (decodedFromAbi === '0x' || hexToBigInt(decodedFromAbi) === 0n) {
|
|
281
|
-
return { ...baseItem, value: null }
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
if (type === 'text') {
|
|
285
|
-
const decodedFromAbi = await _getText.decode(client, item)
|
|
286
|
-
return { ...baseItem, value: decodedFromAbi }
|
|
287
|
-
}
|
|
288
|
-
if (type === 'coin') {
|
|
289
|
-
const decodedFromAbi = await _getAddr.decode(client, item, {
|
|
290
|
-
name,
|
|
291
|
-
coin: key,
|
|
292
|
-
})
|
|
293
|
-
return { ...baseItem, value: decodedFromAbi }
|
|
294
|
-
}
|
|
295
|
-
if (type === 'contentHash') {
|
|
296
|
-
const decodedFromAbi = await _getContentHash.decode(client, item)
|
|
297
|
-
return { ...baseItem, value: decodedFromAbi }
|
|
298
|
-
}
|
|
299
|
-
// abi
|
|
300
|
-
const decodedFromAbi = await _getAbi.decode(client, item)
|
|
301
|
-
return { ...baseItem, value: decodedFromAbi }
|
|
302
|
-
}),
|
|
417
|
+
filteredRecordData.map(async (item, i) =>
|
|
418
|
+
decodeRecord(client, { item, call: filteredCalls[i] }),
|
|
419
|
+
),
|
|
303
420
|
)
|
|
304
421
|
|
|
305
|
-
const records = decodedRecords.reduce(
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
return prev
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (curr.type === 'text') {
|
|
313
|
-
return {
|
|
314
|
-
...prev,
|
|
315
|
-
texts: [
|
|
316
|
-
...(prev.texts || []),
|
|
317
|
-
{ key: curr.key, value: curr.value } as DecodedText,
|
|
318
|
-
],
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
if (curr.type === 'coin') {
|
|
322
|
-
return {
|
|
323
|
-
...prev,
|
|
324
|
-
coins: [...(prev.coins || []), curr.value as DecodedAddr],
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
if (curr.type === 'contentHash') {
|
|
328
|
-
return {
|
|
329
|
-
...prev,
|
|
330
|
-
contentHash: curr.value as InternalGetContentHashReturnType,
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
// abi
|
|
334
|
-
return { ...prev, abi: curr.value as InternalGetAbiReturnType }
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
resolverAddress,
|
|
338
|
-
...('texts' in recordsParams ? { texts: [] } : {}),
|
|
339
|
-
...('coins' in recordsParams ? { coins: [] } : {}),
|
|
340
|
-
...('contentHash' in recordsParams ? { contentHash: null } : {}),
|
|
341
|
-
} as GetRecordsReturnType<
|
|
342
|
-
GetRecordsParameters & {
|
|
343
|
-
records: Required<GetRecordsParameters['records']>
|
|
344
|
-
}
|
|
345
|
-
>,
|
|
346
|
-
)
|
|
422
|
+
const records = decodedRecords.reduce(createRecordResult, {
|
|
423
|
+
...emptyResult,
|
|
424
|
+
resolverAddress,
|
|
425
|
+
} as GetRecordsReturnType)
|
|
347
426
|
|
|
348
|
-
return records as GetRecordsReturnType<
|
|
427
|
+
return records as GetRecordsReturnType<TTexts, TCoins, TContentHash, TAbi>
|
|
349
428
|
}
|
|
350
429
|
|
|
351
430
|
type EncoderFunction = typeof encode
|
|
@@ -354,12 +433,20 @@ type DecoderFunction = typeof decode<any>
|
|
|
354
433
|
type BatchableFunctionObject = {
|
|
355
434
|
encode: EncoderFunction
|
|
356
435
|
decode: DecoderFunction
|
|
357
|
-
batch: <
|
|
358
|
-
|
|
436
|
+
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,
|
|
444
|
+
>(
|
|
445
|
+
args: GetRecordsParameters<TTexts, TCoins, TContentHash, TAbi>,
|
|
359
446
|
) => {
|
|
360
|
-
args: [
|
|
447
|
+
args: [GetRecordsParameters<TTexts, TCoins, TContentHash, TAbi>]
|
|
361
448
|
encode: EncoderFunction
|
|
362
|
-
decode: typeof decode<
|
|
449
|
+
decode: typeof decode<TTexts, TCoins, TContentHash, TAbi>
|
|
363
450
|
}
|
|
364
451
|
}
|
|
365
452
|
|
|
@@ -390,11 +477,25 @@ type BatchableFunctionObject = {
|
|
|
390
477
|
* // { texts: [{ key: 'com.twitter', value: 'ensdomains' }, { key: 'com.github', value: 'ensdomains' }], coins: [{ id: 60, name: 'ETH', value: '0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7' }], contentHash: { protocolType: 'ipns', decoded: 'k51qzi5uqu5djdczd6zw0grmo23j2vkj9uzvujencg15s5rlkq0ss4ivll8wqw' } }
|
|
391
478
|
*/
|
|
392
479
|
const getRecords = generateFunction({ encode, decode }) as (<
|
|
393
|
-
|
|
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,
|
|
394
487
|
>(
|
|
395
488
|
client: ClientWithEns,
|
|
396
|
-
{
|
|
397
|
-
|
|
489
|
+
{
|
|
490
|
+
name,
|
|
491
|
+
texts,
|
|
492
|
+
coins,
|
|
493
|
+
contentHash,
|
|
494
|
+
abi,
|
|
495
|
+
resolver,
|
|
496
|
+
gatewayUrls,
|
|
497
|
+
}: GetRecordsParameters<TTexts, TCoins, TContentHash, TAbi>,
|
|
498
|
+
) => Promise<GetRecordsReturnType<TTexts, TCoins, TContentHash, TAbi>>) &
|
|
398
499
|
BatchableFunctionObject
|
|
399
500
|
|
|
400
501
|
export default getRecords
|