@hyperlane-xyz/registry 1.1.1 → 1.2.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.
@@ -261,6 +261,24 @@ export declare const chainAddresses: {
261
261
  timelockController: string;
262
262
  validatorAnnounce: string;
263
263
  };
264
+ holesky: {
265
+ mailbox: string;
266
+ proxyAdmin: string;
267
+ validatorAnnounce: string;
268
+ testRecipient: string;
269
+ staticMerkleRootMultisigIsmFactory: string;
270
+ staticMessageIdMultisigIsmFactory: string;
271
+ staticAggregationIsmFactory: string;
272
+ staticAggregationHookFactory: string;
273
+ domainRoutingIsmFactory: string;
274
+ interchainSecurityModule: string;
275
+ merkleTreeHook: string;
276
+ fallbackRoutingHook: string;
277
+ pausableHook: string;
278
+ storageGasOracle: string;
279
+ interchainGasPaymaster: string;
280
+ protocolFee: string;
281
+ };
264
282
  inevm: {
265
283
  aggregationHook: string;
266
284
  domainRoutingIsm: string;
@@ -261,6 +261,24 @@ export const chainAddresses = {
261
261
  "timelockController": "0x0000000000000000000000000000000000000000",
262
262
  "validatorAnnounce": "0x87ED6926abc9E38b9C7C19f835B41943b622663c"
263
263
  },
264
+ "holesky": {
265
+ "mailbox": "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc",
266
+ "proxyAdmin": "0x33dB966328Ea213b0f76eF96CA368AB37779F065",
267
+ "validatorAnnounce": "0xAb9B273366D794B7F80B4378bc8Aaca75C6178E2",
268
+ "testRecipient": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD",
269
+ "staticMerkleRootMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2",
270
+ "staticMessageIdMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039",
271
+ "staticAggregationIsmFactory": "0x54148470292C24345fb828B003461a9444414517",
272
+ "staticAggregationHookFactory": "0x589C201a07c26b4725A4A829d772f24423da480B",
273
+ "domainRoutingIsmFactory": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD",
274
+ "interchainSecurityModule": "0x751f2b684EeBb916dB777767CCb8fd793C8b2956",
275
+ "merkleTreeHook": "0x98AAE089CaD930C64a76dD2247a2aC5773a4B8cE",
276
+ "fallbackRoutingHook": "0x07009DA2249c388aD0f416a235AfE90D784e1aAc",
277
+ "pausableHook": "0xF7561c34f17A32D5620583A3397C304e7038a7F6",
278
+ "storageGasOracle": "0x2b2a158B4059C840c7aC67399B153bb567D06303",
279
+ "interchainGasPaymaster": "0x5CBf4e70448Ed46c2616b04e9ebc72D29FF0cfA9",
280
+ "protocolFee": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C"
281
+ },
264
282
  "inevm": {
265
283
  "aggregationHook": "0xe0dDb5dE7D52918237cC1Ae131F29dcAbcb0F62B",
266
284
  "domainRoutingIsm": "0xBD70Ea9D599a0FC8158B026797177773C3445730",
@@ -485,6 +485,36 @@ export const chainMetadata = {
485
485
  }
486
486
  ]
487
487
  },
