import Modal from 'react-native-modal'; import React from 'react'; import { View, StyleSheet, Linking } from 'react-native'; import StyledButton from '../StyledButton'; import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import Text from '../../Base/Text'; import NetworkDetails from './NetworkDetails'; import NetworkAdded from './NetworkAdded'; import Engine from '../../../core/Engine'; import { isprivateConnection } from '../../../util/networks'; import getDecimalChainId from '../../../util/networks/getDecimalChainId'; import URLPARSE from 'url-parse'; import scaling from '../../../util/scaling'; import { isWebUri } from 'valid-url'; import FAIcon from 'react-native-vector-icons/FontAwesome'; import InfoModal from '../Swaps/components/InfoModal'; import ImageIcons from '../../UI/ImageIcon'; import { useDispatch } from 'react-redux'; import AnalyticsV2 from '../../../util/analyticsV2'; import sanitizeUrl from '../../../util/sanitizeUrl'; import { useAppThemeFromContext, mockTheme } from '../../../util/theme'; import { networkSwitched } from '../../../actions/onboardNetwork'; import { APPROVE_NETWORK_DISPLAY_NAME_ID, APPROVE_NETWORK_MODAL_ID, APPROVE_NETWORK_CANCEL_BUTTON_ID, APPROVE_NETWORK_APPROVE_BUTTON_ID, } from '../../../constants/test-ids'; const createStyles = (colors) => StyleSheet.create({ bottomModal: { justifyContent: 'flex-end', margin: 0, }, modalContainer: { borderRadius: 10, backgroundColor: colors.background.default, padding: 20, }, buttonView: { flexDirection: 'row', paddingVertical: 16, }, button: { flex: 1, }, cancel: { marginRight: 8, borderColor: colors.text.muted, borderWidth: 1, }, confirm: { marginLeft: 8, }, networkInformation: { flexDirection: 'row', justifyContent: 'flex-start', borderWidth: 1, borderColor: colors.text.muted, borderRadius: 10, padding: 16, marginBottom: 10, }, title: { ...fontStyles.bold, fontSize: scaling.scale(18), textAlign: 'center', color: colors.text.default, lineHeight: 34, marginVertical: 10, paddingHorizontal: 16, }, bottomSpace: { marginBottom: 10, }, nameWrapper: { backgroundColor: colors.background.alternative, marginRight: '15%', marginLeft: '15%', paddingVertical: 5, borderRadius: 40, justifyContent: 'center', alignItems: 'center', flexDirection: 'row', }, infoIconContainer: { paddingHorizontal: 3, }, infoIcon: { fontSize: 12, color: colors.icon.default, }, popularNetworkImage: { width: 20, height: 20, marginRight: 10, borderRadius: 10, }, }); interface NetworkProps { isVisible: boolean; onClose: () => void; network: any; navigation: any; } const NetworkModals = (props: NetworkProps) => { const { navigation, isVisible, onClose, network: { chainId, nickname, ticker, rpcUrl, formattedRpcUrl, rpcPrefs: { blockExplorerUrl, imageUrl }, }, } = props; const [showDetails, setShowDetails] = React.useState(false); const [showInfo, setShowInfo] = React.useState(false); const [networkAdded, setNetworkAdded] = React.useState(false); const showDetailsModal = () => setShowDetails(!showDetails); const { colors } = useAppThemeFromContext() || mockTheme; const styles = createStyles(colors); const dispatch = useDispatch(); const validateRpcUrl = (url: string) => { if (!isWebUri(url)) return false; return true; }; const addNetwork = async () => { const { PreferencesController } = Engine.context; let formChainId = chainId.trim().toLowerCase(); if (!formChainId.startsWith('0x')) { formChainId = `0x${parseInt(formChainId, 10).toString(16)}`; } const validUrl = validateRpcUrl(rpcUrl); if (validUrl) { const url = new URLPARSE(rpcUrl); const sanitizedUrl = sanitizeUrl(url.href); const decimalChainId = getDecimalChainId(chainId); !isprivateConnection(url.hostname) && url.set('protocol', 'https:'); PreferencesController.addToFrequentRpcList( url.href, decimalChainId, ticker, nickname, { blockExplorerUrl, }, ); const analyticsParamsAdd = { rpc_url: sanitizedUrl, chain_id: decimalChainId, source: 'Popular network list', symbol: ticker, block_explorer_url: blockExplorerUrl, network_name: nickname, }; AnalyticsV2.trackEvent( AnalyticsV2.ANALYTICS_EVENTS.NETWORK_ADDED, analyticsParamsAdd, ); setNetworkAdded(true); } else { setNetworkAdded(false); } }; const showToolTip = () => setShowInfo(!showInfo); const goToLink = () => Linking.openURL(strings('networks.security_link')); const closeModal = () => { onClose(); }; const switchNetwork = () => { const { NetworkController, CurrencyRateController } = Engine.context; const url = new URLPARSE(rpcUrl); const decimalChainId = getDecimalChainId(chainId); CurrencyRateController.setNativeCurrency(ticker); NetworkController.setRpcTarget(url.href, decimalChainId, ticker, nickname); closeModal(); navigation.navigate('WalletView'); dispatch(networkSwitched({ networkUrl: url.href, networkStatus: true })); }; return ( {showDetails ? ( ) : networkAdded ? ( ) : ( {showInfo && ( )} {nickname} {strings('networks.want_to_add_network')} {strings('networks.network_infomation')} {strings('networks.network_endorsement')} {strings('networks.learn_about')} {strings('networks.network_risk')} {strings('networks.network_display_name')} {nickname} {strings('networks.network_chain_id')} {chainId} {strings('networks.network_rpc_url')} {formattedRpcUrl || rpcUrl} {strings('networks.view_details')} {strings('networks.cancel')} {strings('networks.approve')} )} ); }; export default NetworkModals;