diff --git a/packages/suite/src/constants/suite/anchors.ts b/packages/suite/src/constants/suite/anchors.ts index 472cc2c14e9..04481ac0353 100644 --- a/packages/suite/src/constants/suite/anchors.ts +++ b/packages/suite/src/constants/suite/anchors.ts @@ -6,6 +6,7 @@ export const enum SettingsAnchor { LabelingDisconnect = '@general-settings/labeling-disconnect', LabelingConnect = '@general-settings/labeling-connect', Tor = '@general-settings/tor', + TorExternal = '@general-settings/tor-external', TorOnionLinks = '@general-settings/tor-onion-links', Theme = '@general-settings/theme', AddressDisplay = '@general-settings/address-display', diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index c28557b07aa..e5b0ac78651 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -5039,6 +5039,15 @@ export default defineMessages({ defaultMessage: 'Connect to an external Tor daemon running on port 9050, rather than using the one bundled with Trezor Suite.', }, + TR_EXPERIMENTAL_TOR_EXTERNAL_PORT: { + id: 'TR_EXPERIMENTAL_TOR_EXTERNAL_PORT', + defaultMessage: 'Tor external port', + }, + TR_EXPERIMENTAL_TOR_EXTERNAL_PORT_DESCRIPTION: { + id: 'TR_EXPERIMENTAL_TOR_EXTERNAL_PORT_DESCRIPTION', + defaultMessage: + 'Allows you to use Tor daemon running in a external process instead of the one bundled with Trezor Suite.', + }, TR_EARLY_ACCESS: { id: 'TR_EARLY_ACCESS', defaultMessage: 'Early Access Program', diff --git a/packages/suite/src/views/settings/SettingsGeneral/SettingsGeneral.tsx b/packages/suite/src/views/settings/SettingsGeneral/SettingsGeneral.tsx index 2972d683f3f..5dbf0ec39d3 100644 --- a/packages/suite/src/views/settings/SettingsGeneral/SettingsGeneral.tsx +++ b/packages/suite/src/views/settings/SettingsGeneral/SettingsGeneral.tsx @@ -7,6 +7,7 @@ import { useLayoutSize, useSelector } from 'src/hooks/suite'; import { selectIsSettingsDesktopAppPromoBannerShown, selectTorState, + selectHasExperimentalFeature, } from 'src/reducers/suite/suiteReducer'; import { selectEnabledNetworks } from 'src/reducers/wallet/settingsReducer'; import { selectSelectedProviderForLabels } from 'src/reducers/suite/metadataReducer'; @@ -32,6 +33,7 @@ import { Experimental } from './Experimental'; import { AutomaticUpdate } from './AutomaticUpdate'; import { AutoStart } from './AutoStart'; import { ShowOnTray } from './ShowOnTray'; +import { TorExternal } from './TorExternal'; export const SettingsGeneral = () => { const shouldShowSettingsDesktopAppPromoBanner = useSelector( @@ -50,6 +52,10 @@ export const SettingsGeneral = () => { return networkFeatures.includes('amount-unit'); }); + const torExternalExperimentalFeature = useSelector( + selectHasExperimentalFeature('tor-external'), + ); + const isMetadataEnabled = metadata.enabled && !metadata.initiating; const isProviderConnected = useSelector(selectSelectedProviderForLabels); const isExperimentalEnabled = useSelector(state => state.suite.settings.experimental); @@ -80,6 +86,7 @@ export const SettingsGeneral = () => { } icon="torBrowser"> {isDesktop() && } {isTorEnabled && } + {torExternalExperimentalFeature && } )} diff --git a/packages/suite/src/views/settings/SettingsGeneral/TorExternal.tsx b/packages/suite/src/views/settings/SettingsGeneral/TorExternal.tsx new file mode 100644 index 00000000000..0588a1a0c20 --- /dev/null +++ b/packages/suite/src/views/settings/SettingsGeneral/TorExternal.tsx @@ -0,0 +1,84 @@ +import { useEffect, useState } from 'react'; + +import { TorSettings } from '@trezor/suite-desktop-api/src/messages'; +import { desktopApi } from '@trezor/suite-desktop-api'; + +import { ActionColumn, ActionSelect, TextColumn, Translation } from 'src/components/suite'; +import { selectTorState } from 'src/reducers/suite/suiteReducer'; +import { useSelector } from 'src/hooks/suite'; +import { SettingsSectionItem } from 'src/components/settings'; +import { SettingsAnchor } from 'src/constants/suite/anchors'; + +const options = [ + { + value: 9050, + label: 'Tor external (9050)', + }, + { + value: 9150, + label: 'Tor browser (9150)', + }, +]; + +export const TorExternal = () => { + const { isTorEnabled } = useSelector(selectTorState); + + const [torSettings, setTorSettings] = useState(null); + + const [selectedOption, setSelectedOption] = useState<{ value: number; label: string }>( + options[0], + ); + + useEffect(() => { + const fetchTorSettings = async () => { + const result = await desktopApi.getTorSettings(); + if (result.success) { + setTorSettings(result.payload); + } + }; + + fetchTorSettings(); + + const handleTorSettingsChange = (settings: TorSettings) => setTorSettings(settings); + desktopApi.on('tor/settings', handleTorSettingsChange); + + return () => { + desktopApi.removeAllListeners('tor/settings'); + }; + }, []); + + useEffect(() => { + if (!torSettings) return; + const { externalPort } = torSettings; + const selectedOption = options.find(o => o.value === externalPort); + setSelectedOption(selectedOption!); + }, [torSettings]); + + const onChange = async ({ value }: { value: number }) => { + if (!torSettings) return; + await desktopApi.changeTorSettings({ + ...torSettings, + externalPort: value, + }); + }; + + if (!torSettings) return null; + + return ( + + } + description={} + /> + + + + + ); +};