Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/api/models/MinersDashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export type ScoreFactors = {
closedSwaps: number;
credibilityRamp: number;
credibilityRampTarget: number;
// Timed-out swaps in the credibility window — used to explain a hard-zeroed ramp.
credibilityTimedOut: number;
successRate30d: number;
successMultiplier: number;
};
Expand Down
46 changes: 37 additions & 9 deletions src/components/miners/ScoreFactorsStrip.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import React from 'react';
import { Box, Stack, Typography, alpha, useTheme } from '@mui/material';
import {
Box,
Stack,
Tooltip,
Typography,
alpha,
useTheme,
} from '@mui/material';
import type { ScoreFactors } from '../../api';
import { FONTS } from '../../theme';
import { formatTao } from '../../utils/format';
Expand All @@ -19,10 +26,17 @@ type Card = {
description: string;
delta?: Delta;
weak?: boolean;
tooltip?: string;
};

// Mirrors CREDIBILITY_MAX_TIMEOUTS in allways/das-allways — used for display copy
// only; the zeroing itself is computed server-side.
const CREDIBILITY_MAX_TIMEOUTS = 2;

const buildCards = (sf: ScoreFactors): Card[] => {
const credibilityRamped = sf.closedSwaps >= sf.credibilityRampTarget;
// Ramp forced to 0 while closed swaps exist = the timeout hard-floor tripped.
const zeroedByTimeouts = sf.closedSwaps > 0 && sf.credibilityRamp === 0;
return [
{
label: 'Crown share',
Expand Down Expand Up @@ -72,14 +86,21 @@ const buildCards = (sf: ScoreFactors): Card[] => {
{
label: 'Credibility',
window: 'last 30d',
headline: credibilityRamped
? fmtMultiplier(1.0)
: fmtMultiplier(sf.credibilityRamp),
headline: zeroedByTimeouts
? fmtMultiplier(0)
: credibilityRamped
? fmtMultiplier(1.0)
: fmtMultiplier(sf.credibilityRamp),
fill: sf.credibilityRamp,
description: credibilityRamped
? `fully ramped · ${sf.closedSwaps} of ${sf.credibilityRampTarget} closed`
: `${sf.closedSwaps} / ${sf.credibilityRampTarget} closed · resets if you fall below`,
weak: !credibilityRamped,
description: zeroedByTimeouts
? `auto-zeroed · ${sf.credibilityTimedOut} timeouts (limit ${CREDIBILITY_MAX_TIMEOUTS})`
: credibilityRamped
? `fully ramped · ${sf.closedSwaps} of ${sf.credibilityRampTarget} closed`
: `${sf.closedSwaps} / ${sf.credibilityRampTarget} closed · resets if you fall below`,
tooltip: zeroedByTimeouts
? `More than ${CREDIBILITY_MAX_TIMEOUTS} timed-out swaps in the 30-day window zero your credibility — and with it your whole reward. It recovers as old timeouts age out of the window.`
: undefined,
weak: zeroedByTimeouts || !credibilityRamped,
},
];
};
Expand Down Expand Up @@ -169,7 +190,7 @@ const FactorCard: React.FC<{ card: Card }> = ({ card }) => {
: theme.palette.primary.main;
const headlineColor = card.weak ? 'text.secondary' : 'text.primary';

return (
const body = (
<Box sx={{ px: 2.25, py: 2, minWidth: 0 }}>
<Typography
variant="monoSmall"
Expand Down Expand Up @@ -240,6 +261,13 @@ const FactorCard: React.FC<{ card: Card }> = ({ card }) => {
</Typography>
</Box>
);

if (!card.tooltip) return body;
return (
<Tooltip title={card.tooltip} arrow placement="top">
{body}
</Tooltip>
);
};

const composeMultiplier = (sf: ScoreFactors): number =>
Expand Down
Loading