2024-01-04 20:08:27 +00:00
|
|
|
import 'dart:io';
|
|
|
|
|
2024-01-24 17:39:13 +00:00
|
|
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
2024-01-04 20:08:27 +00:00
|
|
|
import 'package:cake_wallet/di.dart';
|
|
|
|
import 'package:cake_wallet/store/app_store.dart';
|
2023-12-20 01:20:21 +00:00
|
|
|
import 'package:cake_wallet/store/settings_store.dart';
|
2024-01-04 18:43:11 +00:00
|
|
|
import 'package:cake_wallet/view_model/settings/tor_connection.dart';
|
2024-01-24 17:39:13 +00:00
|
|
|
import 'package:cw_core/wallet_type.dart';
|
2023-12-20 01:20:21 +00:00
|
|
|
import 'package:mobx/mobx.dart';
|
2024-01-12 19:53:19 +00:00
|
|
|
import 'package:socks5_proxy/socks_client.dart';
|
2024-01-04 18:43:11 +00:00
|
|
|
import 'package:tor/tor.dart';
|
2023-12-20 01:20:21 +00:00
|
|
|
|
|
|
|
part 'tor_view_model.g.dart';
|
|
|
|
|
|
|
|
class TorViewModel = TorViewModelBase with _$TorViewModel;
|
|
|
|
|
2024-01-04 18:43:11 +00:00
|
|
|
enum TorConnectionStatus { connecting, connected, disconnected }
|
2023-12-20 01:20:21 +00:00
|
|
|
|
2024-01-04 18:43:11 +00:00
|
|
|
abstract class TorViewModelBase with Store {
|
2024-01-04 20:08:27 +00:00
|
|
|
TorViewModelBase(this._settingsStore) {
|
|
|
|
reaction((_) => torConnectionMode, (TorConnectionMode mode) async {
|
2024-01-23 18:36:46 +00:00
|
|
|
if (mode == TorConnectionMode.enabled || mode == TorConnectionMode.torOnly) {
|
2024-01-04 20:08:27 +00:00
|
|
|
startTor();
|
|
|
|
} else {
|
|
|
|
stopTor();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2023-12-20 01:20:21 +00:00
|
|
|
|
|
|
|
final SettingsStore _settingsStore;
|
|
|
|
|
|
|
|
@action
|
|
|
|
Future<void> updateStartOnLaunch(bool value) async {
|
|
|
|
_settingsStore.shouldStartTorOnLaunch = value;
|
|
|
|
}
|
2024-01-04 18:43:11 +00:00
|
|
|
|
|
|
|
@computed
|
|
|
|
TorConnectionMode get torConnectionMode => _settingsStore.torConnectionMode;
|
|
|
|
|
2024-01-04 20:08:27 +00:00
|
|
|
@observable
|
|
|
|
TorConnectionStatus torConnectionStatus = TorConnectionStatus.disconnected;
|
|
|
|
|
2024-01-04 18:43:11 +00:00
|
|
|
@action
|
|
|
|
void setTorConnectionMode(TorConnectionMode mode) => _settingsStore.torConnectionMode = mode;
|
|
|
|
|
2024-01-19 16:18:01 +00:00
|
|
|
Future<void> connectOrDisconnectNodeToProxy({required bool connect}) async {
|
|
|
|
final appStore = getIt.get<AppStore>();
|
|
|
|
if (appStore.wallet != null) {
|
|
|
|
final node = _settingsStore.getCurrentNode(appStore.wallet!.type);
|
|
|
|
if (connect && (node.socksProxyAddress?.isEmpty ?? true)) {
|
|
|
|
node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}";
|
|
|
|
} else if (!connect) {
|
|
|
|
node.socksProxyAddress = null;
|
|
|
|
}
|
2024-01-24 17:39:13 +00:00
|
|
|
|
|
|
|
bool torOnly = _settingsStore.torConnectionMode == TorConnectionMode.torOnly;
|
|
|
|
if ([WalletType.bitcoin, WalletType.litecoin].contains(appStore.wallet!.type)) {
|
|
|
|
bitcoin!.setTorOnly(appStore.wallet!, torOnly);
|
|
|
|
}
|
|
|
|
|
2024-01-19 16:18:01 +00:00
|
|
|
await appStore.wallet!.connectToNode(node: node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-04 20:08:27 +00:00
|
|
|
@action
|
|
|
|
Future<void> startTor() async {
|
|
|
|
try {
|
|
|
|
torConnectionStatus = TorConnectionStatus.connecting;
|
2024-01-12 19:53:19 +00:00
|
|
|
|
2024-01-04 20:08:27 +00:00
|
|
|
await Tor.init();
|
2024-01-12 19:53:19 +00:00
|
|
|
|
|
|
|
// start only if not already running:
|
|
|
|
if (Tor.instance.port == -1) {
|
|
|
|
await Tor.instance.enable();
|
|
|
|
}
|
2024-01-04 18:43:11 +00:00
|
|
|
|
2024-01-04 20:08:27 +00:00
|
|
|
_settingsStore.shouldStartTorOnLaunch = true;
|
|
|
|
|
|
|
|
torConnectionStatus = TorConnectionStatus.connected;
|
2024-01-04 18:43:11 +00:00
|
|
|
|
2024-01-12 19:53:19 +00:00
|
|
|
SocksTCPClient.setProxy(proxies: [
|
|
|
|
ProxySettings(
|
|
|
|
InternetAddress.loopbackIPv4,
|
|
|
|
Tor.instance.port,
|
|
|
|
password: null,
|
|
|
|
),
|
|
|
|
]);
|
|
|
|
|
2024-01-04 20:08:27 +00:00
|
|
|
// connect to node through the proxy:
|
2024-01-19 16:18:01 +00:00
|
|
|
await connectOrDisconnectNodeToProxy(connect: true);
|
2024-01-04 20:08:27 +00:00
|
|
|
} catch (e) {
|
|
|
|
torConnectionStatus = TorConnectionStatus.disconnected;
|
2024-01-04 18:43:11 +00:00
|
|
|
}
|
2024-01-04 20:08:27 +00:00
|
|
|
}
|
2024-01-04 18:43:11 +00:00
|
|
|
|
2024-01-04 20:08:27 +00:00
|
|
|
@action
|
|
|
|
Future<void> stopTor() async {
|
2024-01-19 16:18:01 +00:00
|
|
|
// Tor.instance.disable();// removed because we don't want to have to start tor again
|
|
|
|
// setting the torConnectionMode to disabled will prevent anything from actually using the proxy
|
2024-01-04 20:08:27 +00:00
|
|
|
_settingsStore.shouldStartTorOnLaunch = false;
|
|
|
|
torConnectionStatus = TorConnectionStatus.disconnected;
|
2024-01-19 16:18:01 +00:00
|
|
|
await connectOrDisconnectNodeToProxy(connect: false);
|
2024-01-16 16:23:34 +00:00
|
|
|
SocksTCPClient.removeProxy();
|
2024-01-04 18:43:11 +00:00
|
|
|
}
|
2023-12-20 01:20:21 +00:00
|
|
|
}
|