feat: use chain name or domain as identifier instead of chainId (#136)

relates to:
- https://github.com/hyperlane-xyz/hyperlane-warp-ui-template/pull/313
- https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4798

testing:
- [x] update SDK to latest once monorepo PR is merged + rolled out
- [x] add duplicate chain metadata with different domain id to custom
yaml

---------

Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com>
pull/137/head
Paul Balaji 4 weeks ago committed by GitHub
parent ec0db733e5
commit b8e0d310e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      package.json
  2. 7
      src/components/icons/ChainLogo.tsx
  3. 10
      src/components/search/SearchFilterBar.tsx
  4. 15
      src/features/chains/MissingChainConfigToast.tsx
  5. 8
      src/features/chains/queries/useScrapedChains.ts
  6. 18
      src/features/chains/utils.ts
  7. 16
      src/features/deliveryStatus/fetchDeliveryStatus.ts
  8. 17
      src/features/deliveryStatus/useMessageDeliveryStatus.tsx
  9. 26
      src/features/messages/MessageDetails.tsx
  10. 15
      src/features/messages/MessageTable.tsx
  11. 2
      src/features/messages/cards/GasDetailsCard.tsx
  12. 47
      src/features/messages/cards/TransactionCard.tsx
  13. 43
      src/features/messages/pi-queries/fetchPiChainMessages.ts
  14. 5
      src/features/messages/pi-queries/usePiChainMessageQuery.ts
  15. 14
      src/features/messages/queries/parse.ts
  16. 26
      src/utils/explorers.ts
  17. 75
      yarn.lock

@ -6,9 +6,9 @@
"dependencies": { "dependencies": {
"@headlessui/react": "^2.1.8", "@headlessui/react": "^2.1.8",
"@hyperlane-xyz/registry": "5.1.0", "@hyperlane-xyz/registry": "5.1.0",
"@hyperlane-xyz/sdk": "5.7.0", "@hyperlane-xyz/sdk": "6.0.0",
"@hyperlane-xyz/utils": "5.7.0", "@hyperlane-xyz/utils": "6.0.0",
"@hyperlane-xyz/widgets": "5.7.0", "@hyperlane-xyz/widgets": "6.0.0",
"@tanstack/react-query": "^5.35.5", "@tanstack/react-query": "^5.35.5",
"bignumber.js": "^9.1.2", "bignumber.js": "^9.1.2",
"buffer": "^6.0.3", "buffer": "^6.0.3",

@ -1,21 +1,18 @@
import { ChainLogo as ChainLogoInner } from '@hyperlane-xyz/widgets'; import { ChainLogo as ChainLogoInner } from '@hyperlane-xyz/widgets';
import { useMultiProvider, useRegistry } from '../../store'; import { useRegistry } from '../../store';
export function ChainLogo({ export function ChainLogo({
chainId,
chainName, chainName,
background, background,
size, size,
}: { }: {
chainId: ChainId;
chainName?: string; chainName?: string;
background?: boolean; background?: boolean;
size?: number; size?: number;
}) { }) {
const multiProvider = useMultiProvider();
const registry = useRegistry(); const registry = useRegistry();
const name = chainName || multiProvider.tryGetChainName(chainId) || ''; const name = chainName || '';
return ( return (
<ChainLogoInner chainName={name} registry={registry} size={size} background={background} /> <ChainLogoInner chainName={name} registry={registry} size={size} background={background} />
); );

@ -64,14 +64,16 @@ function ChainSelector({
onChangeValue, onChangeValue,
}: { }: {
text: string; text: string;
value: ChainId | null; value: string | null;
onChangeValue: (value: string | null) => void; onChangeValue: (value: string | null) => void;
}) { }) {
const { isOpen, open, close } = useModal(); const { isOpen, open, close } = useModal();
const multiProvider = useMultiProvider(); const multiProvider = useMultiProvider();
const chainName = value
? trimToLength(getChainDisplayName(multiProvider, value, true), 12) const chainName = value ? multiProvider.getChainName(value) : undefined;
const chainDisplayName = chainName
? trimToLength(getChainDisplayName(multiProvider, chainName, true), 12)
: undefined; : undefined;
const onClickChain = (c: ChainMetadata) => { const onClickChain = (c: ChainMetadata) => {
@ -93,7 +95,7 @@ function ChainSelector({
)} )}
onClick={open} onClick={open}
> >
<span>{chainName || text} </span> <span>{chainDisplayName || text} </span>
{!value && ( {!value && (
<ChevronIcon <ChevronIcon
direction="s" direction="s"

@ -1,18 +1,7 @@
export function MissingChainConfigToast({ export function MissingChainConfigToast({ domainId }: { domainId: number }) {
domainId,
chainId,
}: {
domainId: number;
chainId: number | string | null | undefined;
}) {
const errorDesc = chainId
? `chain ID: ${chainId}`
: domainId
? `domain ID: ${domainId}`
: 'unknown message chain';
return ( return (
<div> <div>
<span>{`No chain config found for ${errorDesc}. You can add a config in the origin/destination chain selector.`}</span> <span>{`No chain config found for domain ${domainId}. You can add a config in the origin/destination chain selector.`}</span>
</div> </div>
); );
} }

@ -42,8 +42,8 @@ export function useScrapedChains(multiProvider: MultiProvider) {
const scrapedChains = objFilter( const scrapedChains = objFilter(
chainMetadata, chainMetadata,
(_, chainMetadata): chainMetadata is ChainMetadata => (_, chainMetadata): chainMetadata is ChainMetadata =>
!isPiChain(multiProvider, scrapedDomains, chainMetadata.chainId) && !isPiChain(multiProvider, scrapedDomains, chainMetadata.domainId) &&
!isUnscrapedDbChain(multiProvider, chainMetadata.chainId), !isUnscrapedDbChain(multiProvider, chainMetadata.domainId),
); );
return { chains: scrapedChains }; return { chains: scrapedChains };
}, [multiProvider, chainMetadata, scrapedDomains]); }, [multiProvider, chainMetadata, scrapedDomains]);
@ -52,7 +52,7 @@ export function useScrapedChains(multiProvider: MultiProvider) {
} }
// TODO: Remove once all chains in the DB are scraped // TODO: Remove once all chains in the DB are scraped
export function isUnscrapedDbChain(multiProvider: MultiProvider, chainIdOrName: number | string) { export function isUnscrapedDbChain(multiProvider: MultiProvider, domainId: DomainId) {
const chainName = multiProvider.tryGetChainName(chainIdOrName); const chainName = multiProvider.tryGetChainName(domainId);
return chainName && unscrapedChainsInDb.includes(chainName); return chainName && unscrapedChainsInDb.includes(chainName);
} }

@ -19,18 +19,18 @@ export async function getMailboxAddress(
export function getChainDisplayName( export function getChainDisplayName(
multiProvider: MultiProvider, multiProvider: MultiProvider,
chainOrDomainId?: ChainId | DomainId, chainName?: string,
shortName = false, shortName = false,
fallbackToId = true, fallbackToId = true,
): string { ): string {
const metadata = multiProvider.tryGetChainMetadata(chainOrDomainId || 0); const metadata = multiProvider.tryGetChainMetadata(chainName || 0);
if (!metadata) return fallbackToId && chainOrDomainId ? chainOrDomainId.toString() : 'Unknown'; if (!metadata) return fallbackToId && chainName ? chainName : 'Unknown';
const displayName = shortName ? metadata.displayNameShort : metadata.displayName; const displayName = shortName ? metadata.displayNameShort : metadata.displayName;
return toTitleCase(displayName || metadata.displayName || metadata.name); return toTitleCase(displayName || metadata.displayName || metadata.name);
} }
export function getChainEnvironment(multiProvider: MultiProvider, chainIdOrName: number | string) { export function getChainEnvironment(multiProvider: MultiProvider, domainId: DomainId) {
const isTestnet = multiProvider.tryGetChainMetadata(chainIdOrName)?.isTestnet; const isTestnet = multiProvider.tryGetChainMetadata(domainId)?.isTestnet;
return isTestnet ? Environment.Testnet : Environment.Mainnet; return isTestnet ? Environment.Testnet : Environment.Mainnet;
} }
@ -38,14 +38,14 @@ export function getChainEnvironment(multiProvider: MultiProvider, chainIdOrName:
export function isPiChain( export function isPiChain(
multiProvider: MultiProvider, multiProvider: MultiProvider,
scrapedChains: DomainsEntry[], scrapedChains: DomainsEntry[],
chainIdOrName: number | string, domainId: DomainId,
) { ) {
const chainName = multiProvider.tryGetChainName(chainIdOrName); const chainName = multiProvider.tryGetChainName(domainId);
// Note: .trim() because one chain name in the DB has a trailing \n char for some reason // Note: .trim() because one chain name in the DB has a trailing \n char for some reason
return !chainName || !scrapedChains.find((chain) => chain.name.trim() === chainName); return !chainName || !scrapedChains.find((chain) => chain.name.trim() === chainName);
} }
export function isEvmChain(multiProvider: MultiProvider, chainIdOrName: number | string) { export function isEvmChain(multiProvider: MultiProvider, domainId: DomainId) {
const protocol = multiProvider.tryGetProtocol(chainIdOrName); const protocol = multiProvider.tryGetProtocol(domainId);
return protocol === ProtocolType.Ethereum; return protocol === ProtocolType.Ethereum;
} }

@ -25,7 +25,7 @@ export async function fetchDeliveryStatus(
overrideChainMetadata: ChainMap<Partial<ChainMetadata>>, overrideChainMetadata: ChainMap<Partial<ChainMetadata>>,
message: Message, message: Message,
): Promise<MessageDeliveryStatusResponse> { ): Promise<MessageDeliveryStatusResponse> {
const destName = multiProvider.getChainName(message.destinationChainId); const destName = multiProvider.getChainName(message.destinationDomainId);
const destMailboxAddr = await getMailboxAddress(destName, overrideChainMetadata, registry); const destMailboxAddr = await getMailboxAddress(destName, overrideChainMetadata, registry);
if (!destMailboxAddr) if (!destMailboxAddr)
throw new Error( throw new Error(
@ -41,7 +41,7 @@ export async function fetchDeliveryStatus(
if (isDelivered) { if (isDelivered) {
const txDetails = await fetchTransactionDetails( const txDetails = await fetchTransactionDetails(
multiProvider, multiProvider,
message.destinationChainId, message.destinationDomainId,
transactionHash, transactionHash,
); );
// If a delivery (aka process) tx is found, mark as success // If a delivery (aka process) tx is found, mark as success
@ -85,8 +85,8 @@ async function checkIsMessageDelivered(
message: Message, message: Message,
mailboxAddr: Address, mailboxAddr: Address,
) { ) {
const { msgId, destinationChainId } = message; const { msgId, destinationDomainId } = message;
const provider = multiProvider.getProvider(destinationChainId); const provider = multiProvider.getProvider(destinationDomainId);
const mailbox = IMailbox__factory.connect(mailboxAddr, provider); const mailbox = IMailbox__factory.connect(mailboxAddr, provider);
// Try finding logs first as they have more info // Try finding logs first as they have more info
@ -114,9 +114,13 @@ async function checkIsMessageDelivered(
return { isDelivered }; return { isDelivered };
} }
function fetchTransactionDetails(multiProvider: MultiProvider, chainId: ChainId, txHash?: string) { function fetchTransactionDetails(
multiProvider: MultiProvider,
domainId: DomainId,
txHash?: string,
) {
if (!txHash) return null; if (!txHash) return null;
logger.debug(`Searching for transaction details for ${txHash}`); logger.debug(`Searching for transaction details for ${txHash}`);
const provider = multiProvider.getProvider(chainId); const provider = multiProvider.getProvider(domainId);
return provider.getTransaction(txHash); return provider.getTransaction(txHash);
} }

@ -31,12 +31,11 @@ export function useMessageDeliveryStatus({
return { message }; return { message };
} }
const { id, originChainId, originDomainId, destinationChainId, destinationDomainId } = const { id, originDomainId, destinationDomainId } = message;
message;
if ( if (
!checkChain(multiProvider, originChainId, originDomainId) || !checkChain(multiProvider, originDomainId) ||
!checkChain(multiProvider, destinationChainId, destinationDomainId) !checkChain(multiProvider, destinationDomainId)
) { ) {
return { message }; return { message };
} }
@ -93,13 +92,13 @@ export function useMessageDeliveryStatus({
}; };
} }
function checkChain(multiProvider: MultiProvider, chainId: ChainId, domainId: number) { function checkChain(multiProvider: MultiProvider, domainId: number) {
if (!multiProvider.hasChain(chainId)) { if (!multiProvider.hasChain(domainId)) {
toast.error(<MissingChainConfigToast chainId={chainId} domainId={domainId} />); toast.error(<MissingChainConfigToast domainId={domainId} />);
return false; return false;
} }
if (!isEvmChain(multiProvider, chainId)) { if (!isEvmChain(multiProvider, domainId)) {
logger.debug('Skipping delivery status check for non-EVM chain:', chainId); logger.debug('Skipping delivery status check for non-EVM chain:', domainId);
return false; return false;
} }
return true; return true;

@ -73,17 +73,8 @@ export function MessageDetails({ messageId, message: messageFromUrlParams }: Pro
enabled: isMessageFound, enabled: isMessageFound,
}); });
const { const { msgId, status, originDomainId, destinationDomainId, origin, destination, isPiMsg } =
msgId, message;
status,
originChainId,
destinationChainId,
originDomainId,
destinationDomainId,
origin,
destination,
isPiMsg,
} = message;
const duration = destination?.timestamp const duration = destination?.timestamp
? getHumanReadableDuration(destination.timestamp - origin.timestamp, 3) ? getHumanReadableDuration(destination.timestamp - origin.timestamp, 3)
@ -91,12 +82,15 @@ export function MessageDetails({ messageId, message: messageFromUrlParams }: Pro
const showTimeline = const showTimeline =
!isPiMsg && !isPiMsg &&
isEvmChain(multiProvider, originChainId) && isEvmChain(multiProvider, originDomainId) &&
isEvmChain(multiProvider, destinationChainId); isEvmChain(multiProvider, destinationDomainId);
// Banner color setter // Banner color setter
useDynamicBannerColor(isFetching, status, isMessageFound, isError || isPiError); useDynamicBannerColor(isFetching, status, isMessageFound, isError || isPiError);
const originChainName = multiProvider.getChainName(originDomainId);
const destinationChainName = multiProvider.getChainName(destinationDomainId);
return ( return (
<> <>
<Card className="flex items-center justify-between rounded-full px-1"> <Card className="flex items-center justify-between rounded-full px-1">
@ -104,7 +98,7 @@ export function MessageDetails({ messageId, message: messageFromUrlParams }: Pro
isIcaMsg ? 'ICA ' : '' isIcaMsg ? 'ICA ' : ''
} Message ${trimToLength(msgId, 6)} to ${getChainDisplayName( } Message ${trimToLength(msgId, 6)} to ${getChainDisplayName(
multiProvider, multiProvider,
destinationChainId, destinationChainName,
)}`}</h2> )}`}</h2>
<StatusHeader <StatusHeader
messageStatus={status} messageStatus={status}
@ -115,13 +109,13 @@ export function MessageDetails({ messageId, message: messageFromUrlParams }: Pro
</Card> </Card>
<div className="mt-3 flex flex-wrap items-stretch justify-between gap-3 md:mt-4 md:gap-4"> <div className="mt-3 flex flex-wrap items-stretch justify-between gap-3 md:mt-4 md:gap-4">
<OriginTransactionCard <OriginTransactionCard
chainId={originChainId} chainName={originChainName}
domainId={originDomainId} domainId={originDomainId}
transaction={origin} transaction={origin}
blur={blur} blur={blur}
/> />
<DestinationTransactionCard <DestinationTransactionCard
chainId={destinationChainId} chainName={destinationChainName}
domainId={destinationDomainId} domainId={destinationDomainId}
status={status} status={status}
transaction={destination} transaction={destination}

@ -53,7 +53,7 @@ export function MessageTable({
} }
export function MessageSummaryRow({ message, mp }: { message: MessageStub; mp: MultiProvider }) { export function MessageSummaryRow({ message, mp }: { message: MessageStub; mp: MultiProvider }) {
const { msgId, status, sender, recipient, originChainId, destinationChainId, origin } = message; const { msgId, status, sender, recipient, originDomainId, destinationDomainId, origin } = message;
let statusIcon = undefined; let statusIcon = undefined;
let statusTitle = ''; let statusTitle = '';
@ -67,15 +67,20 @@ export function MessageSummaryRow({ message, mp }: { message: MessageStub; mp: M
const base64 = message.isPiMsg ? serializeMessage(message) : undefined; const base64 = message.isPiMsg ? serializeMessage(message) : undefined;
const originChainName = mp.getChainName(originDomainId);
const destinationChainName = mp.getChainName(destinationDomainId);
return ( return (
<> <>
<LinkCell id={msgId} base64={base64} aClasses="flex items-center py-3.5 pl-3 sm:pl-5"> <LinkCell id={msgId} base64={base64} aClasses="flex items-center py-3.5 pl-3 sm:pl-5">
<ChainLogo chainId={originChainId} size={20} /> <ChainLogo chainName={originChainName} size={20} />
<div className={styles.chainName}>{getChainDisplayName(mp, originChainId, true)}</div> <div className={styles.chainName}>{getChainDisplayName(mp, originChainName, true)}</div>
</LinkCell> </LinkCell>
<LinkCell id={msgId} base64={base64} aClasses="flex items-center py-3.5 "> <LinkCell id={msgId} base64={base64} aClasses="flex items-center py-3.5 ">
<ChainLogo chainId={destinationChainId} size={20} /> <ChainLogo chainName={destinationChainName} size={20} />
<div className={styles.chainName}>{getChainDisplayName(mp, destinationChainId, true)}</div> <div className={styles.chainName}>
{getChainDisplayName(mp, destinationChainName, true)}
</div>
</LinkCell> </LinkCell>
<LinkCell id={msgId} base64={base64} tdClasses="hidden sm:table-cell" aClasses={styles.value}> <LinkCell id={msgId} base64={base64} tdClasses="hidden sm:table-cell" aClasses={styles.value}>
{shortenAddress(sender) || 'Invalid Address'} {shortenAddress(sender) || 'Invalid Address'}

@ -27,7 +27,7 @@ interface Props {
export function GasDetailsCard({ message, blur, igpPayments = {} }: Props) { export function GasDetailsCard({ message, blur, igpPayments = {} }: Props) {
const multiProvider = useMultiProvider(); const multiProvider = useMultiProvider();
const unitOptions = useMemo(() => { const unitOptions = useMemo(() => {
const originMetadata = multiProvider.tryGetChainMetadata(message.originChainId); const originMetadata = multiProvider.tryGetChainMetadata(message.originDomainId);
const nativeCurrencyName = originMetadata?.nativeToken?.symbol || 'Eth'; const nativeCurrencyName = originMetadata?.nativeToken?.symbol || 'Eth';
return [ return [
{ value: 18, display: toTitleCase(nativeCurrencyName) }, { value: 18, display: toTitleCase(nativeCurrencyName) },

@ -21,20 +21,20 @@ import { LabelAndCodeBlock } from './CodeBlock';
import { KeyValueRow } from './KeyValueRow'; import { KeyValueRow } from './KeyValueRow';
export function OriginTransactionCard({ export function OriginTransactionCard({
chainId, chainName,
domainId, domainId,
transaction, transaction,
blur, blur,
}: { }: {
chainId: ChainId; chainName: string;
domainId: DomainId; domainId: DomainId;
transaction: MessageTx; transaction: MessageTx;
blur: boolean; blur: boolean;
}) { }) {
return ( return (
<TransactionCard chainId={chainId} title="Origin Transaction" helpText={helpText.origin}> <TransactionCard chainName={chainName} title="Origin Transaction" helpText={helpText.origin}>
<TransactionDetails <TransactionDetails
chainId={chainId} chainName={chainName}
domainId={domainId} domainId={domainId}
transaction={transaction} transaction={transaction}
blur={blur} blur={blur}
@ -44,7 +44,7 @@ export function OriginTransactionCard({
} }
export function DestinationTransactionCard({ export function DestinationTransactionCard({
chainId, chainName,
domainId, domainId,
status, status,
transaction, transaction,
@ -54,7 +54,7 @@ export function DestinationTransactionCard({
isPiMsg, isPiMsg,
blur, blur,
}: { }: {
chainId: ChainId; chainName: string;
domainId: DomainId; domainId: DomainId;
status: MessageStatus; status: MessageStatus;
transaction?: MessageTx; transaction?: MessageTx;
@ -65,9 +65,9 @@ export function DestinationTransactionCard({
blur: boolean; blur: boolean;
}) { }) {
const multiProvider = useMultiProvider(); const multiProvider = useMultiProvider();
const hasChainConfig = !!multiProvider.tryGetChainMetadata(chainId); const hasChainConfig = !!multiProvider.tryGetChainMetadata(domainId);
const isDestinationEvmChain = isEvmChain(multiProvider, chainId); const isDestinationEvmChain = isEvmChain(multiProvider, domainId);
const { isOpen, open, close } = useModal(); const { isOpen, open, close } = useModal();
@ -75,9 +75,9 @@ export function DestinationTransactionCard({
if (transaction) { if (transaction) {
content = ( content = (
<TransactionDetails <TransactionDetails
transaction={transaction} chainName={chainName}
chainId={chainId}
domainId={domainId} domainId={domainId}
transaction={transaction}
duration={duration} duration={duration}
blur={blur} blur={blur}
/> />
@ -156,7 +156,7 @@ export function DestinationTransactionCard({
return ( return (
<TransactionCard <TransactionCard
chainId={chainId} chainName={chainName}
title="Destination Transaction" title="Destination Transaction"
helpText={helpText.destination} helpText={helpText.destination}
> >
@ -166,16 +166,16 @@ export function DestinationTransactionCard({
} }
function TransactionCard({ function TransactionCard({
chainId, chainName,
title, title,
helpText, helpText,
children, children,
}: PropsWithChildren<{ chainId: ChainId; title: string; helpText: string }>) { }: PropsWithChildren<{ chainName: string; title: string; helpText: string }>) {
return ( return (
<Card className="flex min-w-fit flex-1 flex-col space-y-3"> <Card className="flex min-w-fit flex-1 flex-col space-y-3">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="relative -left-0.5 -top-px"> <div className="relative -left-0.5 -top-px">
<ChainLogo chainId={chainId} /> <ChainLogo chainName={chainName} />
</div> </div>
<div className="flex items-center pb-1"> <div className="flex items-center pb-1">
<h3 className="mr-2 text-md font-medium text-blue-500">{title}</h3> <h3 className="mr-2 text-md font-medium text-blue-500">{title}</h3>
@ -194,13 +194,13 @@ function TransactionCard({
} }
function TransactionDetails({ function TransactionDetails({
chainId, chainName,
domainId, domainId,
transaction, transaction,
duration, duration,
blur, blur,
}: { }: {
chainId: ChainId; chainName: string;
domainId: DomainId; domainId: DomainId;
transaction: MessageTx; transaction: MessageTx;
duration?: string; duration?: string;
@ -214,13 +214,13 @@ function TransactionDetails({
const txExplorerLink = const txExplorerLink =
hash && !new BigNumber(hash).isZero() hash && !new BigNumber(hash).isZero()
? multiProvider.tryGetExplorerTxUrl(chainId, { hash: formattedHash }) ? multiProvider.tryGetExplorerTxUrl(chainName, { hash: formattedHash })
: null; : null;
return ( return (
<> <>
<ChainDescriptionRow <ChainDescriptionRow
chainId={chainId} chainName={chainName}
domainId={domainId} domainId={domainId}
multiProvider={multiProvider} multiProvider={multiProvider}
blur={blur} blur={blur}
@ -337,20 +337,23 @@ function CallDataModal({ debugResult }: { debugResult?: MessageDebugResult }) {
} }
function ChainDescriptionRow({ function ChainDescriptionRow({
chainId, chainName,
domainId, domainId,
multiProvider, multiProvider,
blur, blur,
}: { }: {
chainId: ChainId; chainName: string;
domainId: DomainId; domainId: DomainId;
multiProvider: MultiProvider; multiProvider: MultiProvider;
blur: boolean; blur: boolean;
}) { }) {
const idString = chainId && chainId !== domainId ? `${chainId} / ${domainId}` : `${domainId}`; const idString =
chainName && chainName !== multiProvider.tryGetChainName(domainId)
? `${chainName} / ${domainId}`
: `${domainId}`;
const chainDescription = `${getChainDisplayName( const chainDescription = `${getChainDisplayName(
multiProvider, multiProvider,
domainId, chainName,
false, false,
false, false,
)} (${idString})`; )} (${idString})`;

@ -36,7 +36,7 @@ export enum PiQueryType {
MsgId = 'msgId', MsgId = 'msgId',
} }
/* Pseudo-code for the fetch algo below: /* Pseudo-code for the fetch algo below:
======================================== ========================================
searchForMessages(input): searchForMessages(input):
for chain of piChains: for chain of piChains:
@ -53,7 +53,7 @@ searchForMessages(input):
if tx is found: if tx is found:
logs = tx.logs where topic0 is Dispatch or Process logs = tx.logs where topic0 is Dispatch or Process
if logs are found return logs.map( l => l.message ) if logs are found return logs.map( l => l.message )
else tx is not found: else tx is not found:
// input may be a message ID // input may be a message ID
logs = dataSource.getLogs() where: logs = dataSource.getLogs() where:
contract is mailbox contract is mailbox
@ -112,10 +112,10 @@ async function fetchLogsForAddress(
multiProvider: MultiProvider, multiProvider: MultiProvider,
registry: IRegistry, registry: IRegistry,
): Promise<ExtendedLog[]> { ): Promise<ExtendedLog[]> {
const { chainId } = chainMetadata; const { name, domainId } = chainMetadata;
const address = query.input; const address = query.input;
logger.debug(`Fetching logs for address ${address} on chain ${chainId}`); logger.debug(`Fetching logs for address ${address} on chain ${name} (${domainId})`);
const mailbox = await resolveMailbox(chainMetadata, multiProvider, registry); const mailbox = await resolveMailbox(chainMetadata, registry);
if (!mailbox) return []; if (!mailbox) return [];
const dispatchTopic = addressToBytes32(address); const dispatchTopic = addressToBytes32(address);
@ -127,23 +127,23 @@ async function fetchLogsForAddress(
// [processTopic0, null, null, dispatchTopic], // [processTopic0, null, null, dispatchTopic],
], ],
mailbox, mailbox,
chainId, domainId,
query, query,
multiProvider, multiProvider,
); );
} }
async function fetchLogsForTxHash( async function fetchLogsForTxHash(
{ chainId }: ChainMetadata, { name, domainId }: ChainMetadata,
query: PiMessageQuery, query: PiMessageQuery,
multiProvider: MultiProvider, multiProvider: MultiProvider,
): Promise<ExtendedLog[]> { ): Promise<ExtendedLog[]> {
const txHash = query.input; const txHash = query.input;
logger.debug(`Fetching logs for txHash ${txHash} on chain ${chainId}`); logger.debug(`Fetching logs for txHash ${txHash} on chain ${name} (${domainId})`);
const provider = multiProvider.getProvider(chainId); const provider = multiProvider.getProvider(domainId);
const txReceipt = await provider.getTransactionReceipt(txHash); const txReceipt = await provider.getTransactionReceipt(txHash);
if (txReceipt) { if (txReceipt) {
logger.debug(`Tx receipt found from provider for chain ${chainId}`); logger.debug(`Tx receipt found from provider for chain ${name} (${domainId})`);
const block = await tryFetchBlockFromProvider(provider, txReceipt.blockNumber); const block = await tryFetchBlockFromProvider(provider, txReceipt.blockNumber);
return txReceipt.logs.map((l) => ({ return txReceipt.logs.map((l) => ({
...l, ...l,
@ -152,7 +152,7 @@ async function fetchLogsForTxHash(
to: txReceipt.to, to: txReceipt.to,
})); }));
} else { } else {
logger.debug(`Tx hash not found from provider for chain ${chainId}`); logger.debug(`Tx hash not found from provider for chain ${name} (${domainId})`);
return []; return [];
} }
} }
@ -163,10 +163,10 @@ async function fetchLogsForMsgId(
multiProvider: MultiProvider, multiProvider: MultiProvider,
registry: IRegistry, registry: IRegistry,
): Promise<ExtendedLog[]> { ): Promise<ExtendedLog[]> {
const { chainId } = chainMetadata; const { name, domainId } = chainMetadata;
const msgId = query.input; const msgId = query.input;
logger.debug(`Fetching logs for msgId ${msgId} on chain ${chainId}`); logger.debug(`Fetching logs for msgId ${msgId} on chain ${name} (${domainId})`);
const mailbox = await resolveMailbox(chainMetadata, multiProvider, registry); const mailbox = await resolveMailbox(chainMetadata, registry);
if (!mailbox) return []; if (!mailbox) return [];
const topic1 = msgId; const topic1 = msgId;
const logs: ExtendedLog[] = await fetchLogsFromProvider( const logs: ExtendedLog[] = await fetchLogsFromProvider(
@ -175,7 +175,7 @@ async function fetchLogsForMsgId(
// [processIdTopic0, topic1], // [processIdTopic0, topic1],
], ],
mailbox, mailbox,
chainId, domainId,
query, query,
multiProvider, multiProvider,
); );
@ -194,11 +194,11 @@ async function fetchLogsForMsgId(
async function fetchLogsFromProvider( async function fetchLogsFromProvider(
topics: Array<Array<string | null>>, topics: Array<Array<string | null>>,
contractAddr: Address, contractAddr: Address,
chainId: ChainId, domainId: DomainId,
query: PiMessageQuery, query: PiMessageQuery,
multiProvider: MultiProvider, multiProvider: MultiProvider,
): Promise<ExtendedLog[]> { ): Promise<ExtendedLog[]> {
const provider = multiProvider.getProvider(chainId); const provider = multiProvider.getProvider(domainId);
let { fromBlock, toBlock } = query; let { fromBlock, toBlock } = query;
fromBlock ||= (await provider.getBlockNumber()) - PI_MESSAGE_LOG_CHECK_BLOCK_RANGE; fromBlock ||= (await provider.getBlockNumber()) - PI_MESSAGE_LOG_CHECK_BLOCK_RANGE;
@ -316,15 +316,15 @@ async function tryFetchIgpGasPayments(
chainMetadata: ChainMetadata<{ interchainGasPaymaster?: Address }>, chainMetadata: ChainMetadata<{ interchainGasPaymaster?: Address }>,
multiProvider: MultiProvider, multiProvider: MultiProvider,
): Promise<Message> { ): Promise<Message> {
const { chainId, interchainGasPaymaster } = chainMetadata; const { name, domainId, interchainGasPaymaster } = chainMetadata;
if (!interchainGasPaymaster || !isValidAddress(interchainGasPaymaster)) { if (!interchainGasPaymaster || !isValidAddress(interchainGasPaymaster)) {
logger.warn('No IGP address found for chain:', chainId); logger.warn(`No IGP address found for chain ${name} (${domainId})`);
return message; return message;
} }
const igp = IInterchainGasPaymaster__factory.connect( const igp = IInterchainGasPaymaster__factory.connect(
interchainGasPaymaster, interchainGasPaymaster,
multiProvider.getProvider(chainId), multiProvider.getProvider(domainId),
); );
const filter = igp.filters.GasPayment(message.msgId); const filter = igp.filters.GasPayment(message.msgId);
const matchedEvents = (await igp.queryFilter(filter)) || []; const matchedEvents = (await igp.queryFilter(filter)) || [];
@ -346,11 +346,10 @@ async function tryFetchIgpGasPayments(
async function resolveMailbox( async function resolveMailbox(
chainMetadata: ChainMetadata<{ mailbox?: Address }>, chainMetadata: ChainMetadata<{ mailbox?: Address }>,
multiProvider: MultiProvider,
registry: IRegistry, registry: IRegistry,
) { ) {
if (chainMetadata.mailbox) return chainMetadata.mailbox; if (chainMetadata.mailbox) return chainMetadata.mailbox;
const chainName = multiProvider.getChainName(chainMetadata.chainId); const chainName = chainMetadata.name;
const chainAddresses = await registry.getChainAddresses(chainName); const chainAddresses = await registry.getChainAddresses(chainName);
const mailbox = chainAddresses?.mailbox; const mailbox = chainAddresses?.mailbox;
if (!mailbox) logger.debug(`No mailbox address found for chain ${chainName}`); if (!mailbox) logger.debug(`No mailbox address found for chain ${chainName}`);

@ -54,8 +54,9 @@ export function usePiChainMessageSearchQuery({
const allChains = Object.values(multiProvider.metadata); const allChains = Object.values(multiProvider.metadata);
const piChains = allChains.filter( const piChains = allChains.filter(
(c) => (c) =>
isEvmChain(multiProvider, c.chainId) && c.domainId !== undefined &&
isPiChain(multiProvider, scrapedChains, c.chainId), isEvmChain(multiProvider, c.domainId) &&
isPiChain(multiProvider, scrapedChains, c.domainId),
); );
try { try {
const results = await Promise.allSettled( const results = await Promise.allSettled(

@ -61,16 +61,10 @@ function parseMessageStub(
try { try {
const originMetadata = multiProvider.tryGetChainMetadata(m.origin_domain_id); const originMetadata = multiProvider.tryGetChainMetadata(m.origin_domain_id);
const destinationMetadata = multiProvider.tryGetChainMetadata(m.destination_domain_id); const destinationMetadata = multiProvider.tryGetChainMetadata(m.destination_domain_id);
let destinationChainId = m.destination_chain_id || destinationMetadata?.chainId;
if (!destinationChainId) {
logger.debug(
`No chainId known for domain ${m.destination_domain_id}. Using domain as chainId`,
);
destinationChainId = m.destination_domain_id;
}
const isPiMsg = const isPiMsg =
isPiChain(multiProvider, scrapedChains, m.origin_chain_id) || isPiChain(multiProvider, scrapedChains, m.origin_domain_id) ||
isPiChain(multiProvider, scrapedChains, destinationChainId); isPiChain(multiProvider, scrapedChains, m.destination_domain_id);
return { return {
status: getMessageStatus(m), status: getMessageStatus(m),
@ -81,7 +75,7 @@ function parseMessageStub(
recipient: postgresByteaToAddress(m.recipient, destinationMetadata), recipient: postgresByteaToAddress(m.recipient, destinationMetadata),
originChainId: m.origin_chain_id, originChainId: m.origin_chain_id,
originDomainId: m.origin_domain_id, originDomainId: m.origin_domain_id,
destinationChainId, destinationChainId: m.destination_chain_id,
destinationDomainId: m.destination_domain_id, destinationDomainId: m.destination_domain_id,
origin: { origin: {
timestamp: parseTimestampString(m.send_occurred_at), timestamp: parseTimestampString(m.send_occurred_at),

@ -22,12 +22,12 @@ export interface ExplorerQueryResponse<R> {
async function queryExplorer<P>( async function queryExplorer<P>(
multiProvider: MultiProvider, multiProvider: MultiProvider,
chainId: ChainId, chainName: string,
params: URLSearchParams, params: URLSearchParams,
useKey = false, useKey = false,
) { ) {
const baseUrl = multiProvider.tryGetExplorerApiUrl(chainId); const baseUrl = multiProvider.tryGetExplorerApiUrl(chainName);
if (!baseUrl) throw new Error(`No valid URL found for explorer for chain ${chainId}`); if (!baseUrl) throw new Error(`No valid URL found for explorer for chain ${chainName}`);
const url = new URL(baseUrl); const url = new URL(baseUrl);
for (const [key, val] of params.entries()) { for (const [key, val] of params.entries()) {
@ -35,8 +35,8 @@ async function queryExplorer<P>(
} }
if (useKey) { if (useKey) {
const apiKey = config.explorerApiKeys[chainId]; const apiKey = config.explorerApiKeys[chainName];
if (!apiKey) throw new Error(`No API key for explorer for chain ${chainId}`); if (!apiKey) throw new Error(`No API key for explorer for chain ${chainName}`);
url.searchParams.set('apikey', apiKey); url.searchParams.set('apikey', apiKey);
} }
@ -85,13 +85,13 @@ export interface ExplorerLogEntry {
export async function queryExplorerForLogs( export async function queryExplorerForLogs(
multiProvider: MultiProvider, multiProvider: MultiProvider,
chainId: ChainId, chainName: string,
params: string, params: string,
useKey = false, useKey = false,
): Promise<ExplorerLogEntry[]> { ): Promise<ExplorerLogEntry[]> {
const logs = await queryExplorer<ExplorerLogEntry[]>( const logs = await queryExplorer<ExplorerLogEntry[]>(
multiProvider, multiProvider,
chainId, chainName,
new URLSearchParams(params), new URLSearchParams(params),
useKey, useKey,
); );
@ -127,7 +127,7 @@ export function toProviderLog(log: ExplorerLogEntry): ExtendedLog {
export async function queryExplorerForTx( export async function queryExplorerForTx(
multiProvider: MultiProvider, multiProvider: MultiProvider,
chainId: ChainId, chainName: string,
txHash: string, txHash: string,
useKey = false, useKey = false,
) { ) {
@ -138,7 +138,7 @@ export async function queryExplorerForTx(
}); });
const tx = await queryExplorer<providers.TransactionResponse>( const tx = await queryExplorer<providers.TransactionResponse>(
multiProvider, multiProvider,
chainId, chainName,
params, params,
useKey, useKey,
); );
@ -152,7 +152,7 @@ export async function queryExplorerForTx(
export async function queryExplorerForTxReceipt( export async function queryExplorerForTxReceipt(
multiProvider: MultiProvider, multiProvider: MultiProvider,
chainId: ChainId, chainName: string,
txHash: string, txHash: string,
useKey = false, useKey = false,
) { ) {
@ -163,7 +163,7 @@ export async function queryExplorerForTxReceipt(
}); });
const tx = await queryExplorer<providers.TransactionReceipt>( const tx = await queryExplorer<providers.TransactionReceipt>(
multiProvider, multiProvider,
chainId, chainName,
params, params,
useKey, useKey,
); );
@ -177,7 +177,7 @@ export async function queryExplorerForTxReceipt(
export async function queryExplorerForBlock( export async function queryExplorerForBlock(
multiProvider: MultiProvider, multiProvider: MultiProvider,
chainId: ChainId, chainName: string,
blockNumber?: number | string, blockNumber?: number | string,
useKey = false, useKey = false,
) { ) {
@ -187,7 +187,7 @@ export async function queryExplorerForBlock(
tag: blockNumber?.toString() || 'latest', tag: blockNumber?.toString() || 'latest',
boolean: 'false', boolean: 'false',
}); });
const block = await queryExplorer<providers.Block>(multiProvider, chainId, params, useKey); const block = await queryExplorer<providers.Block>(multiProvider, chainName, params, useKey);
if (!block || BigNumber.from(block.number).lte(0)) { if (!block || BigNumber.from(block.number).lte(0)) {
const msg = 'Invalid block result'; const msg = 'Invalid block result';
logger.error(msg, JSON.stringify(block), params); logger.error(msg, JSON.stringify(block), params);

@ -2120,13 +2120,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@hyperlane-xyz/core@npm:5.7.0": "@hyperlane-xyz/core@npm:5.7.1":
version: 5.7.0 version: 5.7.1
resolution: "@hyperlane-xyz/core@npm:5.7.0" resolution: "@hyperlane-xyz/core@npm:5.7.1"
dependencies: dependencies:
"@arbitrum/nitro-contracts": "npm:^1.2.1" "@arbitrum/nitro-contracts": "npm:^1.2.1"
"@eth-optimism/contracts": "npm:^0.6.0" "@eth-optimism/contracts": "npm:^0.6.0"
"@hyperlane-xyz/utils": "npm:5.7.0" "@hyperlane-xyz/utils": "npm:6.0.0"
"@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2" "@layerzerolabs/lz-evm-oapp-v2": "npm:2.0.2"
"@openzeppelin/contracts": "npm:^4.9.3" "@openzeppelin/contracts": "npm:^4.9.3"
"@openzeppelin/contracts-upgradeable": "npm:^v4.9.3" "@openzeppelin/contracts-upgradeable": "npm:^v4.9.3"
@ -2135,7 +2135,7 @@ __metadata:
"@ethersproject/abi": "*" "@ethersproject/abi": "*"
"@ethersproject/providers": "*" "@ethersproject/providers": "*"
"@types/sinon-chai": "*" "@types/sinon-chai": "*"
checksum: 10/7ca52943789378dc631cce932ab46ff68f2efe892e2e53f59e704e52a625962b1dd4c0f3bf4ee7eff6e08e17886a44a8d4ca72a98509cf54de272bdb7d96af4e checksum: 10/53fa047cb0d417b8453cbe422a385e804d9c84758dba10f3e1408a76b88ac57024be3aa0f942f404702e6e680da1e41aaf540155b5ce9cfca2896d244e2ef6d1
languageName: node languageName: node
linkType: hard linkType: hard
@ -2145,9 +2145,9 @@ __metadata:
dependencies: dependencies:
"@headlessui/react": "npm:^2.1.8" "@headlessui/react": "npm:^2.1.8"
"@hyperlane-xyz/registry": "npm:5.1.0" "@hyperlane-xyz/registry": "npm:5.1.0"
"@hyperlane-xyz/sdk": "npm:5.7.0" "@hyperlane-xyz/sdk": "npm:6.0.0"
"@hyperlane-xyz/utils": "npm:5.7.0" "@hyperlane-xyz/utils": "npm:6.0.0"
"@hyperlane-xyz/widgets": "npm:5.7.0" "@hyperlane-xyz/widgets": "npm:6.0.0"
"@tanstack/eslint-plugin-query": "npm:^5.28.6" "@tanstack/eslint-plugin-query": "npm:^5.28.6"
"@tanstack/react-query": "npm:^5.35.5" "@tanstack/react-query": "npm:^5.35.5"
"@types/jest": "npm:^29.5.3" "@types/jest": "npm:^29.5.3"
@ -2197,25 +2197,24 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@hyperlane-xyz/sdk@npm:5.7.0": "@hyperlane-xyz/sdk@npm:6.0.0":
version: 5.7.0 version: 6.0.0
resolution: "@hyperlane-xyz/sdk@npm:5.7.0" resolution: "@hyperlane-xyz/sdk@npm:6.0.0"
dependencies: dependencies:
"@arbitrum/sdk": "npm:^4.0.0" "@arbitrum/sdk": "npm:^4.0.0"
"@aws-sdk/client-s3": "npm:^3.74.0" "@aws-sdk/client-s3": "npm:^3.74.0"
"@cosmjs/cosmwasm-stargate": "npm:^0.32.4" "@cosmjs/cosmwasm-stargate": "npm:^0.32.4"
"@cosmjs/stargate": "npm:^0.32.4" "@cosmjs/stargate": "npm:^0.32.4"
"@hyperlane-xyz/core": "npm:5.7.0" "@hyperlane-xyz/core": "npm:5.7.1"
"@hyperlane-xyz/utils": "npm:5.7.0" "@hyperlane-xyz/utils": "npm:6.0.0"
"@safe-global/api-kit": "npm:1.3.0" "@safe-global/api-kit": "npm:1.3.0"
"@safe-global/protocol-kit": "npm:1.3.0" "@safe-global/protocol-kit": "npm:1.3.0"
"@safe-global/safe-deployments": "npm:1.37.8" "@safe-global/safe-deployments": "npm:1.37.8"
"@solana/spl-token": "npm:^0.3.8" "@solana/spl-token": "npm:^0.3.8"
"@solana/web3.js": "npm:^1.78.0" "@solana/web3.js": "npm:^1.78.0"
"@types/coingecko-api": "npm:^1.0.10"
"@wagmi/chains": "npm:^1.8.0" "@wagmi/chains": "npm:^1.8.0"
bignumber.js: "npm:^9.1.1" bignumber.js: "npm:^9.1.1"
coingecko-api: "npm:^1.0.10" coingecko-api-v3: "npm:^0.0.29"
cosmjs-types: "npm:^0.9.0" cosmjs-types: "npm:^0.9.0"
cross-fetch: "npm:^3.1.5" cross-fetch: "npm:^3.1.5"
ethers: "npm:^5.7.2" ethers: "npm:^5.7.2"
@ -2225,13 +2224,13 @@ __metadata:
peerDependencies: peerDependencies:
"@ethersproject/abi": "*" "@ethersproject/abi": "*"
"@ethersproject/providers": "*" "@ethersproject/providers": "*"
checksum: 10/c604cf4e1fbbc41d16d9236418bd15eee4034c6145362d8746ae5ac51a67f4932b6f5cde08166de9e20c427c689fc91aacc6edbd9d52778dc8170c42a3af3db7 checksum: 10/5d8ca83c7c52cd6ada1a3b4684ff5770ec9568e281c9b8d306b46ab61d188d88a1d22ec04e4024ef32fb92df158951201b3e900bb29955d416417415f53c035c
languageName: node languageName: node
linkType: hard linkType: hard
"@hyperlane-xyz/utils@npm:5.7.0": "@hyperlane-xyz/utils@npm:6.0.0":
version: 5.7.0 version: 6.0.0
resolution: "@hyperlane-xyz/utils@npm:5.7.0" resolution: "@hyperlane-xyz/utils@npm:6.0.0"
dependencies: dependencies:
"@cosmjs/encoding": "npm:^0.32.4" "@cosmjs/encoding": "npm:^0.32.4"
"@solana/web3.js": "npm:^1.78.0" "@solana/web3.js": "npm:^1.78.0"
@ -2240,23 +2239,23 @@ __metadata:
lodash-es: "npm:^4.17.21" lodash-es: "npm:^4.17.21"
pino: "npm:^8.19.0" pino: "npm:^8.19.0"
yaml: "npm:2.4.5" yaml: "npm:2.4.5"
checksum: 10/62d7c0c3513df50208c1819dad78911524e894cfd4681b65cba3e15d1e3837dcb28ff4b49ee6b9a5c522b4b27943eb2554d227b26c3399468dfaca6c2e80b5cb checksum: 10/bc75da2dfdec1ee26d7fb29db211d457b3ec07226059c9d2ea91602297547fecb0e369d0301fa0545bb2b89c77ca63d11434e8fb6b498fa1906082c4fcd8b3ba
languageName: node languageName: node
linkType: hard linkType: hard
"@hyperlane-xyz/widgets@npm:5.7.0": "@hyperlane-xyz/widgets@npm:6.0.0":
version: 5.7.0 version: 6.0.0
resolution: "@hyperlane-xyz/widgets@npm:5.7.0" resolution: "@hyperlane-xyz/widgets@npm:6.0.0"
dependencies: dependencies:
"@headlessui/react": "npm:^2.1.8" "@headlessui/react": "npm:^2.1.8"
"@hyperlane-xyz/sdk": "npm:5.7.0" "@hyperlane-xyz/sdk": "npm:6.0.0"
"@hyperlane-xyz/utils": "npm:5.7.0" "@hyperlane-xyz/utils": "npm:6.0.0"
clsx: "npm:^2.1.1" clsx: "npm:^2.1.1"
react-tooltip: "npm:^5.28.0" react-tooltip: "npm:^5.28.0"
peerDependencies: peerDependencies:
react: ^18 react: ^18
react-dom: ^18 react-dom: ^18
checksum: 10/d3dd5e657d67c061f842f9fc4beb319b97f694ffa0bc30bcd796826cfa911962f655722d249c35fce4c91833b3e4efaa5a37893cb2f6cd365fef29978dee920a checksum: 10/52f2170820f3ffbaa3c64fa44b84a1bfbef53101ed8877a04561711e2b1eb8bfd9685fb59a31fce51d7dba12181681e33e85d360205e0f1725b1e1ff86b72316
languageName: node languageName: node
linkType: hard linkType: hard
@ -4110,13 +4109,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/coingecko-api@npm:^1.0.10":
version: 1.0.10
resolution: "@types/coingecko-api@npm:1.0.10"
checksum: 10/2523f946e6d293c2ee94a0abee624f53c34b4643f8df685d0164509aba66e8234276e5d8c202c514551024757f0987f7062daa7428ccaf6673bad9a5c55779a2
languageName: node
linkType: hard
"@types/connect@npm:^3.4.33": "@types/connect@npm:^3.4.33":
version: 3.4.35 version: 3.4.35
resolution: "@types/connect@npm:3.4.35" resolution: "@types/connect@npm:3.4.35"
@ -5738,10 +5730,12 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"coingecko-api@npm:^1.0.10": "coingecko-api-v3@npm:^0.0.29":
version: 1.0.10 version: 0.0.29
resolution: "coingecko-api@npm:1.0.10" resolution: "coingecko-api-v3@npm:0.0.29"
checksum: 10/e0000df5aebbeee508f25824485fe8e4be57cd07825b3cfbf2dc3c51b646200eefd336c833e81747d4a209bf10c32019baef1070fb2bfbcdbae099420954d1fa dependencies:
https: "npm:^1.0.0"
checksum: 10/e60a0996472419232a144ec77028c060bd9c289f799dd40d46dbb7229cff3d868a3e35bf88724059dc25767b8136d794789e4dd31711592fa73a7be1ca2fcbc7
languageName: node languageName: node
linkType: hard linkType: hard
@ -8139,6 +8133,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"https@npm:^1.0.0":
version: 1.0.0
resolution: "https@npm:1.0.0"
checksum: 10/ccea8a8363a018d4b241db7748cff3a85c9f5b71bf80639e9c37dc6823f590f35dda098b80b726930e9f945387c8bfd6b1461df25cab5bf65a31903d81875b5d
languageName: node
linkType: hard
"human-signals@npm:^2.1.0": "human-signals@npm:^2.1.0":
version: 2.1.0 version: 2.1.0
resolution: "human-signals@npm:2.1.0" resolution: "human-signals@npm:2.1.0"

Loading…
Cancel
Save