Skip to content

Commit 00d72b3

Browse files
committed
feat: allow proposing without connecting a wallet
1 parent 8bf0ad2 commit 00d72b3

File tree

6 files changed

+67
-51
lines changed

6 files changed

+67
-51
lines changed

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

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ const PermissionDepermissionKey = ({
5656
const [priceAccounts, setPriceAccounts] = useState<PublicKey[]>([])
5757
const { cluster } = useContext(ClusterContext)
5858
const { rawConfig, dataIsLoading, connection } = usePythContext()
59-
const { connected } = useWallet()
6059

6160
// get current input value
6261

@@ -265,22 +264,16 @@ const PermissionDepermissionKey = ({
265264
/>
266265
</div>
267266
<div className="mt-6">
268-
{!connected ? (
269-
<div className="flex justify-center">
270-
<WalletModalButton className="action-btn text-base" />
271-
</div>
272-
) : (
273-
<button
274-
className="action-btn text-base"
275-
onClick={handleSubmitButton}
276-
>
277-
{isSubmitButtonLoading ? (
278-
<Spinner />
279-
) : (
280-
'Submit Proposal'
281-
)}
282-
</button>
283-
)}
267+
<button
268+
className="action-btn text-base"
269+
onClick={handleSubmitButton}
270+
>
271+
{isSubmitButtonLoading ? (
272+
<Spinner />
273+
) : (
274+
'Submit Proposal'
275+
)}
276+
</button>
284277
</div>
285278
</div>
286279
</Dialog.Panel>

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
4646
useState(false)
4747
const { cluster } = useContext(ClusterContext)
4848
const isRemote: boolean = isRemoteCluster(cluster) // Move to multisig context
49-
const { isLoading: isMultisigLoading, squads } = useMultisigContext()
49+
const { isLoading: isMultisigLoading, readOnlySquads } = useMultisigContext()
5050
const { rawConfig, dataIsLoading, connection } = usePythContext()
5151
const { connected } = useWallet()
5252
const [pythProgramClient, setPythProgramClient] =
@@ -289,12 +289,17 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
289289
}
290290

291291
const handleSendProposalButtonClick = async () => {
292-
if (pythProgramClient && dataChanges && !isMultisigLoading && squads) {
292+
if (
293+
pythProgramClient &&
294+
dataChanges &&
295+
!isMultisigLoading &&
296+
readOnlySquads
297+
) {
293298
const instructions: TransactionInstruction[] = []
294299
const publisherInPriceStoreInitializationsVerified: PublicKey[] = []
295300

296301
for (const symbol of Object.keys(dataChanges)) {
297-
const multisigAuthority = squads.getAuthorityPDA(
302+
const multisigAuthority = readOnlySquads.getAuthorityPDA(
298303
PRICE_FEED_MULTISIG[getMultisigCluster(cluster)],
299304
1
300305
)
@@ -845,11 +850,10 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
845850
<button
846851
className="action-btn text-base"
847852
onClick={handleSendProposalButtonClick}
848-
disabled={isSendProposalButtonLoading || !squads}
853+
disabled={isSendProposalButtonLoading}
849854
>
850855
{isSendProposalButtonLoading ? <Spinner /> : 'Send Proposal'}
851856
</button>
852-
{!squads && <div>Please connect your wallet</div>}
853857
</>
854858
)}
855859
</>
@@ -858,10 +862,10 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
858862

859863
// create anchor wallet when connected
860864
useEffect(() => {
861-
if (connected && squads && connection) {
865+
if (connected && readOnlySquads && connection) {
862866
const provider = new AnchorProvider(
863867
connection,
864-
squads.wallet as Wallet,
868+
readOnlySquads.wallet as Wallet,
865869
AnchorProvider.defaultOptions()
866870
)
867871
setPythProgramClient(
@@ -878,7 +882,7 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
878882
)
879883
}
880884
}
881-
}, [connection, connected, cluster, squads])
885+
}, [connection, connected, cluster, readOnlySquads])
882886

883887
return (
884888
<div className="relative">
@@ -903,13 +907,13 @@ const General = ({ proposerServerUrl }: { proposerServerUrl: string }) => {
903907
<PermissionDepermissionKey
904908
isPermission={true}
905909
pythProgramClient={pythProgramClient}
906-
squads={squads}
910+
squads={readOnlySquads}
907911
proposerServerUrl={proposerServerUrl}
908912
/>
909913
<PermissionDepermissionKey
910914
isPermission={false}
911915
pythProgramClient={pythProgramClient}
912-
squads={squads}
916+
squads={readOnlySquads}
913917
proposerServerUrl={proposerServerUrl}
914918
/>
915919
</div>

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ export const Proposal = ({
183183
const {
184184
squads,
185185
isLoading: isMultisigLoading,
186-
connection,
187186
refreshData,
187+
readOnlySquads,
188188
} = useMultisigContext()
189189
const {
190190
priceAccountKeyToSymbolMapping,
@@ -240,11 +240,7 @@ export const Proposal = ({
240240
useEffect(() => {
241241
let isCancelled = false
242242
const fetchInstructions = async () => {
243-
if (proposal && connection) {
244-
const readOnlySquads = new SquadsMesh({
245-
connection,
246-
wallet: new NodeWallet(new Keypair()),
247-
})
243+
if (proposal && readOnlySquads) {
248244
const proposalInstructions = (
249245
await getManyProposalsInstructions(readOnlySquads, [proposal])
250246
)[0]
@@ -267,7 +263,7 @@ export const Proposal = ({
267263
return () => {
268264
isCancelled = true
269265
}
270-
}, [cluster, proposal, squads, connection])
266+
}, [cluster, proposal, readOnlySquads])
271267

272268
const handleClick = async (
273269
instructionGenerator: (

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

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import SquadsMesh from '@sqds/mesh'
21
import { MultisigAccount, TransactionAccount } from '@sqds/mesh/lib/types'
32
import { useRouter } from 'next/router'
43
import { useCallback, useContext, useEffect, useRef, useState } from 'react'
@@ -7,10 +6,8 @@ import { ClusterContext } from '../../../contexts/ClusterContext'
76
import { useMultisigContext } from '../../../contexts/MultisigContext'
87
import { StatusTag } from './StatusTag'
98
import { getInstructionsSummary, getProposalStatus } from './utils'
10-
11-
import NodeWallet from '@coral-xyz/anchor/dist/cjs/nodewallet'
129
import { useWallet } from '@solana/wallet-adapter-react'
13-
import { AccountMeta, Keypair } from '@solana/web3.js'
10+
import { AccountMeta } from '@solana/web3.js'
1411
import {
1512
MultisigParser,
1613
getManyProposalsInstructions,
@@ -28,7 +25,11 @@ export const ProposalRow = ({
2825
useState<(readonly [string, number])[]>()
2926
const status = getProposalStatus(proposal, multisig)
3027
const { cluster } = useContext(ClusterContext)
31-
const { isLoading: isMultisigLoading, connection } = useMultisigContext()
28+
const {
29+
isLoading: isMultisigLoading,
30+
connection,
31+
readOnlySquads,
32+
} = useMultisigContext()
3233
const router = useRouter()
3334
const elementRef = useRef(null)
3435
const { publicKey: walletPublicKey } = useWallet()
@@ -73,12 +74,9 @@ export const ProposalRow = ({
7374
})
7475
}
7576

77+
if (!readOnlySquads) return
7678
// calculate instructions summary
7779
if (!instructions) {
78-
const readOnlySquads = new SquadsMesh({
79-
connection,
80-
wallet: new NodeWallet(new Keypair()),
81-
})
8280
const proposalInstructions = (
8381
await getManyProposalsInstructions(readOnlySquads, [proposal])
8482
)[0]
@@ -130,7 +128,15 @@ export const ProposalRow = ({
130128
observer.unobserve(element)
131129
}
132130
}
133-
}, [time, cluster, proposal, connection, isMultisigLoading, instructions])
131+
}, [
132+
time,
133+
cluster,
134+
proposal,
135+
connection,
136+
readOnlySquads,
137+
isMultisigLoading,
138+
instructions,
139+
])
134140

135141
const handleClickIndividualProposal = useCallback(
136142
(proposalPubkey: string) => {

governance/xc_admin/packages/xc_admin_frontend/contexts/MultisigContext.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const MultisigContext = createContext<MultisigHookData>({
88
priceFeedMultisigProposals: [],
99
isLoading: true,
1010
squads: undefined,
11+
readOnlySquads: undefined,
1112
refreshData: undefined,
1213
connection: undefined,
1314
})
@@ -30,6 +31,7 @@ export const MultisigContextProvider: React.FC<
3031
priceFeedMultisigProposals,
3132
refreshData,
3233
connection,
34+
readOnlySquads,
3335
} = useMultisig()
3436

3537
const value = useMemo(
@@ -42,6 +44,7 @@ export const MultisigContextProvider: React.FC<
4244
squads,
4345
refreshData,
4446
connection,
47+
readOnlySquads,
4548
}),
4649
[
4750
squads,
@@ -52,6 +55,7 @@ export const MultisigContextProvider: React.FC<
5255
priceFeedMultisigProposals,
5356
refreshData,
5457
connection,
58+
readOnlySquads,
5559
]
5660
)
5761

governance/xc_admin/packages/xc_admin_frontend/hooks/useMultisig.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { deriveWsUrl, pythClusterApiUrls } from '../utils/pythClusterApiUrl'
1616
export interface MultisigHookData {
1717
isLoading: boolean
1818
squads: SquadsMesh | undefined
19+
readOnlySquads: SquadsMesh | undefined
1920
upgradeMultisigAccount: MultisigAccount | undefined
2021
priceFeedMultisigAccount: MultisigAccount | undefined
2122
upgradeMultisigProposals: TransactionAccount[]
@@ -47,6 +48,7 @@ export const useMultisig = (): MultisigHookData => {
4748
TransactionAccount[]
4849
>([])
4950
const [squads, setSquads] = useState<SquadsMesh | undefined>()
51+
const [readOnlySquads, setReadOnlySquads] = useState<SquadsMesh | undefined>()
5052

5153
const [urlsIndex, setUrlsIndex] = useState(0)
5254

@@ -73,21 +75,31 @@ export const useMultisig = (): MultisigHookData => {
7375
})
7476
)
7577
} else {
76-
setSquads(undefined)
78+
setSquads(
79+
new SquadsMesh({
80+
connection,
81+
wallet: new NodeWallet(new Keypair()),
82+
})
83+
)
7784
}
78-
}, [wallet, urlsIndex, cluster, connection])
85+
}, [wallet, connection])
86+
87+
useEffect(() => {
88+
setReadOnlySquads(
89+
new SquadsMesh({
90+
connection,
91+
wallet: new NodeWallet(new Keypair()),
92+
})
93+
)
94+
}, [connection])
7995

8096
const refreshData = useCallback(() => {
8197
let cancelled = false
8298

8399
const fetchData = async () => {
84100
setIsLoading(true)
85101
try {
86-
// mock wallet to allow users to view proposals without connecting their wallet
87-
const readOnlySquads = new SquadsMesh({
88-
connection,
89-
wallet: new NodeWallet(new Keypair()),
90-
})
102+
if (!readOnlySquads) return
91103
if (cancelled) return
92104
const upgradeMultisigAccount = await readOnlySquads.getMultisig(
93105
UPGRADE_MULTISIG[multisigCluster]
@@ -147,6 +159,7 @@ export const useMultisig = (): MultisigHookData => {
147159
return {
148160
isLoading,
149161
squads,
162+
readOnlySquads,
150163
upgradeMultisigAccount,
151164
priceFeedMultisigAccount,
152165
upgradeMultisigProposals,

0 commit comments

Comments
 (0)