@snapshot-labs/snapshot.js 0.12.54 → 0.12.56

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.
@@ -30,8 +30,8 @@ interface validateSchemaOptions {
30
30
  export declare function validateSchema(schema: any, data: any, options?: validateSchemaOptions): true | import("ajv").ErrorObject<string, Record<string, any>, unknown>[] | null | undefined;
31
31
  export declare function getEnsTextRecord(ens: string, record: string, network?: string, options?: any): Promise<string | null>;
32
32
  export declare function getSpaceUri(id: string, network?: string, options?: any): Promise<string | null>;
33
- export declare function getEnsOwner(ens: string, network?: string, options?: any): Promise<string | null>;
34
- export declare function getSpaceController(id: string, network?: string, options?: any): Promise<string | null>;
33
+ export declare function getEnsOwner(ens: string, network?: string, options?: any): Promise<string>;
34
+ export declare function getSpaceController(id: string, network?: string, options?: any): Promise<string>;
35
35
  export declare function clone(item: any): any;
36
36
  export declare function sleep(time: any): Promise<unknown>;
37
37
  export declare function getNumberWithOrdinal(n: any): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapshot-labs/snapshot.js",
3
- "version": "0.12.54",
3
+ "version": "0.12.56",
4
4
  "repository": "snapshot-labs/snapshot.js",
5
5
  "license": "MIT",
6
6
  "main": "dist/snapshot.cjs.js",
package/src/networks.json CHANGED
@@ -1414,7 +1414,7 @@
1414
1414
  "multicall": "0xc454132B017b55b427f45078E335549A7124f5f7",
1415
1415
  "rpc": [],
1416
1416
  "explorer": {
1417
- "url": "https://explorer.curtis.apechain.com"
1417
+ "url": "https://curtis.apescan.io"
1418
1418
  },
1419
1419
  "start": 6661339,
1420
1420
  "logo": "ipfs://bafkreicljxttjq2xkgfwwpii5xegirgq2ctrnsjnzelxudjj33qzq65apu",
@@ -1429,7 +1429,7 @@
1429
1429
  "multicall": "0xcA11bde05977b3631167028862bE2a173976CA11",
1430
1430
  "rpc": [],
1431
1431
  "explorer": {
1432
- "url": "https://apechain.calderaexplorer.xyz"
1432
+ "url": "https://apescan.io"
1433
1433
  },
1434
1434
  "start": 20889,
1435
1435
  "logo": "ipfs://bafkreielbgcox2jsw3g6pqulqb7pyjgx7czjt6ahnibihaij6lozoy53w4"
@@ -1671,6 +1671,21 @@
1671
1671
  "logo": "ipfs://QmaxRoHpxZd8PqccAynherrMznMufG6sdmHZLihkECXmZv",
1672
1672
  "testnet": true
1673
1673
  },
