1
- import { TransactionAccount } from '@sqds/mesh/lib/types'
2
1
import { useRouter } from 'next/router'
3
- import { useCallback , useContext , useEffect , useState , useMemo } from 'react'
4
- import { ClusterContext } from '../../../contexts/ClusterContext'
5
- import { useMultisigContext } from '../../../contexts/MultisigContext'
6
- import { PROPOSAL_STATUSES } from './utils'
7
- import ClusterSwitch from '../../ClusterSwitch'
2
+ import { ProgramType } from '@pythnetwork/xc-admin-common'
3
+ import { useProgramContext } from '../../../contexts/ProgramContext'
8
4
import ProgramSwitch from '../../ProgramSwitch'
9
- import Loadbar from '../../loaders/Loadbar'
10
- import { Select } from '../../Select'
11
- import { useQueryState , parseAsStringLiteral } from 'nuqs'
12
-
13
- import { ProposalRow } from './ProposalRow'
14
- import { getProposalStatus } from './utils'
15
- import { Proposal } from './Proposal'
16
- import { useWallet } from '@solana/wallet-adapter-react'
17
-
18
- type ProposalType = 'priceFeed' | 'governance'
19
-
20
- const VOTE_STATUSES = [
21
- 'any' ,
22
- 'voted' ,
23
- 'approved' ,
24
- 'rejected' ,
25
- 'cancelled' ,
26
- 'notVoted' ,
27
- ] as const
28
- const DEFAULT_VOTE_STATUS = 'any'
29
-
30
- const PROPOSAL_STATUS_FILTERS = [ 'all' , ...PROPOSAL_STATUSES ] as const
31
- const DEFAULT_PROPOSAL_STATUS_FILTER = 'all'
5
+ import PythCoreProposals from './PythCoreProposals'
6
+ import PythLazerProposals from './PythLazerProposals'
32
7
33
8
const Proposals = ( ) => {
34
9
const router = useRouter ( )
35
- const [ currentProposal , setCurrentProposal ] = useState < TransactionAccount > ( )
36
- const [ currentProposalPubkey , setCurrentProposalPubkey ] = useState < string > ( )
37
- const [ statusFilter , setStatusFilter ] = useQueryState (
38
- 'status' ,
39
- parseAsStringLiteral ( PROPOSAL_STATUS_FILTERS ) . withDefault (
40
- DEFAULT_PROPOSAL_STATUS_FILTER
41
- )
42
- )
43
- const [ voteStatus , setVoteStatus ] = useQueryState (
44
- 'voteStatus' ,
45
- parseAsStringLiteral ( VOTE_STATUSES ) . withDefault ( DEFAULT_VOTE_STATUS )
46
- )
47
- const { cluster } = useContext ( ClusterContext )
48
- const { publicKey : walletPublicKey } = useWallet ( )
49
-
50
- const {
51
- upgradeMultisigAccount,
52
- priceFeedMultisigAccount,
53
- priceFeedMultisigProposals,
54
- upgradeMultisigProposals,
55
- isLoading : isMultisigLoading ,
56
- refreshData,
57
- } = useMultisigContext ( )
58
-
59
- const [ proposalType , setProposalType ] = useState < ProposalType > ( 'priceFeed' )
60
-
61
- const multisigAccount =
62
- proposalType === 'priceFeed'
63
- ? priceFeedMultisigAccount
64
- : upgradeMultisigAccount
65
- const multisigProposals =
66
- proposalType === 'priceFeed'
67
- ? priceFeedMultisigProposals
68
- : upgradeMultisigProposals
10
+ const { programType } = useProgramContext ( )
69
11
70
12
const handleClickBackToProposals = ( ) => {
71
13
delete router . query . proposal
@@ -79,219 +21,51 @@ const Proposals = () => {
79
21
)
80
22
}
81
23
82
- useEffect ( ( ) => {
83
- if ( router . query . proposal ) {
84
- setCurrentProposalPubkey ( router . query . proposal as string )
85
- } else {
86
- setCurrentProposalPubkey ( undefined )
87
- }
88
- } , [ router . query . proposal ] )
89
-
90
- const switchProposalType = useCallback ( ( ) => {
91
- if ( proposalType === 'priceFeed' ) {
92
- setProposalType ( 'governance' )
93
- } else {
94
- setProposalType ( 'priceFeed' )
95
- }
96
- } , [ proposalType ] )
97
-
98
- useEffect ( ( ) => {
99
- if ( currentProposalPubkey ) {
100
- const currProposal = multisigProposals . find (
101
- ( proposal ) => proposal . publicKey . toBase58 ( ) === currentProposalPubkey
102
- )
103
- setCurrentProposal ( currProposal )
104
- if ( currProposal === undefined ) {
105
- const otherProposals =
106
- proposalType !== 'priceFeed'
107
- ? priceFeedMultisigProposals
108
- : upgradeMultisigProposals
109
- if (
110
- otherProposals . findIndex (
111
- ( proposal ) =>
112
- proposal . publicKey . toBase58 ( ) === currentProposalPubkey
113
- ) !== - 1
114
- ) {
115
- switchProposalType ( )
116
- }
117
- }
118
- }
119
- } , [
120
- switchProposalType ,
121
- priceFeedMultisigProposals ,
122
- proposalType ,
123
- upgradeMultisigProposals ,
124
- currentProposalPubkey ,
125
- multisigProposals ,
126
- cluster ,
127
- ] )
128
-
129
- const proposalsFilteredByStatus = useMemo (
130
- ( ) =>
131
- statusFilter === 'all'
132
- ? multisigProposals
133
- : multisigProposals . filter (
134
- ( proposal ) =>
135
- getProposalStatus ( proposal , multisigAccount ) === statusFilter
136
- ) ,
137
- [ statusFilter , multisigAccount , multisigProposals ]
138
- )
139
-
140
- const filteredProposals = useMemo ( ( ) => {
141
- if ( walletPublicKey ) {
142
- switch ( voteStatus ) {
143
- case 'any' :
144
- return proposalsFilteredByStatus
145
- case 'voted' : {
146
- return proposalsFilteredByStatus . filter ( ( proposal ) =>
147
- [
148
- ...proposal . approved ,
149
- ...proposal . rejected ,
150
- ...proposal . cancelled ,
151
- ] . some ( ( vote ) => vote . equals ( walletPublicKey ) )
152
- )
153
- }
154
- case 'approved' : {
155
- return proposalsFilteredByStatus . filter ( ( proposal ) =>
156
- proposal . approved . some ( ( vote ) => vote . equals ( walletPublicKey ) )
157
- )
158
- }
159
- case 'rejected' : {
160
- return proposalsFilteredByStatus . filter ( ( proposal ) =>
161
- proposal . rejected . some ( ( vote ) => vote . equals ( walletPublicKey ) )
24
+ // Function to render the appropriate program component
25
+ const renderProgramComponent = ( ) => {
26
+ try {
27
+ const proposalPubkey = router . query . proposal as string | undefined
28
+
29
+ switch ( programType ) {
30
+ case ProgramType . PYTH_CORE :
31
+ return (
32
+ < PythCoreProposals
33
+ proposalPubkey = { proposalPubkey }
34
+ onBackToProposals = { handleClickBackToProposals }
35
+ />
162
36
)
163
- }
164
- case 'cancelled' : {
165
- return proposalsFilteredByStatus . filter ( ( proposal ) =>
166
- proposal . cancelled . some ( ( vote ) => vote . equals ( walletPublicKey ) )
37
+ case ProgramType . PYTH_LAZER :
38
+ return (
39
+ < PythLazerProposals
40
+ proposalPubkey = { proposalPubkey }
41
+ onBackToProposals = { handleClickBackToProposals }
42
+ />
167
43
)
168
- }
169
- case 'notVoted' : {
170
- return proposalsFilteredByStatus . filter ( ( proposal ) =>
171
- [
172
- ...proposal . approved ,
173
- ...proposal . rejected ,
174
- ...proposal . cancelled ,
175
- ] . every ( ( vote ) => ! vote . equals ( walletPublicKey ) )
176
- )
177
- }
44
+ default :
45
+ return < div > Unknown program type</ div >
178
46
}
179
- } else {
180
- return proposalsFilteredByStatus
47
+ } catch ( error ) {
48
+ console . error ( 'Error rendering program component:' , error )
49
+ return < div > An error occurred loading the program component</ div >
181
50
}
182
- } , [ proposalsFilteredByStatus , walletPublicKey , voteStatus ] )
51
+ }
183
52
184
53
return (
185
54
< div className = "relative" >
186
55
< div className = "container flex flex-col items-center justify-between lg:flex-row" >
187
56
< div className = "mb-4 w-full text-left lg:mb-0" >
188
57
< h1 className = "h1 mb-4" >
189
- { proposalType === 'priceFeed' ? 'Price Feed ' : 'Governance ' } { ' ' }
190
58
{ router . query . proposal === undefined ? 'Proposals' : 'Proposal' }
191
59
</ h1 >
192
60
</ div >
193
61
</ div >
194
62
< div className = "container min-h-[50vh]" >
195
- { router . query . proposal === undefined ? (
196
- < >
197
- < div className = "flex flex-col justify-between md:flex-row" >
198
- < div className = "mb-4 flex items-center md:mb-0" >
199
- < div className = "flex space-x-4 items-center" >
200
- < ProgramSwitch />
201
- < ClusterSwitch />
202
- </ div >
203
- </ div >
204
- < div className = "flex space-x-2" >
205
- { refreshData && (
206
- < button
207
- disabled = { isMultisigLoading }
208
- className = "sub-action-btn text-base"
209
- onClick = { ( ) => {
210
- const { fetchData } = refreshData ( )
211
- fetchData ( )
212
- } }
213
- >
214
- Refresh
215
- </ button >
216
- ) }
217
- < button
218
- disabled = { isMultisigLoading }
219
- className = "action-btn text-base"
220
- onClick = { switchProposalType }
221
- >
222
- Show
223
- { proposalType !== 'priceFeed'
224
- ? ' Price Feed '
225
- : ' Governance ' }
226
- Proposals
227
- </ button >
228
- </ div >
229
- </ div >
230
- < div className = "relative mt-6" >
231
- { isMultisigLoading ? (
232
- < div className = "mt-3" >
233
- < Loadbar theme = "light" />
234
- </ div >
235
- ) : (
236
- < >
237
- < div className = "flex items-end md:flex-row-reverse justify-between pb-4" >
238
- < div className = "flex flex-col md:flex-row md:items-center gap-4 text-sm" >
239
- { walletPublicKey && (
240
- < Select
241
- label = "Your Vote"
242
- value = { voteStatus }
243
- options = { VOTE_STATUSES }
244
- onChange = { setVoteStatus }
245
- />
246
- ) }
247
- < Select
248
- label = "Proposal Status"
249
- value = { statusFilter }
250
- options = { PROPOSAL_STATUS_FILTERS }
251
- onChange = { setStatusFilter }
252
- />
253
- </ div >
254
- < h4 className = "h4" >
255
- Total Proposals: { filteredProposals . length }
256
- </ h4 >
257
- </ div >
258
- { filteredProposals . length > 0 ? (
259
- < div className = "flex flex-col" >
260
- { filteredProposals . map ( ( proposal , _idx ) => (
261
- < ProposalRow
262
- key = { proposal . publicKey . toBase58 ( ) }
263
- proposal = { proposal }
264
- multisig = { multisigAccount }
265
- />
266
- ) ) }
267
- </ div >
268
- ) : (
269
- < div className = "mt-4" >
270
- No proposals found. If you're a member of the
271
- multisig, you can create a proposal.
272
- </ div >
273
- ) }
274
- </ >
275
- ) }
276
- </ div >
277
- </ >
278
- ) : ! isMultisigLoading && currentProposal !== undefined ? (
279
- < >
280
- < div
281
- className = "max-w-fit cursor-pointer bg-darkGray2 p-3 text-xs font-semibold outline-none transition-colors hover:bg-darkGray3 md:text-base"
282
- onClick = { handleClickBackToProposals }
283
- >
284
- ← back to proposals
285
- </ div >
286
- < div className = "relative mt-6" >
287
- < Proposal proposal = { currentProposal } multisig = { multisigAccount } />
288
- </ div >
289
- </ >
290
- ) : (
291
- < div className = "mt-3" >
292
- < Loadbar theme = "light" />
63
+ < div className = "mb-4 md:mb-0" >
64
+ < div className = "flex space-x-4 mb-4 items-center" >
65
+ < ProgramSwitch />
293
66
</ div >
294
- ) }
67
+ </ div >
68
+ { renderProgramComponent ( ) }
295
69
</ div >
296
70
</ div >
297
71
)
0 commit comments