Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for filtering TX lists for method type #1679

Merged
merged 8 commits into from
Jan 24, 2025
Merged
1 change: 1 addition & 0 deletions .changelog/1679.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for filtering transactions by method type
288 changes: 176 additions & 112 deletions src/app/components/ConsensusTransactionMethod/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import PriceChangeIcon from '@mui/icons-material/PriceChange'
import QuestionMarkIcon from '@mui/icons-material/QuestionMark'
import Tooltip from '@mui/material/Tooltip'
import { tooltipDelay } from '../../../styles/theme'
import { ConsensusTxMethod } from '../../../oasis-nexus/api'
import { ConsensusTxMethod, GetConsensusTransactionsParams } from '../../../oasis-nexus/api'
import { COLORS } from '../../../styles/theme/colors'
import { SelectOptionBase } from '../Select'
import { exhaustedTypeWarning } from '../../../types/errors'

type MethodIconProps = {
border?: boolean
Expand Down Expand Up @@ -170,6 +172,135 @@ const MethodIconWithTruncatedLabel: FC<MethodIconProps> = props => {
)
}

const getConsensusTransactionLabel = (t: TFunction, method: ConsensusTxMethod | undefined): string => {
// Please note: when updating this, keep it in sync
// with the knownConsensusTxMethods array below!

switch (method) {
csillag marked this conversation as resolved.
Show resolved Hide resolved
case ConsensusTxMethod.stakingTransfer:
return t('transactions.method.stakingTransfer')
case ConsensusTxMethod.stakingAddEscrow:
return t('transactions.method.stakingAddEscrow')
case ConsensusTxMethod.stakingReclaimEscrow:
return t('transactions.method.stakingReclaimEscrow')
case ConsensusTxMethod.stakingAmendCommissionSchedule:
return t('transactions.method.stakingAmendCommissionSchedule')
case ConsensusTxMethod.stakingAllow:
return t('transactions.method.stakingAllow')
case ConsensusTxMethod.stakingWithdraw:
return t('transactions.method.stakingWithdraw')
case ConsensusTxMethod.roothashExecutorCommit:
return t('transactions.method.roothashExecutorCommit')
case ConsensusTxMethod.roothashExecutorProposerTimeout:
return t('transactions.method.roothashExecutorProposerTimeout')
case ConsensusTxMethod.registryRegisterEntity:
return t('transactions.method.registryRegisterEntity')
case ConsensusTxMethod.registryRegisterNode:
return t('transactions.method.registryRegisterNode')
case ConsensusTxMethod.registryRegisterRuntime:
return t('transactions.method.registryRegisterRuntime')
case ConsensusTxMethod.governanceCastVote:
return t('transactions.method.governanceCastVote')
case ConsensusTxMethod.governanceSubmitProposal:
return t('transactions.method.governanceSubmitProposal')
case ConsensusTxMethod.beaconPVSSCommit:
return t('transactions.method.beaconPVSSCommit')
case ConsensusTxMethod.beaconPVSSReveal:
return t('transactions.method.beaconPVSSReveal')
case ConsensusTxMethod.beaconVRFProve:
return t('transactions.method.beaconVRFProve')
case ConsensusTxMethod.consensusMeta:
return t('transactions.method.consensus.meta')
case ConsensusTxMethod.keymanagerPublishEphemeralSecret:
return t('transactions.method.keyManager.publishEphemeralSecret')
case ConsensusTxMethod.keymanagerPublishMasterSecret:
return t('transactions.method.keyManager.publishMasterSecret')
case ConsensusTxMethod.keymanagerUpdatePolicy:
return t('transactions.method.keyManager.updatePolicy')
case ConsensusTxMethod['keymanager/churpApply']:
return t('transactions.method.keyManager.churp.apply')
case ConsensusTxMethod['keymanager/churpConfirm']:
return t('transactions.method.keyManager.churp.confirm')
case ConsensusTxMethod['keymanager/churpCreate']:
return t('transactions.method.keyManager.churp.create')
case ConsensusTxMethod['keymanager/churpUpdate']:
return t('transactions.method.keyManager.churp.update')
case ConsensusTxMethod.registryDeregisterEntity:
return t('transactions.method.registryDeregisterEntity')
case ConsensusTxMethod.registryProveFreshness:
return t('transactions.method.registryProveFreshness')
case ConsensusTxMethod.registryUnfreezeNode:
return t('transactions.method.registryUnfreezeNode')
case ConsensusTxMethod.roothashEvidence:
return t('transactions.method.roothashEvidence')
case ConsensusTxMethod.roothashSubmitMsg:
return t('transactions.method.roothashSubmitMessage')
case ConsensusTxMethod.stakingBurn:
return t('transactions.method.stakingBurn')
case ConsensusTxMethod.vaultAuthorizeAction:
return t('transactions.method.vault.authorizeAction')
case ConsensusTxMethod.vaultCancelAction:
return t('transactions.method.vault.cancelAction')
case ConsensusTxMethod.vaultCreate:
return t('transactions.method.vault.create')
case undefined:
return t('common.missing')
default:
exhaustedTypeWarning('Unexpected consensus transaction method', method)
return method || t('common.unknown')
csillag marked this conversation as resolved.
Show resolved Hide resolved
}
}

