Last fixes

- Pending Delegate events with registry-miss identity keep explorer navigation; unbonded label limited to pending Undelegate rows (`isPendingUndelegateWithRegistryMiss`, `formatPendingDelegationLinkLabel`).
- Tests in `delegationIdentity.test.ts`.
This commit is contained in:
Tommy Verrall
2026-06-08 12:38:09 +02:00
parent c52fc0c9af
commit 2c1b5f59a3
5 changed files with 61 additions and 27 deletions
@@ -319,28 +319,9 @@ export const DelegationList: FCWithChildren<{
Pending
</Typography>
<Stack spacing={2}>
{pendingItems.map((item: any, index: number) => {
if (
item.event &&
item.event.kind === 'Delegate' &&
(!item.node_identity || item.node_identity === '')
) {
return (
<PendingDelegationCard
key={pendingKey(item, `d-${index}`)}
item={{
...item,
node_identity: `Mix Identity Key ${item.event.mix_id}`,
}}
explorerUrl={explorerUrl}
/>
);
}
return (
<PendingDelegationCard key={pendingKey(item, `p-${index}`)} item={item} explorerUrl={explorerUrl} />
);
})}
{pendingItems.map((item: any, index: number) => (
<PendingDelegationCard key={pendingKey(item, `p-${index}`)} item={item} explorerUrl={explorerUrl} />
))}
</Stack>
</Stack>
)}
@@ -2,11 +2,16 @@ import React from 'react';
import { Box, Chip, Paper, Stack, Tooltip, Typography } from '@mui/material';
import { WrappedDelegationEvent } from '@nymproject/types';
import { TauriLink as Link } from 'src/components/TauriLinkWrapper';
import { formatDelegationNodeIdentityForDisplay, isUnbondedNodeIdentity } from 'src/utils/delegationIdentity';
import {
formatDelegationNodeIdentityForDisplay,
formatPendingDelegationLinkLabel,
isPendingUndelegateWithRegistryMiss,
} from 'src/utils/delegationIdentity';
export const PendingDelegationCard = ({ item, explorerUrl }: { item: WrappedDelegationEvent; explorerUrl: string }) => {
const pendingUndelegateRegistryMiss = isPendingUndelegateWithRegistryMiss(item);
const displayIdentity = formatDelegationNodeIdentityForDisplay(item.node_identity, item.event.mix_id);
const nodeIsUnbonded = isUnbondedNodeIdentity(item.node_identity);
const linkLabel = formatPendingDelegationLinkLabel(item.node_identity, item.event.mix_id);
return (
<Paper
@@ -20,7 +25,7 @@ export const PendingDelegationCard = ({ item, explorerUrl }: { item: WrappedDele
}}
>
<Stack spacing={1.5} direction={{ xs: 'column', sm: 'row' }} alignItems={{ sm: 'center' }} flexWrap="wrap">
{nodeIsUnbonded ? (
{pendingUndelegateRegistryMiss ? (
<Typography variant="body2" color="text.secondary">
{displayIdentity}
</Typography>
@@ -28,7 +33,7 @@ export const PendingDelegationCard = ({ item, explorerUrl }: { item: WrappedDele
<Link
target="_blank"
href={`${explorerUrl}/nodes/${item.event.mix_id}`}
text={`${item.node_identity.slice(0, 6)}...${item.node_identity.slice(-6)}`}
text={linkLabel}
color="text.primary"
noIcon
/>
@@ -2,9 +2,12 @@ import {
UNBONDED_NODE_IDENTITY_PREFIX,
formatUnbondedNodeLabel,
formatDelegationNodeIdentityForDisplay,
formatPendingDelegationLinkLabel,
isFullyUnbondedDelegation,
isPendingUndelegateWithRegistryMiss,
isUnbondedNodeIdentity,
} from './delegationIdentity';
import { buildPendingDelegateEvent, buildPendingUndelegateEvent } from './unbondedDelegation.fixture';
describe('delegationIdentity', () => {
it('treats empty identity as unbonded', () => {
@@ -35,4 +38,20 @@ describe('delegationIdentity', () => {
'2Abcdefghijklmnopqrstuvwxyz1234567890',
);
});
it('uses unbonded label only for pending undelegate registry misses', () => {
const pendingDelegate = buildPendingDelegateEvent(`unbonded:${42}`);
const pendingUndelegate = buildPendingUndelegateEvent(`unbonded:${42}`);
expect(isPendingUndelegateWithRegistryMiss(pendingDelegate)).toBe(false);
expect(isPendingUndelegateWithRegistryMiss(pendingUndelegate)).toBe(true);
});
it('formats pending delegate explorer link label by mix id when identity lookup missed', () => {
expect(formatPendingDelegationLinkLabel('', 788)).toBe('Mix 788');
expect(formatPendingDelegationLinkLabel('unbonded:788', 788)).toBe('Mix 788');
expect(formatPendingDelegationLinkLabel('2Abcdefghijklmnopqrstuvwxyz1234567890', 788)).toBe(
'2Abcde...567890',
);
});
});
+14 -1
View File
@@ -1,4 +1,4 @@
import type { DelegationWithEverything } from '@nymproject/types';
import type { DelegationWithEverything, WrappedDelegationEvent } from '@nymproject/types';
export const UNBONDED_NODE_IDENTITY_PREFIX = 'unbonded:';
@@ -25,3 +25,16 @@ export function formatDelegationNodeIdentityForDisplay(nodeIdentity: string, mix
}
return nodeIdentity;
}
export function isPendingUndelegateWithRegistryMiss(
item: Pick<WrappedDelegationEvent, 'node_identity' | 'event'>,
): boolean {
return item.event.kind === 'Undelegate' && isUnbondedNodeIdentity(item.node_identity);
}
export function formatPendingDelegationLinkLabel(nodeIdentity: string, mixId: number): string {
if (!nodeIdentity || isUnbondedNodeIdentity(nodeIdentity)) {
return `Mix ${mixId}`;
}
return `${nodeIdentity.slice(0, 6)}...${nodeIdentity.slice(-6)}`;
}
@@ -69,3 +69,19 @@ export function buildPendingUndelegateEvent(
},
};
}
export function buildPendingDelegateEvent(
nodeIdentity: string,
mixId: number = EXAMPLE_UNBONDED_MIX_ID,
): WrappedDelegationEvent {
return {
node_identity: nodeIdentity,
event: {
kind: 'Delegate',
mix_id: mixId,
address: EXAMPLE_DELEGATOR_ADDRESS,
amount: { amount: '1000000', denom: 'nym' },
proxy: null,
},
};
}