generated from stacks-network/.github
-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
1,345 additions
and
182 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { useMemo } from 'react'; | ||
|
||
import { useSuspenseSignerStackersInfinite } from '../../../app/signers/data/UseSignerAddresses'; | ||
import { CopyButton } from '../../../common/components/CopyButton'; | ||
import { ListFooter } from '../../../common/components/ListFooter'; | ||
import { Section } from '../../../common/components/Section'; | ||
import { Box } from '../../../ui/Box'; | ||
import { Flex } from '../../../ui/Flex'; | ||
import { Stack } from '../../../ui/Stack'; | ||
import { Text } from '../../../ui/Text'; | ||
import { useSuspenseCurrentStackingCycle } from '../../_components/Stats/CurrentStackingCycle/useCurrentStackingCycle'; | ||
|
||
const addressItemHeight = 69; | ||
|
||
export function AssociatedAddressesTable({ signerKey }: { signerKey: string }) { | ||
const { currentCycleId } = useSuspenseCurrentStackingCycle(); | ||
const { | ||
data: signerStackers, | ||
isFetchingNextPage, | ||
fetchNextPage, | ||
hasNextPage, | ||
} = useSuspenseSignerStackersInfinite(currentCycleId, signerKey); | ||
|
||
const stackers = useMemo( | ||
() => signerStackers?.pages.flatMap(page => page.results), | ||
[signerStackers] | ||
); | ||
|
||
return ( | ||
<Section title="Associated addresses"> | ||
<Stack gap={0}> | ||
<Box h={addressItemHeight * 10} overflow="auto"> | ||
{signerStackers?.pages | ||
.flatMap(page => page.results) | ||
.map((stacker, i) => ( | ||
<Flex | ||
key={stacker.stacker_address} | ||
alignItems={'center'} | ||
gap={1} | ||
py={6} | ||
borderBottom={ | ||
i !== (stackers?.length ?? 0) - 1 | ||
? '1px solid var(--stacks-colors-borderSecondary)' | ||
: 'none' | ||
} | ||
> | ||
<Text fontSize={'sm'}>{stacker.stacker_address}</Text> | ||
<CopyButton | ||
className={'fancy-copy'} | ||
initialValue={stacker.pox_address} | ||
aria-label={'copy row'} | ||
size={4} | ||
color="textSubdued" | ||
/> | ||
</Flex> | ||
))} | ||
</Box> | ||
|
||
<ListFooter | ||
label="addresses" | ||
isLoading={isFetchingNextPage} | ||
fetchNextPage={fetchNextPage} | ||
hasNextPage={hasNextPage} | ||
pb={6} | ||
position={'sticky'} | ||
bottom={0} | ||
bg="surface" | ||
/> | ||
</Stack> | ||
</Section> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { SortDescending } from '@phosphor-icons/react'; | ||
import { useMemo } from 'react'; | ||
|
||
import { FilterMenu } from '../../../common/components/FilterMenu'; | ||
|
||
export enum CycleSortOrder { | ||
Asc = 'asc', | ||
Desc = 'desc', | ||
} | ||
|
||
function getSortOptionLabel(order: CycleSortOrder) { | ||
switch (order) { | ||
case CycleSortOrder.Asc: | ||
return 'Cycle Asc'; | ||
case CycleSortOrder.Desc: | ||
return 'Cycle Desc'; | ||
} | ||
} | ||
|
||
export function CycleSortFilter({ | ||
cycleSortOrder, | ||
setCycleSortOrder, | ||
}: { | ||
cycleSortOrder: CycleSortOrder; | ||
setCycleSortOrder: (order: CycleSortOrder) => void; | ||
}) { | ||
const menuItems = useMemo( | ||
() => | ||
Object.values(CycleSortOrder).map(order => ({ | ||
onClick: () => { | ||
setCycleSortOrder(order); | ||
}, | ||
label: getSortOptionLabel(order), | ||
})), | ||
[setCycleSortOrder] | ||
); | ||
|
||
return ( | ||
<FilterMenu | ||
filterLabel={() => getSortOptionLabel(cycleSortOrder)} | ||
menuItems={menuItems} | ||
leftIcon={SortDescending} | ||
/> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
'use client'; | ||
|
||
import { useParams } from 'next/navigation'; | ||
|
||
import { Grid, GridProps } from '../../../ui/Grid'; | ||
import { Stack } from '../../../ui/Stack'; | ||
import { PageTitle } from '../../_components/PageTitle'; | ||
import { AssociatedAddressesTable } from './AssociatedAddressesTable'; | ||
import { SignerKeyStats } from './SignerKeyStats'; | ||
import { SignerKeySummary } from './SignerKeySummary'; | ||
import { StackingHistoryTable } from './StackingHistoryTable'; | ||
|
||
export function SignerKeyPageLayout(props: GridProps) { | ||
return ( | ||
<Grid | ||
gridColumnGap={8} | ||
gridTemplateColumns={['100%', '100%', 'repeat(1, calc(100% - 352px) 320px)']} | ||
gridRowGap={[8, 8, 'unset']} | ||
maxWidth="100%" | ||
alignItems="flex-start" | ||
{...props} | ||
/> | ||
); | ||
} | ||
|
||
export default function PageClient() { | ||
const params = useParams<{ signerKey: string }>(); | ||
|
||
if (!params) { | ||
console.error('params is undefined. This component should receive params from its parent.'); | ||
return null; // or some error UI | ||
} | ||
|
||
const { signerKey } = params; | ||
return ( | ||
<> | ||
<PageTitle>Signer key</PageTitle> | ||
|
||
<SignerKeyPageLayout> | ||
<Stack gap={8}> | ||
<SignerKeySummary signerKey={signerKey} /> | ||
<AssociatedAddressesTable signerKey={signerKey} /> | ||
<StackingHistoryTable signerKey={signerKey} /> | ||
</Stack> | ||
<Stack gap={8}> | ||
<SignerKeyStats signerKey={signerKey} /> | ||
</Stack> | ||
</SignerKeyPageLayout> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { ExplorerErrorBoundary } from '@/app/_components/ErrorBoundary'; | ||
import { useSuspenseSignerStackers } from '@/app/signers/data/UseSignerAddresses'; | ||
import { Section } from '@/common/components/Section'; | ||
import { Box } from '@/ui/Box'; | ||
import { Stack } from '@/ui/Stack'; | ||
import { Caption } from '@/ui/typography'; | ||
|
||
import { useSuspenseCurrentStackingCycle } from '../../_components/Stats/CurrentStackingCycle/useCurrentStackingCycle'; | ||
import { useSuspensePoxSigner } from '../../signers/data/UseSigner'; | ||
|
||
interface SignerKeyStatsProps { | ||
signerKey: string; | ||
} | ||
|
||
function SignerKeyStatsBase({ signerKey }: SignerKeyStatsProps) { | ||
const { currentCycleId } = useSuspenseCurrentStackingCycle(); | ||
const { data: signerData } = useSuspensePoxSigner(currentCycleId, signerKey); | ||
const { data: signerStackers } = useSuspenseSignerStackers(currentCycleId, signerKey); | ||
|
||
return ( | ||
<Section title={'Stats'}> | ||
<Stack gap={2} py={4}> | ||
<Caption>Performance</Caption> | ||
<Box>Waiting on the API for the data</Box> | ||
</Stack> | ||
<Stack gap={2} py={4}> | ||
<Caption>Total signed transactions</Caption> | ||
<Box>Waiting on the API for the data</Box> | ||
</Stack> | ||
<Stack gap={2} py={4}> | ||
<Caption>Slot success rate</Caption> | ||
<Box>Waiting on the API for the data</Box> | ||
</Stack> | ||
<Stack gap={2} py={4}> | ||
<Caption>Uptime</Caption> | ||
<Box>Waiting on the API for the data</Box> | ||
</Stack> | ||
</Section> | ||
); | ||
} | ||
|
||
export function SignerKeyStats(props: SignerKeyStatsProps) { | ||
return ( | ||
<ExplorerErrorBoundary Wrapper={Section} wrapperProps={{ title: 'STX Balance' }} tryAgainButton> | ||
<SignerKeyStatsBase {...props} /> | ||
</ExplorerErrorBoundary> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { useSuspenseSignerStackers } from '@/app/signers/data/UseSignerAddresses'; | ||
import { KeyValueHorizontal } from '@/common/components/KeyValueHorizontal'; | ||
import { Section } from '@/common/components/Section'; | ||
import { Value } from '@/common/components/Value'; | ||
import { microToStacksFormatted } from '@/common/utils/utils'; | ||
import { Box } from '@/ui/Box'; | ||
import { Flex } from '@/ui/Flex'; | ||
|
||
import { getEntityName } from '../../../app/signers/SignersTable'; | ||
import { useSuspenseCurrentStackingCycle } from '../../_components/Stats/CurrentStackingCycle/useCurrentStackingCycle'; | ||
import { useSuspensePoxSigner } from '../../signers/data/UseSigner'; | ||
|
||
interface SignerKeySummaryProps { | ||
signerKey: string; | ||
} | ||
export const SignerKeySummary = ({ signerKey }: SignerKeySummaryProps) => { | ||
const { currentCycleId } = useSuspenseCurrentStackingCycle(); | ||
const { data: signerData } = useSuspensePoxSigner(currentCycleId, signerKey); | ||
const { data: signerStackers } = useSuspenseSignerStackers(currentCycleId, signerKey); | ||
|
||
return ( | ||
<Section title="Summary"> | ||
<Flex width="100%" flexDirection={['column', 'column', 'row']}> | ||
<Box width={['100%']}> | ||
<KeyValueHorizontal | ||
label={'Key'} | ||
value={<Value>{signerKey}</Value>} | ||
copyValue={signerKey} | ||
/> | ||
<KeyValueHorizontal | ||
label={'Entity'} | ||
value={<Value>{getEntityName(signerKey)}</Value>} | ||
copyValue={getEntityName(signerKey)} | ||
/> | ||
{/* <KeyValueHorizontal // TODO: this is stupid, I don't think we should show this as the calculation adds unncessary network calls | ||
label={'Rank'} | ||
value={<Value>{principal}</Value>} | ||
copyValue={principal} | ||
/> */} | ||
<KeyValueHorizontal | ||
label={'Voting Power'} | ||
value={<Value>{signerData?.weight_percent.toFixed(2)}%</Value>} | ||
copyValue={signerData?.weight_percent.toFixed(2)} | ||
/> | ||
<KeyValueHorizontal | ||
label={'STX Stacked'} | ||
value={<Value>{microToStacksFormatted(signerData?.stacked_amount)}</Value>} | ||
copyValue={microToStacksFormatted(signerData?.stacked_amount)} | ||
/> | ||
<KeyValueHorizontal | ||
label={'Associated Addresses'} | ||
value={<Value>{signerStackers?.results.length}</Value>} | ||
copyValue={signerStackers?.results.length.toString()} | ||
/> | ||
</Box> | ||
</Flex> | ||
</Section> | ||
); | ||
}; |
Oops, something went wrong.