Skip to content

Commit

Permalink
feat(evm): disable stake strategies
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsimao committed Dec 19, 2024
1 parent d299182 commit 3cca3cf
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const getLabel = (status: GatewaySteps, confirmations: number, totalConfirmation
case 'l2-confirmation':
return 'L2 confirmation';
case 'l2-incomplete':
return 'L2 incomplete';
return 'L2 partial success';
}
};

Expand Down
13 changes: 12 additions & 1 deletion apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ type BridgeParams = {

type UseGatewayLiquidityProps = {
params: BridgeParams | StakeParams;
isDisabled?: boolean;
onMutate?: (data: Optional<InitGatewayTransaction, 'amount'>) => void;
onSuccess?: (data: InitGatewayTransaction) => void;
onError?: () => void;
Expand Down Expand Up @@ -157,7 +158,13 @@ type UseGatewayReturnType = {
isTapRootAddress: boolean;
};

const useGateway = ({ params, onError, onMutate, onSuccess }: UseGatewayLiquidityProps): UseGatewayReturnType => {
const useGateway = ({
params,
isDisabled: isDisabledProp,
onError,
onMutate,
onSuccess
}: UseGatewayLiquidityProps): UseGatewayReturnType => {
const { i18n } = useLingui();
const queryClient = useQueryClient();

Expand Down Expand Up @@ -309,6 +316,10 @@ const useGateway = ({ params, onError, onMutate, onSuccess }: UseGatewayLiquidit
const mutation = useMutation({
mutationKey: bridgeKeys.btcDeposit(evmAddress, btcAddress),
mutationFn: async ({ evmAddress }: { evmAddress: Address | string }): Promise<InitGatewayTransaction> => {
if (isDisabledProp) {
throw new Error('Operation disabled');
}

if (!satsConnector) {
throw new Error('Connector missing');
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { Flex, Input } from '@gobob/ui';
import { Alert, Flex, Input, P } from '@gobob/ui';
import { t, Trans } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { chain, mergeProps } from '@react-aria/utils';
Expand All @@ -9,6 +9,7 @@ import { useAccount } from 'wagmi';

import { BtcTokenInput, GatewayGasSwitch, GatewayTransactionDetails } from '../../../components';
import { useGateway, useGatewayForm } from '../../../hooks';
import { StakingInfo } from '../../../utils/stakeData';

import { StrategyData } from './StakeForm';

Expand All @@ -18,12 +19,13 @@ import { GatewayTransactionType, InitGatewayTransaction } from '@/types';

type BtcBridgeFormProps = {
strategy: StrategyData;
stakingInfo: StakingInfo;
onStart: (data: Optional<InitGatewayTransaction, 'amount'>) => void;
onSuccess: (data: InitGatewayTransaction) => void;
onError: () => void;
};

const BtcStakeForm = ({ strategy, onStart, onSuccess, onError }: BtcBridgeFormProps): JSX.Element => {
const BtcStakeForm = ({ strategy, stakingInfo, onStart, onSuccess, onError }: BtcBridgeFormProps): JSX.Element => {
const { i18n } = useLingui();

const { address: evmAddress } = useAccount();
Expand All @@ -33,6 +35,7 @@ const BtcStakeForm = ({ strategy, onStart, onSuccess, onError }: BtcBridgeFormPr
};

const gateway = useGateway({
isDisabled: !!stakingInfo.isDisabled,
params: {
type: GatewayTransactionType.STAKE,
toChain: strategy?.raw.chain.chainId,
Expand Down Expand Up @@ -63,7 +66,12 @@ const BtcStakeForm = ({ strategy, onStart, onSuccess, onError }: BtcBridgeFormPr
onSubmit: handleSubmit
});

const isDisabled = isSubmitDisabled || gateway.isDisabled || !gateway.isReady || gateway.query.quote.isPending;
const isDisabled =
isSubmitDisabled ||
gateway.isDisabled ||
!gateway.isReady ||
gateway.query.quote.isPending ||
stakingInfo.isDisabled;

const isLoading = gateway.mutation.isPending || gateway.query.quote.isLoading;

Expand Down Expand Up @@ -93,6 +101,13 @@ const BtcStakeForm = ({ strategy, onStart, onSuccess, onError }: BtcBridgeFormPr
assetName={strategy?.raw.integration.name}
gateway={gateway}
/>
{stakingInfo.isDisabled && (
<Alert status='warning' variant='outlined'>
<P size='s'>
<Trans>Staking to {stakingInfo.strategy} is temporarily unavailable.</Trans>
</P>
</Alert>
)}
<AuthButton isBtcAuthRequired color='primary' disabled={isDisabled} loading={isLoading} size='xl' type='submit'>
{gateway.isReady ? <Trans>Stake</Trans> : <Trans>Preparing...</Trans>}
</AuthButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useState } from 'react';

import { GatewayTransactionModal } from '../../../components';
import { StrategyData } from '../../hooks';
import { StakingInfo } from '../../../utils/stakeData';

import { StyledFlex } from './StakeForm.style';
import { BtcStakeForm } from './BtcStakeForm';
Expand All @@ -17,10 +18,11 @@ type GatewayTransactionModalState = {

type BridgeFormProps = {
strategy: StrategyData;
stakingInfo: StakingInfo;
onStakeSuccess?: () => void;
};

const StakingForm = ({ strategy, onStakeSuccess }: BridgeFormProps): JSX.Element => {
const StakingForm = ({ strategy, stakingInfo, onStakeSuccess }: BridgeFormProps): JSX.Element => {
const [gatewayModalState, setGatewayModalState] = useState<GatewayTransactionModalState>({
isOpen: false
});
Expand All @@ -42,6 +44,7 @@ const StakingForm = ({ strategy, onStakeSuccess }: BridgeFormProps): JSX.Element
<>
<StyledFlex direction='column' flex={1}>
<BtcStakeForm
stakingInfo={stakingInfo}
strategy={strategy}
onError={handleCloseGatewayModal}
onStart={handleStartGateway}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Trans } from '@lingui/macro';
import { ReactNode } from 'react';
import { PellNetwork, Spice } from '@gobob/icons';

import { stakingInfo, StakingInfo, Incentive } from '../../../utils/stakeData';
import { stakingInfo, Incentive } from '../../../utils/stakeData';

const SpiceRewards = () => (
<Chip background='primary-500' size='s' startAdornment={<Spice size='xs' />}>
Expand Down Expand Up @@ -77,8 +77,6 @@ const incentivesMap: Record<Incentive, () => ReactNode> = {
[Incentive.supply]: SupplyApr
};

const stakingInfoAny = stakingInfo as StakingInfo;

type Props = {
slug: string;
};
Expand All @@ -90,7 +88,7 @@ type StakeRewardsProps = Props & InheritAttrs;
const StakeRewards = ({ slug, ...props }: StakeRewardsProps) => (
<Flex gap='xs' {...props}>
<SpiceRewards />
{stakingInfoAny[slug]?.incentives.map((incentive, key) => {
{stakingInfo[slug]?.incentives.map((incentive, key) => {
const Comp = incentivesMap[incentive];

return <Comp key={key} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { t, Trans } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { ReactNode, useEffect, useMemo, useState } from 'react';

import { stakingInfo, StakingInfo } from '../../../utils/stakeData';
import { stakingInfo } from '../../../utils/stakeData';
import { StrategyData, useGetStakingStrategies } from '../../hooks';
import { StakeRewards } from '../StakeRewards';
import { StrategyModal } from '../StrategyModal';
Expand Down Expand Up @@ -42,8 +42,6 @@ const columns = [
{ name: '', id: StakeTableColumns.ACTIONS }
];

const stakingInfoAny = stakingInfo as StakingInfo;

interface Props {
searchParams?: { receive: string };
onStakeSuccess: () => void;
Expand Down Expand Up @@ -82,8 +80,8 @@ const StakeTable = ({ searchParams, onStakeSuccess }: Props) => {
<PellNetwork style={{ height: '1.3rem', width: '1.3rem' }} />
)}
<StrategyCell
name={stakingInfoAny[strategy?.raw.integration.slug ?? '']?.strategy as string}
protocol={stakingInfoAny[strategy?.raw.integration.slug ?? '']?.protocol as string}
name={stakingInfo[strategy?.raw.integration.slug ?? '']?.strategy as string}
protocol={stakingInfo[strategy?.raw.integration.slug ?? '']?.protocol as string}
/>
</Flex>
),
Expand All @@ -100,7 +98,7 @@ const StakeTable = ({ searchParams, onStakeSuccess }: Props) => {
<Button
variant='outline'
onPress={() =>
window.open(stakingInfoAny[strategy?.raw.integration.slug ?? '']?.website, '_blank', 'noreferrer')
window.open(stakingInfo[strategy?.raw.integration.slug ?? '']?.website, '_blank', 'noreferrer')
}
>
<Trans>Manage</Trans>
Expand All @@ -119,7 +117,8 @@ const StakeTable = ({ searchParams, onStakeSuccess }: Props) => {
<Table aria-label={t(i18n)`Staking table`} columns={columns} rows={rows} />
{strategy && (
<StrategyModal
stakingInfo={stakingInfoAny[strategy?.raw.integration.slug]}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
stakingInfo={stakingInfo[strategy?.raw.integration.slug] as any}
strategy={strategy}
onCloseModal={() => setStrategy(undefined)}
onStakeSuccess={onStakeSuccess}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
} from '@gobob/ui';
import { truncateUrl } from '@gobob/utils';
import { Trans } from '@lingui/macro';
import { ValueOf } from 'viem';

import { StrategyData } from '../../hooks';
import { StakingForm } from '../StakeForm';
Expand All @@ -30,7 +29,7 @@ import { chainL2 } from '@/constants';
interface Props {
onStakeSuccess: () => void;
strategy: StrategyData;
stakingInfo: ValueOf<StakingInfo>;
stakingInfo: StakingInfo;
onCloseModal: () => void;
}

Expand Down Expand Up @@ -60,7 +59,7 @@ const StrategyModal = ({ strategy, stakingInfo, onStakeSuccess, onCloseModal }:
</ModalHeader>
<ModalBody>
<StyledFlex direction={{ base: 'column', md: 'row' }} gap='xl'>
<StakingForm strategy={strategy} onStakeSuccess={onStakeSuccess} />
<StakingForm stakingInfo={stakingInfo} strategy={strategy} onStakeSuccess={onStakeSuccess} />
<StyledFlex direction='column' flex={1} gap='xl'>
<Dl direction='column' gap='lg'>
<DlGroup alignItems='center' justifyContent='space-between'>
Expand Down
27 changes: 20 additions & 7 deletions apps/evm/src/app/[lang]/(bridge)/utils/stakeData.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Alert, Flex, P } from '@gobob/ui';
import { Trans } from '@lingui/macro';
import { ValueOf } from 'viem';

enum Incentive {
spice,
Expand All @@ -12,9 +11,20 @@ enum Incentive {
supply
}

type StakingInfo = Record<string, ValueOf<typeof stakingInfo> | undefined>;
type StakingInfo = {
strategy: string;
protocol: string;
incentives: Incentive[];
tvl: string;
about: JSX.Element;
inputToken: string;
outputToken: string;
securityReview: string;
website: string;
isDisabled?: boolean;
};

const stakingInfo = {
const stakingInfo: Record<string, StakingInfo> = {
'bedrock-unibtc': {
strategy: 'Liquid Staking Bedrock-Babylon',
protocol: 'Bedrock',
Expand Down Expand Up @@ -48,7 +58,8 @@ const stakingInfo = {
inputToken: 'BTC',
outputToken: 'SolvBTC.BBN',
securityReview: 'https://www.bitcoinlayers.org/infrastructure/solvlst',
website: 'https://app.solv.finance/babylon?network=bob'
website: 'https://app.solv.finance/babylon?network=bob',
isDisabled: true
},
'pell-solvbtcbbn': {
strategy: 'Restaking Pell-SolvBTC-Babylon',
Expand All @@ -65,7 +76,8 @@ const stakingInfo = {
inputToken: 'BTC',
outputToken: 'SolvBTC.BBN',
securityReview: '',
website: 'https://app.pell.network/restake'
website: 'https://app.pell.network/restake',
isDisabled: true
},
'pell-unibtc': {
strategy: 'Restaking Pell-uniBTC-Babylon',
Expand Down Expand Up @@ -129,7 +141,8 @@ const stakingInfo = {
inputToken: 'BTC',
outputToken: 'seSOLVBTCBBN',
securityReview: '',
website: 'https://app.segment.finance'
website: 'https://app.segment.finance',
isDisabled: true
},
'segment-seunibtc': {
strategy: 'Staked Lending Segment-uniBTC-Babylon',
Expand All @@ -146,7 +159,7 @@ const stakingInfo = {
securityReview: '',
website: 'https://app.segment.finance'
}
};
} as const;

export { stakingInfo, Incentive };
export type { StakingInfo };
Loading

0 comments on commit 3cca3cf

Please sign in to comment.