diff --git a/governance/cypress/cypress/e2e/Councils - Voting.e2e.js b/governance/cypress/cypress/e2e/Councils - Voting.e2e.js
index ceb9f874f..503d86acc 100644
--- a/governance/cypress/cypress/e2e/Councils - Voting.e2e.js
+++ b/governance/cypress/cypress/e2e/Councils - Voting.e2e.js
@@ -34,10 +34,7 @@ it('Councils - Administration', () => {
cy.get(
'[data-cy="user-blockies-council-tabs-0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"]'
).should('exist');
- cy.reload();
- cy.get(
- '[data-cy="user-blockies-council-tabs-0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"]'
- ).should('exist');
+
cy.get('[data-cy="selected-badge-my-row"]').should('exist');
cy.wait(3000);
cy.get('[data-cy="my-votes-voting-power"]').contains('30.00');
diff --git a/governance/ui/src/components/CouncilNominees/CouncilNominees.tsx b/governance/ui/src/components/CouncilNominees/CouncilNominees.tsx
index 4a6715258..7dfa69a29 100644
--- a/governance/ui/src/components/CouncilNominees/CouncilNominees.tsx
+++ b/governance/ui/src/components/CouncilNominees/CouncilNominees.tsx
@@ -49,7 +49,8 @@ export default function CouncilNominees({ activeCouncil }: { activeCouncil: Coun
const { state } = useVoteContext();
const currentSelectedUser = getVoteSelectionState(
state,
- epochId,
+ activeWallet?.address,
+ epochId?.toString(),
network?.id.toString(),
activeCouncil
);
diff --git a/governance/ui/src/components/CouncilTabs/CouncilTabs.tsx b/governance/ui/src/components/CouncilTabs/CouncilTabs.tsx
index 82ebdf3d9..4a7f6c95f 100644
--- a/governance/ui/src/components/CouncilTabs/CouncilTabs.tsx
+++ b/governance/ui/src/components/CouncilTabs/CouncilTabs.tsx
@@ -11,6 +11,7 @@ import {
useGetUserBallot,
useNetwork,
useGetEpochIndex,
+ useWallet,
} from '../../queries';
import { ProfilePicture } from '../UserProfileCard/ProfilePicture';
import { ArrowBackIcon, ArrowForwardIcon } from '@chakra-ui/icons';
@@ -21,6 +22,7 @@ import { getVoteSelectionState } from '../../utils/localstorage';
export default function CouncilTabs({ activeCouncil }: { activeCouncil: CouncilSlugs }) {
const { data: councilPeriod } = useGetCurrentPeriod(activeCouncil);
const location = useLocation();
+ const { activeWallet } = useWallet();
const isInMyVotesPage = location.pathname.includes('my-votes');
const isInMyProfilePage = location.pathname.includes('profile');
const { data: schedule, isLoading } = useGetEpochSchedule(activeCouncil);
@@ -28,7 +30,12 @@ export default function CouncilTabs({ activeCouncil }: { activeCouncil: CouncilS
const { data: epochId } = useGetEpochIndex(activeCouncil);
const { state } = useVoteContext();
// @dev dont put activeCounil in here cause its always spartan for the timer
- const networkForState = getVoteSelectionState(state, epochId, network?.id.toString());
+ const networkForState = getVoteSelectionState(
+ state,
+ activeWallet?.address,
+ epochId?.toString(),
+ network?.id.toString()
+ );
const votedNomineesData = [
useGetUserBallot('spartan'),
@@ -88,7 +95,6 @@ export default function CouncilTabs({ activeCouncil }: { activeCouncil: CouncilS
Back to Councils
) : (
- // If on my votes page, spartan council is active by default for navigation
<>
{councilPeriod === '2' && utils.isAddress(newVoteCast || '') ? (
-
+ <>
+
+ {userInformation[index]?.userInformation?.address
+ ? newVoteCast?.toLowerCase() !==
+ userInformation[index]?.userInformation?.address?.toLowerCase() && (
+ <>
+
+
+ >
+ )
+ : null}
+ >
) : (
councilPeriod === '2' && (
<>
@@ -178,6 +200,7 @@ export default function CouncilTabs({ activeCouncil }: { activeCouncil: CouncilS
address={userInformation[index].userInformation?.address}
size={9}
newVoteCast={newVoteCast}
+ isCouncilTabs
/>
)}
diff --git a/governance/ui/src/components/MyVoteRow/MyVoteRow.tsx b/governance/ui/src/components/MyVoteRow/MyVoteRow.tsx
index 94e998e20..896aec577 100644
--- a/governance/ui/src/components/MyVoteRow/MyVoteRow.tsx
+++ b/governance/ui/src/components/MyVoteRow/MyVoteRow.tsx
@@ -4,7 +4,7 @@ import { AddIcon, ArrowForwardIcon, CloseIcon } from '@chakra-ui/icons';
import { useNavigate } from 'react-router-dom';
import CouncilUser from '../CouncilUser/CouncilUser';
import { useVoteContext } from '../../context/VoteContext';
-import { useGetEpochIndex, useGetUserBallot, useNetwork } from '../../queries';
+import { useGetEpochIndex, useGetUserBallot, useNetwork, useWallet } from '../../queries';
import { getVoteSelectionState } from '../../utils/localstorage';
import { Badge } from '../Badge';
@@ -18,6 +18,7 @@ export default function MyVoteRow({
isLast: boolean;
}) {
const navigate = useNavigate();
+ const { activeWallet } = useWallet();
const { data: ballot } = useGetUserBallot(councilSlug);
const { data: epochId } = useGetEpochIndex(councilSlug);
const { dispatch, state } = useVoteContext();
@@ -25,13 +26,13 @@ export default function MyVoteRow({
const networkForState = getVoteSelectionState(
state,
- epochId,
+ activeWallet?.address,
+ epochId?.toString(),
network?.id.toString(),
councilSlug
);
const voteAddressState = typeof networkForState === 'string' ? networkForState : '';
-
return (
- {ballot?.votedCandidates[0] && networkForState === 'remove' && (
- <>
-
-
- >
- )}
+ {ballot?.votedCandidates[0] &&
+ voteAddressState &&
+ ballot.votedCandidates[0].toLowerCase() !== voteAddressState.toLowerCase() && (
+ <>
+
+
+ >
+ )}
{ballot?.votedCandidates.includes(voteAddressState) ? (
Your Vote
@@ -95,7 +98,8 @@ export default function MyVoteRow({
payload: {
action: 'remove',
network: network.id.toString(),
- epochId,
+ epochId: epochId?.toString(),
+ wallet: activeWallet?.address,
},
});
} else {
@@ -104,7 +108,8 @@ export default function MyVoteRow({
payload: {
action: networkForState === 'remove' ? 'remove' : undefined,
network: network.id.toString(),
- epochId,
+ epochId: epochId?.toString(),
+ wallet: activeWallet?.address,
},
});
}
diff --git a/governance/ui/src/components/MyVotesSummary/MyVotesSummary.tsx b/governance/ui/src/components/MyVotesSummary/MyVotesSummary.tsx
index aed2eed0a..aab329e3c 100644
--- a/governance/ui/src/components/MyVotesSummary/MyVotesSummary.tsx
+++ b/governance/ui/src/components/MyVotesSummary/MyVotesSummary.tsx
@@ -5,7 +5,7 @@ import MyVotesBox from '../MyVotesBox/MyVotesBox';
import { useNavigate } from 'react-router-dom';
import councils from '../../utils/councils';
import { useVoteContext, VoteStateForNetwork } from '../../context/VoteContext';
-import { useGetEpochIndex, useNetwork } from '../../queries';
+import { useGetEpochIndex, useNetwork, useWallet } from '../../queries';
import { voteCardState } from '../../state/vote-card';
import { useRecoilState } from 'recoil';
import { getVoteSelectionState } from '../../utils/localstorage';
@@ -36,7 +36,13 @@ export const MyVotesSummary = ({
const { network } = useNetwork();
const { data: epochId } = useGetEpochIndex('spartan');
const { state } = useVoteContext();
- const networkForState = getVoteSelectionState(state, epochId, network?.id.toString());
+ const { activeWallet } = useWallet();
+ const networkForState = getVoteSelectionState(
+ state,
+ activeWallet?.address,
+ epochId?.toString(),
+ network?.id.toString()
+ );
const stateFromCouncils = (
typeof networkForState !== 'string' ? networkForState : { spartan: networkForState }
) as VoteStateForNetwork;
diff --git a/governance/ui/src/components/UserProfileCard/UserProfileDetails.tsx b/governance/ui/src/components/UserProfileCard/UserProfileDetails.tsx
index a2e56636b..06d6786f1 100644
--- a/governance/ui/src/components/UserProfileCard/UserProfileDetails.tsx
+++ b/governance/ui/src/components/UserProfileCard/UserProfileDetails.tsx
@@ -8,7 +8,7 @@ import { useNavigate } from 'react-router-dom';
import { useVoteContext } from '../../context/VoteContext';
import { ProfilePicture } from './ProfilePicture';
import { EditIcon, ShareIcon } from '../Icons';
-import { useGetEpochIndex, useGetUserBallot, useNetwork } from '../../queries';
+import { useGetEpochIndex, useGetUserBallot, useNetwork, useWallet } from '../../queries';
import { useEffect, useRef, useState } from 'react';
import { useRecoilState } from 'recoil';
import { voteCardState } from '../../state/vote-card';
@@ -32,6 +32,7 @@ export const UserProfileDetails = ({
councilPeriod,
}: UserProfileDetailsProps) => {
const [_, setVoteCard] = useRecoilState(voteCardState);
+ const { activeWallet } = useWallet();
const [tooltipLabel, setTooltipLabel] = useState('Copy Profile Link');
const [walletToolTipLabel, setWalletTooltipLabel] = useState('Copy');
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
@@ -43,11 +44,16 @@ export const UserProfileDetails = ({
const { data: ballot } = useGetUserBallot(activeCouncil);
const elementRef = useRef(null);
const [isOverflowing, setIsOverflowing] = useState(false);
- const networkForState = getVoteSelectionState(state, epochId, network?.id.toString());
+ const networkForState = getVoteSelectionState(
+ state,
+ activeWallet?.address,
+ epochId?.toString(),
+ network?.id.toString(),
+ activeCouncil
+ );
const voteAddressState = typeof networkForState === 'string' ? networkForState : '';
-
const isSelected = voteAddressState
- ? voteAddressState?.toLowerCase() === userData?.address?.toLowerCase()
+ ? voteAddressState?.toLowerCase().trim() === userData?.address?.toLowerCase().trim()
: false;
const isAlreadyVoted =
@@ -293,12 +299,22 @@ export const UserProfileDetails = ({
if (isAlreadyVoted) {
dispatch({
type: activeCouncil.toUpperCase(),
- payload: { action: 'remove', network: parsedNetwork, epochId },
+ payload: {
+ action: 'remove',
+ network: parsedNetwork,
+ epochId: epochId?.toString(),
+ wallet: activeWallet?.address,
+ },
});
} else if (isSelected) {
dispatch({
type: activeCouncil.toUpperCase(),
- payload: { action: undefined, network: parsedNetwork, epochId },
+ payload: {
+ action: undefined,
+ network: parsedNetwork,
+ epochId: epochId?.toString(),
+ wallet: activeWallet?.address,
+ },
});
} else {
dispatch({
@@ -306,7 +322,8 @@ export const UserProfileDetails = ({
payload: {
action: userData?.address.toLowerCase(),
network: parsedNetwork,
- epochId,
+ epochId: epochId?.toString(),
+ wallet: activeWallet?.address,
},
});
}
diff --git a/governance/ui/src/components/UserTableView/UserTableView.tsx b/governance/ui/src/components/UserTableView/UserTableView.tsx
index 71b52d192..03fed4635 100644
--- a/governance/ui/src/components/UserTableView/UserTableView.tsx
+++ b/governance/ui/src/components/UserTableView/UserTableView.tsx
@@ -6,10 +6,9 @@ import { useGetCurrentPeriod } from '../../queries/useGetCurrentPeriod';
import { CouncilSlugs } from '../../utils/councils';
import { ProfilePicture } from '../UserProfileCard/ProfilePicture';
import { prettyString } from '@snx-v3/format';
-import { useGetEpochIndex, useGetUserBallot, useNetwork } from '../../queries';
-import { getVoteSelectionState } from '../../utils/localstorage';
-import { useVoteContext } from '../../context/VoteContext';
-import { BigNumber } from 'ethers';
+import { useGetUserBallot } from '../../queries';
+import { BigNumber, utils } from 'ethers';
+import { formatNumber } from '@snx-v3/formatters';
import { renderCorrectBorder } from '../../utils/table-border';
export default function UserTableView({
@@ -31,20 +30,11 @@ export default function UserTableView({
const { data: ballot } = useGetUserBallot(activeCouncil);
const { data: councilPeriod } = useGetCurrentPeriod(activeCouncil);
const isSelected = searchParams.get('view') === user.address;
- const { network } = useNetwork();
- const { data: epochId } = useGetEpochIndex(activeCouncil);
- const { state } = useVoteContext();
const councilIsInAdminOrVoting = councilPeriod === '2' || councilPeriod === '0';
- const networkForState = getVoteSelectionState(
- state,
- epochId,
- network?.id.toString(),
- activeCouncil
- );
- const voteAddressState = typeof networkForState === 'string' ? networkForState : '';
- const totalVotingPowerPercentage = totalVotingPower
- ? user.voteResult?.votePower.mul(100).div(totalVotingPower).toNumber().toFixed(2)
- : 'N/A';
+ const totalVotingPowerPercentage =
+ totalVotingPower && user.voteResult
+ ? formatNumber(user.voteResult?.votePower.mul(100).div(totalVotingPower).toString())
+ : 'N/A';
return (
{totalVotingPowerPercentage ? totalVotingPowerPercentage + '%' : 'N/A'}
- {totalVotingPowerPercentage ? user.voteResult?.votePower.toString() : '—'}
+ {totalVotingPowerPercentage && user.voteResult
+ ? formatNumber(utils.formatEther(user.voteResult.votePower || '0'))
+ : '—'}
)}
@@ -144,7 +136,7 @@ export default function UserTableView({
fontSize="sm"
fontWeight={700}
>
- {ballot?.votedCandidates.includes(voteAddressState) ? (
+ {ballot?.votedCandidates.includes(user.address) ? (
Your Vote
diff --git a/governance/ui/src/context/VoteContext.tsx b/governance/ui/src/context/VoteContext.tsx
index 8e0827088..fec24a5fe 100644
--- a/governance/ui/src/context/VoteContext.tsx
+++ b/governance/ui/src/context/VoteContext.tsx
@@ -6,7 +6,7 @@ import React, {
useReducer,
useState,
} from 'react';
-import { useGetEpochIndex, useGetUserBallot, useNetwork } from '../queries';
+import { useGetEpochIndex, useGetUserBallot, useNetwork, useWallet } from '../queries';
import { localStorageKey, removeCandidate, setCandidate } from '../utils/localstorage';
export interface VoteStateForNetwork {
@@ -17,26 +17,35 @@ export interface VoteStateForNetwork {
export interface VoteState {
[key: string]: {
- [key: string]: VoteStateForNetwork;
+ [key: string]: {
+ [key: string]: VoteStateForNetwork;
+ };
};
}
type Action = {
type: string;
- payload: { action: string | undefined; network: string | undefined; epochId: string | undefined };
+ payload: {
+ action: string | undefined;
+ network: string | undefined;
+ epochId: string | undefined;
+ wallet: string | undefined;
+ };
};
-const initialState = (chainId?: string, epochId?: string) => {
- if (!epochId || !chainId) return {};
+const initialState = (chainId?: string, epochId?: string, wallet?: string) => {
+ if (!epochId || !chainId || !wallet) return {};
const parsedState = JSON.parse(localStorage.getItem(localStorageKey) || '{}');
return {
- [epochId]: {
- [chainId]: {
- spartan: parsedState[epochId]?.[chainId]?.spartan || undefined,
- ambassador: parsedState[epochId]?.[chainId]?.ambassador || undefined,
- treasury: parsedState[epochId]?.[chainId]?.treasury || undefined,
+ [wallet]: {
+ [epochId]: {
+ [chainId]: {
+ spartan: parsedState[epochId]?.[chainId]?.spartan || undefined,
+ ambassador: parsedState[epochId]?.[chainId]?.ambassador || undefined,
+ treasury: parsedState[epochId]?.[chainId]?.treasury || undefined,
+ },
},
},
} as VoteState;
@@ -56,20 +65,31 @@ const voteReducer = (state: VoteState, action: Action): VoteState => {
if (action.payload.action && action.payload.action !== 'remove') {
setCandidate(
action.payload.action,
+ action.payload.wallet,
'spartan',
action.payload.network,
action.payload.epochId
);
} else {
- removeCandidate('spartan', action.payload.network, action.payload.epochId);
+ removeCandidate(
+ 'spartan',
+ action.payload.wallet,
+ action.payload.network,
+ action.payload.epochId
+ );
}
return {
...state,
- [action.payload.epochId!]: {
- ...(state[action.payload.epochId!] || {}),
- [action.payload.network!]: {
- ...(state[action.payload.epochId!]?.[action.payload.network!] || {}),
- spartan: action.payload.action,
+ [action.payload.wallet!]: {
+ ...(state[action.payload.wallet!] || {}),
+ [action.payload.epochId!]: {
+ ...(state[action.payload.wallet!]?.[action.payload.epochId!] || {}),
+ [action.payload.network!]: {
+ ...(state[action.payload.wallet!]?.[action.payload.epochId!]?.[
+ action.payload.network!
+ ] || {}),
+ spartan: action.payload.action,
+ },
},
},
};
@@ -78,20 +98,31 @@ const voteReducer = (state: VoteState, action: Action): VoteState => {
if (action.payload.action && action.payload.action !== 'remove') {
setCandidate(
action.payload.action,
+ action.payload.wallet,
'ambassador',
action.payload.network,
action.payload.epochId
);
} else {
- removeCandidate('ambassador', action.payload.network, action.payload.epochId);
+ removeCandidate(
+ 'ambassador',
+ action.payload.wallet,
+ action.payload.network,
+ action.payload.epochId
+ );
}
return {
...state,
- [action.payload.epochId!]: {
- ...(state[action.payload.epochId!] || {}),
- [action.payload.network!]: {
- ...(state[action.payload.epochId!]?.[action.payload.network!] || {}),
- ambassador: action.payload.action,
+ [action.payload.wallet!]: {
+ ...(state[action.payload.wallet!] || {}),
+ [action.payload.epochId!]: {
+ ...(state[action.payload.wallet!]?.[action.payload.epochId!] || {}),
+ [action.payload.network!]: {
+ ...(state[action.payload.wallet!]?.[action.payload.epochId!]?.[
+ action.payload.network!
+ ] || {}),
+ ambassador: action.payload.action,
+ },
},
},
};
@@ -100,20 +131,31 @@ const voteReducer = (state: VoteState, action: Action): VoteState => {
if (action.payload.action && action.payload.action !== 'remove') {
setCandidate(
action.payload.action,
+ action.payload.wallet,
'treasury',
action.payload.network,
action.payload.epochId
);
} else {
- removeCandidate('treasury', action.payload.network, action.payload.epochId);
+ removeCandidate(
+ 'treasury',
+ action.payload.wallet,
+ action.payload.network,
+ action.payload.epochId
+ );
}
return {
...state,
- [action.payload.epochId!]: {
- ...(state[action.payload.epochId!] || {}),
- [action.payload.network!]: {
- ...(state[action.payload.epochId!]?.[action.payload.network!] || {}),
- treasury: action.payload.action,
+ [action.payload.wallet!]: {
+ ...(state[action.payload.wallet!] || {}),
+ [action.payload.epochId!]: {
+ ...(state[action.payload.wallet!]?.[action.payload.epochId!] || {}),
+ [action.payload.network!]: {
+ ...(state[action.payload.wallet!]?.[action.payload.epochId!]?.[
+ action.payload.network!
+ ] || {}),
+ treasury: action.payload.action,
+ },
},
},
};
@@ -125,6 +167,7 @@ const voteReducer = (state: VoteState, action: Action): VoteState => {
const VoteProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const { network } = useNetwork();
+ const { activeWallet } = useWallet();
const { data: epochId } = useGetEpochIndex('spartan');
const [init, setInit] = useState(false);
const [state, dispatch] = useReducer(
@@ -147,30 +190,40 @@ const VoteProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
isTreasuryBallotFetched &&
spartanBallot &&
ambassadorBallot &&
- treasuryBallot
+ treasuryBallot &&
+ activeWallet?.address
) {
[spartanBallot, ambassadorBallot, treasuryBallot].forEach((ballot) => {
dispatch({
payload: {
action: ballot?.votedCandidates[0],
network: network.id.toString(),
- epochId,
+ epochId: epochId.toString(),
+ wallet: activeWallet.address,
},
type: ballot.council.toUpperCase(),
});
});
- const initState = initialState(network.id.toString(), epochId);
- const voteStateForNetwork = initState[epochId][network.id.toString()];
+ const initState = initialState(
+ network.id.toString(),
+ epochId.toString(),
+ activeWallet.address
+ );
+ const voteStateForNetwork =
+ initState[activeWallet.address][epochId.toString()][network.id.toString()];
- Object.keys(initState[epochId][network.id.toString()]).forEach((key) => {
+ Object.keys(
+ initState[activeWallet.address][epochId.toString()][network.id.toString()]
+ ).forEach((key) => {
const candidate = voteStateForNetwork[key as keyof VoteStateForNetwork];
if (candidate) {
dispatch({
payload: {
action: candidate,
network: network.id.toString(),
- epochId,
+ epochId: epochId.toString(),
+ wallet: activeWallet.address,
},
type: key.toUpperCase(),
});
@@ -188,6 +241,7 @@ const VoteProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
spartanBallot,
ambassadorBallot,
treasuryBallot,
+ activeWallet?.address,
]);
return {children};
};
diff --git a/governance/ui/src/mutations/useCastVotes.ts b/governance/ui/src/mutations/useCastVotes.ts
index f721eb49e..5b45069bc 100644
--- a/governance/ui/src/mutations/useCastVotes.ts
+++ b/governance/ui/src/mutations/useCastVotes.ts
@@ -133,7 +133,7 @@ export function useCastVotes(
console.error(error);
toast({
title: 'Could not cast votes.',
- description: error && 'message' in error ? error.message : '',
+ description: 'Check the browser console for more information',
status: 'error',
isClosable: true,
});
@@ -157,11 +157,21 @@ export function useCastVotes(
shouldWithdrawVote
? dispatch({
type: council.toUpperCase(),
- payload: { action: undefined, network: network!.id.toString(), epochId },
+ payload: {
+ action: undefined,
+ network: network!.id.toString(),
+ epochId: epochId?.toString(),
+ wallet: activeWallet?.address,
+ },
})
: dispatch({
type: council.toUpperCase(),
- payload: { action: candidates[council], network: network!.id.toString(), epochId },
+ payload: {
+ action: candidates[council],
+ network: network!.id.toString(),
+ epochId: epochId?.toString(),
+ wallet: activeWallet?.address,
+ },
});
});
await Promise.all(
diff --git a/governance/ui/src/pages/MyVotes.tsx b/governance/ui/src/pages/MyVotes.tsx
index 158768304..a7dd94e8a 100644
--- a/governance/ui/src/pages/MyVotes.tsx
+++ b/governance/ui/src/pages/MyVotes.tsx
@@ -17,7 +17,13 @@ import { useGetCurrentPeriod } from '../queries/useGetCurrentPeriod';
import { useGetEpochSchedule } from '../queries/useGetEpochSchedule';
import { Timer } from '../components/Timer';
import CouncilTabs from '../components/CouncilTabs/CouncilTabs';
-import { useGetEpochIndex, useGetUserVotingPower, useNetwork, useWallet } from '../queries/';
+import {
+ useGetEpochIndex,
+ useGetUserBallot,
+ useGetUserVotingPower,
+ useNetwork,
+ useWallet,
+} from '../queries/';
import { useCastVotes } from '../mutations';
import { formatNumber } from '@snx-v3/formatters';
import MyVoteRow from '../components/MyVoteRow/MyVoteRow';
@@ -35,19 +41,45 @@ export default function MyVotes() {
const { data: schedule } = useGetEpochSchedule('spartan');
const { data: epochId } = useGetEpochIndex('spartan');
const { network } = useNetwork();
- const { connect } = useWallet();
+ const { activeWallet, connect } = useWallet();
const { data: votingPowerSpartan } = useGetUserVotingPower('spartan');
const { data: votingPowerAmbassador } = useGetUserVotingPower('ambassador');
const { data: votingPowerTreassury } = useGetUserVotingPower('treasury');
+ const { data: spartanBallot } = useGetUserBallot('spartan');
+ const { data: ambassadorBallot } = useGetUserBallot('ambassador');
+ const { data: treasuryBallot } = useGetUserBallot('treasury');
+ const ballots = {
+ spartan: spartanBallot,
+ ambassador: ambassadorBallot,
+ treasury: treasuryBallot,
+ };
const { state } = useVoteContext();
- const networkForState = getVoteSelectionState(state, epochId, network?.id.toString());
+ const networkForState = getVoteSelectionState(
+ state,
+ activeWallet?.address,
+ epochId?.toString(),
+ network?.id.toString()
+ );
const stateFromCouncils = (
typeof networkForState !== 'string' ? networkForState : {}
) as VoteStateForNetwork;
const councilToCastVote = Object.entries(stateFromCouncils)
- .filter(([_, candidate]) => !!candidate)
+ .filter(([council, candidate]) => {
+ if ((ballots as any)[council].votedCandidates.length) {
+ return !(ballots as any)[council].votedCandidates.includes(candidate);
+ }
+ return !!(stateFromCouncils as any)[council];
+ })
.map(([council]) => council) as CouncilSlugs[];
- const { mutateAsync, isPending } = useCastVotes(councilToCastVote, stateFromCouncils);
+
+ const councilsToAddress = councilToCastVote.reduce(
+ (cur, prev) => {
+ cur[prev] = stateFromCouncils[prev] ?? '';
+ return cur;
+ },
+ {} as Record
+ );
+ const { mutateAsync, isPending } = useCastVotes(councilToCastVote, councilsToAddress);
const navigate = useNavigate();
const formattedVotePower = formatNumber(
votingPowerSpartan?.power && votingPowerAmbassador?.power && votingPowerTreassury?.power
@@ -262,8 +294,8 @@ export default function MyVotes() {
{council.title}
- {stateFromCouncils[council.slug] ? (
-
+ {councilsToAddress[council.slug] ? (
+
) : (
)}
diff --git a/governance/ui/src/queries/useGetEpochIndex.ts b/governance/ui/src/queries/useGetEpochIndex.ts
index e2158b874..52a69a6c2 100644
--- a/governance/ui/src/queries/useGetEpochIndex.ts
+++ b/governance/ui/src/queries/useGetEpochIndex.ts
@@ -3,6 +3,7 @@ import { CouncilSlugs } from '../utils/councils';
import { getCouncilContract } from '../utils/contracts';
import { motherShipProvider } from '../utils/providers';
import { useNetwork } from './useWallet';
+import { BigNumber } from 'ethers';
export function useGetEpochIndex(council: CouncilSlugs) {
const { network } = useNetwork();
@@ -10,9 +11,9 @@ export function useGetEpochIndex(council: CouncilSlugs) {
return useQuery({
queryKey: ['epochId', council, network?.id],
queryFn: async () => {
- return await getCouncilContract(council)
+ return (await getCouncilContract(council)
.connect(motherShipProvider(network?.id || 2192))
- .getEpochIndex();
+ .getEpochIndex()) as BigNumber;
},
staleTime: 900000,
});
diff --git a/governance/ui/src/utils/localstorage.ts b/governance/ui/src/utils/localstorage.ts
index 039fb5158..fbee679bd 100644
--- a/governance/ui/src/utils/localstorage.ts
+++ b/governance/ui/src/utils/localstorage.ts
@@ -5,23 +5,28 @@ export const localStorageKey = 'voteSelection';
export const setCandidate = (
candidate?: string,
+ wallet?: string,
council?: CouncilSlugs,
network?: string,
epochId?: string
) => {
try {
- if (!candidate || !council || !network || !epochId) return;
+ if (!candidate || !council || !network || !epochId || !wallet) return;
const parsedSelection = JSON.parse(localStorage.getItem(localStorageKey) || '{}');
- if (!parsedSelection[epochId]) {
- parsedSelection[epochId] = {};
+ if (!parsedSelection[wallet]) {
+ parsedSelection[wallet] = {};
}
- if (!parsedSelection[epochId][network]) {
- parsedSelection[epochId][network] = {};
+
+ if (!parsedSelection[wallet][epochId]) {
+ parsedSelection[wallet][epochId] = {};
+ }
+ if (!parsedSelection[wallet][epochId][network]) {
+ parsedSelection[wallet][epochId][network] = {};
}
- parsedSelection[epochId][network][council] = candidate;
+ parsedSelection[wallet][epochId][network][council] = candidate;
localStorage.setItem(localStorageKey, JSON.stringify(parsedSelection));
} catch (error) {
@@ -29,24 +34,33 @@ export const setCandidate = (
}
};
-export const removeCandidate = (council?: CouncilSlugs, network?: string, epochId?: string) => {
- if (!council || !network || !epochId) return;
+export const removeCandidate = (
+ council?: CouncilSlugs,
+ wallet?: string,
+ network?: string,
+ epochId?: string
+) => {
+ if (!council || !network || !epochId || !wallet) return;
try {
const parsedSelection = JSON.parse(localStorage.getItem(localStorageKey) || '{}');
if (
- parsedSelection[epochId] &&
- parsedSelection[epochId][network] &&
- parsedSelection[epochId][network][council]
+ parsedSelection[wallet] &&
+ parsedSelection[wallet][epochId] &&
+ parsedSelection[wallet][epochId][network] &&
+ parsedSelection[wallet][epochId][network][council]
) {
- delete parsedSelection[epochId][network][council];
+ delete parsedSelection[wallet][epochId][network][council];
- if (Object.keys(parsedSelection[epochId][network]).length === 0) {
- delete parsedSelection[epochId][network];
+ if (Object.keys(parsedSelection[wallet][epochId][network]).length === 0) {
+ delete parsedSelection[wallet][epochId][network];
+ }
+ if (Object.keys(parsedSelection[wallet][epochId]).length === 0) {
+ delete parsedSelection[wallet][epochId];
}
- if (Object.keys(parsedSelection[epochId]).length === 0) {
- delete parsedSelection[epochId];
+ if (Object.keys(parsedSelection[wallet]).length === 0) {
+ delete parsedSelection[wallet];
}
localStorage.setItem(localStorageKey, JSON.stringify(parsedSelection));
@@ -55,6 +69,7 @@ export const removeCandidate = (council?: CouncilSlugs, network?: string, epochI
console.error(
'Tried to remove address that wasn’t present in local storage: ',
council,
+ wallet,
network,
epochId,
err
@@ -64,30 +79,38 @@ export const removeCandidate = (council?: CouncilSlugs, network?: string, epochI
export const getVoteSelectionState = (
state: VoteState,
+ wallet?: string,
epochId?: string,
networkId?: string,
councilSlug?: CouncilSlugs
) => {
- if (!epochId || !networkId) return '';
-
+ if (!epochId || !networkId || !wallet) return '';
if (councilSlug) {
- return epochId
- ? state[epochId]
- ? networkId
- ? state[epochId][networkId]
- ? state[epochId][networkId][councilSlug]
- ? state[epochId][networkId][councilSlug]
+ return wallet
+ ? state[wallet]
+ ? epochId
+ ? state[wallet][epochId]
+ ? networkId
+ ? state[wallet][epochId][networkId]
+ ? state[wallet][epochId][networkId][councilSlug]
+ ? state[wallet][epochId][networkId][councilSlug]
+ : ''
+ : ''
: ''
: ''
: ''
: ''
: '';
}
- return epochId
- ? state[epochId]
- ? networkId
- ? state[epochId][networkId]
- ? state[epochId][networkId]
+ return wallet
+ ? state[wallet]
+ ? epochId
+ ? state[wallet][epochId]
+ ? networkId
+ ? state[wallet][epochId][networkId]
+ ? state[wallet][epochId][networkId]
+ : ''
+ : ''
: ''
: ''
: ''
diff --git a/governance/ui/src/utils/sort-users.ts b/governance/ui/src/utils/sort-users.ts
index 6ea98e1c4..abd24797a 100644
--- a/governance/ui/src/utils/sort-users.ts
+++ b/governance/ui/src/utils/sort-users.ts
@@ -21,9 +21,9 @@ export const sortUsers = (
if (councilNomineesDetails?.length && votes) {
const candidatesByVotePowerRanking = votes
? Object.keys(votes[activeCouncil]).sort((a, b) => {
- return votes[activeCouncil][b].votePower
- .sub(votes[activeCouncil][a].votePower)
- .toNumber();
+ return votes[activeCouncil][b].votePower.sub(votes[activeCouncil][a].votePower).gt(0)
+ ? 1
+ : -1;
})
: [];
return councilNomineesDetails
@@ -72,15 +72,17 @@ export const sortUsers = (
if (sortConfig[1] === 'votingPower') {
if (sortConfig[0]) {
if (!b.voteResult?.votePower) return -1;
- return b.voteResult?.votePower
- .sub(a.voteResult?.votePower || BigNumber.from(0))
- .toNumber();
+ return b.voteResult?.votePower.sub(a.voteResult?.votePower || BigNumber.from(0)).gt(0)
+ ? 1
+ : -1;
} else {
if (!b.voteResult?.votePower) return 1;
return b.voteResult?.votePower
.sub(a.voteResult?.votePower || BigNumber.from(0))
.mul(-1)
- .toNumber();
+ .gt(0)
+ ? 1
+ : -1;
}
}
if (sortConfig[1] === 'votes') {
@@ -92,9 +94,9 @@ export const sortUsers = (
}
if (sortConfig[1] === 'ranking') {
if (!b.voteResult?.votePower) return -1;
- return b.voteResult?.votePower
- .sub(a.voteResult?.votePower || BigNumber.from(0))
- .toNumber();
+ return b.voteResult?.votePower.sub(a.voteResult?.votePower || BigNumber.from(0)).gt(0)
+ ? 1
+ : -1;
}
return 0;
});