diff --git a/apps/govern/common-util/functions/requests.ts b/apps/govern/common-util/functions/requests.ts
index a9c27cc7..228b6cc5 100644
--- a/apps/govern/common-util/functions/requests.ts
+++ b/apps/govern/common-util/functions/requests.ts
@@ -12,7 +12,7 @@ import { SUPPORTED_CHAINS, wagmiConfig } from 'common-util/config/wagmi';
import { RPC_URLS } from 'common-util/constants/rpcs';
import { getAddressFromBytes32 } from './addresses';
-import { getStartOfNextWeekTimestamp } from './time';
+import { getUnixNextWeekStartTimestamp } from './time';
import { getVoteWeightingContract } from './web3';
type VoteForNomineeWeightsParams = {
@@ -109,7 +109,7 @@ export const checkLockExpired = async (account: Address) => {
args: [account],
});
- const nextWeek = getStartOfNextWeekTimestamp();
+ const nextWeek = getUnixNextWeekStartTimestamp();
return result ? nextWeek >= (result as number) : false;
};
diff --git a/apps/govern/common-util/functions/time.ts b/apps/govern/common-util/functions/time.ts
index 4838358f..b2629f4b 100644
--- a/apps/govern/common-util/functions/time.ts
+++ b/apps/govern/common-util/functions/time.ts
@@ -1,23 +1,27 @@
-export const getStartOfNextWeekTimestamp = () => {
- const date = new Date();
- const dayOfWeek = date.getDay();
- const daysUntilNextWeek = dayOfWeek === 1 ? 7 : (8 - dayOfWeek) % 7;
+// Returns the closest Thursday in the future
+// which is the start of the next week by Unix time
+export const getUnixNextWeekStartTimestamp = () => {
+ const now = new Date();
+ const dayOfWeek = now.getDay();
+ const daysUntilNextThursday = (4 - dayOfWeek + 7) % 7;
- const nextWeekStartDate = new Date(date);
- nextWeekStartDate.setDate(date.getDate() + daysUntilNextWeek);
- nextWeekStartDate.setHours(0, 0, 0, 0);
+ const result = new Date(now);
+ result.setDate(now.getDate() + daysUntilNextThursday);
+ result.setHours(0, 0, 0, 0);
- return nextWeekStartDate.getTime() / 1000;
+ return result.getTime() / 1000;
};
-export const getThisWeekMondayTimestamp = () => {
+// Returns the closest Thursday in the past
+// which is the start of the current week by Unix time
+export const getUnixWeekStartTimestamp = () => {
const now = new Date();
const dayOfWeek = now.getDay();
- const daysToMonday = (dayOfWeek + 6) % 7;
- const monday = new Date(now);
+ const daysSinceThursday = ((dayOfWeek + 2) % 7) + 1;
+ const result = new Date(now);
- monday.setDate(now.getDate() - daysToMonday);
- monday.setHours(0, 0, 0, 0);
+ result.setDate(now.getDate() - daysSinceThursday);
+ result.setHours(0, 0, 0, 0);
- return monday.getTime() / 1000;
+ return result.getTime() / 1000;
};
diff --git a/apps/govern/components/Contracts/ContractsList.spec.tsx b/apps/govern/components/Contracts/ContractsList.spec.tsx
index 13fab168..69a0766c 100644
--- a/apps/govern/components/Contracts/ContractsList.spec.tsx
+++ b/apps/govern/components/Contracts/ContractsList.spec.tsx
@@ -89,11 +89,11 @@ describe('', () => {
// current weight column
expect(screen.getByText(/10.12%/)).toBeInTheDocument();
- expect(screen.getByText(/298.8k veOlas/)).toBeInTheDocument();
+ expect(screen.getByText(/298.8k veOLAS/)).toBeInTheDocument();
// next weight column
expect(screen.getByText(/25.56%/)).toBeInTheDocument();
- expect(screen.getByText(/297.4k veOlas/)).toBeInTheDocument();
+ expect(screen.getByText(/297.4k veOLAS/)).toBeInTheDocument();
});
describe('Already voted', () => {
diff --git a/apps/govern/components/Contracts/ContractsList.tsx b/apps/govern/components/Contracts/ContractsList.tsx
index e4082b66..5e7870b2 100644
--- a/apps/govern/components/Contracts/ContractsList.tsx
+++ b/apps/govern/components/Contracts/ContractsList.tsx
@@ -1,5 +1,5 @@
import { CheckOutlined, InfoCircleOutlined, PlusOutlined } from '@ant-design/icons';
-import { Button, Card as CardAntd, Space, Table, Tooltip, Typography } from 'antd';
+import { Button, Card as CardAntd, Space, Table, Typography } from 'antd';
import { ColumnsType } from 'antd/es/table';
import styled from 'styled-components';
import { Allocation, StakingContract } from 'types';
@@ -9,20 +9,12 @@ import { COLOR } from 'libs/ui-theme/src';
import { CHAIN_NAMES } from 'libs/util-constants/src';
import { formatWeiBalance } from 'common-util/functions/balance';
+import { NextWeekTooltip } from 'components/NextWeekTooltip';
import { useVotingPower } from 'hooks/useVotingPower';
import { useAppSelector } from 'store/index';
const { Title, Paragraph, Text } = Typography;
-const NextWeekTitle = () => (
- Updated voting weights will take effect at the start of next week}
- >
- {"Next week's weight"}
-
-);
-
const Card = styled(CardAntd)`
flex: auto;
`;
@@ -68,18 +60,23 @@ const getColumns = ({
render: (currentWeight) => (
{`${currentWeight?.percentage.toFixed(2)}%`}
- {`${formatWeiBalance(currentWeight?.value)} veOlas`}
+ {`${formatWeiBalance(currentWeight?.value)} veOLAS`}
),
},
{
- title: ,
+ title: (
+
+ Next week's weight
+
+
+ ),
key: 'nextWeight',
dataIndex: 'nextWeight',
render: (nextWeight) => (
{`${nextWeight?.percentage.toFixed(2)}%`}
- {`${formatWeiBalance(nextWeight?.value)} veOlas`}
+ {`${formatWeiBalance(nextWeight?.value)} veOLAS`}
),
},
diff --git a/apps/govern/components/Contracts/MyVotingWeight/MyVotingWeight.tsx b/apps/govern/components/Contracts/MyVotingWeight/MyVotingWeight.tsx
index 87ea385d..ebcb9b5d 100644
--- a/apps/govern/components/Contracts/MyVotingWeight/MyVotingWeight.tsx
+++ b/apps/govern/components/Contracts/MyVotingWeight/MyVotingWeight.tsx
@@ -109,7 +109,7 @@ export const MyVotingWeight = ({
return ;
}
- // If the user doesn't have voting power, suggest to get veOlas
+ // If the user doesn't have voting power, suggest to get veOLAS
if (Number(votingPower) === 0) {
return ;
}
diff --git a/apps/govern/components/Contracts/MyVotingWeight/Votes.tsx b/apps/govern/components/Contracts/MyVotingWeight/Votes.tsx
index e85d968f..a0389197 100644
--- a/apps/govern/components/Contracts/MyVotingWeight/Votes.tsx
+++ b/apps/govern/components/Contracts/MyVotingWeight/Votes.tsx
@@ -10,6 +10,7 @@ import { CHAIN_NAMES } from 'libs/util-constants/src';
import { RETAINER_ADDRESS } from 'common-util/constants/addresses';
import { getBytes32FromAddress } from 'common-util/functions/addresses';
+import { NextWeekTooltip } from 'components/NextWeekTooltip';
import { useAppSelector } from 'store/index';
const ONE_DAY_IN_MS = 24 * 60 * 60 * 1000;
@@ -77,12 +78,9 @@ const columns: ColumnsType = [
},
{
title: (
- Updated voting weights will take effect at the start of next week}
- >
+
My updated weight
-
+
),
key: 'nextWeight',
dataIndex: 'nextWeight',
@@ -156,7 +154,10 @@ export const Votes = ({ setIsUpdating, setAllocations }: VotesProps) => {
isRetainer: true,
});
}
- return res;
+ return res.sort((item) =>
+ // put Rollover address at the end
+ item.address === getBytes32FromAddress(RETAINER_ADDRESS) ? 1 : -1,
+ );
}, []);
}, [userVotes, stakingContracts]);
diff --git a/apps/govern/components/NextWeekTooltip.tsx b/apps/govern/components/NextWeekTooltip.tsx
new file mode 100644
index 00000000..60f5cc55
--- /dev/null
+++ b/apps/govern/components/NextWeekTooltip.tsx
@@ -0,0 +1,36 @@
+import { Space, Tooltip, Typography } from 'antd';
+import { ReactNode } from 'react';
+import { mainnet } from 'viem/chains';
+
+import { COLOR } from 'libs/ui-theme/src';
+import { UNICODE_SYMBOLS } from 'libs/util-constants/src';
+import { VOTE_WEIGHTING } from 'libs/util-contracts/src/lib/abiAndAddresses';
+
+const { Text } = Typography;
+
+const TOOLTIP_STYLE = { maxWidth: '350px' };
+
+export const NextWeekTooltip = ({ children }: { children: ReactNode }) => {
+ return (
+
+ Updated voting weights will take effect at the start of next week Unix time.
+
+ {`View timestamp when the last votes apply ${UNICODE_SYMBOLS.EXTERNAL_LINK}`}
+
+
+ }
+ >
+ {children}
+
+ );
+};
diff --git a/apps/govern/hooks/useFetchStakingContractsList.ts b/apps/govern/hooks/useFetchStakingContractsList.ts
index 42307b42..df8d80da 100644
--- a/apps/govern/hooks/useFetchStakingContractsList.ts
+++ b/apps/govern/hooks/useFetchStakingContractsList.ts
@@ -1,11 +1,14 @@
import { useEffect } from 'react';
import { StakingContract } from 'types';
-import { useBlock } from 'wagmi';
+import { Address } from 'viem';
+import { mainnet } from 'viem/chains';
+import { useReadContract } from 'wagmi';
+
+import { VOTE_WEIGHTING } from 'libs/util-contracts/src/lib/abiAndAddresses';
import { RETAINER_ADDRESS } from 'common-util/constants/addresses';
-import { LATEST_BLOCK_KEY, NEXT_RELATIVE_WEIGHTS_KEY } from 'common-util/constants/scopeKeys';
+import { NEXT_RELATIVE_WEIGHTS_KEY } from 'common-util/constants/scopeKeys';
import { getBytes32FromAddress } from 'common-util/functions';
-import { getStartOfNextWeekTimestamp } from 'common-util/functions/time';
import { setStakingContracts } from 'store/govern';
import { useAppDispatch, useAppSelector } from 'store/index';
@@ -13,6 +16,15 @@ import { useNominees } from './useNominees';
import { useNomineesMetadata } from './useNomineesMetadata';
import { useNomineesWeights } from './useNomineesWeights';
+const WEEK_IN_SECONDS = 604_800;
+
+const getCurrentWeightTimestamp = (timeSum: number | undefined) => {
+ if (!timeSum) return null;
+ // If timeSum is in the future, subtract a week from it
+ if (timeSum * 1000 > Date.now()) return timeSum - WEEK_IN_SECONDS;
+ return timeSum;
+};
+
export const useFetchStakingContractsList = () => {
const dispatch = useAppDispatch();
const { stakingContracts } = useAppSelector((state) => state.govern);
@@ -20,17 +32,28 @@ export const useFetchStakingContractsList = () => {
// Get nominees list
const { data: nominees } = useNominees();
- const { data: block } = useBlock({ blockTag: 'latest', scopeKey: LATEST_BLOCK_KEY });
- const now = block ? Number(block.timestamp) : null;
- const nextWeek = block ? getStartOfNextWeekTimestamp() : null;
+ // Get last scheduled time (next week) from the contract
+ // Has the timestamp when the last votes should be applied
+ const { data: timeSum } = useReadContract({
+ address: (VOTE_WEIGHTING.addresses as Record)[mainnet.id],
+ abi: VOTE_WEIGHTING.abi,
+ chainId: mainnet.id,
+ functionName: 'timeSum',
+ query: {
+ select: (data) => Number(data),
+ },
+ });
- // Get contracts current weight
- const { data: currentWeight } = useNomineesWeights(nominees || [], now);
+ // Get contracts current week weights
+ const { data: currentWeight } = useNomineesWeights(
+ nominees || [],
+ getCurrentWeightTimestamp(timeSum),
+ );
- // Get contracts next weight
+ // Get contracts next week weights
const { data: nextWeight } = useNomineesWeights(
nominees || [],
- nextWeek,
+ timeSum || null,
NEXT_RELATIVE_WEIGHTS_KEY,
);
diff --git a/apps/govern/hooks/useFetchUserVotes.ts b/apps/govern/hooks/useFetchUserVotes.ts
index 584cd247..39a5901d 100644
--- a/apps/govern/hooks/useFetchUserVotes.ts
+++ b/apps/govern/hooks/useFetchUserVotes.ts
@@ -3,7 +3,7 @@ import { UserVotes } from 'types';
import { useAccount, useBlock } from 'wagmi';
import { LATEST_BLOCK_KEY, NEXT_USERS_SLOPES_KEY } from 'common-util/constants/scopeKeys';
-import { getThisWeekMondayTimestamp } from 'common-util/functions/time';
+import { getUnixWeekStartTimestamp } from 'common-util/functions/time';
import { setLastUserVote, setUserVotes } from 'store/govern';
import { useAppDispatch, useAppSelector } from 'store/index';
@@ -16,12 +16,13 @@ import { useVoteUserSlopes } from './useVoteUserSlopes';
const SECONDS_PER_BLOCK = 12;
const CONTRACT_DEPLOY_BLOCK = 20312875;
-// Current votes are those that have been applied at the start of the week
+// Current votes are those that have been applied at the start of the week (unix time)
const getCurrentVotesBlock = (blockNumber: bigint, blockTimestamp: bigint) => {
const mondayBlock =
Number(blockNumber) -
- // Approx number of blocks between current timestamp and this Monday
- Math.round((Number(blockTimestamp) - getThisWeekMondayTimestamp()) / SECONDS_PER_BLOCK);
+ // Approximate number of blocks between the current timestamp and
+ // the start of the current week by Unix time
+ Math.round((Number(blockTimestamp) - getUnixWeekStartTimestamp()) / SECONDS_PER_BLOCK);
return BigInt(Math.max(CONTRACT_DEPLOY_BLOCK, mondayBlock));
};
diff --git a/libs/common-middleware/src/lib/cspHeader.ts b/libs/common-middleware/src/lib/cspHeader.ts
index 44b2a302..0b349f1f 100644
--- a/libs/common-middleware/src/lib/cspHeader.ts
+++ b/libs/common-middleware/src/lib/cspHeader.ts
@@ -64,6 +64,9 @@ const ALLOWED_ORIGINS = [
// tenderly
'https://virtual.mainnet.rpc.tenderly.co/',
+ 'https://virtual.gnosis.rpc.tenderly.co/',
+ 'https://virtual.polygon.rpc.tenderly.co/',
+ 'https://rpc.tenderly.co/fork/',
// others
'https://api.thegraph.com/',