@@ -13,6 +13,7 @@ import {
13
13
useEffect ,
14
14
useState ,
15
15
} from 'react'
16
+ import toast from 'react-hot-toast'
16
17
import {
17
18
ExecutePostedVaa ,
18
19
getMultisigCluster ,
@@ -26,6 +27,7 @@ import {
26
27
import { ClusterContext } from '../../contexts/ClusterContext'
27
28
import { useMultisigContext } from '../../contexts/MultisigContext'
28
29
import CopyIcon from '../../images/icons/copy.inline.svg'
30
+ import { capitalizeFirstLetter } from '../../utils/capitalizeFirstLetter'
29
31
import ClusterSwitch from '../ClusterSwitch'
30
32
import Loadbar from '../loaders/Loadbar'
31
33
@@ -115,6 +117,8 @@ const Proposal = ({
115
117
const { cluster } = useContext ( ClusterContext )
116
118
const { squads, isLoading : isMultisigLoading } = useMultisigContext ( )
117
119
120
+ const proposalStatus = proposal ? Object . keys ( proposal . status ) [ 0 ] : 'unknown'
121
+
118
122
useEffect ( ( ) => {
119
123
const fetchProposalInstructions = async ( ) => {
120
124
const multisigParser = MultisigParser . fromCluster (
@@ -145,6 +149,50 @@ const Proposal = ({
145
149
fetchProposalInstructions ( )
146
150
} , [ proposal , squads , cluster ] )
147
151
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
+
148
196
return proposal !== undefined &&
149
197
multisig !== undefined &&
150
198
! isMultisigLoading &&
@@ -153,6 +201,10 @@ const Proposal = ({
153
201
< div className = "col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4 lg:col-span-2" >
154
202
< h4 className = "h4 font-semibold" > Info</ h4 >
155
203
< 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 >
156
208
< div className = "flex justify-between" >
157
209
< div > Proposal</ div >
158
210
< div > { proposal . publicKey . toBase58 ( ) } </ div >
@@ -169,7 +221,7 @@ const Proposal = ({
169
221
< div className = "col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4 lg:col-span-1" >
170
222
< h4 className = "h4 mb-4 font-semibold" > Results</ h4 >
171
223
< 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" >
173
225
< div >
174
226
< div className = "font-bold" > Confirmed</ div >
175
227
< div className = "text-lg" > { proposal . approved . length } </ div >
@@ -185,6 +237,37 @@ const Proposal = ({
185
237
</ div >
186
238
</ div >
187
239
</ 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 }
188
271
</ div >
189
272
< div className = "col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4" >
190
273
< h4 className = "h4 font-semibold" > Instructions</ h4 >
0 commit comments