// List of known consensus ts types, to offer in filter
// Please keep them in alphabetical order
const knownConsensusTxMethods = [
ConsensusTxMethod.stakingAllow,
ConsensusTxMethod.stakingAmendCommissionSchedule,
ConsensusTxMethod.governanceCastVote,
ConsensusTxMethod.stakingBurn,
ConsensusTxMethod.consensusMeta,
ConsensusTxMethod.stakingWithdraw,
ConsensusTxMethod.registryDeregisterEntity,
ConsensusTxMethod.roothashExecutorCommit,
ConsensusTxMethod.roothashExecutorProposerTimeout,
ConsensusTxMethod['keymanager/churpApply'],
ConsensusTxMethod['keymanager/churpConfirm'],
ConsensusTxMethod['keymanager/churpCreate'],
ConsensusTxMethod['keymanager/churpUpdate'],
ConsensusTxMethod.keymanagerPublishEphemeralSecret,
ConsensusTxMethod.keymanagerPublishMasterSecret,
ConsensusTxMethod.keymanagerUpdatePolicy,
ConsensusTxMethod.beaconPVSSCommit,
ConsensusTxMethod.beaconPVSSReveal,
ConsensusTxMethod.registryRegisterEntity,
ConsensusTxMethod.registryRegisterNode,
ConsensusTxMethod.registryRegisterRuntime,
ConsensusTxMethod.registryProveFreshness,
ConsensusTxMethod.registryUnfreezeNode,
ConsensusTxMethod.roothashEvidence,
ConsensusTxMethod.roothashSubmitMsg,
ConsensusTxMethod.stakingAddEscrow,
ConsensusTxMethod.stakingReclaimEscrow,
ConsensusTxMethod.governanceSubmitProposal,
ConsensusTxMethod.stakingTransfer,
ConsensusTxMethod.beaconVRFProve,
ConsensusTxMethod.vaultAuthorizeAction,
ConsensusTxMethod.vaultCancelAction,
ConsensusTxMethod.vaultCreate,
] satisfies ConsensusTxMethod[]

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const typeTestExhaustiveArray =
undefined as unknown as ConsensusTxMethod satisfies (typeof knownConsensusTxMethods)[number]

export const getConsensusTxMethodOptions = (t: TFunction): SelectOptionBase[] =>
knownConsensusTxMethods.map(
(method): SelectOptionBase => ({
value: method,
label: getConsensusTransactionLabel(t, method),
}),
)

