diff --git a/src/custom/pages/Claim/ClaimsTable.tsx b/src/custom/pages/Claim/ClaimsTable.tsx index b5c7f50c9..f1a748fed 100644 --- a/src/custom/pages/Claim/ClaimsTable.tsx +++ b/src/custom/pages/Claim/ClaimsTable.tsx @@ -1,5 +1,11 @@ +import { + ClaimType, + useAirdropDeadline, + useClaimState, + useDeploymentTimestamp, + useInvestmentDeadline, +} from 'state/claim/hooks' import styled from 'styled-components/macro' -import { ClaimType, useClaimState } from 'state/claim/hooks' import { ClaimTable, ClaimBreakdown, TokenLogo } from 'pages/Claim/styled' import CowProtocolLogo from 'components/CowProtocolLogo' import { ClaimStatus } from 'state/claim/actions' @@ -9,6 +15,7 @@ import { EnhancedUserClaimData } from './types' import { useAllClaimingTransactionIndices } from 'state/enhancedTransactions/hooks' import { CustomLightSpinner } from 'theme' import Circle from 'assets/images/blue-loader.svg' +import { Countdown } from 'pages/Claim/Countdown' type ClaimsTableProps = { handleSelectAll: (event: React.ChangeEvent) => void @@ -22,6 +29,8 @@ type ClaimsTableProps = { type ClaimsTableRowProps = EnhancedUserClaimData & Pick & { selected: number[] + start: number | null + end: number | null isPendingClaim: boolean } @@ -50,6 +59,8 @@ const ClaimsTableRow = ({ cost, handleSelect, selected, + start, + end, }: ClaimsTableRowProps) => { return ( @@ -99,7 +110,7 @@ const ClaimsTableRow = ({ Vesting: {type === ClaimType.Airdrop ? 'No' : '4 years (linear)'} - Ends in: 28 days, 10h, 50m + Ends in: {start && end && } @@ -119,6 +130,10 @@ export default function ClaimsTable({ const hideTable = isAirdropOnly || !hasClaims || !activeClaimAccount || claimStatus !== ClaimStatus.DEFAULT || isInvestFlowActive + const start = useDeploymentTimestamp() + const investmentEnd = useInvestmentDeadline() + const airdropEnd = useAirdropDeadline() + if (hideTable) return null return ( @@ -146,6 +161,8 @@ export default function ClaimsTable({ isPendingClaim={pendingClaimsSet.has(claim.index)} selected={selected} handleSelect={handleSelect} + start={start} + end={claim.isFree ? airdropEnd : investmentEnd} /> ))} diff --git a/src/custom/pages/Claim/Countdown.tsx b/src/custom/pages/Claim/Countdown.tsx new file mode 100644 index 000000000..74b15ca16 --- /dev/null +++ b/src/custom/pages/Claim/Countdown.tsx @@ -0,0 +1,67 @@ +// Sort of a mod of but not quite from src/pages/Earn/Countdown.tsx +import { useEffect, useState } from 'react' + +const MINUTE = 60 +const HOUR = MINUTE * 60 +const DAY = HOUR * 24 + +export type Props = { + start: number + end: number +} + +/** + * Copied over from src/pages/Earn/Countdown.tsx and heavily modified it + * + * If current time is past end time, returns null + * + * @param start start time in ms + * @param end end time in ms + */ +export function Countdown({ start, end }: Props) { + // get current time, store as seconds because 🤷 + const [time, setTime] = useState(() => Math.floor(Date.now() / 1000)) + + useEffect((): (() => void) | void => { + // we only need to tick if not ended yet + if (time <= end / 1000) { + const timeout = setTimeout(() => setTime(Math.floor(Date.now() / 1000)), 1000) + return () => { + clearTimeout(timeout) + } + } + }, [time, end]) + + const timeUntilGenesis = start / 1000 - time + const timeUntilEnd = end / 1000 - time + + let timeRemaining: number + if (timeUntilGenesis >= 0) { + timeRemaining = timeUntilGenesis + } else { + const ongoing = timeUntilEnd >= 0 + if (ongoing) { + timeRemaining = timeUntilEnd + } else { + timeRemaining = Infinity + } + } + + const days = (timeRemaining - (timeRemaining % DAY)) / DAY + timeRemaining -= days * DAY + const hours = (timeRemaining - (timeRemaining % HOUR)) / HOUR + timeRemaining -= hours * HOUR + const minutes = (timeRemaining - (timeRemaining % MINUTE)) / MINUTE + timeRemaining -= minutes * MINUTE + const seconds = timeRemaining + + return ( + <> + {Number.isFinite(timeRemaining) + ? `${days} days, ${hours.toString().padStart(2, '0')}h, ${minutes.toString().padStart(2, '0')}m, ${seconds + .toString() + .padStart(2, '0')}s` + : 'No longer claimable'} + + ) +} diff --git a/src/custom/state/claim/hooks/index.ts b/src/custom/state/claim/hooks/index.ts index ef4b0623f..f9e5cd55e 100644 --- a/src/custom/state/claim/hooks/index.ts +++ b/src/custom/state/claim/hooks/index.ts @@ -282,7 +282,7 @@ const createMockTx = (data: number[]) => ({ * * Returns null if in there's no network or vCowContract doesn't exist */ -function useDeploymentTimestamp(): number | null { +export function useDeploymentTimestamp(): number | null { const { chainId } = useActiveWeb3React() const vCowContract = useVCowContract() const [timestamp, setTimestamp] = useState(null)