Skip to content

Commit 60b1a36

Browse files
authored
[xc-admin] enable publisher key and multisig signer key mapping when available (#663)
* enable publisher key and multisig signer key mapping when available * fix permission/depermission button border radius * address comments and add mapping filepath * fix precommit error
1 parent 55a8f85 commit 60b1a36

File tree

5 files changed

+178
-67
lines changed

5 files changed

+178
-67
lines changed

governance/xc_admin/packages/xc_admin_frontend/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,8 @@ yarn-error.log*
3434
# typescript
3535
*.tsbuildinfo
3636
next-env.d.ts
37+
38+
39+
# mappings
40+
publishers.json
41+
signers.json

governance/xc_admin/packages/xc_admin_frontend/components/PermissionDepermissionKey.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ const PermissionDepermissionKey = ({
144144
{({ open }) => (
145145
<>
146146
<Menu.Button
147-
className={`inline-flex w-full items-center justify-between rounded-lg bg-darkGray2 py-3 px-6 text-sm outline-0`}
147+
className={`inline-flex w-full items-center justify-between bg-darkGray2 py-3 px-6 text-sm outline-0`}
148148
>
149149
<span className="mr-3">
150150
{isPermission ? 'Permission Key' : 'Depermission Key'}

governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals.tsx

Lines changed: 133 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,16 @@ const ParsedAccountPubkeyRow = ({
173173
}
174174

175175
const Proposal = ({
176+
publisherKeyToNameMapping,
177+
multisigSignerKeyToNameMapping,
176178
proposal,
177179
proposalIndex,
178180
instructions,
179181
verified,
180182
multisig,
181183
}: {
184+
publisherKeyToNameMapping: Record<string, string>
185+
multisigSignerKeyToNameMapping: Record<string, string>
182186
proposal: TransactionAccount | undefined
183187
proposalIndex: number
184188
instructions: MultisigInstruction[]
@@ -425,10 +429,20 @@ const Proposal = ({
425429
</h4>
426430
<hr className="border-gray-700" />
427431
{currentProposal.approved.map((pubkey, idx) => (
428-
<div className="flex justify-between" key={pubkey.toBase58()}>
429-
<div>Key {idx + 1}</div>
430-
<CopyPubkey pubkey={pubkey.toBase58()} />
431-
</div>
432+
<>
433+
<div className="flex justify-between" key={pubkey.toBase58()}>
434+
<div>Key {idx + 1}</div>
435+
<CopyPubkey pubkey={pubkey.toBase58()} />
436+
</div>
437+
{pubkey.toBase58() in multisigSignerKeyToNameMapping ? (
438+
<ParsedAccountPubkeyRow
439+
key={`${idx}_${pubkey.toBase58()}_confirmed`}
440+
mapping={multisigSignerKeyToNameMapping}
441+
title="owner"
442+
pubkey={pubkey.toBase58()}
443+
/>
444+
) : null}
445+
</>
432446
))}
433447
</div>
434448
) : null}
@@ -439,10 +453,20 @@ const Proposal = ({
439453
</h4>
440454
<hr className="border-gray-700" />
441455
{currentProposal.rejected.map((pubkey, idx) => (
442-
<div className="flex justify-between" key={pubkey.toBase58()}>
443-
<div>Key {idx + 1}</div>
444-
<CopyPubkey pubkey={pubkey.toBase58()} />
445-
</div>
456+
<>
457+
<div className="flex justify-between" key={pubkey.toBase58()}>
458+
<div>Key {idx + 1}</div>
459+
<CopyPubkey pubkey={pubkey.toBase58()} />
460+
</div>
461+
{pubkey.toBase58() in multisigSignerKeyToNameMapping ? (
462+
<ParsedAccountPubkeyRow
463+
key={`${idx}_${pubkey.toBase58()}_rejected`}
464+
mapping={multisigSignerKeyToNameMapping}
465+
title="owner"
466+
pubkey={pubkey.toBase58()}
467+
/>
468+
) : null}
469+
</>
446470
))}
447471
</div>
448472
) : null}
@@ -525,28 +549,42 @@ const Proposal = ({
525549
<div>Value</div>
526550
</div>
527551
{Object.keys(instruction.args).map((key, index) => (
528-
<div
529-
key={index}
530-
className="flex justify-between border-t border-beige-300 py-3"
531-
>
532-
<div>{key}</div>
533-
{instruction.args[key] instanceof PublicKey ? (
534-
<CopyPubkey
552+
<>
553+
<div
554+
key={index}
555+
className="flex justify-between border-t border-beige-300 py-3"
556+
>
557+
<div>{key}</div>
558+
{instruction.args[key] instanceof PublicKey ? (
559+
<CopyPubkey
560+
pubkey={instruction.args[key].toBase58()}
561+
/>
562+
) : typeof instruction.args[key] === 'string' &&
563+
isPubkey(instruction.args[key]) ? (
564+
<CopyPubkey pubkey={instruction.args[key]} />
565+
) : (
566+
<div className="max-w-sm break-all">
567+
{typeof instruction.args[key] === 'string'
568+
? instruction.args[key]
569+
: instruction.args[key] instanceof Uint8Array
570+
? instruction.args[key].toString('hex')
571+
: JSON.stringify(instruction.args[key])}
572+
</div>
573+
)}
574+
</div>
575+
{key === 'pub' &&
576+
instruction.args[key].toBase58() in
577+
publisherKeyToNameMapping ? (
578+
<ParsedAccountPubkeyRow
579+
key={`${index}_${instruction.args[
580+
key
581+
].toBase58()}`}
582+
mapping={publisherKeyToNameMapping}
583+
title="publisher"
535584
pubkey={instruction.args[key].toBase58()}
536585
/>
537-
) : typeof instruction.args[key] === 'string' &&
538-
isPubkey(instruction.args[key]) ? (
539-
<CopyPubkey pubkey={instruction.args[key]} />
540-
) : (
541-
<div className="max-w-sm break-all">
542-
{typeof instruction.args[key] === 'string'
543-
? instruction.args[key]
544-
: instruction.args[key] instanceof Uint8Array
545-
? instruction.args[key].toString('hex')
546-
: JSON.stringify(instruction.args[key])}
547-
</div>
548-
)}
549-
</div>
586+
) : null}
587+
</>
550588
))}
551589
</div>
552590
) : (
@@ -739,45 +777,69 @@ const Proposal = ({
739777
</div>
740778
{Object.keys(parsedInstruction.args).map(
741779
(key, index) => (
742-
<div
743-
key={index}
744-
className="flex justify-between border-t border-beige-300 py-3"
745-
>
746-
<div>{key}</div>
747-
{parsedInstruction.args[
780+
<>
781+
<div
782+
key={index}
783+
className="flex justify-between border-t border-beige-300 py-3"
784+
>
785+
<div>{key}</div>
786+
{parsedInstruction.args[
787+
key
788+
] instanceof PublicKey ? (
789+
<CopyPubkey
790+
pubkey={parsedInstruction.args[
791+
key
792+
].toBase58()}
793+
/>
794+
) : typeof instruction.args[key] ===
795+
'string' &&
796+
isPubkey(
797+
instruction.args[key]
798+
) ? (
799+
<CopyPubkey
800+
pubkey={
801+
parsedInstruction.args[key]
802+
}
803+
/>
804+
) : (
805+
<div className="max-w-sm break-all">
806+
{typeof parsedInstruction.args[
807+
key
808+
] === 'string'
809+
? parsedInstruction.args[key]
810+
: parsedInstruction.args[
811+
key
812+
] instanceof Uint8Array
813+
? parsedInstruction.args[
814+
key
815+
].toString('hex')
816+
: JSON.stringify(
817+
parsedInstruction.args[
818+
key
819+
]
820+
)}
821+
</div>
822+
)}
823+
</div>
824+
{key === 'pub' &&
825+
parsedInstruction.args[
748826
key
749-
] instanceof PublicKey ? (
750-
<CopyPubkey
827+
].toBase58() in
828+
publisherKeyToNameMapping ? (
829+
<ParsedAccountPubkeyRow
830+
key={`${index}_${parsedInstruction.args[
831+
key
832+
].toBase58()}`}
833+
mapping={
834+
publisherKeyToNameMapping
835+
}
836+
title="publisher"
751837
pubkey={parsedInstruction.args[
752838
key
753839
].toBase58()}
754840
/>
755-
) : typeof instruction.args[key] ===
756-
'string' &&
757-
isPubkey(instruction.args[key]) ? (
758-
<CopyPubkey
759-
pubkey={
760-
parsedInstruction.args[key]
761-
}
762-
/>
763-
) : (
764-
<div className="max-w-sm break-all">
765-
{typeof parsedInstruction.args[
766-
key
767-
] === 'string'
768-
? parsedInstruction.args[key]
769-
: parsedInstruction.args[
770-
key
771-
] instanceof Uint8Array
772-
? parsedInstruction.args[
773-
key
774-
].toString('hex')
775-
: JSON.stringify(
776-
parsedInstruction.args[key]
777-
)}
778-
</div>
779-
)}
780-
</div>
841+
) : null}
842+
</>
781843
)
782844
)}
783845
</div>
@@ -962,7 +1024,13 @@ const Proposal = ({
9621024
)
9631025
}
9641026

965-
const Proposals = () => {
1027+
const Proposals = ({
1028+
publisherKeyToNameMapping,
1029+
multisigSignerKeyToNameMapping,
1030+
}: {
1031+
publisherKeyToNameMapping: Record<string, string>
1032+
multisigSignerKeyToNameMapping: Record<string, string>
1033+
}) => {
9661034
const router = useRouter()
9671035
const [currentProposal, setCurrentProposal] = useState<TransactionAccount>()
9681036
const [currentProposalIndex, setCurrentProposalIndex] = useState<number>()
@@ -1112,6 +1180,8 @@ const Proposals = () => {
11121180
</div>
11131181
<div className="relative mt-6">
11141182
<Proposal
1183+
publisherKeyToNameMapping={publisherKeyToNameMapping}
1184+
multisigSignerKeyToNameMapping={multisigSignerKeyToNameMapping}
11151185
proposal={currentProposal}
11161186
proposalIndex={currentProposalIndex}
11171187
instructions={allProposalsIxsParsed[currentProposalIndex]}

governance/xc_admin/packages/xc_admin_frontend/next.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const nextConfig = {
55
externalDir: true,
66
},
77
webpack(config) {
8+
config.resolve.fallback = { fs: false }
89
const fileLoaderRule = config.module.rules.find(
910
(rule) => rule.test && rule.test.test('.svg')
1011
)

governance/xc_admin/packages/xc_admin_frontend/pages/index.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Tab } from '@headlessui/react'
2-
import type { NextPage } from 'next'
2+
import * as fs from 'fs'
3+
import type { GetStaticProps, NextPage } from 'next'
34
import { useRouter } from 'next/router'
45
import { useEffect, useState } from 'react'
56
import Layout from '../components/layout/Layout'
@@ -10,6 +11,34 @@ import { MultisigContextProvider } from '../contexts/MultisigContext'
1011
import { PythContextProvider } from '../contexts/PythContext'
1112
import { classNames } from '../utils/classNames'
1213

14+
export const getStaticProps: GetStaticProps = async () => {
15+
const publisherMappingFilePath = `${
16+
process.env.MAPPING_BASE_PATH || ''
17+
}publishers.json`
18+
const publisherKeyToNameMapping = fs.existsSync(publisherMappingFilePath)
19+
? JSON.parse(
20+
(await fs.promises.readFile(publisherMappingFilePath)).toString()
21+
)
22+
: {}
23+
const multisigSignerMappingFilePath = `${
24+
process.env.MAPPING_BASE_PATH || ''
25+
}signers.json`
26+
const multisigSignerKeyToNameMapping = fs.existsSync(
27+
multisigSignerMappingFilePath
28+
)
29+
? JSON.parse(
30+
(await fs.promises.readFile(multisigSignerMappingFilePath)).toString()
31+
)
32+
: {}
33+
34+
return {
35+
props: {
36+
publisherKeyToNameMapping,
37+
multisigSignerKeyToNameMapping,
38+
},
39+
}
40+
}
41+
1342
const TAB_INFO = {
1443
General: {
1544
title: 'General',
@@ -30,7 +59,10 @@ const TAB_INFO = {
3059

3160
const DEFAULT_TAB = 'general'
3261

33-
const Home: NextPage = () => {
62+
const Home: NextPage<{
63+
publisherKeyToNameMapping: Record<string, string>
64+
multisigSignerKeyToNameMapping: Record<string, string>
65+
}> = ({ publisherKeyToNameMapping, multisigSignerKeyToNameMapping }) => {
3466
const [currentTabIndex, setCurrentTabIndex] = useState(0)
3567
const tabInfoArray = Object.values(TAB_INFO)
3668

@@ -100,7 +132,10 @@ const Home: NextPage = () => {
100132
<UpdatePermissions />
101133
) : tabInfoArray[currentTabIndex].queryString ===
102134
TAB_INFO.Proposals.queryString ? (
103-
<Proposals />
135+
<Proposals
136+
publisherKeyToNameMapping={publisherKeyToNameMapping}
137+
multisigSignerKeyToNameMapping={multisigSignerKeyToNameMapping}
138+
/>
104139
) : null}
105140
</MultisigContextProvider>
106141
</PythContextProvider>

0 commit comments

Comments
 (0)