488
+ "holesky": {
489
+ "blockExplorers": [
490
+ {
491
+ "apiUrl": "https://api-holesky.etherscan.io/api",
492
+ "family": "etherscan",
493
+ "name": "Etherscan",
494
+ "url": "https://holesky.etherscan.io"
495
+ }
496
+ ],
497
+ "blocks": {
498
+ "confirmations": 1,
499
+ "estimateBlockTime": 13,
500
+ "reorgPeriod": 2
501
+ },
502
+ "name": "holesky",
503
+ "chainId": 17000,
504
+ "isTestnet": true,
505
+ "domainId": 17000,
506
+ "protocol": "ethereum",
507
+ "nativeToken": {
508
+ "decimals": 18,
509
+ "name": "Ether",
510
+ "symbol": "ETH"
511
+ },
512
+ "rpcUrls": [
513
+ {
514
+ "http": "https://ethereum-holesky-rpc.publicnode.com"
515
+ }
516
+ ]
517
+ },
488
518
  "inevm": {
489
519
  "blockExplorers": [
490
520
  {
@@ -0,0 +1,18 @@
1
+ export declare const addresses: {
2
+ mailbox: string;
3
+ proxyAdmin: string;
4
+ validatorAnnounce: string;
5
+ testRecipient: string;
6
+ staticMerkleRootMultisigIsmFactory: string;
7
+ staticMessageIdMultisigIsmFactory: string;
8
+ staticAggregationIsmFactory: string;
9
+ staticAggregationHookFactory: string;
10
+ domainRoutingIsmFactory: string;
11
+ interchainSecurityModule: string;
12
+ merkleTreeHook: string;
13
+ fallbackRoutingHook: string;
14
+ pausableHook: string;
15
+ storageGasOracle: string;
16
+ interchainGasPaymaster: string;
17
+ protocolFee: string;
18
+ };
@@ -0,0 +1,18 @@
1
+ export const addresses = {
2
+ "mailbox": "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc",
3
+ "proxyAdmin": "0x33dB966328Ea213b0f76eF96CA368AB37779F065",
4
+ "validatorAnnounce": "0xAb9B273366D794B7F80B4378bc8Aaca75C6178E2",
5
+ "testRecipient": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD",
6
+ "staticMerkleRootMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2",
7
+ "staticMessageIdMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039",
8
+ "staticAggregationIsmFactory": "0x54148470292C24345fb828B003461a9444414517",
9
+ "staticAggregationHookFactory": "0x589C201a07c26b4725A4A829d772f24423da480B",
10
+ "domainRoutingIsmFactory": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD",
11
+ "interchainSecurityModule": "0x751f2b684EeBb916dB777767CCb8fd793C8b2956",
12
+ "merkleTreeHook": "0x98AAE089CaD930C64a76dD2247a2aC5773a4B8cE",
13
+ "fallbackRoutingHook": "0x07009DA2249c388aD0f416a235AfE90D784e1aAc",
14
+ "pausableHook": "0xF7561c34f17A32D5620583A3397C304e7038a7F6",
15
+ "storageGasOracle": "0x2b2a158B4059C840c7aC67399B153bb567D06303",
16
+ "interchainGasPaymaster": "0x5CBf4e70448Ed46c2616b04e9ebc72D29FF0cfA9",
17
+ "protocolFee": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C"
18
+ };
@@ -0,0 +1,18 @@
1
+ {
2
+ "mailbox": "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc",
3
+ "proxyAdmin": "0x33dB966328Ea213b0f76eF96CA368AB37779F065",
4
+ "validatorAnnounce": "0xAb9B273366D794B7F80B4378bc8Aaca75C6178E2",
5
+ "testRecipient": "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD",
6
+ "staticMerkleRootMultisigIsmFactory": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2",
7
+ "staticMessageIdMultisigIsmFactory": "0x6966b0E55883d49BFB24539356a2f8A673E02039",
8
+ "staticAggregationIsmFactory": "0x54148470292C24345fb828B003461a9444414517",
9
+ "staticAggregationHookFactory": "0x589C201a07c26b4725A4A829d772f24423da480B",
10
+ "domainRoutingIsmFactory": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD",
11
+ "interchainSecurityModule": "0x751f2b684EeBb916dB777767CCb8fd793C8b2956",
12
+ "merkleTreeHook": "0x98AAE089CaD930C64a76dD2247a2aC5773a4B8cE",
13
+ "fallbackRoutingHook": "0x07009DA2249c388aD0f416a235AfE90D784e1aAc",
14
+ "pausableHook": "0xF7561c34f17A32D5620583A3397C304e7038a7F6",
15
+ "storageGasOracle": "0x2b2a158B4059C840c7aC67399B153bb567D06303",
16
+ "interchainGasPaymaster": "0x5CBf4e70448Ed46c2616b04e9ebc72D29FF0cfA9",
17
+ "protocolFee": "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C"
18
+ }
@@ -0,0 +1,16 @@
1
+ mailbox: "0x46f7C5D896bbeC89bE1B19e4485e59b4Be49e9Cc"
2
+ proxyAdmin: "0x33dB966328Ea213b0f76eF96CA368AB37779F065"
3
+ validatorAnnounce: "0xAb9B273366D794B7F80B4378bc8Aaca75C6178E2"
4
+ testRecipient: "0x86fb9F1c124fB20ff130C41a79a432F770f67AFD"
5
+ staticMerkleRootMultisigIsmFactory: "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2"
6
+ staticMessageIdMultisigIsmFactory: "0x6966b0E55883d49BFB24539356a2f8A673E02039"
7
+ staticAggregationIsmFactory: "0x54148470292C24345fb828B003461a9444414517"
8
+ staticAggregationHookFactory: "0x589C201a07c26b4725A4A829d772f24423da480B"
9
+ domainRoutingIsmFactory: "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD"
10
+ interchainSecurityModule: "0x751f2b684EeBb916dB777767CCb8fd793C8b2956"
11
+ merkleTreeHook: "0x98AAE089CaD930C64a76dD2247a2aC5773a4B8cE"
12
+ fallbackRoutingHook: "0x07009DA2249c388aD0f416a235AfE90D784e1aAc"
13
+ pausableHook: "0xF7561c34f17A32D5620583A3397C304e7038a7F6"
14
+ storageGasOracle: "0x2b2a158B4059C840c7aC67399B153bb567D06303"
15
+ interchainGasPaymaster: "0x5CBf4e70448Ed46c2616b04e9ebc72D29FF0cfA9"
16
+ protocolFee: "0x6b1bb4ce664Bb4164AEB4d3D2E7DE7450DD8084C"
@@ -0,0 +1,2 @@
1
+ export { metadata } from './metadata.js';
2
+ export { addresses } from './addresses.js';
@@ -0,0 +1,2 @@
1
+ export { metadata } from './metadata.js';
2
+ export { addresses } from './addresses.js';
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" fill-rule="evenodd" clip-rule="evenodd" viewBox="-150 0 1100 1277.4"><g fill-rule="nonzero"><path fill="#343434" d="m392.1 0-8.6 29.1v844.6l8.6 8.6 392-231.8z"/><path fill="#8C8C8C" d="M392.1 0 0 650.5l392.1 231.8v-410z"/><path fill="#3C3C3B" d="m392.1 956.5-4.9 5.9v300.9l4.9 14.1 392.3-552.5z"/><path fill="#8C8C8C" d="M392.1 1277.4V956.5L0 724.9z"/><path fill="#141414" d="m392.1 882.3 392-231.8-392-178.2z"/><path fill="#393939" d="m0 650.5 392.1 231.8v-410z"/></g></svg>
@@ -0,0 +1,2 @@
1
+ import type { ChainMetadata } from '@hyperlane-xyz/sdk';
2
+ export declare const metadata: ChainMetadata;
@@ -0,0 +1,30 @@
1
+ export const metadata = {
2
+ "blockExplorers": [
3
+ {
4
+ "apiUrl": "https://api-holesky.etherscan.io/api",
5
+ "family": "etherscan",
6
+ "name": "Etherscan",
7
+ "url": "https://holesky.etherscan.io"
8
+ }
9
+ ],
10
+ "blocks": {
11
+ "confirmations": 1,
12
+ "estimateBlockTime": 13,
13
+ "reorgPeriod": 2
14
+ },
15
+ "name": "holesky",
16
+ "chainId": 17000,
17
+ "isTestnet": true,
18
+ "domainId": 17000,
19
+ "protocol": "ethereum",
20
+ "nativeToken": {
21
+ "decimals": 18,
22
+ "name": "Ether",
23
+ "symbol": "ETH"
24
+ },
25
+ "rpcUrls": [
26
+ {
27
+ "http": "https://ethereum-holesky-rpc.publicnode.com"
28
+ }
29
+ ]
30
+ };
@@ -0,0 +1,30 @@
1
+ {
2
+ "blockExplorers": [
3
+ {
4
+ "apiUrl": "https://api-holesky.etherscan.io/api",
5
+ "family": "etherscan",
6
+ "name": "Etherscan",
7
+ "url": "https://holesky.etherscan.io"
8
+ }
9
+ ],
10
+ "blocks": {
11
+ "confirmations": 1,
12
+ "estimateBlockTime": 13,
13
+ "reorgPeriod": 2
14
+ },
15
+ "name": "holesky",
16
+ "chainId": 17000,
17
+ "isTestnet": true,
18
+ "domainId": 17000,
19
+ "protocol": "ethereum",
20
+ "nativeToken": {
21
+ "decimals": 18,
22
+ "name": "Ether",
23
+ "symbol": "ETH"
24
+ },
25
+ "rpcUrls": [
26
+ {
27
+ "http": "https://ethereum-holesky-rpc.publicnode.com"
28
+ }
29
+ ]
30
+ }
@@ -0,0 +1,21 @@
1
+ # yaml-language-server: $schema=../schema.json
2
+ blockExplorers:
3
+ - apiUrl: https://api-holesky.etherscan.io/api
4
+ family: etherscan
5
+ name: Etherscan
6
+ url: https://holesky.etherscan.io
7
+ blocks:
8
+ confirmations: 1
9
+ estimateBlockTime: 13
10
+ reorgPeriod: 2
11
+ name: holesky
12
+ chainId: 17000
13
+ isTestnet: true
14
+ domainId: 17000
15
+ protocol: ethereum
16
+ nativeToken:
17
+ decimals: 18
18
+ name: Ether
19
+ symbol: ETH
20
+ rpcUrls:
21
+ - http: https://ethereum-holesky-rpc.publicnode.com
package/dist/index.d.ts CHANGED
@@ -34,6 +34,8 @@ export { metadata as fuji } from './chains/fuji/metadata.js';
34
34
  export { addresses as fujiAddresses } from './chains/fuji/addresses.js';
35
35
  export { metadata as gnosis } from './chains/gnosis/metadata.js';
36
36
  export { addresses as gnosisAddresses } from './chains/gnosis/addresses.js';
37
+ export { metadata as holesky } from './chains/holesky/metadata.js';
38
+ export { addresses as holeskyAddresses } from './chains/holesky/addresses.js';
37
39
  export { metadata as inevm } from './chains/inevm/metadata.js';
38
40
  export { addresses as inevmAddresses } from './chains/inevm/addresses.js';
39
41
  export { metadata as injective } from './chains/injective/metadata.js';
package/dist/index.js CHANGED
@@ -34,6 +34,8 @@ export { metadata as fuji } from './chains/fuji/metadata.js';
34
34
  export { addresses as fujiAddresses } from './chains/fuji/addresses.js';
35
35
  export { metadata as gnosis } from './chains/gnosis/metadata.js';
36
36
  export { addresses as gnosisAddresses } from './chains/gnosis/addresses.js';
37
+ export { metadata as holesky } from './chains/holesky/metadata.js';
38
+ export { addresses as holeskyAddresses } from './chains/holesky/addresses.js';
37
39
  export { metadata as inevm } from './chains/inevm/metadata.js';
38
40
  export { addresses as inevmAddresses } from './chains/inevm/addresses.js';
39
41
  export { metadata as injective } from './chains/injective/metadata.js';
@@ -9,7 +9,9 @@ export declare abstract class BaseRegistry implements IRegistry {
9
9
  protected readonly logger: Logger;
10
10
  protected listContentCache?: RegistryContent;
11
11
  protected metadataCache?: ChainMap<ChainMetadata>;
12
+ protected isMetadataCacheFull: boolean;
12
13
  protected addressCache?: ChainMap<ChainAddresses>;
14
+ protected isAddressCacheFull: boolean;
13
15
  constructor({ uri, logger }: {
14
16
  uri: string;
15
17
  logger?: Logger;
@@ -25,6 +27,7 @@ export declare abstract class BaseRegistry implements IRegistry {
25
27
  abstract getChainMetadata(chainName: ChainName): MaybePromise<ChainMetadata | null>;
26
28
  abstract getAddresses(): MaybePromise<ChainMap<ChainAddresses>>;
27
29
  abstract getChainAddresses(chainName: ChainName): MaybePromise<ChainAddresses | null>;
30
+ getChainLogoUri(chainName: ChainName): Promise<string | null>;
28
31
  abstract addChain(chain: {
29
32
  chainName: ChainName;
30
33
  metadata?: ChainMetadata;
@@ -1,11 +1,13 @@
1
- export const CHAIN_FILE_REGEX = /chains\/([a-z0-9]+)\/([a-z]+)\.yaml/;
1
+ export const CHAIN_FILE_REGEX = /chains\/([a-z0-9]+)\/([a-z]+)\.(yaml|svg)/;
2
2
  export class BaseRegistry {
3
3
  uri;
4
4
  logger;
5
5
  // Caches
6
6
  listContentCache;
7
7
  metadataCache;
8
+ isMetadataCacheFull = false;
8
9
  addressCache;
10
+ isAddressCacheFull = false;
9
11
  constructor({ uri, logger }) {
10
12
  this.uri = uri;
11
13
  // @ts-ignore forcing in to avoid a @hyperlane-xyz/utils
@@ -30,4 +32,9 @@ export class BaseRegistry {
30
32
  const basePath = `deployments/warp_routes/${symbol}/${chains}`;
31
33
  return { configPath: `${basePath}-config.yaml`, addressesPath: `${basePath}-addresses.yaml` };
32
34
  }
35
+ async getChainLogoUri(chainName) {
36
+ const registryContent = await this.listRegistryContent();
37
+ const chain = registryContent.chains[chainName];
38
+ return chain?.logo ?? null;
39
+ }
33
40
  }
@@ -19,9 +19,9 @@ export declare class GithubRegistry extends BaseRegistry implements IRegistry {
19
19
  listRegistryContent(): Promise<RegistryContent>;
20
20
  getChains(): Promise<Array<ChainName>>;
21
21
  getMetadata(): Promise<ChainMap<ChainMetadata>>;
22
- getChainMetadata(chainName: ChainName): Promise<ChainMetadata>;
22
+ getChainMetadata(chainName: ChainName): Promise<ChainMetadata | null>;
23
23
  getAddresses(): Promise<ChainMap<ChainAddresses>>;
24
- getChainAddresses(chainName: ChainName): Promise<ChainAddresses>;
24
+ getChainAddresses(chainName: ChainName): Promise<ChainAddresses | null>;
25
25
  addChain(_chains: {
26
26
  chainName: ChainName;
27
27
  metadata?: ChainMetadata;
@@ -35,6 +35,7 @@ export declare class GithubRegistry extends BaseRegistry implements IRegistry {
35
35
  removeChain(_chains: ChainName): Promise<void>;
36
36
  addWarpRoute(_config: WarpCoreConfig): Promise<void>;
37
37
  protected getRawContentUrl(path: string): string;
38
- protected fetchChainFiles<T>(fileName: keyof ChainFiles): Promise<ChainMap<T>>;
38
+ protected fetchChainFiles<T>(fileName: keyof ChainFiles, chainNames?: ChainName[]): Promise<ChainMap<T>>;
39
+ protected fetchSingleChainFile<T>(fileName: keyof ChainFiles, chainName: ChainName): Promise<T | null>;
39
40
  protected fetch(url: string): Promise<Response>;
40
41
  }
@@ -1,6 +1,5 @@
1
1
  import { parse as yamlParse } from 'yaml';
2
2
  import { DEFAULT_GITHUB_REGISTRY, GITHUB_FETCH_CONCURRENCY_LIMIT } from '../consts.js';
3
- import { ChainAddressesSchema } from '../types.js';
4
3
  import { concurrentMap } from '../utils.js';
5
4
  import { BaseRegistry, CHAIN_FILE_REGEX } from './BaseRegistry.js';
6
5
  import { RegistryType, } from './IRegistry.js';
@@ -33,10 +32,10 @@ export class GithubRegistry extends BaseRegistry {
33
32
  const chains = {};
34
33
  for (const node of tree) {
35
34
  if (CHAIN_FILE_REGEX.test(node.path)) {
36
- const [_, chainName, fileName] = node.path.match(CHAIN_FILE_REGEX);
35
+ const [_, chainName, fileName, extension] = node.path.match(CHAIN_FILE_REGEX);
37
36
  chains[chainName] ??= {};
38
37
  // @ts-ignore allow dynamic key assignment
39
- chains[chainName][fileName] = this.getRawContentUrl(`${chainPath}/${chainName}/${fileName}.yaml`);
38
+ chains[chainName][fileName] = this.getRawContentUrl(`${chainPath}/${chainName}/${fileName}.${extension}`);
40
39
  }
41
40
  // TODO add handling for deployment artifact files here too
42
41
  }
@@ -47,32 +46,36 @@ export class GithubRegistry extends BaseRegistry {
47
46
  return Object.keys(repoContents.chains);
48
47
  }
49
48
  async getMetadata() {
50
- if (this.metadataCache)
49
+ if (this.metadataCache && this.isMetadataCacheFull)
51
50
  return this.metadataCache;
52
51
  const chainMetadata = await this.fetchChainFiles('metadata');
52
+ this.isMetadataCacheFull = true;
53
53
  return (this.metadataCache = chainMetadata);
54
54
  }
55
55
  async getChainMetadata(chainName) {
56
56
  if (this.metadataCache?.[chainName])
57
57
  return this.metadataCache[chainName];
58
- const url = this.getRawContentUrl(`${this.getChainsPath()}/${chainName}/metadata.yaml`);
59
- const response = await this.fetch(url);
60
- const data = await response.text();
61
- return yamlParse(data);
58
+ const data = await this.fetchSingleChainFile('metadata', chainName);
59
+ if (!data)
60
+ return null;
61
+ this.metadataCache = { ...this.metadataCache, [chainName]: data };
62
+ return data;
62
63
  }
63
64
  async getAddresses() {
64
- if (this.addressCache)
65
+ if (this.addressCache && this.isAddressCacheFull)
65
66
  return this.addressCache;
66
67
  const chainAddresses = await this.fetchChainFiles('addresses');
68
+ this.isAddressCacheFull = true;
67
69
  return (this.addressCache = chainAddresses);
68
70
  }
69
71
  async getChainAddresses(chainName) {
70
72
  if (this.addressCache?.[chainName])
71
73
  return this.addressCache[chainName];
72
- const url = this.getRawContentUrl(`${this.getChainsPath()}/${chainName}/addresses.yaml`);
73
- const response = await this.fetch(url);
74
- const data = await response.text();
75
- return ChainAddressesSchema.parse(yamlParse(data));
74
+ const data = await this.fetchSingleChainFile('addresses', chainName);
75
+ if (!data)
76
+ return null;
77
+ this.addressCache = { ...this.addressCache, [chainName]: data };
78
+ return data;
76
79
  }
77
80
  async addChain(_chains) {
78
81
  throw new Error('TODO: Implement');
@@ -89,9 +92,11 @@ export class GithubRegistry extends BaseRegistry {
89
92
  getRawContentUrl(path) {
90
93
  return `https://raw.githubusercontent.com/${this.repoOwner}/${this.repoName}/${this.branch}/${path}`;
91
94
  }
92
- async fetchChainFiles(fileName) {
95
+ // Fetches all files of a particular type in parallel
96
+ // Defaults to all known chains if chainNames is not provided
97
+ async fetchChainFiles(fileName, chainNames) {
93
98
  const repoContents = await this.listRegistryContent();
94
- const chainNames = Object.keys(repoContents.chains);
99
+ chainNames ||= Object.keys(repoContents.chains);
95
100
  const fileUrls = chainNames.reduce((acc, chainName) => {
96
101
  const fileUrl = repoContents.chains[chainName][fileName];
97
102
  if (fileUrl)
@@ -105,6 +110,10 @@ export class GithubRegistry extends BaseRegistry {
105
110
  });
106
111
  return Object.fromEntries(results);
107
112
  }
113
+ async fetchSingleChainFile(fileName, chainName) {
114
+ const results = await this.fetchChainFiles(fileName, [chainName]);
115
+ return results[chainName] ?? null;
116
+ }
108
117
  async fetch(url) {
109
118
  this.logger.debug(`Fetching from github: ${url}`);
110
119
  const response = await fetch(url);
@@ -3,6 +3,7 @@ import type { ChainAddresses, MaybePromise } from '../types.js';
3
3
  export interface ChainFiles {
4
4
  metadata?: string;
5
5
  addresses?: string;
6
+ logo?: string;
6
7
  }
7
8
  export interface RegistryContent {
8
9
  chains: ChainMap<ChainFiles>;
@@ -21,6 +22,7 @@ export interface IRegistry {
21
22
  getChainMetadata(chainName: ChainName): MaybePromise<ChainMetadata | null>;
22
23
  getAddresses(): MaybePromise<ChainMap<ChainAddresses>>;
23
24
  getChainAddresses(chainName: ChainName): MaybePromise<ChainAddresses | null>;
25
+ getChainLogoUri(chainName: ChainName): Promise<string | null>;
24
26
  addChain(chain: {
25
27
  chainName: ChainName;
26
28
  metadata?: ChainMetadata;
@@ -13,9 +13,9 @@ export declare class LocalRegistry extends BaseRegistry implements IRegistry {
13
13
  listRegistryContent(): RegistryContent;
14
14
  getChains(): Array<ChainName>;
15
15
  getMetadata(): ChainMap<ChainMetadata>;
16
- getChainMetadata(chainName: ChainName): ChainMetadata;
16
+ getChainMetadata(chainName: ChainName): ChainMetadata | null;
17
17
  getAddresses(): ChainMap<ChainAddresses>;
18
- getChainAddresses(chainName: ChainName): ChainAddresses;
18
+ getChainAddresses(chainName: ChainName): ChainAddresses | null;
19
19
  addChain(chain: {
20
20
  chainName: ChainName;
21
21
  metadata?: ChainMetadata;
@@ -47,9 +47,7 @@ export class LocalRegistry extends BaseRegistry {
47
47
  }
48
48
  getChainMetadata(chainName) {
49
49
  const metadata = this.getMetadata();
50
- if (!metadata[chainName])
51
- throw new Error(`Metadata not found in registry for chain: ${chainName}`);
52
- return metadata[chainName];
50
+ return metadata[chainName] ?? null;
53
51
  }
54
52
  getAddresses() {
55
53
  if (this.addressCache)
@@ -66,9 +64,7 @@ export class LocalRegistry extends BaseRegistry {
66
64
  }
67
65
  getChainAddresses(chainName) {
68
66
  const addresses = this.getAddresses();
69
- if (!addresses[chainName])
70
- throw new Error(`Addresses not found in registry for chain: ${chainName}`);
71
- return addresses[chainName];
67
+ return addresses[chainName] ?? null;
72
68
  }
73
69
  addChain(chain) {
74
70
  const currentChains = this.listRegistryContent().chains;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hyperlane-xyz/registry",
3
3
  "description": "A collection of configs, artifacts, and schemas for Hyperlane",
4
- "version": "1.1.1",
4
+ "version": "1.2.0",
5
5
  "dependencies": {
6
6
  "yaml": "^2",
7
7
  "zod": "^3.21.2"