1
1
import { InfoCircleOutlined } from '@ant-design/icons' ;
2
- import { Button , Flex , Space , Statistic , Table , Tooltip , Typography } from 'antd' ;
2
+ import {
3
+ Button ,
4
+ Flex ,
5
+ Modal ,
6
+ notification ,
7
+ Space ,
8
+ Statistic ,
9
+ Table ,
10
+ Tooltip ,
11
+ Typography ,
12
+ } from 'antd' ;
3
13
import { ColumnsType } from 'antd/es/table' ;
4
14
import { Dispatch , SetStateAction , useEffect , useMemo , useState } from 'react' ;
5
15
import styled from 'styled-components' ;
@@ -10,7 +20,13 @@ import { CHAIN_NAMES, RETAINER_ADDRESS } from 'libs/util-constants/src';
10
20
11
21
import { getBytes32FromAddress } from 'common-util/functions/addresses' ;
12
22
import { NextWeekTooltip } from 'components/NextWeekTooltip' ;
13
- import { useAppSelector } from 'store/index' ;
23
+ import { useAppDispatch , useAppSelector } from 'store/index' ;
24
+ import { Address } from 'viem' ;
25
+ import { useAccount } from 'wagmi' ;
26
+ import { voteForNomineeWeights } from 'common-util/functions' ;
27
+ import { queryClient } from 'context/Web3ModalProvider' ;
28
+ import { INVALIDATE_AFTER_UPDATE_KEYS } from 'common-util/constants/scopeKeys' ;
29
+ import { clearState } from 'store/govern' ;
14
30
15
31
const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000 ;
16
32
const TEN_DAYS_IN_MS = 10 * ONE_DAY_IN_MS ;
@@ -93,10 +109,18 @@ type VotesProps = {
93
109
} ;
94
110
95
111
export const Votes = ( { setIsUpdating, setAllocations } : VotesProps ) => {
112
+ const dispatch = useAppDispatch ( ) ;
96
113
const { stakingContracts } = useAppSelector ( ( state ) => state . govern ) ;
97
114
const { lastUserVote, userVotes } = useAppSelector ( ( state ) => state . govern ) ;
115
+ const { address : account } = useAccount ( ) ;
98
116
const [ votesBlocked , setVotesBlocked ] = useState ( false ) ;
99
117
118
+ const [ isResetModalOpen , setIsResetModalOpen ] = useState ( false ) ;
119
+ const [ isResetLoading , setIsResetLoading ] = useState ( false ) ;
120
+
121
+ const showResetModal = ( ) => setIsResetModalOpen ( true ) ;
122
+ const closeResetModal = ( ) => setIsResetModalOpen ( false ) ;
123
+
100
124
useEffect ( ( ) => {
101
125
setVotesBlocked ( lastUserVote !== null ? lastUserVote + TEN_DAYS_IN_MS > Date . now ( ) : false ) ;
102
126
} , [ lastUserVote ] ) ;
@@ -119,6 +143,57 @@ export const Votes = ({ setIsUpdating, setAllocations }: VotesProps) => {
119
143
) ;
120
144
} ;
121
145
146
+ const resetAllWeights = async ( ) => {
147
+ if ( ! account ) return ;
148
+
149
+ setIsResetLoading ( true ) ;
150
+
151
+ const nominees : Address [ ] = [ ] ;
152
+ const chainIds : number [ ] = [ ] ;
153
+ const weights : string [ ] = [ ] ;
154
+
155
+ Object . keys ( userVotes ) . forEach ( ( address ) => {
156
+ const contract = stakingContracts . find ( ( contract ) => contract . address === address ) ;
157
+ if ( contract ) {
158
+ // Set each staking contract's weight to 0
159
+ nominees . push ( contract . address ) ;
160
+ chainIds . push ( contract . chainId ) ;
161
+ weights . push ( '0' ) ;
162
+ } else if ( address === getBytes32FromAddress ( RETAINER_ADDRESS ) ) {
163
+ // set the retainer's weight to 0
164
+ nominees . push ( getBytes32FromAddress ( RETAINER_ADDRESS ) ) ;
165
+ chainIds . push ( 1 ) ;
166
+ weights . push ( '0' ) ;
167
+ }
168
+ } ) ;
169
+
170
+ // Vote
171
+ voteForNomineeWeights ( { account, nominees, chainIds, weights } )
172
+ . then ( ( ) => {
173
+ closeResetModal ( ) ;
174
+ notification . success ( {
175
+ message : 'Your votes have been reset' ,
176
+ } ) ;
177
+
178
+ // Reset previously saved data so it's re-fetched automatically
179
+ queryClient . removeQueries ( {
180
+ predicate : ( query ) =>
181
+ INVALIDATE_AFTER_UPDATE_KEYS . includes (
182
+ ( query . queryKey [ 1 ] as Record < string , string > ) ?. scopeKey ,
183
+ ) ,
184
+ } ) ;
185
+ dispatch ( clearState ( ) ) ;
186
+ } )
187
+ . catch ( ( error ) => {
188
+ notification . error ( {
189
+ message : error . message ,
190
+ } ) ;
191
+ } )
192
+ . finally ( ( ) => {
193
+ setIsResetLoading ( false ) ;
194
+ } ) ;
195
+ } ;
196
+
122
197
const unblockVoting = ( ) => setVotesBlocked ( false ) ;
123
198
const deadline = lastUserVote ? lastUserVote + TEN_DAYS_IN_MS : undefined ;
124
199
@@ -157,34 +232,59 @@ export const Votes = ({ setIsUpdating, setAllocations }: VotesProps) => {
157
232
} , [ userVotes , stakingContracts ] ) ;
158
233
159
234
return (
160
- < VotesRoot >
161
- < Flex gap = { 16 } align = "center" justify = "end" >
162
- { votesBlocked && lastUserVote !== null && (
163
- < Text type = "secondary" >
164
- < Countdown
165
- prefix = { < Text type = "secondary" > Cooldown period: </ Text > }
166
- format = {
167
- deadline && deadline < Date . now ( ) + ONE_DAY_IN_MS
168
- ? 'H[h] m[m] s[s]'
169
- : 'D[d] H[h] m[m]'
170
- }
171
- value = { deadline }
172
- onFinish = { unblockVoting }
173
- />
174
- </ Text >
175
- ) }
176
- < Button size = "large" type = "primary" disabled = { votesBlocked } onClick = { startEditing } >
177
- Update voting weight
178
- </ Button >
179
- </ Flex >
180
- < Table < MyVote >
181
- className = "mt-16"
182
- columns = { columns }
183
- dataSource = { data }
184
- pagination = { false }
185
- rowClassName = { rowClassName }
186
- rowKey = { ( record ) => record . address || record . name }
187
- />
188
- </ VotesRoot >
235
+ < >
236
+ < VotesRoot >
237
+ < Flex gap = { 16 } align = "center" justify = "space-between" >
238
+ { votesBlocked && lastUserVote !== null && (
239
+ < Text type = "secondary" >
240
+ < Countdown
241
+ prefix = { < Text type = "secondary" > Cooldown period: </ Text > }
242
+ format = {
243
+ deadline && deadline < Date . now ( ) + ONE_DAY_IN_MS
244
+ ? 'H[h] m[m] s[s]'
245
+ : 'D[d] H[h] m[m]'
246
+ }
247
+ value = { deadline }
248
+ onFinish = { unblockVoting }
249
+ />
250
+ </ Text >
251
+ ) }
252
+ < Flex gap = { 8 } >
253
+ < Button size = "large" disabled = { votesBlocked } onClick = { showResetModal } >
254
+ Reset all weights
255
+ </ Button >
256
+ < Button size = "large" type = "primary" disabled = { votesBlocked } onClick = { startEditing } >
257
+ Update voting weight
258
+ </ Button >
259
+ </ Flex >
260
+ </ Flex >
261
+ < Table < MyVote >
262
+ className = "mt-16"
263
+ columns = { columns }
264
+ dataSource = { data }
265
+ pagination = { false }
266
+ rowClassName = { rowClassName }
267
+ rowKey = { ( record ) => record . address || record . name }
268
+ />
269
+ </ VotesRoot >
270
+ < Modal
271
+ title = "Reset all weights"
272
+ open = { isResetModalOpen }
273
+ onOk = { resetAllWeights }
274
+ onCancel = { closeResetModal }
275
+ cancelText = "Cancel"
276
+ okText = "Reset all weights"
277
+ confirmLoading = { isResetLoading }
278
+ >
279
+ < Paragraph >
280
+ This will seize all your voting weight, including unallocated ones applied to the Rollover
281
+ Pool.
282
+ </ Paragraph >
283
+ < Paragraph >
284
+ After you confirm, you’ll enter a 10 day cooldown period. You won't be able to update
285
+ your weights during that time.
286
+ </ Paragraph >
287
+ </ Modal >
288
+ </ >
189
289
) ;
190
290
} ;
0 commit comments