1- import { useMemo , useState , Fragment } from "react" ;
1+ import { useMemo , useState , useEffect } from "react" ;
22import { Box , Tabs , Tab , styled , Skeleton } from "@mui/material" ;
33import { useLocation } from "react-router-dom" ;
4+ import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline" ;
5+ import CancelOutlinedIcon from "@mui/icons-material/CancelOutlined" ;
6+ import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined" ;
47
58import { CopyButton , ExternalModalButton , Tooltip , Typography } from "@atoms" ;
69import {
@@ -23,8 +26,10 @@ import {
2326 getFullGovActionId ,
2427 mapArrayToObjectByKeys ,
2528 encodeCIP129Identifier ,
29+ validateSignature ,
2630} from "@utils" ;
2731import { MetadataValidationStatus , ProposalData } from "@models" ;
32+ import { errorRed , successGreen } from "@/consts" ;
2833import { GovernanceActionType } from "@/types/governanceAction" ;
2934import { useAppContext } from "@/context" ;
3035
@@ -77,6 +82,7 @@ export const GovernanceActionDetailsCardData = ({
7782 proposal : {
7883 abstract,
7984 authors,
85+ json : jsonContent ,
8086 createdDate,
8187 createdEpochNo,
8288 details,
@@ -369,28 +375,39 @@ export const GovernanceActionDetailsCardData = ({
369375 < GovernanceActionCardElement
370376 label = { t ( "govActions.authors.title" ) }
371377 text = {
372- ( authors ?? [ ] ) . length <= 0
373- ? t ( "govActions.authors.noDataAvailable" )
374- : ( authors ?? [ ] ) . map ( ( author , idx , arr ) => (
375- < Fragment key = { author . publicKey } >
376- < Tooltip
377- heading = { `${ t ( "govActions.authors.witnessAlgorithm" ) } : ${
378- author . witnessAlgorithm
379- } `}
380- paragraphOne = { `${ t ( "govActions.authors.publicKey" ) } : ${
381- author . publicKey
382- } `}
383- paragraphTwo = { `${ t ( "govActions.authors.signature" ) } : ${
384- author . signature
385- } `}
386- placement = "bottom-end"
387- arrow
378+ < Box sx = { { display : "flex" , gap : 2 , flexWrap : "wrap" } } >
379+ { ( authors ?? [ ] ) . length <= 0
380+ ? t ( "govActions.authors.noDataAvailable" )
381+ : ( authors ?? [ ] ) . map ( ( author ) => (
382+ < Box
383+ key = { author . publicKey }
384+ sx = { { display : "flex" , gap : 0.5 , alignItems : "center" } }
388385 >
386+ < AuthorSignatureStatus
387+ signature = { author . signature }
388+ publicKey = { author . publicKey }
389+ algorithm = { author . witnessAlgorithm }
390+ jsonContent = { jsonContent }
391+ />
389392 < span > { author . name } </ span >
390- </ Tooltip >
391- { idx < arr . length - 1 && < span > , </ span > }
392- </ Fragment >
393- ) )
393+ < Tooltip
394+ heading = { `${ t ( "govActions.authors.witnessAlgorithm" ) } : ${
395+ author . witnessAlgorithm
396+ } `}
397+ paragraphOne = { `${ t ( "govActions.authors.publicKey" ) } : ${
398+ author . publicKey
399+ } `}
400+ paragraphTwo = { `${ t ( "govActions.authors.signature" ) } : ${
401+ author . signature
402+ } `}
403+ placement = "bottom-end"
404+ arrow
405+ >
406+ < InfoOutlinedIcon fontSize = "small" />
407+ </ Tooltip >
408+ </ Box >
409+ ) ) }
410+ </ Box >
394411 }
395412 textVariant = "longText"
396413 dataTestId = "authors"
@@ -498,3 +515,62 @@ const HardforkDetailsTabContent = ({
498515 </ Box >
499516 ) ;
500517} ;
518+
519+ const AuthorSignatureStatus = ( {
520+ algorithm,
521+ publicKey,
522+ signature,
523+ jsonContent,
524+ } : {
525+ algorithm ?: string ;
526+ publicKey ?: string ;
527+ signature ?: string ;
528+ jsonContent ?: Record < string , unknown > ;
529+ } ) => {
530+ const { t } = useTranslation ( ) ;
531+ const [ isSignatureValid , setIsSignatureValid ] = useState < boolean | null > (
532+ null ,
533+ ) ;
534+
535+ useEffect ( ( ) => {
536+ let cancelled = false ;
537+ async function checkSignature ( ) {
538+ const args = {
539+ jsonContent,
540+ algorithm,
541+ publicKey,
542+ signature,
543+ } ;
544+ const result = await validateSignature ( args ) ;
545+ if ( ! cancelled ) setIsSignatureValid ( result ) ;
546+ }
547+ checkSignature ( ) ;
548+ return ( ) => {
549+ cancelled = true ;
550+ } ;
551+ } , [ algorithm , jsonContent , publicKey , signature ] ) ;
552+
553+ if ( isSignatureValid === null ) {
554+ return < Skeleton variant = "text" width = { 16 } /> ;
555+ }
556+ return (
557+ < Tooltip
558+ heading = {
559+ isSignatureValid
560+ ? t ( "govActions.authors.singatureVerified" )
561+ : t ( "govActions.authors.signatureNotVerified" )
562+ }
563+ placement = "bottom-end"
564+ arrow
565+ >
566+ { isSignatureValid ? (
567+ < CheckCircleOutlineIcon
568+ sx = { { color : successGreen . c500 } }
569+ fontSize = "small"
570+ />
571+ ) : (
572+ < CancelOutlinedIcon sx = { { color : errorRed . c500 } } fontSize = "small" />
573+ ) }
574+ </ Tooltip >
575+ ) ;
576+ } ;
0 commit comments