From a930cf8a1f788dac93c4e604f1f490e27fa78687 Mon Sep 17 00:00:00 2001 From: wsdt Date: Mon, 22 Apr 2024 18:58:00 +0200 Subject: [PATCH 1/8] feat: Add Disburser native out of funds error --- src/actions/bridgeAction.ts | 7 +++++++ src/actions/networkAction.ts | 5 +++++ .../modals/tokenPicker/TokenPickerModal.tsx | 6 ++++++ src/hooks/useBridgeAlerts/index.ts | 17 ++++++++++++++++ src/reducers/bridgeReducer.ts | 2 ++ src/selectors/bridgeSelector.ts | 3 +++ src/services/networkService.ts | 20 +++++++++++++++++++ 7 files changed, 60 insertions(+) diff --git a/src/actions/bridgeAction.ts b/src/actions/bridgeAction.ts index 7ff0711e..3863f52c 100644 --- a/src/actions/bridgeAction.ts +++ b/src/actions/bridgeAction.ts @@ -70,6 +70,13 @@ export const setTeleportationOfAssetSupported = payload, }) +export const setTeleportationDisburserBalance = + (payload: string) => (dispatch) => + dispatch({ + type: 'BRIDGE/TELEPORTER/DISBURSER_BALANCE', + payload, + }) + export const setTeleportationDestChainId = (payload: BigNumberish) => (dispatch) => dispatch({ diff --git a/src/actions/networkAction.ts b/src/actions/networkAction.ts index 1866dcbb..aa6af860 100644 --- a/src/actions/networkAction.ts +++ b/src/actions/networkAction.ts @@ -51,6 +51,11 @@ export const isTeleportationOfAssetSupported = ( networkService.isTeleportationOfAssetSupported(layer, asset, destChainId) ) +export const getDisburserBalance = (layer: string, asset: string) => + createAction('DEPOSIT/TELEPORTATION/DISBURSER_BALANCE', () => + networkService.getNativeDisburserBalance(layer, asset) + ) + export const depositWithLightBridge = ( layer: string, currency: string, diff --git a/src/containers/modals/tokenPicker/TokenPickerModal.tsx b/src/containers/modals/tokenPicker/TokenPickerModal.tsx index b945065a..7d47651d 100644 --- a/src/containers/modals/tokenPicker/TokenPickerModal.tsx +++ b/src/containers/modals/tokenPicker/TokenPickerModal.tsx @@ -1,10 +1,12 @@ import React, { FC, useEffect, useState } from 'react' import { setTeleportationOfAssetSupported, + setTeleportationDisburserBalance, updateToken, } from 'actions/bridgeAction' import { fetchBalances, + getDisburserBalance, isTeleportationOfAssetSupported, } from 'actions/networkAction' import { closeModal } from 'actions/uiAction' @@ -146,7 +148,11 @@ const TokenPickerModal: FC = ({ open, tokenIndex }) => { const isSupported = await dispatch( isTeleportationOfAssetSupported(layer, token.address, destChainId) ) + const disburserBalance = await dispatch( + getDisburserBalance(layer, token.address) + ) dispatch(setTeleportationOfAssetSupported(isSupported)) + dispatch(setTeleportationDisburserBalance(disburserBalance)) } handleClose() } diff --git a/src/hooks/useBridgeAlerts/index.ts b/src/hooks/useBridgeAlerts/index.ts index 7a512e48..b05a6161 100644 --- a/src/hooks/useBridgeAlerts/index.ts +++ b/src/hooks/useBridgeAlerts/index.ts @@ -11,6 +11,7 @@ import { selectBobaFeeChoice, selectBobaPriceRatio, selectBridgeType, + selectTeleportationDisburserBalance, selectExitFee, selectFastDepositCost, selectFastExitCost, @@ -33,6 +34,7 @@ import BN from 'bignumber.js' import { BRIDGE_TYPE } from 'containers/Bridging/BridgeTypeSelector' import { Network } from 'util/network/network.util' import { BigNumber, BigNumberish, ethers } from 'ethers' +import { formatEther } from '@ethersproject/units' enum ALERT_KEYS { OMG_INFO = 'OMG_INFO', @@ -46,6 +48,7 @@ enum ALERT_KEYS { DEPRECATION_WARNING = 'DEPRECATION_WARNING', TELEPORTATION_ASSET_NOT_SUPPORTED = 'TELEPORTER_ASSET_NOT_SUPPORTED', TELEPORTATION_NO_UNCONVENTIONAL_WALLETS = 'TELEPORTATION_NO_UNCONVENTIONAL_WALLETS', + TELEPORTATION_DISBURSER_OUT_OF_FUNDS = 'TELEPORTATION_DISBURSER_OUT_OF_FUNDS', } interface ITeleportationTokenSupport { @@ -67,6 +70,9 @@ const useBridgeAlerts = () => { const activeNetwork = useSelector(selectActiveNetwork()) const tokenForTeleportationSupported: ITeleportationTokenSupport = useSelector(selectIsTeleportationOfAssetSupported()) + const disburserBalance: BigNumber | undefined = useSelector( + selectTeleportationDisburserBalance() + ) // fast input layer 1 const L1LPBalance = useSelector(selectL2LPBalanceString) @@ -114,10 +120,21 @@ const useBridgeAlerts = () => { ALERT_KEYS.VALUE_LESS_THAN_MIN_BRIDGE_CONFIG_AMOUNT, ALERT_KEYS.VALUE_GREATER_THAN_MAX_BRIDGE_CONFIG_AMOUNT, ALERT_KEYS.MAX_BRIDGE_AMOUNT_PER_DAY_EXCEEDED, + ALERT_KEYS.TELEPORTATION_DISBURSER_OUT_OF_FUNDS, ], }) ) + if (disburserBalance && disburserBalance.lt(amountToBridge)) { + dispatch( + setBridgeAlert({ + meta: ALERT_KEYS.TELEPORTATION_DISBURSER_OUT_OF_FUNDS, + type: 'error', + text: `LightBridge has not enough funds for destination network left.`, + }) + ) + } + const maxDepositAmount = Number( ethers.utils.formatEther( tokenForTeleportationSupported.maxDepositAmount diff --git a/src/reducers/bridgeReducer.ts b/src/reducers/bridgeReducer.ts index fc075e79..16e289d4 100644 --- a/src/reducers/bridgeReducer.ts +++ b/src/reducers/bridgeReducer.ts @@ -35,6 +35,7 @@ interface IBridgeReducerState { amountToBridge: number destChainIdBridge: number isFetchTxBlockNumber: boolean + teleportationDisburserBalance: BigNumberish isTeleportationOfAssetSupported: { supported: boolean minDepositAmount: number @@ -57,6 +58,7 @@ const initialState: IBridgeReducerState = { amountToBridge: 0, destChainIdBridge: 0, isFetchTxBlockNumber: false, + teleportationDisburserBalance: 0, isTeleportationOfAssetSupported: { supported: false, minDepositAmount: 0, diff --git a/src/selectors/bridgeSelector.ts b/src/selectors/bridgeSelector.ts index d5067889..cd1c0f85 100644 --- a/src/selectors/bridgeSelector.ts +++ b/src/selectors/bridgeSelector.ts @@ -36,5 +36,8 @@ export const selectIsFetchTxBlockNumber = () => (state) => export const selectIsTeleportationOfAssetSupported = () => (state) => state.bridge.isTeleportationOfAssetSupported +export const selectTeleportationDisburserBalance = () => (state) => + state.bridge.teleportationDisburserBalance + export const selectReenterWithdrawalConfig = () => (state) => state.bridge.withdrawalConfig diff --git a/src/services/networkService.ts b/src/services/networkService.ts index 34b6fcdf..e200dfd4 100644 --- a/src/services/networkService.ts +++ b/src/services/networkService.ts @@ -42,6 +42,7 @@ import { CHAIN_ID_LIST, getNetworkDetail, getRpcUrl, + getRpcUrlByChainId, Network, networkLimitedAvailability, NetworkType, @@ -2002,6 +2003,7 @@ class NetworkService { // FIXME: move this to separate service of earn. /***********************************************/ /***** Get Reward *****/ + /***********************************************/ async getReward( currencyAddress, @@ -2140,6 +2142,24 @@ class NetworkService { return this.LightBridge!.attach(lightBridgeAddr).connect(provider) } + async getNativeDisburserBalance(destChainId, token) { + // not just simply L2/L1 as also L2<>L2 supported, .. + const destProvider = new ethers.providers.StaticJsonRpcProvider( + getRpcUrlByChainId(destChainId) + ) + const isNative = + token === ethers.constants.AddressZero || + token === this.addresses.L2_ETH_Address + + const disburserAddr = + await this.getLightBridgeContract(destChainId)?.disburser() + if (!disburserAddr || !isNative) { + return + } + // TODO: Add token support later on (proper token mapping, avoid code duplication & maintenance overhead) + return destProvider.getBalance(disburserAddr) + } + async isTeleportationOfAssetSupported(layer, token, destChainId) { const lightBridgeAddr = layer === Layer.L1 From 548a6a2ce4f1b01d4b0a984e49c3b7ed5b8705bc Mon Sep 17 00:00:00 2001 From: wsdt Date: Mon, 22 Apr 2024 23:45:06 +0200 Subject: [PATCH 2/8] fix tests --- src/hooks/useBridgeAlerts/index.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hooks/useBridgeAlerts/index.test.tsx b/src/hooks/useBridgeAlerts/index.test.tsx index 4d370627..786b85e1 100644 --- a/src/hooks/useBridgeAlerts/index.test.tsx +++ b/src/hooks/useBridgeAlerts/index.test.tsx @@ -101,6 +101,7 @@ describe('useBridgeAlerts', () => { 'VALUE_LESS_THAN_MIN_BRIDGE_CONFIG_AMOUNT', 'VALUE_GREATER_THAN_MAX_BRIDGE_CONFIG_AMOUNT', 'MAX_BRIDGE_AMOUNT_PER_DAY_EXCEEDED', + 'TELEPORTATION_DISBURSER_OUT_OF_FUNDS', ], }, type: 'BRIDGE/ALERT/CLEAR', From cf512b8d936c6745186143bc1736072b6f942fed Mon Sep 17 00:00:00 2001 From: Sahil Kashetwar Date: Wed, 24 Apr 2024 09:08:52 +0530 Subject: [PATCH 3/8] change for token bigNumber --- .../VerticalStepper.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx b/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx index 3b0310de..f2e63b47 100644 --- a/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx +++ b/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx @@ -30,11 +30,13 @@ import { dayNowUnix, isBeforeDate, } from 'util/dates' +import { toWei_String } from 'util/amountConvert' +import { parseUnits } from '@ethersproject/units' interface IVerticalStepperProps { handleClose: () => void token?: any - amountToBridge?: number + amountToBridge: number reenterWithdrawConfig?: any } @@ -89,10 +91,22 @@ export const VerticalStepper = (props: IVerticalStepperProps) => { const isNativeWithdrawal = props.token.address === networkService.addresses.NETWORK_NATIVE_TOKEN selectModalState('transactionSuccess') + console.log( + `usdt amount`, + toWei_String(props.amountToBridge, props.token.decimals) + ) + console.log( + `usdt amount p`, + parseUnits(props.amountToBridge.toString(), props.token.decimals) + ) + const value = parseUnits( + props.amountToBridge.toString(), + props.token.decimals + ) handleInitiateWithdrawal( networkService as MinimalNetworkService, L2StandardERC20ABI, - ethers.utils.parseEther(props.amountToBridge!.toString()).toString(), + value.toString(), isNativeWithdrawal ? null : props.token ) .then((res) => { From 4da9478077ba372b570600b9c1e427dd3943adac Mon Sep 17 00:00:00 2001 From: Sahil Kashetwar Date: Wed, 24 Apr 2024 09:27:39 +0530 Subject: [PATCH 4/8] parsing of funds before making withdraw --- .../MultiStepWithdrawalModal/VerticalStepper.tsx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx b/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx index f2e63b47..26d8b59a 100644 --- a/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx +++ b/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx @@ -91,22 +91,12 @@ export const VerticalStepper = (props: IVerticalStepperProps) => { const isNativeWithdrawal = props.token.address === networkService.addresses.NETWORK_NATIVE_TOKEN selectModalState('transactionSuccess') - console.log( - `usdt amount`, - toWei_String(props.amountToBridge, props.token.decimals) - ) - console.log( - `usdt amount p`, - parseUnits(props.amountToBridge.toString(), props.token.decimals) - ) - const value = parseUnits( - props.amountToBridge.toString(), - props.token.decimals - ) handleInitiateWithdrawal( networkService as MinimalNetworkService, L2StandardERC20ABI, - value.toString(), + ethers.utils + .parseUnits(props.amountToBridge!.toString(), props.token.decimals) + .toString(), isNativeWithdrawal ? null : props.token ) .then((res) => { From da6501c79642b02b4394a8e0632dbcc36a7eae0d Mon Sep 17 00:00:00 2001 From: Sahil Kashetwar Date: Wed, 24 Apr 2024 09:31:36 +0530 Subject: [PATCH 5/8] - remove unused import --- .../modals/MultiStepWithdrawalModal/VerticalStepper.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx b/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx index 26d8b59a..d4995d0b 100644 --- a/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx +++ b/src/containers/modals/MultiStepWithdrawalModal/VerticalStepper.tsx @@ -30,8 +30,6 @@ import { dayNowUnix, isBeforeDate, } from 'util/dates' -import { toWei_String } from 'util/amountConvert' -import { parseUnits } from '@ethersproject/units' interface IVerticalStepperProps { handleClose: () => void From 64a75b1eb2f0d96213b03fffa23fef523a8e41fc Mon Sep 17 00:00:00 2001 From: Sahil Kashetwar Date: Wed, 24 Apr 2024 09:45:07 +0530 Subject: [PATCH 6/8] refactor open modal function --- src/actions/uiAction.ts | 27 +++++++++---------- src/components/listProposal/listProposal.js | 2 +- .../Bridging/BridgeAction/index.tsx | 2 +- .../Bridging/BridgeHeader/index.tsx | 2 +- src/containers/Bridging/BridgeInput/index.tsx | 2 +- src/containers/Bridging/chain/index.tsx | 15 ++++------- src/containers/Bridging/index.tsx | 2 +- src/containers/dao/OldDao.js | 4 +-- .../earn/earnList/earnListItem/index.tsx | 2 +- .../history/TransactionsResolver.tsx | 2 +- .../VerticalStepper.tsx | 4 +-- .../earn/EarnWithdrawConfirmModal/index.tsx | 2 +- src/containers/modals/earn/index.tsx | 2 +- src/containers/modals/index.tsx | 5 ---- .../modals/noMetaMask/NoMetaMaskModal.tsx | 2 +- src/containers/save/Save.tsx | 4 ++- src/hooks/useBridge/index.ts | 6 ++--- src/hooks/useSwitchChain/index.ts | 2 +- src/hooks/useWalletConnect/index.ts | 8 +++--- src/hooks/useWalletSwitch/index.ts | 2 +- src/services/wallet.service.ts | 2 +- 21 files changed, 45 insertions(+), 54 deletions(-) diff --git a/src/actions/uiAction.ts b/src/actions/uiAction.ts index 880935dc..dbf495c6 100644 --- a/src/actions/uiAction.ts +++ b/src/actions/uiAction.ts @@ -18,25 +18,24 @@ export const setTheme = (dispatch) => dispatch({ type: 'UI/THEME/UPDATE', payload: theme }) +interface IOpenModalProps { + modal?: string + proposalId?: any + selectionLayer?: any + destNetworkSelection?: any +} + export const openModal = - ( - modal?, - token?, - fast?, - tokenIndex?, - lock?, - proposalId?, - selectionLayer?, - destNetworkSelection? - ): any => + ({ + modal, + proposalId, + selectionLayer, + destNetworkSelection, + }: IOpenModalProps): any => (dispatch) => dispatch({ type: 'UI/MODAL/OPEN', payload: modal, - token, - fast, - tokenIndex, - lock, proposalId, selectionLayer, destNetworkSelection, diff --git a/src/components/listProposal/listProposal.js b/src/components/listProposal/listProposal.js index 666787ba..4c62d61c 100644 --- a/src/components/listProposal/listProposal.js +++ b/src/components/listProposal/listProposal.js @@ -55,7 +55,7 @@ const ListProposal = ({ proposal }) => { }, [proposal]) const onVote = (id) => { - dispatch(openModal('castVoteModal', null, null, null, null, id)) + dispatch(openModal({modal: 'castVoteModal',proposalId: id})) } const doQueueProposal = async () => { diff --git a/src/containers/Bridging/BridgeAction/index.tsx b/src/containers/Bridging/BridgeAction/index.tsx index ab7d80c9..f80bd8e3 100644 --- a/src/containers/Bridging/BridgeAction/index.tsx +++ b/src/containers/Bridging/BridgeAction/index.tsx @@ -29,7 +29,7 @@ const BridgeAction = () => { const onBridge = () => { if (!isBridgeActionDisabled()) { - dispatch(openModal('bridgeConfirmModal')) + dispatch(openModal({ modal: 'bridgeConfirmModal' })) } } diff --git a/src/containers/Bridging/BridgeHeader/index.tsx b/src/containers/Bridging/BridgeHeader/index.tsx index 6382fb45..d9c475c3 100644 --- a/src/containers/Bridging/BridgeHeader/index.tsx +++ b/src/containers/Bridging/BridgeHeader/index.tsx @@ -34,7 +34,7 @@ const BridgeHeader = () => { theme.name === 'light' ? theme.colors.gray[600] : theme.colors.gray[100] const openSettingModal = () => { - dispatch(openModal('settingsModal')) + dispatch(openModal({ modal: 'settingsModal' })) } // TODO: update the copy when the anchorage bridge is enabled. diff --git a/src/containers/Bridging/BridgeInput/index.tsx b/src/containers/Bridging/BridgeInput/index.tsx index 10511262..97f82298 100644 --- a/src/containers/Bridging/BridgeInput/index.tsx +++ b/src/containers/Bridging/BridgeInput/index.tsx @@ -38,7 +38,7 @@ const BridgeInput: FC = (props) => { useBridgeSetup() const openTokenPicker = () => { - dispatch(openModal('tokenPicker')) + dispatch(openModal({ modal: 'tokenPicker' })) } if (!isAccountEnabled) { diff --git a/src/containers/Bridging/chain/index.tsx b/src/containers/Bridging/chain/index.tsx index 14bd1591..c871120e 100644 --- a/src/containers/Bridging/chain/index.tsx +++ b/src/containers/Bridging/chain/index.tsx @@ -49,16 +49,11 @@ const Chains = (props: Props) => { sLayer = inputLayer === 'l1' ? 'l2' : 'l1' } dispatch( - openModal( - 'networkPicker', - null, - null, - null, - null, - null, - sLayer, - destNetworkSelection - ) + openModal({ + modal: 'networkPicker', + selectionLayer: sLayer, + destNetworkSelection, + }) ) } diff --git a/src/containers/Bridging/index.tsx b/src/containers/Bridging/index.tsx index 535b434c..c920e0d2 100644 --- a/src/containers/Bridging/index.tsx +++ b/src/containers/Bridging/index.tsx @@ -64,7 +64,7 @@ const Bridging = () => { state={reenterWithdrawConfig?.state} onReenterWithdrawal={() => { dispatch(setReenterWithdrawalConfig(reenterWithdrawConfig)) - dispatch(openModal('bridgeMultiStepWithdrawal')) + dispatch(openModal({ modal: 'bridgeMultiStepWithdrawal' })) }} /> )} diff --git a/src/containers/dao/OldDao.js b/src/containers/dao/OldDao.js index 788d8060..26428f40 100644 --- a/src/containers/dao/OldDao.js +++ b/src/containers/dao/OldDao.js @@ -119,7 +119,7 @@ const OldDao = () => { ) ) } else { - dispatch(openModal('newProposalModal')) + dispatch(openModal({modal: 'newProposalModal'})) } } @@ -175,7 +175,7 @@ const OldDao = () => {