CakeWallet/lib/reactions/on_current_wallet_change.dart
cyan 5082dc20f3
CW-519 Enable built-in Tor (#1950)
* tor wip

* Enable tor on iOS

* Prevent app lag when node is exceptionally slow (usually over tor)

* fix: logic in daemonBlockchainHeight refresh
fix: storing tor state

* Pin ledger_flutter_plus dependency to fix builds

* bump arti version

* wip

* add single httpclient

* route everything I was able to catch trough the built-in tor node

* Enable proxy for http.Client [run tests]

* add tor proxy support to cw_evm, cw_tron and cw_polygon [run tests]

* remove log pollution, cleanup [skip slack]

* fix tests not working in latest main [skip slack] [run tests]

* remove cw_wownero import

* fix build issues

* migrate all remaining calls to use ProxyWrapper
add a CI action to enforce using ProxyWrapper instead of http/http.dart to prevent leaks

* fix tor background sync (will work on test builds after #2142 is merged and this PR is rebased on top)

* wip [skip ci]

* relicense to GPLv3 add socks5 license, build fixes

* use ProxyWrapper instead of http in robinhood

* Revert "relicense to GPLv3"

* feat(cw_bitcoin): support socks proxy and CakeTor

* fix(tor): migrate OCP and EVM over to ProxyWrapper()

* chore: cleanup
fix: show tor loading screen when app is starting

* fix: tor switch properly dismisses fullscreen loading dialog
fix: connectToNode after tor startup on app start

* fix(tor): status check for xmr/wow/zano

* fix(tor): onramper request fix

* fix(api): ServicesResponse is now being cached and doesn't fetch data everytime DashboardViewModel is being rebuilt
fix(tor): do not fallback to clearnet when tor failed.
fix(tor): do not leak connections during app startup
chore: refactor bootstrap() function to be separated into bootstrapOffline and bootstrapOnline
fix(cw_bitcoin): migrate payjoin to use ProxyWrapper

* [skip ci] remove print

* address comments from review

* fix: derusting tor implementation

Instead of rust-based Arti I've moved back to the
OG C++ tor implementation.
This fixed all issues we had with Tor.
- onion services now work
- all requests are going through without random errors
- we don't have to navigate a maze of multiple forks of multiple packages
- fully working `torrc` config file (probably will be needed for Tari).
- logging for Tor client
- and so on.

feat: network logging tab
feat: use built-in proxy on Tails - this should resolve all issues for Tails users (needs testing though)

* fix conflicts with main
bump https to fix build issue
relax store() call

* fix(cw_wownero): tor connection
fix(tor): connection issues

* fix(cw_evm): add missing chainId
fix(cw_core): solana rpc fix

* feat: mark tor as experimental
fix: drop anonpay onion authority
fix: drop fiatapi onion authority
fix: drop trocador onion authority
fix: disable networkimage when tor is enabled
fix: handle cakepay errors gracefully

* fix re-formatting [skip ci]

* changes from review

* Delete android/.kotlin/sessions/kotlin-compiler-2468481326039681181.salive

* fix missing imports

* Update pubspec_base.yaml

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
2025-06-20 22:56:18 +03:00

164 lines
6.1 KiB
Dart

import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cake_wallet/entities/wallet_manager.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/solana/solana.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/utils/tor.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/transaction_history.dart';
import 'package:cw_core/balance.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/reactions/check_connection.dart';
import 'package:cake_wallet/reactions/on_wallet_sync_status_change.dart';
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/core/fiat_conversion_service.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_type.dart';
ReactionDisposer? _onCurrentWalletChangeReaction;
ReactionDisposer? _onCurrentWalletChangeFiatRateUpdateReaction;
//ReactionDisposer _onCurrentWalletAddressChangeReaction;
void startCurrentWalletChangeReaction(
AppStore appStore, SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
_onCurrentWalletChangeReaction?.reaction.dispose();
_onCurrentWalletChangeFiatRateUpdateReaction?.reaction.dispose();
//_onCurrentWalletAddressChangeReaction?.reaction?dispose();
//_onCurrentWalletAddressChangeReaction = reaction((_) => appStore.wallet.walletAddresses.address,
//(String address) async {
//if (address == appStore.wallet.walletInfo.yatLastUsedAddress) {
// return;
//}
//try {
// final yatStore = getIt.get<YatStore>();
// await updateEmojiIdAddress(
// appStore.wallet.walletInfo.yatEmojiId,
// appStore.wallet.walletAddresses.address,
// yatStore.apiKey,
// appStore.wallet.type
// );
// appStore.wallet.walletInfo.yatLastUsedAddress = address;
// await appStore.wallet.walletInfo.save();
//} catch (e) {
// printV(e.toString());
//}
//});
_onCurrentWalletChangeReaction = reaction((_) => appStore.wallet,
(WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
wallet) async {
try {
if (wallet == null) {
return;
}
await getIt.get<WalletManager>().ensureGroupHasHashedIdentifier(wallet);
final node = settingsStore.getCurrentNode(wallet.type);
startWalletSyncStatusChangeReaction(wallet, settingsStore);
startCheckConnectionReaction(wallet, settingsStore);
await Future.delayed(Duration.zero);
if (wallet.type == WalletType.monero ||
wallet.type == WalletType.wownero ||
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoinCash ||
wallet.type == WalletType.decred) {
_setAutoGenerateSubaddressStatus(wallet, settingsStore);
}
if (wallet.type == WalletType.bitcoin) {
bitcoin!.updatePayjoinState(wallet, settingsStore.usePayjoin);
}
if (settingsStore.currentBuiltinTor) {
await ensureTorStarted(context: null);
}
await wallet.connectToNode(node: node);
if (wallet.type == WalletType.nano || wallet.type == WalletType.banano) {
final powNode = settingsStore.getCurrentPowNode(wallet.type);
await wallet.connectToPowNode(node: powNode);
}
if (wallet.walletInfo.address.isEmpty) {
wallet.walletInfo.address = wallet.walletAddresses.address;
if (wallet.walletInfo.isInBox) {
await wallet.walletInfo.save();
}
}
} catch (e) {
printV(e.toString());
}
});
_onCurrentWalletChangeFiatRateUpdateReaction = reaction((_) => appStore.wallet,
(WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
wallet) async {
try {
if (wallet == null || settingsStore.fiatApiMode == FiatApiMode.disabled) {
return;
}
fiatConversionStore.prices[wallet.currency] = 0;
fiatConversionStore.prices[wallet.currency] = await FiatConversionService.fetchPrice(
crypto: wallet.currency,
fiat: settingsStore.fiatCurrency,
torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly);
Iterable<CryptoCurrency>? currencies;
if (wallet.type == WalletType.ethereum) {
currencies =
ethereum!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled);
}
if (wallet.type == WalletType.polygon) {
currencies =
polygon!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled);
}
if (wallet.type == WalletType.solana) {
currencies =
solana!.getSPLTokenCurrencies(appStore.wallet!).where((element) => element.enabled);
}
if (wallet.type == WalletType.tron) {
currencies =
tron!.getTronTokenCurrencies(appStore.wallet!).where((element) => element.enabled);
}
if (currencies != null) {
for (final currency in currencies) {
() async {
fiatConversionStore.prices[currency] = await FiatConversionService.fetchPrice(
crypto: currency,
fiat: settingsStore.fiatCurrency,
torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly);
}.call();
}
}
} catch (e) {
printV(e.toString());
}
});
}
void _setAutoGenerateSubaddressStatus(
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet,
SettingsStore settingsStore,
) async {
wallet.isEnabledAutoGenerateSubaddress =
settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.enabled ||
settingsStore.autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.initialized;
}