UNPKG

@hyperlane-xyz/sdk

Version:

The official SDK for the Hyperlane Network

148 lines 5.66 kB
import { pick } from '@hyperlane-xyz/utils'; import { multisigIsmVerifyCosts } from '../consts/multisigIsmVerifyCosts.js'; import { IsmType } from '../ism/types.js'; /** * Extracts the ISM and Hook factory addresses from chain-specific registry addresses * @param registryAddresses The registry addresses for a specific chain * @returns The extracted ISM and Hook factory addresses */ export function ismTreeContainsRateLimited(ism) { if (typeof ism !== 'object' || ism === null) return false; const node = ism; if (node.type === IsmType.RATE_LIMITED) return true; if (Array.isArray(node.modules)) { if (node.modules.some(ismTreeContainsRateLimited)) return true; } if (node.domains !== null && typeof node.domains === 'object') { if (Object.values(node.domains).some(ismTreeContainsRateLimited)) return true; } if (ismTreeContainsRateLimited(node.lowerIsm)) return true; if (ismTreeContainsRateLimited(node.upperIsm)) return true; return false; } /** * Recursively sets `recipient` on all RATE_LIMITED ISM nodes in the config tree. * Pass `undefined` to strip the field. * `defaultOwner` is set on nodes that don't have an explicit owner. */ export function setRateLimitedIsmRecipient(ismConfig, recipient, defaultOwner) { if (typeof ismConfig === 'string') return ismConfig; if (ismConfig.type === IsmType.RATE_LIMITED) { return { ...ismConfig, recipient, ...(defaultOwner != null && ismConfig.owner == null ? { owner: defaultOwner } : {}), }; } if (ismConfig.type === IsmType.AGGREGATION || ismConfig.type === IsmType.STORAGE_AGGREGATION) { return { ...ismConfig, modules: ismConfig.modules.map((m) => setRateLimitedIsmRecipient(m, recipient, defaultOwner)), }; } if (ismConfig.type === IsmType.ROUTING || ismConfig.type === IsmType.FALLBACK_ROUTING || ismConfig.type === IsmType.INCREMENTAL_ROUTING) { const newDomains = {}; for (const [domain, domainIsm] of Object.entries(ismConfig.domains)) { newDomains[domain] = setRateLimitedIsmRecipient(domainIsm, recipient, defaultOwner); } return { ...ismConfig, domains: newDomains }; } if (ismConfig.type === IsmType.AMOUNT_ROUTING) { return { ...ismConfig, lowerIsm: setRateLimitedIsmRecipient(ismConfig.lowerIsm, recipient, defaultOwner), upperIsm: setRateLimitedIsmRecipient(ismConfig.upperIsm, recipient, defaultOwner), }; } return ismConfig; } export function extractIsmAndHookFactoryAddresses(registryAddresses) { return pick(registryAddresses, [ 'domainRoutingIsmFactory', 'incrementalDomainRoutingIsmFactory', 'staticMerkleRootMultisigIsmFactory', 'staticMessageIdMultisigIsmFactory', 'staticAggregationIsmFactory', 'staticAggregationHookFactory', 'staticMerkleRootWeightedMultisigIsmFactory', 'staticMessageIdWeightedMultisigIsmFactory', ]); } export function multisigIsmVerificationCost(m, n) { if (!(`${n}` in multisigIsmVerifyCosts) || // @ts-ignore !(`${m}` in multisigIsmVerifyCosts[`${n}`])) { throw new Error(`No multisigIsmVerificationCost found for ${m}-of-${n}`); } // @ts-ignore return multisigIsmVerifyCosts[`${n}`][`${m}`]; } // Function to recursively remove 'address' properties and lowercase string properties export function normalizeConfig(obj) { return sortArraysInConfig(lowerCaseConfig(obj)); } function lowerCaseConfig(obj) { if (Array.isArray(obj)) { return obj.map(normalizeConfig); } else if (obj !== null && typeof obj === 'object') { const newObj = {}; for (const key in obj) { if (key !== 'address' && key !== 'ownerOverrides') { newObj[key] = key === 'type' ? obj[key] : normalizeConfig(obj[key]); } } return newObj; } else if (typeof obj === 'string') { return obj.toLowerCase(); } return obj; } // write a function that will go through an object and sort any arrays it finds export function sortArraysInConfig(config) { // Check if the current object is an array if (Array.isArray(config)) { return config.map(sortArraysInConfig); } // Check if it's an object and not null else if (typeof config === 'object' && config !== null) { const sortedConfig = {}; for (const key in config) { if (key === 'validators' && Array.isArray(config[key])) { // Sort the validators array in lexicographical order (since they're already lowercase) sortedConfig[key] = [...config[key]].sort(); } // if key is modules or hooks, sort the objects in the array by their 'type' property else if ((key === 'modules' || key === 'hooks') && Array.isArray(config[key])) { sortedConfig[key] = [...config[key]].sort((a, b) => { if (a.type < b.type) return -1; if (a.type > b.type) return 1; return 0; }); } else { // Recursively apply sorting to other fields sortedConfig[key] = sortArraysInConfig(config[key]); } } return sortedConfig; } return config; } //# sourceMappingURL=ism.js.map