Skip to content

Commit

Permalink
Implement set error flag (#121)
Browse files Browse the repository at this point in the history
* Implement set error flag
  • Loading branch information
Orelsanpls authored Aug 12, 2022
1 parent 4c4a667 commit 15f6786
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 123 deletions.
173 changes: 128 additions & 45 deletions components/ProposalActions.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useEffect, useState } from 'react';
import { useHasVoteTimeExpired } from '../hooks/useHasVoteTimeExpired';
import useRealm from '../hooks/useRealm';
import { getSignatoryRecordAddress } from '@solana/spl-governance';
import {
getSignatoryRecordAddress,
InstructionExecutionStatus,
} from '@solana/spl-governance';
import useWalletStore, {
EnhancedProposalState,
} from '../stores/useWalletStore';
Expand All @@ -15,11 +18,14 @@ import { Proposal } from '@solana/spl-governance';
import { ProgramAccount } from '@solana/spl-governance';
import { cancelProposal } from 'actions/cancelProposal';
import { getProgramVersionForRealm } from '@models/registry/api';
import { flagInstructionError } from 'actions/flagInstructionError';
import useProposal from '@hooks/useProposal';

const ProposalActionsPanel = () => {
const { governance, proposal, proposalOwner } = useWalletStore(
(s) => s.selectedProposal,
);
const { instructions } = useProposal();
const { realmInfo } = useRealm();
const wallet = useWalletStore((s) => s.current);
const connected = useWalletStore((s) => s.connected);
Expand Down Expand Up @@ -69,6 +75,20 @@ const ProposalActionsPanel = () => {
wallet.publicKey,
);

const canSetFlagToExecutionError =
proposal &&
governance &&
proposalOwner &&
wallet?.publicKey &&
proposalOwner?.account.governingTokenOwner.equals(wallet.publicKey) &&
(proposal?.account.state === EnhancedProposalState.Succeeded ||
proposal?.account.state === EnhancedProposalState.Executing ||
proposal?.account.state === EnhancedProposalState.ExecutingWithErrors) &&
Object.values(instructions).some(
(instruction) =>
instruction.account.executionStatus === InstructionExecutionStatus.None,
);

const signOffTooltipContent = !connected
? 'Connect your wallet to sign off this proposal'
: !signatoryRecord
Expand Down Expand Up @@ -102,6 +122,11 @@ const ProposalActionsPanel = () => {
!hasVoteTimeExpired
? 'Proposal is being voting right now, you need to wait the vote to finish to be able to finalize it.'
: '';

const setFlagToExecutionErrorTooltipContent = !connected
? 'Connect your wallet to set the error flag for this proposal.'
: 'Set error execution flag for this proposal.';

const handleFinalizeVote = async () => {
try {
if (proposal && realmInfo && governance) {
Expand All @@ -127,6 +152,51 @@ const ProposalActionsPanel = () => {
}
};

const handleSetExecutionErrorFlag = async () => {
try {
if (proposal && realmInfo && governance) {
const rpcContext = new RpcContext(
proposal.owner,
getProgramVersionForRealm(realmInfo),
wallet!,
connection.current,
connection.endpoint,
);

if (Object.keys(instructions).length === 0) {
notify({
type: 'info',
message: 'Cannot set the error flag',
description: 'The proposal does not contain any instruction',
});

return;
}

const filteredInstructions = Object.values(instructions).filter(
(instruction) =>
instruction.account.executionStatus ===
InstructionExecutionStatus.None,
);

// Set flag error for one instruction after another until there are no more to set flag to
for (const instruction of filteredInstructions) {
await flagInstructionError(rpcContext, proposal, instruction.pubkey);
}

await fetchRealm(realmInfo!.programId, realmInfo!.realmId);
}
} catch (error) {
notify({
type: 'error',
message: `Error: Could not finalize vote.`,
description: `${error}`,
});

console.error('error finalizing vote', error);
}
};

const handleSignOffProposal = async () => {
try {
if (proposal && realmInfo) {
Expand Down Expand Up @@ -157,6 +227,7 @@ const ProposalActionsPanel = () => {
console.error('error sign off', error);
}
};

const handleCancelProposal = async (
proposal: ProgramAccount<Proposal> | undefined,
) => {
Expand Down Expand Up @@ -184,51 +255,63 @@ const ProposalActionsPanel = () => {
console.error('error cancelling proposal', error);
}
};

if (
!canCancelProposal &&
!canSignOff &&
!canFinalizeVote &&
!canSetFlagToExecutionError
) {
return null;
}

return (
<>
{EnhancedProposalState.Cancelled === proposal?.account.state ||
EnhancedProposalState.Succeeded === proposal?.account.state ||
EnhancedProposalState.Outdated === proposal?.account.state ||
EnhancedProposalState.Defeated === proposal?.account.state ||
(!canCancelProposal && !canSignOff && !canFinalizeVote) ? null : (
<div>
<div className="bg-bkg-2 rounded-lg p-6 space-y-6 flex justify-center items-center text-center flex-col w-full mt-4">
{canSignOff && (
<Button
tooltipMessage={signOffTooltipContent}
className="w-1/2"
onClick={handleSignOffProposal}
disabled={!connected || !canSignOff}
>
Sign Off
</Button>
)}

{canCancelProposal && (
<SecondaryButton
tooltipMessage={cancelTooltipContent}
className="w-1/2"
onClick={() => handleCancelProposal(proposal)}
disabled={!connected}
>
Cancel
</SecondaryButton>
)}

{canFinalizeVote && (
<Button
tooltipMessage={finalizeVoteTooltipContent}
className="w-1/2"
onClick={handleFinalizeVote}
disabled={!connected || !canFinalizeVote}
>
Finalize
</Button>
)}
</div>
</div>
)}
</>
<div>
<div className="bg-bkg-2 rounded-lg p-6 space-y-6 flex justify-center items-center text-center flex-col w-full mt-4">
{canSignOff && (
<Button
tooltipMessage={signOffTooltipContent}
className="w-1/2"
onClick={handleSignOffProposal}
disabled={!connected || !canSignOff}
>
Sign Off
</Button>
)}

{canCancelProposal && (
<SecondaryButton
tooltipMessage={cancelTooltipContent}
className="w-1/2"
onClick={() => handleCancelProposal(proposal)}
disabled={!connected}
>
Cancel
</SecondaryButton>
)}

{canFinalizeVote && (
<Button
tooltipMessage={finalizeVoteTooltipContent}
className="w-1/2"
onClick={handleFinalizeVote}
disabled={!connected || !canFinalizeVote}
>
Finalize
</Button>
)}

{canSetFlagToExecutionError && (
<Button
tooltipMessage={setFlagToExecutionErrorTooltipContent}
onClick={handleSetExecutionErrorFlag}
disabled={!connected}
>
Set Execution Error Flag
</Button>
)}
</div>
</div>
);
};

Expand Down
10 changes: 0 additions & 10 deletions components/ProposalFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ const initialFilterSettings: Filters = {
[EnhancedProposalState.Cancelled]: false,
[EnhancedProposalState.Defeated]: true,
[EnhancedProposalState.ExecutingWithErrors]: true,
[EnhancedProposalState.Outdated]: false,
};

const StyledAlertCount = styled.span`
Expand Down Expand Up @@ -159,15 +158,6 @@ const ProposalFilter = ({ filters, setFilters }) => {
}
/>
</div>
<div className="flex items-center justify-between pb-2">
Outdated
<Switch
checked={filterSettings[EnhancedProposalState.Outdated]}
onChange={(checked) =>
handleFilters(EnhancedProposalState.Outdated, checked)
}
/>
</div>
<div className="flex items-center justify-between">
Voting
<Switch
Expand Down
6 changes: 0 additions & 6 deletions components/ProposalStatusBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ function getProposalStateLabel(
switch (state) {
case EnhancedProposalState.ExecutingWithErrors:
return 'Execution Errors';
case EnhancedProposalState.Outdated:
return 'Outdated';
case EnhancedProposalState.Voting:
// If there is no tipping point and voting period ends then proposal stays in Voting state and needs to be manually finalized
return hasVoteEnded ? 'Finalizing' : 'Voting';
Expand Down Expand Up @@ -47,10 +45,6 @@ function getProposalStateStyle(state: EnhancedProposalState) {
return 'border border-red text-red';
}

if (state === EnhancedProposalState.Outdated) {
return 'border border-orange text-orange';
}

return 'border border-fgd-3 text-fgd-3';
}

Expand Down
1 change: 0 additions & 1 deletion components/instructions/ExecuteAllInstructionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ export function ExecuteAllInstructionButton({
EnhancedProposalState.Executing,
EnhancedProposalState.ExecutingWithErrors,
EnhancedProposalState.Succeeded,
EnhancedProposalState.Outdated,
].includes(proposal.account.state)
) {
return null;
Expand Down
3 changes: 1 addition & 2 deletions components/instructions/ExecuteInstructionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ export function ExecuteInstructionButton({
if (
proposal.account.state !== EnhancedProposalState.Executing &&
proposal.account.state !== EnhancedProposalState.ExecutingWithErrors &&
proposal.account.state !== EnhancedProposalState.Succeeded &&
proposal.account.state !== EnhancedProposalState.Outdated
proposal.account.state !== EnhancedProposalState.Succeeded
) {
return null;
}
Expand Down
2 changes: 2 additions & 0 deletions components/instructions/FlagInstructionErrorButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { flagInstructionError } from 'actions/flagInstructionError';
import {
InstructionExecutionStatus,
Proposal,
ProposalState,
ProposalTransaction,
TokenOwnerRecord,
} from '@solana/spl-governance';
Expand Down Expand Up @@ -34,6 +35,7 @@ export function FlagInstructionErrorButton({
const connection = useWalletStore((s) => s.connection);

if (
proposal.account.state === ProposalState.ExecutingWithErrors ||
playState !== PlayState.Error ||
proposalInstruction.account.executionStatus !==
InstructionExecutionStatus.Error ||
Expand Down
12 changes: 8 additions & 4 deletions components/instructions/instructionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ExternalLinkIcon } from '@heroicons/react/outline';
import {
AccountMetaData,
Proposal,
ProposalState,
ProposalTransaction,
} from '@solana/spl-governance';
import {
Expand Down Expand Up @@ -169,10 +170,12 @@ export default function InstructionCard({
></img>
)}
</h3>

<InstructionProgram
endpoint={connection.endpoint}
programId={proposalInstruction.account.getSingleInstruction().programId}
></InstructionProgram>
/>

<div className="border-b border-bkg-4 mb-6">
{proposalInstruction.account
.getSingleInstruction()
Expand Down Expand Up @@ -202,7 +205,7 @@ export default function InstructionCard({
<img src={nftImgUrl}></img>
</div>
) : (
<InstructionData descriptor={descriptor}></InstructionData>
<InstructionData descriptor={descriptor} />
)}

{
Expand Down Expand Up @@ -236,7 +239,8 @@ export default function InstructionCard({
proposalInstruction={proposalInstruction}
/>

{proposal && (
{proposal &&
proposal.account.state !== ProposalState.ExecutingWithErrors ? (
<ExecuteInstructionButton
disabled={
isInstructionAboutOrcaWhirlpoolOpenPosition && !additionalSigner
Expand All @@ -247,7 +251,7 @@ export default function InstructionCard({
setPlaying={setPlaying}
additionalSigner={additionalSigner ?? undefined}
/>
)}
) : null}
</div>
</div>
);
Expand Down
8 changes: 5 additions & 3 deletions components/instructions/instructionPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Disclosure } from '@headlessui/react';
import { ChevronDownIcon } from '@heroicons/react/solid';
import { useEffect, useRef, useState } from 'react';
import useWalletStore from 'stores/useWalletStore';
import { RpcContext } from '@solana/spl-governance';
import { ProposalState, RpcContext } from '@solana/spl-governance';
import useRealm from '@hooks/useRealm';
import { getProgramVersionForRealm } from '@models/registry/api';
import {
Expand Down Expand Up @@ -104,7 +104,9 @@ export function InstructionPanel() {
</div>
))}

{proposal && proposalInstructions.length > 1 && (
{proposal &&
proposalInstructions.length > 1 &&
proposal.account.state !== ProposalState.ExecutingWithErrors ? (
<div className="flex justify-end">
<ExecuteAllInstructionButton
proposal={proposal}
Expand All @@ -113,7 +115,7 @@ export function InstructionPanel() {
setPlaying={setPlaying}
/>
</div>
)}
) : null}
</Disclosure.Panel>
</>
)}
Expand Down
3 changes: 1 addition & 2 deletions pages/dao/[symbol]/proposal/[pk].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ const Proposal = () => {
(proposal.account.state === EnhancedProposalState.Completed ||
proposal.account.state === EnhancedProposalState.Executing ||
proposal.account.state === EnhancedProposalState.SigningOff ||
proposal.account.state === EnhancedProposalState.Succeeded ||
proposal.account.state === EnhancedProposalState.Outdated);
proposal.account.state === EnhancedProposalState.Succeeded);

useEffect(() => {
const handleResolveDescription = async () => {
Expand Down
Loading

1 comment on commit 15f6786

@vercel
Copy link

@vercel vercel bot commented on 15f6786 Aug 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.