1674
+ "314159": {
1675
+ "key": "314159",
1676
+ "name": "Filecoin Calibration Testnet",
1677
+ "shortName": "testnet",
1678
+ "chainId": 314159,
1679
+ "network": "testnet",
1680
+ "multicall": "0xcA11bde05977b3631167028862bE2a173976CA11",
1681
+ "rpc": [],
1682
+ "explorer": {
1683
+ "url": "https://calibration.filscan.io/en"
1684
+ },
1685
+ "start": 1446201,
1686
+ "logo": "ipfs://bafkreiffbopdjior7li3nlemzko7rjua6wd2hfh2vhdbenqbv4tfsbnzwu",
1687
+ "testnet": true
1688
+ },
1674
1689
  "686868": {
1675
1690
  "key": "686868",
1676
1691
  "name": "Merlin Testnet",
package/src/utils.spec.js CHANGED
@@ -10,6 +10,8 @@ import {
10
10
  getEnsTextRecord
11
11
  } from './utils';
12
12
 
13
+ const EMPTY_ADDRESS = '0x0000000000000000000000000000000000000000';
14
+
13
15
  vi.mock('cross-fetch', async () => {
14
16
  const actual = await vi.importActual('cross-fetch');
15
17
 
@@ -617,7 +619,13 @@ describe('utils', () => {
617
619
  describe('getEnsOwner', () => {
618
620
  test('should return null when the ENS is not valid', () => {
619
621
  // special hidden characters after the k
620
- expect(getEnsOwner('elonmusk‍‍.eth')).resolves.toBe(null);
622
+ expect(getEnsOwner('elonmusk‍‍.eth')).resolves.toBe(EMPTY_ADDRESS);
623
+ });
624
+
625
+ test('throw an error when the network is not supported', () => {
626
+ expect(getEnsOwner('shot.eth', '100')).rejects.toThrow(
627
+ 'Network not supported'
628
+ );
621
629
  });
622
630
  });
623
631
 
package/src/utils.ts CHANGED
@@ -30,6 +30,15 @@ interface Strategy {
30
30
  params: any;
31
31
  }
32
32
 
33
+ type DomainType = 'ens' | 'tld' | 'other-tld' | 'subdomain';
34
+
35
+ const MUTED_ERRORS = [
36
+ // mute error from coinbase, when the subdomain is not found
37
+ // most other resolvers just return an empty address
38
+ 'response not found during CCIP fetch',
39
+ // mute error from missing offchain resolver (mostly for sepolia)
40
+ 'UNSUPPORTED_OPERATION'
41
+ ];
33
42
  const ENS_REGISTRY = '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e';
34
43
  const ENS_ABI = [
35
44
  'function text(bytes32 node, string calldata key) external view returns (string memory)',
@@ -219,6 +228,45 @@ ajv.addFormat('domain', {
219
228
  }
220
229
  });
221
230
 
231
+ function getDomainType(domain: string): DomainType {
232
+ const isEns = domain.endsWith('.eth');
233
+
234
+ const tokens = domain.split('.');
235
+
236
+ if (tokens.length === 1) return 'tld';
237
+ else if (tokens.length === 2 && !isEns) return 'other-tld';
238
+ else if (tokens.length > 2) return 'subdomain';
239
+ else if (isEns) return 'ens';
240
+ else throw new Error('Invalid domain');
241
+ }
242
+
243
+ // see https://docs.ens.domains/registry/dns#gasless-import
244
+ async function getDNSOwner(domain: string): Promise<string> {
245
+ const response = await fetch(
246
+ `https://cloudflare-dns.com/dns-query?name=${domain}&type=TXT`,
247
+ {
248
+ headers: {
249
+ accept: 'application/dns-json'
250
+ }
251
+ }
252
+ );
253
+
254
+ const data = await response.json();
255
+ // Error list: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
256
+ if (data.Status === 3) return EMPTY_ADDRESS;
257
+ if (data.Status !== 0) throw new Error('Failed to fetch DNS Owner');
258
+
259
+ const ownerRecord = data.Answer?.find((record: any) =>
260
+ record.data.includes('ENS1')
261
+ );
262
+
263
+ if (!ownerRecord) return EMPTY_ADDRESS;
264
+
265
+ return getAddress(
266
+ ownerRecord.data.replace(new RegExp('"', 'g'), '').split(' ').pop()
267
+ );
268
+ }
269
+
222
270
  export async function call(provider, abi: any[], call: any[], options?) {
223
271
  const contract = new Contract(call[0], abi, provider);
224
272
  try {
@@ -611,7 +659,12 @@ export async function getEnsOwner(
611
659
  ens: string,
612
660
  network = '1',
613
661
  options: any = {}
614
- ): Promise<string | null> {
662
+ ): Promise<string> {
663
+ if (!networks[network]?.ensResolvers?.length) {
664
+ throw new Error('Network not supported');
665
+ }
666
+
667
+ const domainType = getDomainType(ens);
615
668
  const provider = getProvider(network, options);
616
669
  const ensRegistry = new Contract(
617
670
  ENS_REGISTRY,
@@ -624,7 +677,7 @@ export async function getEnsOwner(
624
677
  try {
625
678
  ensHash = namehash(ensNormalize(ens));
626
679
  } catch (e: any) {
627
- return null;
680
+ return EMPTY_ADDRESS;
628
681
  }
629
682
 
630
683
  const ensNameWrapper =
@@ -639,14 +692,35 @@ export async function getEnsOwner(
639
692
  );
640
693
  owner = await ensNameWrapperContract.ownerOf(ensHash);
641
694
  }
642
- return owner;
695
+
696
+ if (owner === EMPTY_ADDRESS && domainType === 'other-tld') {
697
+ const resolvedAddress = await provider.resolveName(ens);
698
+
699
+ // Filter out domains with valid TXT records, but not imported
700
+ if (resolvedAddress) {
701
+ owner = await getDNSOwner(ens);
702
+ }
703
+ }
704
+
705
+ if (owner === EMPTY_ADDRESS && domainType === 'subdomain') {
706
+ try {
707
+ owner = await provider.resolveName(ens);
708
+ } catch (e: any) {
709
+ if (MUTED_ERRORS.every((error) => !e.message.includes(error))) {
710
+ throw e;
711
+ }
712
+ owner = EMPTY_ADDRESS;
713
+ }
714
+ }
715
+
716
+ return owner || EMPTY_ADDRESS;
643
717
  }
644
718
 
645
719
  export async function getSpaceController(
646
720
  id: string,
647
721
  network = '1',
648
722
  options: any = {}
649
- ): Promise<string | null> {
723
+ ): Promise<string> {
650
724
  const spaceUri = await getSpaceUri(id, network, options);
651
725
  if (spaceUri) {
652
726
  let isUriAddress = isAddress(spaceUri);