@ensdomains/ensjs 3.0.0-alpha.26 → 3.0.0-alpha.28
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/README.md +1 -1
- package/dist/cjs/contracts/getContractAddress.js +1 -1
- package/dist/cjs/functions/batchWrappers.js +41 -8
- package/dist/cjs/functions/getName.js +2 -2
- package/dist/cjs/functions/getNames.js +89 -1
- package/dist/cjs/functions/getOwner.js +4 -4
- package/dist/cjs/functions/getProfile.js +117 -87
- package/dist/cjs/functions/getWrapperData.js +1 -11
- package/dist/cjs/generated/factories/NameWrapper__factory.js +13 -0
- package/dist/cjs/generated/factories/UniversalResolver__factory.js +277 -0
- package/dist/cjs/utils/ccip.js +128 -0
- package/dist/cjs/utils/fuses.js +17 -0
- package/dist/cjs/utils/singleCall.js +1 -1
- package/dist/esm/contracts/getContractAddress.mjs +1 -1
- package/dist/esm/functions/batchWrappers.mjs +35 -8
- package/dist/esm/functions/getName.mjs +2 -2
- package/dist/esm/functions/getNames.mjs +89 -1
- package/dist/esm/functions/getOwner.mjs +4 -4
- package/dist/esm/functions/getProfile.mjs +117 -87
- package/dist/esm/functions/getWrapperData.mjs +2 -12
- package/dist/esm/generated/factories/NameWrapper__factory.mjs +13 -0
- package/dist/esm/generated/factories/UniversalResolver__factory.mjs +277 -0
- package/dist/esm/utils/ccip.mjs +114 -0
- package/dist/esm/utils/fuses.mjs +17 -0
- package/dist/esm/utils/singleCall.mjs +1 -1
- package/dist/types/functions/batchWrappers.d.ts +58 -1
- package/dist/types/functions/getNames.d.ts +9 -3
- package/dist/types/functions/getProfile.d.ts +6 -0
- package/dist/types/functions/getWrapperData.d.ts +1 -2
- package/dist/types/generated/NameWrapper.d.ts +9 -1
- package/dist/types/generated/UniversalResolver.d.ts +123 -21
- package/dist/types/index.d.ts +68 -3
- package/dist/types/utils/ccip.d.ts +3 -0
- package/dist/types/utils/fuses.d.ts +2 -0
- package/package.json +3 -3
- package/src/contracts/getContractAddress.ts +1 -1
- package/src/functions/batchWrappers.ts +40 -9
- package/src/functions/getName.ts +2 -2
- package/src/functions/getNames.test.ts +27 -0
- package/src/functions/getNames.ts +101 -3
- package/src/functions/getOwner.ts +4 -2
- package/src/functions/getProfile-ccip.test.ts +29 -0
- package/src/functions/getProfile.test.ts +1 -1
- package/src/functions/getProfile.ts +160 -100
- package/src/functions/getWrapperData.ts +3 -15
- package/src/functions/setName.test.ts +6 -2
- package/src/functions/setRecord.test.ts +3 -3
- package/src/functions/setRecords.test.ts +2 -2
- package/src/generated/NameWrapper.ts +14 -0
- package/src/generated/UniversalResolver.ts +382 -19
- package/src/generated/factories/NameWrapper__factory.ts +13 -0
- package/src/generated/factories/UniversalResolver__factory.ts +277 -0
- package/src/index.ts +1 -1
- package/src/utils/ccip.ts +148 -0
- package/src/utils/fuses.ts +21 -0
- package/src/utils/singleCall.ts +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ENSArgs } from '..'
|
|
2
2
|
import { truncateFormat } from '../utils/format'
|
|
3
|
+
import { CurrentFuses, decodeFuses } from '../utils/fuses'
|
|
3
4
|
import { decryptName } from '../utils/labels'
|
|
4
5
|
|
|
5
6
|
export type Name = {
|
|
@@ -15,12 +16,13 @@ export type Name = {
|
|
|
15
16
|
createdAt?: Date
|
|
16
17
|
registrationDate?: Date
|
|
17
18
|
expiryDate?: Date
|
|
18
|
-
|
|
19
|
+
fuses?: CurrentFuses
|
|
20
|
+
type: 'domain' | 'registration' | 'wrappedDomain'
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
type BaseParams = {
|
|
22
24
|
address: string
|
|
23
|
-
type: 'registrant' | 'owner' | 'all'
|
|
25
|
+
type: 'registrant' | 'owner' | 'wrappedOwner' | 'all'
|
|
24
26
|
page?: number
|
|
25
27
|
pageSize?: number
|
|
26
28
|
orderDirection?: 'asc' | 'desc'
|
|
@@ -36,6 +38,11 @@ type OwnerParams = {
|
|
|
36
38
|
orderBy?: 'createdAt' | 'labelName'
|
|
37
39
|
}
|
|
38
40
|
|
|
41
|
+
type WrappedOwnerParams = {
|
|
42
|
+
type: 'wrappedOwner'
|
|
43
|
+
orderBy?: 'expiryDate' | 'labelName'
|
|
44
|
+
}
|
|
45
|
+
|
|
39
46
|
type AllParams = {
|
|
40
47
|
type: 'all'
|
|
41
48
|
orderBy?: 'labelName' | 'creationDate'
|
|
@@ -43,7 +50,8 @@ type AllParams = {
|
|
|
43
50
|
pageSize?: never
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
type Params = BaseParams &
|
|
53
|
+
type Params = BaseParams &
|
|
54
|
+
(RegistrantParams | OwnerParams | WrappedOwnerParams | AllParams)
|
|
47
55
|
|
|
48
56
|
const mapDomain = (domain: any) => {
|
|
49
57
|
const decrypted = decryptName(domain.name)
|
|
@@ -56,6 +64,16 @@ const mapDomain = (domain: any) => {
|
|
|
56
64
|
}
|
|
57
65
|
}
|
|
58
66
|
|
|
67
|
+
const mapWrappedDomain = (wrappedDomain: any) => {
|
|
68
|
+
const domain = mapDomain(wrappedDomain.domain)
|
|
69
|
+
return {
|
|
70
|
+
expiryDate: new Date(parseInt(wrappedDomain.expiryDate) * 1000),
|
|
71
|
+
fuses: decodeFuses(wrappedDomain.fuses),
|
|
72
|
+
...domain,
|
|
73
|
+
type: 'wrappedDomain',
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
59
77
|
const mapRegistration = (registration: any) => {
|
|
60
78
|
const decrypted = decryptName(registration.domain.name)
|
|
61
79
|
return {
|
|
@@ -116,6 +134,17 @@ const getNames = async (
|
|
|
116
134
|
${domainQueryData}
|
|
117
135
|
createdAt
|
|
118
136
|
}
|
|
137
|
+
wrappedDomains(first: 1000) {
|
|
138
|
+
expiryDate
|
|
139
|
+
fuses
|
|
140
|
+
domain {
|
|
141
|
+
${domainQueryData}
|
|
142
|
+
registration {
|
|
143
|
+
registrationDate
|
|
144
|
+
expiryDate
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
119
148
|
}
|
|
120
149
|
}
|
|
121
150
|
`
|
|
@@ -167,6 +196,71 @@ const getNames = async (
|
|
|
167
196
|
}
|
|
168
197
|
`
|
|
169
198
|
|
|
199
|
+
queryVars = {
|
|
200
|
+
id: address,
|
|
201
|
+
first: pageSize,
|
|
202
|
+
skip: (page || 0) * pageSize,
|
|
203
|
+
orderBy,
|
|
204
|
+
orderDirection,
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
} else if (type === 'wrappedOwner') {
|
|
208
|
+
if (typeof page !== 'number') {
|
|
209
|
+
finalQuery = gqlInstance.gql`
|
|
210
|
+
query getNames(
|
|
211
|
+
$id: ID!
|
|
212
|
+
$orderBy: WrappedDomain_orderBy
|
|
213
|
+
$orderDirection: OrderDirection
|
|
214
|
+
$expiryDate: Int
|
|
215
|
+
) {
|
|
216
|
+
account(id: $id) {
|
|
217
|
+
wrappedDomains(
|
|
218
|
+
orderBy: $orderBy
|
|
219
|
+
orderDirection: $orderDirection
|
|
220
|
+
where: { expiryDate_gt: $expiryDate }
|
|
221
|
+
) {
|
|
222
|
+
expiryDate
|
|
223
|
+
fuses
|
|
224
|
+
domain {
|
|
225
|
+
${domainQueryData}
|
|
226
|
+
createdAt
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
`
|
|
232
|
+
|
|
233
|
+
queryVars = {
|
|
234
|
+
id: address,
|
|
235
|
+
expiryDate: Math.floor(Date.now() / 1000) - 90 * 24 * 60 * 60,
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
finalQuery = gqlInstance.gql`
|
|
239
|
+
query getNames(
|
|
240
|
+
$id: ID!
|
|
241
|
+
$first: Int
|
|
242
|
+
$skip: Int
|
|
243
|
+
$orderBy: WrappedDomain_orderBy
|
|
244
|
+
$orderDirection: OrderDirection
|
|
245
|
+
) {
|
|
246
|
+
account(id: $id) {
|
|
247
|
+
wrappedDomains(
|
|
248
|
+
first: $first
|
|
249
|
+
skip: $skip
|
|
250
|
+
orderBy: $orderBy
|
|
251
|
+
orderDirection: $orderDirection
|
|
252
|
+
) {
|
|
253
|
+
expiryDate
|
|
254
|
+
fuses
|
|
255
|
+
domain {
|
|
256
|
+
${domainQueryData}
|
|
257
|
+
createdAt
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
`
|
|
263
|
+
|
|
170
264
|
queryVars = {
|
|
171
265
|
id: address,
|
|
172
266
|
first: pageSize,
|
|
@@ -248,6 +342,7 @@ const getNames = async (
|
|
|
248
342
|
return [
|
|
249
343
|
...account.domains.map(mapDomain),
|
|
250
344
|
...account.registrations.map(mapRegistration),
|
|
345
|
+
...account.wrappedDomains.map(mapWrappedDomain),
|
|
251
346
|
].sort((a, b) => {
|
|
252
347
|
if (orderDirection === 'desc') {
|
|
253
348
|
if (orderBy === 'labelName') {
|
|
@@ -264,6 +359,9 @@ const getNames = async (
|
|
|
264
359
|
if (type === 'owner') {
|
|
265
360
|
return account.domains.map(mapDomain) as Name[]
|
|
266
361
|
}
|
|
362
|
+
if (type === 'wrappedOwner') {
|
|
363
|
+
return account.wrappedDomains.map(mapWrappedDomain) as Name[]
|
|
364
|
+
}
|
|
267
365
|
return account.registrations.map(mapRegistration) as Name[]
|
|
268
366
|
}
|
|
269
367
|
|
|
@@ -100,7 +100,7 @@ const decode = async (
|
|
|
100
100
|
name: string,
|
|
101
101
|
contract?: 'nameWrapper' | 'registry' | 'registrar',
|
|
102
102
|
): Promise<Owner | undefined> => {
|
|
103
|
-
if (data
|
|
103
|
+
if (!data) return
|
|
104
104
|
const labels = name.split('.')
|
|
105
105
|
if (contract || labels.length === 1) {
|
|
106
106
|
const singleOwner = singleContractOwnerDecode(data)
|
|
@@ -119,7 +119,7 @@ const decode = async (
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
const result = await multicallWrapper.decode(data)
|
|
122
|
-
if (result
|
|
122
|
+
if (!result) return
|
|
123
123
|
const nameWrapper = await contracts?.getNameWrapper()!
|
|
124
124
|
|
|
125
125
|
const decodedData = [result[0][1], result[1][1], result[2]?.[1]].map(
|
|
@@ -163,6 +163,7 @@ const decode = async (
|
|
|
163
163
|
// this means that the subname is wrapped
|
|
164
164
|
if (
|
|
165
165
|
registryOwner === nameWrapper.address &&
|
|
166
|
+
nameWrapperOwner &&
|
|
166
167
|
ethers.utils.hexStripZeros(nameWrapperOwner) !== '0x'
|
|
167
168
|
) {
|
|
168
169
|
return {
|
|
@@ -186,6 +187,7 @@ const decode = async (
|
|
|
186
187
|
// and for wrapped names, owner and registrant are the same thing
|
|
187
188
|
if (
|
|
188
189
|
registryOwner === nameWrapper.address &&
|
|
190
|
+
nameWrapperOwner &&
|
|
189
191
|
ethers.utils.hexStripZeros(nameWrapperOwner) !== '0x'
|
|
190
192
|
) {
|
|
191
193
|
return {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import dotenv from 'dotenv'
|
|
2
|
+
import { ENS } from '..'
|
|
3
|
+
import setup from '../tests/setup'
|
|
4
|
+
|
|
5
|
+
dotenv.config()
|
|
6
|
+
|
|
7
|
+
let ensInstance: ENS
|
|
8
|
+
|
|
9
|
+
beforeAll(async () => {
|
|
10
|
+
;({ ensInstance } = await setup(true))
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
jest.setTimeout(20000)
|
|
14
|
+
|
|
15
|
+
describe('getProfile', () => {
|
|
16
|
+
it('should return a profile from a ccip-read name', async () => {
|
|
17
|
+
const result = await ensInstance.getProfile('1.offchainexample.eth', {
|
|
18
|
+
fallback: {
|
|
19
|
+
texts: ['email', 'description'],
|
|
20
|
+
contentHash: true,
|
|
21
|
+
coinTypes: ['0', '60'],
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
expect(result).toBeTruthy()
|
|
25
|
+
if (result) {
|
|
26
|
+
expect(result.address).toBe('0x41563129cDbbD0c5D3e1c86cf9563926b243834d')
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { formatsByName } from '@ensdomains/address-encoder'
|
|
2
2
|
import { ethers } from 'ethers'
|
|
3
|
+
import { hexStripZeros } from 'ethers/lib/utils'
|
|
3
4
|
import { ENSArgs } from '..'
|
|
4
5
|
import { decodeContenthash, DecodedContentHash } from '../utils/contentHash'
|
|
5
6
|
import { hexEncodeName } from '../utils/hexEncodedName'
|
|
@@ -18,6 +19,12 @@ type ProfileResponse = {
|
|
|
18
19
|
coinTypes?: string[]
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
type FallbackRecords = {
|
|
23
|
+
contentHash?: boolean
|
|
24
|
+
texts?: string[]
|
|
25
|
+
coinTypes?: string[]
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
type DataItem = {
|
|
22
29
|
key: string | number
|
|
23
30
|
type: 'addr' | 'text' | 'contentHash'
|
|
@@ -41,19 +48,25 @@ type ResolvedProfile = {
|
|
|
41
48
|
reverseResolverAddress?: string
|
|
42
49
|
}
|
|
43
50
|
|
|
51
|
+
type CallObj = {
|
|
52
|
+
key: string
|
|
53
|
+
data: {
|
|
54
|
+
to: string
|
|
55
|
+
data: string
|
|
56
|
+
}
|
|
57
|
+
type: 'addr' | 'text' | 'contentHash'
|
|
58
|
+
}
|
|
59
|
+
|
|
44
60
|
const makeMulticallData = async (
|
|
45
61
|
{
|
|
46
62
|
_getAddr,
|
|
47
63
|
_getContentHash,
|
|
48
64
|
_getText,
|
|
49
|
-
|
|
50
|
-
}: ENSArgs<
|
|
51
|
-
'_getText' | '_getAddr' | '_getContentHash' | 'resolverMulticallWrapper'
|
|
52
|
-
>,
|
|
65
|
+
}: ENSArgs<'_getText' | '_getAddr' | '_getContentHash'>,
|
|
53
66
|
name: string,
|
|
54
67
|
options: InternalProfileOptions,
|
|
55
68
|
) => {
|
|
56
|
-
let calls:
|
|
69
|
+
let calls: (CallObj | null)[] = []
|
|
57
70
|
if (options.texts)
|
|
58
71
|
calls = [
|
|
59
72
|
...calls,
|
|
@@ -61,7 +74,7 @@ const makeMulticallData = async (
|
|
|
61
74
|
options.texts.map(async (x) => ({
|
|
62
75
|
key: x,
|
|
63
76
|
data: await _getText.raw(name, x),
|
|
64
|
-
type: 'text',
|
|
77
|
+
type: 'text' as const,
|
|
65
78
|
})),
|
|
66
79
|
)),
|
|
67
80
|
]
|
|
@@ -73,7 +86,7 @@ const makeMulticallData = async (
|
|
|
73
86
|
options.coinTypes.map(async (x) => ({
|
|
74
87
|
key: x,
|
|
75
88
|
data: await _getAddr.raw(name, x, true),
|
|
76
|
-
type: 'addr',
|
|
89
|
+
type: 'addr' as const,
|
|
77
90
|
})),
|
|
78
91
|
)),
|
|
79
92
|
]
|
|
@@ -82,21 +95,19 @@ const makeMulticallData = async (
|
|
|
82
95
|
calls.push({
|
|
83
96
|
key: 'contentHash',
|
|
84
97
|
data: await _getContentHash.raw(name),
|
|
85
|
-
type: '
|
|
98
|
+
type: 'contentHash' as const,
|
|
86
99
|
})
|
|
87
100
|
}
|
|
88
101
|
|
|
89
|
-
if (!calls.find((x) => x
|
|
102
|
+
if (!calls.find((x) => x!.key === '60')) {
|
|
90
103
|
calls.push({
|
|
91
104
|
key: '60',
|
|
92
105
|
data: await _getAddr.raw(name, '60', true),
|
|
93
|
-
type: 'addr',
|
|
106
|
+
type: 'addr' as const,
|
|
94
107
|
})
|
|
95
108
|
}
|
|
96
109
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return { data: prRawData.data, calls }
|
|
110
|
+
return { data: calls.map((x) => x!.data.data), calls }
|
|
100
111
|
}
|
|
101
112
|
|
|
102
113
|
const fetchWithoutResolverMulticall = async (
|
|
@@ -116,9 +127,11 @@ const fetchWithoutResolverMulticall = async (
|
|
|
116
127
|
data: call.data.data,
|
|
117
128
|
}))
|
|
118
129
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
)
|
|
130
|
+
const results = await multicallWrapper(callsWithResolver)
|
|
131
|
+
|
|
132
|
+
if (!results || !results.length) return []
|
|
133
|
+
|
|
134
|
+
return results.map((x: [boolean, string]) => x[1])
|
|
122
135
|
}
|
|
123
136
|
|
|
124
137
|
const formatRecords = async (
|
|
@@ -139,7 +152,7 @@ const formatRecords = async (
|
|
|
139
152
|
key: calls[i].key,
|
|
140
153
|
type: calls[i].type,
|
|
141
154
|
}
|
|
142
|
-
if (itemRet.type === '
|
|
155
|
+
if (itemRet.type === 'contentHash') {
|
|
143
156
|
;[decodedFromAbi] = ethers.utils.defaultAbiCoder.decode(
|
|
144
157
|
['bytes'],
|
|
145
158
|
item,
|
|
@@ -171,7 +184,7 @@ const formatRecords = async (
|
|
|
171
184
|
} catch {
|
|
172
185
|
return
|
|
173
186
|
}
|
|
174
|
-
case '
|
|
187
|
+
case 'contentHash':
|
|
175
188
|
try {
|
|
176
189
|
itemRet = {
|
|
177
190
|
...itemRet,
|
|
@@ -217,7 +230,7 @@ const formatRecords = async (
|
|
|
217
230
|
}
|
|
218
231
|
} else if (options.contentHash) {
|
|
219
232
|
const foundRecord = returnedRecords.find(
|
|
220
|
-
(item: any) => item.type === '
|
|
233
|
+
(item: any) => item.type === 'contentHash',
|
|
221
234
|
)
|
|
222
235
|
returnedResponse.contentHash = foundRecord ? foundRecord.value : null
|
|
223
236
|
}
|
|
@@ -240,7 +253,6 @@ const getDataForName = async (
|
|
|
240
253
|
_getAddr,
|
|
241
254
|
_getContentHash,
|
|
242
255
|
_getText,
|
|
243
|
-
resolverMulticallWrapper,
|
|
244
256
|
multicallWrapper,
|
|
245
257
|
}: ENSArgs<
|
|
246
258
|
| 'contracts'
|
|
@@ -252,62 +264,77 @@ const getDataForName = async (
|
|
|
252
264
|
>,
|
|
253
265
|
name: string,
|
|
254
266
|
options: InternalProfileOptions,
|
|
255
|
-
fallbackResolver?: string,
|
|
256
267
|
specificResolver?: string,
|
|
257
268
|
) => {
|
|
258
|
-
const universalResolver = await contracts?.getUniversalResolver()
|
|
269
|
+
const universalResolver = await contracts?.getUniversalResolver()!
|
|
259
270
|
|
|
260
271
|
const { data, calls } = await makeMulticallData(
|
|
261
|
-
{ _getAddr, _getContentHash, _getText
|
|
272
|
+
{ _getAddr, _getContentHash, _getText },
|
|
262
273
|
name,
|
|
263
274
|
options,
|
|
264
275
|
)
|
|
265
276
|
|
|
266
|
-
let
|
|
267
|
-
let
|
|
268
|
-
|
|
269
|
-
|
|
277
|
+
let recordData: (string | null)[] | undefined
|
|
278
|
+
let resolverAddress: string | undefined = specificResolver
|
|
279
|
+
|
|
280
|
+
if (specificResolver) {
|
|
281
|
+
try {
|
|
270
282
|
const publicResolver = await contracts?.getPublicResolver(
|
|
271
283
|
undefined,
|
|
272
284
|
specificResolver,
|
|
273
285
|
)
|
|
274
|
-
|
|
275
|
-
|
|
286
|
+
recordData = await publicResolver?.callStatic.multicall(data)
|
|
287
|
+
} catch (e: any) {
|
|
288
|
+
console.error('getProfile error:', e)
|
|
289
|
+
recordData = await fetchWithoutResolverMulticall(
|
|
290
|
+
{ multicallWrapper },
|
|
291
|
+
calls as CallObj[],
|
|
292
|
+
resolverAddress!,
|
|
276
293
|
)
|
|
277
|
-
} else {
|
|
278
|
-
resolvedData = await universalResolver?.resolve(hexEncodeName(name), data)
|
|
279
294
|
}
|
|
280
|
-
} catch {
|
|
281
|
-
useFallbackResolver = true
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
let resolverAddress: string
|
|
285
|
-
let recordData: any
|
|
286
|
-
|
|
287
|
-
if (useFallbackResolver) {
|
|
288
|
-
resolverAddress = specificResolver || fallbackResolver!
|
|
289
|
-
recordData = await fetchWithoutResolverMulticall(
|
|
290
|
-
{ multicallWrapper },
|
|
291
|
-
calls,
|
|
292
|
-
resolverAddress,
|
|
293
|
-
)
|
|
294
295
|
} else {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
296
|
+
const resolvedData = await universalResolver['resolve(bytes,bytes[])'](
|
|
297
|
+
hexEncodeName(name),
|
|
298
|
+
data,
|
|
299
|
+
{
|
|
300
|
+
ccipReadEnabled: true,
|
|
301
|
+
},
|
|
302
|
+
)
|
|
303
|
+
recordData = [...resolvedData['0']]
|
|
304
|
+
resolverAddress = resolvedData['1']
|
|
305
|
+
for (let i = 0; i < recordData.length; i += 1) {
|
|
306
|
+
// error code for reverted call in batch
|
|
307
|
+
// this is expected when using offchain resolvers, so should be ignored
|
|
308
|
+
if (recordData[i]!.startsWith('0x0d1947a9')) {
|
|
309
|
+
calls[i] = null
|
|
310
|
+
recordData[i] = null
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (
|
|
315
|
+
!resolverAddress ||
|
|
316
|
+
!recordData ||
|
|
317
|
+
hexStripZeros(resolverAddress) === '0x'
|
|
318
|
+
) {
|
|
319
|
+
return {
|
|
320
|
+
address: null,
|
|
321
|
+
records: {},
|
|
322
|
+
resolverAddress: null,
|
|
300
323
|
}
|
|
301
324
|
}
|
|
302
325
|
|
|
303
|
-
const
|
|
326
|
+
const filteredCalls = calls.filter((x) => x) as CallObj[]
|
|
327
|
+
const filteredRecordData = recordData.filter((x) => x)
|
|
328
|
+
|
|
329
|
+
const matchAddress =
|
|
330
|
+
filteredRecordData[filteredCalls.findIndex((x) => x.key === '60')]
|
|
304
331
|
|
|
305
332
|
return {
|
|
306
333
|
address: matchAddress && (await _getAddr.decode(matchAddress)),
|
|
307
334
|
records: await formatRecords(
|
|
308
335
|
{ _getAddr, _getContentHash, _getText },
|
|
309
|
-
|
|
310
|
-
|
|
336
|
+
filteredRecordData,
|
|
337
|
+
filteredCalls,
|
|
311
338
|
options,
|
|
312
339
|
),
|
|
313
340
|
resolverAddress,
|
|
@@ -332,7 +359,6 @@ const graphFetch = async (
|
|
|
332
359
|
addr {
|
|
333
360
|
id
|
|
334
361
|
}
|
|
335
|
-
address
|
|
336
362
|
}
|
|
337
363
|
}
|
|
338
364
|
}
|
|
@@ -379,14 +405,7 @@ const graphFetch = async (
|
|
|
379
405
|
|
|
380
406
|
const returnedRecords: ProfileResponse = {}
|
|
381
407
|
|
|
382
|
-
if (!resolverResponse) return { isMigrated, createdAt }
|
|
383
|
-
|
|
384
|
-
if (!wantedRecords)
|
|
385
|
-
return {
|
|
386
|
-
isMigrated,
|
|
387
|
-
createdAt,
|
|
388
|
-
graphResolverAddress: resolverResponse.address || resolverAddress,
|
|
389
|
-
}
|
|
408
|
+
if (!resolverResponse || !wantedRecords) return { isMigrated, createdAt }
|
|
390
409
|
|
|
391
410
|
Object.keys(wantedRecords).forEach((key: string) => {
|
|
392
411
|
const data = wantedRecords[key as keyof ProfileOptions]
|
|
@@ -403,7 +422,6 @@ const graphFetch = async (
|
|
|
403
422
|
...returnedRecords,
|
|
404
423
|
isMigrated,
|
|
405
424
|
createdAt,
|
|
406
|
-
graphResolverAddress: resolverResponse.address || resolverAddress,
|
|
407
425
|
}
|
|
408
426
|
}
|
|
409
427
|
|
|
@@ -415,6 +433,7 @@ type ProfileOptions = {
|
|
|
415
433
|
|
|
416
434
|
type InputProfileOptions = ProfileOptions & {
|
|
417
435
|
resolverAddress?: string
|
|
436
|
+
fallback?: FallbackRecords
|
|
418
437
|
}
|
|
419
438
|
|
|
420
439
|
const getProfileFromName = async (
|
|
@@ -438,7 +457,7 @@ const getProfileFromName = async (
|
|
|
438
457
|
name: string,
|
|
439
458
|
options?: InputProfileOptions,
|
|
440
459
|
) => {
|
|
441
|
-
const { resolverAddress, ..._options } = options || {}
|
|
460
|
+
const { resolverAddress, fallback, ..._options } = options || {}
|
|
442
461
|
const optsLength = Object.keys(_options).length
|
|
443
462
|
let usingOptions: InputProfileOptions | undefined
|
|
444
463
|
if (!optsLength || _options?.texts === true || _options?.coinTypes === true) {
|
|
@@ -452,35 +471,69 @@ const getProfileFromName = async (
|
|
|
452
471
|
usingOptions,
|
|
453
472
|
resolverAddress,
|
|
454
473
|
)
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
474
|
+
let isMigrated: boolean | null = null
|
|
475
|
+
let createdAt: string | null = null
|
|
476
|
+
let result: Awaited<ReturnType<typeof getDataForName>> | null = null
|
|
477
|
+
if (!graphResult) {
|
|
478
|
+
if (!fallback) return
|
|
479
|
+
result = await getDataForName(
|
|
480
|
+
{
|
|
481
|
+
contracts,
|
|
482
|
+
_getAddr,
|
|
483
|
+
_getContentHash,
|
|
484
|
+
_getText,
|
|
485
|
+
resolverMulticallWrapper,
|
|
486
|
+
multicallWrapper,
|
|
487
|
+
},
|
|
488
|
+
name,
|
|
489
|
+
fallback,
|
|
490
|
+
undefined,
|
|
491
|
+
)
|
|
492
|
+
} else {
|
|
493
|
+
const {
|
|
494
|
+
isMigrated: _isMigrated,
|
|
495
|
+
createdAt: _createdAt,
|
|
496
|
+
...wantedRecords
|
|
497
|
+
}: {
|
|
498
|
+
isMigrated: boolean
|
|
499
|
+
createdAt: string
|
|
500
|
+
} & InternalProfileOptions = graphResult
|
|
501
|
+
isMigrated = _isMigrated
|
|
502
|
+
createdAt = _createdAt
|
|
503
|
+
let recordsWithFallback = usingOptions
|
|
504
|
+
? wantedRecords
|
|
505
|
+
: (_options as InternalProfileOptions)
|
|
506
|
+
if (
|
|
507
|
+
(Object.keys(recordsWithFallback).length === 0 ||
|
|
508
|
+
(!recordsWithFallback.coinTypes &&
|
|
509
|
+
!recordsWithFallback.texts &&
|
|
510
|
+
Object.keys(recordsWithFallback.contentHash || {}).length === 0)) &&
|
|
511
|
+
fallback
|
|
512
|
+
) {
|
|
513
|
+
recordsWithFallback = fallback
|
|
514
|
+
}
|
|
515
|
+
result = await getDataForName(
|
|
516
|
+
{
|
|
517
|
+
contracts,
|
|
518
|
+
_getAddr,
|
|
519
|
+
_getContentHash,
|
|
520
|
+
_getText,
|
|
521
|
+
resolverMulticallWrapper,
|
|
522
|
+
multicallWrapper,
|
|
523
|
+
},
|
|
524
|
+
name,
|
|
525
|
+
recordsWithFallback,
|
|
526
|
+
options?.resolverAddress!,
|
|
527
|
+
)
|
|
528
|
+
}
|
|
529
|
+
if (!result?.resolverAddress)
|
|
530
|
+
return {
|
|
531
|
+
isMigrated,
|
|
532
|
+
createdAt,
|
|
533
|
+
message: !result
|
|
534
|
+
? "Records fetch didn't complete"
|
|
535
|
+
: "Name doesn't have a resolver",
|
|
536
|
+
}
|
|
484
537
|
return { ...result, isMigrated, createdAt, message: undefined }
|
|
485
538
|
}
|
|
486
539
|
|
|
@@ -537,6 +590,13 @@ const getProfileFromAddress = async (
|
|
|
537
590
|
}
|
|
538
591
|
}
|
|
539
592
|
|
|
593
|
+
const mapCoinTypes = (coin: string) => {
|
|
594
|
+
if (!Number.isNaN(parseInt(coin))) {
|
|
595
|
+
return coin
|
|
596
|
+
}
|
|
597
|
+
return `${formatsByName[coin.toUpperCase()].coinType}`
|
|
598
|
+
}
|
|
599
|
+
|
|
540
600
|
export default async function (
|
|
541
601
|
{
|
|
542
602
|
contracts,
|
|
@@ -560,13 +620,13 @@ export default async function (
|
|
|
560
620
|
nameOrAddress: string,
|
|
561
621
|
options?: InputProfileOptions,
|
|
562
622
|
): Promise<ResolvedProfile | undefined> {
|
|
563
|
-
if (options
|
|
564
|
-
options.coinTypes
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
623
|
+
if (options) {
|
|
624
|
+
if (options.coinTypes && typeof options.coinTypes !== 'boolean') {
|
|
625
|
+
options.coinTypes = options.coinTypes.map(mapCoinTypes)
|
|
626
|
+
}
|
|
627
|
+
if (options.fallback && options.fallback.coinTypes) {
|
|
628
|
+
options.fallback.coinTypes = options.fallback.coinTypes.map(mapCoinTypes)
|
|
629
|
+
}
|
|
570
630
|
}
|
|
571
631
|
|
|
572
632
|
const inputType = parseInputType(nameOrAddress)
|