feat(explorer): highlight transfer types and add epoch overview
This commit is contained in:
parent
4d3cd74847
commit
429a4ca454
@ -8,12 +8,14 @@ import EpochMissingOverview from './epoch-missing';
|
||||
import { Icon, Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import type { IconProps } from '@vegaprotocol/ui-toolkit';
|
||||
import isPast from 'date-fns/isPast';
|
||||
import { EpochSymbol } from '../links/block-link/block-link';
|
||||
|
||||
const borderClass =
|
||||
'border-solid border-2 border-vega-dark-200 border-collapse';
|
||||
|
||||
export type EpochOverviewProps = {
|
||||
id?: string;
|
||||
icon?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -24,7 +26,7 @@ export type EpochOverviewProps = {
|
||||
*
|
||||
* The details are hidden in a tooltip, behind the epoch number
|
||||
*/
|
||||
const EpochOverview = ({ id }: EpochOverviewProps) => {
|
||||
const EpochOverview = ({ id, icon = true }: EpochOverviewProps) => {
|
||||
const { data, error, loading } = useExplorerEpochQuery({
|
||||
variables: { id: id || '' },
|
||||
});
|
||||
@ -38,7 +40,12 @@ const EpochOverview = ({ id }: EpochOverviewProps) => {
|
||||
}
|
||||
|
||||
if (!ti || loading || error) {
|
||||
return <span>{id}</span>;
|
||||
return (
|
||||
<span>
|
||||
<EpochSymbol />
|
||||
{id}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const description = (
|
||||
@ -90,7 +97,11 @@ const EpochOverview = ({ id }: EpochOverviewProps) => {
|
||||
return (
|
||||
<Tooltip description={description}>
|
||||
<p>
|
||||
<IconForEpoch start={ti.start} end={ti.end} />
|
||||
{icon ? (
|
||||
<IconForEpoch start={ti.start} end={ti.end} />
|
||||
) : (
|
||||
<EpochSymbol />
|
||||
)}
|
||||
{id}
|
||||
</p>
|
||||
</Tooltip>
|
||||
|
@ -5,6 +5,7 @@ import { Link } from 'react-router-dom';
|
||||
import type { ComponentProps } from 'react';
|
||||
import Hash from '../hash';
|
||||
import { useExplorerEpochForBlockQuery } from './__generated__/EpochByBlock';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
export type BlockLinkProps = Partial<ComponentProps<typeof Link>> & {
|
||||
height: string;
|
||||
@ -22,8 +23,6 @@ const BlockLink = ({ height, showEpoch = false, ...props }: BlockLinkProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const EpochSymbol = 'ⓔ';
|
||||
|
||||
export function EpochForBlock(props: { block: string }) {
|
||||
const { error, data, loading } = useExplorerEpochForBlockQuery({
|
||||
errorPolicy: 'ignore',
|
||||
@ -37,10 +36,24 @@ export function EpochForBlock(props: { block: string }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<span className="ml-2">
|
||||
{EpochSymbol} {data.epoch.id}
|
||||
<span className="ml-2" title={t('Epoch')}>
|
||||
<EpochSymbol />
|
||||
{data.epoch.id}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export const EPOCH_SYMBOL = 'ⓔ';
|
||||
|
||||
export function EpochSymbol() {
|
||||
return (
|
||||
<em
|
||||
title={t('Epoch')}
|
||||
className="mr-1 cursor-default text-xl leading-none align-text-bottom not-italic"
|
||||
>
|
||||
{EPOCH_SYMBOL}
|
||||
</em>
|
||||
);
|
||||
}
|
||||
|
||||
export default BlockLink;
|
||||
|
@ -10,6 +10,8 @@ import { ChainResponseCode } from '../chain-response-code/chain-reponse.code';
|
||||
import { TxDataView } from '../../tx-data-view';
|
||||
import Hash from '../../../links/hash';
|
||||
import { Signature } from '../../../signature/signature';
|
||||
import { useExplorerEpochForBlockQuery } from '../../../links/block-link/__generated__/EpochByBlock';
|
||||
import EpochOverview from '../../../epoch-overview/epoch';
|
||||
|
||||
interface TxDetailsSharedProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@ -44,6 +46,11 @@ export const TxDetailsShared = ({
|
||||
blockData,
|
||||
hideTypeRow = false,
|
||||
}: TxDetailsSharedProps) => {
|
||||
const { data } = useExplorerEpochForBlockQuery({
|
||||
errorPolicy: 'ignore',
|
||||
variables: { block: txData?.block.toString() || '' },
|
||||
});
|
||||
|
||||
if (!txData) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
@ -74,7 +81,7 @@ export const TxDetailsShared = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell {...sharedHeaderProps}>{t('Block')}</TableCell>
|
||||
<TableCell>
|
||||
<BlockLink height={height} showEpoch={true} />
|
||||
<BlockLink height={height} showEpoch={false} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
@ -83,6 +90,7 @@ export const TxDetailsShared = ({
|
||||
<Signature signature={txData.signature} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell {...sharedHeaderProps}>{t('Time')}</TableCell>
|
||||
<TableCell>
|
||||
@ -100,6 +108,14 @@ export const TxDetailsShared = ({
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{data && data.epoch && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell scope="row">{t('Epoch')}</TableCell>
|
||||
<TableCell modifier="bordered">
|
||||
<EpochOverview id={data.epoch.id} icon={false} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell {...sharedHeaderProps}>{t('Response code')}</TableCell>
|
||||
<TableCell>
|
||||
|
@ -113,13 +113,16 @@ export const TxDetailsTransfer = ({
|
||||
|
||||
/**
|
||||
* Gets a string description of this transfer
|
||||
* @param txData A full transfer
|
||||
* @param tx A full transfer
|
||||
* @returns string Transfer label
|
||||
*/
|
||||
export function getTypeLabelForTransfer(tx: Transfer) {
|
||||
if (tx.to === SPECIAL_CASE_NETWORK || tx.to === SPECIAL_CASE_NETWORK_ID) {
|
||||
if (tx.toAccountType === 'ACCOUNT_TYPE_NETWORK_TREASURY') {
|
||||
return 'Treasury transfer';
|
||||
}
|
||||
if (tx.recurring && tx.recurring.dispatchStrategy) {
|
||||
return 'Reward top up transfer';
|
||||
return 'Reward transfer';
|
||||
}
|
||||
// Else: we don't know that it's a reward transfer, so let's not guess
|
||||
} else if (tx.recurring) {
|
||||
|
@ -2,6 +2,7 @@ import { t } from '@vegaprotocol/i18n';
|
||||
import type { components } from '../../../types/explorer';
|
||||
import { VoteIcon } from '../vote-icon/vote-icon';
|
||||
import { ExternalChainIcon } from '../links/external-explorer-link/external-chain-icon';
|
||||
import { getTypeLabelForTransfer } from './details/tx-transfer';
|
||||
|
||||
interface TxOrderTypeProps {
|
||||
orderType: string;
|
||||
@ -95,7 +96,7 @@ export function getLabelForOrderType(
|
||||
|
||||
/**
|
||||
* Given a proposal, will return a specific label
|
||||
* @param chainEvent
|
||||
* @param proposal
|
||||
* @returns
|
||||
*/
|
||||
export function getLabelForProposal(
|
||||
@ -142,6 +143,36 @@ export function getLabelForProposal(
|
||||
}
|
||||
}
|
||||
|
||||
type label = {
|
||||
type: string;
|
||||
colours: string;
|
||||
};
|
||||
|
||||
export function getLabelForTransfer(
|
||||
transfer: components['schemas']['commandsv1Transfer']
|
||||
): label {
|
||||
const type = getTypeLabelForTransfer(transfer);
|
||||
|
||||
if (transfer.toAccountType === 'ACCOUNT_TYPE_NETWORK_TREASURY') {
|
||||
return {
|
||||
type,
|
||||
colours:
|
||||
'text-vega-green dark:text-green bg-vega-dark-150 dark:bg-vega-dark-250',
|
||||
};
|
||||
} else if (transfer.recurring) {
|
||||
return {
|
||||
type,
|
||||
colours:
|
||||
'text-vega-yellow dark:text-yellow bg-vega-dark-150 dark:bg-vega-dark-250',
|
||||
};
|
||||
}
|
||||
return {
|
||||
type,
|
||||
colours:
|
||||
'text-white dark:text-white bg-vega-dark-150 dark:bg-vega-dark-250',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a chain event, will try to provide a more useful label
|
||||
* @param chainEvent
|
||||
@ -225,9 +256,10 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
|
||||
if (type === 'Chain Event' && !!command?.chainEvent) {
|
||||
type = getLabelForChainEvent(command.chainEvent);
|
||||
colours = 'text-white dark-text-white bg-vega-pink dark:bg-vega-pink';
|
||||
} else if (type === 'Validator Heartbeat') {
|
||||
colours =
|
||||
'text-white dark-text-white bg-vega-light-200 dark:bg-vega-dark-100';
|
||||
} else if (type === 'Transfer Funds' && command?.transfer) {
|
||||
const res = getLabelForTransfer(command.transfer);
|
||||
type = res.type;
|
||||
colours = res.colours;
|
||||
} else if (type === 'Proposal' || type === 'Governance Proposal') {
|
||||
if (command && !!command.proposalSubmission) {
|
||||
type = getLabelForProposal(command.proposalSubmission);
|
||||
|
@ -17,6 +17,7 @@ import { NodeLink } from '../../../components/links';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
import EmptyList from '../../../components/empty-list/empty-list';
|
||||
import { useExplorerEpochForBlockQuery } from '../../../components/links/block-link/__generated__/EpochByBlock';
|
||||
import EpochOverview from '../../../components/epoch-overview/epoch';
|
||||
|
||||
type Params = { block: string };
|
||||
|
||||
@ -106,9 +107,9 @@ const Block = () => {
|
||||
</TableRow>
|
||||
{data && data.epoch && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableHeader scope="row">{t('Epoch')}</TableHeader>
|
||||
<TableCell scope="row">{t('Epoch')}</TableCell>
|
||||
<TableCell modifier="bordered">
|
||||
<code>{data.epoch.id}</code>
|
||||
<EpochOverview id={data.epoch.id} icon={false} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
|
Loading…
Reference in New Issue
Block a user