diff --git a/src/components/bridge/ethereum/L1.vue b/src/components/bridge/ethereum/L1.vue index 52ee5a488..75d4704a9 100644 --- a/src/components/bridge/ethereum/L1.vue +++ b/src/components/bridge/ethereum/L1.vue @@ -15,7 +15,7 @@ :set-right-ui="setRightUi" :bridge-amt="String(bridgeAmt)" :err-msg="errMsg" - :is-disabled-bridge="isDisabledBridge" + :is-disabled-bridge="isDisabledBridge || !isGelatoApiConnected" :from-bridge-balance="fromBridgeBalance" :to-bridge-balance="toBridgeBalance" :from-chain-name="fromChainName" @@ -111,6 +111,7 @@ export default defineComponent({ l1Network, l2Network, isActionRequired, + isGelatoApiConnected, fetchUserHistory, handleClaim, } = useL1History(); @@ -224,6 +225,7 @@ export default defineComponent({ isApproved, isApproving, isApproveMaxAmount, + isGelatoApiConnected, inputImportTokenHandler, cancelHighlight, handleSetToken, diff --git a/src/hooks/bridge/useL1History.ts b/src/hooks/bridge/useL1History.ts index e80e3b808..5c742d517 100644 --- a/src/hooks/bridge/useL1History.ts +++ b/src/hooks/bridge/useL1History.ts @@ -9,6 +9,7 @@ import { ZkChainId, checkIsL1, fetchAccountHistory, + fetchIsGelatoApiHealth, getChainIdFromNetId, } from 'src/modules/zk-evm-bridge'; import { container } from 'src/v2/common'; @@ -19,8 +20,14 @@ import { useEthProvider } from '../custom-signature/useEthProvider'; import { astarNativeTokenErcAddr } from 'src/modules/xcm'; import { AbiItem } from 'web3-utils'; import ERC20_ABI from 'src/config/abi/ERC20.json'; +import { useStore } from 'src/store'; +import { useI18n } from 'vue-i18n'; export const useL1History = () => { + const { t } = useI18n(); + const store = useStore(); + const isGelatoApiConnected = ref(false); + const l1Network = computed(() => { const networkIdxStore = String(localStorage.getItem(LOCAL_STORAGE.NETWORK_IDX)); return networkIdxStore === String(endpointKey.ASTAR_ZKEVM) @@ -68,9 +75,16 @@ export const useL1History = () => { }; const fetchUserHistory = async (): Promise => { + if (!currentAccount.value) return; try { isLoadingHistories.value = true; const data = await fetchAccountHistory(currentAccount.value); + const isHealth = await fetchIsGelatoApiHealth(); + if (!isHealth) { + throw Error('The API is currently in maintenance mode.'); + } + isGelatoApiConnected.value = true; + const l1Web3 = buildWeb3Instance(EthBridgeChainId[l1Network.value as EthBridgeNetworkName]); const l2Web3 = buildWeb3Instance(EthBridgeChainId[l2Network.value as EthBridgeNetworkName]); @@ -121,6 +135,16 @@ export const useL1History = () => { isFetchAutomatically.value = numberInProgress > 0; histories.value = formattedResult.sort((a, b) => Number(b.timestamp) - Number(a.timestamp)); } catch (error) { + // Memo: disable sending bridge transactions from UI + store.dispatch( + 'general/showAlertMsg', + { + msg: t('bridge.gelatoApiError'), + alertType: 'error', + }, + { root: true } + ); + isGelatoApiConnected.value = false; console.error(error); isFetchAutomatically.value = false; } finally { @@ -146,6 +170,7 @@ export const useL1History = () => { histories, isLoadingHistories, isActionRequired, + isGelatoApiConnected, handleClaim, fetchUserHistory, }; diff --git a/src/hooks/useGasPrice.ts b/src/hooks/useGasPrice.ts index f171f805e..1155c3762 100644 --- a/src/hooks/useGasPrice.ts +++ b/src/hooks/useGasPrice.ts @@ -74,7 +74,13 @@ export const useGasPrice = (isFetch = false) => { watch( [network], async () => { - if (isFetch && network.value && !gas.value && isEnableSpeedConfiguration.value) { + if ( + isFetch && + network.value && + !gas.value && + isEnableSpeedConfiguration.value && + !isZkEvm.value + ) { // console.info('gas price', network.value, gas.value); await dispatchGasPrice(network.value); } diff --git a/src/i18n/en-US/index.ts b/src/i18n/en-US/index.ts index 2fe1d4a65..21a5d3792 100644 --- a/src/i18n/en-US/index.ts +++ b/src/i18n/en-US/index.ts @@ -986,6 +986,7 @@ export default { warning32blocks: 'It could take around 10~20mins or more to finalize', warning2steps: 'Bridging to L1 (Ethereum) involves 2 steps, and it requires users to make a claim on the L1 network (available in Recent History)', + gelatoApiError: 'Bridge UI is not available, please try again later', tokenInfo: { invalidTokenAddress: 'Invalid token address', tokenAddress: '{network} token address', diff --git a/src/modules/zk-evm-bridge/l1-bridge/utils.ts b/src/modules/zk-evm-bridge/l1-bridge/utils.ts index da9f05ca9..dace6a84f 100644 --- a/src/modules/zk-evm-bridge/l1-bridge/utils.ts +++ b/src/modules/zk-evm-bridge/l1-bridge/utils.ts @@ -65,6 +65,13 @@ const getApiUrl = (): string => { return zkEvmApi[network]; }; +export const fetchIsGelatoApiHealth = async (): Promise => { + const base = getApiUrl(); + const url = `${base}/healthz`; + const result = await axios.get<{ status: string }>(url); + return result && result.data.status === 'SERVING'; +}; + export const fetchAccountHistory = async (address: string): Promise => { const base = getApiUrl(); const limit = 15;