diff --git a/src/screens/Confirmations/variants/AddNetworkConfirmation/index.tsx b/src/screens/Confirmations/variants/AddNetworkConfirmation/index.tsx index 4637923d2..87b00bac3 100644 --- a/src/screens/Confirmations/variants/AddNetworkConfirmation/index.tsx +++ b/src/screens/Confirmations/variants/AddNetworkConfirmation/index.tsx @@ -1,16 +1,20 @@ import { ConfirmationDefinitions, ConfirmationResult } from '@subwallet/extension-base/background/KoniTypes'; import { ConfirmationContent, ConfirmationGeneralInfo } from 'components/common/Confirmation'; import ConfirmationFooter from 'components/common/Confirmation/ConfirmationFooter'; -import { Button, Icon } from 'components/design-system-ui'; +import { ActivityIndicator, Button, Icon } from 'components/design-system-ui'; import { FieldBase } from 'components/Field/Base'; import { useSubWalletTheme } from 'hooks/useSubWalletTheme'; -import { CheckCircle, Globe, ShareNetwork, XCircle } from 'phosphor-react-native'; -import React, { useCallback, useMemo, useState } from 'react'; +import { CheckCircle, Globe, ShareNetwork, WifiHigh, WifiSlash, XCircle } from 'phosphor-react-native'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { Text, View } from 'react-native'; -import { completeConfirmation } from 'messaging/index'; +import { completeConfirmation, validateCustomChain } from 'messaging/index'; import i18n from 'utils/i18n/i18n'; import createStyle from './styles'; +import { ValidationInfo } from 'screens/ImportNetwork'; +import { isUrl } from 'utils/index'; +import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chain-service/handler/types'; +import { Warning } from 'components/Warning'; interface Props { request: ConfirmationDefinitions['addNetworkRequest'][0]; @@ -28,7 +32,10 @@ const AddNetworkConfirmation: React.FC = (props: Props) => { const { payload: { chainEditInfo, chainSpec, mode }, } = request; - + const [isShowConnectionStatus, setIsShowConnectionStatus] = useState(false); + const [providerValidation, setProviderValidation] = useState({ status: '' }); + const [isValidating, setIsValidating] = useState(false); + const [errorMessage, setErrorMessage] = useState(undefined); const theme = useSubWalletTheme().swThemes; const styles = useMemo(() => createStyle(theme), [theme]); @@ -54,6 +61,80 @@ const AddNetworkConfirmation: React.FC = (props: Props) => { }, 300); }, [request]); + const handleErrorMessage = useCallback((errorCode: _CHAIN_VALIDATION_ERROR) => { + switch (errorCode) { + case _CHAIN_VALIDATION_ERROR.CONNECTION_FAILURE: + return i18n.errorMessage.cannotConnectToThisProvider; + case _CHAIN_VALIDATION_ERROR.EXISTED_PROVIDER: + return i18n.errorMessage.thisChainHasAlreadyBeenAdded; + case _CHAIN_VALIDATION_ERROR.EXISTED_CHAIN: + return i18n.errorMessage.thisChainHasAlreadyBeenAdded; + default: + return i18n.errorMessage.validateProviderError; + } + }, []); + + const providerValidateFunc = useCallback( + (provider: string) => { + if (isUrl(provider)) { + setIsShowConnectionStatus(true); + setIsValidating(true); + const parsedProvider = provider.split(' ').join(''); + + validateCustomChain(parsedProvider) + .then(result => { + setIsValidating(false); + + if (result.success) { + setProviderValidation({ status: 'success' }); + setErrorMessage(undefined); + } + + if (result.error) { + setProviderValidation({ status: 'error' }); + setErrorMessage(handleErrorMessage(result.error)); + } + }) + .catch(() => { + setIsValidating(false); + setProviderValidation({ status: 'error' }); + setErrorMessage(i18n.errorMessage.validateProviderError); + }); + } else { + setProviderValidation({ status: '' }); + setIsShowConnectionStatus(false); + setErrorMessage(i18n.errorMessage.invalidProviderUrl); + } + }, + [handleErrorMessage], + ); + + useEffect(() => { + providerValidateFunc(chainEditInfo.providers[chainEditInfo.currentProvider]); + }, [chainEditInfo.currentProvider, chainEditInfo.providers, providerValidateFunc]); + + const providerSuffix = useCallback(() => { + if (!isShowConnectionStatus) { + return <>; + } + + if (providerValidation.status === 'success') { + return ( + + ); + } + + if (isValidating) { + return ; + } + + if (providerValidation.status === 'error') { + return ; + } + + return <>; + }, [isShowConnectionStatus, isValidating, providerValidation.status, theme]); + return ( @@ -61,26 +142,36 @@ const AddNetworkConfirmation: React.FC = (props: Props) => { {i18n.confirmation.addNetworkRequest} - - - - {chainEditInfo.providers[chainEditInfo.currentProvider] || i18n.confirmation.providerUrl} - + + + + + {chainEditInfo.providers[chainEditInfo.currentProvider] || i18n.confirmation.providerUrl} + + + {providerSuffix()} + + {errorMessage && } - {chainEditInfo.name || i18n.common.network} + + {chainEditInfo.name || i18n.common.network} + - {chainEditInfo.symbol || i18n.common.symbol} + + {chainEditInfo.symbol || i18n.common.symbol} + @@ -89,31 +180,49 @@ const AddNetworkConfirmation: React.FC = (props: Props) => { - {chainSpec?.decimals || i18n.common.decimals} + + {chainSpec?.decimals || i18n.common.decimals} + - {chainSpec?.evmChainId || i18n.confirmation.chainId} + + {chainSpec?.evmChainId || i18n.confirmation.chainId} + - {chainEditInfo.chainType || i18n.confirmation.chainType} + + {chainEditInfo.chainType || i18n.confirmation.chainType} + - {chainEditInfo.blockExplorer || i18n.confirmation.blockExplorer} + + {chainEditInfo.blockExplorer || i18n.confirmation.blockExplorer} + - {chainEditInfo.crowdloanUrl || i18n.confirmation.crowdloanURL} + + {chainEditInfo.crowdloanUrl || i18n.confirmation.crowdloanURL} + @@ -124,8 +233,16 @@ const AddNetworkConfirmation: React.FC = (props: Props) => {