explorer: transaction hashes & links to explorers
Change-Id: Id262184f6c61c301f3d09f502b23d88c62b94e8d
This commit is contained in:
parent
84de7c2fd0
commit
aff990487d
|
@ -87,6 +87,6 @@ GATSBY_MAINNET_BSC_CORE_BRIDGE=0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B
|
||||||
GATSBY_MAINNET_BSC_TOKEN_BRIDGE=0xB6F6D86a8f9879A9c87f643768d9efc38c1Da6E7
|
GATSBY_MAINNET_BSC_TOKEN_BRIDGE=0xB6F6D86a8f9879A9c87f643768d9efc38c1Da6E7
|
||||||
GATSBY_MAINNET_BSC_NFT_BRIDGE=0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE
|
GATSBY_MAINNET_BSC_NFT_BRIDGE=0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE
|
||||||
|
|
||||||
GATSBY_MAINNET_POLYGON_CORE_BRIDGE=0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B
|
GATSBY_MAINNET_POLYGON_CORE_BRIDGE=0x7A4B5a56256163F07b2C80A7cA55aBE66c4ec4d7
|
||||||
GATSBY_MAINNET_POLYGON_TOKEN_BRIDGE=0xB6F6D86a8f9879A9c87f643768d9efc38c1Da6E7
|
GATSBY_MAINNET_POLYGON_TOKEN_BRIDGE=0x5a58505a96d1dbf8df91cb21b54419fc36e93fde
|
||||||
GATSBY_MAINNET_POLYGON_NFT_BRIDGE=0x5a58505a96D1dbf8dF91cB21B54419FC36e93fdE
|
GATSBY_MAINNET_POLYGON_NFT_BRIDGE=0x90bbd86a6fe93d3bc3ed6335935447e75fab7fcf
|
||||||
|
|
|
@ -3,13 +3,14 @@ import { Spin, Typography } from 'antd'
|
||||||
const { Title } = Typography
|
const { Title } = Typography
|
||||||
|
|
||||||
import { FormattedMessage } from 'gatsby-plugin-intl'
|
import { FormattedMessage } from 'gatsby-plugin-intl'
|
||||||
import { arrayify, isHexString, zeroPad } from "ethers/lib/utils";
|
import { arrayify, isHexString, zeroPad, hexlify } from "ethers/lib/utils";
|
||||||
import { Bech32, toHex } from "@cosmjs/encoding"
|
import { Bech32, toHex, fromHex } from "@cosmjs/encoding"
|
||||||
import { ExplorerSummary } from '~/components/ExplorerSummary';
|
import { ExplorerSummary } from '~/components/ExplorerSummary';
|
||||||
import { titleStyles } from '~/styles';
|
import { titleStyles } from '~/styles';
|
||||||
import { NetworkContext } from '~/components/NetworkSelect';
|
import { NetworkContext } from '~/components/NetworkSelect';
|
||||||
import { getEmitterAddressSolana } from "@certusone/wormhole-sdk";
|
import { getEmitterAddressSolana } from "@certusone/wormhole-sdk";
|
||||||
import { chainIDs } from '~/utils/misc/constants';
|
import { ChainIDs, chainIDs } from '~/utils/misc/constants';
|
||||||
|
import { PublicKey } from '@solana/web3.js';
|
||||||
|
|
||||||
export interface VAA {
|
export interface VAA {
|
||||||
Version: number | string,
|
Version: number | string,
|
||||||
|
@ -25,10 +26,10 @@ export interface VAA {
|
||||||
}
|
}
|
||||||
export interface BigTableMessage {
|
export interface BigTableMessage {
|
||||||
InitiatingTxID?: string
|
InitiatingTxID?: string
|
||||||
SignedVAABytes: string // base64 encoded byte array
|
SignedVAABytes?: string // base64 encoded byte array
|
||||||
SignedVAA: VAA
|
SignedVAA?: VAA
|
||||||
QuorumTime: string // "2021-08-11 00:16:11.757 +0000 UTC"
|
QuorumTime?: string // "2021-08-11 00:16:11.757 +0000 UTC"
|
||||||
EmitterChain: "solana" | "ethereum" | "terra" | "bsc"
|
EmitterChain: keyof ChainIDs
|
||||||
EmitterAddress: string
|
EmitterAddress: string
|
||||||
Sequence: string
|
Sequence: string
|
||||||
}
|
}
|
||||||
|
@ -98,14 +99,31 @@ const ExplorerQuery = (props: ExplorerQuery) => {
|
||||||
|
|
||||||
if (sequence.length <= 15) {
|
if (sequence.length <= 15) {
|
||||||
paddedSequence = sequence.padStart(16, "0")
|
paddedSequence = sequence.padStart(16, "0")
|
||||||
} else if (sequence.length >= 17) {
|
|
||||||
paddedSequence = sequence.slice(-16)
|
|
||||||
} else {
|
} else {
|
||||||
paddedSequence = sequence
|
paddedSequence = sequence
|
||||||
}
|
}
|
||||||
url = `${base}/readrow?emitterChain=${emitterChain}&emitterAddress=${paddedAddress}&sequence=${paddedSequence}`
|
url = `${base}/readrow?emitterChain=${emitterChain}&emitterAddress=${paddedAddress}&sequence=${paddedSequence}`
|
||||||
} else if (txId) {
|
} else if (txId) {
|
||||||
url = `${base}/transaction?id=${txId}`
|
let transformedTxId = txId
|
||||||
|
if (isHexString(txId)) {
|
||||||
|
// valid hexString, no transformation needed.
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
let pubKey = new PublicKey(txId).toBytes()
|
||||||
|
let solHex = hexlify(pubKey)
|
||||||
|
transformedTxId = solHex
|
||||||
|
} catch (_) {
|
||||||
|
// not solana, try terra
|
||||||
|
try {
|
||||||
|
let arr = fromHex(txId)
|
||||||
|
let terraHex = hexlify(arr)
|
||||||
|
transformedTxId = terraHex
|
||||||
|
} catch (_) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
url = `${base}/transaction?id=${transformedTxId}`
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(url)
|
fetch(url)
|
||||||
|
|
|
@ -65,8 +65,8 @@ const ChainOverviewCard: React.FC<ChainOverviewCardProps> = ({ Icon, iconStyle,
|
||||||
loading ? "loading" : intl.formatMessage({ id: "explorer.comingSoon" })}>
|
loading ? "loading" : intl.formatMessage({ id: "explorer.comingSoon" })}>
|
||||||
<Card
|
<Card
|
||||||
style={{
|
style={{
|
||||||
width: 200,
|
width: 190,
|
||||||
paddingTop: 10
|
paddingTop: 10,
|
||||||
}}
|
}}
|
||||||
className="hover-z-index"
|
className="hover-z-index"
|
||||||
cover={<Icon style={{ height: 140, ...iconStyle }} />}
|
cover={<Icon style={{ height: 140, ...iconStyle }} />}
|
||||||
|
@ -86,11 +86,11 @@ const ChainOverviewCard: React.FC<ChainOverviewCardProps> = ({ Icon, iconStyle,
|
||||||
{!!totalCount ? (
|
{!!totalCount ? (
|
||||||
<>
|
<>
|
||||||
<div style={{ display: 'flex', justifyContent: "space-between", alignItems: 'center', gap: 12 }}>
|
<div style={{ display: 'flex', justifyContent: "space-between", alignItems: 'center', gap: 12 }}>
|
||||||
<div><Text type="secondary" style={{ fontSize: 14 }}>last 24 hours</Text></div>
|
<div><Text type="secondary" style={{ fontSize: 14 }}>last 24 hours</Text></div>
|
||||||
<div><Text className={animate ? "highlight-new-val" : ""} style={{ fontSize: 26 }}>{lastDayCount}</Text></div>
|
<div><Text className={animate ? "highlight-new-val" : ""} style={{ fontSize: 26 }}>{lastDayCount}</Text></div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', justifyContent: "center", alignItems: 'center', gap: 12 }}>
|
<div style={{ display: 'flex', justifyContent: "center", alignItems: 'center', gap: 12 }}>
|
||||||
<div><Text type="secondary" style={{ fontSize: 14 }}>last {totalDays} days</Text></div>
|
<div><Text type="secondary" style={{ fontSize: 14 }}>last {totalDays} days</Text></div>
|
||||||
<div><Text className={animate ? "highlight-new-val" : ""} style={{ fontSize: 26 }}>{totalCount}</Text></div>
|
<div><Text className={animate ? "highlight-new-val" : ""} style={{ fontSize: 26 }}>{totalCount}</Text></div>
|
||||||
</div>
|
</div>
|
||||||
{/* <Statistic title={<span>last 24 hours</span>} value={totals?.LastDayCount[dataKey]} style={{ display: 'flex', justifyContent: "space-between", alignItems: 'center', gap: 12 }} valueStyle={{ fontSize: 26 }} /> */}
|
{/* <Statistic title={<span>last 24 hours</span>} value={totals?.LastDayCount[dataKey]} style={{ display: 'flex', justifyContent: "space-between", alignItems: 'center', gap: 12 }} valueStyle={{ fontSize: 26 }} /> */}
|
||||||
|
|
|
@ -177,7 +177,7 @@ const Stats: React.FC<StatsProps> = ({ emitterChain, emitterAddress }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!emitterChain && !emitterAddress &&
|
{!emitterChain && !emitterAddress &&
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-around', alignItems: 'flex-end', flexWrap: 'wrap', marginBottom: 40 }}>
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'flex-end', flexWrap: 'wrap', marginBottom: 40, gap: 20 }}>
|
||||||
<ChainOverviewCard totalDays={daysSinceDataStart} totals={totals} dataKey="1" title={ChainID[1]} Icon={SolanaIcon} iconStyle={{ height: 120, margin: '10px 0' }} />
|
<ChainOverviewCard totalDays={daysSinceDataStart} totals={totals} dataKey="1" title={ChainID[1]} Icon={SolanaIcon} iconStyle={{ height: 120, margin: '10px 0' }} />
|
||||||
<ChainOverviewCard totalDays={daysSinceDataStart} totals={totals} dataKey="2" title={ChainID[2]} Icon={EthereumIcon} />
|
<ChainOverviewCard totalDays={daysSinceDataStart} totals={totals} dataKey="2" title={ChainID[2]} Icon={EthereumIcon} />
|
||||||
<ChainOverviewCard totalDays={daysSinceDataStart} totals={totals} dataKey="3" title={ChainID[3]} Icon={TerraIcon} />
|
<ChainOverviewCard totalDays={daysSinceDataStart} totals={totals} dataKey="3" title={ChainID[3]} Icon={TerraIcon} />
|
||||||
|
|
|
@ -55,13 +55,13 @@ const RecentMessages = (props: RecentMessagesProps) => {
|
||||||
{
|
{
|
||||||
title: "message",
|
title: "message",
|
||||||
key: "payload",
|
key: "payload",
|
||||||
render: (item: BigTableMessage) => <DecodePayload
|
render: (item: BigTableMessage) => item.SignedVAABytes ? <DecodePayload
|
||||||
base64VAA={item.SignedVAABytes}
|
base64VAA={item.SignedVAABytes}
|
||||||
emitterChainName={item.EmitterChain}
|
emitterChainName={item.EmitterChain}
|
||||||
emitterAddress={item.EmitterAddress}
|
emitterAddress={item.EmitterAddress}
|
||||||
showType={true}
|
showType={true}
|
||||||
showSummary={true}
|
showSummary={true}
|
||||||
/>
|
/> : null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "sequence",
|
title: "sequence",
|
||||||
|
|
|
@ -30,7 +30,7 @@ const makeGroupName = (groupKey: string, activeNetwork: ActiveNetwork, emitterCh
|
||||||
const getNativeAddress = (chainId: number, emitterAddress: string, activeNetwork?: ActiveNetwork): string => {
|
const getNativeAddress = (chainId: number, emitterAddress: string, activeNetwork?: ActiveNetwork): string => {
|
||||||
let nativeAddress = ""
|
let nativeAddress = ""
|
||||||
|
|
||||||
if (chainId === chainIDs["ethereum"] || chainId === chainIDs["bsc"]) {
|
if (chainId === chainIDs["ethereum"] || chainId === chainIDs["bsc"] || chainId === chainIDs["polygon"]) {
|
||||||
// remove zero-padding
|
// remove zero-padding
|
||||||
let unpadded = emitterAddress.slice(-40)
|
let unpadded = emitterAddress.slice(-40)
|
||||||
nativeAddress = `0x${unpadded}`.toLowerCase()
|
nativeAddress = `0x${unpadded}`.toLowerCase()
|
||||||
|
@ -81,7 +81,7 @@ const contractNameFormatter = (address: string, chainId: number, activeNetwork?:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const nativeExplorerUri = (chainId: number, address: string, activeNetwork?: ActiveNetwork): string => {
|
const nativeExplorerContractUri = (chainId: number, address: string, activeNetwork?: ActiveNetwork): string => {
|
||||||
if (!activeNetwork) {
|
if (!activeNetwork) {
|
||||||
activeNetwork = useContext(NetworkContext).activeNetwork
|
activeNetwork = useContext(NetworkContext).activeNetwork
|
||||||
}
|
}
|
||||||
|
@ -100,17 +100,40 @@ const nativeExplorerUri = (chainId: number, address: string, activeNetwork?: Act
|
||||||
} else if (chainId === chainIDs["bsc"]) {
|
} else if (chainId === chainIDs["bsc"]) {
|
||||||
let base = "https://bscscan.com/address/"
|
let base = "https://bscscan.com/address/"
|
||||||
return `${base}${nativeAddress}`
|
return `${base}${nativeAddress}`
|
||||||
|
} else if (chainId === chainIDs["polygon"]) {
|
||||||
|
let base = "https://polygonscan.com/address/"
|
||||||
|
return `${base}${nativeAddress}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
const nativeExplorerTxUri = (chainId: number, transactionId: string): string => {
|
||||||
|
if (chainId === chainIDs["solana"]) {
|
||||||
|
let base = "https://explorer.solana.com/address/"
|
||||||
|
return `${base}${transactionId}`
|
||||||
|
} else if (chainId === chainIDs["ethereum"]) {
|
||||||
|
let base = "https://etherscan.io/tx/"
|
||||||
|
return `${base}${transactionId}`
|
||||||
|
} else if (chainId === chainIDs["terra"]) {
|
||||||
|
let base = "https://finder.terra.money/columbus-5/tx/"
|
||||||
|
return `${base}${transactionId}`
|
||||||
|
} else if (chainId === chainIDs["bsc"]) {
|
||||||
|
let base = "https://bscscan.com/tx/"
|
||||||
|
return `${base}${transactionId}`
|
||||||
|
} else if (chainId === chainIDs["polygon"]) {
|
||||||
|
let base = "https://polygonscan.com/tx/"
|
||||||
|
return `${base}${transactionId}`
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
const chainColors: { [chain: string]: string } = {
|
const chainColors: { [chain: string]: string } = {
|
||||||
"*": "hsl(183, 100%, 61%)",
|
"*": "hsl(183, 100%, 61%)",
|
||||||
"1": "hsl(297, 100%, 61%)",
|
"1": "hsl(297, 100%, 61%)",
|
||||||
"2": "hsl(235, 5%, 43%)",
|
"2": "hsl(235, 5%, 43%)",
|
||||||
"3": "hsl(235, 100%, 61%)",
|
"3": "hsl(235, 100%, 61%)",
|
||||||
"4": "hsl(54, 100%, 61%)"
|
"4": "hsl(54, 100%, 61%)",
|
||||||
|
"5": "hsl(271, 100%, 61%)",
|
||||||
}
|
}
|
||||||
|
|
||||||
export { makeDate, makeGroupName, chainColors, truncateAddress, contractNameFormatter, nativeExplorerUri }
|
export { makeDate, makeGroupName, chainColors, truncateAddress, contractNameFormatter, nativeExplorerContractUri, nativeExplorerTxUri }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect } from 'react';
|
import React from 'react';
|
||||||
import { Button, Spin, Typography } from 'antd'
|
import { Button, Spin, Typography } from 'antd'
|
||||||
const { Title } = Typography
|
const { Title } = Typography
|
||||||
import { useIntl, FormattedMessage } from 'gatsby-plugin-intl'
|
import { useIntl, FormattedMessage } from 'gatsby-plugin-intl'
|
||||||
|
@ -8,8 +8,10 @@ import ReactTimeAgo from 'react-time-ago'
|
||||||
import { titleStyles } from '~/styles';
|
import { titleStyles } from '~/styles';
|
||||||
import { CloseOutlined, ReloadOutlined } from '@ant-design/icons';
|
import { CloseOutlined, ReloadOutlined } from '@ant-design/icons';
|
||||||
import { Link } from 'gatsby';
|
import { Link } from 'gatsby';
|
||||||
import { contractNameFormatter, nativeExplorerUri } from '../ExplorerStats/utils';
|
import { contractNameFormatter, nativeExplorerContractUri, nativeExplorerTxUri } from '../ExplorerStats/utils';
|
||||||
import { OutboundLink } from 'gatsby-plugin-google-gtag';
|
import { OutboundLink } from 'gatsby-plugin-google-gtag';
|
||||||
|
import { chainIDs } from '~/utils/misc/constants';
|
||||||
|
import { hexToNativeString } from '@certusone/wormhole-sdk';
|
||||||
|
|
||||||
interface SummaryProps {
|
interface SummaryProps {
|
||||||
emitterChain?: number,
|
emitterChain?: number,
|
||||||
|
@ -27,6 +29,24 @@ const Summary = (props: SummaryProps) => {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const { SignedVAA, ...message } = props.message
|
const { SignedVAA, ...message } = props.message
|
||||||
|
|
||||||
|
const { EmitterChain, EmitterAddress, InitiatingTxID } = message
|
||||||
|
// get chainId from chain name
|
||||||
|
let chainId = chainIDs[EmitterChain]
|
||||||
|
|
||||||
|
let transactionId: string | undefined
|
||||||
|
if (InitiatingTxID) {
|
||||||
|
if (chainId === chainIDs["ethereum"] || chainId === chainIDs["bsc"] || chainId === chainIDs["polygon"]) {
|
||||||
|
transactionId = InitiatingTxID
|
||||||
|
} else {
|
||||||
|
if (chainId === chainIDs["solana"]) {
|
||||||
|
const txId = InitiatingTxID.slice(2) // remove the leading "0x"
|
||||||
|
transactionId = hexToNativeString(txId, chainId)
|
||||||
|
} else if (chainId === chainIDs["terra"]) {
|
||||||
|
transactionId = InitiatingTxID.slice(2) // remove the leading "0x"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'baseline' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'baseline' }}>
|
||||||
|
@ -63,18 +83,7 @@ const Summary = (props: SummaryProps) => {
|
||||||
style={{ fontSize: 12, marginBottom: 20 }}
|
style={{ fontSize: 12, marginBottom: 20 }}
|
||||||
>{JSON.stringify(SignedVAA, undefined, 2)}</pre>
|
>{JSON.stringify(SignedVAA, undefined, 2)}</pre>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: "flex-end" }}>
|
||||||
|
|
||||||
{props.emitterChain && props.emitterAddress && nativeExplorerUri(props.emitterChain, props.emitterAddress) ?
|
|
||||||
<OutboundLink
|
|
||||||
href={nativeExplorerUri(props.emitterChain, props.emitterAddress)}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
style={{ fontSize: 16 }}
|
|
||||||
>
|
|
||||||
{'View "'}{contractNameFormatter(props.emitterAddress, props.emitterChain)}{'" emitter contract on native explorer'}
|
|
||||||
</OutboundLink> : <div />}
|
|
||||||
|
|
||||||
{props.lastFetched ? (
|
{props.lastFetched ? (
|
||||||
<span>
|
<span>
|
||||||
<FormattedMessage id="explorer.lastUpdated" />:
|
<FormattedMessage id="explorer.lastUpdated" />:
|
||||||
|
@ -83,6 +92,26 @@ const Summary = (props: SummaryProps) => {
|
||||||
|
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', }}>
|
||||||
|
{EmitterChain && EmitterAddress && nativeExplorerContractUri(chainId, EmitterAddress) ?
|
||||||
|
<OutboundLink
|
||||||
|
href={nativeExplorerContractUri(chainId, EmitterAddress)}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ fontSize: 16, marginBottom: '6px 0' }}
|
||||||
|
>
|
||||||
|
{'View "'}{contractNameFormatter(EmitterAddress, chainId)}{'" contract on native explorer'}
|
||||||
|
</OutboundLink> : <div />}
|
||||||
|
{transactionId && EmitterChain ?
|
||||||
|
<OutboundLink
|
||||||
|
href={nativeExplorerTxUri(chainId, transactionId)}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ fontSize: 16, margin: '6px 0' }}
|
||||||
|
>
|
||||||
|
{'View transaction "'}{transactionId}{'" on native explorer'}
|
||||||
|
</OutboundLink> : <div />}
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ const parseAssetMetaPayload = (arr: Buffer): AssetMetaPayload => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function useBase64ToBuffer(base64VAA: string) {
|
function useBase64ToBuffer(base64VAA: string = "") {
|
||||||
const [buf, setBuf] = useState<Buffer>()
|
const [buf, setBuf] = useState<Buffer>()
|
||||||
|
|
||||||
function convertbase64ToBinary(base64: string) {
|
function convertbase64ToBinary(base64: string) {
|
||||||
|
@ -177,7 +177,7 @@ function useBase64ToBuffer(base64VAA: string) {
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
interface DecodePayloadProps {
|
interface DecodePayloadProps {
|
||||||
base64VAA: string
|
base64VAA?: string
|
||||||
emitterChainName: keyof ChainIDs
|
emitterChainName: keyof ChainIDs
|
||||||
emitterAddress: string
|
emitterAddress: string
|
||||||
showType?: boolean
|
showType?: boolean
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { WithNetwork, NetworkSelect } from '~/components/NetworkSelect'
|
||||||
import { ExplorerSearchForm, ExplorerTxForm } from '~/components/App/ExplorerSearch';
|
import { ExplorerSearchForm, ExplorerTxForm } from '~/components/App/ExplorerSearch';
|
||||||
import { ChainID } from '~/utils/misc/constants';
|
import { ChainID } from '~/utils/misc/constants';
|
||||||
import { OutboundLink } from 'gatsby-plugin-google-gtag';
|
import { OutboundLink } from 'gatsby-plugin-google-gtag';
|
||||||
import { nativeExplorerUri } from '~/components/ExplorerStats/utils';
|
import { nativeExplorerContractUri } from '~/components/ExplorerStats/utils';
|
||||||
import { CloseOutlined } from '@ant-design/icons';
|
import { CloseOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,9 +127,9 @@ const Explorer: React.FC<ExplorerProps> = ({ location, navigate }) => {
|
||||||
// show heading with the context of the address
|
// show heading with the context of the address
|
||||||
<Title level={3} style={{ ...titleStyles }}>
|
<Title level={3} style={{ ...titleStyles }}>
|
||||||
Recent messages from {ChainID[emitterChain]}
|
Recent messages from {ChainID[emitterChain]}
|
||||||
{nativeExplorerUri(emitterChain, emitterAddress) ?
|
{nativeExplorerContractUri(emitterChain, emitterAddress) ?
|
||||||
<OutboundLink
|
<OutboundLink
|
||||||
href={nativeExplorerUri(emitterChain, emitterAddress)}
|
href={nativeExplorerContractUri(emitterChain, emitterAddress)}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue