Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow proposing without connecting a wallet #2262

Merged
merged 7 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading