mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
token transfers and call data
This commit is contained in:
@@ -47,4 +47,6 @@ export type UserOp = {
|
||||
signature: string;
|
||||
nonce: string;
|
||||
call_data: string;
|
||||
user_logs_start_index: number;
|
||||
user_logs_count: number;
|
||||
}
|
||||
|
||||
+22
-4
@@ -1,6 +1,8 @@
|
||||
import { inRange } from 'lodash';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import type { TokenTransfer } from 'types/api/tokenTransfer';
|
||||
import type { RoutedTab } from 'ui/shared/Tabs/types';
|
||||
|
||||
import useApiQuery from 'lib/api/useApiQuery';
|
||||
@@ -13,6 +15,8 @@ import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TabsSkeleton from 'ui/shared/Tabs/TabsSkeleton';
|
||||
import TxTokenTransfer from 'ui/tx/TxTokenTransfer';
|
||||
import UserOpCallData from 'ui/userOp/UserOpCallData';
|
||||
import UserOpDetails from 'ui/userOp/UserOpDetails';
|
||||
|
||||
const TAB_LIST_PROPS = {
|
||||
@@ -35,14 +39,28 @@ const BlockPageContent = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const filterTokenTransfersByLogIndex = React.useCallback((tt: TokenTransfer) => {
|
||||
if (!userOpQuery.data) {
|
||||
return true;
|
||||
} else {
|
||||
if (inRange(Number(tt.log_index), userOpQuery.data.user_logs_start_index, userOpQuery.data.user_logs_start_index + userOpQuery.data.user_logs_count)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, [ userOpQuery.data ]);
|
||||
|
||||
const tabs: Array<RoutedTab> = React.useMemo(() => ([
|
||||
{ id: 'index', title: 'Details', component: <UserOpDetails query={ userOpQuery }/> },
|
||||
{ id: 'token_transfers', title: 'Token transfers', component: null },
|
||||
// { id: 'token_transfers', title: 'Token transfers', component: <UserOpTokenTransfers txHash={ userOpQuery.data?.transaction_hash }/> },
|
||||
// { id: 'call_data', title: 'Call data', component: <UserOpCallData callData={ userOpQuery.data?.call_data }/> }
|
||||
{
|
||||
id: 'token_transfers',
|
||||
title: 'Token transfers',
|
||||
component: <TxTokenTransfer txHash={ userOpQuery.data?.transaction_hash } tokenTransferFilter={ filterTokenTransfersByLogIndex }/>,
|
||||
},
|
||||
{ id: 'call_data', title: 'Call data', component: <UserOpCallData rawCallData={ userOpQuery.data?.call_data }/> },
|
||||
// { id: 'logs', title: 'Logs', component: <UserOpLogs txHash={ userOpQuery.data?.transaction_hash }/> }
|
||||
// { id: 'raw', title: 'Raw', component: <UserOpRaw txHash={ userOpQuery.data?.transaction_hash }/> }
|
||||
].filter(Boolean)), [ userOpQuery ]);
|
||||
].filter(Boolean)), [ userOpQuery, filterTokenTransfersByLogIndex ]);
|
||||
|
||||
if (!hash) {
|
||||
throw new Error('User operation not found', { cause: { status: 404 } });
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import type { TokenType } from 'types/api/token';
|
||||
import type { TokenTransfer } from 'types/api/tokenTransfer';
|
||||
|
||||
import { SECOND } from 'lib/consts';
|
||||
import getFilterValuesFromQuery from 'lib/getFilterValuesFromQuery';
|
||||
@@ -23,8 +24,13 @@ import useFetchTxInfo from 'ui/tx/useFetchTxInfo';
|
||||
|
||||
const getTokenFilterValue = (getFilterValuesFromQuery<TokenType>).bind(null, TOKEN_TYPE_IDS);
|
||||
|
||||
const TxTokenTransfer = () => {
|
||||
const txsInfo = useFetchTxInfo({ updateDelay: 5 * SECOND });
|
||||
type Props = {
|
||||
txHash?: string;
|
||||
tokenTransferFilter?: (tt: TokenTransfer) => boolean;
|
||||
}
|
||||
|
||||
const TxTokenTransfer = ({ txHash, tokenTransferFilter }: Props) => {
|
||||
const txsInfo = useFetchTxInfo({ updateDelay: 5 * SECOND, txHash });
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -56,13 +62,23 @@ const TxTokenTransfer = () => {
|
||||
const numActiveFilters = typeFilter.length;
|
||||
const isActionBarHidden = !numActiveFilters && !tokenTransferQuery.data?.items.length;
|
||||
|
||||
let items: Array<TokenTransfer> = [];
|
||||
|
||||
if (tokenTransferQuery.data?.items) {
|
||||
if (tokenTransferQuery.isPlaceholderData) {
|
||||
items = tokenTransferQuery.data?.items;
|
||||
} else {
|
||||
items = tokenTransferFilter ? tokenTransferQuery.data.items.filter(tokenTransferFilter) : tokenTransferQuery.data.items;
|
||||
}
|
||||
}
|
||||
|
||||
const content = tokenTransferQuery.data?.items ? (
|
||||
<>
|
||||
<Hide below="lg" ssr={ false }>
|
||||
<TokenTransferTable data={ tokenTransferQuery.data?.items } top={ isActionBarHidden ? 0 : 80 } isLoading={ tokenTransferQuery.isPlaceholderData }/>
|
||||
<TokenTransferTable data={ items } top={ isActionBarHidden ? 0 : 80 } isLoading={ tokenTransferQuery.isPlaceholderData }/>
|
||||
</Hide>
|
||||
<Show below="lg" ssr={ false }>
|
||||
<TokenTransferList data={ tokenTransferQuery.data?.items } isLoading={ tokenTransferQuery.isPlaceholderData }/>
|
||||
<TokenTransferList data={ items } isLoading={ tokenTransferQuery.isPlaceholderData }/>
|
||||
</Show>
|
||||
</>
|
||||
) : null;
|
||||
@@ -82,7 +98,7 @@ const TxTokenTransfer = () => {
|
||||
return (
|
||||
<DataListDisplay
|
||||
isError={ txsInfo.isError || tokenTransferQuery.isError }
|
||||
items={ tokenTransferQuery.data?.items }
|
||||
items={ items }
|
||||
emptyText="There are no token transfers."
|
||||
filterProps={{
|
||||
emptyFilteredText: `Couldn${ apos }t find any token transfer that matches your query.`,
|
||||
|
||||
@@ -18,17 +18,18 @@ import { TX, TX_ZKEVM_L2 } from 'stubs/tx';
|
||||
interface Params {
|
||||
onTxStatusUpdate?: () => void;
|
||||
updateDelay?: number;
|
||||
txHash?: string;
|
||||
}
|
||||
|
||||
type ReturnType = UseQueryResult<Transaction, ResourceError<{ status: number }>> & {
|
||||
socketStatus: 'close' | 'error' | undefined;
|
||||
}
|
||||
|
||||
export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay }: Params | undefined = {}): ReturnType {
|
||||
export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay, txHash }: Params | undefined = {}): ReturnType {
|
||||
const router = useRouter();
|
||||
const queryClient = useQueryClient();
|
||||
const [ socketStatus, setSocketStatus ] = React.useState<'close' | 'error'>();
|
||||
const hash = getQueryParamString(router.query.hash);
|
||||
const hash = txHash || getQueryParamString(router.query.hash);
|
||||
|
||||
const queryResult = useApiQuery<'tx', { status: number }>('tx', {
|
||||
pathParams: { hash },
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
|
||||
import RawInputData from 'ui/shared/RawInputData';
|
||||
|
||||
// decoded calldata will be added later
|
||||
type Props = {
|
||||
rawCallData?: string;
|
||||
}
|
||||
|
||||
const UserOpCallData = ({ rawCallData }: Props) => {
|
||||
if (!rawCallData) {
|
||||
return null;
|
||||
}
|
||||
return <RawInputData hex={ rawCallData }/>;
|
||||
};
|
||||
|
||||
export default UserOpCallData;
|
||||
Reference in New Issue
Block a user