Skip to content

Commit

Permalink
Restake rewards (#1358)
Browse files Browse the repository at this point in the history
* Bonus rewards distribution per dApp

* Error fix

* Restake initial implementation

* Text fix

* Code cleanup

* Button color fix

* Restake on claim

* Disable restaking if no stakes
  • Loading branch information
bobo-k2 authored Aug 16, 2024
1 parent be0e2e1 commit 99561ac
Show file tree
Hide file tree
Showing 16 changed files with 430 additions and 94 deletions.
9 changes: 9 additions & 0 deletions src/i18n/en-US/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,15 @@ export default {
'Stake to essential projects that enhance the productivity and functionality of Web3.',
othersDescription: 'Explore a diverse set of blockchain dApps.',
basicAprPlusBonus: 'Basic APR + Bonus',
restake: {
title: 'Re-stake your rewards',
description:
'Would you like to re-stake your rewards today? This will increase your daily staking rewards.',
restakeConfirmation: 'Yes re-stake my rewards',
restakeCancelation: 'No I would not wish to re-stake my rewards',
rewardDistribution:
'All rewards will be proportionally distributed to the dApps you are currently staking on.',
},
},
bridge: {
selectBridge: 'Select a Bridge',
Expand Down
100 changes: 100 additions & 0 deletions src/staking-v3/components/ClaimAndRestakeButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<template>
<div @click="setShowRestakeModal(true)">
<slot>
<astar-button :disabled="amountToClaim <= 0" :width="width" :height="height">
{{ $t('stakingV3.claim') }}
</astar-button>
</slot>
<Teleport to="#app--main">
<modal-restake
:show="showRestakeModal"
:set-is-open="setShowRestakeModal"
:rewards="amountToClaim"
:on-confirm="handleRestakeConfirm"
/>
</Teleport>
</div>
</template>

<script lang="ts">
import { defineComponent, ref, computed } from 'vue';
import ModalRestake from './vote/re-stake/ModalRestake.vue';
import { useDappStaking, useVote } from '../hooks';
import { ClaimType } from '../logic';
export default defineComponent({
components: {
ModalRestake,
},
props: {
claimType: {
type: Number,
required: false,
default: ClaimType.Staker,
},
width: {
type: Number,
required: false,
default: 100,
},
height: {
type: Number,
required: false,
default: 32,
},
},
setup(props) {
const {
totalStakerRewards,
rewards,
stakerInfo,
claimStakerRewards,
claimBonusRewards,
claimStakerAndBonusRewards,
} = useDappStaking();
const { vote } = useVote(ref([]));
const showRestakeModal = ref<boolean>(false);
const amountToClaim = computed<bigint>(() => {
if (props.claimType === ClaimType.Staker) {
return rewards.value.staker.amount;
} else if (props.claimType === ClaimType.Bonus) {
return rewards.value.bonus;
} else {
return totalStakerRewards.value;
}
});
const setShowRestakeModal = async (value: boolean) => {
// Idea is to restake proportionally to already staked dApps.
// At the beginning of a period all stakes are reset so user will be able to claim rewards only.
if (value && stakerInfo.value.size === 0) {
await handleRestakeConfirm(false);
} else {
showRestakeModal.value = value;
}
};
const handleRestakeConfirm = async (restake: boolean): Promise<void> => {
if (restake && stakerInfo.value.size > 0) {
await vote(restake);
} else {
if (props.claimType === ClaimType.Staker) {
await claimStakerRewards();
} else if (props.claimType === ClaimType.Bonus) {
await claimBonusRewards();
} else {
await claimStakerAndBonusRewards();
}
}
};
return {
showRestakeModal,
amountToClaim,
setShowRestakeModal,
handleRestakeConfirm,
};
},
});
</script>
39 changes: 9 additions & 30 deletions src/staking-v3/components/PeriodInfoBuild.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,7 @@
</div>
</div>
<div>
<astar-button
:disabled="!hasStakerRewards"
:height="32"
:width="100"
@click="claimStakerRewards()"
>{{ $t('stakingV3.claim') }}</astar-button
>
<claim-and-restake-button :claim-type="ClaimType.Staker" />
</div>
</div>
<div class="rewards-row">
Expand All @@ -62,13 +56,7 @@
</div>
</div>
<div>
<astar-button
:disabled="!hasBonusRewards"
:height="32"
:width="100"
@click="claimBonusRewards()"
>{{ $t('stakingV3.claim') }}</astar-button
>
<claim-and-restake-button :claim-type="ClaimType.Bonus" />
</div>
</div>
</div>
Expand All @@ -79,24 +67,18 @@

<script lang="ts">
import { defineComponent, ref, watch, computed } from 'vue';
import { ethers } from 'ethers';
import { truncate } from '@astar-network/astar-sdk-core';
import { PeriodType } from 'src/staking-v3/logic';
import { PeriodType, ClaimType } from 'src/staking-v3/logic';
import { useAprV3, useDappStaking, useDappStakingNavigation, usePeriod } from '../hooks';
import GradientKpi from './GradientKpi.vue';
import TokenBalanceNative from 'src/components/common/TokenBalanceNative.vue';
import { ethers } from 'ethers';
import ClaimAndRestakeButton from './ClaimAndRestakeButton.vue';
export default defineComponent({
components: { GradientKpi, TokenBalanceNative },
components: { GradientKpi, TokenBalanceNative, ClaimAndRestakeButton },
setup() {
const {
protocolState,
rewards,
hasStakerRewards,
hasBonusRewards,
claimStakerRewards,
claimBonusRewards,
} = useDappStaking();
const { protocolState, rewards } = useDappStaking();
const { navigateToAssets } = useDappStakingNavigation();
const { remainingEras } = usePeriod();
const { stakerApr, bonusApr, getEstimatedBonus } = useAprV3({ isWatch: true });
Expand All @@ -119,17 +101,14 @@ export default defineComponent({
return {
PeriodType,
ClaimType,
protocolState,
remainingEras,
stakerApr,
bonusApr,
rewards,
bonusToDisplay,
hasStakerRewards,
hasBonusRewards,
formatApr,
claimStakerRewards,
claimBonusRewards,
navigateToAssets,
};
},
Expand Down Expand Up @@ -175,7 +154,7 @@ export default defineComponent({
.rewards-row {
display: flex;
width: 100%;
align-items: flex-end;
align-items: center;
justify-content: space-between;
font-size: 14px;
gap: 16px;
Expand Down
18 changes: 7 additions & 11 deletions src/staking-v3/components/PeriodInfoVote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,7 @@
</div>
<div class="reward-options">
<token-balance-native class="balance" :balance="totalStakerRewards.toString()" />
<astar-button
:disabled="totalStakerRewards === BigInt(0)"
:height="32"
:width="100"
@click="claimStakerAndBonusRewards()"
>{{ $t('stakingV3.claim') }}</astar-button
>
<claim-and-restake-button :claim-type="ClaimType.Both" />
</div>
</div>
<div class="reward-info">
Expand All @@ -56,29 +50,31 @@
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { useAprV3, useDappStaking, useDappStakingNavigation, useVotingCountdown } from '../hooks';
import { PeriodType } from 'src/staking-v3/logic';
import { PeriodType, ClaimType } from 'src/staking-v3/logic';
import TokenBalanceNative from 'src/components/common/TokenBalanceNative.vue';
import ClaimAndRestakeButton from './ClaimAndRestakeButton.vue';
export default defineComponent({
components: {
TokenBalanceNative,
ClaimAndRestakeButton,
},
setup() {
const { protocolState, totalStakerRewards, claimStakerAndBonusRewards } = useDappStaking();
const { protocolState, totalStakerRewards } = useDappStaking();
const { navigateToAssets } = useDappStakingNavigation();
const { timeLeftFormatted } = useVotingCountdown();
const { stakerApr, bonusApr } = useAprV3({ isWatch: true });
const totalApr = computed<number>(() => stakerApr.value + bonusApr.value);
return {
PeriodType,
ClaimType,
protocolState,
timeLeftFormatted,
PeriodType,
totalStakerRewards,
totalApr,
navigateToAssets,
claimStakerAndBonusRewards,
};
},
});
Expand Down
44 changes: 23 additions & 21 deletions src/staking-v3/components/my-staking/MyStaking.vue
Original file line number Diff line number Diff line change
Expand Up @@ -128,34 +128,32 @@
:is-tool-tip="!!bonus"
:text-tool-tip="$t('stakingV3.bonusTip')"
/>
<button
<claim-and-restake-button
v-if="width <= screenSize.sm"
class="btn--claim-mobile"
:disabled="!hasStakerRewards && !hasBonusRewards"
@click="claimStakerAndBonusRewards()"
:claim-type="ClaimType.Both"
:width="400"
>
{{ $t('stakingV3.claimNow') }}
</button>
<button class="btn--claim-mobile" :disabled="!hasStakerRewards && !hasBonusRewards">
{{ $t('stakingV3.claimNow') }}
</button>
</claim-and-restake-button>
<img
class="bg--rewards"
:src="require('/src/staking-v3/assets/unclaimed_rewards_bg.webp')"
alt=""
/>
</div>
<button
v-if="width >= screenSize.sm"
class="btn--claim"
:disabled="!hasStakerRewards && !hasBonusRewards"
@click="claimStakerAndBonusRewards()"
>
<span class="text--label">{{ $t('stakingV3.claimEstimatedRewards') }}</span>
<span class="text--balance">
<span class="text--amount">
{{ $n(truncate(ethers.utils.formatEther(totalStakerRewards.toString()) ?? '0', 2)) }}
<claim-and-restake-button v-if="width >= screenSize.sm" :claim-type="ClaimType.Both">
<button class="btn--claim" :disabled="!hasStakerRewards && !hasBonusRewards">
<span class="text--label">{{ $t('stakingV3.claimEstimatedRewards') }}</span>
<span class="text--balance">
<span class="text--amount">
{{ $n(truncate(ethers.utils.formatEther(totalStakerRewards.toString()) ?? '0', 2)) }}
</span>
<div class="text--symbol">{{ nativeTokenSymbol }}</div>
</span>
<div class="text--symbol">{{ nativeTokenSymbol }}</div>
</span>
</button>
</button>
</claim-and-restake-button>
</div>
<modal-unlock-tokens
v-if="lockedButUnstaked > BigInt(0)"
Expand All @@ -177,13 +175,16 @@ import { useNetworkInfo, useBreakpoints } from 'src/hooks';
import { truncate } from '@astar-network/astar-sdk-core';
import Balloon from 'src/components/common/Balloon.vue';
import ModalUnlockTokens from './ModalUnlockTokens.vue';
import ClaimAndRestakeButton from '../ClaimAndRestakeButton.vue';
import { ClaimType } from 'src/staking-v3/logic';
export default defineComponent({
components: {
MyStakingCard,
TokenBalanceNative,
Balloon,
ModalUnlockTokens,
ClaimAndRestakeButton,
},
props: {
tabSelected: {
Expand All @@ -202,7 +203,6 @@ export default defineComponent({
totalStake,
protocolState,
eraLengths,
claimStakerAndBonusRewards,
formatPeriod,
} = useDappStaking();
Expand Down Expand Up @@ -264,6 +264,7 @@ export default defineComponent({
watchEffect(setBonus);
return {
ClaimType,
rewards,
totalStakerRewards,
hasStakerRewards,
Expand All @@ -283,7 +284,6 @@ export default defineComponent({
closeLockedBalloon,
closeStakedBalloon,
truncate,
claimStakerAndBonusRewards,
navigateToVote,
handleTabSelected,
formatPeriod,
Expand Down Expand Up @@ -474,6 +474,7 @@ export default defineComponent({
background: linear-gradient(101deg, #0297fb 50.27%, #0070eb 88.26%, #0ae2ff 173.42%);
line-height: 1.25;
transition: all 0.2s ease;
cursor: pointer;
&:hover {
filter: brightness(1.2);
}
Expand Down Expand Up @@ -502,6 +503,7 @@ export default defineComponent({
}
.btn--claim-mobile {
width: 100%;
padding: 8px;
border-radius: 9999px;
background: linear-gradient(101deg, #0297fb 50.27%, #0070eb 88.26%, #0ae2ff 173.42%);
Expand Down
Loading

0 comments on commit 99561ac

Please sign in to comment.