diff --git a/apps/explorer/src/app/components/epoch-overview/epoch-missing.tsx b/apps/explorer/src/app/components/epoch-overview/epoch-missing.tsx
index b39ee3aba..5454b6fdf 100644
--- a/apps/explorer/src/app/components/epoch-overview/epoch-missing.tsx
+++ b/apps/explorer/src/app/components/epoch-overview/epoch-missing.tsx
@@ -1,19 +1,9 @@
-import {
- useExplorerEpochQuery,
- useExplorerFutureEpochQuery,
-} from './__generated__/Epoch';
+import { useExplorerFutureEpochQuery } from './__generated__/Epoch';
-import { t } from '@vegaprotocol/react-helpers';
-import { BlockLink } from '../links';
-import { Time } from '../time';
-import { TimeAgo } from '../time-ago';
-import parseISO from 'date-fns/parseISO';
import addSeconds from 'date-fns/addSeconds';
-import parse from 'date-fns/parse';
import formatDistance from 'date-fns/formatDistance';
-
-const borderClass =
- 'border-solid border-2 border-vega-dark-150 border-collapse';
+import { Icon, Tooltip } from '@vegaprotocol/ui-toolkit';
+import isFuture from 'date-fns/isFuture';
export type EpochMissingOverviewProps = {
missingEpochId?: string;
@@ -26,11 +16,16 @@ const EpochMissingOverview = ({
}: EpochMissingOverviewProps) => {
const { data, error, loading } = useExplorerFutureEpochQuery();
+ if (!missingEpochId) {
+ return - ;
+ }
if (!data || loading || error) {
return {missingEpochId} ;
}
let label = 'Missing data';
+ // Let's assume it is
+ let isInFuture = true;
const epochLength = data.networkParameter?.value || '';
const epochLengthInSeconds = getSeconds(epochLength);
@@ -42,19 +37,29 @@ const EpochMissingOverview = ({
const diff = missing - current;
const futureDate = addSeconds(startFrom, diff * epochLengthInSeconds);
- label = `${futureDate.toLocaleString()} - roughly ${formatDistance(
+
+ label = `Estimate: ${futureDate.toLocaleString()} - ${formatDistance(
futureDate,
- startFrom
+ startFrom,
+ { addSuffix: true }
)} `;
+
+ isInFuture = isFuture(futureDate);
}
+ const description =
{label}
;
+
return (
-
- {missingEpochId}
-
-
+
+
+ {isInFuture ? (
+
+ ) : (
+
+ )}
+ {missingEpochId}
+
+
);
};
diff --git a/apps/explorer/src/app/components/epoch-overview/epoch.tsx b/apps/explorer/src/app/components/epoch-overview/epoch.tsx
index 974e8649b..332bc81ff 100644
--- a/apps/explorer/src/app/components/epoch-overview/epoch.tsx
+++ b/apps/explorer/src/app/components/epoch-overview/epoch.tsx
@@ -5,9 +5,12 @@ import { BlockLink } from '../links';
import { Time } from '../time';
import { TimeAgo } from '../time-ago';
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';
const borderClass =
- 'border-solid border-2 border-vega-dark-150 border-collapse';
+ 'border-solid border-2 border-vega-dark-200 border-collapse';
export type EpochOverviewProps = {
id?: string;
@@ -32,54 +35,82 @@ const EpochOverview = ({ id }: EpochOverviewProps) => {
return {id} ;
}
+ const description = (
+
+
+
+
+ {t('Block')}
+ {t('Time')}
+
+
+
+
+ {t('Start')}
+
+ {ti.firstBlock ? : '-'}
+
+
+
+
+
+
+
+
+ {t('End')}
+
+ {ti.lastBlock ? (
+
+ ) : (
+ t('In progress')
+ )}
+
+
+ {ti.end ? (
+ <>
+
+
+
+ >
+ ) : (
+ {t('-')}
+ )}
+
+
+
+
+ );
+
return (
-
- {id}
-
-
-
-
- {t('Block')}
- {t('Time')}
-
-
-
-
- {t('Epoch start')}
-
- {ti.firstBlock ? : '-'}
-
-
-
- —
-
-
-
-
- {t('Epoch end')}
-
- {ti.lastBlock ? (
-
- ) : (
- t('In progress')
- )}
-
-
- {ti.end ? (
- <>
-
- —
-
- >
- ) : (
- {t('-')}
- )}
-
-
-
-
-
+
+
+
+ {id}
+
+
);
};
+export type IconForEpochProps = {
+ start: string;
+ end: string;
+};
+
+function IconForEpoch({ start, end }: IconForEpochProps) {
+ const startHasPassed = isPast(new Date(start));
+ const endHasPassed = end ? isPast(new Date(end)) : false;
+
+ let i: IconProps['name'] = 'calendar';
+
+ if (!startHasPassed && !endHasPassed) {
+ i = 'calendar';
+ } else if (startHasPassed && !endHasPassed) {
+ i = 'circle';
+ } else if (startHasPassed && endHasPassed) {
+ i = 'tick-circle';
+ }
+
+ return ;
+}
+
export default EpochOverview;
diff --git a/apps/explorer/src/app/components/links/party-link/party-link.tsx b/apps/explorer/src/app/components/links/party-link/party-link.tsx
index 69bd88d66..726b323a9 100644
--- a/apps/explorer/src/app/components/links/party-link/party-link.tsx
+++ b/apps/explorer/src/app/components/links/party-link/party-link.tsx
@@ -5,16 +5,18 @@ import type { ComponentProps } from 'react';
import Hash from '../hash';
import { t } from '@vegaprotocol/react-helpers';
import { isValidPartyId } from '../../../routes/parties/id/components/party-id-error';
+import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
-const SPECIAL_CASE_NETWORK_ID =
+export const SPECIAL_CASE_NETWORK_ID =
'0000000000000000000000000000000000000000000000000000000000000000';
-const SPECIAL_CASE_NETWORK = 'network';
+export const SPECIAL_CASE_NETWORK = 'network';
export type PartyLinkProps = Partial> & {
id: string;
+ truncate?: boolean;
};
-const PartyLink = ({ id, ...props }: PartyLinkProps) => {
+const PartyLink = ({ id, truncate = false, ...props }: PartyLinkProps) => {
// Some transactions will involve the 'network' party, which is alias for '000...000'
// The party page does not handle this nicely, so in this case we render the word 'Network'
if (id === SPECIAL_CASE_NETWORK || id === SPECIAL_CASE_NETWORK_ID) {
@@ -41,7 +43,7 @@ const PartyLink = ({ id, ...props }: PartyLinkProps) => {
{...props}
to={`/${Routes.PARTIES}/${id}`}
>
-
+
);
};
diff --git a/apps/explorer/src/app/components/size-in-asset/size-in-asset.tsx b/apps/explorer/src/app/components/size-in-asset/size-in-asset.tsx
index 2414d9038..152386e75 100644
--- a/apps/explorer/src/app/components/size-in-asset/size-in-asset.tsx
+++ b/apps/explorer/src/app/components/size-in-asset/size-in-asset.tsx
@@ -1,7 +1,6 @@
import { useAssetDataProvider } from '@vegaprotocol/assets';
import { addDecimalsFormatNumber } from '@vegaprotocol/react-helpers';
import { AssetLink } from '../links';
-import { useExplorerMarketQuery } from '../links/market-link/__generated__/Market';
export type DecimalSource = 'ASSET';
diff --git a/apps/explorer/src/app/components/txs/details/transfer/transfer-recurring.tsx b/apps/explorer/src/app/components/txs/details/transfer/transfer-recurring.tsx
index c6650e600..5f9f94273 100644
--- a/apps/explorer/src/app/components/txs/details/transfer/transfer-recurring.tsx
+++ b/apps/explorer/src/app/components/txs/details/transfer/transfer-recurring.tsx
@@ -1,10 +1,30 @@
import { t } from '@vegaprotocol/react-helpers';
+import { Icon, Tooltip } from '@vegaprotocol/ui-toolkit';
import type { components } from '../../../../../types/explorer';
import EpochOverview from '../../../epoch-overview/epoch';
-import { AssetLink, MarketLink } from '../../../links';
+import { useExplorerFutureEpochQuery } from '../../../epoch-overview/__generated__/Epoch';
+import { AssetLink, MarketLink, PartyLink } from '../../../links';
+import {
+ SPECIAL_CASE_NETWORK,
+ SPECIAL_CASE_NETWORK_ID,
+} from '../../../links/party-link/party-link';
+import type { IconProps } from '@vegaprotocol/ui-toolkit';
+import SizeInAsset from '../../../size-in-asset/size-in-asset';
+import { AccountTypeMapping } from '@vegaprotocol/types';
+import { AccountType } from '@vegaprotocol/types';
+
+export type Metric = components['schemas']['vegaDispatchMetric'];
+
+const wrapperClasses =
+ 'border border-zinc-200 dark:border-zinc-800 rounded-md pv-2 mb-5 w-full sm:w-1/4 min-w-[200px] ';
+const headerClasses =
+ 'bg-solid bg-zinc-200 dark:bg-zinc-800 border-zinc-200 text-center text-xl py-2 font-alpha';
+
+type Transfer = components['schemas']['commandsv1Transfer'];
interface TransferRecurringProps {
- transfer: components['schemas']['v1RecurringTransfer'];
+ transfer: Transfer;
+ from: string;
}
/**
@@ -13,27 +33,144 @@ interface TransferRecurringProps {
*
* @param transfer A recurring transfer object
*/
-export function TransferRecurring({ transfer }: TransferRecurringProps) {
+export function TransferRecurring({ transfer, from }: TransferRecurringProps) {
+ const recurring = transfer.recurring;
+ const { data } = useExplorerFutureEpochQuery();
+ const metric =
+ recurring?.dispatchStrategy?.metric || 'DISPATCH_METRIC_UNSPECIFIED';
+
+ const fromAcct =
+ transfer.fromAccountType &&
+ transfer.fromAccountType !== 'ACCOUNT_TYPE_UNSPECIFIED'
+ ? AccountType[transfer.fromAccountType]
+ : AccountType.ACCOUNT_TYPE_GENERAL;
+ const fromAccountTypeLabel = transfer.fromAccountType
+ ? AccountTypeMapping[fromAcct]
+ : 'Unknown';
+
+ const toAcct =
+ transfer.toAccountType &&
+ transfer.toAccountType !== 'ACCOUNT_TYPE_UNSPECIFIED'
+ ? AccountType[transfer.toAccountType]
+ : AccountType.ACCOUNT_TYPE_GENERAL;
+ const toAccountTypeLabel = transfer.fromAccountType
+ ? AccountTypeMapping[toAcct]
+ : 'Unknown';
+
return (
-