Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CP-9586 Unable to start staking #2132

Merged
merged 5 commits into from
Nov 26, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ import { isDevnet } from 'utils/isDevnet'
import { useAvalancheXpProvider } from 'hooks/networks/networkProviderHooks'

export type useEarnCalcEstimatedRewardsProps = {
amount: TokenUnit
amountNanoAvax: bigint
duration: Seconds
delegationFee: number
}

/**
*
* @param amount nAVAX
* @param amountNanoAvax nAVAX
* @param duration between current datetime to validator end time
* @param delegationFee
* @returns
*/
export const useEarnCalcEstimatedRewards = ({
amount,
amountNanoAvax,
duration,
delegationFee
}: useEarnCalcEstimatedRewardsProps): UseQueryResult<
Expand Down Expand Up @@ -54,7 +54,7 @@ export const useEarnCalcEstimatedRewards = ({
},
select: ({ supply: currentSupply }: pvm.GetCurrentSupplyResponse) => {
const reward = EarnService.calcReward(
amount,
amountNanoAvax,
duration,
new TokenUnit(
currentSupply,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,18 @@ export const calculateAmountForCrossChainTransfer = (
: stakingAmount
}
}
/**
* Calculates how much Avax we need to transfer from C to P
*/
export const calculateAmountForCrossChainTransferBigint = (
stakingAmount: bigint,
claimableBalance?: bigint
): bigint => {
if (claimableBalance !== undefined && claimableBalance > stakingAmount) {
return 0n
} else {
return claimableBalance !== undefined
? stakingAmount - claimableBalance
: stakingAmount
}
}
31 changes: 15 additions & 16 deletions packages/core-mobile/app/hooks/earn/useIssueDelegation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import EarnService from 'services/earn/EarnService'
import { selectIsDeveloperMode } from 'store/settings/advanced'
import { selectActiveAccount } from 'store/account'
import { selectSelectedCurrency } from 'store/settings/currency'
import { calculateAmountForCrossChainTransfer } from 'hooks/earn/useGetAmountForCrossChainTransfer'
import { calculateAmountForCrossChainTransferBigint } from 'hooks/earn/useGetAmountForCrossChainTransfer'
import Logger from 'utils/Logger'
import { FundsStuckError } from 'hooks/earn/errors'
import NetworkService from 'services/network/NetworkService'
Expand All @@ -20,6 +20,7 @@ import { isTokenWithBalancePVM } from '@avalabs/avalanche-module'
import { TokenUnit } from '@avalabs/core-utils-sdk'
import { isDevnet } from 'utils/isDevnet'
import { selectActiveNetwork } from 'store/network'
import { nanoToWei } from 'utils/units/converter'
import { useCChainBalance } from './useCChainBalance'
import { useGetFeeState } from './useGetFeeState'

Expand All @@ -33,11 +34,11 @@ export const useIssueDelegation = (
Error,
{
nodeId: string
stakingAmount: TokenUnit
stakingAmountNanoAvax: bigint
startDate: Date
endDate: Date
gasPrice?: bigint
requiredPFee?: TokenUnit
requiredPFeeNanoAvax?: bigint
},
unknown
>
Expand All @@ -62,11 +63,11 @@ export const useIssueDelegation = (
const issueDelegationMutation = useMutation({
mutationFn: async (data: {
nodeId: string
stakingAmount: TokenUnit
stakingAmountNanoAvax: bigint
startDate: Date
endDate: Date
gasPrice?: bigint
requiredPFee?: TokenUnit
requiredPFeeNanoAvax?: bigint
}) => {
if (!activeAccount) {
return Promise.reject('no active account')
Expand Down Expand Up @@ -120,21 +121,19 @@ export const useIssueDelegation = (
: undefined

Logger.trace('getPChainBalance: ', claimableBalance?.toDisplay())
const cChainRequiredAmountAvax = calculateAmountForCrossChainTransfer(
data.stakingAmount.add(data.requiredPFee ?? 0),
claimableBalance
)
const cChainRequiredAmountNanoAvax =
calculateAmountForCrossChainTransferBigint(
data.stakingAmountNanoAvax + (data.requiredPFeeNanoAvax ?? 0n),
claimableBalance?.toSubUnit()
)

Logger.trace(
'cChainRequiredAmount: ',
cChainRequiredAmountAvax.toDisplay()
)
Logger.trace('cChainRequiredAmount: ', cChainRequiredAmountNanoAvax)
Logger.trace('collectTokensForStaking...')
await EarnService.collectTokensForStaking({
activeAccount,
cChainBalance: cChainBalanceWei,
cChainBalanceWei,
isDevMode: isDeveloperMode,
requiredAmount: cChainRequiredAmountAvax.toSubUnit(),
requiredAmountWei: nanoToWei(cChainRequiredAmountNanoAvax),
selectedCurrency,
isDevnet: isDevnet(activeNetwork),
feeState: getFeeState(data.gasPrice)
Expand All @@ -145,7 +144,7 @@ export const useIssueDelegation = (
endDate: data.endDate,
isDevMode: isDeveloperMode,
nodeId: data.nodeId,
stakeAmount: data.stakingAmount.toSubUnit(),
stakeAmountNanoAvax: data.stakingAmountNanoAvax,
startDate: data.startDate,
isDevnet: isDevnet(activeNetwork),
feeState: getFeeState(data.gasPrice)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import { UTCDate } from '@date-fns/utc'
export type StakeSetupStackParamList = {
[AppNavigation.StakeSetup.GetStarted]: undefined
[AppNavigation.StakeSetup.SmartStakeAmount]: undefined
[AppNavigation.StakeSetup.StakingDuration]: { stakingAmount: TokenUnit }
[AppNavigation.StakeSetup.StakingDuration]: {
stakingAmountNanoAvax: bigint
}
[AppNavigation.StakeSetup.AdvancedStaking]: {
stakingEndTime: UTCDate
stakingAmount: TokenUnit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export const Confirmation = (): JSX.Element | null => {
}, [validatedStakingEndTime])

const { data } = useEarnCalcEstimatedRewards({
amount: deductedStakingAmount,
amountNanoAvax: deductedStakingAmount.toSubUnit(),
duration: validatedStakingDuration,
delegationFee: Number(validator?.delegationFee)
})
Expand Down Expand Up @@ -187,12 +187,12 @@ export const Confirmation = (): JSX.Element | null => {
}
AnalyticsService.capture('StakeIssueDelegation')
issueDelegationMutation.mutate({
stakingAmount: deductedStakingAmount,
stakingAmountNanoAvax: deductedStakingAmount.toSubUnit(),
startDate: minStartTime,
endDate: validatedStakingEndTime,
nodeId,
gasPrice,
requiredPFee
requiredPFeeNanoAvax: requiredPFee?.toSubUnit()
})
}

Expand Down
4 changes: 2 additions & 2 deletions packages/core-mobile/app/screens/earn/StakingAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export default function StakingAmount(): JSX.Element {
percent: (100 / factor).toString()
})
if (!cumulativeBalance) return
setInputAmount(cumulativeBalance.div(factor))
setInputAmount(zeroAvaxPChain().add(cumulativeBalance.div(factor)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious, what issue did you run into here?

}

return (
Expand Down Expand Up @@ -161,7 +161,7 @@ export default function StakingAmount(): JSX.Element {
onPress={() => {
AnalyticsService.capture('StakeOpenDurationSelect')
navigate(AppNavigation.StakeSetup.StakingDuration, {
stakingAmount: inputAmount
stakingAmountNanoAvax: inputAmount.toSubUnit()
})
}}>
Next
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
} from 'date-fns'
import { UTCDate } from '@date-fns/utc'
import { UnixTime } from 'services/earn/types'
import { AvaxXP } from 'types/AvaxXP'
import { CustomDurationOptionItem } from './components/CustomDurationOptionItem'
import { DurationOptionItem } from './components/DurationOptionItem'

Expand All @@ -58,7 +59,8 @@ export const StakingDuration = (): JSX.Element => {
const { theme } = useApplicationContext()
const { navigate, setOptions, goBack } =
useNavigation<ScreenProps['navigation']>()
const { stakingAmount } = useRoute<ScreenProps['route']>().params
const { stakingAmountNanoAvax } = useRoute<ScreenProps['route']>().params
const stakingAmount = AvaxXP.fromNanoAvax(stakingAmountNanoAvax)
const isNextDisabled =
stakeEndTime === undefined ||
(!!stakeEndTime && stakeEndTime < millisecondsToSeconds(UTCDate.now()))
Expand Down Expand Up @@ -151,7 +153,7 @@ export const StakingDuration = (): JSX.Element => {
return (
<DurationOptionItem
key={item.title}
stakeAmount={stakingAmount}
stakingAmountNanoAvax={stakingAmountNanoAvax}
item={item}
isSelected={selectedDuration?.title === item.title}
onRadioSelect={onRadioSelect}
Expand All @@ -162,7 +164,7 @@ export const StakingDuration = (): JSX.Element => {

const renderCustomOption = (): JSX.Element => (
<CustomDurationOptionItem
stakeAmount={stakingAmount}
stakingAmountNanoAvax={stakingAmountNanoAvax}
stakeEndTime={fromUnixTime(stakeEndTime)}
onRadioSelect={onRadioSelect}
handleDateConfirm={handleDateConfirm}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@ import { useSelector } from 'react-redux'
import { selectIsDeveloperMode } from 'store/settings/advanced'
import { differenceInMilliseconds } from 'date-fns'
import { useNow } from 'hooks/time/useNow'
import { TokenUnit } from '@avalabs/core-utils-sdk'
import { UTCDate } from '@date-fns/utc'
import { UNKNOWN_AMOUNT } from 'consts/amount'

export const CustomDurationOptionItem = ({
stakeAmount,
stakingAmountNanoAvax,
stakeEndTime,
onRadioSelect,
handleDateConfirm
}: {
stakeAmount: TokenUnit
stakingAmountNanoAvax: bigint
stakeEndTime: UTCDate
onRadioSelect: (item: DurationOption) => void
handleDateConfirm: (dateInput: UTCDate) => void
Expand Down Expand Up @@ -62,7 +61,7 @@ export const CustomDurationOptionItem = ({
BigInt(stakeDurationMs) as MilliSeconds
)
const { data } = useEarnCalcEstimatedRewards({
amount: stakeAmount,
amountNanoAvax: stakingAmountNanoAvax,
duration: stakeDurationSec,
delegationFee: 2
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@ import { RadioButton } from 'components/RadioButton'
import AvaText from 'components/AvaText'
import { selectIsDeveloperMode } from 'store/settings/advanced'
import { useSelector } from 'react-redux'
import { TokenUnit } from '@avalabs/core-utils-sdk'
import { UNKNOWN_AMOUNT } from 'consts/amount'

export const DurationOptionItem = ({
stakeAmount,
stakingAmountNanoAvax,
item,
onRadioSelect,
isSelected
}: {
stakeAmount: TokenUnit
stakingAmountNanoAvax: bigint
item: DurationOption
onRadioSelect: (item: DurationOption) => void
isSelected: boolean
Expand All @@ -38,7 +37,7 @@ export const DurationOptionItem = ({
BigInt(stakeDurationUnixMs) as MilliSeconds
)
const { data } = useEarnCalcEstimatedRewards({
amount: stakeAmount,
amountNanoAvax: stakingAmountNanoAvax,
duration: stakeDurationUnixSec,
delegationFee: 2
})
Expand Down
4 changes: 2 additions & 2 deletions packages/core-mobile/app/services/earn/EarnService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('EarnService', () => {
it('should return zero if current supply is max', () => {
expect(
EarnService.calcReward(
new TokenUnit(25 * 10 ** 9, 9, 'AVAX'),
BigInt(25 * 10 ** 9),
Seconds(7 * 24 * Hour),
new TokenUnit(
MainnetParams.stakingConfig.RewardConfig.SupplyCap,
Expand All @@ -43,7 +43,7 @@ describe('EarnService', () => {
it('should return non zero if current supply is less than max', () => {
expect(
EarnService.calcReward(
new TokenUnit(2000000 * 10 ** 9, 9, 'AVAX'),
BigInt(2000000 * 10 ** 9),
Seconds(7 * 24 * Hour),
new TokenUnit(400_000_000 * 10 ** 9, 9, 'AVAX'),
2,
Expand Down
21 changes: 12 additions & 9 deletions packages/core-mobile/app/services/earn/EarnService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import AnalyticsService from 'services/analytics/AnalyticsService'
import { TokenUnit } from '@avalabs/core-utils-sdk'
import { Avalanche } from '@avalabs/core-wallets-sdk'
import { Network } from '@avalabs/core-chains-sdk'
import { AvaxXP } from 'types/AvaxXP'
import {
getTransformedTransactions,
maxGetAtomicUTXOsRetries,
Expand Down Expand Up @@ -128,21 +129,21 @@ class EarnService {
* Collect tokens for staking by moving Avax from C to P-chain
*/
async collectTokensForStaking({
cChainBalance,
requiredAmount,
cChainBalanceWei,
requiredAmountWei,
activeAccount,
isDevMode,
selectedCurrency,
isDevnet,
feeState
}: CollectTokensForStakingParams & { isDevnet: boolean }): Promise<void> {
if (requiredAmount === 0n) {
if (requiredAmountWei === 0n) {
Logger.info('no need to cross chain')
return
}
await exportC({
cChainBalance,
requiredAmount,
cChainBalanceWei,
requiredAmountWei,
activeAccount,
isDevMode,
isDevnet
Expand Down Expand Up @@ -190,21 +191,23 @@ class EarnService {

/**
*
* @param amount
* @param amountNanoAvax in nAvax
* @param duration in s
* @param currentSupply
* @param delegationFee in percent
* @param isDeveloperMode
*/
// eslint-disable-next-line max-params
calcReward(
amount: TokenUnit,
amountNanoAvax: bigint,
duration: Seconds,
currentSupply: TokenUnit,
delegationFee: number,
isDeveloperMode: boolean,
isDevnet: boolean
): TokenUnit {
const amount = AvaxXP.fromNanoAvax(amountNanoAvax)

const avaxPNetwork = NetworkService.getAvalancheNetworkP(
isDeveloperMode,
isDevnet
Expand Down Expand Up @@ -250,7 +253,7 @@ class EarnService {
async issueAddDelegatorTransaction({
activeAccount,
nodeId,
stakeAmount,
stakeAmountNanoAvax,
startDate,
endDate,
isDevMode,
Expand All @@ -272,7 +275,7 @@ class EarnService {
nodeId,
startDate: startDateUnix,
endDate: endDateUnix,
stakeAmountInNAvax: stakeAmount,
stakeAmountInNAvax: stakeAmountNanoAvax,
isDevMode,
feeState
} as AddDelegatorProps)
Expand Down
Loading
Loading