diff --git a/.env.example b/.env.example index c272c237d..f332a0119 100644 --- a/.env.example +++ b/.env.example @@ -7,12 +7,10 @@ RESEARCH_ORIGIN=https://research.lido.fi # EL_RPC_URLS_{CHAIN_ID} list or URLs delimeted by commas, first entry is primary, else are fallbacks EL_RPC_URLS_1= -EL_RPC_URLS_5= EL_RPC_URLS_17000= # IPFS prefill RPC URLs - list of URLs delimited by commas PREFILL_UNSAFE_EL_RPC_URLS_1= -PREFILL_UNSAFE_EL_RPC_URLS_5= PREFILL_UNSAFE_EL_RPC_URLS_17000= # supported networks for connecting wallet diff --git a/IPFS.json b/IPFS.json index 64256ff70..9c1feb582 100644 --- a/IPFS.json +++ b/IPFS.json @@ -11,6 +11,9 @@ "17000": { "__warning__": "For testing purposes only", "cid": "bafybeibbsoqlofslw273b4ih2pdxfaz2zbjmred2ijog725tcmfoewix7y", - "leastSafeVersion": "0.36.1" + "leastSafeVersion": "0.36.1", + "config": { + "enabledWithdrawalDexes": ["one-inch", "paraswap", "bebop"] + } } } diff --git a/README.md b/README.md index 0bc9fd878..46903a392 100644 --- a/README.md +++ b/README.md @@ -67,8 +67,8 @@ yarn build:ipfs ## Adding a new route API - create a new file in `pages/api/` folder -- use `wrapRequest` function from `utilsApi/apiWrappers.ts` -- use default wrappers from `utilsApi/apiWrappers.ts` if needed (e.g. `defaultErrorHandler` for handle errors) +- use `wrapRequest` function from `@lidofinance/next-api-wrapper` package. +- use default wrappers from `utilsApi/nextApiWrappers.ts` if needed (e.g. `defaultErrorHandler` for handle errors) **Example:** diff --git a/abi/partialStakingRouter.abi.json b/abi/partialStakingRouter.abi.json new file mode 100644 index 000000000..3d98c089e --- /dev/null +++ b/abi/partialStakingRouter.abi.json @@ -0,0 +1,125 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_depositContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "stakingModuleId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakingModuleFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "treasuryFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "setBy", + "type": "address" + } + ], + "name": "StakingModuleFeesSet", + "type": "event" + }, + { + "inputs": [], + "name": "FEE_PRECISION_POINTS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOTAL_BASIS_POINTS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLido", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStakingFeeAggregateDistribution", + "outputs": [ + { "internalType": "uint96", "name": "modulesFee", "type": "uint96" }, + { "internalType": "uint96", "name": "treasuryFee", "type": "uint96" }, + { "internalType": "uint256", "name": "basePrecision", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStakingFeeAggregateDistributionE4Precision", + "outputs": [ + { "internalType": "uint16", "name": "modulesFee", "type": "uint16" }, + { "internalType": "uint16", "name": "treasuryFee", "type": "uint16" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStakingRewardsDistribution", + "outputs": [ + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "stakingModuleIds", + "type": "uint256[]" + }, + { + "internalType": "uint96[]", + "name": "stakingModuleFees", + "type": "uint96[]" + }, + { "internalType": "uint96", "name": "totalFee", "type": "uint96" }, + { + "internalType": "uint256", + "name": "precisionPoints", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalFeeE4Precision", + "outputs": [ + { "internalType": "uint16", "name": "totalFee", "type": "uint16" } + ], + "stateMutability": "view", + "type": "function" + }, + { "stateMutability": "payable", "type": "receive" } +] diff --git a/consts/matomo-wallets-events.ts b/consts/matomo-wallets-events.ts index f7f5d3c47..fe83f9cbf 100644 --- a/consts/matomo-wallets-events.ts +++ b/consts/matomo-wallets-events.ts @@ -4,8 +4,6 @@ import { Metrics as WalletsMetrics } from 'reef-knot/connect-wallet-modal'; export const enum MATOMO_WALLETS_EVENTS_TYPES { onClickAmbire = 'onClickAmbire', onConnectAmbire = 'onConnectAmbire', - onClickBlockchaincom = 'onClickBlockchaincom', - onConnectBlockchaincom = 'onConnectBlockchaincom', onClickBrave = 'onClickBrave', onConnectBrave = 'onConnectBrave', onClickCoin98 = 'onClickCoin98', @@ -14,36 +12,22 @@ export const enum MATOMO_WALLETS_EVENTS_TYPES { onConnectCoinbase = 'onConnectCoinbase', onClickExodus = 'onClickExodus', onConnectExodus = 'onConnectExodus', - onClickGamestop = 'onClickGamestop', - onConnectGamestop = 'onConnectGamestop', onClickImToken = 'onClickImToken', onConnectImToken = 'onConnectImToken', onClickLedger = 'onClickLedger', onConnectLedger = 'onConnectLedger', - onClickMathWallet = 'onClickMathWallet', - onConnectMathWallet = 'onConnectMathWallet', onClickMetamask = 'onClickMetamask', onConnectMetamask = 'onConnectMetamask', - onClickOperaWallet = 'onClickOperaWallet', - onConnectOperaWallet = 'onConnectOperaWallet', - onClickTally = 'onClickTally', - onConnectTally = 'onConnectTally', onClickTrust = 'onClickTrust', onConnectTrust = 'onConnectTrust', onClickWC = 'onClickWC', onConnectWC = 'onConnectWC', onClickXdefi = 'onClickXdefi', onConnectXdefi = 'onConnectXdefi', - onClickZenGo = 'onClickZenGo', - onConnectZenGo = 'onConnectZenGo', - onClickZerion = 'onClickZerion', - onConnectZerion = 'onConnectZerion', onClickOkx = 'onClickOkx', onConnectOkx = 'onConnectOkx', - onClickPhantom = 'onClickPhantom', - onConnectPhantom = 'onConnectPhantom', - onClickBitkeep = 'onClickBitkeep', - onConnectBitkeep = 'onConnectBitkeep', + onClickBitget = 'onClickBitget', + onConnectBitget = 'onConnectBitget', } export const MATOMO_WALLETS_EVENTS: Record< @@ -60,16 +44,6 @@ export const MATOMO_WALLETS_EVENTS: Record< 'Connect Ambire wallet', 'eth_widget_connect_ambire', ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickBlockchaincom]: [ - 'Ethereum_Staking_Widget', - 'Click Blockchain.com wallet', - 'eth_widget_click_blockchaincom', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectBlockchaincom]: [ - 'Ethereum_Staking_Widget', - 'Connect Blockchain.com wallet', - 'eth_widget_connect_blockchaincom', - ], [MATOMO_WALLETS_EVENTS_TYPES.onClickBrave]: [ 'Ethereum_Staking_Widget', 'Click Brave wallet', @@ -110,16 +84,6 @@ export const MATOMO_WALLETS_EVENTS: Record< 'Connect Exodus wallet', 'eth_widget_connect_exodus', ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickGamestop]: [ - 'Ethereum_Staking_Widget', - 'Click Gamestop wallet', - 'eth_widget_click_gamestop', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectGamestop]: [ - 'Ethereum_Staking_Widget', - 'Connect Gamestop wallet', - 'eth_widget_connect_gamestop', - ], [MATOMO_WALLETS_EVENTS_TYPES.onClickImToken]: [ 'Ethereum_Staking_Widget', 'Click imToken wallet', @@ -140,16 +104,6 @@ export const MATOMO_WALLETS_EVENTS: Record< 'Connect Ledger wallet', 'eth_widget_connect_ledger', ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickMathWallet]: [ - 'Ethereum_Staking_Widget', - 'Click MathWallet wallet', - 'eth_widget_click_mathwallet', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectMathWallet]: [ - 'Ethereum_Staking_Widget', - 'Connect MathWallet wallet', - 'eth_widget_connect_mathwallet', - ], [MATOMO_WALLETS_EVENTS_TYPES.onClickMetamask]: [ 'Ethereum_Staking_Widget', 'Click Metamask wallet', @@ -160,26 +114,6 @@ export const MATOMO_WALLETS_EVENTS: Record< 'Connect Metamask wallet', 'eth_widget_connect_metamask', ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickOperaWallet]: [ - 'Ethereum_Staking_Widget', - 'Click Opera wallet', - 'eth_widget_click_opera', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectOperaWallet]: [ - 'Ethereum_Staking_Widget', - 'Connect Opera wallet', - 'eth_widget_connect_opera', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickTally]: [ - 'Ethereum_Staking_Widget', - 'Click Tally wallet', - 'eth_widget_click_tally', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectTally]: [ - 'Ethereum_Staking_Widget', - 'Connect Tally wallet', - 'eth_widget_connect_tally', - ], [MATOMO_WALLETS_EVENTS_TYPES.onClickTrust]: [ 'Ethereum_Staking_Widget', 'Click Trust wallet', @@ -210,26 +144,6 @@ export const MATOMO_WALLETS_EVENTS: Record< 'Connect XDEFI wallet', 'eth_widget_connect_xdefi', ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickZenGo]: [ - 'Ethereum_Staking_Widget', - 'Click ZenGo wallet', - 'eth_widget_click_zengo', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectZenGo]: [ - 'Ethereum_Staking_Widget', - 'Connect ZenGo wallet', - 'eth_widget_connect_zengo', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickZerion]: [ - 'Ethereum_Staking_Widget', - 'Click Zerion wallet', - 'eth_widget_click_zerion', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectZerion]: [ - 'Ethereum_Staking_Widget', - 'Connect Zerion wallet', - 'eth_widget_connect_zerion', - ], [MATOMO_WALLETS_EVENTS_TYPES.onClickOkx]: [ 'Ethereum_Staking_Widget', 'Click OKX wallet', @@ -240,25 +154,15 @@ export const MATOMO_WALLETS_EVENTS: Record< 'Connect OKX wallet', 'eth_widget_connect_okx', ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickPhantom]: [ - 'Ethereum_Staking_Widget', - 'Click Phantom wallet', - 'eth_widget_click_phantom', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectPhantom]: [ + [MATOMO_WALLETS_EVENTS_TYPES.onClickBitget]: [ 'Ethereum_Staking_Widget', - 'Connect Phantom wallet', - 'eth_widget_connect_phantom', + 'Click BitGet wallet', + 'eth_widget_click_bitget', ], - [MATOMO_WALLETS_EVENTS_TYPES.onClickBitkeep]: [ + [MATOMO_WALLETS_EVENTS_TYPES.onConnectBitget]: [ 'Ethereum_Staking_Widget', - 'Click BitKeep wallet', - 'eth_widget_click_bitkeep', - ], - [MATOMO_WALLETS_EVENTS_TYPES.onConnectBitkeep]: [ - 'Ethereum_Staking_Widget', - 'Connect BitKeep wallet', - 'eth_widget_connect_bitkeep', + 'Connect BitGet wallet', + 'eth_widget_connect_bitget', ], }; @@ -269,9 +173,6 @@ export const walletsMetrics: WalletsMetrics = { onClickAmbire: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onClickAmbire); }, - onClickBlockchaincom: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickBlockchaincom); - }, onClickBrave: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onClickBrave); }, @@ -284,27 +185,15 @@ export const walletsMetrics: WalletsMetrics = { onClickExodus: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onClickExodus); }, - onClickGamestop: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickGamestop); - }, onClickImToken: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onClickImToken); }, onClickLedger: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onClickLedger); }, - onClickMathWallet: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickMathWallet); - }, onClickMetamask: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onClickMetamask); }, - onClickOperaWallet: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickOperaWallet); - }, - onClickTally: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickTally); - }, onClickTrust: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onClickTrust); }, @@ -314,20 +203,11 @@ export const walletsMetrics: WalletsMetrics = { onClickXdefi: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onClickXdefi); }, - onClickZenGo: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickZenGo); - }, - onClickZerion: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickZerion); - }, onClickOkx: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onClickOkx); }, - onClickPhantom: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickPhantom); - }, - onClickBitkeep: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onClickBitkeep); + onClickBitget: () => { + trackEvent(...MATOMO_WALLETS_EVENTS.onClickBitget); }, }, }, @@ -336,9 +216,6 @@ export const walletsMetrics: WalletsMetrics = { onConnectAmbire: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onConnectAmbire); }, - onConnectBlockchaincom: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectBlockchaincom); - }, onConnectBrave: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onConnectBrave); }, @@ -351,27 +228,15 @@ export const walletsMetrics: WalletsMetrics = { onConnectExodus: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onConnectExodus); }, - onConnectGamestop: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectGamestop); - }, onConnectImToken: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onConnectImToken); }, onConnectLedger: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onConnectLedger); }, - onConnectMathWallet: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectMathWallet); - }, onConnectMetamask: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onConnectMetamask); }, - onConnectOperaWallet: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectOperaWallet); - }, - onConnectTally: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectTally); - }, onConnectTrust: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onConnectTrust); }, @@ -381,20 +246,11 @@ export const walletsMetrics: WalletsMetrics = { onConnectXdefi: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onConnectXdefi); }, - onConnectZenGo: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectZenGo); - }, - onConnectZerion: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectZerion); - }, onConnectOkx: () => { trackEvent(...MATOMO_WALLETS_EVENTS.onConnectOkx); }, - onConnectPhantom: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectPhantom); - }, - onConnectBitkeep: () => { - trackEvent(...MATOMO_WALLETS_EVENTS.onConnectBitkeep); + onConnectBitget: () => { + trackEvent(...MATOMO_WALLETS_EVENTS.onConnectBitget); }, }, }, diff --git a/consts/staking-router.ts b/consts/staking-router.ts new file mode 100644 index 000000000..8cd8c95e1 --- /dev/null +++ b/consts/staking-router.ts @@ -0,0 +1,23 @@ +import { CHAINS } from '@lido-sdk/constants'; +import { contractHooksFactory } from '@lido-sdk/react'; +import invariant from 'tiny-invariant'; + +import { PartialStakingRouterAbi__factory } from 'generated/factories/PartialStakingRouterAbi__factory'; + +export const STAKING_ROUTER_BY_NETWORK: { + [key in CHAINS]?: string; +} = { + [CHAINS.Mainnet]: '0xFdDf38947aFB03C621C71b06C9C70bce73f12999', + [CHAINS.Holesky]: '0xd6EbF043D30A7fe46D1Db32BA90a0A51207FE229', +}; + +export const getStakingRouterAddress = (chainId: CHAINS): string => { + const address = STAKING_ROUTER_BY_NETWORK[chainId]; + invariant(address, 'chain is not supported'); + return address; +}; + +export const stakingRouter = contractHooksFactory( + PartialStakingRouterAbi__factory, + (chainId) => getStakingRouterAddress(chainId), +); diff --git a/features/rewards/components/rewardsTable/RewardsTable.tsx b/features/rewards/components/rewardsTable/RewardsTable.tsx index 7e0e27995..53462dc3b 100644 --- a/features/rewards/components/rewardsTable/RewardsTable.tsx +++ b/features/rewards/components/rewardsTable/RewardsTable.tsx @@ -39,13 +39,15 @@ export const RewardsTable: FC = (props) => { - setPage(currentPage - 1)} - activePage={page + 1} - siblingCount={0} - data-testid="pagination" - /> + {pageCount > 1 && ( + setPage(currentPage - 1)} + activePage={page + 1} + siblingCount={0} + data-testid="pagination" + /> + )} ); }; diff --git a/features/rewards/components/stats/Stats.tsx b/features/rewards/components/stats/Stats.tsx index 85061db6a..9bff50b72 100644 --- a/features/rewards/components/stats/Stats.tsx +++ b/features/rewards/components/stats/Stats.tsx @@ -70,7 +70,7 @@ export const Stats: React.FC = () => { )} - <Link href={`${config.rootOrigin}/faq`}> + <Link href={`${config.rootOrigin}/ethereum#apr`}> <Box data-testid="moreInfo" color="secondary" diff --git a/features/stake/stake-faq/list/lido-fee.tsx b/features/stake/stake-faq/list/lido-fee.tsx index afb74b737..6e0fa1eb8 100644 --- a/features/stake/stake-faq/list/lido-fee.tsx +++ b/features/stake/stake-faq/list/lido-fee.tsx @@ -1,19 +1,16 @@ import { FC } from 'react'; import { Accordion } from '@lidofinance/lido-ui'; -import { useContractSWR, useSTETHContractRPC } from '@lido-sdk/react'; import { DATA_UNAVAILABLE } from 'consts/text'; +import { useProtocolFee } from 'shared/hooks/use-protocol-fee'; export const LidoFee: FC = () => { - const contractRpc = useSTETHContractRPC(); - const lidoFee = useContractSWR({ - contract: contractRpc, - method: 'getFee', - }); + const protocolFee = useProtocolFee(); + const feeValue = - lidoFee.initialLoading || !lidoFee.data + protocolFee.initialLoading || !protocolFee.data ? DATA_UNAVAILABLE - : `${lidoFee.data / 100}%`; + : `${protocolFee.data}%`; return ( <Accordion summary="What fee is applied by Lido? What is this used for?"> diff --git a/features/stake/stake-faq/list/what-is-lido.tsx b/features/stake/stake-faq/list/what-is-lido.tsx index ea86bf430..bb5c1aaa4 100644 --- a/features/stake/stake-faq/list/what-is-lido.tsx +++ b/features/stake/stake-faq/list/what-is-lido.tsx @@ -6,9 +6,9 @@ export const WhatIsLido: FC = () => { <Accordion defaultExpanded summary="What is Lido?"> <p> Lido is the name of a family of open-source peer-to-system software - tools deployed and functioning on the Ethereum, Solana, and Polygon - blockchain networks. The software enables users to mint transferable - utility tokens, which receive rewards linked to the related validation + tools deployed and functioning on the Ethereum and Polygon blockchain + networks. The software enables users to mint transferable utility + tokens, which receive rewards linked to the related validation activities of writing data to the blockchain, while the tokens can be used in other on-chain activities. </p> diff --git a/features/stake/stake-form/stake-form-info.tsx b/features/stake/stake-form/stake-form-info.tsx index 9f4ff107b..d2252f674 100644 --- a/features/stake/stake-form/stake-form-info.tsx +++ b/features/stake/stake-form/stake-form-info.tsx @@ -2,25 +2,20 @@ import { useWatch } from 'react-hook-form'; import { Zero } from '@ethersproject/constants'; import { DataTable, DataTableRow } from '@lidofinance/lido-ui'; -import { useContractSWR, useSTETHContractRPC } from '@lido-sdk/react'; import { DATA_UNAVAILABLE } from 'consts/text'; -import { STRATEGY_CONSTANT } from 'consts/swr-strategies'; import { FormatPrice, FormatToken } from 'shared/formatters'; import { useEthUsd } from 'shared/hooks/use-eth-usd'; +import { useProtocolFee } from 'shared/hooks/use-protocol-fee'; import { StakeFormInput, useStakeFormData } from './stake-form-context'; export const StakeFormInfo = () => { const { gasCost, loading } = useStakeFormData(); const amount = useWatch<StakeFormInput, 'amount'>({ name: 'amount' }); - const contractRpc = useSTETHContractRPC(); - const lidoFee = useContractSWR({ - contract: contractRpc, - method: 'getFee', - config: STRATEGY_CONSTANT, - }); + const { usdAmount, initialLoading: isEthUsdLoading } = useEthUsd(gasCost); + const protocolFee = useProtocolFee(); return ( <DataTable data-testid="stakeFormInfo"> @@ -40,11 +35,11 @@ export const StakeFormInfo = () => { <DataTableRow title="Reward fee" data-testid="lidoFee" - loading={lidoFee.initialLoading} + loading={protocolFee.initialLoading} help="Please note: this fee applies to staking rewards only, and is NOT taken from your staked amount." > - {!lidoFee.data ? DATA_UNAVAILABLE : `${lidoFee.data / 100}%`} + {!protocolFee.data ? DATA_UNAVAILABLE : `${protocolFee.data}%`} </DataTableRow> </DataTable> ); diff --git a/features/withdrawals/claim/claim-form-context/claim-form-context.tsx b/features/withdrawals/claim/claim-form-context/claim-form-context.tsx index a09f44186..ac4c471b6 100644 --- a/features/withdrawals/claim/claim-form-context/claim-form-context.tsx +++ b/features/withdrawals/claim/claim-form-context/claim-form-context.tsx @@ -79,7 +79,7 @@ export const ClaimFormProvider: FC<PropsWithChildren> = ({ children }) => { defaultSelectedRequestCount, ).requests.map((request) => ({ ...request, - checked: checkedIds.has(request.token_id), + checked: request.status.isFinalized && checkedIds.has(request.token_id), })); setValue('requests', newRequests, { diff --git a/features/withdrawals/hooks/contract/useWithdrawalsData.ts b/features/withdrawals/hooks/contract/useWithdrawalsData.ts index b1a0e4161..592f97d8f 100644 --- a/features/withdrawals/hooks/contract/useWithdrawalsData.ts +++ b/features/withdrawals/hooks/contract/useWithdrawalsData.ts @@ -94,7 +94,9 @@ export const useWithdrawalRequests = () => { // const currentShareRate = args[3] as BigNumber; const [requestIds, lastCheckpointIndex] = await Promise.all([ - contractRpc.getWithdrawalRequests(account), + contractRpc.getWithdrawalRequests(account).then((ids) => { + return [...ids].sort((aId, bId) => (aId.gt(bId) ? 1 : -1)); + }), contractRpc.getLastCheckpointIndex(), ]); const requestStatuses = await contractRpc.getWithdrawalStatus(requestIds); @@ -153,24 +155,21 @@ export const useWithdrawalRequests = () => { isClamped ||= pendingRequests.splice(MAX_SHOWN_REQUEST_PER_TYPE).length > 0; - const _sortedClaimableRequests = claimableRequests.sort((aReq, bReq) => - aReq.id.gt(bReq.id) ? 1 : -1, - ); - const hints = await contractRpc.findCheckpointHints( - _sortedClaimableRequests.map(({ id }) => id), + claimableRequests.map(({ id }) => id), 1, lastCheckpointIndex, ); const claimableEth = await contractRpc.getClaimableEther( - _sortedClaimableRequests.map(({ id }) => id), + claimableRequests.map(({ id }) => id), hints, ); let claimableAmountOfETH = BigNumber.from(0); + const sortedClaimableRequests: RequestStatusClaimable[] = - _sortedClaimableRequests.map((request, index) => { + claimableRequests.map((request, index) => { claimableAmountOfETH = claimableAmountOfETH.add(claimableEth[index]); return { ...request, @@ -195,6 +194,7 @@ export const useWithdrawalRequests = () => { ); const oldData = swr.data; const mutate = swr.mutate; + const optimisticClaimRequests = useCallback( async (requests: RequestStatusClaimable[]) => { if (!oldData) return undefined; diff --git a/shared/hooks/use-protocol-fee.ts b/shared/hooks/use-protocol-fee.ts new file mode 100644 index 000000000..c5b2a06cc --- /dev/null +++ b/shared/hooks/use-protocol-fee.ts @@ -0,0 +1,46 @@ +import { formatEther } from '@ethersproject/units'; + +import { CHAINS } from '@lido-sdk/constants'; +import { useLidoSWR, useSDK } from '@lido-sdk/react'; +import { useStakingRouter } from './use-stakign-router-contract'; +import { PartialStakingRouterAbi } from 'generated/PartialStakingRouterAbi'; + +import { config } from 'config'; +import { STRATEGY_CONSTANT } from 'consts/swr-strategies'; + +export const useProtocolFee = () => { + const { chainId } = useSDK(); + const { contractRpc } = useStakingRouter(); + + return useLidoSWR<number>( + ['swr:useProtocolFee', chainId, contractRpc, config.enableQaHelpers], + // @ts-expect-error broken lidoSWR typings + async ( + _key: string, + _chainId: CHAINS, + contractRpc: PartialStakingRouterAbi, + shouldMock: boolean, + ) => { + const mockDataString = window.localStorage.getItem('protocolFee'); + + if (shouldMock && mockDataString) { + try { + const mockData = JSON.parse(mockDataString); + return mockData; + } catch (e) { + console.warn('Failed to load mock data'); + console.warn(e); + } + } + + const fee = await contractRpc.getStakingFeeAggregateDistribution(); + const value = Number(formatEther(fee.modulesFee.add(fee.treasuryFee))); + + return value.toFixed(0); + }, + { + ...STRATEGY_CONSTANT, + refreshInterval: 60000, + }, + ); +}; diff --git a/shared/hooks/use-stakign-router-contract.ts b/shared/hooks/use-stakign-router-contract.ts new file mode 100644 index 000000000..12bc17df4 --- /dev/null +++ b/shared/hooks/use-stakign-router-contract.ts @@ -0,0 +1,7 @@ +import { stakingRouter } from 'consts/staking-router'; + +export const useStakingRouter = () => { + const contractRpc = stakingRouter.useContractRPC(); + + return { contractRpc }; +};