From 00d72b3827981eb996876784aad2e6121f816908 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Date: Wed, 15 Jan 2025 18:11:06 +0000 Subject: [PATCH] feat: allow proposing without connecting a wallet --- .../components/PermissionDepermissionKey.tsx | 27 +++++++------------ .../components/tabs/General.tsx | 24 ++++++++++------- .../components/tabs/Proposals/Proposal.tsx | 10 +++---- .../components/tabs/Proposals/ProposalRow.tsx | 26 +++++++++++------- .../contexts/MultisigContext.tsx | 4 +++ .../xc_admin_frontend/hooks/useMultisig.ts | 27 ++++++++++++++----- 6 files changed, 67 insertions(+), 51 deletions(-) diff --git a/governance/xc_admin/packages/xc_admin_frontend/components/PermissionDepermissionKey.tsx b/governance/xc_admin/packages/xc_admin_frontend/components/PermissionDepermissionKey.tsx index ac1f7c9ac5..23c799437f 100644 --- a/governance/xc_admin/packages/xc_admin_frontend/components/PermissionDepermissionKey.tsx +++ b/governance/xc_admin/packages/xc_admin_frontend/components/PermissionDepermissionKey.tsx @@ -56,7 +56,6 @@ const PermissionDepermissionKey = ({ const [priceAccounts, setPriceAccounts] = useState([]) const { cluster } = useContext(ClusterContext) const { rawConfig, dataIsLoading, connection } = usePythContext() - const { connected } = useWallet() // get current input value @@ -265,22 +264,16 @@ const PermissionDepermissionKey = ({ />
- {!connected ? ( -
- -
- ) : ( - - )} +
diff --git a/governance/xc_admin/packages/xc_admin_frontend/components/tabs/General.tsx b/governance/xc_admin/packages/xc_admin_frontend/components/tabs/General.tsx index 7451fcae04..a8cbb01a09 100644 --- a/governance/xc_admin/packages/xc_admin_frontend/components/tabs/General.tsx +++ b/governance/xc_admin/packages/xc_admin_frontend/components/tabs/General.tsx @@ -46,7 +46,7 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => { useState(false) const { cluster } = useContext(ClusterContext) const isRemote: boolean = isRemoteCluster(cluster) // Move to multisig context - const { isLoading: isMultisigLoading, squads } = useMultisigContext() + const { isLoading: isMultisigLoading, readOnlySquads } = useMultisigContext() const { rawConfig, dataIsLoading, connection } = usePythContext() const { connected } = useWallet() const [pythProgramClient, setPythProgramClient] = @@ -289,12 +289,17 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => { } const handleSendProposalButtonClick = async () => { - if (pythProgramClient && dataChanges && !isMultisigLoading && squads) { + if ( + pythProgramClient && + dataChanges && + !isMultisigLoading && + readOnlySquads + ) { const instructions: TransactionInstruction[] = [] const publisherInPriceStoreInitializationsVerified: PublicKey[] = [] for (const symbol of Object.keys(dataChanges)) { - const multisigAuthority = squads.getAuthorityPDA( + const multisigAuthority = readOnlySquads.getAuthorityPDA( PRICE_FEED_MULTISIG[getMultisigCluster(cluster)], 1 ) @@ -845,11 +850,10 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => { - {!squads &&
Please connect your wallet
} )} @@ -858,10 +862,10 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => { // create anchor wallet when connected useEffect(() => { - if (connected && squads && connection) { + if (connected && readOnlySquads && connection) { const provider = new AnchorProvider( connection, - squads.wallet as Wallet, + readOnlySquads.wallet as Wallet, AnchorProvider.defaultOptions() ) setPythProgramClient( @@ -878,7 +882,7 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => { ) } } - }, [connection, connected, cluster, squads]) + }, [connection, connected, cluster, readOnlySquads]) return (
@@ -903,13 +907,13 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
diff --git a/governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals/Proposal.tsx b/governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals/Proposal.tsx index dde775549c..871a035128 100644 --- a/governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals/Proposal.tsx +++ b/governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals/Proposal.tsx @@ -183,8 +183,8 @@ export const Proposal = ({ const { squads, isLoading: isMultisigLoading, - connection, refreshData, + readOnlySquads, } = useMultisigContext() const { priceAccountKeyToSymbolMapping, @@ -240,11 +240,7 @@ export const Proposal = ({ useEffect(() => { let isCancelled = false const fetchInstructions = async () => { - if (proposal && connection) { - const readOnlySquads = new SquadsMesh({ - connection, - wallet: new NodeWallet(new Keypair()), - }) + if (proposal && readOnlySquads) { const proposalInstructions = ( await getManyProposalsInstructions(readOnlySquads, [proposal]) )[0] @@ -267,7 +263,7 @@ export const Proposal = ({ return () => { isCancelled = true } - }, [cluster, proposal, squads, connection]) + }, [cluster, proposal, readOnlySquads]) const handleClick = async ( instructionGenerator: ( diff --git a/governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals/ProposalRow.tsx b/governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals/ProposalRow.tsx index e38f25083f..e56a369529 100644 --- a/governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals/ProposalRow.tsx +++ b/governance/xc_admin/packages/xc_admin_frontend/components/tabs/Proposals/ProposalRow.tsx @@ -1,4 +1,3 @@ -import SquadsMesh from '@sqds/mesh' import { MultisigAccount, TransactionAccount } from '@sqds/mesh/lib/types' import { useRouter } from 'next/router' import { useCallback, useContext, useEffect, useRef, useState } from 'react' @@ -7,10 +6,8 @@ import { ClusterContext } from '../../../contexts/ClusterContext' import { useMultisigContext } from '../../../contexts/MultisigContext' import { StatusTag } from './StatusTag' import { getInstructionsSummary, getProposalStatus } from './utils' - -import NodeWallet from '@coral-xyz/anchor/dist/cjs/nodewallet' import { useWallet } from '@solana/wallet-adapter-react' -import { AccountMeta, Keypair } from '@solana/web3.js' +import { AccountMeta } from '@solana/web3.js' import { MultisigParser, getManyProposalsInstructions, @@ -28,7 +25,11 @@ export const ProposalRow = ({ useState<(readonly [string, number])[]>() const status = getProposalStatus(proposal, multisig) const { cluster } = useContext(ClusterContext) - const { isLoading: isMultisigLoading, connection } = useMultisigContext() + const { + isLoading: isMultisigLoading, + connection, + readOnlySquads, + } = useMultisigContext() const router = useRouter() const elementRef = useRef(null) const { publicKey: walletPublicKey } = useWallet() @@ -73,12 +74,9 @@ export const ProposalRow = ({ }) } + if (!readOnlySquads) return // calculate instructions summary if (!instructions) { - const readOnlySquads = new SquadsMesh({ - connection, - wallet: new NodeWallet(new Keypair()), - }) const proposalInstructions = ( await getManyProposalsInstructions(readOnlySquads, [proposal]) )[0] @@ -130,7 +128,15 @@ export const ProposalRow = ({ observer.unobserve(element) } } - }, [time, cluster, proposal, connection, isMultisigLoading, instructions]) + }, [ + time, + cluster, + proposal, + connection, + readOnlySquads, + isMultisigLoading, + instructions, + ]) const handleClickIndividualProposal = useCallback( (proposalPubkey: string) => { diff --git a/governance/xc_admin/packages/xc_admin_frontend/contexts/MultisigContext.tsx b/governance/xc_admin/packages/xc_admin_frontend/contexts/MultisigContext.tsx index e9647bad43..5268aca9e4 100644 --- a/governance/xc_admin/packages/xc_admin_frontend/contexts/MultisigContext.tsx +++ b/governance/xc_admin/packages/xc_admin_frontend/contexts/MultisigContext.tsx @@ -8,6 +8,7 @@ const MultisigContext = createContext({ priceFeedMultisigProposals: [], isLoading: true, squads: undefined, + readOnlySquads: undefined, refreshData: undefined, connection: undefined, }) @@ -30,6 +31,7 @@ export const MultisigContextProvider: React.FC< priceFeedMultisigProposals, refreshData, connection, + readOnlySquads, } = useMultisig() const value = useMemo( @@ -42,6 +44,7 @@ export const MultisigContextProvider: React.FC< squads, refreshData, connection, + readOnlySquads, }), [ squads, @@ -52,6 +55,7 @@ export const MultisigContextProvider: React.FC< priceFeedMultisigProposals, refreshData, connection, + readOnlySquads, ] ) diff --git a/governance/xc_admin/packages/xc_admin_frontend/hooks/useMultisig.ts b/governance/xc_admin/packages/xc_admin_frontend/hooks/useMultisig.ts index ed5a583a7f..7104187df3 100644 --- a/governance/xc_admin/packages/xc_admin_frontend/hooks/useMultisig.ts +++ b/governance/xc_admin/packages/xc_admin_frontend/hooks/useMultisig.ts @@ -16,6 +16,7 @@ import { deriveWsUrl, pythClusterApiUrls } from '../utils/pythClusterApiUrl' export interface MultisigHookData { isLoading: boolean squads: SquadsMesh | undefined + readOnlySquads: SquadsMesh | undefined upgradeMultisigAccount: MultisigAccount | undefined priceFeedMultisigAccount: MultisigAccount | undefined upgradeMultisigProposals: TransactionAccount[] @@ -47,6 +48,7 @@ export const useMultisig = (): MultisigHookData => { TransactionAccount[] >([]) const [squads, setSquads] = useState() + const [readOnlySquads, setReadOnlySquads] = useState() const [urlsIndex, setUrlsIndex] = useState(0) @@ -73,9 +75,23 @@ export const useMultisig = (): MultisigHookData => { }) ) } else { - setSquads(undefined) + setSquads( + new SquadsMesh({ + connection, + wallet: new NodeWallet(new Keypair()), + }) + ) } - }, [wallet, urlsIndex, cluster, connection]) + }, [wallet, connection]) + + useEffect(() => { + setReadOnlySquads( + new SquadsMesh({ + connection, + wallet: new NodeWallet(new Keypair()), + }) + ) + }, [connection]) const refreshData = useCallback(() => { let cancelled = false @@ -83,11 +99,7 @@ export const useMultisig = (): MultisigHookData => { const fetchData = async () => { setIsLoading(true) try { - // mock wallet to allow users to view proposals without connecting their wallet - const readOnlySquads = new SquadsMesh({ - connection, - wallet: new NodeWallet(new Keypair()), - }) + if (!readOnlySquads) return if (cancelled) return const upgradeMultisigAccount = await readOnlySquads.getMultisig( UPGRADE_MULTISIG[multisigCluster] @@ -147,6 +159,7 @@ export const useMultisig = (): MultisigHookData => { return { isLoading, squads, + readOnlySquads, upgradeMultisigAccount, priceFeedMultisigAccount, upgradeMultisigProposals,