diff --git a/src/components/Modal/TopupTModal/TopUpTModal.tsx b/src/components/Modal/TopupTModal/TopUpTModal.tsx index c15809a26..11eb3009f 100644 --- a/src/components/Modal/TopupTModal/TopUpTModal.tsx +++ b/src/components/Modal/TopupTModal/TopUpTModal.tsx @@ -59,8 +59,15 @@ const TopupTModal: FC< your initial stake. - If you want to put your new topped-up tokens at work, make sure to - increase the authorization to your applications. + If you want to put newly topped-up tokens to work, make sure to + individually increase the total authorization to each Threshold + application (tBTC, Random Beacon & TACo). +
+ If you increase the total number of tokens authorized to the TACo + app, those tokens will automatically be subject to the same unlock + horizon as your current TACo stake, including the min. + deauthorization delay (6 months), plus any lock-up extension on + top of that.
{ - if (isIncreaseAction) onAuthorizeApp(tokenAmount) - else onInitiateDeauthorization(tokenAmount) + if (isIncreaseAction) { + onAuthorizeApp(tokenAmount) + } else { + if (appAuthData.stakingAppId === "taco") { + // const endCommitment = appAuthData.stakingProviderInfo?.endCommitment + const endCommitment = appAuthData.stakingProviderInfo?.endCommitment + const currentTime = Math.floor(Date.now() / 1000) + const isCommited = (Number(endCommitment) ?? 0) > currentTime + const endCommitmentDate = new Date( + (Number(endCommitment) ?? 0) * 1000 + ).toLocaleDateString() + if (isCommited) { + alert( + `Your tokens remain committed until ${endCommitmentDate}, at which point you may initiate deauthorization.` + ) + } else { + onInitiateDeauthorization(tokenAmount) + } + } else { + onInitiateDeauthorization(tokenAmount) + } + } } const onConfirmDeauthorization = () => { diff --git a/src/pages/Staking/StakeDetailsPage/index.tsx b/src/pages/Staking/StakeDetailsPage/index.tsx index 36c638576..4255e0e28 100644 --- a/src/pages/Staking/StakeDetailsPage/index.tsx +++ b/src/pages/Staking/StakeDetailsPage/index.tsx @@ -75,6 +75,12 @@ const StakeDetailsPage: FC = () => { stakingProviderAddress || AddressZero ) + const endCommitment = tacoApp.stakingProviderInfo?.endCommitment + const isCommited = (Number(endCommitment) ?? 0) > 0 + const endCommitmentDate = new Date( + (Number(endCommitment) ?? 0) * 1000 + ).toLocaleDateString() + const isInActiveStake = BigNumber.from(stake?.totalInTStake ?? "0").isZero() const { total: rewardsForStake } = useAppSelector((state) => @@ -166,10 +172,12 @@ const StakeDetailsPage: FC = () => { - {tacoApp.isAuthorized && ( + {tacoApp.isAuthorized && !isCommited ? ( + ) : ( +

Your commitment ends on {endCommitmentDate}

)} ) : ( diff --git a/src/store/staking-applications/slice.ts b/src/store/staking-applications/slice.ts index 4cd0fe065..df6712064 100644 --- a/src/store/staking-applications/slice.ts +++ b/src/store/staking-applications/slice.ts @@ -287,6 +287,7 @@ export const stakingApplicationsSlice = createSlice({ deauthorizationCreatedAt: undefined, isOperatorInPool: undefined, operator: AddressZero, + stakingProviderInfo: undefined, } state.randomBeacon.stakingProviders.data[stakingProvider] = { diff --git a/src/threshold-ts/applications/index.ts b/src/threshold-ts/applications/index.ts index cecbb2985..674efe2f9 100644 --- a/src/threshold-ts/applications/index.ts +++ b/src/threshold-ts/applications/index.ts @@ -38,6 +38,20 @@ export interface AuthorizationParameters< authorizationDecreaseChangePeriod: NumberType } +export interface StakingProviderInfo< + NumberType extends BigNumberish = BigNumber +> { + operator: string + operatorConfirmed: boolean + operatorStartTimestamp: NumberType + authorized: NumberType + deauthorizing: NumberType + endDeauthorization: NumberType + tReward: NumberType + rewardPerTokenPaid: NumberType + endCommitment: NumberType +} + export interface StakingProviderAppInfo< NumberType extends BigNumberish = BigNumber > { @@ -75,6 +89,8 @@ export interface StakingProviderAppInfo< * it means that the operator for a given staking provider is not set. */ isOperatorInPool: boolean | undefined + + stakingProviderInfo?: StakingProviderInfo | undefined } /** @@ -202,6 +218,8 @@ export interface IApplication { */ stakingProviderToOperator(stakingProvider: string): Promise + stakingProviderInfo(stakingProvider: string): Promise + /** * Used to get staking provider address mapped to the given registered * operator address @@ -314,6 +332,15 @@ export class Application implements IApplication { }, ] + const tacoCalls: ContractCall[] = [ + { + interface: this.contract.interface, + address: this.contract.address, + method: "stakingProviderInfo", + args: [stakingProvider], + }, + ] + const [ authorizedStake, pendingAuthorizationDecrease, @@ -323,6 +350,14 @@ export class Application implements IApplication { [operator], ] = await this._multicall.aggregate(calls) + let stakingProviderInfo + try { + ;[stakingProviderInfo] = await this._multicall.aggregate(tacoCalls) + } catch (error) { + console.warn("Failed to aggregate tacoCalls", error) + stakingProviderInfo = undefined + } + let isOperatorInPool = undefined if (operator && !isAddressZero(operator)) { try { @@ -368,6 +403,7 @@ export class Application implements IApplication { deauthorizationCreatedAt, isOperatorInPool, operator, + stakingProviderInfo, } } @@ -448,6 +484,12 @@ export class Application implements IApplication { ) } + stakingProviderInfo = async ( + stakingProvider: string + ): Promise => { + return await this._application.stakingProviderInfo(stakingProvider) + } + stakingProviderToOperator = async ( stakingProvider: string ): Promise => {