@ensdomains/ensjs 3.0.0-alpha.5 → 3.0.0-alpha.8
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/GqlManager.d.ts +3 -0
- package/dist/cjs/GqlManager.js +62 -2
- package/dist/cjs/functions/burnFuses.d.ts +1 -1
- package/dist/cjs/functions/burnFuses.js +1 -1
- package/dist/cjs/functions/createSubname.d.ts +1 -1
- package/dist/cjs/functions/createSubname.js +2 -2
- package/dist/cjs/functions/deleteSubname.d.ts +1 -1
- package/dist/cjs/functions/deleteSubname.js +1 -1
- package/dist/cjs/functions/getProfile.d.ts +4 -1
- package/dist/cjs/functions/getProfile.js +62 -18
- package/dist/cjs/functions/getRecords.d.ts +1 -0
- package/dist/cjs/functions/setName.d.ts +1 -1
- package/dist/cjs/functions/setName.js +2 -2
- package/dist/cjs/functions/setRecords.d.ts +1 -1
- package/dist/cjs/functions/setRecords.js +1 -1
- package/dist/cjs/functions/setResolver.d.ts +1 -1
- package/dist/cjs/functions/setResolver.js +2 -2
- package/dist/cjs/functions/transferName.d.ts +1 -1
- package/dist/cjs/functions/transferName.js +3 -3
- package/dist/cjs/functions/transferSubname.d.ts +1 -1
- package/dist/cjs/functions/transferSubname.js +2 -2
- package/dist/cjs/functions/unwrapName.d.ts +1 -1
- package/dist/cjs/functions/unwrapName.js +2 -2
- package/dist/cjs/functions/wrapName.d.ts +2 -2
- package/dist/cjs/functions/wrapName.js +3 -3
- package/dist/cjs/index.d.ts +34 -52
- package/dist/cjs/index.js +10 -6
- package/dist/cjs/utils/labels.js +4 -3
- package/dist/cjs/utils/normalise.d.ts +1 -1
- package/dist/cjs/utils/normalise.js +10 -3
- package/dist/cjs/utils/writeTx.d.ts +4 -0
- package/dist/cjs/utils/writeTx.js +3 -0
- package/dist/esm/GqlManager.d.ts +3 -0
- package/dist/esm/GqlManager.js +58 -2
- package/dist/esm/functions/burnFuses.d.ts +1 -1
- package/dist/esm/functions/burnFuses.js +1 -1
- package/dist/esm/functions/createSubname.d.ts +1 -1
- package/dist/esm/functions/createSubname.js +2 -2
- package/dist/esm/functions/deleteSubname.d.ts +1 -1
- package/dist/esm/functions/deleteSubname.js +1 -1
- package/dist/esm/functions/getProfile.d.ts +4 -1
- package/dist/esm/functions/getProfile.js +62 -18
- package/dist/esm/functions/getRecords.d.ts +1 -0
- package/dist/esm/functions/setName.d.ts +1 -1
- package/dist/esm/functions/setName.js +2 -2
- package/dist/esm/functions/setRecords.d.ts +1 -1
- package/dist/esm/functions/setRecords.js +1 -1
- package/dist/esm/functions/setResolver.d.ts +1 -1
- package/dist/esm/functions/setResolver.js +2 -2
- package/dist/esm/functions/transferName.d.ts +1 -1
- package/dist/esm/functions/transferName.js +3 -3
- package/dist/esm/functions/transferSubname.d.ts +1 -1
- package/dist/esm/functions/transferSubname.js +2 -2
- package/dist/esm/functions/unwrapName.d.ts +1 -1
- package/dist/esm/functions/unwrapName.js +2 -2
- package/dist/esm/functions/wrapName.d.ts +2 -2
- package/dist/esm/functions/wrapName.js +3 -3
- package/dist/esm/index.d.ts +34 -52
- package/dist/esm/index.js +10 -6
- package/dist/esm/utils/labels.js +4 -3
- package/dist/esm/utils/normalise.d.ts +1 -1
- package/dist/esm/utils/normalise.js +10 -3
- package/dist/esm/utils/writeTx.d.ts +4 -0
- package/dist/esm/utils/writeTx.js +1 -0
- package/package.json +7 -5
- package/src/GqlManager.test.ts +170 -0
- package/src/GqlManager.ts +67 -2
- package/src/functions/burnFuses.ts +1 -1
- package/src/functions/createSubname.ts +2 -2
- package/src/functions/deleteSubname.ts +1 -1
- package/src/functions/getProfile.test.ts +16 -1
- package/src/functions/getProfile.ts +82 -19
- package/src/functions/getRecords.ts +1 -0
- package/src/functions/setName.ts +5 -5
- package/src/functions/setRecords.ts +2 -2
- package/src/functions/setResolver.ts +5 -2
- package/src/functions/transferName.ts +5 -3
- package/src/functions/transferSubname.ts +11 -2
- package/src/functions/unwrapName.ts +10 -2
- package/src/functions/wrapName.ts +5 -8
- package/src/index.ts +37 -12
- package/src/tests/populateTransaction.test.ts +40 -0
- package/src/tests/signerInjection.test.ts +7 -3
- package/src/utils/labels.ts +5 -3
- package/src/utils/normalise.ts +10 -4
- package/src/utils/writeTx.ts +6 -0
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JsonRpcSigner } from '@ethersproject/providers';
|
|
2
|
+
import { ContractTransaction, ethers, PopulatedTransaction } from 'ethers';
|
|
2
3
|
import ContractManager from './contracts';
|
|
3
4
|
import { getContractAddress as _getContractAddress } from './contracts/getContractAddress';
|
|
4
5
|
import { SupportedNetworkId } from './contracts/types';
|
|
6
|
+
import type burnFuses from './functions/burnFuses';
|
|
7
|
+
import type createSubname from './functions/createSubname';
|
|
8
|
+
import type deleteSubname from './functions/deleteSubname';
|
|
9
|
+
import type setName from './functions/setName';
|
|
10
|
+
import type setRecords from './functions/setRecords';
|
|
11
|
+
import type setResolver from './functions/setResolver';
|
|
12
|
+
import type transferName from './functions/transferName';
|
|
13
|
+
import type transferSubname from './functions/transferSubname';
|
|
14
|
+
import type unwrapName from './functions/unwrapName';
|
|
15
|
+
import type wrapName from './functions/wrapName';
|
|
5
16
|
import GqlManager from './GqlManager';
|
|
6
17
|
declare type ENSOptions = {
|
|
7
18
|
graphURI?: string | null;
|
|
@@ -10,7 +21,7 @@ declare type ENSOptions = {
|
|
|
10
21
|
export declare type InternalENS = {
|
|
11
22
|
options?: ENSOptions;
|
|
12
23
|
provider?: ethers.providers.Provider;
|
|
13
|
-
signer:
|
|
24
|
+
signer: JsonRpcSigner;
|
|
14
25
|
graphURI?: string | null;
|
|
15
26
|
} & ENS;
|
|
16
27
|
export declare type ENSArgs<K extends keyof InternalENS> = {
|
|
@@ -20,8 +31,13 @@ declare type OmitFirstArg<F> = F extends (x: any, ...args: infer P) => infer R ?
|
|
|
20
31
|
declare type OmitFirstTwoArgs<F> = F extends (x: any, y: any, ...args: infer P) => infer R ? (...args: P) => R : never;
|
|
21
32
|
declare type WriteOptions = {
|
|
22
33
|
addressOrIndex?: string | number;
|
|
23
|
-
signer?:
|
|
34
|
+
signer?: JsonRpcSigner;
|
|
24
35
|
};
|
|
36
|
+
declare type OptionalWriteOptions<F> = F extends (x: any, arg_0: infer Z, options?: infer P) => infer R ? (name: Z, options?: P & WriteOptions) => R : F extends (x: any, arg_0: infer Z, options: infer P) => infer R ? (name: Z, options: P & WriteOptions) => R : never;
|
|
37
|
+
interface WriteFunction<F extends (...args: any) => any> extends Function {
|
|
38
|
+
(...args: Parameters<OptionalWriteOptions<F>>): Promise<ContractTransaction>;
|
|
39
|
+
populateTransaction: (...args: Parameters<OptionalWriteOptions<F>>) => Promise<PopulatedTransaction>;
|
|
40
|
+
}
|
|
25
41
|
export declare type RawFunction = {
|
|
26
42
|
raw: (...args: any[]) => Promise<{
|
|
27
43
|
to: string;
|
|
@@ -117,11 +133,13 @@ export declare class ENS {
|
|
|
117
133
|
}>;
|
|
118
134
|
decode: ({ multicallWrapper }: ENSArgs<"multicallWrapper">, data: string, ...items: BatchFunctionResult<RawFunction>[]) => Promise<any[] | undefined>;
|
|
119
135
|
}>;
|
|
120
|
-
getProfile: (nameOrAddress: string, options?: {
|
|
136
|
+
getProfile: (nameOrAddress: string, options?: ({
|
|
121
137
|
contentHash?: boolean | undefined;
|
|
122
138
|
texts?: boolean | string[] | undefined;
|
|
123
139
|
coinTypes?: boolean | string[] | undefined;
|
|
124
|
-
}
|
|
140
|
+
} & {
|
|
141
|
+
resolverAddress?: string | undefined;
|
|
142
|
+
}) | undefined) => Promise<{
|
|
125
143
|
isMigrated: boolean | null;
|
|
126
144
|
createdAt: string | null;
|
|
127
145
|
address?: string | undefined;
|
|
@@ -150,6 +168,7 @@ export declare class ENS {
|
|
|
150
168
|
contentHash?: boolean | undefined;
|
|
151
169
|
texts?: boolean | string[] | undefined;
|
|
152
170
|
coinTypes?: boolean | string[] | undefined;
|
|
171
|
+
resolverAddress?: string | undefined;
|
|
153
172
|
} | undefined) => Promise<{
|
|
154
173
|
isMigrated: boolean | null;
|
|
155
174
|
createdAt: string | null;
|
|
@@ -436,53 +455,16 @@ export declare class ENS {
|
|
|
436
455
|
}>;
|
|
437
456
|
decode: ({ contracts }: ENSArgs<"contracts">, data: string) => Promise<any>;
|
|
438
457
|
}>;
|
|
439
|
-
setName:
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
resolver?: string | undefined;
|
|
450
|
-
} & WriteOptions) => Promise<ethers.ContractTransaction>;
|
|
451
|
-
transferName: (name: string, options: {
|
|
452
|
-
newOwner: string;
|
|
453
|
-
contract: "nameWrapper" | "registry" | "baseRegistrar";
|
|
454
|
-
} & WriteOptions) => Promise<ethers.ContractTransaction>;
|
|
455
|
-
wrapName: (name: string, options: {
|
|
456
|
-
wrappedOwner: string;
|
|
457
|
-
fuseOptions?: string | number | import("./@types/FuseOptions").FuseOptions | undefined;
|
|
458
|
-
resolverAddress?: string | undefined;
|
|
459
|
-
} & WriteOptions) => Promise<ethers.ContractTransaction>;
|
|
460
|
-
unwrapName: (name: string, options: {
|
|
461
|
-
newController: string;
|
|
462
|
-
newRegistrant?: string | undefined;
|
|
463
|
-
} & WriteOptions) => Promise<ethers.ContractTransaction>;
|
|
464
|
-
burnFuses: (name: string, options: {
|
|
465
|
-
fusesToBurn: import("./@types/FuseOptions").FuseOptions;
|
|
466
|
-
} & WriteOptions) => Promise<ethers.ContractTransaction>;
|
|
467
|
-
createSubname: (name: string, options: ({
|
|
468
|
-
owner: string;
|
|
469
|
-
resolverAddress?: string | undefined;
|
|
470
|
-
contract: "nameWrapper" | "registry";
|
|
471
|
-
} | ({
|
|
472
|
-
contract: "nameWrapper";
|
|
473
|
-
fuses?: import("./@types/FuseOptions").FuseOptions | undefined;
|
|
474
|
-
} & {
|
|
475
|
-
owner: string;
|
|
476
|
-
resolverAddress?: string | undefined;
|
|
477
|
-
contract: "nameWrapper" | "registry";
|
|
478
|
-
})) & WriteOptions) => Promise<ethers.ContractTransaction>;
|
|
479
|
-
deleteSubname: (name: string, options: {
|
|
480
|
-
contract: "nameWrapper" | "registry";
|
|
481
|
-
} & WriteOptions) => Promise<ethers.ContractTransaction>;
|
|
482
|
-
transferSubname: (name: string, options: {
|
|
483
|
-
contract: "nameWrapper" | "registry";
|
|
484
|
-
address: string;
|
|
485
|
-
} & WriteOptions) => Promise<ethers.ContractTransaction>;
|
|
458
|
+
setName: WriteFunction<typeof setName>;
|
|
459
|
+
setRecords: WriteFunction<typeof setRecords>;
|
|
460
|
+
setResolver: WriteFunction<typeof setResolver>;
|
|
461
|
+
transferName: WriteFunction<typeof transferName>;
|
|
462
|
+
wrapName: WriteFunction<typeof wrapName>;
|
|
463
|
+
unwrapName: WriteFunction<typeof unwrapName>;
|
|
464
|
+
burnFuses: WriteFunction<typeof burnFuses>;
|
|
465
|
+
createSubname: WriteFunction<typeof createSubname>;
|
|
466
|
+
deleteSubname: WriteFunction<typeof deleteSubname>;
|
|
467
|
+
transferSubname: WriteFunction<typeof transferSubname>;
|
|
486
468
|
getDNSOwner: (dnsName: string) => Promise<any>;
|
|
487
469
|
}
|
|
488
470
|
export {};
|
package/dist/esm/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import ContractManager from './contracts';
|
|
|
2
2
|
import { getContractAddress as _getContractAddress } from './contracts/getContractAddress';
|
|
3
3
|
import GqlManager from './GqlManager';
|
|
4
4
|
import singleCall from './utils/singleCall';
|
|
5
|
+
import writeTx from './utils/writeTx';
|
|
5
6
|
const graphURIEndpoints = {
|
|
6
7
|
1: 'https://api.thegraph.com/subgraphs/name/ensdomains/ens',
|
|
7
8
|
3: 'https://api.thegraph.com/subgraphs/name/ensdomains/ensropsten',
|
|
@@ -52,29 +53,29 @@ export class ENS {
|
|
|
52
53
|
await thisRef.checkInitialProvider();
|
|
53
54
|
// import the module dynamically
|
|
54
55
|
const mod = await import(
|
|
55
|
-
/* webpackMode: "lazy", webpackChunkName: "[request]", webpackPreload: true */
|
|
56
|
+
/* webpackMode: "lazy", webpackChunkName: "[request]", webpackPreload: true, webpackExclude: /.*\.ts$/ */
|
|
56
57
|
`./functions/${path}`);
|
|
57
58
|
// if combine isn't specified, run normally
|
|
58
59
|
// otherwise, create a function from the raw and decode functions
|
|
59
60
|
if (subFunc !== 'combine') {
|
|
61
|
+
const writeable = subFunc === 'write' || subFunc === 'populateTransaction';
|
|
60
62
|
// get the function to call
|
|
61
|
-
const func = subFunc && subFunc
|
|
62
|
-
? mod[exportName][subFunc]
|
|
63
|
-
: mod[exportName];
|
|
63
|
+
const func = subFunc && !writeable ? mod[exportName][subFunc] : mod[exportName];
|
|
64
64
|
// get the dependencies to forward to the function as the first arg
|
|
65
65
|
let dependenciesToForward = thisRef.forwardDependenciesFromArray(dependencies);
|
|
66
66
|
// if func is write func, inject signer into dependencies
|
|
67
|
-
if (
|
|
67
|
+
if (writeable) {
|
|
68
68
|
const options = (args[1] || {});
|
|
69
69
|
const signer = options.signer ||
|
|
70
70
|
thisRef.provider?.getSigner(options.addressOrIndex);
|
|
71
|
+
const populate = subFunc === 'populateTransaction';
|
|
71
72
|
if (!signer) {
|
|
72
73
|
throw new Error('No signer specified');
|
|
73
74
|
}
|
|
74
75
|
delete options.addressOrIndex;
|
|
75
76
|
delete options.signer;
|
|
76
77
|
dependenciesToForward = { ...dependenciesToForward, signer };
|
|
77
|
-
return func(dependenciesToForward, args[0], options);
|
|
78
|
+
return func(dependenciesToForward, args[0], options).then(writeTx(signer, populate));
|
|
78
79
|
}
|
|
79
80
|
// return the function with the dependencies forwarded
|
|
80
81
|
return func(dependenciesToForward, ...args);
|
|
@@ -92,6 +93,9 @@ export class ENS {
|
|
|
92
93
|
mainFunc.decode = this.importGenerator(path, dependencies, exportName, 'decode');
|
|
93
94
|
mainFunc.batch = this.importGenerator(path, dependencies, exportName, 'batch', { raw: mainFunc.raw, decode: mainFunc.decode });
|
|
94
95
|
}
|
|
96
|
+
else if (subFunc === 'write') {
|
|
97
|
+
mainFunc.populateTransaction = this.importGenerator(path, dependencies, exportName, 'populateTransaction');
|
|
98
|
+
}
|
|
95
99
|
return mainFunc;
|
|
96
100
|
};
|
|
97
101
|
/**
|
package/dist/esm/utils/labels.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { solidityKeccak256 } from 'ethers/lib/utils';
|
|
2
2
|
import { truncateFormat } from './format';
|
|
3
|
+
const hasLocalStorage = typeof localStorage !== 'undefined';
|
|
3
4
|
export const labelhash = (input) => solidityKeccak256(['string'], [input]);
|
|
4
5
|
export const keccakFromString = (input) => labelhash(input);
|
|
5
6
|
export function decodeLabelhash(hash) {
|
|
@@ -24,12 +25,12 @@ export function isEncodedLabelhash(hash) {
|
|
|
24
25
|
return hash.startsWith('[') && hash.endsWith(']') && hash.length === 66;
|
|
25
26
|
}
|
|
26
27
|
function getLabels() {
|
|
27
|
-
return
|
|
28
|
+
return hasLocalStorage
|
|
28
29
|
? JSON.parse(localStorage.getItem('ensjs:labels')) || {}
|
|
29
30
|
: {};
|
|
30
31
|
}
|
|
31
32
|
function _saveLabel(hash, label) {
|
|
32
|
-
if (!
|
|
33
|
+
if (!hasLocalStorage)
|
|
33
34
|
return hash;
|
|
34
35
|
const labels = getLabels();
|
|
35
36
|
localStorage.setItem('ensjs:labels', JSON.stringify({
|
|
@@ -81,7 +82,7 @@ export function decryptName(name) {
|
|
|
81
82
|
}
|
|
82
83
|
export const truncateUndecryptedName = (name) => truncateFormat(name);
|
|
83
84
|
export function checkLocalStorageSize() {
|
|
84
|
-
if (!
|
|
85
|
+
if (!hasLocalStorage)
|
|
85
86
|
return 'Empty (0 KB)';
|
|
86
87
|
let allStrings = '';
|
|
87
88
|
for (const key in window.localStorage) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const normalise: (name: string) => any;
|
|
2
|
-
export declare const namehash: (
|
|
2
|
+
export declare const namehash: (name: string) => string;
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { concat, hexlify, keccak256, toUtf8Bytes } from 'ethers/lib/utils';
|
|
2
2
|
import uts46 from 'idna-uts46-hx/uts46bundle.js';
|
|
3
|
+
import { decodeLabelhash, isEncodedLabelhash } from './labels';
|
|
3
4
|
const zeros = new Uint8Array(32);
|
|
4
5
|
zeros.fill(0);
|
|
5
6
|
export const normalise = (name) => name ? uts46.toUnicode(name, { useStd3ASCII: true }) : name;
|
|
6
|
-
export const namehash = (
|
|
7
|
+
export const namehash = (name) => {
|
|
7
8
|
let result = zeros;
|
|
8
|
-
const name = normalise(inputName);
|
|
9
9
|
if (name) {
|
|
10
10
|
const labels = name.split('.');
|
|
11
11
|
for (var i = labels.length - 1; i >= 0; i--) {
|
|
12
|
-
|
|
12
|
+
let labelSha;
|
|
13
|
+
if (isEncodedLabelhash(labels[i])) {
|
|
14
|
+
labelSha = decodeLabelhash(labels[i]);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
const normalised = normalise(labels[i]);
|
|
18
|
+
labelSha = keccak256(toUtf8Bytes(normalised));
|
|
19
|
+
}
|
|
13
20
|
result = keccak256(concat([result, labelSha]));
|
|
14
21
|
}
|
|
15
22
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { JsonRpcSigner } from '@ethersproject/providers';
|
|
2
|
+
import type { PopulatedTransaction } from 'ethers';
|
|
3
|
+
declare const _default: (signer: JsonRpcSigner, populate: boolean) => (tx: PopulatedTransaction) => PopulatedTransaction | Promise<import("@ethersproject/abstract-provider").TransactionResponse>;
|
|
4
|
+
export default _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default (signer, populate) => (tx) => populate ? tx : signer.sendTransaction(tx);
|
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.8",
|
|
4
4
|
"description": "ENS javascript library for contract interaction",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"types": "./dist/cjs/index.d.ts",
|
|
@@ -46,12 +46,13 @@
|
|
|
46
46
|
"dns-packet": "^5.3.1",
|
|
47
47
|
"ethers": "^5.6.1",
|
|
48
48
|
"graphql": "^16.3.0",
|
|
49
|
-
"graphql-request": "
|
|
50
|
-
"idna-uts46-hx": "3.4.0"
|
|
49
|
+
"graphql-request": "next",
|
|
50
|
+
"idna-uts46-hx": "3.4.0",
|
|
51
|
+
"traverse": "^0.6.6"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@ensdomains/buffer": "^0.0.13",
|
|
54
|
-
"@ensdomains/ens-test-env": "0.1.
|
|
55
|
+
"@ensdomains/ens-test-env": "0.1.5",
|
|
55
56
|
"@ethersproject/abi": "^5.6.0",
|
|
56
57
|
"@ethersproject/providers": "^5.6.2",
|
|
57
58
|
"@nomiclabs/hardhat-ethers": "^2.0.5",
|
|
@@ -61,6 +62,7 @@
|
|
|
61
62
|
"@typechain/ethers-v5": "^10.0.0",
|
|
62
63
|
"@types/bn.js": "^5.1.0",
|
|
63
64
|
"@types/jest": "^27.4.1",
|
|
65
|
+
"@types/traverse": "^0.6.32",
|
|
64
66
|
"dotenv": "^16.0.0",
|
|
65
67
|
"ens-contracts": "github:ensdomains/ens-contracts#head=master&commit=3ecc56b14beb4aae8296f8a94f7c0d095e62fd93",
|
|
66
68
|
"hardhat": "^2.9.3",
|
|
@@ -81,5 +83,5 @@
|
|
|
81
83
|
"peerDependencies": {
|
|
82
84
|
"ethers": "*"
|
|
83
85
|
},
|
|
84
|
-
"stableVersion": "3.0.0-alpha.
|
|
86
|
+
"stableVersion": "3.0.0-alpha.7"
|
|
85
87
|
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import traverse from 'traverse'
|
|
2
|
+
import { visit, parse } from 'graphql'
|
|
3
|
+
|
|
4
|
+
import { requestMiddleware, responseMiddleware, enter } from './GqlManager'
|
|
5
|
+
import { namehash } from './utils/normalise'
|
|
6
|
+
|
|
7
|
+
describe('GqlManager', () => {
|
|
8
|
+
const queryWithoutId = `
|
|
9
|
+
query getNames($id: ID!, $expiryDate: Int) {
|
|
10
|
+
account(id: $id) {
|
|
11
|
+
registrations(first: 1000, where: { expiryDate_gt: $expiryDate }) {
|
|
12
|
+
registrationDate
|
|
13
|
+
expiryDate
|
|
14
|
+
domain {
|
|
15
|
+
labelName
|
|
16
|
+
labelhash
|
|
17
|
+
name
|
|
18
|
+
isMigrated
|
|
19
|
+
parent {
|
|
20
|
+
name
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
domains(first: 1000) {
|
|
25
|
+
labelName
|
|
26
|
+
labelhash
|
|
27
|
+
name
|
|
28
|
+
isMigrated
|
|
29
|
+
parent {
|
|
30
|
+
name
|
|
31
|
+
}
|
|
32
|
+
createdAt
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`
|
|
37
|
+
|
|
38
|
+
const mockRequest = {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: {
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify({ query: queryWithoutId }),
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const mockResponse = {
|
|
47
|
+
data: {
|
|
48
|
+
account: {
|
|
49
|
+
registrations: [
|
|
50
|
+
{
|
|
51
|
+
registrationDate: '1659245504',
|
|
52
|
+
expiryDate: '1690781504',
|
|
53
|
+
domain: {
|
|
54
|
+
id: '0xb1ccf7f6bb648f39ba48bf80f4a8a4522f474ee7d1edd6ea65f7fa51fe8b1612',
|
|
55
|
+
labelName: 'randydandy',
|
|
56
|
+
labelhash:
|
|
57
|
+
'0x63fd5bfdd0b1eb9f4c33c209b7c3e7dcb87a761d926a65e267f7cb99ee313ddd',
|
|
58
|
+
name: '0xde2551f43e950a2a4d4e6052f25edc450c48a5338faa27f09d1ee99ca9dc04fd',
|
|
59
|
+
isMigrated: true,
|
|
60
|
+
parent: {
|
|
61
|
+
name: '0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae',
|
|
62
|
+
invalidName: true,
|
|
63
|
+
},
|
|
64
|
+
invalidName: true,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
registrationDate: '1635284756',
|
|
69
|
+
expiryDate: '1666841708',
|
|
70
|
+
domain: {
|
|
71
|
+
id: '0xde2551f43e950a2a4d4e6052f25edc450c48a5338faa27f09d1ee99ca9dc04fd',
|
|
72
|
+
labelName: 'randydandy',
|
|
73
|
+
labelhash:
|
|
74
|
+
'0x6a877a8d92ad83c8d044d0c5b69aa0da3050f4d653dcc149fca952d6439e4105',
|
|
75
|
+
name: 'randydandy.eth',
|
|
76
|
+
isMigrated: true,
|
|
77
|
+
parent: {
|
|
78
|
+
name: '0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae',
|
|
79
|
+
invalidName: true,
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
registrationDate: '1659250465',
|
|
85
|
+
expiryDate: '1690786465',
|
|
86
|
+
domain: {
|
|
87
|
+
id: '0xaf119e72f050e5acad6b2d97826a7afb45afe9407376a2ab8240b62173b2d7c2',
|
|
88
|
+
labelName: 'nullbyte',
|
|
89
|
+
labelhash:
|
|
90
|
+
'0xc8985f8323b3dc707003a6ef5b379d9e8a058b6d6bcc2cfb307c61ca36920e27',
|
|
91
|
+
name: '0xb54c7c79c89d571f1fbf4c67f524e336a04441eeee4d76f156e835da99a46ddb',
|
|
92
|
+
isMigrated: true,
|
|
93
|
+
parent: {
|
|
94
|
+
name: '0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae',
|
|
95
|
+
invalidName: true,
|
|
96
|
+
},
|
|
97
|
+
invalidName: true,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
domains: [
|
|
102
|
+
{
|
|
103
|
+
id: '0xaf119e72f050e5acad6b2d97826a7afb45afe9407376a2ab8240b62173b2d7c2',
|
|
104
|
+
labelName: 'nullbyte',
|
|
105
|
+
labelhash:
|
|
106
|
+
'0xc8985f8323b3dc707003a6ef5b379d9e8a058b6d6bcc2cfb307c61ca36920e27',
|
|
107
|
+
name: '0xb54c7c79c89d571f1fbf4c67f524e336a04441eeee4d76f156e835da99a46ddb',
|
|
108
|
+
isMigrated: true,
|
|
109
|
+
parent: {
|
|
110
|
+
name: '0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae',
|
|
111
|
+
invalidName: true,
|
|
112
|
+
},
|
|
113
|
+
createdAt: '1659250465',
|
|
114
|
+
invalidName: true,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: '0xb1ccf7f6bb648f39ba48bf80f4a8a4522f474ee7d1edd6ea65f7fa51fe8b1612',
|
|
118
|
+
labelName: 'randydandy',
|
|
119
|
+
labelhash:
|
|
120
|
+
'0x63fd5bfdd0b1eb9f4c33c209b7c3e7dcb87a761d926a65e267f7cb99ee313ddd',
|
|
121
|
+
name: '0xde2551f43e950a2a4d4e6052f25edc450c48a5338faa27f09d1ee99ca9dc04fd',
|
|
122
|
+
isMigrated: true,
|
|
123
|
+
parent: {
|
|
124
|
+
name: '0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae',
|
|
125
|
+
invalidName: true,
|
|
126
|
+
},
|
|
127
|
+
createdAt: '1659245504',
|
|
128
|
+
invalidName: true,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
id: '0xde2551f43e950a2a4d4e6052f25edc450c48a5338faa27f09d1ee99ca9dc04fd',
|
|
132
|
+
labelName: 'randydandy',
|
|
133
|
+
labelhash:
|
|
134
|
+
'0x6a877a8d92ad83c8d044d0c5b69aa0da3050f4d653dcc149fca952d6439e4105',
|
|
135
|
+
name: 'randydandy.eth',
|
|
136
|
+
isMigrated: true,
|
|
137
|
+
parent: {
|
|
138
|
+
name: '0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae',
|
|
139
|
+
invalidName: true,
|
|
140
|
+
},
|
|
141
|
+
createdAt: '1635284756',
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
headers: {
|
|
147
|
+
map: {
|
|
148
|
+
'content-type': 'application/json',
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
status: 200,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
describe('requestMiddleware', () => {
|
|
155
|
+
it('should add id to a SelectionSet if name is present and id is not', () => {
|
|
156
|
+
const result = requestMiddleware(visit, parse)(mockRequest)
|
|
157
|
+
expect(result.body.includes('id')).toBe(true)
|
|
158
|
+
})
|
|
159
|
+
})
|
|
160
|
+
describe('responseMiddleware', () => {
|
|
161
|
+
it('should replace name with the namehash when there is an invalid name and id combo', () => {
|
|
162
|
+
const result = responseMiddleware(traverse)(mockResponse)
|
|
163
|
+
expect(result.data.account.domains[0].name).toBe(
|
|
164
|
+
namehash(
|
|
165
|
+
'0xb54c7c79c89d571f1fbf4c67f524e336a04441eeee4d76f156e835da99a46ddb',
|
|
166
|
+
),
|
|
167
|
+
)
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
})
|
package/src/GqlManager.ts
CHANGED
|
@@ -1,11 +1,76 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import { namehash } from './utils/normalise'
|
|
3
|
+
|
|
4
|
+
const generateSelection = (selection: any) => ({
|
|
5
|
+
kind: 'Field',
|
|
6
|
+
name: {
|
|
7
|
+
kind: 'Name',
|
|
8
|
+
value: selection,
|
|
9
|
+
},
|
|
10
|
+
arguments: [],
|
|
11
|
+
directives: [],
|
|
12
|
+
alias: undefined,
|
|
13
|
+
selectionSet: undefined,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
export const enter = (node: any) => {
|
|
17
|
+
if (node.kind === 'SelectionSet') {
|
|
18
|
+
const id = node.selections.find((x) => x.name && x.name.value === 'id')
|
|
19
|
+
const name = node.selections.find((x) => x.name && x.name.value === 'name')
|
|
20
|
+
|
|
21
|
+
if (!id && name) {
|
|
22
|
+
node.selections = [...node.selections, generateSelection('id')]
|
|
23
|
+
return node
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const requestMiddleware = (visit, parse) => (request: any) => {
|
|
29
|
+
const requestBody = JSON.parse(request.body)
|
|
30
|
+
const rawQuery = requestBody.query
|
|
31
|
+
const parsedQuery = parse(rawQuery)
|
|
32
|
+
const updatedQuery = visit(parsedQuery, { enter })
|
|
33
|
+
const updatedBody = { ...requestBody, query: updatedQuery.loc.source.body }
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
...request,
|
|
37
|
+
body: JSON.stringify(updatedBody),
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const responseMiddleware = (traverse) => (response: any) => {
|
|
42
|
+
traverse(response).forEach(function (responseItem: any) {
|
|
43
|
+
if (responseItem instanceof Object && responseItem.name) {
|
|
44
|
+
//Name already in hashed form
|
|
45
|
+
if (responseItem.name && responseItem.name.includes('[')) {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const hashedName = namehash(responseItem.name)
|
|
50
|
+
if (responseItem.id !== hashedName) {
|
|
51
|
+
this.update({ ...responseItem, name: hashedName, invalidName: true })
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
return response
|
|
56
|
+
}
|
|
57
|
+
|
|
1
58
|
export default class GqlManager {
|
|
2
59
|
public gql: any = () => null
|
|
3
60
|
public client?: any | null = null
|
|
4
61
|
|
|
5
62
|
public setUrl = async (url: string | null) => {
|
|
6
63
|
if (url) {
|
|
7
|
-
const imported = await
|
|
8
|
-
|
|
64
|
+
const [imported, traverse, { visit, parse }] = await Promise.all([
|
|
65
|
+
import('graphql-request'),
|
|
66
|
+
import('traverse'),
|
|
67
|
+
import('graphql/language'),
|
|
68
|
+
])
|
|
69
|
+
|
|
70
|
+
this.client = new imported.GraphQLClient(url, {
|
|
71
|
+
requestMiddleware: requestMiddleware(visit, parse),
|
|
72
|
+
responseMiddleware: responseMiddleware(traverse.default),
|
|
73
|
+
})
|
|
9
74
|
this.gql = imported.gql
|
|
10
75
|
} else {
|
|
11
76
|
this.client = null
|
|
@@ -44,7 +44,7 @@ export default async function (
|
|
|
44
44
|
case 'registry': {
|
|
45
45
|
const registry = (await contracts?.getRegistry()!).connect(signer)
|
|
46
46
|
|
|
47
|
-
return registry.setSubnodeRecord(
|
|
47
|
+
return registry.populateTransaction.setSubnodeRecord(
|
|
48
48
|
parentNodehash,
|
|
49
49
|
labelhash,
|
|
50
50
|
owner,
|
|
@@ -60,7 +60,7 @@ export default async function (
|
|
|
60
60
|
? generateFuseInput(wrapperArgs.fuses)
|
|
61
61
|
: '0'
|
|
62
62
|
|
|
63
|
-
return nameWrapper.setSubnodeRecord(
|
|
63
|
+
return nameWrapper.populateTransaction.setSubnodeRecord(
|
|
64
64
|
parentNodehash,
|
|
65
65
|
label,
|
|
66
66
|
owner,
|
|
@@ -2,9 +2,14 @@ import { ENS } from '..'
|
|
|
2
2
|
import setup from '../tests/setup'
|
|
3
3
|
|
|
4
4
|
let ENSInstance: ENS
|
|
5
|
+
let revert: Awaited<ReturnType<typeof setup>>['revert']
|
|
5
6
|
|
|
6
7
|
beforeAll(async () => {
|
|
7
|
-
;({ ENSInstance } = await setup())
|
|
8
|
+
;({ ENSInstance, revert } = await setup())
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
afterAll(async () => {
|
|
12
|
+
await revert()
|
|
8
13
|
})
|
|
9
14
|
|
|
10
15
|
const checkRecords = (
|
|
@@ -88,6 +93,16 @@ describe('getProfile', () => {
|
|
|
88
93
|
})
|
|
89
94
|
checkRecords(result)
|
|
90
95
|
})
|
|
96
|
+
it('should return a profile object for a specified resolver', async () => {
|
|
97
|
+
const result = await ENSInstance.getProfile('saganaki.xyz', {
|
|
98
|
+
resolverAddress: '0x12299799a50340fb860d276805e78550cbad3de3',
|
|
99
|
+
})
|
|
100
|
+
expect(result).toBeDefined()
|
|
101
|
+
expect(result?.address).toBe('0x157545BfD441453921049998128Ff090c1c11230')
|
|
102
|
+
expect(result?.resolverAddress).toBe(
|
|
103
|
+
'0x12299799a50340fb860d276805e78550cbad3de3',
|
|
104
|
+
)
|
|
105
|
+
})
|
|
91
106
|
it('should return undefined for an unregistered name', async () => {
|
|
92
107
|
const result = await ENSInstance.getProfile('test123123123cool.eth')
|
|
93
108
|
expect(result).toBeUndefined()
|