@hyperlane-xyz/registry
Version:
A collection of configs, artifacts, and schemas for Hyperlane
114 lines (113 loc) • 5.06 kB
JavaScript
import { assert, objFilter, objLength } from '@hyperlane-xyz/utils';
import { WARP_ROUTE_ID_REGEX } from '../consts.js';
import { stripLeadingSlash } from '../utils.js';
import { MergedRegistry } from './MergedRegistry.js';
import { createWarpRouteConfigId } from './warp-utils.js';
export class BaseRegistry {
uri;
logger;
// Caches
listContentCache;
metadataCache;
isMetadataCacheFull = false;
addressCache;
isAddressCacheFull = false;
warpRouteCache;
isWarpRouteCacheFull = false;
constructor({ uri, logger }) {
this.uri = uri;
// @ts-ignore forcing in to avoid a @hyperlane-xyz/utils
// dependency here, which could bloat consumer bundles
// unnecessarily (e.g. they just want metadata)
this.logger = logger || console;
}
getUri(itemPath) {
if (itemPath)
itemPath = stripLeadingSlash(itemPath);
return itemPath ? `${this.uri}/${itemPath}` : this.uri;
}
getChainsPath() {
return 'chains';
}
getWarpRoutesPath() {
return 'deployments/warp_routes';
}
/**
* Generates a warp route ID from a warp core config.
*
* The function handles three main cases:
* 1. If a warpRouteId is provided in options, it uses that directly
* 2. If there is exactly one synthetic token, it uses that token's chain and symbol
* 3. Otherwise, it uses all chains and requires a single symbol (either from options or tokens)
*/
static warpRouteConfigToId(config, options) {
assert(config?.tokens?.length > 0, 'Cannot generate ID for empty warp config');
const syntheticTokens = config.tokens.filter((token) => token.standard?.includes('Synthetic'));
let warpRouteId;
if (options && 'warpRouteId' in options) {
warpRouteId = options.warpRouteId;
}
else if (syntheticTokens.length === 1) {
const syntheticChain = syntheticTokens[0].chainName;
const syntheticSymbol = syntheticTokens[0].symbol;
const symbol = options?.symbol || syntheticSymbol;
warpRouteId = createWarpRouteConfigId(symbol, syntheticChain);
}
else {
// Only support one symbol per warp config for now
const allChains = config.tokens.map((token) => token.chainName);
const allSymbols = new Set(config.tokens.map((token) => token.symbol));
if (!options?.symbol && allSymbols.size !== 1) {
throw new Error(`Only one token symbol per warp config is supported for now. Found: [${[
...allSymbols,
].join()}]`);
}
const symbol = options?.symbol || [...allSymbols][0];
warpRouteId = createWarpRouteConfigId(symbol, allChains.sort().join('-'));
}
assert(warpRouteId.match(WARP_ROUTE_ID_REGEX), `Invalid warp route ID: ${warpRouteId}. Must be in the format such as: TOKENSYMBOL/label...`);
return warpRouteId;
}
getWarpRouteCoreConfigPath(config, options) {
const warpRouteId = BaseRegistry.warpRouteConfigToId(config, options);
return `${this.getWarpRoutesPath()}/${warpRouteId}-config.yaml`;
}
/**
* Generates a warp route ID based on the deploy config and options.
*
* @param config The warp route deployment config
* @param options Additional config options for the warp route
* @returns A string ID for the warp route
*
* If a warpRouteId is provided in options, use it directly.
* Otherwise, the method attempts to generate an ID based on 1 synthetic chain, or defaults to all chains.
*/
static warpDeployConfigToId(config, options) {
assert(objLength(config) > 0, 'Cannot generate ID for empty warp deploy config');
const syntheticChains = objFilter(config, (_, c) => c.type?.includes('synthetic'));
let warpRouteId;
if ('warpRouteId' in options) {
warpRouteId = options.warpRouteId;
}
else if (objLength(syntheticChains) === 1) {
warpRouteId = createWarpRouteConfigId(options.symbol, Object.keys(syntheticChains)[0]);
}
else {
warpRouteId = createWarpRouteConfigId(options.symbol, Object.keys(config).sort().join('-'));
}
assert(warpRouteId.match(WARP_ROUTE_ID_REGEX), `Invalid warp route ID: ${warpRouteId}. Must be in the format such as: TOKENSYMBOL/label...`);
return warpRouteId;
}
getWarpRouteDeployConfigPath(config, options) {
const warpRouteId = BaseRegistry.warpDeployConfigToId(config, options);
return `${this.getWarpRoutesPath()}/${warpRouteId}-deploy.yaml`;
}
async getChainLogoUri(chainName) {
const registryContent = await this.listRegistryContent();
const chain = registryContent.chains[chainName];
return chain?.logo ?? null;
}
merge(otherRegistry) {
return new MergedRegistry({ registries: [this, otherRegistry], logger: this.logger });
}
}