Skip to content

Commit 0e00fb0

Browse files
authored
[xc-admin] add approve/reject/execute/cancel buttons (#576)
* add approve/reject/execute/cancel buttons * fix useMultisig hook not returning correct isLoading value
1 parent 62083eb commit 0e00fb0

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed

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

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
useEffect,
1414
useState,
1515
} from 'react'
16+
import toast from 'react-hot-toast'
1617
import {
1718
ExecutePostedVaa,
1819
getMultisigCluster,
@@ -26,6 +27,7 @@ import {
2627
import { ClusterContext } from '../../contexts/ClusterContext'
2728
import { useMultisigContext } from '../../contexts/MultisigContext'
2829
import CopyIcon from '../../images/icons/copy.inline.svg'
30+
import { capitalizeFirstLetter } from '../../utils/capitalizeFirstLetter'
2931
import ClusterSwitch from '../ClusterSwitch'
3032
import Loadbar from '../loaders/Loadbar'
3133

@@ -115,6 +117,8 @@ const Proposal = ({
115117
const { cluster } = useContext(ClusterContext)
116118
const { squads, isLoading: isMultisigLoading } = useMultisigContext()
117119

120+
const proposalStatus = proposal ? Object.keys(proposal.status)[0] : 'unknown'
121+
118122
useEffect(() => {
119123
const fetchProposalInstructions = async () => {
120124
const multisigParser = MultisigParser.fromCluster(
@@ -145,6 +149,50 @@ const Proposal = ({
145149
fetchProposalInstructions()
146150
}, [proposal, squads, cluster])
147151

152+
const handleClickApprove = async () => {
153+
if (proposal && squads) {
154+
try {
155+
await squads.approveTransaction(proposal.publicKey)
156+
toast.success(`Approved proposal ${proposal.publicKey.toBase58()}`)
157+
} catch (e: any) {
158+
toast.error(capitalizeFirstLetter(e.message))
159+
}
160+
}
161+
}
162+
163+
const handleClickReject = async () => {
164+
if (proposal && squads) {
165+
try {
166+
await squads.rejectTransaction(proposal.publicKey)
167+
toast.success(`Rejected proposal ${proposal.publicKey.toBase58()}`)
168+
} catch (e: any) {
169+
toast.error(capitalizeFirstLetter(e.message))
170+
}
171+
}
172+
}
173+
174+
const handleClickExecute = async () => {
175+
if (proposal && squads) {
176+
try {
177+
await squads.executeTransaction(proposal.publicKey)
178+
toast.success(`Executed proposal ${proposal.publicKey.toBase58()}`)
179+
} catch (e: any) {
180+
toast.error(capitalizeFirstLetter(e.message))
181+
}
182+
}
183+
}
184+
185+
const handleClickCancel = async () => {
186+
if (proposal && squads) {
187+
try {
188+
await squads.cancelTransaction(proposal.publicKey)
189+
toast.success(`Cancelled proposal ${proposal.publicKey.toBase58()}`)
190+
} catch (e: any) {
191+
toast.error(capitalizeFirstLetter(e.message))
192+
}
193+
}
194+
}
195+
148196
return proposal !== undefined &&
149197
multisig !== undefined &&
150198
!isMultisigLoading &&
@@ -153,6 +201,10 @@ const Proposal = ({
153201
<div className="col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4 lg:col-span-2">
154202
<h4 className="h4 font-semibold">Info</h4>
155203
<hr className="border-gray-700" />
204+
<div className="flex justify-between">
205+
<div>Status</div>
206+
<div>{Object.keys(proposal.status)[0]}</div>
207+
</div>
156208
<div className="flex justify-between">
157209
<div>Proposal</div>
158210
<div>{proposal.publicKey.toBase58()}</div>
@@ -169,7 +221,7 @@ const Proposal = ({
169221
<div className="col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4 lg:col-span-1">
170222
<h4 className="h4 mb-4 font-semibold">Results</h4>
171223
<hr className="border-gray-700" />
172-
<div className="grid grid-cols-3 justify-center gap-4 pt-5 text-center align-middle">
224+
<div className="grid grid-cols-3 justify-center gap-4 text-center align-middle">
173225
<div>
174226
<div className="font-bold">Confirmed</div>
175227
<div className="text-lg">{proposal.approved.length}</div>
@@ -185,6 +237,37 @@ const Proposal = ({
185237
</div>
186238
</div>
187239
</div>
240+
{proposalStatus === 'active' ? (
241+
<div className="flex items-center justify-between px-8 pt-3">
242+
<button
243+
className="action-btn text-base"
244+
onClick={handleClickApprove}
245+
>
246+
Approve
247+
</button>
248+
<button
249+
className="sub-action-btn text-base"
250+
onClick={handleClickReject}
251+
>
252+
Reject
253+
</button>
254+
</div>
255+
) : proposalStatus === 'executeReady' ? (
256+
<div className="flex items-center justify-between px-8 pt-3">
257+
<button
258+
className="action-btn text-base"
259+
onClick={handleClickExecute}
260+
>
261+
Execute
262+
</button>
263+
<button
264+
className="sub-action-btn text-base"
265+
onClick={handleClickCancel}
266+
>
267+
Cancel
268+
</button>
269+
</div>
270+
) : null}
188271
</div>
189272
<div className="col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4">
190273
<h4 className="h4 font-semibold">Instructions</h4>

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export const useMultisig = (wallet: Wallet): MultisigHookData => {
9595
publicKey: new PublicKey(0),
9696
},
9797
})
98+
if (cancelled) return
9899
setUpgradeMultisigAccount(
99100
await squads.getMultisig(
100101
UPGRADE_MULTISIG[getMultisigCluster(cluster)]
@@ -109,6 +110,7 @@ export const useMultisig = (wallet: Wallet): MultisigHookData => {
109110
} else {
110111
setSecurityMultisigAccount(undefined)
111112
}
113+
if (cancelled) return
112114
setUpgradeMultisigProposals(
113115
await getSortedProposals(
114116
squads,
@@ -144,7 +146,9 @@ export const useMultisig = (wallet: Wallet): MultisigHookData => {
144146
}
145147
})()
146148

147-
return () => {}
149+
return () => {
150+
cancelled = true
151+
}
148152
}, [urlsIndex, cluster, wallet])
149153

150154
return {

governance/xc_admin/packages/xc_admin_frontend/styles/globals.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,7 @@
284284
.action-btn {
285285
@apply h-[45px] rounded-full bg-pythPurple px-8 font-mono font-semibold uppercase leading-none transition-colors hover:bg-mediumSlateBlue disabled:opacity-70 disabled:hover:bg-pythPurple;
286286
}
287+
288+
.sub-action-btn {
289+
@apply h-[45px] rounded-full bg-darkGray2 px-8 font-mono font-semibold uppercase leading-none transition-colors hover:bg-darkGray4 disabled:opacity-70 disabled:hover:bg-darkGray2;
290+
}

0 commit comments

Comments
 (0)