-
Notifications
You must be signed in to change notification settings - Fork 94
feat: add transaction page to view all messages in a tx #261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/ica-decoding
Are you sure you want to change the base?
Changes from 4 commits
4c53bf4
1411bdb
8aee94d
e5e15ba
f5fa4d3
01cf382
8f44ffc
d4c0480
c2b6162
1cd7315
7fab189
123a219
2ef0be0
007ddce
e044a9c
5d7d1d4
08fca6d
8e4cf67
9251afe
f477bc2
98f1f58
f7d18d5
785d88a
92c3525
fa3fd9e
bb93bcf
7395e75
105e479
8fa6f07
b79ab39
f1254d2
4a53795
ae53fb7
9b8f72f
a28b3f8
f705c44
bce4884
a6aeab0
7c1f829
c3fbb85
fc391bf
707deff
23f7903
fe5c990
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| import { toTitleCase, trimToLength } from '@hyperlane-xyz/utils'; | ||
| import { SpinnerIcon } from '@hyperlane-xyz/widgets'; | ||
| import Image from 'next/image'; | ||
| import Link from 'next/link'; | ||
| import { useEffect, useMemo } from 'react'; | ||
| import { toast } from 'react-toastify'; | ||
| import { Card } from '../../components/layout/Card'; | ||
|
|
@@ -21,7 +22,7 @@ import { WarpTransferDetailsCard } from './cards/WarpTransferDetailsCard'; | |
| import { useIsIcaMessage } from './ica'; | ||
| import { usePiChainMessageQuery } from './pi-queries/usePiChainMessageQuery'; | ||
| import { PLACEHOLDER_MESSAGE } from './placeholderMessages'; | ||
| import { useMessageQuery } from './queries/useMessageQuery'; | ||
| import { useMessageQuery, useTransactionMessageCount } from './queries/useMessageQuery'; | ||
| import { parseWarpRouteMessageDetails } from './utils'; | ||
|
|
||
| interface Props { | ||
|
|
@@ -96,15 +97,29 @@ export function MessageDetails({ messageId, message: messageFromUrlParams }: Pro | |
| [message, warpRouteChainAddressMap, multiProvider], | ||
| ); | ||
|
|
||
| // Check if there are multiple messages in this origin transaction | ||
| const txMessageCount = useTransactionMessageCount(origin?.hash); | ||
| const showTxLink = txMessageCount > 1; | ||
|
|
||
| return ( | ||
| <> | ||
| <Card className="flex items-center justify-between rounded-full px-1"> | ||
| <h2 className="font-medium text-blue-500">{`${ | ||
| isIcaMsg ? 'ICA ' : '' | ||
| } Message ${trimToLength(msgId, 6)} to ${getChainDisplayName( | ||
| multiProvider, | ||
| destinationChainName, | ||
| )}`}</h2> | ||
| <div className="flex items-center gap-3"> | ||
| <h2 className="font-medium text-blue-500">{`${ | ||
| isIcaMsg ? 'ICA ' : '' | ||
| } Message ${trimToLength(msgId, 6)} to ${getChainDisplayName( | ||
| multiProvider, | ||
| destinationChainName, | ||
| )}`}</h2> | ||
| {showTxLink && ( | ||
| <Link | ||
| href={`/tx/${origin.hash}`} | ||
| className="text-sm text-gray-500 transition-colors hover:text-gray-700" | ||
| > | ||
| View all {txMessageCount} messages in tx → | ||
| </Link> | ||
| )} | ||
|
Comment on lines
+113
to
+116
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| </div> | ||
| <StatusHeader | ||
| messageStatus={status} | ||
| isMessageFound={isMessageFound} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| import { useRouter } from 'next/router'; | ||
| import { useEffect, useRef, useState } from 'react'; | ||
|
|
||
| import { Fade, IconButton, RefreshIcon, useDebounce } from '@hyperlane-xyz/widgets'; | ||
|
|
@@ -10,6 +11,7 @@ import { | |
| SearchEmptyError, | ||
| SearchFetching, | ||
| SearchInvalidError, | ||
| SearchRedirecting, | ||
| SearchUnknownError, | ||
| } from '../../components/search/SearchStates'; | ||
| import { useReadyMultiProvider } from '../../store'; | ||
|
|
@@ -130,6 +132,46 @@ export function MessageSearch() { | |
| const isAnyMessageFound = isMessagesFound || isPiMessagesFound; | ||
| const messageListResult = isMessagesFound ? messageList : piMessageList; | ||
|
|
||
| // Compute redirect URL for direct message/tx lookups | ||
| const router = useRouter(); | ||
| const redirectUrl = (() => { | ||
| // Wait for queries to complete | ||
| if (!hasAllRun || isAnyFetching) return null; | ||
|
|
||
| // Don't redirect without user input (prevents redirect on homepage with latest messages) | ||
| if (!hasInput) return null; | ||
|
|
||
| // Don't redirect if filters are applied | ||
| if (originChainFilter || destinationChainFilter || startTimeFilter || endTimeFilter) | ||
| return null; | ||
|
|
||
| // Need at least one result | ||
| if (!messageListResult.length) return null; | ||
|
|
||
| const firstMessage = messageListResult[0]; | ||
|
|
||
| // Single result → always go to message page | ||
| if (messageListResult.length === 1) { | ||
| return `/message/${firstMessage.msgId}`; | ||
| } | ||
|
yorhodes marked this conversation as resolved.
|
||
|
|
||
| // Multiple results + origin tx hash match → go to tx page | ||
| // Only redirect if GraphQL found results (tx page uses GraphQL only, not PI) | ||
| const inputLower = sanitizedInput.toLowerCase(); | ||
| if (isMessagesFound && firstMessage.origin?.hash?.toLowerCase() === inputLower) { | ||
| return `/tx/${firstMessage.origin.hash}`; | ||
| } | ||
|
|
||
| return null; | ||
| })(); | ||
|
Comment on lines
+229
to
+258
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rather than using a |
||
|
|
||
| // Perform the redirect | ||
| useEffect(() => { | ||
| if (redirectUrl) { | ||
| router.replace(redirectUrl); | ||
| } | ||
| }, [redirectUrl, router]); | ||
|
Comment on lines
+261
to
+265
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use |
||
|
|
||
| // Show message list if there are no errors and filters are valid | ||
| const showMessageTable = | ||
| !isAnyError && | ||
|
|
@@ -176,22 +218,28 @@ export function MessageSearch() { | |
| <RefreshButton loading={isAnyFetching} onClick={refetch} /> | ||
| </div> | ||
| </div> | ||
| <Fade show={showMessageTable}> | ||
| <SearchRedirecting show={!!redirectUrl} /> | ||
| <Fade show={showMessageTable && !redirectUrl}> | ||
| <MessageTable messageList={messageListResult} isFetching={isAnyFetching} /> | ||
| </Fade> | ||
| <SearchFetching | ||
| show={!isAnyError && isValidInput && !isAnyMessageFound && !hasAllRun} | ||
| show={!redirectUrl && !isAnyError && isValidInput && !isAnyMessageFound && !hasAllRun} | ||
| isPiFetching={isPiFetching} | ||
| /> | ||
| <SearchEmptyError | ||
| show={!isAnyError && isValidInput && !isAnyMessageFound && hasAllRun} | ||
| show={!redirectUrl && !isAnyError && isValidInput && !isAnyMessageFound && hasAllRun} | ||
| hasInput={hasInput} | ||
| allowAddress={true} | ||
| /> | ||
| <SearchUnknownError show={isAnyError && isValidInput} /> | ||
| <SearchInvalidError show={!isValidInput} allowAddress={true} /> | ||
| <SearchUnknownError show={!redirectUrl && isAnyError && isValidInput} /> | ||
| <SearchInvalidError show={!redirectUrl && !isValidInput} allowAddress={true} /> | ||
| <SearchChainError | ||
| show={(!isValidOrigin || !isValidDestination) && isValidInput && !!multiProvider} | ||
| show={ | ||
| !redirectUrl && | ||
| (!isValidOrigin || !isValidDestination) && | ||
| isValidInput && | ||
| !!multiProvider | ||
| } | ||
| /> | ||
| </Card> | ||
| </> | ||
|
|
||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in practice this text never actually shows up and it just flashes me from the search page to the tx page