Skip to content

Commit 74cd70d

Browse files
committed
feat(joinstr): route relay and electrum over the app Tor when available
Signed-off-by: Kyle 🐆 <kyle@privkey.io>
1 parent 85b60eb commit 74cd70d

2 files changed

Lines changed: 21 additions & 2 deletions

File tree

lib/features/joinstr/data/joinstr_datasource.dart

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:bb_mobile/core/tor/domain/ports/tor_config_port.dart';
12
import 'package:bb_mobile/core/wallet/domain/entities/wallet.dart';
23
import 'package:bb_mobile/features/joinstr/domain/joinstr.dart';
34
import 'package:joinstr_flutter/joinstr_flutter.dart' as jns;
@@ -6,7 +7,19 @@ import 'package:joinstr_flutter/joinstr_flutter.dart' as jns;
67
/// and domain entities; the `Ffi*` types and the BTC-denominated pool config
78
/// do not escape it.
89
class JoinstrDatasource {
9-
const JoinstrDatasource();
10+
final TorConfigPort _torConfig;
11+
12+
const JoinstrDatasource(this._torConfig);
13+
14+
/// The app's local SOCKS5 proxy (`host:port`) when Tor is available, so every
15+
/// relay and electrum connection the bindings make routes over Tor and the
16+
/// participating IP is not exposed alongside the coin being mixed. Returns
17+
/// null when Tor is not running, which the bindings treat as a direct
18+
/// connection, keeping the flow usable without Tor.
19+
Future<String?> _proxy() async {
20+
final config = await _torConfig.getAvailableExternalTorConfig();
21+
return config == null ? null : '127.0.0.1:${config.port}';
22+
}
1023

1124
/// Runs an FFI call, translating the binding's `JoinstrError` into a domain
1225
/// [JoinstrException] that carries its real message. Without this the error
@@ -24,11 +37,13 @@ class JoinstrDatasource {
2437
required Duration back,
2538
required Duration wait,
2639
}) async {
40+
final proxy = await _proxy();
2741
final pools = await _call(
2842
() => jns.listPools(
2943
back: BigInt.from(back.inSeconds),
3044
timeout: BigInt.from(wait.inMicroseconds),
3145
relay: relay,
46+
proxy: proxy,
3247
),
3348
);
3449

@@ -116,6 +131,7 @@ class JoinstrDatasource {
116131
}) async {
117132
final endpoint = Joinstr.parseElectrumUrl(electrumUrl);
118133
final network = _network(wallet.network);
134+
final proxy = await _proxy();
119135

120136
final coins = await jns.listCoins(
121137
mnemonic: mnemonic,
@@ -124,6 +140,7 @@ class JoinstrDatasource {
124140
rangeStart: 0,
125141
rangeEnd: Joinstr.scanDepth,
126142
network: network,
143+
proxy: proxy,
127144
);
128145

129146
// The window is enforced by every other peer only *after* we broadcast a
@@ -148,6 +165,7 @@ class JoinstrDatasource {
148165
outputAddress: outputAddress,
149166
relay: relay,
150167
network: network,
168+
proxy: proxy,
151169
);
152170
}
153171

lib/features/joinstr/joinstr_locator.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:bb_mobile/core/electrum/domain/repositories/electrum_server_repository.dart';
22
import 'package:bb_mobile/core/seed/data/repository/seed_repository.dart';
33
import 'package:bb_mobile/core/storage/data/datasources/key_value_storage/key_value_storage_datasource.dart';
4+
import 'package:bb_mobile/core/tor/domain/ports/tor_config_port.dart';
45
import 'package:bb_mobile/core/utils/constants.dart';
56
import 'package:bb_mobile/core/wallet/domain/usecases/get_receive_address_usecase.dart';
67
import 'package:bb_mobile/core/wallet/domain/usecases/get_wallets_usecase.dart';
@@ -18,7 +19,7 @@ import 'package:get_it/get_it.dart';
1819
class JoinstrLocator {
1920
static void setup(GetIt locator) {
2021
locator.registerLazySingleton<JoinstrDatasource>(
21-
() => const JoinstrDatasource(),
22+
() => JoinstrDatasource(locator<TorConfigPort>()),
2223
);
2324
locator.registerLazySingleton<JoinstrStore>(
2425
() => JoinstrStore(

0 commit comments

Comments
 (0)