feat(explorer): improve party account list display (#2391)
* feat(explorer): party account list as table
This commit is contained in:
parent
071a9ab34b
commit
b47caa7667
@ -5,13 +5,18 @@ import { useExplorerAssetQuery } from '../links/asset-link/__generated__/Asset';
|
||||
export type AssetBalanceProps = {
|
||||
assetId: string;
|
||||
price: string;
|
||||
showAssetLink?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a market ID and a price it will fetch the market
|
||||
* and format the price in that market's decimal places.
|
||||
*/
|
||||
const AssetBalance = ({ assetId, price }: AssetBalanceProps) => {
|
||||
const AssetBalance = ({
|
||||
assetId,
|
||||
price,
|
||||
showAssetLink = true,
|
||||
}: AssetBalanceProps) => {
|
||||
const { data } = useExplorerAssetQuery({
|
||||
fetchPolicy: 'cache-first',
|
||||
variables: { id: assetId },
|
||||
@ -25,7 +30,9 @@ const AssetBalance = ({ assetId, price }: AssetBalanceProps) => {
|
||||
return (
|
||||
<div className="inline-block">
|
||||
<span>{label}</span>{' '}
|
||||
{data?.asset?.id ? <AssetLink id={data.asset.id} /> : null}
|
||||
{showAssetLink && data?.asset?.id ? (
|
||||
<AssetLink id={data.asset.id} />
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -2,8 +2,8 @@ import { t } from '@vegaprotocol/react-helpers';
|
||||
import { useEffect } from 'react';
|
||||
import { InfoBlock } from '../../components/info-block';
|
||||
import { Panel } from '../../components/panel';
|
||||
import { useExplorerStatsQuery } from './__generated__/explorer-stats';
|
||||
import type { ExplorerStatsFieldsFragment } from './__generated__/explorer-stats';
|
||||
import { useExplorerStatsQuery } from './__generated__/Explorer-stats';
|
||||
import type { ExplorerStatsFieldsFragment } from './__generated__/Explorer-stats';
|
||||
|
||||
interface StatsMap {
|
||||
field: keyof ExplorerStatsFieldsFragment;
|
||||
|
@ -3,7 +3,7 @@ import React from 'react';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { SubHeading } from '../../components/sub-heading';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { useExplorerProposalsQuery } from './__generated__/proposals';
|
||||
import { useExplorerProposalsQuery } from './__generated__/Proposals';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
|
||||
const Governance = () => {
|
||||
|
@ -1,3 +1,28 @@
|
||||
fragment ExplorerPartyAssetsAccounts on AccountBalance {
|
||||
asset {
|
||||
name
|
||||
id
|
||||
decimals
|
||||
symbol
|
||||
source {
|
||||
__typename
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
type
|
||||
balance
|
||||
market {
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query ExplorerPartyAssets($partyId: ID!) {
|
||||
partiesConnection(id: $partyId) {
|
||||
edges {
|
||||
@ -21,28 +46,7 @@ query ExplorerPartyAssets($partyId: ID!) {
|
||||
accountsConnection {
|
||||
edges {
|
||||
node {
|
||||
asset {
|
||||
name
|
||||
id
|
||||
decimals
|
||||
symbol
|
||||
source {
|
||||
__typename
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
type
|
||||
balance
|
||||
market {
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
...ExplorerPartyAssetsAccounts
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerPartyAssetsAccountsFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string } } } | null };
|
||||
|
||||
export type ExplorerPartyAssetsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
@ -10,7 +12,32 @@ export type ExplorerPartyAssetsQueryVariables = Types.Exact<{
|
||||
|
||||
export type ExplorerPartyAssetsQuery = { __typename?: 'Query', partiesConnection?: { __typename?: 'PartyConnection', edges: Array<{ __typename?: 'PartyEdge', node: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string } } } | null } } | null> | null } | null } }> } | null };
|
||||
|
||||
|
||||
export const ExplorerPartyAssetsAccountsFragmentDoc = gql`
|
||||
fragment ExplorerPartyAssetsAccounts on AccountBalance {
|
||||
asset {
|
||||
name
|
||||
id
|
||||
decimals
|
||||
symbol
|
||||
source {
|
||||
__typename
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
type
|
||||
balance
|
||||
market {
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const ExplorerPartyAssetsDocument = gql`
|
||||
query ExplorerPartyAssets($partyId: ID!) {
|
||||
partiesConnection(id: $partyId) {
|
||||
@ -35,28 +62,7 @@ export const ExplorerPartyAssetsDocument = gql`
|
||||
accountsConnection {
|
||||
edges {
|
||||
node {
|
||||
asset {
|
||||
name
|
||||
id
|
||||
decimals
|
||||
symbol
|
||||
source {
|
||||
__typename
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
type
|
||||
balance
|
||||
market {
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
...ExplorerPartyAssetsAccounts
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -64,7 +70,7 @@ export const ExplorerPartyAssetsDocument = gql`
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
${ExplorerPartyAssetsAccountsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useExplorerPartyAssetsQuery__
|
@ -0,0 +1,81 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import get from 'lodash/get';
|
||||
import AssetBalance from '../../../../components/asset-balance/asset-balance';
|
||||
import { AssetLink, MarketLink } from '../../../../components/links';
|
||||
import { Table, TableRow } from '../../../../components/table';
|
||||
import type * as Schema from '@vegaprotocol/types';
|
||||
import type { ExplorerPartyAssetsAccountsFragment } from '../__generated__/Party-assets';
|
||||
|
||||
const accountTypeString: Record<Schema.AccountType, string> = {
|
||||
ACCOUNT_TYPE_BOND: t('Bond'),
|
||||
ACCOUNT_TYPE_EXTERNAL: t('External'),
|
||||
ACCOUNT_TYPE_FEES_INFRASTRUCTURE: t('Fees (Infrastructure)'),
|
||||
ACCOUNT_TYPE_FEES_LIQUIDITY: t('Fees (Liquidity)'),
|
||||
ACCOUNT_TYPE_FEES_MAKER: t('Fees (Maker)'),
|
||||
ACCOUNT_TYPE_GENERAL: t('General'),
|
||||
ACCOUNT_TYPE_GLOBAL_INSURANCE: t('Global Insurance Pool'),
|
||||
ACCOUNT_TYPE_GLOBAL_REWARD: t('Global Reward Pool'),
|
||||
ACCOUNT_TYPE_INSURANCE: t('Insurance'),
|
||||
ACCOUNT_TYPE_MARGIN: t('Margin'),
|
||||
ACCOUNT_TYPE_PENDING_TRANSFERS: t('Pending Transfers'),
|
||||
ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: t('Reward - LP Fees received'),
|
||||
ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES: t('Reward - Maker fees paid'),
|
||||
ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES: t('Reward - Maker fees received'),
|
||||
ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: t('Reward - Market proposers'),
|
||||
ACCOUNT_TYPE_SETTLEMENT: t('Settlement'),
|
||||
};
|
||||
|
||||
interface PartyAccountsProps {
|
||||
accounts: ExplorerPartyAssetsAccountsFragment[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a list of a party's accounts as a table. Currently unsorted, but could
|
||||
* probably do with sorting by asset, and then within asset, by type with general
|
||||
* appearing first and... tbd
|
||||
*/
|
||||
export const PartyAccounts = ({ accounts }: PartyAccountsProps) => {
|
||||
return (
|
||||
<Table className="max-w-5xl min-w-fit">
|
||||
<thead>
|
||||
<TableRow modifier="bordered" className="font-mono">
|
||||
<td>{t('Type')}</td>
|
||||
<td>{t('Market')}</td>
|
||||
<td className="text-right pr-2">{t('Balance')}</td>
|
||||
<td>{t('Asset')}</td>
|
||||
</TableRow>
|
||||
</thead>
|
||||
<tbody>
|
||||
{accounts.map((account) => {
|
||||
const m = get(account, 'market.tradableInstrument.instrument.name');
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
title={account.asset.name}
|
||||
id={`${accountTypeString[account.type]} ${m ? ` - ${m}` : ''}`}
|
||||
>
|
||||
<td className="text-md">{accountTypeString[account.type]}</td>
|
||||
<td className="text-md">
|
||||
{account.market?.id ? (
|
||||
<MarketLink id={account.market?.id} />
|
||||
) : (
|
||||
<p>-</p>
|
||||
)}
|
||||
</td>
|
||||
<td className="text-md text-right pr-2">
|
||||
<AssetBalance
|
||||
assetId={account.asset.id}
|
||||
price={account.balance}
|
||||
showAssetLink={false}
|
||||
/>
|
||||
</td>
|
||||
<td className="text-md">
|
||||
<AssetLink id={account.asset.id} />
|
||||
</td>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</Table>
|
||||
);
|
||||
};
|
@ -1,40 +1,17 @@
|
||||
import {
|
||||
t,
|
||||
addDecimalsFormatNumber,
|
||||
useScreenDimensions,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { getNodes, t, useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
import { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { SubHeading } from '../../../components/sub-heading';
|
||||
import { Panel } from '../../../components/panel';
|
||||
import { InfoPanel } from '../../../components/info-panel';
|
||||
import { toNonHex } from '../../../components/search/detect-search';
|
||||
import { useTxsData } from '../../../hooks/use-txs-data';
|
||||
import { TxsInfiniteList } from '../../../components/txs';
|
||||
import { PageHeader } from '../../../components/page-header';
|
||||
import { useExplorerPartyAssetsQuery } from './__generated__/party-assets';
|
||||
import type * as Schema from '@vegaprotocol/types';
|
||||
import get from 'lodash/get';
|
||||
import { useExplorerPartyAssetsQuery } from './__generated__/Party-assets';
|
||||
import type { ExplorerPartyAssetsAccountsFragment } from './__generated__/Party-assets';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
|
||||
const accountTypeString: Record<Schema.AccountType, string> = {
|
||||
ACCOUNT_TYPE_BOND: t('Bond'),
|
||||
ACCOUNT_TYPE_EXTERNAL: t('External'),
|
||||
ACCOUNT_TYPE_FEES_INFRASTRUCTURE: t('Fees (Infrastructure)'),
|
||||
ACCOUNT_TYPE_FEES_LIQUIDITY: t('Fees (Liquidity)'),
|
||||
ACCOUNT_TYPE_FEES_MAKER: t('Fees (Maker)'),
|
||||
ACCOUNT_TYPE_GENERAL: t('General'),
|
||||
ACCOUNT_TYPE_GLOBAL_INSURANCE: t('Global Insurance Pool'),
|
||||
ACCOUNT_TYPE_GLOBAL_REWARD: t('Global Reward Pool'),
|
||||
ACCOUNT_TYPE_INSURANCE: t('Insurance'),
|
||||
ACCOUNT_TYPE_MARGIN: t('Margin'),
|
||||
ACCOUNT_TYPE_PENDING_TRANSFERS: t('Pending Transfers'),
|
||||
ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: t('Reward - LP Fees received'),
|
||||
ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES: t('Reward - Maker fees paid'),
|
||||
ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES: t('Reward - Maker fees received'),
|
||||
ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: t('Reward - Market proposers'),
|
||||
ACCOUNT_TYPE_SETTLEMENT: t('Settlement'),
|
||||
};
|
||||
import GovernanceAssetBalance from '../../../components/asset-balance/governance-asset-balance';
|
||||
import { PartyAccounts } from './components/party-accounts';
|
||||
|
||||
const Party = () => {
|
||||
const { party } = useParams<{ party: string }>();
|
||||
@ -71,63 +48,23 @@ const Party = () => {
|
||||
</Panel>
|
||||
);
|
||||
|
||||
const accounts = (
|
||||
<section>
|
||||
{p?.accountsConnection?.edges?.length ? (
|
||||
p.accountsConnection?.edges?.map((a) => {
|
||||
const account = a?.node;
|
||||
if (!account || !account.asset) {
|
||||
return '';
|
||||
}
|
||||
const m = get(account, 'market.tradableInstrument.instrument.name');
|
||||
|
||||
return (
|
||||
<InfoPanel
|
||||
title={account.asset.name}
|
||||
id={`${accountTypeString[account.type]} ${m ? ` - ${m}` : ''}`}
|
||||
>
|
||||
<section>
|
||||
<dl className="flex gap-2 flex-wrap">
|
||||
<dt className="text-zinc-500 dark:text-zinc-400 text-md">
|
||||
<p>
|
||||
{t('Balance')} ({account.asset.symbol})
|
||||
</p>
|
||||
</dt>
|
||||
<dd className="text-md">
|
||||
{addDecimalsFormatNumber(
|
||||
account.balance,
|
||||
account.asset.decimals
|
||||
)}
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</InfoPanel>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<Panel>
|
||||
<p>No Data</p>
|
||||
</Panel>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
|
||||
const staking = (
|
||||
<section>
|
||||
{p?.stakingSummary?.currentStakeAvailable ? (
|
||||
<InfoPanel
|
||||
title={t('Current Stake Available')}
|
||||
id={p?.stakingSummary?.currentStakeAvailable}
|
||||
copy={false}
|
||||
/>
|
||||
) : (
|
||||
<Panel>
|
||||
<p>Nothing staked for {party}</p>
|
||||
</Panel>
|
||||
)}
|
||||
<p className="mt-4 leading-3">
|
||||
<strong className="font-semibold">{t('Staking Balance: ')}</strong>
|
||||
<GovernanceAssetBalance
|
||||
price={p.stakingSummary.currentStakeAvailable}
|
||||
/>
|
||||
</p>
|
||||
) : null}
|
||||
</section>
|
||||
);
|
||||
|
||||
const accounts = getNodes<ExplorerPartyAssetsAccountsFragment>(
|
||||
p?.accountsConnection
|
||||
);
|
||||
|
||||
return (
|
||||
<section>
|
||||
<h1
|
||||
@ -140,8 +77,7 @@ const Party = () => {
|
||||
<>
|
||||
{header}
|
||||
<SubHeading>{t('Asset data')}</SubHeading>
|
||||
{accounts}
|
||||
<SubHeading>{t('Staking')}</SubHeading>
|
||||
{accounts ? <PartyAccounts accounts={accounts} /> : null}
|
||||
{staking}
|
||||
|
||||
<SubHeading>{t('Transactions')}</SubHeading>
|
||||
|
@ -6,7 +6,7 @@ import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { DATA_SOURCES } from '../../config';
|
||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import type { TendermintValidatorsResponse } from './tendermint-validator-response';
|
||||
import { useExplorerNodesQuery } from './__generated__/nodes';
|
||||
import { useExplorerNodesQuery } from './__generated__/Nodes';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
|
||||
const Validators = () => {
|
||||
|
Loading…
Reference in New Issue
Block a user