Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/haust-dex/src/components/PositionListItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@ export default function PositionListItem({
}: PositionListItemProps) {
const { chainId } = useWeb3React()
const theme = useTheme()
const token0 = useToken(token0Address)
const token1 = useToken(token1Address)
const token0 = useToken(token0Address, true)
const token1 = useToken(token1Address, true)
const {incentiveEvents, loading: incentivesLoading} = useV3Incentive()

const currency0 = token0 ? unwrappedToken(token0) : undefined
Expand Down
15 changes: 8 additions & 7 deletions apps/haust-dex/src/components/PositionListItem/rewardLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,17 @@ const StakingLabel = styled(ThemedText.UtilityBadge)`
interface PositionListItemProps {
incentive: {
rewardToken: string;
pool: string;
startTime: number;
endTime: number;
reward: string;
pool: string;
startTime: number;
endTime: number;
reward: string;
isLocked?: boolean;
}
tokenId: BigNumber
}

const formatTime = (totalSeconds: number): string => {
if (totalSeconds <= 0) return 'Staking ended'
if (totalSeconds <= 0) return 'Staking Rewards Available'

const days = Math.floor(totalSeconds / 86400)
const hours = Math.floor((totalSeconds % 86400) / 3600)
Expand All @@ -50,7 +51,7 @@ export default function RewardLabel({
incentive,
tokenId,
}: PositionListItemProps) {
const {rewardInfo, globalLock} = useV3StakingRewardInfo(
const {rewardInfo} = useV3StakingRewardInfo(
incentive,
tokenId.toString()
)
Expand All @@ -76,7 +77,7 @@ export default function RewardLabel({
return null
}

if (rewardInfo && globalLock) {
if (rewardInfo && incentive?.isLocked) {
return (
<StakingLabel>
{timeRemaining}
Expand Down
2 changes: 1 addition & 1 deletion apps/haust-dex/src/constants/addresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const HAUST_TESTNET_V3_MIGRATOR_ADDRESSES = '0xA0E3f176012B18170581F9AE142723303
const HAUST_TESTNET_MULTICALL_ADDRESS = '0x7646AE4D47281Eb5b641E5ee8959Ac78781c8567'
const HAUST_TESTNET_QUOTER_ADDRESSES = '0x27cd86dd99c73c7F93Ca4407EFd17d7108fBDFA2'
const HAUST_TESTNET_NONFUNGIBLE_POSITION_MANAGER_ADDRESSES = '0x32E7EeC6be44Ff17e30237dF15eB8B3541138C94'
const HAUST_TESTNET_UNISWAP_V3_STAKER_ADDRESSES = '0x27572122ffF50bFB8fc1F649d59b01899c6a2fe0'
const HAUST_TESTNET_UNISWAP_V3_STAKER_ADDRESSES = '0xfc0430ce0777f4ef86dcb263efc8de60fbc76528'
const HAUST_TESTNET_TICK_LENS_ADDRESSES = '0x423043f8C5F9e23BC1fd9f97977458f2Fd606B1f'
const HAUST_TESTNET_POOL_DEPLOYER = '0xbBf50bcbd1439385637FAE13bF1Be84F04C7366b'
const HAUST_TESTNET_UNIVERSAL_ROUTER_ADDRESS = '0xE71Af6EEd736bA513CbD19Ebc82D1Cf943b80b63'
Expand Down
26 changes: 21 additions & 5 deletions apps/haust-dex/src/hooks/Tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,38 @@ export function useAllTokensMultichain(): TokenAddressMap {
}

// Returns all tokens from the default list + user added tokens
export function useDefaultActiveTokens(): { [address: string]: Token } {
export function useDefaultActiveTokens(forPools?: boolean): {
[address: string]: Token;
} {
const defaultListTokens = useCombinedActiveList();
const tokensFromMap = useTokensFromMap(defaultListTokens);
const userAddedTokens = useUserAddedTokens();

return useMemo(() => {
// First filter out MYR tokens from tokensFromMap
const filteredTokensFromMap = forPools
? tokensFromMap
: Object.entries(tokensFromMap).reduce((acc, [address, token]) => {
if (token.symbol !== "MYR") {
acc[address] = token;
}
return acc;
}, {} as { [address: string]: Token });

return (
userAddedTokens
// reduce into all ALL_TOKENS filtered by the current chain
.reduce<{ [address: string]: Token }>(
(tokenMap, token) => {
tokenMap[token.address] = token;
// Only add tokens that are not MYR
if (token.symbol !== "MYR" || !forPools) {
tokenMap[token.address] = token;
}
return tokenMap;
},
// must make a copy because reduce modifies the map, and we do not
// want to make a copy in every iteration
{ ...tokensFromMap }
{ ...filteredTokensFromMap }
)
);
}, [tokensFromMap, userAddedTokens]);
Expand Down Expand Up @@ -203,9 +218,10 @@ export function useIsUserAddedTokenOnChain(
// null if loading or null was passed
// otherwise returns the token
export function useToken(
tokenAddress?: string | null
tokenAddress?: string | null,
forPools?: boolean
): Token | null | undefined {
const tokens = useDefaultActiveTokens();
const tokens = useDefaultActiveTokens(forPools);
return useTokenFromMapOrNetwork(tokens, tokenAddress);
}

Expand Down
4 changes: 3 additions & 1 deletion apps/haust-dex/src/hooks/useV3Incentive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface IncentiveCreatedEvent {
endTime: number;
reward: string;
tokenIds: number[];
isLocked?: boolean;
}

export function useV3Incentive(): UseV3IncentivesCreatedResults {
Expand All @@ -31,7 +32,7 @@ export function useV3Incentive(): UseV3IncentivesCreatedResults {
const incentiveEvents = useMemo(() => {
if (!activeIncentives?.[0]?.[0]) return [];
return activeIncentives[0].map((incentiveData: any[]) => {
const [incentive, tokenIdsData] = incentiveData;
const [incentive, tokenIdsData, isLocked] = incentiveData;
return {
rewardToken: incentive[0],
pool: incentive[1],
Expand All @@ -41,6 +42,7 @@ export function useV3Incentive(): UseV3IncentivesCreatedResults {
tokenIds: tokenIdsData.map(
(tokenId: { _hex: string; _isBigNumber: boolean }) => Number(tokenId)
),
isLocked,
};
});
}, [activeIncentives]);
Expand Down
7 changes: 2 additions & 5 deletions apps/haust-dex/src/hooks/useV3StakingRewardInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ export function useV3StakingRewardInfo(
}
);

const { loading: globalLockLoading, result: globalLock } =
useSingleCallResult(staker, "globalLock");

const rewardInfo = useMemo(() => {
if (!activeIncentives) return undefined;

Expand All @@ -56,8 +53,8 @@ export function useV3StakingRewardInfo(
}, [activeIncentives]);

return {
loading: loading || globalLockLoading,
loading,
rewardInfo,
globalLock: globalLock?.[0] ?? false,
globalLock: true,
};
}
4 changes: 2 additions & 2 deletions apps/haust-dex/src/pages/Pool/PositionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ function PositionPageContent() {
>
Stake Position
</SmallButtonPrimary>
) : (
) : !incentive?.isLocked ? (
<SmallButtonPrimary
as={Link}
to={`/unstake/${tokenId}`}
Expand All @@ -878,7 +878,7 @@ function PositionPageContent() {
>
Unstake position
</SmallButtonPrimary>
)}
) : null}
</>
)}
</AutoColumn>
Expand Down
69 changes: 65 additions & 4 deletions apps/haust-dex/src/pages/Pool/RewardInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,26 @@ import { DarkCard, LightCard } from 'components/Card'
import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/Logo/CurrencyLogo'
import { RowBetween, RowFixed } from 'components/Row'
import { useV3StakingRewardInfo, V3StakingRewardInfo } from 'hooks/useV3StakingRewardInfo'
import { useUSDPrice } from 'hooks/useUSDPrice'
import { useV3StakingRewardInfo } from 'hooks/useV3StakingRewardInfo'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'

import { SmallButtonPrimary } from '../../components/Button'
import { useUSDPrice } from 'hooks/useUSDPrice'
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { colors } from 'theme/colors'

interface V3StakingRewardInfo {
rewardToken: string
pool: string
startTime: number
endTime: number
reward: string
isLocked?: boolean
}

// responsive text
// disable the warning because we don't use the end prop, we just want to filter it out
Expand All @@ -32,7 +43,29 @@ export const ResponsiveRow = styled(RowBetween)`
}
`

export function RewardInfo({tokenId, stakedInfo}: {tokenId: string, stakedInfo: V3StakingRewardInfo}) {
const formatTime = (totalSeconds: number): string => {
if (totalSeconds <= 0) return 'Claim rewards'

const days = Math.floor(totalSeconds / 86400)
const hours = Math.floor((totalSeconds % 86400) / 3600)
const minutes = Math.floor((totalSeconds % 3600) / 60)
const seconds = Math.floor(totalSeconds % 60)

const pad = (num: number): string => num.toString().padStart(2, '0')

if (days > 0) {
return `Rewards available in ${days}d ${pad(hours)}h ${pad(minutes)}m ${pad(seconds)}s`
}
return `Rewards available in ${pad(hours)}h ${pad(minutes)}m ${pad(seconds)}s`
}

export function RewardInfo({
tokenId,
stakedInfo,
}: {
tokenId: string,
stakedInfo: V3StakingRewardInfo,
}) {
const { rewardInfo: rewardAmount } = useV3StakingRewardInfo(
stakedInfo!,
tokenId!
Expand All @@ -43,8 +76,26 @@ export function RewardInfo({tokenId, stakedInfo}: {tokenId: string, stakedInfo:
rewardAmount
}

const [timeRemaining, setTimeRemaining] = useState<string>('')

useEffect(() => {
const updateTimeRemaining = () => {
const now = Math.floor(Date.now() / 1000)
const endTime = stakedInfo.endTime
const secondsRemaining = endTime - now

setTimeRemaining(formatTime(secondsRemaining))
}

updateTimeRemaining()
const interval = setInterval(updateTimeRemaining, 1000)

return () => clearInterval(interval)
}, [stakedInfo.endTime])

const parsedRewardAmount = tryParseCurrencyAmount(rewardAmount?.reward.toString(), rewardToken)
const fiatValue = useUSDPrice(parsedRewardAmount)

return (
<DarkCard>
<AutoColumn gap="md" style={{ width: '100%' }}>
Expand Down Expand Up @@ -89,6 +140,16 @@ export function RewardInfo({tokenId, stakedInfo}: {tokenId: string, stakedInfo:
>
Claim rewards
</SmallButtonPrimary>
) : stakedInfo?.isLocked && stakedInfo?.endTime > Math.floor(Date.now() / 1000) ? (
<SmallButtonPrimary
padding="6px 8px"
width="fit-content"
$borderRadius="12px"
style={{ opacity: 0.3, color: colors.primaryBase, backgroundColor: colors.primaryDark }}
disabled
>
{timeRemaining}
</SmallButtonPrimary>
) : (
<SmallButtonPrimary
as={Link}
Expand Down
Loading