1
1
import { BN } from '@coral-xyz/anchor'
2
- import { useWallet } from '@solana/wallet-adapter-react'
3
2
import { AccountMeta , PublicKey } from '@solana/web3.js'
4
3
import { getIxPDA } from '@sqds/mesh'
5
4
import { MultisigAccount , TransactionAccount } from '@sqds/mesh/lib/types'
@@ -29,6 +28,7 @@ import { useMultisigContext } from '../../contexts/MultisigContext'
29
28
import CopyIcon from '../../images/icons/copy.inline.svg'
30
29
import { capitalizeFirstLetter } from '../../utils/capitalizeFirstLetter'
31
30
import ClusterSwitch from '../ClusterSwitch'
31
+ import CopyPubkey from '../common/CopyPubkey'
32
32
import Loadbar from '../loaders/Loadbar'
33
33
34
34
const ProposalRow = ( {
@@ -65,30 +65,27 @@ const ProposalRow = ({
65
65
}
66
66
>
67
67
< div className = "flex justify-between p-4" >
68
- < div > { proposal . publicKey . toBase58 ( ) } </ div >
69
- < div
70
- className = {
71
- status === 'active'
72
- ? 'text-[#E6DAFE]'
73
- : status === 'executed'
74
- ? 'text-[#1FC3D7]'
75
- : status === 'cancelled'
76
- ? 'text-[#FFA7A0]'
77
- : status === 'rejected'
78
- ? 'text-[#F86B86]'
79
- : ''
80
- }
81
- >
82
- < strong > { status } </ strong >
68
+ < div >
69
+ { ' ' }
70
+ < span className = "mr-2 hidden sm:block" >
71
+ { proposal . publicKey . toBase58 ( ) }
72
+ </ span >
73
+ < span className = "mr-2 sm:hidden" >
74
+ { proposal . publicKey . toBase58 ( ) . slice ( 0 , 6 ) +
75
+ '...' +
76
+ proposal . publicKey . toBase58 ( ) . slice ( - 6 ) }
77
+ </ span > { ' ' }
83
78
</ div >
79
+
80
+ < StatusTag proposalStatus = { status } />
84
81
</ div >
85
82
</ div >
86
83
)
87
84
}
88
85
89
86
const SignerTag = ( ) => {
90
87
return (
91
- < div className = "flex items-center justify-center rounded-full bg-darkGray4 py-1 px-2 text-xs" >
88
+ < div className = "flex items-center justify-center rounded-full bg-[#605D72] py-1 px-2 text-xs" >
92
89
Signer
93
90
</ div >
94
91
)
@@ -102,6 +99,26 @@ const WritableTag = () => {
102
99
)
103
100
}
104
101
102
+ const StatusTag = ( { proposalStatus } : { proposalStatus : string } ) => {
103
+ return (
104
+ < div
105
+ className = { `flex items-center justify-center rounded-full ${
106
+ proposalStatus === 'active'
107
+ ? 'bg-[#3C3299]'
108
+ : proposalStatus === 'executed'
109
+ ? 'bg-[#1C1E5D]'
110
+ : proposalStatus === 'cancelled'
111
+ ? 'bg-[#C4428F]'
112
+ : proposalStatus === 'rejected'
113
+ ? 'bg-[#CF6E42]'
114
+ : 'bg-pythPurple'
115
+ } py-1 px-2 text-xs`}
116
+ >
117
+ { proposalStatus }
118
+ </ div >
119
+ )
120
+ }
121
+
105
122
const Proposal = ( {
106
123
proposal,
107
124
multisig,
@@ -114,6 +131,7 @@ const Proposal = ({
114
131
> ( [ ] )
115
132
const [ isProposalInstructionsLoading , setIsProposalInstructionsLoading ] =
116
133
useState ( false )
134
+ const [ isVerified , setIsVerified ] = useState ( false )
117
135
const { cluster } = useContext ( ClusterContext )
118
136
const { squads, isLoading : isMultisigLoading } = useMultisigContext ( )
119
137
@@ -141,6 +159,30 @@ const Proposal = ({
141
159
} )
142
160
proposalIxs . push ( parsedInstruction )
143
161
}
162
+ setIsVerified (
163
+ proposalIxs . every (
164
+ ( ix ) =>
165
+ ix instanceof PythMultisigInstruction ||
166
+ ( ix instanceof WormholeMultisigInstruction &&
167
+ ix . name === 'postMessage' &&
168
+ ix . governanceAction instanceof ExecutePostedVaa &&
169
+ ix . governanceAction . instructions . every ( ( remoteIx ) => {
170
+ const innerMultisigParser = MultisigParser . fromCluster (
171
+ getRemoteCluster ( cluster )
172
+ )
173
+ const parsedRemoteInstruction =
174
+ innerMultisigParser . parseInstruction ( {
175
+ programId : remoteIx . programId ,
176
+ data : remoteIx . data as Buffer ,
177
+ keys : remoteIx . keys as AccountMeta [ ] ,
178
+ } )
179
+ return (
180
+ parsedRemoteInstruction instanceof PythMultisigInstruction
181
+ )
182
+ } ) &&
183
+ ix . governanceAction . targetChainId === 'pythnet' )
184
+ )
185
+ )
144
186
setProposalInstructions ( proposalIxs )
145
187
setIsProposalInstructionsLoading ( false )
146
188
}
@@ -200,23 +242,32 @@ const Proposal = ({
200
242
! isProposalInstructionsLoading ? (
201
243
< div className = "grid grid-cols-3 gap-4" >
202
244
< div className = "col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4 lg:col-span-2" >
203
- < h4 className = "h4 font-semibold" > Info</ h4 >
245
+ < div className = "flex justify-between" >
246
+ < h4 className = "h4 font-semibold" > Info</ h4 >
247
+ < div
248
+ className = { `flex items-center justify-center rounded-full py-1 px-2 text-xs ${
249
+ isVerified ? 'bg-[#187B51]' : 'bg-[#8D2D41]'
250
+ } `}
251
+ >
252
+ { isVerified ? 'Verified' : 'Unverified' }
253
+ </ div >
254
+ </ div >
204
255
< hr className = "border-gray-700" />
205
256
< div className = "flex justify-between" >
206
257
< div > Status</ div >
207
- < div > { Object . keys ( proposal . status ) [ 0 ] } </ div >
258
+ < StatusTag proposalStatus = { proposalStatus } / >
208
259
</ div >
209
260
< div className = "flex justify-between" >
210
261
< div > Proposal</ div >
211
- < div > { proposal . publicKey . toBase58 ( ) } </ div >
262
+ < CopyPubkey pubkey = { proposal . publicKey . toBase58 ( ) } / >
212
263
</ div >
213
264
< div className = "flex justify-between" >
214
265
< div > Creator</ div >
215
- < div > { proposal . creator . toBase58 ( ) } </ div >
266
+ < CopyPubkey pubkey = { proposal . creator . toBase58 ( ) } / >
216
267
</ div >
217
268
< div className = "flex justify-between" >
218
269
< div > Multisig</ div >
219
- < div > { proposal . ms . toBase58 ( ) } </ div >
270
+ < CopyPubkey pubkey = { proposal . ms . toBase58 ( ) } / >
220
271
</ div >
221
272
</ div >
222
273
< div className = "col-span-3 my-2 space-y-4 bg-[#1E1B2F] p-4 lg:col-span-1" >
@@ -239,7 +290,7 @@ const Proposal = ({
239
290
</ div >
240
291
</ div >
241
292
{ proposalStatus === 'active' ? (
242
- < div className = "flex items-center justify-between px -8 pt-3" >
293
+ < div className = "flex items-center justify-center space-x -8 pt-3" >
243
294
< button
244
295
className = "action-btn text-base"
245
296
onClick = { handleClickApprove }
@@ -338,15 +389,19 @@ const Proposal = ({
338
389
className = "flex justify-between border-t border-beige-300 py-3"
339
390
>
340
391
< div > { key } </ div >
341
- < div className = "max-w-sm break-all" >
342
- { instruction . args [ key ] instanceof PublicKey
343
- ? instruction . args [ key ] . toBase58 ( )
344
- : typeof instruction . args [ key ] === 'string'
345
- ? instruction . args [ key ]
346
- : instruction . args [ key ] instanceof Uint8Array
347
- ? instruction . args [ key ] . toString ( 'hex' )
348
- : JSON . stringify ( instruction . args [ key ] ) }
349
- </ div >
392
+ { instruction . args [ key ] instanceof PublicKey ? (
393
+ < CopyPubkey
394
+ pubkey = { instruction . args [ key ] . toBase58 ( ) }
395
+ />
396
+ ) : (
397
+ < div className = "max-w-sm break-all" >
398
+ { typeof instruction . args [ key ] === 'string'
399
+ ? instruction . args [ key ]
400
+ : instruction . args [ key ] instanceof Uint8Array
401
+ ? instruction . args [ key ] . toString ( 'hex' )
402
+ : JSON . stringify ( instruction . args [ key ] ) }
403
+ </ div >
404
+ ) }
350
405
</ div >
351
406
) ) }
352
407
</ div >
@@ -385,32 +440,11 @@ const Proposal = ({
385
440
{ instruction . accounts . named [ key ] . isWritable ? (
386
441
< WritableTag />
387
442
) : null }
388
- < div
389
- className = "-ml-1 inline-flex cursor-pointer items-center px-1 hover:bg-dark hover:text-white active:bg-darkGray3"
390
- onClick = { ( ) => {
391
- copy (
392
- instruction . accounts . named [
393
- key
394
- ] . pubkey . toBase58 ( )
395
- )
396
- } }
397
- >
398
- < span className = "mr-2 hidden xl:block" >
399
- { instruction . accounts . named [
400
- key
401
- ] . pubkey . toBase58 ( ) }
402
- </ span >
403
- < span className = "mr-2 xl:hidden" >
404
- { instruction . accounts . named [ key ] . pubkey
405
- . toBase58 ( )
406
- . slice ( 0 , 6 ) +
407
- '...' +
408
- instruction . accounts . named [ key ] . pubkey
409
- . toBase58 ( )
410
- . slice ( - 6 ) }
411
- </ span > { ' ' }
412
- < CopyIcon className = "shrink-0" />
413
- </ div >
443
+ < CopyPubkey
444
+ pubkey = { instruction . accounts . named [
445
+ key
446
+ ] . pubkey . toBase58 ( ) }
447
+ />
414
448
</ div >
415
449
</ div >
416
450
</ >
@@ -428,11 +462,13 @@ const Proposal = ({
428
462
className = "flex justify-between"
429
463
>
430
464
< div > Program ID</ div >
431
- < div > { instruction . instruction . programId . toBase58 ( ) } </ div >
465
+ < CopyPubkey
466
+ pubkey = { instruction . instruction . programId . toBase58 ( ) }
467
+ />
432
468
</ div >
433
469
< div key = { `${ index } _data` } className = "flex justify-between" >
434
470
< div > Data</ div >
435
- < div >
471
+ < div className = "max-w-sm break-all" >
436
472
{ instruction . instruction . data . length > 0
437
473
? instruction . instruction . data . toString ( 'hex' )
438
474
: 'No data' }
@@ -552,27 +588,31 @@ const Proposal = ({
552
588
className = "flex justify-between border-t border-beige-300 py-3"
553
589
>
554
590
< div > { key } </ div >
555
- < div className = "max-w-sm break-all" >
556
- { parsedInstruction . args [
557
- key
558
- ] instanceof PublicKey
559
- ? parsedInstruction . args [
560
- key
561
- ] . toBase58 ( )
562
- : typeof parsedInstruction . args [
563
- key
564
- ] === 'string'
565
- ? parsedInstruction . args [ key ]
566
- : parsedInstruction . args [
567
- key
568
- ] instanceof Uint8Array
569
- ? parsedInstruction . args [
570
- key
571
- ] . toString ( 'hex' )
572
- : JSON . stringify (
573
- parsedInstruction . args [ key ]
574
- ) }
575
- </ div >
591
+ { parsedInstruction . args [
592
+ key
593
+ ] instanceof PublicKey ? (
594
+ < CopyPubkey
595
+ pubkey = { parsedInstruction . args [
596
+ key
597
+ ] . toBase58 ( ) }
598
+ />
599
+ ) : (
600
+ < div className = "max-w-sm break-all" >
601
+ { typeof parsedInstruction . args [
602
+ key
603
+ ] === 'string'
604
+ ? parsedInstruction . args [ key ]
605
+ : parsedInstruction . args [
606
+ key
607
+ ] instanceof Uint8Array
608
+ ? parsedInstruction . args [
609
+ key
610
+ ] . toString ( 'hex' )
611
+ : JSON . stringify (
612
+ parsedInstruction . args [ key ]
613
+ ) }
614
+ </ div >
615
+ ) }
576
616
</ div >
577
617
)
578
618
) }
@@ -774,7 +814,6 @@ const Proposals = () => {
774
814
priceFeedMultisigProposals,
775
815
isLoading : isMultisigLoading ,
776
816
} = useMultisigContext ( )
777
- const { connected } = useWallet ( )
778
817
779
818
const handleClickBackToPriceFeeds = ( ) => {
780
819
delete router . query . proposal
0 commit comments