mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-31 19:39:06 +00:00
Merge pull request #833 from cypherstack/tor
Add Tor warning dialog and Network DevTools documentation for checking Tor usage outside of app
This commit is contained in:
commit
a2f74ced8a
26 changed files with 394 additions and 13 deletions
docs
lib
pages
settings_views/global_settings_view
wallets_view/sub_widgets
pages_desktop_specific/my_stack_view
supported_coins.dartwallets/crypto_currency
coins
banano.dartbitcoin.dartbitcoin_frost.dartbitcoincash.dartdogecoin.dartecash.dartepiccash.dartethereum.dartfiro.dartlitecoin.dartmonero.dartnamecoin.dartnano.dartparticl.dartstellar.darttezos.dartwownero.dart
crypto_currency.dartwidgets
|
@ -198,3 +198,11 @@ Run the following commands:
|
|||
flutter pub get
|
||||
flutter run -d windows
|
||||
```
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
Run with `-v` or `--verbose` to see a more detailed error. Certain exceptions (like missing a plugin library) may not report quality errors without `verbose`, especially on Windows.
|
||||
|
||||
## Tor
|
||||
|
||||
To test Tor usage, run Stack Wallet from Android Studio. Click the Flutter DevTools icon in the Run tab (next to the Hot Reload and Hot Restart buttons) and navigate to the Network tab. Connections using Tor will show as `GET InternetAddress('127.0.0.1', IPv4) 101 ws`. Connections outside of Tor will show the destination address directly.
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
@ -20,9 +19,11 @@ import 'package:stackwallet/providers/providers.dart';
|
|||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/dialogs/tor_warning_dialog.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
class HiddenSettings extends StatelessWidget {
|
||||
|
@ -246,24 +247,23 @@ class HiddenSettings extends StatelessWidget {
|
|||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Consumer(
|
||||
builder: (_, ref, __) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
ref
|
||||
.read(prefsChangeNotifierProvider)
|
||||
.frostEnabled =
|
||||
!(ref
|
||||
.read(prefsChangeNotifierProvider)
|
||||
.frostEnabled);
|
||||
if (kDebugMode) {
|
||||
print(
|
||||
"FROST enabled: ${ref.read(prefsChangeNotifierProvider).frostEnabled}");
|
||||
}
|
||||
await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (_) => TorWarningDialog(
|
||||
coin: Coin.stellar,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: RoundedWhiteContainer(
|
||||
child: Text(
|
||||
"Toggle FROST multisig",
|
||||
"Show Tor warning popup",
|
||||
style: STextStyles.button(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
|
|
|
@ -17,6 +17,7 @@ import 'package:flutter_svg/svg.dart';
|
|||
import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
|
||||
import 'package:stackwallet/pages/wallets_view/wallets_overview.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/supported_coins.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
|
@ -26,6 +27,7 @@ import 'package:stackwallet/utilities/show_loading.dart';
|
|||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
|
||||
import 'package:stackwallet/widgets/dialogs/tor_warning_dialog.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
class WalletListItem extends ConsumerWidget {
|
||||
|
@ -58,6 +60,25 @@ class WalletListItem extends ConsumerWidget {
|
|||
BorderRadius.circular(Constants.size.circularBorderRadius),
|
||||
),
|
||||
onPressed: () async {
|
||||
// Check if Tor is enabled...
|
||||
if (ref.read(prefsChangeNotifierProvider).useTor) {
|
||||
// ... and if the coin supports Tor.
|
||||
final cryptocurrency = SupportedCoins.coins[coin];
|
||||
if (cryptocurrency != null && !cryptocurrency!.torSupport) {
|
||||
// If not, show a Tor warning dialog.
|
||||
final shouldContinue = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (_) => TorWarningDialog(
|
||||
coin: coin,
|
||||
),
|
||||
) ??
|
||||
false;
|
||||
if (!shouldContinue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (walletCount == 1 && coin != Coin.ethereum) {
|
||||
final wallet = ref
|
||||
.read(pWallets)
|
||||
|
|
|
@ -15,6 +15,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/pages/wallets_view/wallets_overview.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/supported_coins.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
|
@ -24,6 +25,7 @@ import 'package:stackwallet/wallets/isar/providers/all_wallets_info_provider.dar
|
|||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||
import 'package:stackwallet/widgets/dialogs/tor_warning_dialog.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
class WalletSummaryTable extends ConsumerStatefulWidget {
|
||||
|
@ -85,7 +87,26 @@ class _DesktopWalletSummaryRowState
|
|||
extends ConsumerState<DesktopWalletSummaryRow> {
|
||||
bool _hovering = false;
|
||||
|
||||
void _onPressed() {
|
||||
void _onPressed() async {
|
||||
// Check if Tor is enabled...
|
||||
if (ref.read(prefsChangeNotifierProvider).useTor) {
|
||||
// ... and if the coin supports Tor.
|
||||
final cryptocurrency = SupportedCoins.coins[widget.coin];
|
||||
if (cryptocurrency != null && !cryptocurrency!.torSupport) {
|
||||
// If not, show a Tor warning dialog.
|
||||
final shouldContinue = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (_) => TorWarningDialog(
|
||||
coin: widget.coin,
|
||||
),
|
||||
) ??
|
||||
false;
|
||||
if (!shouldContinue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (_) => DesktopDialog(
|
||||
|
|
78
lib/supported_coins.dart
Normal file
78
lib/supported_coins.dart
Normal file
|
@ -0,0 +1,78 @@
|
|||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/banano.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoin.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoin_frost.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoincash.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/dogecoin.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/ecash.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/epiccash.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/ethereum.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/litecoin.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/monero.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/namecoin.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/nano.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/particl.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/stellar.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/tezos.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/wownero.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
|
||||
|
||||
/// The supported coins.
|
||||
class SupportedCoins {
|
||||
/// A List of our supported coins.
|
||||
static final List<CryptoCurrency> cryptocurrencies = [
|
||||
// Mainnet coins.
|
||||
Bitcoin(CryptoCurrencyNetwork.main),
|
||||
Monero(CryptoCurrencyNetwork.main),
|
||||
Banano(CryptoCurrencyNetwork.main),
|
||||
Bitcoincash(CryptoCurrencyNetwork.main),
|
||||
BitcoinFrost(CryptoCurrencyNetwork.main),
|
||||
Dogecoin(CryptoCurrencyNetwork.main),
|
||||
Ecash(CryptoCurrencyNetwork.main),
|
||||
Epiccash(CryptoCurrencyNetwork.main),
|
||||
Ethereum(CryptoCurrencyNetwork.main),
|
||||
Firo(CryptoCurrencyNetwork.main),
|
||||
Litecoin(CryptoCurrencyNetwork.main),
|
||||
Namecoin(CryptoCurrencyNetwork.main),
|
||||
Nano(CryptoCurrencyNetwork.main),
|
||||
Particl(CryptoCurrencyNetwork.main),
|
||||
Stellar(CryptoCurrencyNetwork.main),
|
||||
Tezos(CryptoCurrencyNetwork.main),
|
||||
Wownero(CryptoCurrencyNetwork.main),
|
||||
|
||||
/// Testnet coins.
|
||||
Bitcoin(CryptoCurrencyNetwork.test),
|
||||
Banano(CryptoCurrencyNetwork.test),
|
||||
Bitcoincash(CryptoCurrencyNetwork.test),
|
||||
BitcoinFrost(CryptoCurrencyNetwork.test),
|
||||
Dogecoin(CryptoCurrencyNetwork.test),
|
||||
Stellar(CryptoCurrencyNetwork.test),
|
||||
Firo(CryptoCurrencyNetwork.test),
|
||||
Litecoin(CryptoCurrencyNetwork.test),
|
||||
Stellar(CryptoCurrencyNetwork.test),
|
||||
];
|
||||
|
||||
/// A Map linking a CryptoCurrency with its associated Coin.
|
||||
///
|
||||
/// Temporary: Remove when the Coin enum is removed.
|
||||
static final Map<Coin, CryptoCurrency> coins = {
|
||||
Coin.bitcoin: Bitcoin(CryptoCurrencyNetwork.main),
|
||||
Coin.monero: Monero(CryptoCurrencyNetwork.main),
|
||||
Coin.banano: Banano(CryptoCurrencyNetwork.main),
|
||||
Coin.bitcoincash: Bitcoincash(CryptoCurrencyNetwork.main),
|
||||
Coin.bitcoinFrost: BitcoinFrost(CryptoCurrencyNetwork.main),
|
||||
Coin.dogecoin: Dogecoin(CryptoCurrencyNetwork.main),
|
||||
Coin.eCash: Ecash(CryptoCurrencyNetwork.main),
|
||||
Coin.epicCash: Epiccash(CryptoCurrencyNetwork.main),
|
||||
Coin.ethereum: Ethereum(CryptoCurrencyNetwork.main),
|
||||
Coin.firo: Firo(CryptoCurrencyNetwork.main),
|
||||
Coin.litecoin: Litecoin(CryptoCurrencyNetwork.main),
|
||||
Coin.namecoin: Namecoin(CryptoCurrencyNetwork.main),
|
||||
Coin.nano: Nano(CryptoCurrencyNetwork.main),
|
||||
Coin.particl: Particl(CryptoCurrencyNetwork.main),
|
||||
Coin.stellar: Stellar(CryptoCurrencyNetwork.main),
|
||||
Coin.tezos: Tezos(CryptoCurrencyNetwork.main),
|
||||
Coin.wownero: Wownero(CryptoCurrencyNetwork.main),
|
||||
};
|
||||
}
|
|
@ -45,4 +45,12 @@ class Banano extends NanoCurrency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Banano && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Banano, network);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@ class Bitcoin extends Bip39HDCurrency with PaynymCurrencyInterface {
|
|||
// change this to change the number of confirms a tx needs in order to show as confirmed
|
||||
int get minConfirms => 1;
|
||||
|
||||
@override
|
||||
bool get torSupport => true;
|
||||
|
||||
@override
|
||||
List<DerivePathType> get supportedDerivationPathTypes => [
|
||||
DerivePathType.bip44,
|
||||
|
@ -200,4 +203,12 @@ class Bitcoin extends Bip39HDCurrency with PaynymCurrencyInterface {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Bitcoin && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Bitcoin, network);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ class BitcoinFrost extends FrostCurrency {
|
|||
@override
|
||||
int get minConfirms => 1;
|
||||
|
||||
@override
|
||||
bool get torSupport => true;
|
||||
|
||||
@override
|
||||
NodeModel get defaultNode {
|
||||
switch (network) {
|
||||
|
@ -69,4 +72,12 @@ class BitcoinFrost extends FrostCurrency {
|
|||
// TODO: implement validateAddress for frost addresses
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is BitcoinFrost && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(BitcoinFrost, network);
|
||||
}
|
||||
|
|
|
@ -34,6 +34,9 @@ class Bitcoincash extends Bip39HDCurrency {
|
|||
// change this to change the number of confirms a tx needs in order to show as confirmed
|
||||
int get minConfirms => 0; // bch zeroconf
|
||||
|
||||
@override
|
||||
bool get torSupport => true;
|
||||
|
||||
@override
|
||||
List<DerivePathType> get supportedDerivationPathTypes => [
|
||||
DerivePathType.bip44,
|
||||
|
@ -286,4 +289,12 @@ class Bitcoincash extends Bip39HDCurrency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Bitcoincash && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Bitcoincash, network);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ class Dogecoin extends Bip39HDCurrency {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool get torSupport => true;
|
||||
|
||||
@override
|
||||
List<DerivePathType> get supportedDerivationPathTypes => [
|
||||
DerivePathType.bip44,
|
||||
|
@ -178,4 +181,12 @@ class Dogecoin extends Bip39HDCurrency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Dogecoin && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Dogecoin, network);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,9 @@ class Ecash extends Bip39HDCurrency {
|
|||
// change this to change the number of confirms a tx needs in order to show as confirmed
|
||||
int get minConfirms => 0; // bch zeroconf
|
||||
|
||||
@override
|
||||
bool get torSupport => true;
|
||||
|
||||
@override
|
||||
List<DerivePathType> get supportedDerivationPathTypes => [
|
||||
DerivePathType.eCash44,
|
||||
|
@ -266,4 +269,12 @@ class Ecash extends Bip39HDCurrency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Ecash && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Ecash, network);
|
||||
}
|
||||
|
|
|
@ -61,4 +61,12 @@ class Epiccash extends Bip39Currency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Epiccash && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Epiccash, network);
|
||||
}
|
||||
|
|
|
@ -34,4 +34,12 @@ class Ethereum extends Bip39Currency {
|
|||
bool validateAddress(String address) {
|
||||
return isValidEthereumAddress(address);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Ethereum && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Ethereum, network);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@ class Firo extends Bip39HDCurrency {
|
|||
@override
|
||||
int get minConfirms => 1;
|
||||
|
||||
@override
|
||||
bool get torSupport => true;
|
||||
|
||||
@override
|
||||
List<DerivePathType> get supportedDerivationPathTypes => [
|
||||
DerivePathType.bip44,
|
||||
|
@ -196,4 +199,12 @@ class Firo extends Bip39HDCurrency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Firo && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Firo, network);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@ class Litecoin extends Bip39HDCurrency {
|
|||
// change this to change the number of confirms a tx needs in order to show as confirmed
|
||||
int get minConfirms => 1;
|
||||
|
||||
@override
|
||||
bool get torSupport => true;
|
||||
|
||||
@override
|
||||
List<DerivePathType> get supportedDerivationPathTypes => [
|
||||
DerivePathType.bip44,
|
||||
|
@ -209,4 +212,12 @@ class Litecoin extends Bip39HDCurrency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Litecoin && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Litecoin, network);
|
||||
}
|
||||
|
|
|
@ -44,4 +44,12 @@ class Monero extends CryptonoteCurrency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Monero && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Monero, network);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ class Namecoin extends Bip39HDCurrency {
|
|||
// See https://github.com/cypherstack/stack_wallet/blob/621aff47969761014e0a6c4e699cb637d5687ab3/lib/services/coins/namecoin/namecoin_wallet.dart#L58
|
||||
int get minConfirms => 2;
|
||||
|
||||
@override
|
||||
bool get torSupport => true;
|
||||
|
||||
@override
|
||||
// See https://github.com/cypherstack/stack_wallet/blob/621aff47969761014e0a6c4e699cb637d5687ab3/lib/services/coins/namecoin/namecoin_wallet.dart#L80
|
||||
String constructDerivePath({
|
||||
|
@ -182,4 +185,12 @@ class Namecoin extends Bip39HDCurrency {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Namecoin && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Namecoin, network);
|
||||
}
|
||||
|
|
|
@ -45,4 +45,12 @@ class Nano extends NanoCurrency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Nano && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Nano, network);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ class Particl extends Bip39HDCurrency {
|
|||
// See https://github.com/cypherstack/stack_wallet/blob/d08b5c9b22b58db800ad07b2ceeb44c6d05f9cf3/lib/services/coins/particl/particl_wallet.dart#L57
|
||||
int get minConfirms => 1;
|
||||
|
||||
@override
|
||||
bool get torSupport => true;
|
||||
|
||||
@override
|
||||
// See https://github.com/cypherstack/stack_wallet/blob/d08b5c9b22b58db800ad07b2ceeb44c6d05f9cf3/lib/services/coins/particl/particl_wallet.dart#L68
|
||||
String constructDerivePath(
|
||||
|
@ -162,4 +165,12 @@ class Particl extends Bip39HDCurrency {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Particl && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Particl, network);
|
||||
}
|
||||
|
|
|
@ -39,4 +39,12 @@ class Stellar extends Bip39Currency {
|
|||
@override
|
||||
bool validateAddress(String address) =>
|
||||
RegExp(r"^[G][A-Z0-9]{55}$").hasMatch(address);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Stellar && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Stellar, network);
|
||||
}
|
||||
|
|
|
@ -146,4 +146,12 @@ class Tezos extends Bip39Currency {
|
|||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Tezos && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Tezos, network);
|
||||
}
|
||||
|
|
|
@ -44,4 +44,12 @@ class Wownero extends CryptonoteCurrency {
|
|||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is Wownero && other.network == network;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(Wownero, network);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ abstract class CryptoCurrency {
|
|||
// (used for eth currently)
|
||||
bool get hasTokenSupport => false;
|
||||
|
||||
// Override in subclass if the currency has Tor support:
|
||||
bool get torSupport => false;
|
||||
|
||||
// TODO: [prio=low] require these be overridden in concrete implementations to remove reliance on [coin]
|
||||
int get fractionDigits => coin.decimals;
|
||||
BigInt get satsPerCoin => Constants.satsPerCoin(coin);
|
||||
|
|
|
@ -26,6 +26,7 @@ class BasicDialog extends StatelessWidget {
|
|||
this.desktopHeight = 474,
|
||||
this.desktopWidth = 641,
|
||||
this.canPopWithBackButton = false,
|
||||
this.flex = false,
|
||||
}) : super(key: key);
|
||||
|
||||
final Widget? leftButton;
|
||||
|
@ -41,6 +42,8 @@ class BasicDialog extends StatelessWidget {
|
|||
|
||||
final bool canPopWithBackButton;
|
||||
|
||||
final bool flex;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isDesktop = Util.isDesktop;
|
||||
|
@ -64,6 +67,10 @@ class BasicDialog extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
if (flex)
|
||||
const Spacer(
|
||||
flex: 2,
|
||||
),
|
||||
if (message != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
|
@ -72,6 +79,10 @@ class BasicDialog extends StatelessWidget {
|
|||
style: STextStyles.desktopTextSmall(context),
|
||||
),
|
||||
),
|
||||
if (flex)
|
||||
const Spacer(
|
||||
flex: 3,
|
||||
),
|
||||
if (leftButton != null || rightButton != null)
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
|
|
44
lib/widgets/dialogs/tor_warning_dialog.dart
Normal file
44
lib/widgets/dialogs/tor_warning_dialog.dart
Normal file
|
@ -0,0 +1,44 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||
import 'package:stackwallet/widgets/dialogs/basic_dialog.dart';
|
||||
|
||||
class TorWarningDialog extends StatelessWidget {
|
||||
final Coin coin;
|
||||
final VoidCallback? onContinue;
|
||||
final VoidCallback? onCancel;
|
||||
|
||||
TorWarningDialog({
|
||||
Key? key,
|
||||
required this.coin,
|
||||
this.onContinue,
|
||||
this.onCancel,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BasicDialog(
|
||||
title: "Warning! Tor not supported.",
|
||||
message: "${coin.prettyName} is not compatible with Tor. "
|
||||
"Continuing will leak your IP address."
|
||||
"\n\nAre you sure you want to continue?",
|
||||
// A PrimaryButton widget:
|
||||
leftButton: PrimaryButton(
|
||||
label: "Cancel",
|
||||
onPressed: () {
|
||||
onCancel?.call();
|
||||
Navigator.of(context).pop(false);
|
||||
},
|
||||
),
|
||||
rightButton: SecondaryButton(
|
||||
label: "Continue",
|
||||
onPressed: () {
|
||||
onContinue?.call();
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
),
|
||||
flex: true,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ import 'package:stackwallet/wallets/wallet/wallet.dart';
|
|||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
|
||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||
import 'package:stackwallet/widgets/dialogs/basic_dialog.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
import 'package:stackwallet/widgets/wallet_info_row/wallet_info_row.dart';
|
||||
|
@ -94,6 +95,37 @@ class SimpleWalletCard extends ConsumerWidget {
|
|||
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
|
||||
// If Tor enabled, show a warning if opening a wallet incompatible with Tor.
|
||||
if (ref.read(prefsChangeNotifierProvider).useTor) {
|
||||
if (!wallet.cryptoCurrency.torSupport) {
|
||||
final shouldContinue = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => BasicDialog(
|
||||
title: "Warning! Tor not supported.",
|
||||
message: "Stacky is not compatible with Tor."
|
||||
"\n\nBy using it, you will leak your IP address. Are you sure you "
|
||||
"want to continue?",
|
||||
// A PrimaryButton widget:
|
||||
leftButton: PrimaryButton(
|
||||
label: "Cancel",
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(false);
|
||||
},
|
||||
),
|
||||
rightButton: SecondaryButton(
|
||||
label: "Continue",
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
),
|
||||
)) ??
|
||||
false;
|
||||
if (!shouldContinue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context.mounted) {
|
||||
final Future<void> loadFuture;
|
||||
if (wallet is CwBasedInterface) {
|
||||
|
|
Loading…
Reference in a new issue