Skip to content

Commit

Permalink
feat: allow proposing without connecting a wallet (#2262)
Browse files Browse the repository at this point in the history
* feat: allow proposing without connecting a wallet

* fix: remove unused imports

* fix: remove connected

* use useMemo

* cleanup multisig context

* remove undefined checks

* rename squads to walletsquads
  • Loading branch information
guibescos authored Jan 17, 2025
1 parent 792520d commit add1428
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { Program } from '@coral-xyz/anchor'
import { Dialog, Menu, Transition } from '@headlessui/react'
import { PythOracle } from '@pythnetwork/client/lib/anchor'
import * as Label from '@radix-ui/react-label'
import { useWallet } from '@solana/wallet-adapter-react'
import { WalletModalButton } from '@solana/wallet-adapter-react-ui'
import { PublicKey, TransactionInstruction } from '@solana/web3.js'
import SquadsMesh from '@sqds/mesh'
import axios from 'axios'
Expand Down Expand Up @@ -39,12 +37,12 @@ const assetTypes = [
const PermissionDepermissionKey = ({
isPermission,
pythProgramClient,
squads,
readOnlySquads,
proposerServerUrl,
}: {
isPermission: boolean
pythProgramClient?: Program<PythOracle>
squads?: SquadsMesh
readOnlySquads: SquadsMesh
proposerServerUrl: string
}) => {
const [publisherKey, setPublisherKey] = useState(
Expand All @@ -56,7 +54,6 @@ const PermissionDepermissionKey = ({
const [priceAccounts, setPriceAccounts] = useState<PublicKey[]>([])
const { cluster } = useContext(ClusterContext)
const { rawConfig, dataIsLoading, connection } = usePythContext()
const { connected } = useWallet()

// get current input value

Expand All @@ -77,9 +74,9 @@ const PermissionDepermissionKey = ({
}

const handleSubmitButton = async () => {
if (pythProgramClient && squads) {
if (pythProgramClient) {
const instructions: TransactionInstruction[] = []
const multisigAuthority = squads.getAuthorityPDA(
const multisigAuthority = readOnlySquads.getAuthorityPDA(
PRICE_FEED_MULTISIG[getMultisigCluster(cluster)],
1
)
Expand Down Expand Up @@ -265,22 +262,16 @@ const PermissionDepermissionKey = ({
/>
</div>
<div className="mt-6">
{!connected ? (
<div className="flex justify-center">
<WalletModalButton className="action-btn text-base" />
</div>
) : (
<button
className="action-btn text-base"
onClick={handleSubmitButton}
>
{isSubmitButtonLoading ? (
<Spinner />
) : (
'Submit Proposal'
)}
</button>
)}
<button
className="action-btn text-base"
onClick={handleSubmitButton}
>
{isSubmitButtonLoading ? (
<Spinner />
) : (
'Submit Proposal'
)}
</button>
</div>
</div>
</Dialog.Panel>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { AnchorProvider, Idl, Program } from '@coral-xyz/anchor'
import { AccountType, getPythProgramKeyForCluster } from '@pythnetwork/client'
import { PythOracle, pythOracleProgram } from '@pythnetwork/client/lib/anchor'
import { useWallet } from '@solana/wallet-adapter-react'
import { PublicKey, TransactionInstruction } from '@solana/web3.js'
import messageBuffer from 'message_buffer/idl/message_buffer.json'
import { MessageBuffer } from 'message_buffer/idl/message_buffer'
Expand Down Expand Up @@ -46,9 +45,8 @@ 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] =
useState<Program<PythOracle>>()

Expand Down Expand Up @@ -289,12 +287,12 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
}

const handleSendProposalButtonClick = async () => {
if (pythProgramClient && dataChanges && !isMultisigLoading && squads) {
if (pythProgramClient && dataChanges && !isMultisigLoading) {
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
)
Expand Down Expand Up @@ -845,23 +843,21 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
<button
className="action-btn text-base"
onClick={handleSendProposalButtonClick}
disabled={isSendProposalButtonLoading || !squads}
disabled={isSendProposalButtonLoading}
>
{isSendProposalButtonLoading ? <Spinner /> : 'Send Proposal'}
</button>
{!squads && <div>Please connect your wallet</div>}
</>
)}
</>
)
}

// create anchor wallet when connected
useEffect(() => {
if (connected && squads && connection) {
if (connection) {
const provider = new AnchorProvider(
connection,
squads.wallet as Wallet,
readOnlySquads.wallet as Wallet,
AnchorProvider.defaultOptions()
)
setPythProgramClient(
Expand All @@ -878,7 +874,7 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
)
}
}
}, [connection, connected, cluster, squads])
}, [connection, cluster, readOnlySquads])

return (
<div className="relative">
Expand All @@ -903,13 +899,13 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
<PermissionDepermissionKey
isPermission={true}
pythProgramClient={pythProgramClient}
squads={squads}
readOnlySquads={readOnlySquads}
proposerServerUrl={proposerServerUrl}
/>
<PermissionDepermissionKey
isPermission={false}
pythProgramClient={pythProgramClient}
squads={squads}
readOnlySquads={readOnlySquads}
proposerServerUrl={proposerServerUrl}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import NodeWallet from '@coral-xyz/anchor/dist/cjs/nodewallet'
import { useWallet } from '@solana/wallet-adapter-react'
import {
AccountMeta,
Keypair,
PublicKey,
SystemProgram,
TransactionInstruction,
Expand Down Expand Up @@ -181,10 +179,10 @@ export const Proposal = ({
: contextCluster

const {
squads,
walletSquads: squads,
isLoading: isMultisigLoading,
connection,
refreshData,
readOnlySquads,
} = useMultisigContext()
const {
priceAccountKeyToSymbolMapping,
Expand Down Expand Up @@ -240,11 +238,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) {
const proposalInstructions = (
await getManyProposalsInstructions(readOnlySquads, [proposal])
)[0]
Expand All @@ -267,7 +261,7 @@ export const Proposal = ({
return () => {
isCancelled = true
}
}, [cluster, proposal, squads, connection])
}, [cluster, proposal, readOnlySquads])

const handleClick = async (
instructionGenerator: (
Expand Down
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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,
Expand All @@ -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()
Expand All @@ -51,7 +52,7 @@ export const ProposalRow = ({
const element = elementRef.current
const observer = new IntersectionObserver(async (entries) => {
if (entries[0].isIntersecting) {
if (isMultisigLoading || !connection) {
if (isMultisigLoading) {
return
}

Expand All @@ -75,10 +76,6 @@ export const ProposalRow = ({

// calculate instructions summary
if (!instructions) {
const readOnlySquads = new SquadsMesh({
connection,
wallet: new NodeWallet(new Keypair()),
})
const proposalInstructions = (
await getManyProposalsInstructions(readOnlySquads, [proposal])
)[0]
Expand Down Expand Up @@ -130,7 +127,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) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ const UpdatePermissions = () => {
const [isSendProposalButtonLoading, setIsSendProposalButtonLoading] =
useState(false)
const { cluster } = useContext(ClusterContext)
const { isLoading: isMultisigLoading, squads } = useMultisigContext()
const { isLoading: isMultisigLoading, walletSquads } = useMultisigContext()
const { rawConfig, dataIsLoading, connection } = usePythContext()
const { connected } = useWallet()
const [pythProgramClient, setPythProgramClient] =
Expand Down Expand Up @@ -239,12 +239,12 @@ const UpdatePermissions = () => {
}

const handleSendProposalButtonClick = () => {
if (pythProgramClient && finalPubkeyChanges && squads) {
if (pythProgramClient && finalPubkeyChanges && walletSquads) {
const programDataAccount = PublicKey.findProgramAddressSync(
[pythProgramClient?.programId.toBuffer()],
BPF_UPGRADABLE_LOADER
)[0]
const multisigAuthority = squads.getAuthorityPDA(
const multisigAuthority = walletSquads.getAuthorityPDA(
UPGRADE_MULTISIG[getMultisigCluster(cluster)],
1
)
Expand All @@ -267,9 +267,9 @@ const UpdatePermissions = () => {
setIsSendProposalButtonLoading(true)
try {
const vault = new MultisigVault(
squads.wallet as Wallet,
walletSquads.wallet as Wallet,
getMultisigCluster(cluster),
squads,
walletSquads,
UPGRADE_MULTISIG[getMultisigCluster(cluster)]
)

Expand Down Expand Up @@ -335,17 +335,17 @@ const UpdatePermissions = () => {

// create anchor wallet when connected
useEffect(() => {
if (connected && squads && connection) {
if (connected && walletSquads && connection) {
const provider = new AnchorProvider(
connection,
squads.wallet as Wallet,
walletSquads.wallet as Wallet,
AnchorProvider.defaultOptions()
)
setPythProgramClient(
pythOracleProgram(getPythProgramKeyForCluster(cluster), provider)
)
}
}, [connection, connected, cluster, squads])
}, [connection, connected, cluster, walletSquads])

return (
<div className="relative">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import React, { createContext, useContext, useMemo } from 'react'
import { MultisigHookData, useMultisig } from '../hooks/useMultisig'

const MultisigContext = createContext<MultisigHookData>({
upgradeMultisigAccount: undefined,
priceFeedMultisigAccount: undefined,
upgradeMultisigProposals: [],
priceFeedMultisigProposals: [],
isLoading: true,
squads: undefined,
refreshData: undefined,
connection: undefined,
})
const MultisigContext = createContext<MultisigHookData | undefined>(undefined)

export const useMultisigContext = () => useContext(MultisigContext)
export const useMultisigContext = () => {
const context = useContext(MultisigContext)
if (!context) {
throw new Error(
'useMultisigContext must be used within a MultisigContext.Provider'
)
}
return context
}

interface MultisigContextProviderProps {
children?: React.ReactNode
Expand All @@ -23,13 +22,14 @@ export const MultisigContextProvider: React.FC<
> = ({ children }) => {
const {
isLoading,
squads,
walletSquads,
upgradeMultisigAccount,
priceFeedMultisigAccount,
upgradeMultisigProposals,
priceFeedMultisigProposals,
refreshData,
connection,
readOnlySquads,
} = useMultisig()

const value = useMemo(
Expand All @@ -39,19 +39,21 @@ export const MultisigContextProvider: React.FC<
upgradeMultisigProposals,
priceFeedMultisigProposals,
isLoading,
squads,
walletSquads,
refreshData,
connection,
readOnlySquads,
}),
[
squads,
walletSquads,
isLoading,
upgradeMultisigAccount,
priceFeedMultisigAccount,
upgradeMultisigProposals,
priceFeedMultisigProposals,
refreshData,
connection,
readOnlySquads,
]
)

Expand Down
Loading

0 comments on commit add1428

Please sign in to comment.