|
|
@ -1,7 +1,9 @@ |
|
|
|
import { useQuery } from '@tanstack/react-query'; |
|
|
|
import { useQuery } from '@tanstack/react-query'; |
|
|
|
|
|
|
|
import Image from 'next/future/image'; |
|
|
|
import { useState } from 'react'; |
|
|
|
import { useState } from 'react'; |
|
|
|
|
|
|
|
|
|
|
|
import { Fade } from '../../components/animation/Fade'; |
|
|
|
import { Fade } from '../../components/animation/Fade'; |
|
|
|
|
|
|
|
import { CopyButton } from '../../components/buttons/CopyButton'; |
|
|
|
import { SearchBar } from '../../components/search/SearchBar'; |
|
|
|
import { SearchBar } from '../../components/search/SearchBar'; |
|
|
|
import { |
|
|
|
import { |
|
|
|
NoSearchError, |
|
|
|
NoSearchError, |
|
|
@ -10,12 +12,13 @@ import { |
|
|
|
SearchUnknownError, |
|
|
|
SearchUnknownError, |
|
|
|
} from '../../components/search/SearchError'; |
|
|
|
} from '../../components/search/SearchError'; |
|
|
|
import { envDisplayValue } from '../../consts/environments'; |
|
|
|
import { envDisplayValue } from '../../consts/environments'; |
|
|
|
|
|
|
|
import ShrugIcon from '../../images/icons/shrug.svg'; |
|
|
|
import { useStore } from '../../store'; |
|
|
|
import { useStore } from '../../store'; |
|
|
|
import useDebounce from '../../utils/debounce'; |
|
|
|
import useDebounce from '../../utils/debounce'; |
|
|
|
import { sanitizeString } from '../../utils/string'; |
|
|
|
import { sanitizeString } from '../../utils/string'; |
|
|
|
import { isValidSearchQuery } from '../search/utils'; |
|
|
|
import { isValidSearchQuery } from '../search/utils'; |
|
|
|
|
|
|
|
|
|
|
|
import { debugMessageForHash } from './debugMessage'; |
|
|
|
import { MessageDebugResult, TxDebugStatus, debugMessageForHash } from './debugMessage'; |
|
|
|
|
|
|
|
|
|
|
|
export function TxDebugger() { |
|
|
|
export function TxDebugger() { |
|
|
|
const environment = useStore((s) => s.environment); |
|
|
|
const environment = useStore((s) => s.environment); |
|
|
@ -49,11 +52,15 @@ export function TxDebugger() { |
|
|
|
placeholder="Search transaction hash to debug message" |
|
|
|
placeholder="Search transaction hash to debug message" |
|
|
|
/> |
|
|
|
/> |
|
|
|
<div className="w-full h-[38.05rem] mt-5 bg-white shadow-md border border-blue-50 rounded overflow-auto relative"> |
|
|
|
<div className="w-full h-[38.05rem] mt-5 bg-white shadow-md border border-blue-50 rounded overflow-auto relative"> |
|
|
|
<div className="px-2 py-3 sm:px-4 md:px-5 md:py-3 flex items-center justify-between border-b border-gray-100"> |
|
|
|
<div className="px-2 py-3 sm:px-4 md:px-5 flex items-center justify-between border-b border-gray-100"> |
|
|
|
<h2 className="text-gray-600">{`Transaction Debugger (${envDisplayValue[environment]})`}</h2> |
|
|
|
<h2 className="text-gray-600">{`Transaction Debugger (${envDisplayValue[environment]})`}</h2> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<Fade show={isValidInput && !hasError && !!data}>{JSON.stringify(data)}</Fade> |
|
|
|
<Fade show={isValidInput && !hasError && !!data}> |
|
|
|
|
|
|
|
<div className="px-2 sm:px-4 md:px-5"> |
|
|
|
|
|
|
|
<DebugResult result={data} /> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</Fade> |
|
|
|
<SearchEmptyError |
|
|
|
<SearchEmptyError |
|
|
|
show={isValidInput && !hasError && !fetching && !data} |
|
|
|
show={isValidInput && !hasError && !fetching && !data} |
|
|
|
hasInput={hasInput} |
|
|
|
hasInput={hasInput} |
|
|
@ -66,3 +73,73 @@ export function TxDebugger() { |
|
|
|
</> |
|
|
|
</> |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function DebugResult({ result }: { result: MessageDebugResult | null | undefined }) { |
|
|
|
|
|
|
|
if (!result) return null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (result.status === TxDebugStatus.NotFound) { |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<div className="py-8 flex flex-col items-center"> |
|
|
|
|
|
|
|
<Image src={ShrugIcon} width={110} className="opacity-80" /> |
|
|
|
|
|
|
|
<h2 className="mt-4 text-lg text-gray-600">No transaction found</h2> |
|
|
|
|
|
|
|
<p className="mt-4 leading-relaxed">{result.details}</p> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (result.status === TxDebugStatus.NoMessages) { |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<div className="py-8 flex flex-col items-center"> |
|
|
|
|
|
|
|
<Image src={ShrugIcon} width={110} className="opacity-80" /> |
|
|
|
|
|
|
|
<h2 className="mt-4 text-lg text-gray-600">No message found</h2> |
|
|
|
|
|
|
|
<p className="mt-4 leading-relaxed">{result.details}</p> |
|
|
|
|
|
|
|
<TxExplorerLink href={result.explorerLink} /> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (result.status === TxDebugStatus.MessagesFound) { |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<> |
|
|
|
|
|
|
|
{result.messageDetails.map((m, i) => ( |
|
|
|
|
|
|
|
<div className="border-b border-gray-200 py-4" key={`message-${i}`}> |
|
|
|
|
|
|
|
<h2 className="text-lg text-gray-600">{`Message ${i + 1} / ${ |
|
|
|
|
|
|
|
result.messageDetails.length |
|
|
|
|
|
|
|
}`}</h2>
|
|
|
|
|
|
|
|
<p className="mt-2 leading-relaxed">{m.summary}</p> |
|
|
|
|
|
|
|
<div className="mt-2 text-sm"> |
|
|
|
|
|
|
|
{Array.from(m.properties.entries()).map(([key, val]) => ( |
|
|
|
|
|
|
|
<div className="flex mt-1" key={`message-${i}-prop-${key}`}> |
|
|
|
|
|
|
|
<label className="text-gray-600 w-32">{key}</label> |
|
|
|
|
|
|
|
<div className="relative ml-2 truncate max-w-xs sm:max-w-sm md:max-w-lg"> |
|
|
|
|
|
|
|
{val} |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
{val.length > 20 && ( |
|
|
|
|
|
|
|
<CopyButton copyValue={val} width={12} height={12} classes="ml-2" /> |
|
|
|
|
|
|
|
)} |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
))} |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
))} |
|
|
|
|
|
|
|
<TxExplorerLink href={result.explorerLink} /> |
|
|
|
|
|
|
|
</> |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function TxExplorerLink({ href }: { href: string | undefined }) { |
|
|
|
|
|
|
|
if (!href) return null; |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<a |
|
|
|
|
|
|
|
className="block my-5 text-blue-600 hover:text-blue-500 underline underline-offset-4" |
|
|
|
|
|
|
|
href={href} |
|
|
|
|
|
|
|
target="_blank" |
|
|
|
|
|
|
|
rel="noopener noreferrer" |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
View transaction in explorer |
|
|
|
|
|
|
|
</a> |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|