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

vote and dictionary changes #1037

Merged
merged 3 commits into from
Nov 21, 2023
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
29 changes: 17 additions & 12 deletions src/i18n/en-US/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -670,19 +670,24 @@ export default {
},
stakingV3: {
title: 'dApp Staking v3',
amountGreater0: 'Amount must be greater than 0.',
periodEndsNextEra: 'Period ends in the next era.',
noDappSelected: 'No dApp selected.',
stakerRewardsExpired: 'Staker rewards expired.',
disabled: 'Pallet is disabled/in maintenance mode.',
unstakeFromPastPeriod:
'Unstaking is rejected since the period in which past stake was active has passed.',
unstakeAmountTooLarge: 'Unstake amount is greater than the staked amount.',
unclaimedRewardsFromPastPeriods:
'There are unclaimed rewards remaining from past periods. They should be claimed before staking again.',
tooManyStakedContracts:
'There are too many contract stake entries for the account. This can be cleaned up by either unstaking or cleaning expired entries.',
unavailableStakeFunds:
'The staking amount surpasses the current balance available for staking.',
dappStaking: {
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',
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.',
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.',
UnstakeAmountTooLarge: 'Unstake amount is greater than the staked amount.',
UnstakeFromPastPeriod:
'Unstaking is rejected since the period in which past stake was active has passed.',
ZeroAmount: 'Amount must be greater than 0.',
},
successfullyStaked: 'You successfully staked to {contractAddress}',
voteTitle: 'Vote!',
minimumStakingAmount: 'Minimum staking amount is {amount} {symbol}',
Expand Down
68 changes: 57 additions & 11 deletions src/staking-v3/components/Vote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
</div>
<div class="wrapper--button">
<astar-button
:disabled="!canConfirm"
:disabled="!isConfirmable"
style="width: 100%; height: 52px; font-size: 22px"
@click="confirm"
>
Expand All @@ -103,6 +103,10 @@ import Amount from './Amount.vue';
import FormatBalance from 'src/components/common/FormatBalance.vue';
import { ethers } from 'ethers';
import { abs } from 'src/v2/common';
import { useStore } from 'src/store';
import { useI18n } from 'vue-i18n';
import BN from 'bn.js';
import { PeriodType } from '../logic';

export default defineComponent({
components: {
Expand All @@ -125,9 +129,39 @@ export default defineComponent({
const stakeToken = ethers.utils.parseEther(stakeAmount.value.toString()).toBigInt();
return locked.value - stakeToken - totalStake.value;
});
const canConfirm = computed<boolean>(
() => !!selectedDapp.value?.address && stakeAmount.value > 0
);

const { t } = useI18n();
const store = useStore();
const protocolState = computed(() => store.getters['stakingV3/getProtocolState']);
const balanceBN = computed(() => new BN(useableBalance.value.toString()));

const canConfirm = (): [boolean, string] => {
const stakeAmountBN = new BN(
ethers.utils.parseEther(stakeAmount.value.toString()).toString()
);

if (!selectedDapp.value?.address) {
// Prevents NoDappSelected
return [false, t('stakingV3.noDappSelected')];
} else if (stakeAmount.value <= 0) {
// Prevents dappStaking.ZeroAmount
return [false, t('stakingV3.dappStaking.ZeroAmount')];
} else if (stakeAmountBN.gt(balanceBN.value)) {
// Prevents dappStaking.UnavailableStakeFunds
return [false, t('stakingV3.dappStaking.UnavailableStakeFunds')];
} else if (protocolState.value?.maintenance) {
// Prevents dappStaking.Disabled
return [false, t('stakingV3.dappStaking.Disabled')];
} else if (
// Prevents dappStaking.PeriodEndsInNextEra
protocolState.value?.periodInfo.subperiod === PeriodType.BuildAndEarn &&
protocolState.value.periodInfo.subperiodEndEra <= protocolState.value.era + 1
) {
return [false, t('stakingV3.dappStaking.PeriodEndsNextEra')];
} // Prevents dappStaking.TooManyStakedContracts

return [true, ''];
};

const dapps = computed<Dapp[]>(() => {
return registeredDapps.value.map((dapp) => ({
Expand All @@ -148,14 +182,17 @@ export default defineComponent({
const confirm = async (): Promise<void> => {
// TODO at the moment only one dApp is supported for staking. This will change in the future.
// If additional funds locking is required remainLockedToken value will be negative.
if (canConfirm) {
const stakeInfo = new Map<string, number>();
stakeInfo.set(selectedDapp.value?.address ?? '', stakeAmount.value);
await claimLockAndStake(
stakeInfo,
remainLockedToken.value < 0 ? remainLockedToken.value * BigInt(-1) : BigInt(0)
);
const [result, error] = canConfirm();
if (!result) {
throw error;
}

const stakeInfo = new Map<string, number>();
stakeInfo.set(selectedDapp.value?.address ?? '', stakeAmount.value);
await claimLockAndStake(
stakeInfo,
remainLockedToken.value < 0 ? remainLockedToken.value * BigInt(-1) : BigInt(0)
);
};

return {
Expand All @@ -175,6 +212,15 @@ export default defineComponent({
abs,
};
},
computed: {
isConfirmable() {
const [confirmable, errorMessage] = this.canConfirm();
if (!confirmable) {
// console.log(errorMessage);
}
return confirmable;
},
},
});
</script>

Expand Down
60 changes: 32 additions & 28 deletions src/staking-v3/hooks/useDappStaking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function useDappStaking() {
const { registeredDapps } = useDapps();
const { decimal } = useChainMetadata();

const { balance, isLoadingBalance } = useBalance(currentAccount);
const { useableBalance } = useBalance(currentAccount);

const protocolState = computed<ProtocolState | undefined>(
() => store.getters['stakingV3/getProtocolState']
Expand Down Expand Up @@ -98,7 +98,7 @@ export function useDappStaking() {
};

const unstake = async (dappAddress: string, amount: number): Promise<void> => {
const [result, error] = await canUnStake(amount);
const [result, error] = await canUnStake(dappAddress, amount);
if (!result) {
throw error;
}
Expand Down Expand Up @@ -190,56 +190,60 @@ export function useDappStaking() {

const canStake = async (amount: number): 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) {
// Prevents ZeroAmount
return [false, t('stakingV3.amountGreater0')];
// Prevents dappStaking.ZeroAmount
return [false, t('stakingV3.dappStaking.ZeroAmount')];
} else if ((ledger.value?.contractStakeCount ?? 0) >= constants.maxNumberOfStakedContracts) {
// Prevents TooManyStakedContracts
return [false, t('stakingV3.tooManyStakedContracts')];
} else if (hasRewards) {
// Prevents UnclaimedRewardsFromPastPeriods
// Prevents dappStaking.TooManyStakedContracts
return [false, t('stakingV3.dappStaking.TooManyStakedContracts')];
} else if (hasRewards.value) {
// Prevents dappStaking.UnclaimedRewardsFromPastPeriods
// May want to auto claim rewards here
return [false, t('stakingV3.unclaimedRewardsFromPastPeriods')];
return [false, t('stakingV3.dappStaking.UnclaimedRewardsFromPastPeriods')];
} else if (protocolState.value?.maintenance) {
// Prevents Disabled
return [false, t('stakingV3.disabled')];
} else if (stakeAmount.gt(balance.value)) {
// Prevents UnavailableStakeFunds
return [false, t('stakingV3.unavailableStakeFunds')];
// 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 PeriodEndsInNextEra
// Prevents dappStaking.PeriodEndsInNextEra
protocolState.value?.periodInfo.subperiod === PeriodType.BuildAndEarn &&
protocolState.value.periodInfo.subperiodEndEra <= protocolState.value.era + 1
) {
return [false, t('stakingV3.periodEndsNextEra')];
return [false, t('stakingV3.dappStaking.PeriodEndsNextEra')];
}

return [true, ''];
};

const canUnStake = async (amount: number): Promise<[boolean, string]> => {
const canUnStake = async (address: 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);

if (amount <= 0) {
// Prevents ZeroAmount
return [false, t('stakingV3.amountGreater0')];
// Prevents dappStaking.ZeroAmount
return [false, t('stakingV3.dappStaking.ZeroAmount')];
} else if (stakeAmount.gt(stakedAmount)) {
// Prevents UnstakeAmountTooLarge
return [false, t('stakingV3.unstakeAmountTooLarge')];
} else if (hasRewards) {
// Prevents UnclaimedRewardsFromPastPeriods
// Prevents dappStaking.UnstakeAmountTooLarge
return [false, t('stakingV3.dappStaking.UnstakeAmountTooLarge')];
} else if (hasRewards.value) {
// Prevents dappStaking.UnclaimedRewardsFromPastPeriods
// May want to auto claim rewards here
return [false, t('stakingV3.unclaimedRewardsFromPastPeriods')];
return [false, t('stakingV3.dappStaking.UnclaimedRewardsFromPastPeriods')];
} else if (protocolState.value?.maintenance) {
// Prevents Disabled
return [false, t('stakingV3.disabled')];
// Prevents dappStaking.Disabled
return [false, t('stakingV3.dappStaking.Disabled')];
} else if (!address) {
// Prevents dappStaking.NoStakingInfo
return [false, t('stakingV3.dappStaking.NoStakingInfo')];
} else if (!amount) {
// Prevents UnstakeFromPastPeriod
return [false, t('stakingV3.unstakeFromPastPeriod')];
// Prevents dappStaking.UnstakeFromPastPeriod
return [false, t('stakingV3.dappStaking.UnstakeFromPastPeriod')];
}

return [true, ''];
Expand Down
Loading