Skip to content

Commit

Permalink
Merge pull request #295 from lidofinance/develop
Browse files Browse the repository at this point in the history
Merge develop to main
  • Loading branch information
jake4take authored Mar 19, 2024
2 parents 759d1a6 + b5f3ea2 commit 18fbbdf
Show file tree
Hide file tree
Showing 20 changed files with 305 additions and 106 deletions.
19 changes: 19 additions & 0 deletions assets/icons/bebop.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions config/matomoClickEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const enum MATOMO_CLICK_EVENTS_TYPES {
withdrawalOtherFactorsTooltipMode = 'withdrawalOtherFactorsTooltipMode',
withdrawalFAQtooltipEthAmount = 'withdrawalFAQtooltipEthAmount',
withdrawalGoTo1inch = 'withdrawalGoTo1inch',
withdrawalGoToBebop = 'withdrawalGoToBebop',
withdrawalGoToCowSwap = 'withdrawalGoToCowSwap',
withdrawalGoToParaswap = 'withdrawalGoToParaswap',
withdrawalGoToOpenOcean = 'withdrawalGoToOpenOcean',
Expand Down Expand Up @@ -279,6 +280,11 @@ export const MATOMO_CLICK_EVENTS: Record<
'Click on «Go to 1inch» in aggregators list on Request tab',
'eth_withdrawals_request_go_to_1inch',
],
[MATOMO_CLICK_EVENTS_TYPES.withdrawalGoToBebop]: [
'Ethereum_Withdrawals_Widget',
'Click on «Go to Bebop» in aggregators list on Request tab',
'eth_withdrawals_request_go_to_1inch',
],
[MATOMO_CLICK_EVENTS_TYPES.withdrawalGoToCowSwap]: [
'Ethereum_Withdrawals_Widget',
'Click on «Go to CowSwap» in aggregators list on Request tab',
Expand Down
65 changes: 16 additions & 49 deletions features/rewards/components/stats/Stats.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,42 @@
import { FC, useCallback, useEffect, useState } from 'react';
import type { BigNumber as EthersBigNumber } from 'ethers';
import { constants } from 'ethers';
import { useStethEthRate } from 'features/rewards/hooks/use-steth-eth-rate';
import { useRewardsHistory } from 'features/rewards/hooks';
import { useRewardsBalanceData } from 'features/rewards/hooks/use-rewards-balance-data';

import { Box, Link } from '@lidofinance/lido-ui';
import { useSDK, useTokenBalance } from '@lido-sdk/react';
import { TOKENS, getTokenAddress } from '@lido-sdk/constants';

import { dynamics } from 'config';
import { stEthEthRequest } from 'features/rewards/fetchers/requesters';
import EthSymbol from 'features/rewards/components/EthSymbol';
import NumberFormat from 'features/rewards/components/NumberFormat';
import { Big, BigDecimal } from 'features/rewards/helpers';
import { ETHER } from 'features/rewards/constants';
import { STRATEGY_LAZY } from 'utils/swrStrategies';
import { useMainnetStaticRpcProvider } from 'shared/hooks/use-mainnet-static-rpc-provider';

import { Item } from './Item';
import { Stat } from './Stat';
import { Title } from './Title';
import { StatsProps } from './types';

// TODO: refactoring to style files
export const Stats: FC<StatsProps> = (props) => {
const { address, data, currency, pending } = props;

const [stEthEth, setStEthEth] = useState<EthersBigNumber>();
const { chainId } = useSDK();

const steth = useTokenBalance(
getTokenAddress(chainId, TOKENS.STETH),
address,
STRATEGY_LAZY,
);
const mainnetStaticRpcProvider = useMainnetStaticRpcProvider();

const getStEthEth = useCallback(async () => {
if (dynamics.defaultChain !== 1) {
setStEthEth(constants.WeiPerEther);
} else {
const stEthEth = await stEthEthRequest(mainnetStaticRpcProvider);

setStEthEth(stEthEth);
}
}, [mainnetStaticRpcProvider]);

useEffect(() => {
void getStEthEth();
}, [getStEthEth]);

const stEthBalanceParsed = steth.data && new Big(steth.data.toString());
const stEthCurrencyBalance =
steth.data &&
data &&
new BigDecimal(steth.data.toString()) // Convert to right BN
.div(ETHER)
.times(data.stETHCurrencyPrice[currency.id]);
export const Stats: React.FC = () => {
const {
currencyObject: currency,
data,
initialLoading: pending,
} = useRewardsHistory();
const { data: stEthEth } = useStethEthRate();
const { data: balanceData } = useRewardsBalanceData();

return (
<>
<Item data-testid="stEthBalanceBlock">
<Title mb="8px">stETH balance</Title>
<Stat data-testid="stEthBalance" mb="6px">
<EthSymbol />
<NumberFormat number={stEthBalanceParsed} pending={pending} />
<NumberFormat
number={balanceData?.stEthBalanceParsed}
pending={pending}
/>
</Stat>
<Title data-testid="stEthBalanceIn$" hideMobile>
<Box display="inline-block" pr="3px">
{currency.symbol}
</Box>
<NumberFormat
number={stEthCurrencyBalance}
number={balanceData?.stEthCurrencyBalance}
currency
pending={pending}
/>
Expand Down
9 changes: 0 additions & 9 deletions features/rewards/components/stats/types.ts

This file was deleted.

18 changes: 3 additions & 15 deletions features/rewards/features/top-card/top-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,8 @@ const INPUT_DESC_TEXT =
'Current balance may differ from last balance in the table due to rounding.';

export const TopCard: FC = () => {
const {
address,
isAddressResolving,
currencyObject,
data,
inputValue,
setInputValue,
initialLoading,
} = useRewardsHistory();
const { address, isAddressResolving, inputValue, setInputValue } =
useRewardsHistory();

return (
<Block color="accent" style={{ padding: 0 }}>
Expand All @@ -35,12 +28,7 @@ export const TopCard: FC = () => {
</ThemeProvider>
</InputWrapper>
<StatsWrapper>
<Stats
address={address}
currency={currencyObject}
data={data}
pending={initialLoading}
/>
<Stats />
</StatsWrapper>
</Block>
);
Expand Down
23 changes: 23 additions & 0 deletions features/rewards/hooks/use-laggy-data-wrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useEffect, useRef } from 'react';

export const useLaggyDataWrapper = <Data>(data: Data) => {
const laggyDataRef = useRef<Data | undefined>();
const isDataPresented = data !== undefined && data !== null;

useEffect(() => {
if (isDataPresented) {
laggyDataRef.current = data;
}
}, [data, isDataPresented]);

// Return to previous data if current data is not defined.
const dataOrLaggyData = !isDataPresented ? laggyDataRef.current : data;

// Shows previous data.
const isLagging = !isDataPresented && laggyDataRef.current !== undefined;

return {
isLagging,
dataOrLaggyData,
};
};
39 changes: 39 additions & 0 deletions features/rewards/hooks/use-rewards-balance-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useMemo } from 'react';
import { useSDK, useTokenBalance } from '@lido-sdk/react';
import { useRewardsHistory } from './useRewardsHistory';
import { useLaggyDataWrapper } from './use-laggy-data-wrapper';

import { ETHER } from 'features/rewards/constants';
import { TOKENS, getTokenAddress } from '@lido-sdk/constants';
import { STRATEGY_LAZY } from 'utils/swrStrategies';
import { Big, BigDecimal } from '../helpers';

export const useRewardsBalanceData = () => {
const { chainId } = useSDK();
const { address, data, currencyObject } = useRewardsHistory();

const { data: steth } = useTokenBalance(
getTokenAddress(chainId, TOKENS.STETH),
address,
STRATEGY_LAZY,
);

const balanceData = useMemo(
() =>
steth
? {
stEthBalanceParsed: new Big(steth.toString()),
stEthCurrencyBalance:
data &&
new BigDecimal(steth.toString()) // Convert to right BN
.div(ETHER)
.times(data.stETHCurrencyPrice[currencyObject.id]),
}
: null,
[currencyObject.id, data, steth],
);

const { isLagging, dataOrLaggyData } = useLaggyDataWrapper(balanceData);

return { isLagging: !!address && isLagging, data: dataOrLaggyData };
};
26 changes: 26 additions & 0 deletions features/rewards/hooks/use-steth-eth-rate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { STRATEGY_LAZY } from 'utils/swrStrategies';
import { useMainnetStaticRpcProvider } from 'shared/hooks/use-mainnet-static-rpc-provider';
import { useLidoSWR, useSDK } from '@lido-sdk/react';

import { stEthEthRequest } from 'features/rewards/fetchers/requesters';
import { constants } from 'ethers';

export const useStethEthRate = () => {
const { chainId } = useSDK();
const mainnetStaticRpcProvider = useMainnetStaticRpcProvider();

const swrResult = useLidoSWR(
`steth-eth-${chainId}`,
async () => {
if (chainId !== 1) {
return constants.WeiPerEther;
} else {
const stEthEth = await stEthEthRequest(mainnetStaticRpcProvider);
return stEthEth;
}
},
STRATEGY_LAZY,
);

return swrResult;
};
19 changes: 3 additions & 16 deletions features/rewards/hooks/useRewardsDataLoad.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useEffect, useRef } from 'react';
import { Backend } from 'features/rewards/types';
import { dynamics } from 'config';
import { useLidoSWR } from 'shared/hooks';
import { swrAbortableMiddleware } from 'utils';
import { useLaggyDataWrapper } from './use-laggy-data-wrapper';

type UseRewardsDataLoad = (props: {
address: string;
Expand All @@ -29,8 +29,6 @@ export const useRewardsDataLoad: UseRewardsDataLoad = (props) => {
limit,
} = props;

const laggyDataRef = useRef<Backend | undefined>();

const requestOptions = {
address,
currency,
Expand Down Expand Up @@ -61,18 +59,7 @@ export const useRewardsDataLoad: UseRewardsDataLoad = (props) => {
},
);

useEffect(() => {
if (data !== undefined) {
laggyDataRef.current = data;
}
}, [data]);

// Return to previous data if current data is not defined.
const dataOrLaggyData = data === undefined ? laggyDataRef.current : data;

// Shows previous data.
const isLagging =
!!address && data === undefined && laggyDataRef.current !== undefined;
const { isLagging, dataOrLaggyData } = useLaggyDataWrapper(data);

return { ...rest, isLagging, data: dataOrLaggyData };
return { ...rest, isLagging: !!address && isLagging, data: dataOrLaggyData };
};
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const ClaimFormProvider: FC<PropsWithChildren> = ({ children }) => {
// for regular updates generate new list but keep user input
const oldValues = getValues('requests');
const checkedIds = new Set(
oldValues.filter((req) => req.checked).map((req) => req.token_id),
oldValues?.filter((req) => req.checked).map((req) => req.token_id),
);
const newRequests = generateDefaultValues(
data,
Expand Down
8 changes: 8 additions & 0 deletions features/withdrawals/request/withdrawal-rates/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import styled from 'styled-components';
import OpenOcean from 'assets/icons/open-ocean.svg';
import Paraswap from 'assets/icons/paraswap-circle.svg';
import Oneinch from 'assets/icons/oneinch-circle.svg';
import Bebop from 'assets/icons/bebop.svg';

export const OpenOceanIcon = styled.img.attrs({
src: OpenOcean,
Expand All @@ -23,3 +24,10 @@ export const OneInchIcon = styled.img.attrs({
})`
display: block;
`;

export const BebopIcon = styled.img.attrs({
src: Bebop,
alt: 'Bebop',
})`
display: block;
`;
31 changes: 30 additions & 1 deletion features/withdrawals/request/withdrawal-rates/integrations.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { Zero } from '@ethersproject/constants';
import { getTokenAddress, CHAINS, TOKENS } from '@lido-sdk/constants';
import { BigNumber } from 'ethers';
import { getAddress } from 'ethers/lib/utils.js';
import { formatEther } from '@ethersproject/units';

import { getOneInchRate } from 'utils/get-one-inch-rate';
import { getBebopRate } from 'utils/get-bebop-rate';
import { getOpenOceanRate } from 'utils/get-open-ocean-rate';
import { standardFetcher } from 'utils/standardFetcher';
import { OPEN_OCEAN_REFERRAL_ADDRESS } from 'config/external-links';
import { MATOMO_CLICK_EVENTS_TYPES } from 'config/matomoClickEvents';

import { OneInchIcon, OpenOceanIcon, ParaSwapIcon } from './icons';
import { BebopIcon, OneInchIcon, OpenOceanIcon, ParaSwapIcon } from './icons';

import type {
DexWithdrawalApi,
Expand Down Expand Up @@ -124,6 +126,23 @@ const getOneInchWithdrawalRate: GetRateType = async (params) => {
};
};

const getBebopWithdrawalRate: GetRateType = async ({ amount, token }) => {
try {
if (amount.gt(Zero)) {
return await getBebopRate(amount, token, 'ETH');
}
} catch (e) {
console.warn(
'[getOneInchWithdrawalRate] Failed to receive withdraw rate',
e,
);
}
return {
rate: null,
toReceive: null,
};
};

const dexWithdrawalMap: DexWithdrawalIntegrationMap = {
'open-ocean': {
title: 'OpenOcean',
Expand Down Expand Up @@ -158,6 +177,16 @@ const dexWithdrawalMap: DexWithdrawalIntegrationMap = {
token == TOKENS.STETH ? 'stETH' : 'wstETH'
}/ETH?sourceTokenAmount=${formatEther(amount)}`,
},
bebop: {
title: 'Bebop',
icon: BebopIcon,
fetcher: getBebopWithdrawalRate,
matomoEvent: MATOMO_CLICK_EVENTS_TYPES.withdrawalGoToBebop,
link: (amount, token) =>
`https://bebop.xyz/trade?network=ethereum&buy=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&sell=${getAddress(
getTokenAddress(CHAINS.Mainnet, token),
)}&sellAmounts=${formatEther(amount)}`,
},
} as const;

export const getDexConfig = (dexKey: DexWithdrawalApi) =>
Expand Down
Loading

0 comments on commit 18fbbdf

Please sign in to comment.