Skip to content

Commit

Permalink
feat: maxUnlockingChunks (#1071)
Browse files Browse the repository at this point in the history
* maxUnlockingChunks

* using getDapp method
  • Loading branch information
gluneau committed Dec 5, 2023
1 parent 364c344 commit 246f020
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 12 deletions.
7 changes: 5 additions & 2 deletions src/i18n/en-US/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -694,13 +694,16 @@ export default {
Disabled: 'Pallet is disabled/in maintenance mode.',
NoExpiredEntries: 'There are no expired entries to clean up.',
NoStakingInfo: 'Account has no staking information for the contract',
NotOperatedDApp: 'dApp is part of dApp staking but is not active anymore.',
PeriodEndsNextEra: 'Period ends in the next era.',
TooManyStakedContracts:
'There are too many contract stake entries for the account. This can be cleaned up by either unstaking or cleaning expired entries.',
TooManyUnlockingChunks:
'Contract has too many unlocking chunks. Withdraw the existing chunks if possible or wait for current chunks to complete unlocking process to withdraw them.',
UnavailableStakeFunds:
'The staking amount surpasses the current balance available for staking.',
UnclaimedRewardsFromPastPeriods:
'There are unclaimed rewards remaining from past periods. They should be claimed before staking again.',
UnclaimedRewards:
'There are unclaimed rewards remaining from past eras or periods. They should be claimed before attempting any stake modification again.',
UnstakeAmountTooLarge: 'Unstake amount is greater than the staked amount.',
UnstakeFromPastPeriod:
'Unstaking is rejected since the period in which past stake was active has passed.',
Expand Down
45 changes: 35 additions & 10 deletions src/staking-v3/hooks/useDappStaking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function useDappStaking() {
const { t } = useI18n();
const store = useStore();
const { currentAccount } = useAccount();
const { registeredDapps, fetchStakeAmountsToStore } = useDapps();
const { registeredDapps, fetchStakeAmountsToStore, getDapp } = useDapps();
const { decimal } = useChainMetadata();
const { useableBalance } = useBalance(currentAccount);

Expand Down Expand Up @@ -138,7 +138,7 @@ export function useDappStaking() {
: true;

const stake = async (dappAddress: string, amount: number): Promise<void> => {
const [result, error] = await canStake(amount);
const [result, error] = await canStake(dappAddress, amount);
if (!result) {
throw error;
}
Expand Down Expand Up @@ -281,58 +281,83 @@ export function useDappStaking() {
store.commit('stakingV3/setCurrentEraInfo', eraInfo);
};

const canStake = async (amount: number): Promise<[boolean, string]> => {
const canStake = async (
dappAddress: string,
amount: number,
ignoreCanClaim = false
): Promise<[boolean, string]> => {
const stakeAmount = new BN(ethers.utils.parseEther(amount.toString()).toString());
const balanceBN = new BN(useableBalance.value.toString());
const stakingRepo = container.get<IDappStakingRepository>(Symbols.DappStakingRepositoryV3);
const constants = await stakingRepo.getConstants();

if (amount <= 0) {
if (!dappAddress) {
// Prevents NoDappSelected
return [false, t('stakingV3.noDappSelected')];
} else if (amount <= 0) {
// Prevents dappStaking.ZeroAmount
return [false, t('stakingV3.dappStaking.ZeroAmount')];
} else if ((ledger.value?.contractStakeCount ?? 0) >= constants.maxNumberOfStakedContracts) {
// Prevents dappStaking.TooManyStakedContracts
return [false, t('stakingV3.dappStaking.TooManyStakedContracts')];
} else if (hasRewards.value) {
// Prevents dappStaking.UnclaimedRewardsFromPastPeriods
} else if (hasRewards.value && !ignoreCanClaim) {
// Prevents dappStaking.UnclaimedRewards
// May want to auto claim rewards here
return [false, t('stakingV3.dappStaking.UnclaimedRewardsFromPastPeriods')];
return [false, t('stakingV3.dappStaking.UnclaimedRewards')];
} else if (protocolState.value?.maintenance) {
// Prevents dappStaking.Disabled
return [false, t('stakingV3.dappStaking.Disabled')];
} else if (stakeAmount.gt(balanceBN)) {
// Prevents dappStaking.UnavailableStakeFunds
return [false, t('stakingV3.dappStaking.UnavailableStakeFunds')];
} else if (
// Prevents dappStaking.PeriodEndsInNextEra
protocolState.value?.periodInfo.subperiod === PeriodType.BuildAndEarn &&
protocolState.value.periodInfo.nextSubperiodStartEra <= protocolState.value.era + 1
) {
// Prevents dappStaking.PeriodEndsInNextEra
return [false, t('stakingV3.dappStaking.PeriodEndsNextEra')];
} else if (getDapp(dappAddress)?.chain?.state === 'Unregistered') {
// Prevents dappStaking.NotOperatedDApp
return [false, t('stakingV3.dappStaking.NotOperatedDApp')];
}

return [true, ''];
};

const canUnStake = async (address: string, amount: number): Promise<[boolean, string]> => {
const canUnStake = async (dappAddress: string, amount: number): Promise<[boolean, string]> => {
const stakeAmount = new BN(ethers.utils.parseEther(amount.toString()).toString());
const stakedAmount = new BN(ledger.value?.locked?.toString() ?? 0);
const stakingRepo = container.get<IDappStakingRepository>(Symbols.DappStakingRepositoryV3);
const [constants, stakerInfo] = await Promise.all([
stakingRepo.getConstants(),
stakingRepo.getStakerInfo(currentAccount.value, false),
]);

console.log('ledger.value?.unlocking?.length)', ledger.value?.unlocking?.length);
console.log('constants.maxNumberOfUnlockingChunks', constants.maxUnlockingChunks);

if (amount <= 0) {
// Prevents dappStaking.ZeroAmount
return [false, t('stakingV3.dappStaking.ZeroAmount')];
} else if (stakeAmount.gt(stakedAmount)) {
// Prevents dappStaking.UnstakeAmountTooLarge
return [false, t('stakingV3.dappStaking.UnstakeAmountTooLarge')];
} else if (hasRewards.value) {
// Prevents dappStaking.UnclaimedRewards
// May want to auto claim rewards here
return [false, t('stakingV3.dappStaking.UnclaimedRewards')];
} else if (protocolState.value?.maintenance) {
// Prevents dappStaking.Disabled
return [false, t('stakingV3.dappStaking.Disabled')];
} else if (!address) {
} else if (!stakerInfo.get(dappAddress)) {
// Prevents dappStaking.NoStakingInfo
return [false, t('stakingV3.dappStaking.NoStakingInfo')];
} else if (!amount) {
// Prevents dappStaking.UnstakeFromPastPeriod
return [false, t('stakingV3.dappStaking.UnstakeFromPastPeriod')];
} else if ((ledger.value?.unlocking?.length ?? 0) >= constants.maxUnlockingChunks) {
// Prevents dappStaking.TooManyUnlockingChunks
return [false, t('stakingV3.dappStaking.TooManyUnlockingChunks')];
}

return [true, ''];
Expand Down
1 change: 1 addition & 0 deletions src/staking-v3/logic/models/DappStaking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export interface Constants {
minBalanceAfterStaking: number;
maxNumberOfStakedContracts: number;
maxNumberOfContracts: number;
maxUnlockingChunks: number;
standardErasPerBuildAndEarnPeriod: number;
standardErasPerVotingPeriod: number;
unlockingPeriod: number;
Expand Down
1 change: 1 addition & 0 deletions src/staking-v3/logic/repositories/DappStakingRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ export class DappStakingRepository implements IDappStakingRepository {
api.consts.dappStaking.maxNumberOfStakedContracts
)).toNumber(),
maxNumberOfContracts: (<u32>api.consts.dappStaking.maxNumberOfContracts).toNumber(),
maxUnlockingChunks: (<u32>api.consts.dappStaking.maxUnlockingChunks).toNumber(),
standardErasPerBuildAndEarnPeriod: 10, // (<u32>(
// api.consts.dappStaking.standardErasPerBuildAndEarnPeriod
// )).toNumber(),
Expand Down

0 comments on commit 246f020

Please sign in to comment.