@ensdomains/ensjs 3.0.0-alpha.40 → 3.0.0-alpha.41
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/functions/getSpecificRecord.js +83 -0
- package/dist/cjs/index.js +10 -0
- package/dist/cjs/utils/recordHelpers.js +54 -0
- package/dist/esm/functions/getSpecificRecord.mjs +78 -1
- package/dist/esm/index.mjs +10 -0
- package/dist/esm/utils/recordHelpers.mjs +48 -0
- package/dist/types/functions/burnFuses.d.ts +1 -1
- package/dist/types/functions/commitName.d.ts +6 -6
- package/dist/types/functions/createSubname.d.ts +1 -1
- package/dist/types/functions/deleteSubname.d.ts +1 -1
- package/dist/types/functions/getSpecificRecord.d.ts +22 -0
- package/dist/types/functions/importDNSSECName.d.ts +1 -1
- package/dist/types/functions/registerName.d.ts +1 -1
- package/dist/types/functions/renewNames.d.ts +2 -2
- package/dist/types/functions/setName.d.ts +1 -1
- package/dist/types/functions/setRecord.d.ts +5 -1
- package/dist/types/functions/setRecords.d.ts +1 -1
- package/dist/types/functions/setResolver.d.ts +1 -1
- package/dist/types/functions/transferController.d.ts +1 -1
- package/dist/types/functions/transferName.d.ts +1 -1
- package/dist/types/functions/transferSubname.d.ts +1 -1
- package/dist/types/functions/types.d.ts +3 -1
- package/dist/types/functions/unwrapName.d.ts +1 -1
- package/dist/types/functions/wrapName.d.ts +1 -1
- package/dist/types/index.d.ts +25 -3
- package/dist/types/utils/recordHelpers.d.ts +14 -2
- package/dist/types/utils/writeTx.d.ts +5 -5
- package/package.json +4 -1
- package/src/@types/pako.d.ts +188 -0
- package/src/contracts/bulkRenewal.ts +1 -1
- package/src/functions/getSpecificRecord.test.ts +162 -0
- package/src/functions/getSpecificRecord.ts +95 -1
- package/src/functions/setRecord.test.ts +147 -1
- package/src/functions/setRecord.ts +6 -1
- package/src/functions/types.ts +4 -0
- package/src/index.ts +12 -0
- package/src/utils/recordHelpers.ts +63 -1
|
@@ -1,17 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { BigNumberish } from 'ethers';
|
|
1
3
|
import type { PublicResolver } from '../generated';
|
|
2
4
|
declare type RecordItem = {
|
|
3
5
|
key: string;
|
|
4
6
|
value: string;
|
|
5
7
|
};
|
|
8
|
+
declare type ABIEncodeAs = 'json' | 'zlib' | 'cbor' | 'uri';
|
|
9
|
+
declare type ABIItem = {
|
|
10
|
+
contentType?: BigNumberish;
|
|
11
|
+
data: object | string;
|
|
12
|
+
};
|
|
6
13
|
export declare type RecordOptions = {
|
|
7
14
|
clearRecords?: boolean;
|
|
8
15
|
contentHash?: string;
|
|
9
16
|
texts?: RecordItem[];
|
|
10
17
|
coinTypes?: RecordItem[];
|
|
18
|
+
abi?: ABIItem;
|
|
11
19
|
};
|
|
12
20
|
export declare const generateSetAddr: (namehash: string, coinType: string, address: string, resolver: PublicResolver) => string;
|
|
13
|
-
export declare
|
|
14
|
-
|
|
21
|
+
export declare const generateABIInput: (encodeAs: ABIEncodeAs, data: object | string) => Promise<{
|
|
22
|
+
contentType: number;
|
|
23
|
+
data: string | Uint8Array | Buffer;
|
|
24
|
+
}>;
|
|
25
|
+
export declare type RecordTypes = 'contentHash' | 'text' | 'addr' | 'abi';
|
|
26
|
+
export declare type RecordInput<T extends RecordTypes> = T extends 'contentHash' ? string : T extends 'abi' ? ABIItem : RecordItem;
|
|
15
27
|
export declare function generateSingleRecordCall<T extends RecordTypes>(namehash: string, resolver: PublicResolver, type: T): (record: RecordInput<T>) => string;
|
|
16
28
|
export declare const generateRecordCallArray: (namehash: string, records: RecordOptions, resolver: PublicResolver) => string[];
|
|
17
29
|
export {};
|
|
@@ -5,15 +5,15 @@ declare const _default: (signer: JsonRpcSigner, populate: boolean) => ({ customD
|
|
|
5
5
|
to?: string | undefined;
|
|
6
6
|
from?: string | undefined;
|
|
7
7
|
nonce?: number | undefined;
|
|
8
|
-
gasLimit?: import("
|
|
9
|
-
gasPrice?: import("
|
|
8
|
+
gasLimit?: import("ethers").BigNumber | undefined;
|
|
9
|
+
gasPrice?: import("ethers").BigNumber | undefined;
|
|
10
10
|
data?: string | undefined;
|
|
11
|
-
value?: import("
|
|
11
|
+
value?: import("ethers").BigNumber | undefined;
|
|
12
12
|
chainId?: number | undefined;
|
|
13
13
|
type?: number | undefined;
|
|
14
14
|
accessList?: import("@ethersproject/transactions").AccessList | undefined;
|
|
15
|
-
maxFeePerGas?: import("
|
|
16
|
-
maxPriorityFeePerGas?: import("
|
|
15
|
+
maxFeePerGas?: import("ethers").BigNumber | undefined;
|
|
16
|
+
maxPriorityFeePerGas?: import("ethers").BigNumber | undefined;
|
|
17
17
|
ccipReadEnabled?: boolean | undefined;
|
|
18
18
|
} | Promise<import("@ethersproject/abstract-provider").TransactionResponse | (import("@ethersproject/abstract-provider").TransactionResponse & {
|
|
19
19
|
customData: CustomData;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ensdomains/ensjs",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.41",
|
|
4
4
|
"description": "ENS javascript library for contract interaction",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.mjs",
|
|
@@ -59,10 +59,12 @@
|
|
|
59
59
|
"@ensdomains/content-hash": "^2.5.7",
|
|
60
60
|
"@ensdomains/dnsprovejs": "^0.4.1",
|
|
61
61
|
"@ensdomains/dnssecoraclejs": "^0.2.7",
|
|
62
|
+
"cbor": "^8.1.0",
|
|
62
63
|
"dns-packet": "^5.3.1",
|
|
63
64
|
"graphql": "^16.3.0",
|
|
64
65
|
"graphql-request": "next",
|
|
65
66
|
"idna-uts46-hx": "3.4.0",
|
|
67
|
+
"pako": "^2.1.0",
|
|
66
68
|
"traverse": "^0.6.6"
|
|
67
69
|
},
|
|
68
70
|
"devDependencies": {
|
|
@@ -91,6 +93,7 @@
|
|
|
91
93
|
"@typechain/ethers-v5": "^10.1.0",
|
|
92
94
|
"@types/bn.js": "^5.1.0",
|
|
93
95
|
"@types/jest": "^27.4.1",
|
|
96
|
+
"@types/pako": "^2.0.0",
|
|
94
97
|
"@types/traverse": "^0.6.32",
|
|
95
98
|
"dotenv": "^16.0.0",
|
|
96
99
|
"esbuild": "^0.15.6",
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/* eslint-disable max-classes-per-file */
|
|
2
|
+
// Type definitions for pako 2.0
|
|
3
|
+
// Project: https://github.com/nodeca/pako
|
|
4
|
+
// Definitions by: Caleb Eggensperger <https://github.com/calebegg>
|
|
5
|
+
// Muhammet Öztürk <https://github.com/hlthi>
|
|
6
|
+
// Thibault Poisson <https://github.com/OrIOg>
|
|
7
|
+
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
|
8
|
+
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
10
|
+
enum constants {
|
|
11
|
+
// FlushValues
|
|
12
|
+
Z_NO_FLUSH = 0,
|
|
13
|
+
Z_PARTIAL_FLUSH = 1,
|
|
14
|
+
Z_SYNC_FLUSH = 2,
|
|
15
|
+
Z_FULL_FLUSH = 3,
|
|
16
|
+
Z_FINISH = 4,
|
|
17
|
+
Z_BLOCK = 5,
|
|
18
|
+
Z_TREES = 6,
|
|
19
|
+
// StrategyValues
|
|
20
|
+
Z_FILTERED = 1,
|
|
21
|
+
Z_HUFFMAN_ONLY = 2,
|
|
22
|
+
Z_RLE = 3,
|
|
23
|
+
Z_FIXED = 4,
|
|
24
|
+
Z_DEFAULT_STRATEGY = 0,
|
|
25
|
+
// ReturnCodes
|
|
26
|
+
Z_OK = 0,
|
|
27
|
+
Z_STREAM_END = 1,
|
|
28
|
+
Z_NEED_DICT = 2,
|
|
29
|
+
Z_ERRNO = -1,
|
|
30
|
+
Z_STREAM_ERROR = -2,
|
|
31
|
+
Z_DATA_ERROR = -3,
|
|
32
|
+
Z_BUF_ERROR = -5,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type FlushValues =
|
|
36
|
+
| constants.Z_NO_FLUSH
|
|
37
|
+
| constants.Z_PARTIAL_FLUSH
|
|
38
|
+
| constants.Z_SYNC_FLUSH
|
|
39
|
+
| constants.Z_FINISH
|
|
40
|
+
| constants.Z_BLOCK
|
|
41
|
+
| constants.Z_TREES
|
|
42
|
+
|
|
43
|
+
type StrategyValues =
|
|
44
|
+
| constants.Z_FILTERED
|
|
45
|
+
| constants.Z_HUFFMAN_ONLY
|
|
46
|
+
| constants.Z_RLE
|
|
47
|
+
| constants.Z_FIXED
|
|
48
|
+
| constants.Z_DEFAULT_STRATEGY
|
|
49
|
+
|
|
50
|
+
type ReturnCodes =
|
|
51
|
+
| constants.Z_OK
|
|
52
|
+
| constants.Z_STREAM_END
|
|
53
|
+
| constants.Z_NEED_DICT
|
|
54
|
+
| constants.Z_ERRNO
|
|
55
|
+
| constants.Z_STREAM_ERROR
|
|
56
|
+
| constants.Z_DATA_ERROR
|
|
57
|
+
| constants.Z_BUF_ERROR
|
|
58
|
+
| constants.Z_DEFAULT_STRATEGY
|
|
59
|
+
|
|
60
|
+
interface DeflateOptions {
|
|
61
|
+
level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | undefined
|
|
62
|
+
windowBits?: number | undefined
|
|
63
|
+
memLevel?: number | undefined
|
|
64
|
+
strategy?: StrategyValues | undefined
|
|
65
|
+
dictionary?: any
|
|
66
|
+
raw?: boolean | undefined
|
|
67
|
+
chunkSize?: number | undefined
|
|
68
|
+
gzip?: boolean | undefined
|
|
69
|
+
header?: Header | undefined
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
interface DeflateFunctionOptions {
|
|
73
|
+
level?: -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | undefined
|
|
74
|
+
windowBits?: number | undefined
|
|
75
|
+
memLevel?: number | undefined
|
|
76
|
+
strategy?: StrategyValues | undefined
|
|
77
|
+
dictionary?: any
|
|
78
|
+
raw?: boolean | undefined
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface InflateOptions {
|
|
82
|
+
windowBits?: number | undefined
|
|
83
|
+
dictionary?: any
|
|
84
|
+
raw?: boolean | undefined
|
|
85
|
+
to?: 'string' | undefined
|
|
86
|
+
chunkSize?: number | undefined
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface InflateFunctionOptions {
|
|
90
|
+
windowBits?: number | undefined
|
|
91
|
+
raw?: boolean | undefined
|
|
92
|
+
to?: 'string' | undefined
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
interface Header {
|
|
96
|
+
text?: boolean | undefined
|
|
97
|
+
time?: number | undefined
|
|
98
|
+
os?: number | undefined
|
|
99
|
+
extra?: number[] | undefined
|
|
100
|
+
name?: string | undefined
|
|
101
|
+
comment?: string | undefined
|
|
102
|
+
hcrc?: boolean | undefined
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
type Data = Uint8Array | ArrayBuffer
|
|
106
|
+
|
|
107
|
+
declare module 'pako/dist/pako_inflate.min.js' {
|
|
108
|
+
/**
|
|
109
|
+
* Decompress data with inflate/ungzip and options. Autodetect format via wrapper header
|
|
110
|
+
* by default. That's why we don't provide separate ungzip method.
|
|
111
|
+
*/
|
|
112
|
+
function inflate(
|
|
113
|
+
data: Data,
|
|
114
|
+
options: InflateFunctionOptions & { to: 'string' },
|
|
115
|
+
): string
|
|
116
|
+
function inflate(data: Data, options?: InflateFunctionOptions): Uint8Array
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The same as inflate, but creates raw data, without wrapper (header and adler32 crc).
|
|
120
|
+
*/
|
|
121
|
+
function inflateRaw(
|
|
122
|
+
data: Data,
|
|
123
|
+
options: InflateFunctionOptions & { to: 'string' },
|
|
124
|
+
): string
|
|
125
|
+
function inflateRaw(data: Data, options?: InflateFunctionOptions): Uint8Array
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Just shortcut to inflate, because it autodetects format by header.content. Done for convenience.
|
|
129
|
+
*/
|
|
130
|
+
function ungzip(
|
|
131
|
+
data: Data,
|
|
132
|
+
options: InflateFunctionOptions & { to: 'string' },
|
|
133
|
+
): string
|
|
134
|
+
function ungzip(data: Data, options?: InflateFunctionOptions): Uint8Array
|
|
135
|
+
|
|
136
|
+
// https://github.com/nodeca/pako/blob/893381abcafa10fa2081ce60dae7d4d8e873a658/lib/inflate.js
|
|
137
|
+
class Inflate {
|
|
138
|
+
constructor(options?: InflateOptions)
|
|
139
|
+
header?: Header | undefined
|
|
140
|
+
|
|
141
|
+
err: ReturnCodes
|
|
142
|
+
|
|
143
|
+
msg: string
|
|
144
|
+
|
|
145
|
+
result: Uint8Array | string
|
|
146
|
+
onData(chunk: Data): void
|
|
147
|
+
onEnd(status: number): void
|
|
148
|
+
push(data: Data, mode?: FlushValues | boolean): boolean
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
declare module 'pako/dist/pako_deflate.min.js' {
|
|
153
|
+
/**
|
|
154
|
+
* Compress data with deflate algorithm and options.
|
|
155
|
+
*/
|
|
156
|
+
function deflate(
|
|
157
|
+
data: Data | string,
|
|
158
|
+
options?: DeflateFunctionOptions,
|
|
159
|
+
): Uint8Array
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The same as deflate, but creates raw data, without wrapper (header and adler32 crc).
|
|
163
|
+
*/
|
|
164
|
+
function deflateRaw(
|
|
165
|
+
data: Data | string,
|
|
166
|
+
options?: DeflateFunctionOptions,
|
|
167
|
+
): Uint8Array
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* The same as deflate, but create gzip wrapper instead of deflate one.
|
|
171
|
+
*/
|
|
172
|
+
function gzip(
|
|
173
|
+
data: Data | string,
|
|
174
|
+
options?: DeflateFunctionOptions,
|
|
175
|
+
): Uint8Array
|
|
176
|
+
|
|
177
|
+
class Deflate {
|
|
178
|
+
constructor(options?: DeflateOptions)
|
|
179
|
+
err: ReturnCodes
|
|
180
|
+
|
|
181
|
+
msg: string
|
|
182
|
+
|
|
183
|
+
result: Uint8Array
|
|
184
|
+
onData(chunk: Data): void
|
|
185
|
+
onEnd(status: number): void
|
|
186
|
+
push(data: Data | string, mode?: FlushValues | boolean): boolean
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { JsonRpcProvider } from '@ethersproject/providers'
|
|
2
2
|
import { BulkRenewal__factory } from '../generated/factories/BulkRenewal__factory'
|
|
3
3
|
|
|
4
|
-
// Use a higher-order function to
|
|
4
|
+
// Use a higher-order function to override the address that is passed in from getContractAddress()
|
|
5
5
|
export default (provider: JsonRpcProvider, address: string) =>
|
|
6
6
|
BulkRenewal__factory.connect(address, provider)
|
|
@@ -7,6 +7,125 @@ beforeAll(async () => {
|
|
|
7
7
|
;({ ensInstance } = await setup())
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
+
const dummyABI = [
|
|
11
|
+
{
|
|
12
|
+
type: 'event',
|
|
13
|
+
anonymous: false,
|
|
14
|
+
name: 'ABIChanged',
|
|
15
|
+
inputs: [
|
|
16
|
+
{
|
|
17
|
+
type: 'bytes32',
|
|
18
|
+
indexed: true,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: 'uint256',
|
|
22
|
+
indexed: true,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: 'event',
|
|
28
|
+
anonymous: false,
|
|
29
|
+
name: 'VersionChanged',
|
|
30
|
+
inputs: [
|
|
31
|
+
{
|
|
32
|
+
type: 'bytes32',
|
|
33
|
+
indexed: true,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: 'uint64',
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: 'function',
|
|
42
|
+
name: 'ABI',
|
|
43
|
+
constant: true,
|
|
44
|
+
stateMutability: 'view',
|
|
45
|
+
payable: false,
|
|
46
|
+
inputs: [
|
|
47
|
+
{
|
|
48
|
+
type: 'bytes32',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
type: 'uint256',
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
outputs: [
|
|
55
|
+
{
|
|
56
|
+
type: 'uint256',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: 'bytes',
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: 'function',
|
|
65
|
+
name: 'clearRecords',
|
|
66
|
+
constant: false,
|
|
67
|
+
payable: false,
|
|
68
|
+
inputs: [
|
|
69
|
+
{
|
|
70
|
+
type: 'bytes32',
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
outputs: [],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
type: 'function',
|
|
77
|
+
name: 'recordVersions',
|
|
78
|
+
constant: true,
|
|
79
|
+
stateMutability: 'view',
|
|
80
|
+
payable: false,
|
|
81
|
+
inputs: [
|
|
82
|
+
{
|
|
83
|
+
type: 'bytes32',
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
outputs: [
|
|
87
|
+
{
|
|
88
|
+
type: 'uint64',
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: 'function',
|
|
94
|
+
name: 'setABI',
|
|
95
|
+
constant: false,
|
|
96
|
+
payable: false,
|
|
97
|
+
inputs: [
|
|
98
|
+
{
|
|
99
|
+
type: 'bytes32',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
type: 'uint256',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: 'bytes',
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
outputs: [],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
type: 'function',
|
|
112
|
+
name: 'supportsInterface',
|
|
113
|
+
constant: true,
|
|
114
|
+
stateMutability: 'view',
|
|
115
|
+
payable: false,
|
|
116
|
+
inputs: [
|
|
117
|
+
{
|
|
118
|
+
type: 'bytes4',
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
outputs: [
|
|
122
|
+
{
|
|
123
|
+
type: 'bool',
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
]
|
|
128
|
+
|
|
10
129
|
describe('getSpecificRecord', () => {
|
|
11
130
|
describe('getContentHash', () => {
|
|
12
131
|
it('should return null for a non-existent name', async () => {
|
|
@@ -76,4 +195,47 @@ describe('getSpecificRecord', () => {
|
|
|
76
195
|
expect(result).toBeUndefined()
|
|
77
196
|
})
|
|
78
197
|
})
|
|
198
|
+
|
|
199
|
+
describe('getABI', () => {
|
|
200
|
+
it('should return object for type 1 ABI', async () => {
|
|
201
|
+
const result = await ensInstance.getABI('with-type-1-abi.eth')
|
|
202
|
+
expect(result).toBeTruthy()
|
|
203
|
+
if (result) {
|
|
204
|
+
expect(result.contentType).toBe(1)
|
|
205
|
+
expect(result.decoded).toBe(true)
|
|
206
|
+
expect(result.abi).toMatchObject(dummyABI)
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
it('should return object for type 2 ABI', async () => {
|
|
210
|
+
const result = await ensInstance.getABI('with-type-2-abi.eth')
|
|
211
|
+
expect(result).toBeTruthy()
|
|
212
|
+
if (result) {
|
|
213
|
+
expect(result.contentType).toBe(2)
|
|
214
|
+
expect(result.decoded).toBe(true)
|
|
215
|
+
expect(result.abi).toMatchObject(dummyABI)
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
it('should return object for type 4 ABI', async () => {
|
|
219
|
+
const result = await ensInstance.getABI('with-type-4-abi.eth')
|
|
220
|
+
expect(result).toBeTruthy()
|
|
221
|
+
if (result) {
|
|
222
|
+
expect(result.contentType).toBe(4)
|
|
223
|
+
expect(result.decoded).toBe(true)
|
|
224
|
+
expect(result.abi).toMatchObject(dummyABI)
|
|
225
|
+
}
|
|
226
|
+
})
|
|
227
|
+
it('should return unresolved URI for type 8 ABI', async () => {
|
|
228
|
+
const result = await ensInstance.getABI('with-type-8-abi.eth')
|
|
229
|
+
expect(result).toBeTruthy()
|
|
230
|
+
if (result) {
|
|
231
|
+
expect(result.contentType).toBe(8)
|
|
232
|
+
expect(result.decoded).toBe(false)
|
|
233
|
+
expect(result.abi).toBe('https://example.com')
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
it('should return undefined if unsupported contentType', async () => {
|
|
237
|
+
const result = await ensInstance.getABI('with-type-256-abi.eth')
|
|
238
|
+
expect(result).toBeUndefined()
|
|
239
|
+
})
|
|
240
|
+
})
|
|
79
241
|
})
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { formatsByCoinType, formatsByName } from '@ensdomains/address-encoder'
|
|
2
|
-
import {
|
|
2
|
+
import { BigNumber } from '@ethersproject/bignumber'
|
|
3
|
+
import { arrayify, hexStripZeros, isBytesLike } from '@ethersproject/bytes'
|
|
4
|
+
import { toUtf8String } from '@ethersproject/strings'
|
|
3
5
|
import { ENSArgs } from '..'
|
|
4
6
|
import { decodeContenthash } from '../utils/contentHash'
|
|
5
7
|
import { namehash } from '../utils/normalise'
|
|
@@ -234,3 +236,95 @@ export const getAddr = {
|
|
|
234
236
|
return _getAddr.decode({ contracts }, urData.data, _name, coinType)
|
|
235
237
|
},
|
|
236
238
|
}
|
|
239
|
+
|
|
240
|
+
// Supported content types as bitwise OR
|
|
241
|
+
// ID 1: JSON
|
|
242
|
+
// ID 2: zlib compressed JSON
|
|
243
|
+
// ID 4: CBOR
|
|
244
|
+
// ID 8: URI
|
|
245
|
+
const supportedContentTypes = '0xf'
|
|
246
|
+
|
|
247
|
+
export const _getABI = {
|
|
248
|
+
raw: async ({ contracts }: ENSArgs<'contracts'>, name: string) => {
|
|
249
|
+
const publicResolver = await contracts?.getPublicResolver()!
|
|
250
|
+
return {
|
|
251
|
+
to: '0x0000000000000000000000000000000000000000',
|
|
252
|
+
data: publicResolver.interface.encodeFunctionData('ABI', [
|
|
253
|
+
namehash(name),
|
|
254
|
+
supportedContentTypes,
|
|
255
|
+
]),
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
decode: async ({ contracts }: ENSArgs<'contracts'>, data: string) => {
|
|
259
|
+
const publicResolver = await contracts?.getPublicResolver()!
|
|
260
|
+
const [bnContentType, encodedABIData] =
|
|
261
|
+
publicResolver.interface.decodeFunctionResult('ABI', data)
|
|
262
|
+
if (!bnContentType || !data) {
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
const contentType = (bnContentType as BigNumber).toNumber()
|
|
266
|
+
if (!contentType) {
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
let abiData: string | object
|
|
270
|
+
let decoded = false
|
|
271
|
+
switch (contentType) {
|
|
272
|
+
// JSON
|
|
273
|
+
case 1:
|
|
274
|
+
abiData = JSON.parse(toUtf8String(encodedABIData))
|
|
275
|
+
decoded = true
|
|
276
|
+
break
|
|
277
|
+
// zlib compressed JSON
|
|
278
|
+
case 2: {
|
|
279
|
+
const { inflate } = await import('pako/dist/pako_inflate.min.js')
|
|
280
|
+
abiData = JSON.parse(
|
|
281
|
+
inflate(arrayify(encodedABIData), { to: 'string' }),
|
|
282
|
+
)
|
|
283
|
+
decoded = true
|
|
284
|
+
break
|
|
285
|
+
}
|
|
286
|
+
// CBOR
|
|
287
|
+
case 4: {
|
|
288
|
+
const { decodeFirst } = await import('cbor')
|
|
289
|
+
abiData = await decodeFirst(arrayify(encodedABIData))
|
|
290
|
+
decoded = true
|
|
291
|
+
break
|
|
292
|
+
}
|
|
293
|
+
// URI
|
|
294
|
+
case 8:
|
|
295
|
+
abiData = toUtf8String(encodedABIData)
|
|
296
|
+
decoded = false
|
|
297
|
+
break
|
|
298
|
+
default:
|
|
299
|
+
try {
|
|
300
|
+
abiData = toUtf8String(encodedABIData)
|
|
301
|
+
} catch {
|
|
302
|
+
abiData = encodedABIData
|
|
303
|
+
}
|
|
304
|
+
decoded = false
|
|
305
|
+
}
|
|
306
|
+
return {
|
|
307
|
+
contentType,
|
|
308
|
+
decoded,
|
|
309
|
+
abi: abiData,
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export const getABI = {
|
|
315
|
+
raw: async (
|
|
316
|
+
{ contracts, universalWrapper }: ENSArgs<'contracts' | 'universalWrapper'>,
|
|
317
|
+
name: string,
|
|
318
|
+
) => {
|
|
319
|
+
const prData = await _getABI.raw({ contracts }, name)
|
|
320
|
+
return universalWrapper.raw(name, prData.data)
|
|
321
|
+
},
|
|
322
|
+
decode: async (
|
|
323
|
+
{ contracts, universalWrapper }: ENSArgs<'contracts' | 'universalWrapper'>,
|
|
324
|
+
data: string,
|
|
325
|
+
) => {
|
|
326
|
+
const urData = await universalWrapper.decode(data)
|
|
327
|
+
if (!urData) return
|
|
328
|
+
return _getABI.decode({ contracts }, urData.data)
|
|
329
|
+
},
|
|
330
|
+
}
|