UNPKG

@fuel-infrastructure/fuel-hyperlane-registry

Version:

A collection of configs, artifacts, and schemas for Hyperlane

111 lines (110 loc) 4.6 kB
import { objMerge } from '../utils.js'; import { RegistryType, } from './IRegistry.js'; /** * A registry that accepts multiple sub-registries. * Read methods are performed on all sub-registries and the results are merged. * Write methods are performed on all sub-registries. * Can be created manually or by calling `.merge()` on an existing registry. */ export class MergedRegistry { type = RegistryType.Merged; uri = '__merged_registry__'; registries; logger; constructor({ registries, logger }) { if (!registries.length) throw new Error('At least one registry URI is required'); this.registries = registries; // @ts-ignore this.logger = logger || console; } getUri() { throw new Error('getUri method not applicable to MergedRegistry'); } async listRegistryContent() { const results = await this.multiRegistryRead((r) => r.listRegistryContent()); return results.reduce((acc, content) => objMerge(acc, content), { chains: {}, deployments: { warpRoutes: {}, warpDeployConfig: {} }, }); } async getChains() { return Object.keys(await this.getMetadata()); } async getMetadata() { const results = await this.multiRegistryRead((r) => r.getMetadata()); return results.reduce((acc, content) => objMerge(acc, content), {}); } async getChainMetadata(chainName) { return (await this.getMetadata())[chainName] || null; } async getAddresses() { const results = await this.multiRegistryRead((r) => r.getAddresses()); return results.reduce((acc, content) => objMerge(acc, content), {}); } async getChainAddresses(chainName) { return (await this.getAddresses())[chainName] || null; } async getChainLogoUri(chainName) { const results = await this.multiRegistryRead((r) => r.getChainLogoUri(chainName)); return results.find((uri) => !!uri) || null; } async addChain(chain) { return this.multiRegistryWrite(async (registry) => await registry.addChain(chain), `adding chain ${chain.chainName}`); } async updateChain(chain) { return this.multiRegistryWrite(async (registry) => await registry.updateChain(chain), `updating chain ${chain.chainName}`); } async removeChain(chain) { return this.multiRegistryWrite(async (registry) => await registry.removeChain(chain), `removing chain ${chain}`); } async getWarpRoute(id) { const results = await this.multiRegistryRead((r) => r.getWarpRoute(id)); return results.find((r) => !!r) || null; } async getWarpDeployConfig(id) { const results = await this.multiRegistryRead((r) => r.getWarpDeployConfig(id)); return results.find((r) => !!r) || null; } async getWarpRoutes(filter) { const results = await this.multiRegistryRead((r) => r.getWarpRoutes(filter)); return results.reduce((acc, content) => objMerge(acc, content), {}); } async getWarpDeployConfigs(filter) { const results = await this.multiRegistryRead((r) => r.getWarpDeployConfigs(filter)); return results.reduce((acc, content) => objMerge(acc, content), {}); } async addWarpRoute(config, options) { return this.multiRegistryWrite(async (registry) => await registry.addWarpRoute(config, options), 'adding warp route'); } multiRegistryRead(readFn) { return Promise.all(this.registries.map(readFn)); } async multiRegistryWrite(writeFn, logMsg) { for (const registry of this.registries) { // TODO remove this when GithubRegistry supports write methods if (registry.type === RegistryType.Github) { this.logger.warn(`Skipping ${logMsg} at ${registry.type} registry`); continue; } try { this.logger.info(`Now ${logMsg} at ${registry.type} registry at ${registry.uri}`); await writeFn(registry); this.logger.info(`Done ${logMsg} at ${registry.type} registry`); } catch (error) { // To prevent loss of artifacts, MergedRegistry write methods are failure tolerant this.logger.error(`Failure ${logMsg} at ${registry.type} registry`, error); } } } merge(otherRegistry) { return new MergedRegistry({ registries: [...this.registries, otherRegistry], logger: this.logger, }); } }