const getConsensusTransactionMethod = (
t: TFunction,
method: ConsensusTxMethod | undefined,
Expand All @@ -178,135 +309,62 @@ const getConsensusTransactionMethod = (
const props = {
truncate,
}
const label = getConsensusTransactionLabel(t, method)
switch (method) {
case ConsensusTxMethod.stakingTransfer:
return (
<MethodIcon
color="green"
icon={<ArrowForwardIcon />}
label={t('transactions.method.stakingTransfer')}
{...props}
/>
)
return <MethodIcon color="green" icon={<ArrowForwardIcon />} label={label} {...props} />
case ConsensusTxMethod.stakingAddEscrow:
return (
<MethodIcon
color="green"
icon={<ExitToAppIcon />}
label={t('transactions.method.stakingAddEscrow')}
{...props}
/>
)
return <MethodIcon color="green" icon={<ExitToAppIcon />} label={label} {...props} />
case ConsensusTxMethod.stakingReclaimEscrow:
return (
<MethodIcon
icon={<ExitToAppIcon />}
label={t('transactions.method.stakingReclaimEscrow')}
{...props}
/>
)
return <MethodIcon icon={<ExitToAppIcon />} label={label} {...props} />
case ConsensusTxMethod.stakingAmendCommissionSchedule:
return (
<MethodIcon
icon={<PriceChangeIcon />}
label={t('transactions.method.stakingAmendCommissionSchedule')}
{...props}
/>
)
return <MethodIcon icon={<PriceChangeIcon />} label={label} {...props} />
case ConsensusTxMethod.stakingAllow:
return (
<MethodIcon icon={<LibraryAddCheckIcon />} label={t('transactions.method.stakingAllow')} {...props} />
)
return <MethodIcon icon={<LibraryAddCheckIcon />} label={label} {...props} />
case ConsensusTxMethod.stakingWithdraw:
return (
<MethodIcon
color="green"
icon={<ArrowDownwardIcon />}
label={t('transactions.method.stakingWithdraw')}
{...props}
/>
)
return <MethodIcon color="green" icon={<ArrowDownwardIcon />} label={label} {...props} />
case ConsensusTxMethod.roothashExecutorCommit:
return (
<MethodIcon
icon={<MiscellaneousServicesIcon />}
label={t('transactions.method.roothashExecutorCommit')}
{...props}
/>
)
return <MethodIcon icon={<MiscellaneousServicesIcon />} label={label} {...props} />
case ConsensusTxMethod.roothashExecutorProposerTimeout:
return (
<MethodIcon
icon={<MiscellaneousServicesIcon />}
label={t('transactions.method.roothashExecutorProposerTimeout')}
{...props}
/>
)
return <MethodIcon icon={<MiscellaneousServicesIcon />} label={label} {...props} />
case ConsensusTxMethod.registryRegisterEntity:
return (
<MethodIcon
icon={<PersonIcon />}
label={t('transactions.method.registryRegisterEntity')}
{...props}
/>
)
return <MethodIcon icon={<PersonIcon />} label={label} {...props} />
case ConsensusTxMethod.registryRegisterNode:
return (
<MethodIcon icon={<DnsIcon />} label={t('transactions.method.registryRegisterNode')} {...props} />
)
return <MethodIcon icon={<DnsIcon />} label={label} {...props} />
case ConsensusTxMethod.registryRegisterRuntime:
return (
<MethodIcon
icon={<MiscellaneousServicesIcon />}
label={t('transactions.method.registryRegisterRuntime')}
{...props}
/>
)
return <MethodIcon icon={<MiscellaneousServicesIcon />} label={label} {...props} />
case ConsensusTxMethod.governanceCastVote:
return (
<MethodIcon icon={<HowToVoteIcon />} label={t('transactions.method.governanceCastVote')} {...props} />
)
return <MethodIcon icon={<HowToVoteIcon />} label={label} {...props} />
case ConsensusTxMethod.governanceSubmitProposal:
return (
<MethodIcon
icon={<AccountBalanceIcon />}
label={t('transactions.method.governanceSubmitProposal')}
{...props}
/>
)
return <MethodIcon icon={<AccountBalanceIcon />} label={label} {...props} />
case ConsensusTxMethod.beaconPVSSCommit:
return (
<MethodIcon
icon={<MiscellaneousServicesIcon />}
label={t('transactions.method.beaconPVSSCommit')}
{...props}
/>
)
return <MethodIcon icon={<MiscellaneousServicesIcon />} label={label} {...props} />
case ConsensusTxMethod.beaconPVSSReveal:
return (
<MethodIcon
icon={<MiscellaneousServicesIcon />}
label={t('transactions.method.beaconPVSSReveal')}
{...props}
/>
)
return <MethodIcon icon={<MiscellaneousServicesIcon />} label={label} {...props} />
case ConsensusTxMethod.beaconVRFProve:
return (
<MethodIcon
icon={<MiscellaneousServicesIcon />}
label={t('transactions.method.beaconVRFProve')}
{...props}
/>
)
return <MethodIcon icon={<MiscellaneousServicesIcon />} label={label} {...props} />
case ConsensusTxMethod['keymanager/churpApply']: // TODO: provide dedicated icon
case ConsensusTxMethod['keymanager/churpConfirm']: // TODO: provide dedicated icon
case ConsensusTxMethod['keymanager/churpCreate']: // TODO: provide dedicated icon
case ConsensusTxMethod['keymanager/churpUpdate']: // TODO: provide dedicated icon
case ConsensusTxMethod.vaultCreate: // TODO: provide dedicated icon
case ConsensusTxMethod.keymanagerPublishEphemeralSecret: // TODO: provide dedicated icon
case ConsensusTxMethod.keymanagerPublishMasterSecret: // TODO: provide dedicated icon
case ConsensusTxMethod.keymanagerUpdatePolicy: // TODO: provide dedicated icon
case ConsensusTxMethod.registryDeregisterEntity: // TODO: provide dedicated icon
case ConsensusTxMethod.registryProveFreshness: // TODO: provide dedicated icon
case ConsensusTxMethod.registryUnfreezeNode: // TODO: provide dedicated icon
case ConsensusTxMethod.roothashEvidence: // TODO: provide dedicated icon
case ConsensusTxMethod.roothashSubmitMsg: // TODO: provide dedicated icon
case ConsensusTxMethod.vaultAuthorizeAction: // TODO: provide dedicated icon
case ConsensusTxMethod.vaultCancelAction: // TODO: provide dedicated icon
case ConsensusTxMethod.consensusMeta: // TODO: provide dedicated icon
case ConsensusTxMethod.stakingBurn: // TODO: provide dedicated icon
case undefined:
return <MethodIcon color="gray" icon={<QuestionMarkIcon />} label={label} {...props} />
default:
return (
<MethodIcon
color="gray"
icon={<QuestionMarkIcon />}
label={method || t('common.unknown')}
{...props}
/>
)
exhaustedTypeWarning('Unexpected consensus transaction method', method)
return <MethodIcon color="gray" icon={<QuestionMarkIcon />} label={label} {...props} />
csillag marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand All @@ -320,3 +378,9 @@ export const ConsensusTransactionMethod: FC<ConsensusTransactionMethodProps> = (

return <>{getConsensusTransactionMethod(t, method, truncate)}</>
}

export type ConsensusTxMethodFilterOption = ConsensusTxMethod | 'any'

export const getConsensusTransactionMethodFilteringParam = (
method: ConsensusTxMethodFilterOption,
): Partial<GetConsensusTransactionsParams> => (method === 'any' ? {} : { method })
5 changes: 3 additions & 2 deletions src/app/components/LinkableCardLayout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ type LinkableCardLayoutProps = {
children: ReactNode
containerId: string
title: ReactNode
action?: ReactNode | undefined
}
export const LinkableCardLayout: FC<LinkableCardLayoutProps> = ({ children, containerId, title }) => {
export const LinkableCardLayout: FC<LinkableCardLayoutProps> = ({ children, containerId, title, action }) => {
return (
<Card>
<LinkableDiv id={containerId}>
<CardHeader disableTypography component="h3" title={title} />
<CardHeader disableTypography component="h3" title={title} action={action} />
</LinkableDiv>
<CardContent>
<ErrorBoundary light={true}>{children}</ErrorBoundary>
Expand Down
Loading
Loading