Quellcode durchsuchen

[xc-admin-frontend] XC admin frontend fix part2 (#970)

* Add some missing hook dependencies

* Smarter target cluster detection

* Show approved/rejected count for active proposals
Mohammad Amin Khashkhashi Moghaddam vor 2 Jahren
Ursprung
Commit
813ad34b68

+ 3 - 1
governance/xc_admin/packages/xc_admin_frontend/components/InstructionViews/WormholeInstructionView.tsx

@@ -24,6 +24,7 @@ import { ParsedAccountPubkeyRow, SignerTag, WritableTag } from './AccountUtils'
 import { usePythContext } from '../../contexts/PythContext'
 
 import { getMappingCluster, isPubkey } from './utils'
+import { PythCluster } from '@pythnetwork/client'
 
 const GovernanceInstructionView = ({
   instruction,
@@ -48,10 +49,11 @@ const GovernanceInstructionView = ({
 }
 export const WormholeInstructionView = ({
   instruction,
+  cluster,
 }: {
   instruction: WormholeMultisigInstruction
+  cluster: PythCluster
 }) => {
-  const { cluster } = useContext(ClusterContext)
   const {
     priceAccountKeyToSymbolMapping,
     productAccountKeyToSymbolMapping,

+ 79 - 6
governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals.tsx

@@ -51,6 +51,7 @@ import {
 } from '../InstructionViews/AccountUtils'
 
 import { getMappingCluster, isPubkey } from '../InstructionViews/utils'
+import { getPythProgramKeyForCluster, PythCluster } from '@pythnetwork/client'
 const ProposalRow = ({
   proposal,
   multisig,
@@ -94,15 +95,39 @@ const ProposalRow = ({
               proposal.publicKey.toBase58().slice(-6)}
           </span>{' '}
         </div>
-        <div>
-          <StatusTag proposalStatus={status} />
+        <div className="flex space-x-2">
+          {proposal.approved.length > 0 && status === 'active' && (
+            <div>
+              <StatusTag
+                proposalStatus="executed"
+                text={`Approved: ${proposal.approved.length}`}
+              />
+            </div>
+          )}
+          {proposal.rejected.length > 0 && status === 'active' && (
+            <div>
+              <StatusTag
+                proposalStatus="rejected"
+                text={`Rejected: ${proposal.rejected.length}`}
+              />
+            </div>
+          )}
+          <div>
+            <StatusTag proposalStatus={status} />
+          </div>
         </div>
       </div>
     </div>
   )
 }
 
-const StatusTag = ({ proposalStatus }: { proposalStatus: string }) => {
+const StatusTag = ({
+  proposalStatus,
+  text,
+}: {
+  proposalStatus: string
+  text?: string
+}) => {
   return (
     <div
       className={`flex items-center justify-center rounded-full ${
@@ -119,7 +144,7 @@ const StatusTag = ({ proposalStatus }: { proposalStatus: string }) => {
           : 'bg-pythPurple'
       } py-1 px-2 text-xs`}
     >
-      {proposalStatus}
+      {text || proposalStatus}
     </div>
   )
 }
@@ -230,7 +255,40 @@ const Proposal = ({
 }) => {
   const [instructions, setInstructions] = useState<MultisigInstruction[]>([])
   const [isTransactionLoading, setIsTransactionLoading] = useState(false)
-  const { cluster } = useContext(ClusterContext)
+  const { cluster: contextCluster } = useContext(ClusterContext)
+  const multisigCluster = getMultisigCluster(contextCluster)
+  const targetClusters: (PythCluster | 'unknown')[] = []
+  instructions.map((ix) => {
+    if (ix instanceof PythMultisigInstruction) {
+      targetClusters.push(multisigCluster)
+    } else if (
+      ix instanceof WormholeMultisigInstruction &&
+      ix.governanceAction instanceof ExecutePostedVaa
+    ) {
+      ix.governanceAction.instructions.map((ix) => {
+        const remoteClusters: PythCluster[] = [
+          'pythnet',
+          'pythtest-conformance',
+          'pythtest-crosschain',
+        ]
+        for (const remoteCluster of remoteClusters) {
+          if (
+            multisigCluster === getMultisigCluster(remoteCluster) &&
+            ix.programId.equals(getPythProgramKeyForCluster(remoteCluster))
+          ) {
+            targetClusters.push(remoteCluster)
+          }
+        }
+      })
+    } else {
+      targetClusters.push('unknown')
+    }
+  })
+  const uniqueTargetCluster = new Set(targetClusters).size === 1
+  const cluster =
+    uniqueTargetCluster && targetClusters[0] !== 'unknown'
+      ? targetClusters[0]
+      : contextCluster
 
   const {
     voteSquads,
@@ -243,6 +301,7 @@ const Proposal = ({
     productAccountKeyToSymbolMapping,
     publisherKeyToNameMapping,
   } = usePythContext()
+
   const publisherKeyToNameMappingCluster =
     publisherKeyToNameMapping[getMappingCluster(cluster)]
   const { publicKey: signerPublicKey } = useWallet()
@@ -367,6 +426,17 @@ const Proposal = ({
     multisig !== undefined &&
     !isMultisigLoading ? (
     <div className="grid grid-cols-3 gap-4">
+      <div className="col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4">
+        <h4 className="h4 font-semibold">
+          {uniqueTargetCluster
+            ? `Target Pyth Program: ${targetClusters[0]}`
+            : targetClusters.length == 0
+            ? 'No target Pyth program detected'
+            : `Multiple target Pyth programs detected ${targetClusters.join(
+                ' '
+              )}`}
+        </h4>
+      </div>
       <div className="col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4 lg:col-span-2">
         <div className="flex justify-between">
           <h4 className="h4 font-semibold">Info</h4>
@@ -689,7 +759,10 @@ const Proposal = ({
               </>
             ) : null}
             {instruction instanceof WormholeMultisigInstruction && (
-              <WormholeInstructionView instruction={instruction} />
+              <WormholeInstructionView
+                cluster={cluster}
+                instruction={instruction}
+              />
             )}
 
             {index !== instructions.length - 1 ? (

+ 2 - 0
governance/xc_admin/packages/xc_admin_frontend/contexts/PythContext.tsx

@@ -86,6 +86,8 @@ export const PythContextProvider: React.FC<PythContextProviderProps> = ({
       connection,
       publisherKeyToNameMapping,
       multisigSignerKeyToNameMapping,
+      priceAccountKeyToSymbolMapping,
+      productAccountKeyToSymbolMapping,
     ]
   )