Skip to content

Commit

Permalink
feat: continue
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsimao committed Aug 28, 2023
1 parent 4e538ae commit 17e4132
Show file tree
Hide file tree
Showing 15 changed files with 334 additions and 86 deletions.
1 change: 1 addition & 0 deletions src/assets/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
"rewards_apr_ticker": "Rewards APR {{ticker}}",
"wallet": "Wallet",
"learn_more": "Learn more",
"stake": "Stake",
"navigation": {
"btc": "BTC",
"strategies": "Strategies",
Expand Down
22 changes: 21 additions & 1 deletion src/hooks/api/escrow/use-get-account-staking-data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { MonetaryAmount } from '@interlay/monetary-js';
import { AccountId } from '@polkadot/types/interfaces';
import Big from 'big.js';
import { add } from 'date-fns';
import { useCallback } from 'react';
import { useErrorHandler } from 'react-error-boundary';
import { useQuery } from 'react-query';

import { BLOCK_TIME } from '@/config/parachain';
import { REFETCH_INTERVAL } from '@/utils/constants/api';
import { convertWeeksToBlockNumbers } from '@/utils/helpers/staking';

import useAccountId from '../../use-account-id';

Expand All @@ -19,6 +21,7 @@ type AccountUnlockStakingData = {
type AccountStakingData = {
unlock: AccountUnlockStakingData;
balance: MonetaryAmount<CurrencyExt>;
endBlock: number;
votingBalance: MonetaryAmount<CurrencyExt>;
claimableRewards: MonetaryAmount<CurrencyExt>;
projected: {
Expand Down Expand Up @@ -62,6 +65,7 @@ const getAccountStakingData = async (accountId: AccountId): Promise<AccountStaki
return {
unlock,
balance: stakedBalance.amount,
endBlock: stakedBalance.endBlock,
votingBalance,
claimableRewards,
projected
Expand All @@ -70,6 +74,7 @@ const getAccountStakingData = async (accountId: AccountId): Promise<AccountStaki

interface UseGetAccountStakingDataResult {
data: AccountStakingData | null | undefined;
getUnlockHeight: (lockTime: number) => Promise<number>;
refetch: () => void;
}

Expand All @@ -85,9 +90,24 @@ const useGetAccountStakingData = (): UseGetAccountStakingDataResult => {
enabled: !!accountId
});

const getUnlockHeight = useCallback(
async (lockTime: number) => {
const newLockBlockNumber = convertWeeksToBlockNumbers(lockTime);

if (data) {
return data.endBlock + newLockBlockNumber;
}

const currentBlockNumber = await window.bridge.system.getCurrentBlockNumber();

return currentBlockNumber + newLockBlockNumber;
},
[data]
);

useErrorHandler(error);

return { data, refetch };
return { data, refetch, getUnlockHeight };
};

export { useGetAccountStakingData };
Expand Down
57 changes: 42 additions & 15 deletions src/hooks/api/escrow/use-get-staking-estimation-data.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
import { CurrencyExt } from '@interlay/interbtc-api';
import { CurrencyExt, newMonetaryAmount } from '@interlay/interbtc-api';
import { MonetaryAmount } from '@interlay/monetary-js';
import { AccountId } from '@polkadot/types/interfaces';
import Big from 'big.js';
import { useMutation, UseMutationOptions, UseMutationResult } from 'react-query';
import { useRef } from 'react';
import { MutationFunction, useMutation, UseMutationOptions, UseMutationResult } from 'react-query';

import { GOVERNANCE_TOKEN } from '@/config/relay-chains';
import { convertWeeksToBlockNumbers } from '@/utils/helpers/staking';

import useAccountId from '../../use-account-id';
import { AccountStakingData, useGetAccountStakingData } from './use-get-account-staking-data';

type GetAccountStakingEstimationData = {
type AccountStakingEstimationData = {
amount: MonetaryAmount<CurrencyExt>;
apy: Big;
};

const getRewardEstimate = async (accountId?: AccountId, amount?: MonetaryAmount<CurrencyExt>, lockTime?: number) => {
if (!accountId || !(amount && lockTime)) return;
const getRewardEstimate = async (
accountId?: AccountId,
accountData?: AccountStakingData | null,
amount: MonetaryAmount<CurrencyExt> = newMonetaryAmount(0, GOVERNANCE_TOKEN),
lockTime = 0
): Promise<AccountStakingEstimationData | undefined> => {
if (!accountId) return;

const baseBlockNumber = accountData?.endBlock || (await window.bridge.system.getCurrentBlockNumber());

const newBlockNumber = baseBlockNumber + convertWeeksToBlockNumbers(lockTime);

return window.bridge.escrow.getRewardEstimate(accountId, amount, lockTime);
return window.bridge.escrow.getRewardEstimate(accountId, amount, newBlockNumber);
};

type StakingEstimationVariables = {
Expand All @@ -23,31 +37,44 @@ type StakingEstimationVariables = {
};

type UseGetStakingEstimationOptions = UseMutationOptions<
GetAccountStakingEstimationData | undefined,
AccountStakingEstimationData | undefined,
Error,
StakingEstimationVariables,
unknown
>;

type GetAccountStakingEstimationDataResult = UseMutationResult<
GetAccountStakingEstimationData | undefined,
type UseGetAccountStakingEstimationDataResult = UseMutationResult<
AccountStakingEstimationData | undefined,
Error,
StakingEstimationVariables,
unknown
>;

const useGetStakingEstimationData = (
options?: UseGetStakingEstimationOptions
): GetAccountStakingEstimationDataResult => {
): UseGetAccountStakingEstimationDataResult => {
const accountId = useAccountId();
const resultRef = useRef<AccountStakingEstimationData>();

const accountData = useGetAccountStakingData();

const fn: MutationFunction<AccountStakingEstimationData | undefined, StakingEstimationVariables> = ({
amount,
lockTime
}) => getRewardEstimate(accountId, accountData.data, amount, lockTime);

const mutation = useMutation(
({ amount, lockTime }) => getRewardEstimate(accountId, amount, lockTime) as any,
options
const mutation = useMutation<AccountStakingEstimationData | undefined, Error, StakingEstimationVariables, unknown>(
fn,
{
...options,
onSuccess: (data) => {
resultRef.current = data;
}
}
);

return mutation;
return { ...mutation, data: resultRef.current } as UseGetAccountStakingEstimationDataResult;
};

export { useGetStakingEstimationData };
export type { GetAccountStakingEstimationData, GetAccountStakingEstimationDataResult };
export type { AccountStakingEstimationData, UseGetAccountStakingEstimationDataResult };
2 changes: 1 addition & 1 deletion src/hooks/transaction/extrinsics/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const getLibExtrinsic = async (params: LibActions): Promise<ExtrinsicData> => {
case Transaction.ESCROW_INCREASE_LOOKED_TIME_AND_AMOUNT: {
const [amount, unlockHeight] = params.args;
const txs = [
window.bridge.api.tx.escrow.increaseAmount(amount),
window.bridge.api.tx.escrow.increaseAmount(amount.toString(true)),
window.bridge.api.tx.escrow.increaseUnlockHeight(unlockHeight)
];
const batch = window.bridge.api.tx.utility.batchAll(txs);
Expand Down
7 changes: 5 additions & 2 deletions src/hooks/transaction/types/escrow.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { InterBtcApi } from '@interlay/interbtc-api';
import { CurrencyExt, InterBtcApi } from '@interlay/interbtc-api';
import { MonetaryAmount } from '@interlay/monetary-js';

import { Transaction } from '.';

Expand All @@ -7,10 +8,12 @@ interface EscrowCreateLockAction {
args: Parameters<InterBtcApi['escrow']['createLock']>;
}

type CustomEscrowInscreaseLookedTimeAndAmountArgs = [amount: MonetaryAmount<CurrencyExt>];

interface EscrowInscreaseLookedTimeAndAmountAction {
type: Transaction.ESCROW_INCREASE_LOOKED_TIME_AND_AMOUNT;
args: [
...Parameters<InterBtcApi['api']['tx']['escrow']['increaseAmount']>,
...CustomEscrowInscreaseLookedTimeAndAmountArgs,
...Parameters<InterBtcApi['api']['tx']['escrow']['increaseUnlockHeight']>
];
}
Expand Down
17 changes: 17 additions & 0 deletions src/hooks/transaction/utils/fee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,20 @@ const getAmount = (params: Actions): MonetaryAmount<CurrencyExt>[] | undefined =
return [calculatedLimit];
}
/* END - LOANS */
/* START - ESCROW */
case Transaction.ESCROW_CREATE_LOCK: {
const [amount] = params.args;
return [amount];
}
case Transaction.ESCROW_INCREASE_LOOKED_TIME_AND_AMOUNT: {
const [amount] = params.args;
return [amount];
}
case Transaction.ESCROW_INCREASE_LOCKED_AMOUNT: {
const [amount] = params.args;
return [amount];
}
/* END - ESCROW */
case Transaction.STRATEGIES_DEPOSIT: {
const [, amount] = params.args;
return [amount];
Expand All @@ -178,6 +192,9 @@ const getAmount = (params: Actions): MonetaryAmount<CurrencyExt>[] | undefined =
case Transaction.STRATEGIES_ALL_WITHDRAW:
case Transaction.STRATEGIES_WITHDRAW:
case Transaction.AMM_CLAIM_REWARDS:
case Transaction.ESCROW_INCREASE_LOCKED_TIME:
case Transaction.ESCROW_WITHDRAW:
case Transaction.ESCROW_WITHDRAW_REWARDS:
return undefined;
}

Expand Down
19 changes: 16 additions & 3 deletions src/lib/form/schemas/staking.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// import i18n from 'i18next';

import yup, { MaxAmountValidationParams, MinAmountValidationParams } from '../yup.custom';

const STAKING_AMOUNT_FIELD = 'staking-amount';
Expand All @@ -23,20 +25,31 @@ const stakingSchema = (params: StakingValidationParams): yup.ObjectSchema<any> =
yup.object().shape({
[STAKING_AMOUNT_FIELD]: yup
.string()
.requiredAmount('transfer')
// .when([STAKING_LOCK_TIME_AMOUNT_FIELD], {
// is: !hasStaked,
// then: yup.number().required(i18n.t('forms.please_enter_your_field', { field: 'stake' }))
// })
// .requiredAmount('stake')
.maxAmount(params[STAKING_AMOUNT_FIELD] as MaxAmountValidationParams)
.minAmount(params[STAKING_AMOUNT_FIELD] as MinAmountValidationParams, 'transfer'),
[STAKING_FEE_TOKEN_FIELD]: yup.string().required(),
[STAKING_LOCK_TIME_AMOUNT_FIELD]: yup
.number()
// .test('is-required', i18n.t('forms.please_enter_your_field', { field: 'lock time' }), (value) =>
// hasStaked ? true : value !== undefined
// )
// .when([], {
// is: !hasStaked,
// then: yup.number().required(i18n.t('forms.please_enter_your_field', { field: 'lock time' }))
// })
.min(
params[STAKING_LOCK_TIME_AMOUNT_FIELD].min,
`Lock time must be greater than or equal to ${params[STAKING_LOCK_TIME_AMOUNT_FIELD].min}`
)
.max(
params[STAKING_LOCK_TIME_AMOUNT_FIELD].max,
`Lock time must be less than or equal to ${params[STAKING_LOCK_TIME_AMOUNT_FIELD].max}`
)
),
[STAKING_FEE_TOKEN_FIELD]: yup.string().required()
});

export { STAKING_AMOUNT_FIELD, STAKING_FEE_TOKEN_FIELD, STAKING_LOCK_TIME_AMOUNT_FIELD, stakingSchema };
Expand Down
6 changes: 3 additions & 3 deletions src/pages/Staking copy/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ const Staking = (): JSX.Element => {
const extensionTime =
(stakedAmountAndEndBlock?.endBlock || currentBlockNumber) + convertWeeksToBlockNumbers(lockTimeValue);

console.log(stakedAmountAndEndBlock?.endBlock, currentBlockNumber, convertWeeksToBlockNumbers(lockTimeValue));

setBlockLockTimeExtension(extensionTime);
}, [currentBlockNumber, lockTime, stakedAmountAndEndBlock]);

Expand Down Expand Up @@ -372,7 +374,7 @@ const Staking = (): JSX.Element => {

existingStakeTransaction.execute(
Transaction.ESCROW_INCREASE_LOOKED_TIME_AND_AMOUNT,
monetaryAmount.toString(true),
monetaryAmount,
unlockHeight
);
} else if (checkOnlyIncreaseLockAmount(numberTime, monetaryAmount)) {
Expand Down Expand Up @@ -583,8 +585,6 @@ const Staking = (): JSX.Element => {
newLockingAmount = monetaryLockingAmount.add(stakedAmount);
}

console.log(newLockTime);

// Multiplying the new total staked governance token with the staking time divided by the maximum lock time
return newLockingAmount.mul(newLockTime).div(STAKE_LOCK_TIME.MAX);
};
Expand Down
31 changes: 9 additions & 22 deletions src/pages/Staking/Staking.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,28 @@
import { format } from 'date-fns';
import { useTranslation } from 'react-i18next';

import { Card, Flex, P } from '@/component-library';
import { AuthCTA, MainContainer } from '@/components';
import { GOVERNANCE_TOKEN } from '@/config/relay-chains';
import { Flex } from '@/component-library';
import { MainContainer } from '@/components';
import { useGetAccountStakingData } from '@/hooks/api/escrow/use-get-account-staking-data';
import { useGetNetworkStakingData } from '@/hooks/api/escrow/uset-get-network-staking-data';
import FullLoadingSpinner from '@/legacy-components/FullLoadingSpinner';
import { YEAR_MONTH_DAY_PATTERN } from '@/utils/constants/date-time';

import { StakingAccountDetails } from './components';
import { StakingWithdrawCard } from './components/StakingWithdrawCard';
import { StyledStakingForm, StyledWrapper } from './Staking.style';

const Staking = (): JSX.Element => {
const { t } = useTranslation();
const { data: accountStakingData, refetch: refetchAccountStakingData } = useGetAccountStakingData();
const { data: networkStakingData } = useGetNetworkStakingData();
const { data: accountData, refetch: refetchAccountData } = useGetAccountStakingData();
const { data: networkData } = useGetNetworkStakingData();

if (accountStakingData === undefined || networkStakingData === undefined) {
if (accountData === undefined || networkData === undefined) {
return <FullLoadingSpinner />;
}

return (
<MainContainer>
<StyledWrapper gap='spacing8'>
<StyledStakingForm accountData={accountStakingData} networkData={networkStakingData} />
<StyledStakingForm accountData={accountData} networkData={networkData} onStaking={refetchAccountData} />
<Flex direction='column' gap='spacing4'>
<StakingAccountDetails data={accountStakingData} onClaimRewards={refetchAccountStakingData} />
{accountStakingData && (
<Card direction='column' gap='spacing4'>
<P size='s'>
Withdraw Staked {GOVERNANCE_TOKEN.ticker} on{' '}
{format(accountStakingData.unlock.date, YEAR_MONTH_DAY_PATTERN)}
</P>
<AuthCTA>{t('withdraw')}</AuthCTA>
</Card>
)}
<StakingAccountDetails data={accountData} onVotingClaimRewards={refetchAccountData} />
{accountData && <StakingWithdrawCard data={accountData} onClaimRewards={refetchAccountData} />}
</Flex>
</StyledWrapper>
</MainContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,22 @@ import { Transaction, useTransaction } from '@/hooks/transaction';

type Props = {
data: AccountStakingData | null;
onClaimRewards: () => void;
onVotingClaimRewards: () => void;
};

type InheritAttrs = CardProps & Props;

type StakingAccountDetailsProps = Props & InheritAttrs;

const StakingAccountDetails = ({ data, onClaimRewards, ...props }: StakingAccountDetailsProps): JSX.Element | null => {
const StakingAccountDetails = ({
data,
onVotingClaimRewards,
...props
}: StakingAccountDetailsProps): JSX.Element | null => {
const { t } = useTranslation();

const transaction = useTransaction(Transaction.ESCROW_WITHDRAW_REWARDS, {
onSuccess: onClaimRewards
onSuccess: onVotingClaimRewards
});

const handlePress = () => transaction.execute();
Expand Down
Loading

0 comments on commit 17e4132

Please sign in to comment.