feat(explorer): add chain event details pages (#2194)
* feat(explorer): chain event views
This commit is contained in:
parent
be39008b42
commit
031cd9258e
@ -6,6 +6,7 @@ NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https:
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_BLOCK_EXPLORER=
|
||||
|
||||
# App flags
|
||||
|
@ -5,6 +5,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
|
||||
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
|
||||
NX_VEGA_ENV=CUSTOM
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
@ -7,3 +7,4 @@ NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https:
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
@ -7,3 +7,4 @@ NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https:
|
||||
NX_VEGA_ENV=MAINNET
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest/
|
||||
NX_ETHERSCAN_URL=https://etherscan.io
|
||||
|
@ -8,3 +8,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https://explorer.fairground.wtf\"}
|
||||
NX_TENDERMINT_URL=https://tm.n01.sandbox.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.sandbox.vega.xyz/websocket
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
|
@ -10,3 +10,4 @@ NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
|
@ -7,3 +7,4 @@ NX_VEGA_NETWORKS={\"MAINNET"\:\"https://explorer.vega.xyz"\,\"TESTNET\":\"https:
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
|
||||
NX_ETHERSCAN_URL=https://be.stagnet3.vega.xyz/rest
|
@ -9,4 +9,5 @@ NX_VEGA_ENV=TESTNET
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_VEGA_NETWORKS={}
|
||||
NX_VEGA_NETWORKS={}
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
|
@ -5,3 +5,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket
|
||||
NX_VEGA_ENV=CUSTOM
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
|
@ -66,6 +66,14 @@
|
||||
"passWithNoTests": true
|
||||
}
|
||||
},
|
||||
"generate-types": {
|
||||
"executor": "@nrwl/workspace:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.62.1/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||
]
|
||||
}
|
||||
},
|
||||
"build-netlify": {
|
||||
"executor": "@nrwl/workspace:run-commands",
|
||||
"options": {
|
||||
|
@ -26,7 +26,7 @@ const AssetLink = ({ id, ...props }: AssetLinkProps) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Link className="underline" {...props} to={`/${Routes.MARKETS}#${id}`}>
|
||||
<Link className="underline" {...props} to={`/${Routes.ASSETS}#${id}`}>
|
||||
{label}
|
||||
</Link>
|
||||
);
|
||||
|
@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
|
||||
export enum EthExplorerLinkTypes {
|
||||
block = 'block',
|
||||
address = 'address',
|
||||
tx = 'tx',
|
||||
}
|
||||
|
||||
export type EthExplorerLinkProps = Partial<typeof HTMLAnchorElement> & {
|
||||
id: string;
|
||||
type: EthExplorerLinkTypes;
|
||||
};
|
||||
|
||||
export const EthExplorerLink = ({
|
||||
id,
|
||||
type,
|
||||
...props
|
||||
}: EthExplorerLinkProps) => {
|
||||
const link = `${DATA_SOURCES.ethExplorerUrl}/${type}/${id}`;
|
||||
return (
|
||||
<a
|
||||
className="underline external"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
{...props}
|
||||
href={link}
|
||||
>
|
||||
{id}
|
||||
</a>
|
||||
);
|
||||
};
|
@ -19,7 +19,7 @@ const MarketLink = ({ id, ...props }: MarketLinkProps) => {
|
||||
variables: { id },
|
||||
});
|
||||
|
||||
let label: string = id;
|
||||
let label = id;
|
||||
|
||||
if (data?.market?.tradableInstrument.instrument.name) {
|
||||
label = data.market.tradableInstrument.instrument.name;
|
||||
|
14
apps/explorer/src/app/components/time/index.tsx
Normal file
14
apps/explorer/src/app/components/time/index.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
|
||||
interface TimeProps {
|
||||
date: string | null | undefined;
|
||||
}
|
||||
|
||||
export const Time = ({ date }: TimeProps) => {
|
||||
if (!date) {
|
||||
return <>{t('Date unknown')}</>;
|
||||
}
|
||||
const timeFormatted = new Date(date).toLocaleString();
|
||||
|
||||
return <span>{timeFormatted}</span>;
|
||||
};
|
@ -0,0 +1,75 @@
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerNodeVoteQueryVariables = Types.Exact<{
|
||||
id: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerNodeVoteQuery = { __typename?: 'Query', withdrawal?: { __typename?: 'Withdrawal', id: string, status: Types.WithdrawalStatus, createdTimestamp: string, withdrawnTimestamp?: string | null, txHash?: string | null, asset: { __typename?: 'Asset', id: string, name: string, decimals: number }, party: { __typename?: 'Party', id: string } } | null, deposit?: { __typename?: 'Deposit', id: string, status: Types.DepositStatus, createdTimestamp: string, creditedTimestamp?: string | null, txHash?: string | null, asset: { __typename?: 'Asset', id: string, name: string, decimals: number }, party: { __typename?: 'Party', id: string } } | null };
|
||||
|
||||
|
||||
export const ExplorerNodeVoteDocument = gql`
|
||||
query ExplorerNodeVote($id: ID!) {
|
||||
withdrawal(id: $id) {
|
||||
id
|
||||
status
|
||||
createdTimestamp
|
||||
withdrawnTimestamp
|
||||
txHash
|
||||
asset {
|
||||
id
|
||||
name
|
||||
decimals
|
||||
}
|
||||
party {
|
||||
id
|
||||
}
|
||||
}
|
||||
deposit(id: $id) {
|
||||
id
|
||||
status
|
||||
createdTimestamp
|
||||
creditedTimestamp
|
||||
txHash
|
||||
asset {
|
||||
id
|
||||
name
|
||||
decimals
|
||||
}
|
||||
party {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useExplorerNodeVoteQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useExplorerNodeVoteQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useExplorerNodeVoteQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useExplorerNodeVoteQuery({
|
||||
* variables: {
|
||||
* id: // value for 'id'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useExplorerNodeVoteQuery(baseOptions: Apollo.QueryHookOptions<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>(ExplorerNodeVoteDocument, options);
|
||||
}
|
||||
export function useExplorerNodeVoteLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>(ExplorerNodeVoteDocument, options);
|
||||
}
|
||||
export type ExplorerNodeVoteQueryHookResult = ReturnType<typeof useExplorerNodeVoteQuery>;
|
||||
export type ExplorerNodeVoteLazyQueryHookResult = ReturnType<typeof useExplorerNodeVoteLazyQuery>;
|
||||
export type ExplorerNodeVoteQueryResult = Apollo.QueryResult<ExplorerNodeVoteQuery, ExplorerNodeVoteQueryVariables>;
|
@ -0,0 +1,139 @@
|
||||
import { TxDetailsChainMultisigThreshold } from './tx-multisig-threshold';
|
||||
import { TxDetailsChainMultisigSigner } from './tx-multisig-signer';
|
||||
import { TxDetailsChainEventBuiltinDeposit } from './tx-builtin-deposit';
|
||||
import { TxDetailsChainEventStakeDeposit } from './tx-stake-deposit';
|
||||
import { TxDetailsChainEventStakeRemove } from './tx-stake-remove';
|
||||
import { TxDetailsChainEventStakeTotalSupply } from './tx-stake-totalsupply';
|
||||
import { TxDetailsChainEventBuiltinWithdrawal } from './tx-builtin-withdrawal';
|
||||
import { TxDetailsChainEventErc20AssetList } from './tx-erc20-asset-list';
|
||||
import { TxDetailsChainEventErc20AssetLimitsUpdated } from './tx-erc20-asset-limits-updated';
|
||||
import { TxDetailsChainEventErc20BridgePause } from './tx-erc20-bridge-pause';
|
||||
import { TxDetailsChainEventDeposit } from './tx-erc20-deposit';
|
||||
|
||||
import isUndefined from 'lodash/isUndefined';
|
||||
|
||||
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
|
||||
|
||||
interface ChainEventProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects the chain event to determine which details view to show. The list of types
|
||||
* comes from the Swagger document that Block Explorer provides, which can be viewed at
|
||||
* https://docs.vega.xyz/testnet/api/rest/explorer/block-explorer-list-transactions
|
||||
*
|
||||
* This component should have one entry per chain event type, however if there isn't
|
||||
* a bespoke view for an event the tx-details-shared will still render some basic
|
||||
* overview and the transaction viewer will still let people view the raw TX.
|
||||
*
|
||||
* Most chain events simply render more table rows for the header table
|
||||
*
|
||||
* @returns React.JSXElement
|
||||
*/
|
||||
export const ChainEvent = ({ txData }: ChainEventProps) => {
|
||||
const e = txData?.command.chainEvent;
|
||||
if (!e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Builtin Asset events
|
||||
if (e.builtin) {
|
||||
if (e.builtin.deposit) {
|
||||
return <TxDetailsChainEventBuiltinDeposit deposit={e.builtin.deposit} />;
|
||||
}
|
||||
|
||||
if (e.builtin?.withdrawal) {
|
||||
return (
|
||||
<TxDetailsChainEventBuiltinWithdrawal
|
||||
withdrawal={e.builtin?.withdrawal}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ERC20 asset events
|
||||
if (e.erc20) {
|
||||
if (e.erc20.deposit) {
|
||||
return <TxDetailsChainEventDeposit deposit={e.erc20.deposit} />;
|
||||
}
|
||||
|
||||
if (e.erc20.withdrawal) {
|
||||
return (
|
||||
<TxDetailsChainEventBuiltinWithdrawal withdrawal={e.erc20.withdrawal} />
|
||||
);
|
||||
}
|
||||
|
||||
if (e.erc20.assetList) {
|
||||
return (
|
||||
<TxDetailsChainEventErc20AssetList assetList={e.erc20.assetList} />
|
||||
);
|
||||
}
|
||||
|
||||
if (e.erc20.assetLimitsUpdated) {
|
||||
return (
|
||||
<TxDetailsChainEventErc20AssetLimitsUpdated
|
||||
assetLimitsUpdated={e.erc20.assetLimitsUpdated}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const bridgeStopped = e.erc20.bridgeStopped;
|
||||
const bridgeResumed = e.erc20.bridgeResumed;
|
||||
if (!isUndefined(bridgeStopped) || !isUndefined(bridgeResumed)) {
|
||||
const isPaused = bridgeStopped === false || bridgeResumed === true;
|
||||
return <TxDetailsChainEventErc20BridgePause isPaused={isPaused} />;
|
||||
}
|
||||
}
|
||||
|
||||
// ERC20 multisig events
|
||||
if (e.erc20Multisig) {
|
||||
if (e.erc20Multisig.thresholdSet) {
|
||||
return (
|
||||
<TxDetailsChainMultisigThreshold
|
||||
thresholdSet={e.erc20Multisig.thresholdSet}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (e.erc20Multisig.signerAdded) {
|
||||
return (
|
||||
<TxDetailsChainMultisigSigner signer={e.erc20Multisig.signerAdded} />
|
||||
);
|
||||
}
|
||||
|
||||
if (e.erc20Multisig.signerRemoved) {
|
||||
return (
|
||||
<TxDetailsChainMultisigSigner signer={e.erc20Multisig.signerRemoved} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Staking events
|
||||
if (e.stakingEvent) {
|
||||
if (e.stakingEvent.stakeDeposited) {
|
||||
return (
|
||||
<TxDetailsChainEventStakeDeposit
|
||||
deposit={e.stakingEvent.stakeDeposited}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (e.stakingEvent.stakeRemoved) {
|
||||
return (
|
||||
<TxDetailsChainEventStakeRemove remove={e.stakingEvent.stakeRemoved} />
|
||||
);
|
||||
}
|
||||
|
||||
if (e.stakingEvent.totalSupply) {
|
||||
return (
|
||||
<TxDetailsChainEventStakeTotalSupply
|
||||
update={e.stakingEvent.totalSupply}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If we hit this return, tx-shared-details should give a basic overview
|
||||
return null;
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Returns a reasonably formatted time from unix timestamp of block height
|
||||
*
|
||||
* @param date String or null date
|
||||
* @returns String date in locale time
|
||||
*/
|
||||
export function getBlockTime(date?: string) {
|
||||
if (!date) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
const timeInSeconds = parseInt(date, 10);
|
||||
const timeInMs = timeInSeconds * 1000;
|
||||
|
||||
return new Date(timeInMs).toLocaleString();
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink, PartyLink } from '../../../links';
|
||||
|
||||
interface TxDetailsChainEventBuiltinDepositProps {
|
||||
deposit: components['schemas']['vegaBuiltinAssetDeposit'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Someone deposited some of a builtin asset. Builtin assets
|
||||
* have no value outside the Vega chain and should appear only
|
||||
* on Test networks.
|
||||
*/
|
||||
export const TxDetailsChainEventBuiltinDeposit = ({
|
||||
deposit,
|
||||
}: TxDetailsChainEventBuiltinDepositProps) => {
|
||||
if (!deposit) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain Event type')}</TableCell>
|
||||
<TableCell>{t('Built-in asset deposit')}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Recipient')}</TableCell>
|
||||
<TableCell>
|
||||
<PartyLink id={deposit.partyId || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Asset')}</TableCell>
|
||||
<TableCell>
|
||||
<AssetLink id={deposit.vegaAssetId || ''} /> ({t('built in asset')})
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Amount')}</TableCell>
|
||||
<TableCell>{deposit.amount}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,47 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink, PartyLink } from '../../../links';
|
||||
|
||||
interface TxDetailsChainEventBuiltinDepositProps {
|
||||
withdrawal: components['schemas']['vegaBuiltinAssetWithdrawal'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Someone withdrew some of a builtin asset. Builtin assets
|
||||
* have no value outside the Vega chain and should appear only
|
||||
* on Test networks, so someone withdrawing it is pretty rare
|
||||
*/
|
||||
export const TxDetailsChainEventBuiltinWithdrawal = ({
|
||||
withdrawal,
|
||||
}: TxDetailsChainEventBuiltinDepositProps) => {
|
||||
if (!withdrawal) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain Event type')}</TableCell>
|
||||
<TableCell>{t('Built-in asset withdrawal')}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Recipient')}</TableCell>
|
||||
<TableCell>
|
||||
<PartyLink id={withdrawal.partyId || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Asset')}</TableCell>
|
||||
<TableCell>
|
||||
<AssetLink id={withdrawal.vegaAssetId || ''} /> ({t('built in asset')}
|
||||
)
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Amount')}</TableCell>
|
||||
<TableCell>{withdrawal.amount}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,37 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink } from '../../../links';
|
||||
|
||||
interface TxDetailsChainEventErc20AssetDelistProps {
|
||||
assetDelist: components['schemas']['vegaERC20AssetDelist'];
|
||||
}
|
||||
|
||||
/**
|
||||
* An ERC20 asset was removed from the bridge,
|
||||
* The link should link to an asset that doesn't exist. Which feels odd
|
||||
* but I think is better than having no link - in case something
|
||||
* weird is up and it still exists
|
||||
*/
|
||||
export const TxDetailsChainEventErc20AssetDelist = ({
|
||||
assetDelist,
|
||||
}: TxDetailsChainEventErc20AssetDelistProps) => {
|
||||
if (!assetDelist) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain event type')}</TableCell>
|
||||
<TableCell>{t('ERC20 asset removed')}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Removed Vega asset')}</TableCell>
|
||||
<TableCell>
|
||||
<AssetLink id={assetDelist.vegaAssetId || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,65 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventErc20AssetLimitsUpdatedProps {
|
||||
assetLimitsUpdated: components['schemas']['vegaERC20AssetLimitsUpdated'];
|
||||
}
|
||||
|
||||
/**
|
||||
* An ERC20 asset was had its limits changed. The limits are in place
|
||||
* at first to prevent users depositing large sums while the network
|
||||
* is still new, as a safety measure.
|
||||
* - Lifetime limit is how much can be withdrawn of this asset to a
|
||||
* single ethereum address
|
||||
* - Withdraw threshold is the size of a withdrawal that will incur
|
||||
* a delay in processing. The delay is set by a network parameter
|
||||
*/
|
||||
export const TxDetailsChainEventErc20AssetLimitsUpdated = ({
|
||||
assetLimitsUpdated,
|
||||
}: TxDetailsChainEventErc20AssetLimitsUpdatedProps) => {
|
||||
if (!assetLimitsUpdated) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain event type')}</TableCell>
|
||||
<TableCell>{t('ERC20 asset limits updated')}</TableCell>
|
||||
</TableRow>
|
||||
|
||||
{assetLimitsUpdated.sourceEthereumAddress ? (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('ERC20 asset')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
id={assetLimitsUpdated.sourceEthereumAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : null}
|
||||
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Vega asset')}</TableCell>
|
||||
<TableCell>
|
||||
<AssetLink id={assetLimitsUpdated.vegaAssetId || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Total lifetime limit')}</TableCell>
|
||||
<TableCell>{assetLimitsUpdated.lifetimeLimits}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Asset withdrawal threshold')}</TableCell>
|
||||
<TableCell>{assetLimitsUpdated.withdrawThreshold}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,51 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventErc20AssetListProps {
|
||||
assetList: components['schemas']['vegaERC20AssetList'];
|
||||
}
|
||||
|
||||
/**
|
||||
* An ERC20 asset was proposed and then enacted on the bridge,
|
||||
* a Asset List event will be emitted that tells the core to
|
||||
* create the asset. That's this event - it's very basic
|
||||
*/
|
||||
export const TxDetailsChainEventErc20AssetList = ({
|
||||
assetList,
|
||||
}: TxDetailsChainEventErc20AssetListProps) => {
|
||||
if (!assetList) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain event type')}</TableCell>
|
||||
<TableCell>{t('ERC20 asset added')}</TableCell>
|
||||
</TableRow>
|
||||
{assetList.assetSource ? (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
id={assetList.assetSource}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : null}
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Added Vega asset')}</TableCell>
|
||||
<TableCell>
|
||||
<AssetLink id={assetList.vegaAssetId || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
|
||||
interface TxDetailsChainEventErc20BridgePauseProps {
|
||||
isPaused: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* The bridge was either paused or unpaused, preventing withdrawals
|
||||
* or deposits from being enacted. This will only happen if the
|
||||
* validators have signed a multisig bundle requiring it to happen
|
||||
*/
|
||||
export const TxDetailsChainEventErc20BridgePause = ({
|
||||
isPaused,
|
||||
}: TxDetailsChainEventErc20BridgePauseProps) => {
|
||||
const event = isPaused ? 'pause' : 'unpaused';
|
||||
|
||||
return (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain event type')}</TableCell>
|
||||
<TableCell>{t(`ERC20 bridge ${event}`)}</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
};
|
@ -0,0 +1,59 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink, PartyLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventProps {
|
||||
deposit: components['schemas']['vegaERC20Deposit'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Someone deposited some erc20
|
||||
*/
|
||||
export const TxDetailsChainEventDeposit = ({
|
||||
deposit,
|
||||
}: TxDetailsChainEventProps) => {
|
||||
if (!deposit) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain event type')}</TableCell>
|
||||
<TableCell>{t('ERC20 deposit')}</TableCell>
|
||||
</TableRow>
|
||||
{deposit.sourceEthereumAddress ? (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
id={deposit.sourceEthereumAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : null}
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Recipient')}</TableCell>
|
||||
<TableCell>
|
||||
<PartyLink id={deposit.targetPartyId || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Asset')}</TableCell>
|
||||
<TableCell>
|
||||
<AssetLink id={deposit.vegaAssetId || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Amount')}</TableCell>
|
||||
<TableCell>{deposit.amount}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,51 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { AssetLink } from '../../../links';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventWithdrawalProps {
|
||||
withdrawal: components['schemas']['vegaERC20Withdrawal'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Someone deposited some erc20
|
||||
*/
|
||||
export const TxDetailsChainEventWithdrawal = ({
|
||||
withdrawal,
|
||||
}: TxDetailsChainEventWithdrawalProps) => {
|
||||
if (!withdrawal) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain event type')}</TableCell>
|
||||
<TableCell>{t('ERC20 withdrawal')}</TableCell>
|
||||
</TableRow>
|
||||
|
||||
{withdrawal.targetEthereumAddress ? (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Recipient')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
id={withdrawal.targetEthereumAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : null}
|
||||
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Asset')}</TableCell>
|
||||
<TableCell>
|
||||
<AssetLink id={withdrawal.vegaAssetId || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,50 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { getBlockTime } from './lib/get-block-time';
|
||||
|
||||
interface TxDetailsChainMultisigSignerProps {
|
||||
signer:
|
||||
| components['schemas']['vegaERC20SignerAdded']
|
||||
| components['schemas']['vegaERC20SignerRemoved'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Someone updated multsig signer set, either removing or adding someone
|
||||
*/
|
||||
export const TxDetailsChainMultisigSigner = ({
|
||||
signer,
|
||||
}: TxDetailsChainMultisigSignerProps) => {
|
||||
if (!signer) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const blockTime = getBlockTime(signer.blockTime);
|
||||
const target =
|
||||
'newSigner' in signer
|
||||
? signer.newSigner
|
||||
: 'oldSigner' in signer
|
||||
? signer.oldSigner
|
||||
: '';
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain Event type')}</TableCell>
|
||||
{'newSigner' in signer
|
||||
? t('Add ERC20 bridge multisig signer')
|
||||
: t('Remove ERC20 bridge multsig signer')}
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>
|
||||
{'newSigner' in signer ? t('Add signer') : t('Remove signer')}
|
||||
</TableCell>
|
||||
<TableCell>{target}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Signer change at')}</TableCell>
|
||||
<TableCell>{blockTime}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,59 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import isNumber from 'lodash/isNumber';
|
||||
|
||||
/**
|
||||
* Returns a reasonably formatted time from unix timestamp of block height
|
||||
*
|
||||
* @param date String or null date
|
||||
* @returns String date in locale time
|
||||
*/
|
||||
function getBlockTime(date?: string) {
|
||||
if (!date) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
const timeInSeconds = parseInt(date, 10);
|
||||
const timeInMs = timeInSeconds * 1000;
|
||||
|
||||
return new Date(timeInMs).toLocaleString();
|
||||
}
|
||||
|
||||
interface TxDetailsChainMultisigThresholdProps {
|
||||
thresholdSet: components['schemas']['vegaERC20MultiSigEvent']['thresholdSet'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Someone updated multsig threshold value on the smart contract.
|
||||
* It's a percentage, with 1000 being 100% and 0 being 0%.
|
||||
*/
|
||||
export const TxDetailsChainMultisigThreshold = ({
|
||||
thresholdSet,
|
||||
}: TxDetailsChainMultisigThresholdProps) => {
|
||||
if (!thresholdSet) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const blockTime = getBlockTime(thresholdSet.blockTime);
|
||||
const threshold = isNumber(thresholdSet.newThreshold)
|
||||
? thresholdSet.newThreshold / 10
|
||||
: '-';
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain Event type')}</TableCell>
|
||||
<TableCell>{t('ERC20 multisig threshold set')}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Threshold')}</TableCell>
|
||||
<TableCell>{threshold}%</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Threshold set from')}</TableCell>
|
||||
<TableCell>{blockTime}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,49 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { PartyLink } from '../../../links';
|
||||
|
||||
interface TxDetailsChainEventStakeDepositProps {
|
||||
deposit: components['schemas']['vegaStakeDeposited'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Someone addedd some stake for a particular party
|
||||
* This should link to the Governance asset, but doesn't
|
||||
* as that would require checking the Network Paramters
|
||||
* Ethereum address should also be a link to an ETH block explorer
|
||||
*/
|
||||
export const TxDetailsChainEventStakeDeposit = ({
|
||||
deposit,
|
||||
}: TxDetailsChainEventStakeDepositProps) => {
|
||||
if (!deposit) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain Event type')}</TableCell>
|
||||
<TableCell>{t('Stake deposited')}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>{deposit.ethereumAddress || ''}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Recipient')}</TableCell>
|
||||
<TableCell>
|
||||
<PartyLink id={deposit.vegaPublicKey || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Amount')}</TableCell>
|
||||
<TableCell>{deposit.amount}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Deposited at')}</TableCell>
|
||||
<TableCell>{deposit.amount}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,49 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import { PartyLink } from '../../../links';
|
||||
|
||||
interface TxDetailsChainEventStakeRemoveProps {
|
||||
remove: components['schemas']['vegaStakeRemoved'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Someone addedd some stake for a particular party
|
||||
* This should link to the Governance asset, but doesn't
|
||||
* as that would require checking the Network Parameters
|
||||
* Ethereum address should also be a link to an ETH block explorer
|
||||
*/
|
||||
export const TxDetailsChainEventStakeRemove = ({
|
||||
remove,
|
||||
}: TxDetailsChainEventStakeRemoveProps) => {
|
||||
if (!remove) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain Event type')}</TableCell>
|
||||
<TableCell>{t('Stake removed')}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>{remove.ethereumAddress || ''}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Recipient')}</TableCell>
|
||||
<TableCell>
|
||||
<PartyLink id={remove.vegaPublicKey || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Amount')}</TableCell>
|
||||
<TableCell>{remove.amount}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Deposited at')}</TableCell>
|
||||
<TableCell>{remove.blockTime}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,54 @@
|
||||
import { formatNumber, t, toBigNum } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import type { components } from '../../../../../types/explorer';
|
||||
import {
|
||||
EthExplorerLink,
|
||||
EthExplorerLinkTypes,
|
||||
} from '../../../links/eth-explorer-link/eth-explorer-link';
|
||||
|
||||
interface TxDetailsChainEventStakeTotalSupplyProps {
|
||||
update: components['schemas']['vegaStakeTotalSupply'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Chain event set the total supply of the governance asset
|
||||
* Happens whenever the total supply changes, or when the chain
|
||||
* restarts and the total supply is detected.
|
||||
*/
|
||||
export const TxDetailsChainEventStakeTotalSupply = ({
|
||||
update,
|
||||
}: TxDetailsChainEventStakeTotalSupplyProps) => {
|
||||
if (!update) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
let totalSupply = update.totalSupply || '';
|
||||
if (totalSupply.length > 0) {
|
||||
totalSupply = formatNumber(toBigNum(totalSupply, 18));
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Chain Event type')}</TableCell>
|
||||
<TableCell>{t('Stake total supply update')}</TableCell>
|
||||
</TableRow>
|
||||
|
||||
{update.tokenAddress ? (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Source')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
id={update.tokenAddress}
|
||||
type={EthExplorerLinkTypes.address}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : null}
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Total supply')}</TableCell>
|
||||
<TableCell>{totalSupply}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
query ExplorerNodeVote($id: ID!) {
|
||||
withdrawal(id: $id) {
|
||||
id
|
||||
status
|
||||
createdTimestamp
|
||||
withdrawnTimestamp
|
||||
txHash
|
||||
asset {
|
||||
id
|
||||
name
|
||||
decimals
|
||||
}
|
||||
party {
|
||||
id
|
||||
}
|
||||
}
|
||||
deposit(id: $id) {
|
||||
id
|
||||
status
|
||||
createdTimestamp
|
||||
creditedTimestamp
|
||||
txHash
|
||||
asset {
|
||||
id
|
||||
name
|
||||
decimals
|
||||
}
|
||||
party {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TableRow, TableCell } from '../../../table';
|
||||
import { BlockLink, PartyLink } from '../../../links/';
|
||||
@ -6,6 +5,7 @@ import { TimeAgo } from '../../../time-ago';
|
||||
|
||||
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../../routes/blocks/tendermint-blocks-response';
|
||||
import { Time } from '../../../time';
|
||||
|
||||
interface TxDetailsSharedProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@ -29,11 +29,6 @@ export const TxDetailsShared = ({
|
||||
|
||||
const time: string = blockData?.result.block.header.time || '';
|
||||
const height: string = blockData?.result.block.header.height || '';
|
||||
let timeFormatted = '';
|
||||
|
||||
if (time) {
|
||||
timeFormatted = new Date(time).toLocaleString();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -56,7 +51,9 @@ export const TxDetailsShared = ({
|
||||
<TableCell>
|
||||
{time ? (
|
||||
<div>
|
||||
<span className="mr-5">{timeFormatted} </span>
|
||||
<span className="mr-5">
|
||||
<Time date={time} />
|
||||
</span>
|
||||
<span>
|
||||
<TimeAgo date={time} />
|
||||
</span>
|
||||
|
@ -1,9 +1,5 @@
|
||||
import React from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
BlockExplorerTransactionResult,
|
||||
BatchMarketInstructions,
|
||||
} from '../../../routes/types/block-explorer-response';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
import { TableWithTbody, TableRow, TableCell } from '../../table';
|
||||
@ -26,16 +22,17 @@ export const TxDetailsBatch = ({
|
||||
pubKey,
|
||||
blockData,
|
||||
}: TxDetailsBatchProps) => {
|
||||
if (!txData) {
|
||||
if (!txData || !txData.command.batchMarketInstructions) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const cmd = txData.command as BatchMarketInstructions;
|
||||
|
||||
const batchSubmissions = cmd.batchMarketInstructions.submissions.length;
|
||||
const batchAmendments = cmd.batchMarketInstructions.amendments.length;
|
||||
const batchCancellations = cmd.batchMarketInstructions.cancellations.length;
|
||||
const batchTotal = batchSubmissions + batchAmendments + batchCancellations;
|
||||
const countSubmissions =
|
||||
txData.command.batchMarketInstructions.submissions?.length || 0;
|
||||
const countAmendments =
|
||||
txData.command.batchMarketInstructions.amendments?.length || 0;
|
||||
const countCancellations =
|
||||
txData.command.batchMarketInstructions.cancellations?.length || 0;
|
||||
const countTotal = countSubmissions + countAmendments + countCancellations;
|
||||
|
||||
return (
|
||||
<TableWithTbody>
|
||||
@ -43,7 +40,7 @@ export const TxDetailsBatch = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Batch size')}</TableCell>
|
||||
<TableCell>
|
||||
<span>{batchTotal}</span>
|
||||
<span>{countTotal}</span>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
@ -51,7 +48,7 @@ export const TxDetailsBatch = ({
|
||||
<span className="ml-5">{t('Submissions')}</span>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<span>{batchSubmissions}</span>
|
||||
<span>{countSubmissions}</span>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
@ -59,7 +56,7 @@ export const TxDetailsBatch = ({
|
||||
<span className="ml-5">{t('Amendments')}</span>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<span>{batchAmendments}</span>
|
||||
<span>{countAmendments}</span>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
@ -67,7 +64,7 @@ export const TxDetailsBatch = ({
|
||||
<span className="ml-5">{t('Cancellations')}</span>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<span>{batchCancellations}</span>
|
||||
<span>{countCancellations}</span>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableWithTbody>
|
||||
|
@ -1,13 +1,10 @@
|
||||
import React from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
BlockExplorerTransactionResult,
|
||||
ChainEvent,
|
||||
} from '../../../routes/types/block-explorer-response';
|
||||
import { AssetLink, PartyLink } from '../../links';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
||||
import { TableWithTbody } from '../../table';
|
||||
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { ChainEvent } from './chain-events';
|
||||
|
||||
interface TxDetailsChainEventProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@ -20,10 +17,10 @@ interface TxDetailsChainEventProps {
|
||||
* Multiple events will relay the same data, from each validator, so that the
|
||||
* deposit/withdrawal can be verified independently.
|
||||
*
|
||||
* Design considerations so far:
|
||||
* - The ethereum address should be a link to an Ethereum explorer
|
||||
* - Sender and recipient are shown because they are easy
|
||||
* - Amount is not shown because there is no formatter by asset component
|
||||
* There are so many chain events that the specific components have been broken
|
||||
* out in to individual components. `getChainEventComponent` determines which
|
||||
* is the most appropriate based on the transaction shape. See that function
|
||||
* for more information.
|
||||
*/
|
||||
export const TxDetailsChainEvent = ({
|
||||
txData,
|
||||
@ -33,32 +30,11 @@ export const TxDetailsChainEvent = ({
|
||||
if (!txData) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
const cmd = txData.command as ChainEvent;
|
||||
const assetId = cmd.chainEvent.erc20.deposit.vegaAssetId;
|
||||
const sender = cmd.chainEvent.erc20.deposit.sourceEthereumAddress;
|
||||
const recipient = cmd.chainEvent.erc20.deposit.targetPartyId;
|
||||
|
||||
return (
|
||||
<TableWithTbody>
|
||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Asset')}</TableCell>
|
||||
<TableCell>
|
||||
<AssetLink id={assetId} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Sender')}</TableCell>
|
||||
<TableCell>
|
||||
<span>{sender}</span>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Recipient')}</TableCell>
|
||||
<TableCell>
|
||||
<PartyLink id={recipient} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<ChainEvent txData={txData} />
|
||||
</TableWithTbody>
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
import { t, useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { TxDetailsOrder } from './tx-order';
|
||||
@ -10,11 +10,10 @@ import { TxDetailsGeneric } from './tx-generic';
|
||||
import { TxDetailsBatch } from './tx-batch';
|
||||
import { TxDetailsChainEvent } from './tx-chain-event';
|
||||
import { TxContent } from '../../../routes/txs/id/tx-content';
|
||||
|
||||
type resultOrNull = BlockExplorerTransactionResult | undefined;
|
||||
import { TxDetailsNodeVote } from './tx-node-vote';
|
||||
|
||||
interface TxDetailsWrapperProps {
|
||||
txData: resultOrNull;
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
pubKey: string | undefined;
|
||||
height: string;
|
||||
}
|
||||
@ -61,7 +60,7 @@ export const TxDetailsWrapper = ({
|
||||
* @param txData
|
||||
* @returns JSX.Element
|
||||
*/
|
||||
function getTransactionComponent(txData: resultOrNull) {
|
||||
function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
|
||||
if (!txData) {
|
||||
return TxDetailsGeneric;
|
||||
}
|
||||
@ -77,6 +76,8 @@ function getTransactionComponent(txData: resultOrNull) {
|
||||
return TxDetailsBatch;
|
||||
case 'Chain Event':
|
||||
return TxDetailsChainEvent;
|
||||
case 'Node Vote':
|
||||
return TxDetailsNodeVote;
|
||||
default:
|
||||
return TxDetailsGeneric;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
|
@ -1,9 +1,5 @@
|
||||
import React from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
BlockExplorerTransactionResult,
|
||||
ValidatorHeartbeat,
|
||||
} from '../../../routes/types/block-explorer-response';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import { BlockLink, NodeLink } from '../../links/';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
@ -56,11 +52,12 @@ export const TxDetailsHeartbeat = ({
|
||||
pubKey,
|
||||
blockData,
|
||||
}: TxDetailsHeartbeatProps) => {
|
||||
if (!txData) {
|
||||
if (!txData || !txData.command.validatorHeartbeat) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const cmd = txData.command as ValidatorHeartbeat;
|
||||
const nodeId = txData.command.validatorHeartbeat.nodeId || '';
|
||||
const blockHeight = txData.command.blockHeight || '';
|
||||
|
||||
return (
|
||||
<TableWithTbody>
|
||||
@ -68,18 +65,18 @@ export const TxDetailsHeartbeat = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Node')}</TableCell>
|
||||
<TableCell>
|
||||
<NodeLink id={cmd.validatorHeartbeat.nodeId} />
|
||||
<NodeLink id={nodeId} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Signed block height')}</TableCell>
|
||||
<TableCell>
|
||||
<BlockLink height={cmd.blockHeight} />
|
||||
<BlockLink height={blockHeight} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Freshness (lower is better)')}</TableCell>
|
||||
<TableCell>{scoreFreshness(txData.block, cmd.blockHeight)}</TableCell>
|
||||
<TableCell>{scoreFreshness(txData.block, blockHeight)}</TableCell>
|
||||
</TableRow>
|
||||
</TableWithTbody>
|
||||
);
|
||||
|
@ -1,9 +1,5 @@
|
||||
import React from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
AmendLiquidityProvisionOrder,
|
||||
BlockExplorerTransactionResult,
|
||||
} from '../../../routes/types/block-explorer-response';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import { MarketLink } from '../../links/';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
@ -29,7 +25,7 @@ export const TxDetailsLPAmend = ({
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const cmd = txData.command as AmendLiquidityProvisionOrder;
|
||||
const marketId = txData.command.liquidityProvisionAmendment?.marketId || '';
|
||||
|
||||
return (
|
||||
<TableWithTbody>
|
||||
@ -37,7 +33,7 @@ export const TxDetailsLPAmend = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Market')}</TableCell>
|
||||
<TableCell>
|
||||
<MarketLink id={cmd.liquidityProvisionAmendment.marketId} />
|
||||
<MarketLink id={marketId} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableWithTbody>
|
||||
|
144
apps/explorer/src/app/components/txs/details/tx-node-vote.tsx
Normal file
144
apps/explorer/src/app/components/txs/details/tx-node-vote.tsx
Normal file
@ -0,0 +1,144 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
||||
import type { ExplorerNodeVoteQueryResult } from './__generated___/node-vote';
|
||||
import { useExplorerNodeVoteQuery } from './__generated___/node-vote';
|
||||
import { PartyLink } from '../../links';
|
||||
import { Time } from '../../time';
|
||||
|
||||
interface TxDetailsNodeVoteProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
pubKey: string | undefined;
|
||||
blockData: TendermintBlocksResponse | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is not yet a custom component for a transaction, just display
|
||||
* the basic details. This allows someone to view the decoded transaction.
|
||||
*/
|
||||
export const TxDetailsNodeVote = ({
|
||||
txData,
|
||||
pubKey,
|
||||
blockData,
|
||||
}: TxDetailsNodeVoteProps) => {
|
||||
const id = txData?.command.nodeVote?.reference || '';
|
||||
|
||||
const { data } = useExplorerNodeVoteQuery({
|
||||
variables: {
|
||||
id,
|
||||
},
|
||||
// Required as one of these queries will needlessly error
|
||||
errorPolicy: 'ignore',
|
||||
});
|
||||
|
||||
if (!txData) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<TableWithTbody>
|
||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||
{data && !!data.deposit
|
||||
? TxDetailsNodeVoteDeposit({ deposit: data })
|
||||
: data && !!data.withdrawal
|
||||
? TxDetailsNodeVoteWithdrawal({ withdrawal: data })
|
||||
: null}
|
||||
</TableWithTbody>
|
||||
);
|
||||
};
|
||||
|
||||
interface TxDetailsNodeVoteDepositProps {
|
||||
deposit: ExplorerNodeVoteQueryResult['data'];
|
||||
}
|
||||
|
||||
export function TxDetailsNodeVoteDeposit({
|
||||
deposit,
|
||||
}: TxDetailsNodeVoteDepositProps) {
|
||||
if (!deposit) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Witnessed Event type')}</TableCell>
|
||||
{deposit?.deposit?.txHash ? (
|
||||
<TableCell>{t('ERC20 deposit')}</TableCell>
|
||||
) : (
|
||||
<TableCell>{t('Built-in asset deposit')}</TableCell>
|
||||
)}
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('To party')}:</TableCell>
|
||||
<TableCell>
|
||||
<PartyLink id={deposit?.deposit?.party?.id || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Credited on')}:</TableCell>
|
||||
<TableCell>
|
||||
<Time date={deposit?.deposit?.creditedTimestamp} />
|
||||
</TableCell>
|
||||
{deposit?.deposit?.txHash ? (
|
||||
<TxHash hash={deposit?.deposit?.txHash} />
|
||||
) : null}
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface TxDetailsNodeVoteWithdrawalProps {
|
||||
withdrawal: ExplorerNodeVoteQueryResult['data'];
|
||||
}
|
||||
|
||||
export function TxDetailsNodeVoteWithdrawal({
|
||||
withdrawal,
|
||||
}: TxDetailsNodeVoteWithdrawalProps) {
|
||||
if (!withdrawal) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Witnessed Event type')}</TableCell>
|
||||
{withdrawal?.withdrawal?.txHash ? (
|
||||
<TableCell>{t('ERC20 withdrawal')}</TableCell>
|
||||
) : (
|
||||
<TableCell>{t('Built-in asset withdrawal')}</TableCell>
|
||||
)}
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('From party')}:</TableCell>
|
||||
<TableCell>
|
||||
<PartyLink id={withdrawal?.deposit?.party?.id || ''} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Withdrawn on')}:</TableCell>
|
||||
<TableCell>
|
||||
<Time date={withdrawal?.withdrawal?.withdrawnTimestamp} />
|
||||
</TableCell>
|
||||
{withdrawal?.withdrawal?.txHash ? (
|
||||
<TxHash hash={withdrawal?.withdrawal?.txHash} />
|
||||
) : null}
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface TxDetailsEthTxHashProps {
|
||||
hash: string;
|
||||
}
|
||||
|
||||
export function TxHash({ hash }: TxDetailsEthTxHashProps) {
|
||||
if (!hash) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>Ethereum TX:</TableCell>
|
||||
<TableCell>{hash}</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
@ -1,9 +1,5 @@
|
||||
import React from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
BlockExplorerTransactionResult,
|
||||
SubmitOrder,
|
||||
} from '../../../routes/types/block-explorer-response';
|
||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
||||
import { MarketLink } from '../../links/';
|
||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||
@ -26,11 +22,10 @@ export const TxDetailsOrder = ({
|
||||
pubKey,
|
||||
blockData,
|
||||
}: TxDetailsOrderProps) => {
|
||||
if (!txData) {
|
||||
if (!txData || !txData.command.orderSubmission) {
|
||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||
}
|
||||
|
||||
const cmd = txData.command as SubmitOrder;
|
||||
const marketId = txData.command.orderSubmission.marketId || '-';
|
||||
|
||||
return (
|
||||
<TableWithTbody>
|
||||
@ -38,7 +33,7 @@ export const TxDetailsOrder = ({
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Market')}</TableCell>
|
||||
<TableCell>
|
||||
<MarketLink id={cmd.orderSubmission.marketId} />
|
||||
<MarketLink id={marketId} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableWithTbody>
|
||||
|
@ -1,5 +1,9 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { components } from '../../../types/explorer';
|
||||
|
||||
interface TxOrderTypeProps {
|
||||
orderType: string;
|
||||
chainEvent?: components['schemas']['v1ChainEvent'];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
@ -32,13 +36,73 @@ const displayString: StringMap = {
|
||||
ValidatorHeartbeat: 'Validator Heartbeat',
|
||||
};
|
||||
|
||||
export const TxOrderType = ({ orderType }: TxOrderTypeProps) => {
|
||||
/**
|
||||
* Given a chain event, will try to provide a more useful label
|
||||
* @param chainEvent
|
||||
* @returns
|
||||
*/
|
||||
export function getLabelForChainEvent(
|
||||
chainEvent: components['schemas']['v1ChainEvent']
|
||||
): string {
|
||||
if (chainEvent.builtin) {
|
||||
if (chainEvent.builtin.deposit) {
|
||||
return t('Built-in deposit');
|
||||
} else if (chainEvent.builtin.withdrawal) {
|
||||
return t('Built-in withdraw');
|
||||
}
|
||||
return t('Built-in event');
|
||||
} else if (chainEvent.erc20) {
|
||||
if (chainEvent.erc20.assetDelist) {
|
||||
return t('ERC20 delist');
|
||||
} else if (chainEvent.erc20.assetList) {
|
||||
return t('ERC20 list');
|
||||
} else if (chainEvent.erc20.bridgeResumed) {
|
||||
return t('Bridge resume');
|
||||
} else if (chainEvent.erc20.bridgeStopped) {
|
||||
return t('Bridge pause');
|
||||
} else if (chainEvent.erc20.deposit) {
|
||||
return t('ERC20 deposit');
|
||||
} else if (chainEvent.erc20.withdrawal) {
|
||||
return t('ERC20 withdraw');
|
||||
}
|
||||
return t('ERC20 event');
|
||||
} else if (chainEvent.stakingEvent) {
|
||||
if (chainEvent.stakingEvent.stakeDeposited) {
|
||||
return t('Stake add');
|
||||
} else if (chainEvent.stakingEvent.stakeRemoved) {
|
||||
return t('Stake remove');
|
||||
}
|
||||
return t('Staking event');
|
||||
} else if (chainEvent.erc20Multisig) {
|
||||
if (chainEvent.erc20Multisig.signerAdded) {
|
||||
return t('Signer adde');
|
||||
} else if (chainEvent.erc20Multisig.signerRemoved) {
|
||||
return t('Signer remove');
|
||||
} else if (chainEvent.erc20Multisig.thresholdSet) {
|
||||
return t('Signer threshold');
|
||||
}
|
||||
return t('Multisig update');
|
||||
}
|
||||
return t('Chain Event');
|
||||
}
|
||||
|
||||
export const TxOrderType = ({ orderType, chainEvent }: TxOrderTypeProps) => {
|
||||
let type = displayString[orderType] || orderType;
|
||||
|
||||
let colours = 'text-white dark:text-white bg-zinc-800 dark:bg-zinc-800';
|
||||
|
||||
// This will get unwieldy and should probably produce a different colour of tag
|
||||
if (type === 'Chain Event' && !!chainEvent) {
|
||||
type = getLabelForChainEvent(chainEvent);
|
||||
colours =
|
||||
'text-white dark-text-white bg-vega-pink-dark dark:bg-vega-pink-dark';
|
||||
}
|
||||
return (
|
||||
<div
|
||||
data-testid="tx-type"
|
||||
className="text-sm rounded-md leading-none px-2 py-2 inline-block text-white dark:text-white bg-zinc-800 dark:bg-zinc-800 "
|
||||
className={`text-sm rounded-md leading-none px-2 py-2 inline-block ${colours}`}
|
||||
>
|
||||
{displayString[orderType] || orderType}
|
||||
{type}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -13,6 +13,7 @@ export const TxsInfiniteListItem = ({
|
||||
type,
|
||||
block,
|
||||
index,
|
||||
command,
|
||||
}: Partial<BlockExplorerTransactionResult>) => {
|
||||
if (
|
||||
!hash ||
|
||||
@ -54,7 +55,7 @@ export const TxsInfiniteListItem = ({
|
||||
/>
|
||||
</div>
|
||||
<div className="text-sm col-span-5 xl:col-span-2 leading-none flex items-center">
|
||||
<TxOrderType orderType={type} />
|
||||
<TxOrderType orderType={type} chainEvent={command?.chainEvent} />
|
||||
</div>
|
||||
<div
|
||||
className="text-sm col-span-3 xl:col-span-1 leading-none flex items-center"
|
||||
|
@ -26,7 +26,7 @@ const generateTxs = (number: number): BlockExplorerTransactionResult[] => {
|
||||
expiresAt: '1664966445481288736',
|
||||
type: 'TYPE_LIMIT',
|
||||
reference: 'traderbot',
|
||||
peggedOrder: null,
|
||||
peggedOrder: undefined,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
@ -93,7 +93,7 @@ export const TxsInfiniteList = ({
|
||||
{({ onItemsRendered, ref }) => (
|
||||
<List
|
||||
className="List"
|
||||
height={595}
|
||||
height={995}
|
||||
itemCount={itemCount}
|
||||
itemSize={isStacked ? 134 : 72}
|
||||
onItemsRendered={onItemsRendered}
|
||||
|
@ -42,7 +42,9 @@ export const TxsPerBlock = ({ blockHeight }: TxsPerBlockProps) => {
|
||||
</TableRow>
|
||||
</thead>
|
||||
<tbody>
|
||||
{decodedBlockData.map(({ TxHash, PubKey, Type }) => {
|
||||
{decodedBlockData.map(({ TxHash, PubKey, Type, Command }) => {
|
||||
const chainEvent = JSON.parse(Command || '');
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
modifier="bordered"
|
||||
@ -66,7 +68,7 @@ export const TxsPerBlock = ({ blockHeight }: TxsPerBlockProps) => {
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell modifier="bordered">
|
||||
<TxOrderType orderType={Type} />
|
||||
<TxOrderType orderType={Type} chainEvent={chainEvent} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
|
@ -16,6 +16,7 @@ export const ENV = {
|
||||
blockExplorerUrl: windowOrDefault('NX_BLOCK_EXPLORER'),
|
||||
tendermintUrl: windowOrDefault('NX_TENDERMINT_URL'),
|
||||
tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'),
|
||||
ethExplorerUrl: windowOrDefault('NX_ETHERSCAN_URL'),
|
||||
},
|
||||
flags: {
|
||||
assets: truthy.includes(windowOrDefault('NX_EXPLORER_ASSETS')),
|
||||
|
@ -1,3 +1,4 @@
|
||||
import type { components } from '../../../types/explorer';
|
||||
import type { UnknownObject } from '../../components/nested-data-list';
|
||||
|
||||
export interface BlockExplorerTransactionResult {
|
||||
@ -8,13 +9,7 @@ export interface BlockExplorerTransactionResult {
|
||||
type: string;
|
||||
code: number;
|
||||
cursor: string;
|
||||
command:
|
||||
| ValidatorHeartbeat
|
||||
| SubmitOrder
|
||||
| StateVariableProposal
|
||||
| AmendLiquidityProvisionOrder
|
||||
| BatchMarketInstructions
|
||||
| ChainEvent;
|
||||
command: components['schemas']['v1InputData'];
|
||||
}
|
||||
|
||||
export interface BlockExplorerTransactions {
|
||||
@ -103,16 +98,23 @@ export interface BatchCancellationInstruction {
|
||||
export interface ChainEvent {
|
||||
blockHeight: string;
|
||||
nonce: string;
|
||||
chainEvent: {
|
||||
erc20: {
|
||||
deposit: ERC20Deposit;
|
||||
};
|
||||
chainEvent: components['schemas']['v1ChainEvent'];
|
||||
}
|
||||
|
||||
export interface ChainEventErc20Multisig {
|
||||
erc20Multisig: {
|
||||
block: string;
|
||||
index: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ERC20Deposit {
|
||||
vegaAssetId: string;
|
||||
sourceEthereumAddress: string;
|
||||
targetPartyId: string;
|
||||
amount: string;
|
||||
export interface ChainEventErc20Deposit {
|
||||
erc20: {
|
||||
deposit: {
|
||||
vegaAssetId: string;
|
||||
sourceEthereumAddress: string;
|
||||
targetPartyId: string;
|
||||
amount: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
1563
apps/explorer/src/types/explorer.d.ts
vendored
Normal file
1563
apps/explorer/src/types/explorer.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,6 +13,7 @@
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"lib": ["es5", "es6", "dom", "dom.iterable"]
|
||||
},
|
||||
"exclude": ["./src/types/explorer.d.ts"],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user