Skip to content

Commit

Permalink
CP-9383: Mobile - unable to stake on prod build (#2026
Browse files Browse the repository at this point in the history
  • Loading branch information
neven-s authored and atn4z7 committed Oct 29, 2024
1 parent 723bdcb commit 3230673
Show file tree
Hide file tree
Showing 16 changed files with 218 additions and 87 deletions.
7 changes: 4 additions & 3 deletions packages/core-mobile/app/hooks/time/useNow.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useEffect, useState } from 'react'
import { Seconds } from 'types/siUnits'
import { UnixTimeMs } from 'services/earn/types'

const tenSeconds = Seconds(10)
export const useNow = (refreshInterval: Seconds = tenSeconds) => {
const [now, setNow] = useState(new Date())
export const useNow = (refreshInterval: Seconds = tenSeconds): UnixTimeMs => {
const [now, setNow] = useState(Date.now())

useEffect(() => {
const intervalId = setInterval(() => {
setNow(new Date())
setNow(Date.now())
}, Number(refreshInterval * 1000n))

return () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,31 @@ import { BackButton } from 'components/BackButton'
import { FundsStuckModal } from 'screens/earn/FundsStuckModal'
import { handleStakeConfirmationGoBack } from 'utils/earn/handleStakeConfirmationGoBack'
import AnalyticsService from 'services/analytics/AnalyticsService'
import { UTCDate } from '@date-fns/utc'

export type StakeSetupStackParamList = {
[AppNavigation.StakeSetup.GetStarted]: undefined
[AppNavigation.StakeSetup.SmartStakeAmount]: undefined
[AppNavigation.StakeSetup.StakingDuration]: { stakingAmount: Avax }
[AppNavigation.StakeSetup.AdvancedStaking]: {
stakingEndTime: Date
stakingEndTime: UTCDate
stakingAmount: Avax
selectedDuration: string
}
[AppNavigation.StakeSetup.SelectNode]: {
stakingEndTime: Date
stakingEndTime: UTCDate
stakingAmount: Avax
minUpTime?: number
maxFee?: number
}
[AppNavigation.StakeSetup.NodeSearch]: {
stakingEndTime: Date
stakingEndTime: UTCDate
stakingAmount: Avax
}
[AppNavigation.StakeSetup.Confirmation]: {
nodeId: string
stakingAmount: Avax
stakingEndTime: Date
stakingEndTime: UTCDate
onBack?: () => void
}
[AppNavigation.StakeSetup.Cancel]: undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,15 @@ export const Confirmation = (): JSX.Element | null => {
deductedStakingAmount = stakingAmount
}

const validatorEndTimeUnix = useMemo(() => {
if (validator?.endTime) {
return Number(validator?.endTime)
}
return 0
}, [validator?.endTime])

const { minStartTime, validatedStakingEndTime, validatedStakingDuration } =
useValidateStakingEndTime(stakingEndTime, validator?.endTime ?? '')
useValidateStakingEndTime(stakingEndTime, validatorEndTimeUnix)

const { data } = useEarnCalcEstimatedRewards({
amount: deductedStakingAmount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,27 @@ import { useNow } from 'hooks/time/useNow'
import { getMinimumStakeDurationMs } from 'services/earn/utils'
import { selectIsDeveloperMode } from 'store/settings/advanced'
import { MilliSeconds, Seconds, convertToSeconds } from 'types/siUnits'
import { UTCDate } from '@date-fns/utc'
import { UnixTime } from 'services/earn/types'
import { utc } from '@date-fns/utc/utc'

export const useValidateStakingEndTime = (
stakingEndTime: Date,
validatorEndTimeStr: string
stakingEndTime: UTCDate,
validatorEndTimeStr: UnixTime
): {
minStartTime: Date
validatedStakingEndTime: Date
minStartTime: UTCDate
validatedStakingEndTime: UTCDate
validatedStakingDuration: Seconds
} => {
const now = useNow()
const currentUnixMs = useNow()
const isDeveloperMode = useSelector(selectIsDeveloperMode)

const minStakeDurationMs = getMinimumStakeDurationMs(isDeveloperMode)

// minStartTime - 1 minute after submitting
const minStartTime = useMemo(() => {
return addMinutes(now, 1)
}, [now])
return addMinutes(new UTCDate(currentUnixMs), 1)
}, [currentUnixMs])

const validatedStakingEndTime = useMemo(() => {
// check if stake duration is less than minimum, and adjust if necessary
Expand All @@ -31,12 +34,12 @@ export const useValidateStakingEndTime = (
stakingEndTime.getTime() - minStakeDurationMs <
minStartTime.getTime()
) {
return new Date(minStartTime.getTime() + minStakeDurationMs)
return new UTCDate(minStartTime.getTime() + minStakeDurationMs)
}

// check if stake duration is more than validator's end time,
// use validator's end time if it is
const validatorEndTime = fromUnixTime(Number(validatorEndTimeStr))
const validatorEndTime = fromUnixTime(validatorEndTimeStr, { in: utc })

if (stakingEndTime > validatorEndTime) {
return validatorEndTime
Expand All @@ -49,10 +52,10 @@ export const useValidateStakingEndTime = (
() =>
convertToSeconds(
BigInt(
validatedStakingEndTime.getTime() - now.getTime()
validatedStakingEndTime.getTime() - currentUnixMs
) as MilliSeconds
),
[now, validatedStakingEndTime]
[currentUnixMs, validatedStakingEndTime]
)

return { minStartTime, validatedStakingEndTime, validatedStakingDuration }
Expand Down
5 changes: 4 additions & 1 deletion packages/core-mobile/app/screens/earn/StakeDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { RewardType } from '@avalabs/glacier-sdk'
import { isOnGoing } from 'utils/earn/status'
import { estimatesTooltipText } from 'consts/earn'
import { Tooltip } from 'components/Tooltip'
import { UTCDate } from '@date-fns/utc'
import { StatusChip } from './components/StatusChip'
import { StakeProgress } from './components/StakeProgress'

Expand Down Expand Up @@ -79,7 +80,9 @@ const StakeDetails = (): JSX.Element | null => {

const renderActiveDetails = (): JSX.Element => {
const formattedEndDate = format(endDate, 'LLLL d, yyyy, H:mm aa')
const remainingTime = humanize(getReadableDateDuration(endDate))
const remainingTime = humanize(
getReadableDateDuration(new UTCDate(endDate.getTime()))
)
const [estimatedRewardInAvax, estimatedRewardInCurrency] = nAvaxFormatter(
stake.estimatedReward,
true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { Avax } from 'types/Avax'
import { useSelector } from 'react-redux'
import { selectIsDeveloperMode } from 'store/settings/advanced'
import { usePeers } from 'hooks/earn/usePeers'
import { UTCDate } from '@date-fns/utc'
import { PopableContentWithCaption } from './PopableContentWithCaption'

type NavigationProp = StakeSetupScreenProps<
Expand All @@ -36,7 +37,7 @@ export const NodeCard = ({
}: {
data: NodeValidator
stakingAmount: Avax
stakingEndTime: Date
stakingEndTime: UTCDate
}): JSX.Element => {
const { theme } = useApplicationContext()
const [isCardExpanded, setIsCardExpanded] = useState(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { TabsScreenProps } from 'navigation/types'
import AppNavigation from 'navigation/AppNavigation'
import { estimatesTooltipText } from 'consts/earn'
import { Tooltip } from 'components/Tooltip'
import { UTCDate } from '@date-fns/utc'
import { StatusChip } from './StatusChip'

type BaseProps = {
Expand Down Expand Up @@ -60,7 +61,7 @@ export const StakeCard = (props: Props): JSX.Element => {
switch (status) {
case StakeStatus.Ongoing: {
const remainingTime = getReadableDateDuration(
fromUnixTime(props.endTimestamp || 0)
new UTCDate(props.endTimestamp || 0)
)
return (
<AvaText.Caption color={theme.colorText1}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import { BackButton } from 'components/BackButton'
import { Tooltip } from 'components/Tooltip'
import InfoSVG from 'components/svg/InfoSVG'
import AnalyticsService from 'services/analytics/AnalyticsService'
import { fromUnixTime, getUnixTime } from 'date-fns'
import { UTCDate } from '@date-fns/utc'
import { UnixTime } from 'services/earn/types'
import { CustomDurationOptionItem } from './components/CustomDurationOptionItem'
import { DurationOptionItem } from './components/DurationOptionItem'

Expand All @@ -35,35 +38,36 @@ type ScreenProps = StakeSetupScreenProps<

export const StakingDuration = (): JSX.Element => {
const isDeveloperMode = useSelector(selectIsDeveloperMode)
const currentDate = useNow()
const currentUnix = useNow() / 1000
const minDelegationTime = isDeveloperMode ? ONE_DAY : TWO_WEEKS
const [selectedDuration, setSelectedDuration] =
useState<DurationOption>(minDelegationTime)
const [stakeEndTime, setStakeEndTime] = useState<Date>(
getStakeEndDate(
currentDate,
minDelegationTime.stakeDurationFormat,
minDelegationTime.stakeDurationValue,
isDeveloperMode
)
const [stakeEndTime, setStakeEndTime] = useState<UnixTime>(
getStakeEndDate({
startDateUnix: currentUnix,
stakeDurationFormat: minDelegationTime.stakeDurationFormat,
stakeDurationValue: minDelegationTime.stakeDurationValue,
isDeveloperMode: isDeveloperMode
})
)
const { theme } = useApplicationContext()
const { navigate, setOptions, goBack } =
useNavigation<ScreenProps['navigation']>()
const { stakingAmount } = useRoute<ScreenProps['route']>().params
const isNextDisabled =
stakeEndTime === undefined || (stakeEndTime && stakeEndTime < new Date())
stakeEndTime === undefined ||
(!!stakeEndTime && stakeEndTime < UTCDate.now() / 1000)

const selectMinDuration = useCallback(() => {
setSelectedDuration(minDelegationTime)
const calculatedStakeEndTime = getStakeEndDate(
currentDate,
minDelegationTime.stakeDurationFormat,
minDelegationTime.stakeDurationValue,
isDeveloperMode
)
const calculatedStakeEndTime = getStakeEndDate({
startDateUnix: currentUnix,
stakeDurationFormat: minDelegationTime.stakeDurationFormat,
stakeDurationValue: minDelegationTime.stakeDurationValue,
isDeveloperMode: isDeveloperMode
})
setStakeEndTime(calculatedStakeEndTime)
}, [currentDate, isDeveloperMode, minDelegationTime])
}, [currentUnix, isDeveloperMode, minDelegationTime])

useLayoutEffect(() => {
const isCustomSelected =
Expand All @@ -88,18 +92,18 @@ export const StakingDuration = (): JSX.Element => {
}

setSelectedDuration(durationOption)
const calculatedStakeEndTime = getStakeEndDate(
currentDate,
durationOption.stakeDurationFormat,
durationOption.stakeDurationValue,
isDeveloperMode
)
const calculatedStakeEndTime = getStakeEndDate({
startDateUnix: currentUnix,
stakeDurationFormat: durationOption.stakeDurationFormat,
stakeDurationValue: durationOption.stakeDurationValue,
isDeveloperMode: isDeveloperMode
})
setStakeEndTime(calculatedStakeEndTime)
}

const handleDateConfirm = (dateInput: Date): void => {
setSelectedDuration(CUSTOM)
setStakeEndTime(dateInput)
setStakeEndTime(getUnixTime(dateInput))
}

const navigateToNodeSearch = (): void => {
Expand All @@ -110,7 +114,7 @@ export const StakingDuration = (): JSX.Element => {
})
navigate(AppNavigation.StakeSetup.NodeSearch, {
stakingAmount,
stakingEndTime: stakeEndTime
stakingEndTime: new UTCDate(stakeEndTime * 1000)
})
}
}
Expand All @@ -120,7 +124,7 @@ export const StakingDuration = (): JSX.Element => {
AnalyticsService.capture('StakeSelectAdvancedStaking')
navigate(AppNavigation.StakeSetup.AdvancedStaking, {
stakingAmount,
stakingEndTime: stakeEndTime,
stakingEndTime: new UTCDate(stakeEndTime * 1000),
selectedDuration: selectedDuration.title
})
}
Expand Down Expand Up @@ -154,7 +158,7 @@ export const StakingDuration = (): JSX.Element => {
const renderCustomOption = (): JSX.Element => (
<CustomDurationOptionItem
stakeAmount={stakingAmount}
stakeEndTime={stakeEndTime}
stakeEndTime={fromUnixTime(stakeEndTime)}
onRadioSelect={onRadioSelect}
handleDateConfirm={handleDateConfirm}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react'
import React, { useMemo, useState } from 'react'
import { useApplicationContext } from 'contexts/ApplicationContext'
import { useEarnCalcEstimatedRewards } from 'hooks/earn/useEarnCalcEstimatedRewards'
import {
Expand All @@ -24,6 +24,7 @@ import { differenceInMilliseconds } from 'date-fns'
import { Avax } from 'types/Avax'
import { useNow } from 'hooks/time/useNow'
import { useAvaxFormatter } from 'hooks/formatter/useAvaxFormatter'
import { UTCDate } from '@date-fns/utc'

export const CustomDurationOptionItem = ({
stakeAmount,
Expand All @@ -32,34 +33,38 @@ export const CustomDurationOptionItem = ({
handleDateConfirm
}: {
stakeAmount: Avax
stakeEndTime: Date
stakeEndTime: UTCDate
onRadioSelect: (item: DurationOption) => void
handleDateConfirm: (dateInput: Date) => void
}) => {
handleDateConfirm: (dateInput: UTCDate) => void
}): JSX.Element => {
const avaxFormatter = useAvaxFormatter()
const isDeveloperMode = useSelector(selectIsDeveloperMode)
const [isDatePickerVisible, setIsDatePickerVisible] = useState(false)
const currentDate = useNow()
const currentUnix = useNow()
const { theme } = useApplicationContext()
const minDelegationTime = isDeveloperMode ? ONE_DAY : TWO_WEEKS
const stakeEndTimeLocal = useMemo(
() => new Date(stakeEndTime.getTime()),
[stakeEndTime]
)

const minimumStakeEndDate = getMinimumStakeEndTime(
isDeveloperMode,
currentDate
new UTCDate(currentUnix)
)
const maximumStakeEndDate = getMaximumStakeEndDate()

const stakeDurationUnixMs = differenceInMilliseconds(
const stakeDurationMs = differenceInMilliseconds(
stakeEndTime,
currentDate
new UTCDate(currentUnix)
)

const stakeDurationUnixSec = convertToSeconds(
BigInt(stakeDurationUnixMs) as MilliSeconds
const stakeDurationSec = convertToSeconds(
BigInt(stakeDurationMs) as MilliSeconds
)
const { data } = useEarnCalcEstimatedRewards({
amount: stakeAmount,
duration: stakeDurationUnixSec,
duration: stakeDurationSec,
delegationFee: 2
})

Expand All @@ -68,6 +73,10 @@ export const CustomDurationOptionItem = ({
true
)

function handleDateSelected(date: Date): void {
handleDateConfirm(new UTCDate(date.getTime()))
}

return (
<View
style={{
Expand Down Expand Up @@ -97,8 +106,8 @@ export const CustomDurationOptionItem = ({
<Space x={8} />
</Row>
<CalendarInput
date={stakeEndTime}
onDateSelected={handleDateConfirm}
date={stakeEndTimeLocal}
onDateSelected={handleDateSelected}
isDatePickerVisible={isDatePickerVisible}
setIsDatePickerVisible={setIsDatePickerVisible}
placeHolder="Select a date"
Expand Down
Loading

0 comments on commit 3230673

Please sign in to comment.