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

Feat/improve staking page #335

Merged
merged 29 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e698ebc
feat(evm): stake 3.0
danielsimao Dec 6, 2024
7970f58
chore: add support for ionic and avalon strategies (#398)
slavastartsev Jan 10, 2025
6f20644
feat(evm): final
slavastartsev Jan 10, 2025
ca937bf
feat(evm): add LBTC strategy
danielsimao Jan 13, 2025
5ab560c
Feat/lbtc staking (#379)
slavastartsev Jan 13, 2025
f755f0d
feat(evm): add avalon and ionic strategies
danielsimao Jan 13, 2025
655cd20
fix: code review
danielsimao Jan 13, 2025
cb78681
feat: hide strat
danielsimao Jan 14, 2025
7fadce7
feat: add missing info
danielsimao Jan 14, 2025
72dd348
fix: code review
danielsimao Jan 14, 2025
912e5f5
fix: remove outdated test
danielsimao Jan 14, 2025
1ab492f
chore: add tvl calculations
slavastartsev Jan 14, 2025
827727a
chore: add translations
slavastartsev Jan 14, 2025
227db91
chore: update calculations for ionic tvl
slavastartsev Jan 14, 2025
c372a2b
fix: hide tooltip
danielsimao Jan 15, 2025
ab819aa
fix: temp
danielsimao Jan 15, 2025
67971d5
fix: show more data on breakdown
danielsimao Jan 15, 2025
e9edfc4
fix: code review
danielsimao Jan 15, 2025
3ffa97b
fix: code review
danielsimao Jan 15, 2025
533bd05
chore: push temp code
slavastartsev Jan 15, 2025
8c96b2a
chore: add tab enum
slavastartsev Jan 15, 2025
b752e00
chore: more skeletons
slavastartsev Jan 15, 2025
367d01e
chore: update messages, update skeleton for strategy title
slavastartsev Jan 15, 2025
04031b7
fix: code review
danielsimao Jan 15, 2025
df42ee2
chore: update is table check
slavastartsev Jan 15, 2025
b9f6ba9
chore: fix hydration error
slavastartsev Jan 15, 2025
cc972e3
fix: avalon logo
danielsimao Jan 15, 2025
309cd55
chore: update link to avalon logo
slavastartsev Jan 16, 2025
1d1e141
chore: update link to avalon points logo
slavastartsev Jan 16, 2025
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
2 changes: 1 addition & 1 deletion apps/evm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
},
"dependencies": {
"@binance/w3w-wagmi-connector-v2": "1.2.4-alpha.0",
"@gobob/bob-sdk": "^3.1.0",
"@gobob/bob-sdk": "^3.1.1",
"@gobob/chains": "workspace:^",
"@gobob/currency": "workspace:^",
"@gobob/hooks": "workspace:^",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const seTokenAbi = [
export const erc20WithUnderlying = [
{
inputs: [],
stateMutability: 'nonpayable',
Expand Down
1 change: 0 additions & 1 deletion apps/evm/src/app/[lang]/(bridge)/bridge/Bridge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ const Bridge = ({ searchParams }: Props) => {
data={transactions}
isInitialLoading={isTransactionsInitialLoading}
txPendingUserAction={txPendingUserAction}
type='bridge'
onProveSuccess={refetch.bridge}
onRelaySuccess={refetch.bridge}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ const GatewayTransactionDetails = ({
{!query.liquidity.isPending && query.liquidity.data && !query.liquidity.data.hasLiquidity && (
<Alert status='warning'>
<P size='s'>
{type === 'stake' ? (
<Trans>Cannot stake into {assetName} due to insufficient liquidity.</Trans>
{type === GatewayTransactionType.STRATEGY ? (
<Trans>Currently, there is no available liquidity for this strategy.</Trans>
) : (
<Trans>There is currently no available liquidity to onramp BTC into {assetName}.</Trans>
<Trans>Currently, there is no available liquidity to onramp BTC into {assetName}.</Trans>
)}
</P>
</Alert>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { CardProps, Divider, Flex, H2, Link, P, Spinner } from '@gobob/ui';
import { Trans, t } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/macro';
import { useVirtualizer } from '@tanstack/react-virtual';
import { useMemo, useRef } from 'react';
import { useIsClient } from 'usehooks-ts';
import { useAccount } from 'wagmi';
import { useVirtualizer } from '@tanstack/react-virtual';

import { TransactionItem } from './TransactionItem';
import {
Expand All @@ -22,7 +21,6 @@ import { chainL2 } from '@/constants';
import { Transaction } from '@/types';

type Props = {
type: 'bridge' | 'stake';
isInitialLoading?: boolean;
data?: Transaction[];
onProveSuccess?: () => void;
Expand All @@ -35,15 +33,13 @@ type InheritAttrs = Omit<CardProps, keyof Props>;
type TransactionListProps = Props & InheritAttrs;

const TransactionList = ({
type,
isInitialLoading,
data,
onProveSuccess,
onRelaySuccess,
txPendingUserAction,
...props
}: TransactionListProps): JSX.Element => {
const { i18n } = useLingui();
const isClient = useIsClient();
// The scrollable element for your list
const parentRef = useRef(null);
Expand Down Expand Up @@ -80,7 +76,6 @@ const TransactionList = ({

const txsUrl = address ? `${explorerUrl}/address/${address}` : `${explorerUrl}`;
const hasData = !!data?.length;
const txType = type === 'bridge' ? t(i18n)`bridging` : t(i18n)`staking`;

return (
<StyledSection gap='xl' paddingX='4xl' paddingY='3xl' {...props}>
Expand All @@ -97,7 +92,7 @@ const TransactionList = ({
<Flex alignItems='center' gap='md' justifyContent='center' style={{ height: '100%' }}>
<Spinner size='16' thickness={2} />
<P align='center' size='xs'>
<Trans>Fetching {txType} operations...</Trans>
<Trans>Fetching operations...</Trans>
danielsimao marked this conversation as resolved.
Show resolved Hide resolved
</P>
</Flex>
) : (
Expand Down Expand Up @@ -125,7 +120,7 @@ const TransactionList = ({
) : (
<Flex alignItems='center' gap='md' justifyContent='center' style={{ height: '100%' }}>
<P align='center' size='xs'>
<Trans>No {txType} operations found</Trans>
<Trans>No operations found</Trans>
</P>
</Flex>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ const GatewayTransactionModal = ({ data, onClose, ...props }: GatewayTransaction
<Trans>
Your assets will be delivered once your BTC transactions receive at least 3 confirmations and the
processing finishes on our L2 chain. We will provide you with updates accordingly. You can monitor the
progress on your bridge page. It will be marked as complete once the process has concluded.
progress on the &quot;Activity&quot; section. It will be marked as complete once the process has
concluded.
</Trans>
</P>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('useGateway', () => {
const { result } = renderHook(
() =>
useGateway({
params: { type: GatewayTransactionType.STAKE, assetName: 'BTC' }
params: { type: GatewayTransactionType.STRATEGY, assetName: 'BTC' }
}),
{
wrapper
Expand All @@ -54,7 +54,7 @@ describe('useGateway', () => {
const { result } = renderHook(
() =>
useGateway({
params: { type: GatewayTransactionType.STAKE, assetName: 'BTC' }
params: { type: GatewayTransactionType.STRATEGY, assetName: 'BTC' }
}),
{
wrapper
Expand All @@ -72,7 +72,7 @@ describe('useGateway', () => {
const { result } = renderHook(
() =>
useGateway({
params: { type: GatewayTransactionType.STAKE, assetName: 'BTC' }
params: { type: GatewayTransactionType.STRATEGY, assetName: 'BTC' }
}),
{
wrapper
Expand All @@ -94,7 +94,7 @@ describe('useGateway', () => {
const { result } = renderHook(
() =>
useGateway({
params: { type: GatewayTransactionType.STAKE, assetName: 'BTC' },
params: { type: GatewayTransactionType.STRATEGY, assetName: 'BTC' },
onError: mockFeeEstimateQueryResult
}),
{
Expand Down
16 changes: 8 additions & 8 deletions apps/evm/src/app/[lang]/(bridge)/hooks/useGateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ type UseGatewayQueryDataReturnType = {
balance: { data: CurrencyAmount<Bitcoin>; isPending: boolean };
};

type StakeParams = {
type: GatewayTransactionType.STAKE;
type StrategyParams = {
type: GatewayTransactionType.STRATEGY;
assetName?: string;
} & Partial<Pick<GatewayQuoteParams, 'toChain' | 'toToken' | 'strategyAddress'>>;

Expand All @@ -122,7 +122,7 @@ type BridgeParams = {
} & Partial<Pick<GatewayQuoteParams, 'toChain' | 'toToken'>>;

type UseGatewayLiquidityProps = {
params: BridgeParams | StakeParams;
params: BridgeParams | StrategyParams;
isDisabled?: boolean;
onMutate?: (data: Optional<InitGatewayTransaction, 'amount'>) => void;
onSuccess?: (data: InitGatewayTransaction) => void;
Expand Down Expand Up @@ -183,13 +183,13 @@ const useGateway = ({
const isTapRootAddress = btcAddressType === BtcAddressType.p2tr;

const liquidityQueryEnabled = Boolean(
params.toChain && params.toToken && params.type === GatewayTransactionType.STAKE ? params.strategyAddress : true
params.toChain && params.toToken && params.type === GatewayTransactionType.STRATEGY ? params.strategyAddress : true
);

const liquidityQueryKey = bridgeKeys.btcQuote(
params.toToken,
params.toChain,
(params as StakeParams)?.strategyAddress,
(params as StrategyParams)?.strategyAddress,
'liquidity-check'
);

Expand All @@ -208,7 +208,7 @@ const useGateway = ({
...DEFAULT_GATEWAY_QUOTE_PARAMS,
toChain,
toToken,
strategyAddress: params.type === GatewayTransactionType.STAKE ? params.strategyAddress : undefined,
strategyAddress: params.type === GatewayTransactionType.STRATEGY ? params.strategyAddress : undefined,
amount: undefined
});

Expand Down Expand Up @@ -268,7 +268,7 @@ const useGateway = ({
const quoteQueryKey = bridgeKeys.btcQuote(
params.toToken,
params.toChain,
(params as StakeParams)?.strategyAddress,
(params as StrategyParams)?.strategyAddress,
rawAmount,
isTopUpEnabled
);
Expand All @@ -292,7 +292,7 @@ const useGateway = ({
gasRefill: isTopUpEnabled ? GAS_REFILL : 0,
toChain,
toToken,
strategyAddress: params.type === GatewayTransactionType.STAKE ? params.strategyAddress : undefined
strategyAddress: params.type === GatewayTransactionType.STRATEGY ? params.strategyAddress : undefined
});

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const getGatewayTransactions = async (address: Address): Promise<GatewayTransact
totalConfirmations: order.txProofDifficultyFactor,
status,
type: TransactionType.Gateway,
subType: order.strategyAddress ? GatewayTransactionType.STAKE : GatewayTransactionType.BRIDGE,
subType: order.strategyAddress ? GatewayTransactionType.STRATEGY : GatewayTransactionType.BRIDGE,
isPending,
order
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
'use client';

import { Flex } from '@gobob/ui';
import { useStore } from '@tanstack/react-store';
import { watchAccount } from '@wagmi/core';
import { useEffect, useRef } from 'react';
import { useConfig } from 'wagmi';
import { Flex } from '@gobob/ui';

import { Layout, TransactionList } from '../components';
import { GetGatewayTransactionsReturnType, useGetGatewayTransactions } from '../hooks';

import { StakeTable } from './components';
import { StrategiesTable } from './components';

import { PageLangParam } from '@/i18n/withLigui';
import { store } from '@/lib/store';
Expand All @@ -20,16 +20,12 @@ type Props = PageLangParam & {
};

const select = (data: GetGatewayTransactionsReturnType) =>
data.filter((item) => item.subType === GatewayTransactionType.STAKE);
data.filter((item) => item.subType === GatewayTransactionType.STRATEGY);

function Stake({ searchParams }: Props) {
function Strategies({ searchParams }: Props) {
const config = useConfig();

const {
data: transactions,
isLoading: isLoadingTransactions,
refetch: refetchTransactions
} = useGetGatewayTransactions({
const { data: transactions, isLoading: isLoadingTransactions } = useGetGatewayTransactions({
query: { select }
});

Expand All @@ -43,7 +39,7 @@ function Stake({ searchParams }: Props) {
if (account.address) {
store.setState((state) => ({
...state,
stake: { ...state.stake, transactions: { ...state.stake.transactions, isInitialLoading: true } }
stake: { ...state.strategies, transactions: { ...state.strategies.transactions, isInitialLoading: true } }
}));
}
}
Expand All @@ -64,12 +60,12 @@ function Stake({ searchParams }: Props) {

return (
<Layout>
<Flex direction='column' gap='xl' marginTop='xl'>
<StakeTable searchParams={searchParams} onStakeSuccess={refetchTransactions} />
<TransactionList data={transactions} isInitialLoading={isInitialLoading} type='stake' />
<Flex direction='column' gap='xl' marginTop='2xl'>
<StrategiesTable searchParams={searchParams} />
<TransactionList data={transactions} isInitialLoading={isInitialLoading} />
</Flex>
</Layout>
);
}

export { Stake };
export { Strategies };
104 changes: 104 additions & 0 deletions apps/evm/src/app/[lang]/(bridge)/stake/[slug]/Strategy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use client';

import { Alert, ArrowLeft, Avatar, Button, Card, Flex, H1, H2, Link, P, Skeleton, Tabs, TabsItem } from '@gobob/ui';
import { Trans } from '@lingui/macro';
import { useState } from 'react';

import { useGetGatewayTransactions } from '../../hooks';
import { StrategyDetails, StrategyForm } from '../components';
import { useGetStrategies } from '../hooks';

import { Layout, Main } from '@/components';
import { RoutesPath } from '@/constants';
import { PageLangParam } from '@/i18n/withLigui';

type Props = PageLangParam & {
params: { slug: string };
};

enum Tab {
Deposit = 'deposit',
Withdraw = 'withdraw'
}

function Strategy({ params }: Props) {
const { refetch: refetchTransactions } = useGetGatewayTransactions({});
const [tab, setTab] = useState<Tab>(Tab.Deposit);

const { data: strategies = [] } = useGetStrategies();

const strategy = strategies.find((strategy) => strategy.meta.slug === params.slug);

const isLending = strategy?.meta.type === 'lending';

const action = isLending ? <Trans>withdraw</Trans> : <Trans>unstake</Trans>;
const depositTitle = isLending ? <Trans>Supply</Trans> : <Trans>Stake</Trans>;
const withdrawTitle = isLending ? <Trans>Withdraw</Trans> : <Trans>Unstake</Trans>;

return (
<Layout>
<Main maxWidth='5xl' padding='lg'>
<Link href={RoutesPath.STRATEGIES}>
<Flex alignItems='center' gap='s'>
<ArrowLeft size='xs' />
<Trans>Back</Trans>
</Flex>
</Link>
<Flex alignItems='center' gap='lg' marginTop='4xl'>
{strategy ? (
<Avatar size='4xl' src={strategy.info.logoUrl || strategy.meta.logo} />
) : (
<Skeleton height='4xl' rounded='full' width='4xl' />
)}

<Flex alignItems='flex-start' direction='column'>
<H1 size='lg'>{strategy ? strategy.info.name : <Skeleton height='xl' width='12rem' />}</H1>
<H2 color='grey-50' size='md' weight='medium'>
{strategy ? strategy.info.protocol : <Skeleton height='xl' width='8rem' />}
</H2>
</Flex>
</Flex>
{strategy?.info?.warningMessage && (
<Alert status='warning' style={{ marginTop: '1rem' }} variant='outlined'>
{strategy?.info.warningMessage}
</Alert>
)}
<Flex direction={{ base: 'column', md: 'row' }} gap='xl' marginTop='3xl' style={{ width: '100%' }}>
<Card flex='1 0 0%' style={{ height: 'max-content' }}>
<Tabs fullWidth selectedKey={tab} size='lg' onSelectionChange={(key) => setTab(key as Tab)}>
<TabsItem key={Tab.Deposit} title={strategy ? depositTitle : <Skeleton height='xl' width='6rem' />}>
<StrategyForm isLending={isLending} strategy={strategy} onSuccess={refetchTransactions} />
</TabsItem>
<TabsItem key={Tab.Withdraw} title={strategy ? withdrawTitle : <Skeleton height='xl' width='6rem' />}>
<Flex
alignItems='center'
direction='column'
flex={1}
gap='xl'
justifyContent='center'
marginTop='md'
paddingX='md'
style={{ height: '100%', minHeight: '25rem' }}
>
<P align='center' color='grey-50' size='s'>
<Trans>
Complete your {action} by accessing {strategy?.info.protocol} Dapp using the button bellow
</Trans>
</P>
<Button asChild color='primary'>
<Link external href={strategy?.info.links.manage}>
Go to {strategy?.info.protocol} Dapp
</Link>
</Button>
</Flex>
</TabsItem>
</Tabs>
</Card>
<StrategyDetails isLending={isLending} strategy={strategy} />
</Flex>
</Main>
</Layout>
);
}

export { Strategy };
Loading
Loading