Merge pull request #868 from cypherstack/appConfig_julian

remove coin enum
This commit is contained in:
julian-CStack 2024-05-15 16:00:10 -06:00 committed by GitHub
commit 2019f95c72
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
272 changed files with 7865 additions and 7195 deletions

View file

@ -26,13 +26,14 @@ import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets_service.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoincash.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/epiccash.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:tuple/tuple.dart';
@ -59,14 +60,16 @@ class DbVersionMigrator with WalletDB {
ElectrumXClient? client;
int? latestSetId;
final firo = Firo(CryptoCurrencyNetwork.main);
// only instantiate client if there are firo wallets
if (walletInfoList.values.any((element) => element.coin == Coin.firo)) {
if (walletInfoList.values
.any((element) => element.coinIdentifier == firo.identifier)) {
await Hive.openBox<NodeModel>(DB.boxNameNodeModels);
await Hive.openBox<NodeModel>(DB.boxNamePrimaryNodes);
final node = nodeService.getPrimaryNodeFor(coin: Coin.firo) ??
DefaultNodes.firo;
List<ElectrumXNode> failovers = nodeService
.failoverNodesFor(coin: Coin.firo)
final node =
nodeService.getPrimaryNodeFor(currency: firo) ?? firo.defaultNode;
final List<ElectrumXNode> failovers = nodeService
.failoverNodesFor(currency: firo)
.map(
(e) => ElectrumXNode(
address: e.host,
@ -80,11 +83,12 @@ class DbVersionMigrator with WalletDB {
client = ElectrumXClient.from(
node: ElectrumXNode(
address: node.host,
port: node.port,
name: node.name,
id: node.id,
useSSL: node.useSSL),
address: node.host,
port: node.port,
name: node.name,
id: node.id,
useSSL: node.useSSL,
),
prefs: prefs,
failovers: failovers,
cryptoCurrency: Firo(CryptoCurrencyNetwork.main),
@ -96,26 +100,29 @@ class DbVersionMigrator with WalletDB {
// default to 2 for now
latestSetId = 2;
Logging.instance.log(
"Failed to fetch latest coin id during firo db migrate: $e \nUsing a default value of 2",
level: LogLevel.Warning);
"Failed to fetch latest coin id during firo db migrate: $e \nUsing a default value of 2",
level: LogLevel.Warning,
);
}
}
for (final walletInfo in walletInfoList.values) {
// migrate each firo wallet's lelantus coins
if (walletInfo.coin == Coin.firo) {
if (walletInfo.coinIdentifier == firo.identifier) {
await Hive.openBox<dynamic>(walletInfo.walletId);
final _lelantusCoins = DB.instance.get<dynamic>(
boxName: walletInfo.walletId, key: '_lelantus_coins') as List?;
boxName: walletInfo.walletId,
key: '_lelantus_coins',
) as List?;
final List<Map<dynamic, LelantusCoin>> lelantusCoins = [];
for (var lCoin in _lelantusCoins ?? []) {
for (final lCoin in _lelantusCoins ?? []) {
lelantusCoins
.add({lCoin.keys.first: lCoin.values.first as LelantusCoin});
}
List<Map<dynamic, LelantusCoin>> coins = [];
final List<Map<dynamic, LelantusCoin>> coins = [];
for (final element in lelantusCoins) {
LelantusCoin coin = element.values.first;
final LelantusCoin coin = element.values.first;
int anonSetId = coin.anonymitySetId;
if (coin.anonymitySetId == 1 &&
(coin.publicCoin == '' ||
@ -123,21 +130,31 @@ class DbVersionMigrator with WalletDB {
anonSetId = latestSetId!;
}
coins.add({
element.keys.first: LelantusCoin(coin.index, coin.value,
coin.publicCoin, coin.txId, anonSetId, coin.isUsed)
element.keys.first: LelantusCoin(
coin.index,
coin.value,
coin.publicCoin,
coin.txId,
anonSetId,
coin.isUsed,
),
});
}
Logger.print("newcoins $coins", normalLength: false);
await DB.instance.put<dynamic>(
boxName: walletInfo.walletId,
key: '_lelantus_coins',
value: coins);
boxName: walletInfo.walletId,
key: '_lelantus_coins',
value: coins,
);
}
}
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 1);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 1,
);
// try to continue migrating
return await migrate(1, secureStore: secureStore);
@ -161,7 +178,10 @@ class DbVersionMigrator with WalletDB {
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 2);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 2,
);
// try to continue migrating
return await migrate(2, secureStore: secureStore);
@ -176,16 +196,26 @@ class DbVersionMigrator with WalletDB {
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 3);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 3,
);
return await migrate(3, secureStore: secureStore);
case 3:
// clear possible broken firo cache
await DB.instance.clearSharedTransactionCache(coin: Coin.firo);
await DB.instance.clearSharedTransactionCache(
currency: Firo(
CryptoCurrencyNetwork.test,
),
);
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 4);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 4,
);
// try to continue migrating
return await migrate(4, secureStore: secureStore);
@ -196,7 +226,10 @@ class DbVersionMigrator with WalletDB {
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 5);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 5,
);
// try to continue migrating
return await migrate(5, secureStore: secureStore);
@ -212,11 +245,17 @@ class DbVersionMigrator with WalletDB {
"light";
await DB.instance.put<dynamic>(
boxName: DB.boxNamePrefs, key: "theme", value: themeName);
boxName: DB.boxNamePrefs,
key: "theme",
value: themeName,
);
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 6);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 6,
);
// try to continue migrating
return await migrate(6, secureStore: secureStore);
@ -287,7 +326,10 @@ class DbVersionMigrator with WalletDB {
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 7);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 7,
);
// try to continue migrating
return await migrate(7, secureStore: secureStore);
@ -298,7 +340,10 @@ class DbVersionMigrator with WalletDB {
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 8);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 8,
);
// try to continue migrating
return await migrate(8, secureStore: secureStore);
@ -311,8 +356,10 @@ class DbVersionMigrator with WalletDB {
await MainDB.instance.initMainDB();
for (final walletId in walletInfoList.keys) {
final info = walletInfoList[walletId]!;
if (info.coin == Coin.bitcoincash ||
info.coin == Coin.bitcoincashTestnet) {
if (info.coinIdentifier ==
Bitcoincash(CryptoCurrencyNetwork.main).identifier ||
info.coinIdentifier ==
Bitcoincash(CryptoCurrencyNetwork.test).identifier) {
final ids = await MainDB.instance
.getAddresses(walletId)
.filter()
@ -328,7 +375,10 @@ class DbVersionMigrator with WalletDB {
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 9);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 9,
);
// try to continue migrating
return await migrate(9, secureStore: secureStore);
@ -339,7 +389,10 @@ class DbVersionMigrator with WalletDB {
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 10);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 10,
);
// try to continue migrating
return await migrate(10, secureStore: secureStore);
@ -350,7 +403,10 @@ class DbVersionMigrator with WalletDB {
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 11);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 11,
);
// try to continue migrating
return await migrate(11, secureStore: secureStore);
@ -361,7 +417,10 @@ class DbVersionMigrator with WalletDB {
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 12);
boxName: DB.boxNameDBInfo,
key: "hive_data_version",
value: 12,
);
// try to continue migrating
return await migrate(12, secureStore: secureStore);
@ -392,7 +451,8 @@ class DbVersionMigrator with WalletDB {
// we need to manually migrate epic cash transactions as they are not
// stored on the epic cash blockchain
if (info.coin == Coin.epicCash) {
final epic = Epiccash(CryptoCurrencyNetwork.main);
if (info.coinIdentifier == epic.identifier) {
final txnData = walletBox.get("latest_tx_model") as TransactionData?;
// we ever only used index 0 in the past
@ -404,7 +464,7 @@ class DbVersionMigrator with WalletDB {
final txns = txnData.getAllTransactions();
for (final tx in txns.values) {
bool isIncoming = tx.txType == "Received";
final bool isIncoming = tx.txType == "Received";
final iTx = isar_models.Transaction(
walletId: walletId,
@ -417,7 +477,7 @@ class DbVersionMigrator with WalletDB {
amount: tx.amount,
amountString: Amount(
rawValue: BigInt.from(tx.amount),
fractionDigits: info.coin.decimals,
fractionDigits: epic.fractionDigits,
).toJsonString(),
fee: tx.fees,
height: tx.height,
@ -470,12 +530,14 @@ class DbVersionMigrator with WalletDB {
if ((await secureStore.read(key: '${walletId}_mnemonicPassphrase')) ==
null) {
await secureStore.write(
key: '${walletId}_mnemonicPassphrase', value: "");
key: '${walletId}_mnemonicPassphrase',
value: "",
);
}
// doing this for epic cash will delete transaction history as it is not
// stored on the epic cash blockchain
if (info.coin != Coin.epicCash) {
if (info.coinIdentifier != epic.identifier) {
// set flag to initiate full rescan on opening wallet
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo,
@ -498,6 +560,8 @@ class DbVersionMigrator with WalletDB {
final count = await MainDB.instance.getTransactions(walletId).count();
final crypto = SupportedCoins.getCryptoCurrencyFor(info.coinIdentifier);
for (var i = 0; i < count; i += 50) {
final txns = await MainDB.instance
.getTransactions(walletId)
@ -512,7 +576,7 @@ class DbVersionMigrator with WalletDB {
tx
..amountString = Amount(
rawValue: BigInt.from(tx.amount),
fractionDigits: info.coin.decimals,
fractionDigits: crypto.fractionDigits,
).toJsonString(),
tx.address.value,
),
@ -531,11 +595,13 @@ class DbVersionMigrator with WalletDB {
final keys = List<String>.from(addressBookBox.keys);
final contacts = keys
.map((id) => Contact.fromJson(
Map<String, dynamic>.from(
addressBookBox.get(id) as Map,
),
))
.map(
(id) => Contact.fromJson(
Map<String, dynamic>.from(
addressBookBox.get(id) as Map,
),
),
)
.toList(growable: false);
final List<isar_contact.ContactEntry> newContacts = [];
@ -547,7 +613,7 @@ class DbVersionMigrator with WalletDB {
for (final entry in contact.addresses) {
newContactAddressEntries.add(
isar_contact.ContactAddressEntry()
..coinName = entry.coin.name
..coinName = entry.coin.identifier
..address = entry.address
..label = entry.label
..other = entry.other,
@ -580,11 +646,13 @@ class DbVersionMigrator with WalletDB {
await prefs.init();
await MainDB.instance.initMainDB();
final firo = Firo(CryptoCurrencyNetwork.main);
for (final walletId in walletInfoList.keys) {
final info = walletInfoList[walletId]!;
assert(info.walletId == walletId);
if (info.coin == Coin.firo &&
if (info.coinIdentifier == firo.identifier &&
MainDB.instance.isar.lelantusCoins
.where()
.walletIdEqualTo(walletId)

View file

@ -18,8 +18,10 @@ import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/models/notification_model.dart';
import 'package:stackwallet/models/trade_wallet_lookup.dart';
import 'package:stackwallet/services/wallets_service.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class DB {
// legacy (required for migrations)
@ -48,17 +50,18 @@ class DB {
static const String boxNamePrefs = "prefs";
static const String boxNameOneTimeDialogsShown = "oneTimeDialogsShown";
String _boxNameTxCache({required Coin coin}) => "${coin.name}_txCache";
String _boxNameTxCache({required CryptoCurrency currency}) =>
"${currency.identifier}_txCache";
// firo only
String _boxNameSetCache({required Coin coin}) =>
"${coin.name}_anonymitySetCache";
String _boxNameSetSparkCache({required Coin coin}) =>
"${coin.name}_anonymitySetSparkCache";
String _boxNameUsedSerialsCache({required Coin coin}) =>
"${coin.name}_usedSerialsCache";
String _boxNameSparkUsedCoinsTagsCache({required Coin coin}) =>
"${coin.name}_sparkUsedCoinsTagsCache";
String _boxNameSetCache({required CryptoCurrency currency}) =>
"${currency.identifier}_anonymitySetCache";
String _boxNameSetSparkCache({required CryptoCurrency currency}) =>
"${currency.identifier}_anonymitySetSparkCache";
String _boxNameUsedSerialsCache({required CryptoCurrency currency}) =>
"${currency.identifier}_usedSerialsCache";
String _boxNameSparkUsedCoinsTagsCache({required CryptoCurrency currency}) =>
"${currency.identifier}_sparkUsedCoinsTagsCache";
Box<NodeModel>? _boxNodeModels;
Box<NodeModel>? _boxPrimaryNodes;
@ -77,11 +80,11 @@ class DB {
final Map<String, Box<dynamic>> _walletBoxes = {};
final Map<Coin, Box<dynamic>> _txCacheBoxes = {};
final Map<Coin, Box<dynamic>> _setCacheBoxes = {};
final Map<Coin, Box<dynamic>> _setSparkCacheBoxes = {};
final Map<Coin, Box<dynamic>> _usedSerialsCacheBoxes = {};
final Map<Coin, Box<dynamic>> _getSparkUsedCoinsTagsCacheBoxes = {};
final Map<String, Box<dynamic>> _txCacheBoxes = {};
final Map<String, Box<dynamic>> _setCacheBoxes = {};
final Map<String, Box<dynamic>> _setSparkCacheBoxes = {};
final Map<String, Box<dynamic>> _usedSerialsCacheBoxes = {};
final Map<String, Box<dynamic>> _getSparkUsedCoinsTagsCacheBoxes = {};
// exposed for monero
Box<xmr.WalletInfo> get moneroWalletInfoBox => _walletInfoSource!;
@ -97,7 +100,8 @@ class DB {
// TODO: make sure this works properly
if (Isolate.current.debugName != "main") {
throw Exception(
"DB.instance should not be accessed outside the main isolate!");
"DB.instance should not be accessed outside the main isolate!",
);
}
return _instance;
@ -160,17 +164,22 @@ class DB {
names.removeWhere((name, dyn) {
final jsonObject = Map<String, dynamic>.from(dyn as Map);
try {
Coin.values.byName(jsonObject["coin"] as String);
SupportedCoins.getCryptoCurrencyFor(jsonObject["coin"] as String);
return false;
} catch (e, s) {
Logging.instance.log(
"Error, ${jsonObject["coin"]} does not exist, $name wallet cannot be loaded",
level: LogLevel.Error);
"Error, ${jsonObject["coin"]} does not exist, $name wallet cannot be loaded",
level: LogLevel.Error,
);
return true;
}
});
final mapped = Map<String, dynamic>.from(names).map((name, dyn) => MapEntry(
name, WalletInfo.fromJson(Map<String, dynamic>.from(dyn as Map))));
final mapped = Map<String, dynamic>.from(names).map(
(name, dyn) => MapEntry(
name,
WalletInfo.fromJson(Map<String, dynamic>.from(dyn as Map)),
),
);
for (final entry in mapped.entries) {
if (Hive.isBoxOpen(entry.value.walletId)) {
@ -183,70 +192,90 @@ class DB {
}
}
Future<Box<dynamic>> getTxCacheBox({required Coin coin}) async {
if (_txCacheBoxes[coin]?.isOpen != true) {
_txCacheBoxes.remove(coin);
Future<Box<dynamic>> getTxCacheBox({required CryptoCurrency currency}) async {
if (_txCacheBoxes[currency.identifier]?.isOpen != true) {
_txCacheBoxes.remove(currency.identifier);
}
return _txCacheBoxes[coin] ??=
await Hive.openBox<dynamic>(_boxNameTxCache(coin: coin));
return _txCacheBoxes[currency.identifier] ??=
await Hive.openBox<dynamic>(_boxNameTxCache(currency: currency));
}
Future<void> closeTxCacheBox({required Coin coin}) async {
await _txCacheBoxes[coin]?.close();
Future<void> closeTxCacheBox({required CryptoCurrency currency}) async {
await _txCacheBoxes[currency.identifier]?.close();
}
Future<Box<dynamic>> getAnonymitySetCacheBox({required Coin coin}) async {
if (_setCacheBoxes[coin]?.isOpen != true) {
_setCacheBoxes.remove(coin);
Future<Box<dynamic>> getAnonymitySetCacheBox({
required CryptoCurrency currency,
}) async {
if (_setCacheBoxes[currency.identifier]?.isOpen != true) {
_setCacheBoxes.remove(currency.identifier);
}
return _setCacheBoxes[coin] ??=
await Hive.openBox<dynamic>(_boxNameSetCache(coin: coin));
return _setCacheBoxes[currency.identifier] ??=
await Hive.openBox<dynamic>(_boxNameSetCache(currency: currency));
}
Future<Box<dynamic>> getSparkAnonymitySetCacheBox(
{required Coin coin}) async {
if (_setSparkCacheBoxes[coin]?.isOpen != true) {
_setSparkCacheBoxes.remove(coin);
Future<Box<dynamic>> getSparkAnonymitySetCacheBox({
required CryptoCurrency currency,
}) async {
if (_setSparkCacheBoxes[currency.identifier]?.isOpen != true) {
_setSparkCacheBoxes.remove(currency.identifier);
}
return _setSparkCacheBoxes[coin] ??=
await Hive.openBox<dynamic>(_boxNameSetSparkCache(coin: coin));
return _setSparkCacheBoxes[currency.identifier] ??=
await Hive.openBox<dynamic>(_boxNameSetSparkCache(currency: currency));
}
Future<void> closeAnonymitySetCacheBox({required Coin coin}) async {
await _setCacheBoxes[coin]?.close();
Future<void> closeAnonymitySetCacheBox({
required CryptoCurrency currency,
}) async {
await _setCacheBoxes[currency.identifier]?.close();
}
Future<Box<dynamic>> getUsedSerialsCacheBox({required Coin coin}) async {
if (_usedSerialsCacheBoxes[coin]?.isOpen != true) {
_usedSerialsCacheBoxes.remove(coin);
Future<Box<dynamic>> getUsedSerialsCacheBox({
required CryptoCurrency currency,
}) async {
if (_usedSerialsCacheBoxes[currency.identifier]?.isOpen != true) {
_usedSerialsCacheBoxes.remove(currency.identifier);
}
return _usedSerialsCacheBoxes[coin] ??=
await Hive.openBox<dynamic>(_boxNameUsedSerialsCache(coin: coin));
}
Future<Box<dynamic>> getSparkUsedCoinsTagsCacheBox(
{required Coin coin}) async {
if (_getSparkUsedCoinsTagsCacheBoxes[coin]?.isOpen != true) {
_getSparkUsedCoinsTagsCacheBoxes.remove(coin);
}
return _getSparkUsedCoinsTagsCacheBoxes[coin] ??=
return _usedSerialsCacheBoxes[currency.identifier] ??=
await Hive.openBox<dynamic>(
_boxNameSparkUsedCoinsTagsCache(coin: coin));
_boxNameUsedSerialsCache(currency: currency),
);
}
Future<void> closeUsedSerialsCacheBox({required Coin coin}) async {
await _usedSerialsCacheBoxes[coin]?.close();
Future<Box<dynamic>> getSparkUsedCoinsTagsCacheBox({
required CryptoCurrency currency,
}) async {
if (_getSparkUsedCoinsTagsCacheBoxes[currency.identifier]?.isOpen != true) {
_getSparkUsedCoinsTagsCacheBoxes.remove(currency.identifier);
}
return _getSparkUsedCoinsTagsCacheBoxes[currency.identifier] ??=
await Hive.openBox<dynamic>(
_boxNameSparkUsedCoinsTagsCache(currency: currency),
);
}
Future<void> closeUsedSerialsCacheBox({
required CryptoCurrency currency,
}) async {
await _usedSerialsCacheBoxes[currency.identifier]?.close();
}
/// Clear all cached transactions for the specified coin
Future<void> clearSharedTransactionCache({required Coin coin}) async {
await deleteAll<dynamic>(boxName: _boxNameTxCache(coin: coin));
if (coin == Coin.firo || coin == Coin.firoTestNet) {
await deleteAll<dynamic>(boxName: _boxNameSetCache(coin: coin));
await deleteAll<dynamic>(boxName: _boxNameSetSparkCache(coin: coin));
await deleteAll<dynamic>(boxName: _boxNameUsedSerialsCache(coin: coin));
Future<void> clearSharedTransactionCache({
required CryptoCurrency currency,
}) async {
await deleteAll<dynamic>(boxName: _boxNameTxCache(currency: currency));
if (currency is Firo) {
await deleteAll<dynamic>(boxName: _boxNameSetCache(currency: currency));
await deleteAll<dynamic>(
boxName: _boxNameSparkUsedCoinsTagsCache(coin: coin));
boxName: _boxNameSetSparkCache(currency: currency),
);
await deleteAll<dynamic>(
boxName: _boxNameUsedSerialsCache(currency: currency),
);
await deleteAll<dynamic>(
boxName: _boxNameSparkUsedCoinsTagsCache(currency: currency),
);
}
}
@ -284,23 +313,28 @@ class DB {
// writes
Future<void> put<T>(
{required String boxName,
required dynamic key,
required T value}) async =>
Future<void> put<T>({
required String boxName,
required dynamic key,
required T value,
}) async =>
await mutex
.protect(() async => await Hive.box<T>(boxName).put(key, value));
Future<void> add<T>({required String boxName, required T value}) async =>
await mutex.protect(() async => await Hive.box<T>(boxName).add(value));
Future<void> addAll<T>(
{required String boxName, required Iterable<T> values}) async =>
Future<void> addAll<T>({
required String boxName,
required Iterable<T> values,
}) async =>
await mutex
.protect(() async => await Hive.box<T>(boxName).addAll(values));
Future<void> delete<T>(
{required dynamic key, required String boxName}) async =>
Future<void> delete<T>({
required dynamic key,
required String boxName,
}) async =>
await mutex.protect(() async => await Hive.box<T>(boxName).delete(key));
Future<void> deleteAll<T>({required String boxName}) async {

View file

@ -19,8 +19,8 @@ import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/isar/ordinal.dart';
import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/stack_file_system.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/models/frost_wallet_info.dart';
import 'package:stackwallet/wallets/isar/models/spark_coin.dart';
import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart';
@ -149,15 +149,17 @@ class MainDB {
}
// tx block explorers
TransactionBlockExplorer? getTransactionBlockExplorer({required Coin coin}) {
TransactionBlockExplorer? getTransactionBlockExplorer(
{required CryptoCurrency cryptoCurrency}) {
return isar.transactionBlockExplorers
.where()
.tickerEqualTo(coin.ticker)
.tickerEqualTo(cryptoCurrency.ticker)
.findFirstSync();
}
Future<int> putTransactionBlockExplorer(
TransactionBlockExplorer explorer) async {
TransactionBlockExplorer explorer,
) async {
try {
return await isar.writeTxn(() async {
return await isar.transactionBlockExplorers.put(explorer);
@ -169,7 +171,8 @@ class MainDB {
// addresses
QueryBuilder<Address, Address, QAfterWhereClause> getAddresses(
String walletId) =>
String walletId,
) =>
isar.addresses.where().walletIdEqualTo(walletId);
Future<int> putAddress(Address address) async {
@ -194,7 +197,7 @@ class MainDB {
Future<List<int>> updateOrPutAddresses(List<Address> addresses) async {
try {
List<int> ids = [];
final List<int> ids = [];
await isar.writeTxn(() async {
for (final address in addresses) {
final storedAddress = await isar.addresses
@ -239,13 +242,16 @@ class MainDB {
});
} catch (e) {
throw MainDBException(
"failed updateAddress: from=$oldAddress to=$newAddress", e);
"failed updateAddress: from=$oldAddress to=$newAddress",
e,
);
}
}
// transactions
QueryBuilder<Transaction, Transaction, QAfterWhereClause> getTransactions(
String walletId) =>
String walletId,
) =>
isar.transactions.where().walletIdEqualTo(walletId);
Future<int> putTransaction(Transaction transaction) async {
@ -284,7 +290,9 @@ class MainDB {
isar.utxos.where().walletIdEqualTo(walletId);
QueryBuilder<UTXO, UTXO, QAfterFilterCondition> getUTXOsByAddress(
String walletId, String address) =>
String walletId,
String address,
) =>
isar.utxos
.where()
.walletIdEqualTo(walletId)
@ -357,7 +365,9 @@ class MainDB {
});
Future<TransactionNote?> getTransactionNote(
String walletId, String txid) async {
String walletId,
String txid,
) async {
return isar.transactionNotes.getByTxidWalletId(
txid,
walletId,
@ -374,7 +384,8 @@ class MainDB {
// address labels
QueryBuilder<AddressLabel, AddressLabel, QAfterWhereClause> getAddressLabels(
String walletId) =>
String walletId,
) =>
isar.addressLabels.where().walletIdEqualTo(walletId);
Future<int> putAddressLabel(AddressLabel addressLabel) =>
@ -392,7 +403,9 @@ class MainDB {
});
Future<AddressLabel?> getAddressLabel(
String walletId, String addressString) async {
String walletId,
String addressString,
) async {
return isar.addressLabels.getByAddressStringWalletId(
addressString,
walletId,
@ -573,7 +586,7 @@ class MainDB {
List<TransactionV2> transactions,
) async {
try {
List<int> ids = [];
final List<int> ids = [];
await isar.writeTxn(() async {
for (final tx in transactions) {
final storedTx = await isar.transactionV2s
@ -595,7 +608,9 @@ class MainDB {
return ids;
} catch (e) {
throw MainDBException(
"failed updateOrPutTransactionV2s: $transactions", e);
"failed updateOrPutTransactionV2s: $transactions",
e,
);
}
}

View file

@ -6,8 +6,13 @@ import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/epiccash.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.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/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info_meta.dart';
@ -37,13 +42,13 @@ Future<void> migrateWalletsToIsar({
//
final List<
({
Coin coin,
String coinIdentifier,
String name,
String walletId,
})> oldInfo = Map<String, dynamic>.from(names).values.map((e) {
final map = e as Map;
return (
coin: Coin.values.byName(map["coin"] as String),
coinIdentifier: map["coin"] as String,
walletId: map["id"] as String,
name: map["name"] as String,
);
@ -93,16 +98,16 @@ Future<void> migrateWalletsToIsar({
}
// reset stellar + tezos address type
if (old.coin == Coin.stellar ||
old.coin == Coin.stellarTestnet ||
old.coin == Coin.tezos) {
if (old.coinIdentifier == Stellar(CryptoCurrencyNetwork.main).identifier ||
old.coinIdentifier == Stellar(CryptoCurrencyNetwork.test).identifier ||
old.coinIdentifier == Tezos(CryptoCurrencyNetwork.main).identifier) {
await MainDB.instance.deleteWalletBlockchainData(old.walletId);
}
//
// Set other data values
//
Map<String, dynamic> otherData = {};
final Map<String, dynamic> otherData = {};
final List<String>? tokenContractAddresses = walletBox.get(
"ethTokenContracts",
@ -129,7 +134,7 @@ Future<void> migrateWalletsToIsar({
}
// epiccash specifics
if (old.coin == Coin.epicCash) {
if (old.coinIdentifier == Epiccash(CryptoCurrencyNetwork.main)) {
final epicWalletInfo = ExtraEpiccashWalletInfo.fromMap({
"receivingIndex": walletBox.get("receivingIndex") as int? ?? 0,
"changeIndex": walletBox.get("changeIndex") as int? ?? 0,
@ -142,7 +147,9 @@ Future<void> migrateWalletsToIsar({
otherData[WalletInfoKeys.epiccashData] = jsonEncode(
epicWalletInfo.toMap(),
);
} else if (old.coin == Coin.firo || old.coin == Coin.firoTestNet) {
} else if (old.coinIdentifier ==
Firo(CryptoCurrencyNetwork.main).identifier ||
old.coinIdentifier == Firo(CryptoCurrencyNetwork.test).identifier) {
otherData[WalletInfoKeys.lelantusCoinIsarRescanRequired] = walletBox
.get(WalletInfoKeys.lelantusCoinIsarRescanRequired) as bool? ??
true;
@ -161,10 +168,11 @@ Future<void> migrateWalletsToIsar({
);
final info = WalletInfo(
coinName: old.coin.name,
coinName: old.coinIdentifier,
walletId: old.walletId,
name: old.name,
mainAddressType: old.coin.primaryAddressType,
mainAddressType: SupportedCoins.getCryptoCurrencyFor(old.coinIdentifier)
.primaryAddressType,
favouriteOrderIndex: favourites.indexOf(old.walletId),
cachedChainHeight: walletBox.get(
DBKeys.storedChainHeight,

View file

@ -42,7 +42,7 @@ extension MainDBQueries on MainDB {
required CCFilter filter,
required CCSortDescriptor sort,
required String searchTerm,
required Coin coin,
required CryptoCurrency cryptoCurrency,
}) {
var preSort = getUTXOs(walletId).filter().group((q) {
final qq = q.group(
@ -79,7 +79,7 @@ extension MainDBQueries on MainDB {
qq = qq.or().valueEqualTo(
Amount.fromDecimal(
maybeDecimal,
fractionDigits: coin.decimals,
fractionDigits: cryptoCurrency.fractionDigits,
).raw.toInt(),
);
}
@ -114,7 +114,7 @@ extension MainDBQueries on MainDB {
required CCFilter filter,
required CCSortDescriptor sort,
required String searchTerm,
required Coin coin,
required CryptoCurrency cryptoCurrency,
}) {
var preSort = getUTXOs(walletId).filter().group((q) {
final qq = q.group(
@ -151,7 +151,7 @@ extension MainDBQueries on MainDB {
qq = qq.or().valueEqualTo(
Amount.fromDecimal(
maybeDecimal,
fractionDigits: coin.decimals,
fractionDigits: cryptoCurrency.fractionDigits,
).raw.toInt(),
);
}

View file

@ -11,7 +11,8 @@
import 'dart:convert';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/ethereum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class EthTokenTxExtraDTO {
EthTokenTxExtraDTO({
@ -42,7 +43,7 @@ class EthTokenTxExtraDTO {
to: map['to'] as String,
value: Amount(
rawValue: BigInt.parse(map['value'] as String),
fractionDigits: Coin.ethereum.decimals,
fractionDigits: Ethereum(CryptoCurrencyNetwork.main).fractionDigits,
),
gas: _amountFromJsonNum(map['gas']),
gasPrice: _amountFromJsonNum(map['gasPrice']),
@ -70,7 +71,7 @@ class EthTokenTxExtraDTO {
static Amount _amountFromJsonNum(dynamic json) {
return Amount(
rawValue: BigInt.from(json as num),
fractionDigits: Coin.ethereum.decimals,
fractionDigits: Ethereum(CryptoCurrencyNetwork.main).fractionDigits,
);
}

View file

@ -11,7 +11,8 @@
import 'dart:convert';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/ethereum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class EthTxDTO {
EthTxDTO({
@ -75,7 +76,7 @@ class EthTxDTO {
}
return Amount(
rawValue: BigInt.parse(json.toString()),
fractionDigits: Coin.ethereum.decimals,
fractionDigits: Ethereum(CryptoCurrencyNetwork.main).fractionDigits,
);
}

View file

@ -13,8 +13,8 @@ import 'dart:math';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/electrumx_rpc/electrumx_client.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:string_validator/string_validator.dart';
class CachedElectrumXClient {
@ -34,10 +34,11 @@ class CachedElectrumXClient {
Future<Map<String, dynamic>> getAnonymitySet({
required String groupId,
String blockhash = "",
required Coin coin,
required CryptoCurrency cryptoCurrency,
}) async {
try {
final box = await DB.instance.getAnonymitySetCacheBox(coin: coin);
final box =
await DB.instance.getAnonymitySetCacheBox(currency: cryptoCurrency);
final cachedSet = box.get(groupId) as Map?;
Map<String, dynamic> set;
@ -68,30 +69,38 @@ class CachedElectrumXClient {
? base64ToReverseHex(newSet["blockHash"] as String)
: newSet["blockHash"];
for (int i = (newSet["coins"] as List).length - 1; i >= 0; i--) {
dynamic newCoin = newSet["coins"][i];
List<dynamic> translatedCoin = [];
translatedCoin.add(!isHexadecimal(newCoin[0] as String)
? base64ToHex(newCoin[0] as String)
: newCoin[0]);
translatedCoin.add(!isHexadecimal(newCoin[1] as String)
? base64ToReverseHex(newCoin[1] as String)
: newCoin[1]);
final dynamic newCoin = newSet["coins"][i];
final List<dynamic> translatedCoin = [];
translatedCoin.add(
!isHexadecimal(newCoin[0] as String)
? base64ToHex(newCoin[0] as String)
: newCoin[0],
);
translatedCoin.add(
!isHexadecimal(newCoin[1] as String)
? base64ToReverseHex(newCoin[1] as String)
: newCoin[1],
);
try {
translatedCoin.add(!isHexadecimal(newCoin[2] as String)
? base64ToHex(newCoin[2] as String)
: newCoin[2]);
translatedCoin.add(
!isHexadecimal(newCoin[2] as String)
? base64ToHex(newCoin[2] as String)
: newCoin[2],
);
} catch (e) {
translatedCoin.add(newCoin[2]);
}
translatedCoin.add(!isHexadecimal(newCoin[3] as String)
? base64ToReverseHex(newCoin[3] as String)
: newCoin[3]);
translatedCoin.add(
!isHexadecimal(newCoin[3] as String)
? base64ToReverseHex(newCoin[3] as String)
: newCoin[3],
);
set["coins"].insert(0, translatedCoin);
}
// save set to db
await box.put(groupId, set);
Logging.instance.log(
"Updated current anonymity set for ${coin.name} with group ID $groupId",
"Updated current anonymity set for ${cryptoCurrency.identifier} with group ID $groupId",
level: LogLevel.Info,
);
}
@ -99,8 +108,9 @@ class CachedElectrumXClient {
return set;
} catch (e, s) {
Logging.instance.log(
"Failed to process CachedElectrumX.getAnonymitySet(): $e\n$s",
level: LogLevel.Error);
"Failed to process CachedElectrumX.getAnonymitySet(): $e\n$s",
level: LogLevel.Error,
);
rethrow;
}
}
@ -108,11 +118,13 @@ class CachedElectrumXClient {
Future<Map<String, dynamic>> getSparkAnonymitySet({
required String groupId,
String blockhash = "",
required Coin coin,
required CryptoCurrency cryptoCurrency,
required bool useOnlyCacheIfNotEmpty,
}) async {
try {
final box = await DB.instance.getSparkAnonymitySetCacheBox(coin: coin);
final box = await DB.instance.getSparkAnonymitySetCacheBox(
currency: cryptoCurrency,
);
final cachedSet = box.get(groupId) as Map?;
Map<String, dynamic> set;
@ -152,7 +164,7 @@ class CachedElectrumXClient {
// save set to db
await box.put(groupId, set);
Logging.instance.log(
"Updated current anonymity set for ${coin.name} with group ID $groupId",
"Updated current anonymity set for ${cryptoCurrency.identifier} with group ID $groupId",
level: LogLevel.Info,
);
}
@ -160,8 +172,9 @@ class CachedElectrumXClient {
return set;
} catch (e, s) {
Logging.instance.log(
"Failed to process CachedElectrumX.getSparkAnonymitySet(): $e\n$s",
level: LogLevel.Error);
"Failed to process CachedElectrumX.getSparkAnonymitySet(): $e\n$s",
level: LogLevel.Error,
);
rethrow;
}
}
@ -182,11 +195,11 @@ class CachedElectrumXClient {
/// ElectrumX api only called if the tx does not exist in local db
Future<Map<String, dynamic>> getTransaction({
required String txHash,
required Coin coin,
required CryptoCurrency cryptoCurrency,
bool verbose = true,
}) async {
try {
final box = await DB.instance.getTxCacheBox(coin: coin);
final box = await DB.instance.getTxCacheBox(currency: cryptoCurrency);
final cachedTx = box.get(txHash) as Map?;
if (cachedTx == null) {
@ -213,22 +226,24 @@ class CachedElectrumXClient {
}
} catch (e, s) {
Logging.instance.log(
"Failed to process CachedElectrumX.getTransaction(): $e\n$s",
level: LogLevel.Error);
"Failed to process CachedElectrumX.getTransaction(): $e\n$s",
level: LogLevel.Error,
);
rethrow;
}
}
Future<List<String>> getUsedCoinSerials({
required Coin coin,
required CryptoCurrency cryptoCurrency,
int startNumber = 0,
}) async {
try {
final box = await DB.instance.getUsedSerialsCacheBox(coin: coin);
final box =
await DB.instance.getUsedSerialsCacheBox(currency: cryptoCurrency);
final _list = box.get("serials") as List?;
Set<String> cachedSerials =
final Set<String> cachedSerials =
_list == null ? {} : List<String>.from(_list).toSet();
startNumber = max(
@ -269,14 +284,16 @@ class CachedElectrumXClient {
}
Future<Set<String>> getSparkUsedCoinsTags({
required Coin coin,
required CryptoCurrency cryptoCurrency,
}) async {
try {
final box = await DB.instance.getSparkUsedCoinsTagsCacheBox(coin: coin);
final box = await DB.instance.getSparkUsedCoinsTagsCacheBox(
currency: cryptoCurrency,
);
final _list = box.get("tags") as List?;
Set<String> cachedTags =
final Set<String> cachedTags =
_list == null ? {} : List<String>.from(_list).toSet();
final startNumber = max(
@ -314,8 +331,9 @@ class CachedElectrumXClient {
}
/// Clear all cached transactions for the specified coin
Future<void> clearSharedTransactionCache({required Coin coin}) async {
await DB.instance.clearSharedTransactionCache(coin: coin);
await DB.instance.closeAnonymitySetCacheBox(coin: coin);
Future<void> clearSharedTransactionCache(
{required CryptoCurrency cryptoCurrency}) async {
await DB.instance.clearSharedTransactionCache(currency: cryptoCurrency);
await DB.instance.closeAnonymitySetCacheBox(currency: cryptoCurrency);
}
}

View file

@ -9,10 +9,10 @@
*/
import 'package:equatable/equatable.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
abstract class AddWalletListEntity extends Equatable {
Coin get coin;
CryptoCurrency get cryptoCurrency;
String get name;
String get ticker;
}

View file

@ -9,22 +9,22 @@
*/
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class CoinEntity extends AddWalletListEntity {
CoinEntity(this._coin);
final Coin _coin;
final CryptoCurrency _coin;
@override
Coin get coin => _coin;
CryptoCurrency get cryptoCurrency => _coin;
@override
String get name => coin.prettyName;
String get name => cryptoCurrency.prettyName;
@override
String get ticker => coin.ticker;
String get ticker => cryptoCurrency.ticker;
@override
List<Object?> get props => [coin, name, ticker];
List<Object?> get props => [cryptoCurrency.identifier, name, ticker];
}

View file

@ -10,15 +10,17 @@
import 'package:stackwallet/models/add_wallet_list_entity/add_wallet_list_entity.dart';
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/ethereum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class EthTokenEntity extends AddWalletListEntity {
EthTokenEntity(this.token);
final EthContract token;
// TODO: check other networks in future and handle differently?
@override
Coin get coin => Coin.ethereum;
CryptoCurrency get cryptoCurrency => Ethereum(CryptoCurrencyNetwork.main);
@override
String get name => token.name;
@ -27,5 +29,6 @@ class EthTokenEntity extends AddWalletListEntity {
String get ticker => token.symbol;
@override
List<Object?> get props => [coin, name, ticker, token.address];
List<Object?> get props =>
[cryptoCurrency.identifier, name, ticker, token.address];
}

View file

@ -9,46 +9,46 @@
*/
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class AddressBookFilter extends ChangeNotifier {
AddressBookFilter(Set<Coin> coins) {
AddressBookFilter(Set<CryptoCurrency> coins) {
_coins = coins;
}
Set<Coin> _coins = {};
Set<CryptoCurrency> _coins = {};
Set<Coin> get coins => _coins;
Set<CryptoCurrency> get coins => _coins;
set coins(Set<Coin> coins) {
set coins(Set<CryptoCurrency> coins) {
_coins = coins;
notifyListeners();
}
void add(Coin coin, bool shouldNotifyListeners) {
void add(CryptoCurrency coin, bool shouldNotifyListeners) {
_coins.add(coin);
if (shouldNotifyListeners) {
notifyListeners();
}
}
void addAll(Iterable<Coin> coins, bool shouldNotifyListeners) {
void addAll(Iterable<CryptoCurrency> coins, bool shouldNotifyListeners) {
_coins.addAll(coins);
if (shouldNotifyListeners) {
notifyListeners();
}
}
void remove(Coin coin, bool shouldNotifyListeners) {
_coins.removeWhere((e) => e.name == coin.name);
void remove(CryptoCurrency coin, bool shouldNotifyListeners) {
_coins.removeWhere((e) => e.identifier == coin.identifier);
if (shouldNotifyListeners) {
notifyListeners();
}
}
void removeMany(Set<Coin> coins, bool shouldNotifyListeners) {
void removeMany(Set<CryptoCurrency> coins, bool shouldNotifyListeners) {
for (final coin in coins) {
_coins.removeWhere((e) => e.name == coin.name);
_coins.removeWhere((e) => e.identifier == coin.identifier);
}
if (shouldNotifyListeners) {
notifyListeners();

View file

@ -11,7 +11,7 @@
import 'dart:convert';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class Balance {
final Amount total;
@ -26,10 +26,10 @@ class Balance {
required this.pendingSpendable,
});
factory Balance.zeroForCoin({required Coin coin}) {
factory Balance.zeroFor({required CryptoCurrency currency}) {
final amount = Amount(
rawValue: BigInt.zero,
fractionDigits: coin.decimals,
fractionDigits: currency.fractionDigits,
);
return Balance(

View file

@ -10,11 +10,12 @@
import 'dart:convert';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
@Deprecated("Use lib/models/isar/models/contact_entry.dart instead")
class ContactAddressEntry {
final Coin coin;
final CryptoCurrency coin;
final String address;
final String label;
final String? other;
@ -27,7 +28,7 @@ class ContactAddressEntry {
});
ContactAddressEntry copyWith({
Coin? coin,
CryptoCurrency? coin,
String? address,
String? label,
String? other,
@ -42,7 +43,7 @@ class ContactAddressEntry {
factory ContactAddressEntry.fromJson(Map<String, dynamic> jsonObject) {
return ContactAddressEntry(
coin: Coin.values.byName(jsonObject["coin"] as String),
coin: SupportedCoins.getCryptoCurrencyFor(jsonObject["coin"] as String),
address: jsonObject["address"] as String,
label: jsonObject["label"] as String,
other: jsonObject["other"] as String?,
@ -53,7 +54,7 @@ class ContactAddressEntry {
return {
"label": label,
"address": address,
"coin": coin.name,
"coin": coin.identifier,
"other": other ?? "",
};
}

View file

@ -10,8 +10,7 @@
import 'package:flutter/cupertino.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class AddressEntryData extends ChangeNotifier {
late int id;
@ -20,7 +19,7 @@ class AddressEntryData extends ChangeNotifier {
String? _addressLabel;
String? _address;
Coin? _coin;
CryptoCurrency? _coin;
String? get addressLabel => _addressLabel;
@ -36,9 +35,9 @@ class AddressEntryData extends ChangeNotifier {
notifyListeners();
}
Coin? get coin => _coin;
CryptoCurrency? get coin => _coin;
set coin(Coin? coin) {
set coin(CryptoCurrency? coin) {
_coin = coin;
notifyListeners();
}
@ -73,12 +72,12 @@ class AddressEntryData extends ChangeNotifier {
if (_address == null) {
return false;
}
return AddressUtils.validateAddress(_address!, _coin!);
return _coin!.validateAddress(_address!);
}
ContactAddressEntry buildAddressEntry() {
return ContactAddressEntry()
..coinName = coin!.name
..coinName = coin!.identifier
..address = address!
..other = null
..label = addressLabel!;
@ -86,6 +85,6 @@ class AddressEntryData extends ChangeNotifier {
@override
String toString() {
return "AddressEntryData: { addressLabel: $addressLabel, address: $address, coin: ${coin?.name} }";
return "AddressEntryData: { addressLabel: $addressLabel, address: $address, coin: ${coin?.identifier} }";
}
}

View file

@ -10,7 +10,7 @@
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/exchange_cache/pair.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/supported_coins.dart';
part 'currency.g.dart';
@ -161,7 +161,7 @@ class Currency {
static bool checkIsStackCoin(String ticker) {
try {
coinFromTickerCaseInsensitive(ticker);
SupportedCoins.getCryptoCurrencyForTicker(ticker);
return true;
} catch (_) {
return false;

View file

@ -9,7 +9,8 @@
*/
import 'package:isar/isar.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
part 'block_explorer.g.dart';
@ -28,9 +29,9 @@ class TransactionBlockExplorer {
late final String url;
@ignore
Coin? get coin {
CryptoCurrency? get coin {
try {
return coinFromTickerCaseInsensitive(ticker);
return SupportedCoins.getCryptoCurrencyForTicker(ticker);
} catch (_) {
return null;
}

View file

@ -9,7 +9,8 @@
*/
import 'package:isar/isar.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
part 'contact_entry.g.dart';
@ -36,7 +37,7 @@ class ContactEntry {
@ignore
List<ContactAddressEntry> get addressesSorted {
final List<ContactAddressEntry> sorted = [];
for (final coin in Coin.values) {
for (final coin in SupportedCoins.cryptocurrencies) {
final slice = addresses.where((e) => e.coin == coin).toList();
if (slice.isNotEmpty) {
slice.sort(
@ -56,13 +57,13 @@ class ContactEntry {
List<ContactAddressEntry>? addresses,
bool? isFavorite,
}) {
List<ContactAddressEntry> _addresses = [];
final List<ContactAddressEntry> _addresses = [];
if (addresses == null) {
for (var e in this.addresses) {
for (final e in this.addresses) {
_addresses.add(e.copyWith());
}
} else {
for (var e in addresses) {
for (final e in addresses) {
_addresses.add(e.copyWith());
}
}
@ -101,18 +102,18 @@ class ContactAddressEntry {
late final String? other;
@ignore
Coin get coin => Coin.values.byName(coinName);
CryptoCurrency get coin => SupportedCoins.getCryptoCurrencyFor(coinName);
ContactAddressEntry();
ContactAddressEntry copyWith({
Coin? coin,
CryptoCurrency? coin,
String? address,
String? label,
String? other,
}) {
return ContactAddressEntry()
..coinName = coin?.name ?? coinName
..coinName = coin?.identifier ?? coinName
..address = address ?? this.address
..label = label ?? this.label
..other = other ?? this.other;
@ -122,7 +123,7 @@ class ContactAddressEntry {
return {
"label": label,
"address": address,
"coin": coin.name,
"coin": coin.identifier,
"other": other ?? "",
};
}

View file

@ -13,7 +13,7 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/utilities/extensions/impl/box_shadow.dart';
import 'package:stackwallet/utilities/extensions/impl/gradient.dart';
import 'package:stackwallet/utilities/extensions/impl/string.dart';
@ -1482,10 +1482,10 @@ class StackTheme {
// ==== coinColors =====================================================
@ignore
Map<Coin, Color> get coinColors =>
Map<String, Color> get coinColors =>
_coinColors ??= parseCoinColors(coinColorsJsonString);
@ignore
Map<Coin, Color>? _coinColors;
Map<String, Color>? _coinColors;
late final String coinColorsJsonString;
// ==== assets =====================================================
@ -1851,20 +1851,21 @@ class StackTheme {
}
/// parse coin colors json and fetch color or use default
static Map<Coin, Color> parseCoinColors(String jsonString) {
static Map<String, Color> parseCoinColors(String jsonString) {
final json = jsonDecode(jsonString) as Map;
final map = Map<String, dynamic>.from(json);
final Map<Coin, Color> result = {};
final Map<String, Color> result = {};
for (final coin in Coin.values.map((e) => e.mainNetVersion)) {
if (map[coin.name] is String) {
result[coin] = Color(
(map[coin.name] as String).toBigIntFromHex.toInt(),
for (final mainNetId
in SupportedCoins.cryptocurrencies.map((e) => e.mainNetId)) {
if (map[mainNetId] is String) {
result[mainNetId] = Color(
(map[mainNetId] as String).toBigIntFromHex.toInt(),
);
} else {
Logging.instance.log(
"Color not found in theme for $coin",
"Color not found in theme for $mainNetId",
level: LogLevel.Error,
);
}
@ -2080,31 +2081,31 @@ class ThemeAssetsV2 implements IThemeAssets {
late final String coinPlaceholder;
@ignore
Map<Coin, String> get coinIcons => _coinIcons ??= parseCoinAssetsString(
Map<String, String> get coinIcons => _coinIcons ??= parseCoinAssetsString(
coinIconsString,
placeHolder: coinPlaceholder,
);
@ignore
Map<Coin, String>? _coinIcons;
Map<String, String>? _coinIcons;
late final String coinIconsString;
@ignore
Map<Coin, String> get coinImages => _coinImages ??= parseCoinAssetsString(
Map<String, String> get coinImages => _coinImages ??= parseCoinAssetsString(
coinImagesString,
placeHolder: coinPlaceholder,
);
@ignore
Map<Coin, String>? _coinImages;
Map<String, String>? _coinImages;
late final String coinImagesString;
@ignore
Map<Coin, String> get coinSecondaryImages =>
Map<String, String> get coinSecondaryImages =>
_coinSecondaryImages ??= parseCoinAssetsString(
coinSecondaryImagesString,
placeHolder: coinPlaceholder,
);
@ignore
Map<Coin, String>? _coinSecondaryImages;
Map<String, String>? _coinSecondaryImages;
late final String coinSecondaryImagesString;
ThemeAssetsV2();
@ -2166,17 +2167,17 @@ class ThemeAssetsV2 implements IThemeAssets {
return jsonEncode(map);
}
static Map<Coin, String> parseCoinAssetsString(
static Map<String, String> parseCoinAssetsString(
String jsonString, {
required String placeHolder,
}) {
final json = jsonDecode(jsonString) as Map;
final map = Map<String, dynamic>.from(json);
final Map<Coin, String> result = {};
final Map<String, String> result = {};
for (final coin in Coin.values) {
result[coin] = map[coin.name] as String? ?? placeHolder;
for (final coin in SupportedCoins.cryptocurrencies) {
result[coin.mainNetId] = map[coin.mainNetId] as String? ?? placeHolder;
}
return result;
@ -2350,35 +2351,35 @@ class ThemeAssetsV3 implements IThemeAssets {
late final String? dummy3;
@ignore
Map<Coin, String> get coinIcons => _coinIcons ??= parseCoinAssetsString(
Map<String, String> get coinIcons => _coinIcons ??= parseCoinAssetsString(
coinIconsString,
placeHolder: coinPlaceholder,
);
@ignore
Map<Coin, String>? _coinIcons;
Map<String, String>? _coinIcons;
late final String coinIconsString;
@ignore
Map<Coin, String> get coinImages => _coinImages ??= parseCoinAssetsString(
Map<String, String> get coinImages => _coinImages ??= parseCoinAssetsString(
coinImagesString,
placeHolder: coinPlaceholder,
);
@ignore
Map<Coin, String>? _coinImages;
Map<String, String>? _coinImages;
late final String coinImagesString;
@ignore
Map<Coin, String> get coinSecondaryImages =>
Map<String, String> get coinSecondaryImages =>
_coinSecondaryImages ??= parseCoinAssetsString(
coinSecondaryImagesString,
placeHolder: coinPlaceholder,
);
@ignore
Map<Coin, String>? _coinSecondaryImages;
Map<String, String>? _coinSecondaryImages;
late final String coinSecondaryImagesString;
@ignore
Map<Coin, String>? get coinCardImages =>
Map<String, String>? get coinCardImages =>
_coinCardImages ??= coinCardImagesString == null
? null
: parseCoinAssetsString(
@ -2386,11 +2387,11 @@ class ThemeAssetsV3 implements IThemeAssets {
placeHolder: coinPlaceholder,
);
@ignore
Map<Coin, String>? _coinCardImages;
Map<String, String>? _coinCardImages;
late final String? coinCardImagesString;
@ignore
Map<Coin, String>? get coinCardFavoritesImages =>
Map<String, String>? get coinCardFavoritesImages =>
_coinCardFavoritesImages ??= coinCardFavoritesImagesString == null
? null
: parseCoinAssetsString(
@ -2398,7 +2399,7 @@ class ThemeAssetsV3 implements IThemeAssets {
placeHolder: coinPlaceholder,
);
@ignore
Map<Coin, String>? _coinCardFavoritesImages;
Map<String, String>? _coinCardFavoritesImages;
@Name("otherStringParam1")
late final String? coinCardFavoritesImagesString;
@ -2501,19 +2502,18 @@ class ThemeAssetsV3 implements IThemeAssets {
return jsonEncode(map);
}
static Map<Coin, String> parseCoinAssetsString(
static Map<String, String> parseCoinAssetsString(
String jsonString, {
required String placeHolder,
}) {
final json = jsonDecode(jsonString) as Map;
final map = Map<String, dynamic>.from(json);
final Map<Coin, String> result = {};
final Map<String, String> result = {};
for (final coin in Coin.values) {
result[coin] = map[coin.name] as String? ?? placeHolder;
result[coin] = prependIfNeeded(result[coin]!);
for (final coin in SupportedCoins.cryptocurrencies) {
result[coin.mainNetId] = map[coin.mainNetId] as String? ?? placeHolder;
result[coin.mainNetId] = prependIfNeeded(result[coin.mainNetId]!);
}
return result;

View file

@ -11,8 +11,6 @@
import 'package:dart_numerics/dart_numerics.dart';
import 'package:decimal/decimal.dart';
import 'package:hive/hive.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
part '../type_adaptors/transactions_model.g.dart';
@ -236,19 +234,11 @@ class Transaction {
timestamp: json['timestamp'] as int? ??
(DateTime.now().millisecondsSinceEpoch ~/ 1000),
txType: json['txType'] as String,
amount: (Decimal.parse(json["amount"].toString()) *
Decimal.fromInt(Constants.satsPerCoin(Coin
.firo).toInt())) // dirty hack but we need 8 decimal places here to keep consistent data structure
.toBigInt()
.toInt(),
amount: _parse(json["amount"].toString()),
aliens: [],
worthNow: json['worthNow'] as String,
worthAtBlockTimestamp: json['worthAtBlockTimestamp'] as String? ?? "0",
fees: (Decimal.parse(json["fees"].toString()) *
Decimal.fromInt(Constants.satsPerCoin(Coin
.firo).toInt())) // dirty hack but we need 8 decimal places here to keep consistent data structure
.toBigInt()
.toInt(),
fees: _parse(json["fees"].toString()),
inputSize: json['inputSize'] as int? ?? 0,
outputSize: json['outputSize'] as int? ?? 0,
inputs: [],
@ -411,12 +401,7 @@ class Output {
scriptpubkeyAsm: json['scriptPubKey']['asm'] as String?,
scriptpubkeyType: json['scriptPubKey']['type'] as String?,
scriptpubkeyAddress: address,
value: (Decimal.parse(
(json["value"] ?? 0).toString()) *
Decimal.fromInt(Constants.satsPerCoin(Coin
.firo).toInt())) // dirty hack but we need 8 decimal places here to keep consistent data structure
.toBigInt()
.toInt(),
value: _parse((json["value"] ?? 0).toString()),
);
} catch (s, e) {
return Output(
@ -425,11 +410,11 @@ class Output {
scriptpubkeyAsm: "",
scriptpubkeyType: "",
scriptpubkeyAddress: "",
value: (Decimal.parse(0.toString()) *
Decimal.fromInt(Constants.satsPerCoin(Coin
.firo).toInt())) // dirty hack but we need 8 decimal places here to keep consistent data structure
.toBigInt()
.toInt());
value: _parse(0.toString()));
}
}
}
int _parse(String value) {
return (Decimal.parse(value) * Decimal.fromInt(8)).toBigInt().toInt();
}

View file

@ -9,14 +9,14 @@
*/
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/stack_restoring_status.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
class WalletRestoreState extends ChangeNotifier {
final String walletId;
final String walletName;
final Coin coin;
final CryptoCurrency coin;
late StackRestoringStatus _restoringStatus;
Wallet? wallet;
String? address;

View file

@ -15,10 +15,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/models/notification_model.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/themes/theme_providers.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
@ -44,7 +44,8 @@ class NotificationCard extends ConsumerWidget {
String coinIconPath(IThemeAssets assets, WidgetRef ref) {
try {
final coin = coinFromPrettyName(notification.coinName);
final coin =
SupportedCoins.getCryptoCurrencyByPrettyName(notification.coinName);
return ref.read(coinIconProvider(coin));
} catch (_) {
return notification.iconAssetName;

View file

@ -28,13 +28,17 @@ import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/e
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/sub_widgets/next_button.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_eth_tokens.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoin_frost.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/monero.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/wownero.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
@ -61,10 +65,14 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
String _searchTerm = "";
final List<Coin> _coinsTestnet = [
...Coin.values.where((e) => e.isTestNet),
final _coinsTestnet = [
...SupportedCoins.cryptocurrencies
.where((e) => e.network == CryptoCurrencyNetwork.test),
];
final _coins = [
...SupportedCoins.cryptocurrencies
.where((e) => e.network == CryptoCurrencyNetwork.main),
];
final List<Coin> _coins = [...Coin.values.where((e) => !e.isTestNet)];
final List<AddWalletListEntity> coinEntities = [];
final List<EthTokenEntity> tokenEntities = [];
@ -81,7 +89,7 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
(e) =>
e.ticker.toLowerCase().contains(lowercaseTerm) ||
e.name.toLowerCase().contains(lowercaseTerm) ||
e.coin.name.toLowerCase().contains(lowercaseTerm) ||
e.cryptoCurrency.identifier.toLowerCase().contains(lowercaseTerm) ||
(e is EthTokenEntity &&
e.token.address.toLowerCase().contains(lowercaseTerm)),
);
@ -129,15 +137,13 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
_searchFocusNode = FocusNode();
// _coinsTestnet.remove(Coin.firoTestNet);
if (Platform.isWindows) {
_coins.remove(Coin.monero);
_coins.remove(Coin.wownero);
_coins.removeWhere((e) => e is Monero || e is Wownero);
} else if (Platform.isLinux) {
_coins.remove(Coin.wownero);
_coins.removeWhere((e) => e is Wownero);
}
if (Util.isDesktop && !kDebugMode) {
_coins.remove(Coin.bitcoinFrost);
_coins.remove(Coin.bitcoinFrostTestNet);
_coins.removeWhere((e) => e is BitcoinFrost);
}
coinEntities.addAll(_coins.map((e) => CoinEntity(e)));

View file

@ -29,9 +29,9 @@ import 'package:stackwallet/utilities/util.dart';
class CoinSelectItem extends ConsumerWidget {
const CoinSelectItem({
Key? key,
super.key,
required this.entity,
}) : super(key: key);
});
final AddWalletListEntity entity;
@ -90,7 +90,7 @@ class CoinSelectItem extends ConsumerWidget {
)
: SvgPicture.file(
File(
ref.watch(coinIconProvider(entity.coin)),
ref.watch(coinIconProvider(entity.cryptoCurrency)),
),
width: 26,
height: 26,

View file

@ -24,9 +24,9 @@ import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
class CreateOrRestoreWalletView extends StatelessWidget {
const CreateOrRestoreWalletView({
Key? key,
super.key,
required this.entity,
}) : super(key: key);
});
static const routeName = "/createOrRestoreWallet";
@ -57,7 +57,7 @@ class CreateOrRestoreWalletView extends StatelessWidget {
flex: 10,
),*/
CreateRestoreWalletTitle(
coin: entity.coin,
coin: entity.cryptoCurrency,
isDesktop: isDesktop,
),
const SizedBox(
@ -73,7 +73,7 @@ class CreateOrRestoreWalletView extends StatelessWidget {
height: 32,
),
CoinImage(
coin: entity.coin,
coin: entity.cryptoCurrency,
width: isDesktop
? 324
: MediaQuery.of(context).size.width / 1.6,
@ -85,7 +85,7 @@ class CreateOrRestoreWalletView extends StatelessWidget {
height: 32,
),
CreateWalletButtonGroup(
coin: entity.coin,
coin: entity.cryptoCurrency,
isDesktop: isDesktop,
),
/*const Spacer(
@ -129,7 +129,7 @@ class CreateOrRestoreWalletView extends StatelessWidget {
flex: 2,
),
CoinImage(
coin: entity.coin,
coin: entity.cryptoCurrency,
width: isDesktop
? 324
: MediaQuery.of(context).size.width / 1.6,
@ -141,7 +141,7 @@ class CreateOrRestoreWalletView extends StatelessWidget {
flex: 2,
),
CreateRestoreWalletTitle(
coin: entity.coin,
coin: entity.cryptoCurrency,
isDesktop: isDesktop,
),
const SizedBox(
@ -154,7 +154,7 @@ class CreateOrRestoreWalletView extends StatelessWidget {
flex: 5,
),
CreateWalletButtonGroup(
coin: entity.coin,
coin: entity.cryptoCurrency,
isDesktop: isDesktop,
),
],

View file

@ -14,18 +14,18 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/themes/coin_image_provider.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class CoinImage extends ConsumerWidget {
const CoinImage({
Key? key,
super.key,
required this.coin,
this.width,
this.height,
}) : super(key: key);
});
final Coin coin;
final CryptoCurrency coin;
final double? width;
final double? height;

View file

@ -9,17 +9,17 @@
*/
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class CreateRestoreWalletTitle extends StatelessWidget {
const CreateRestoreWalletTitle({
Key? key,
super.key,
required this.coin,
required this.isDesktop,
}) : super(key: key);
});
final Coin coin;
final CryptoCurrency coin;
final bool isDesktop;
@override

View file

@ -14,18 +14,19 @@ import 'package:flutter/material.dart';
import 'package:stackwallet/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/enums/add_wallet_type_enum.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/wownero.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:tuple/tuple.dart';
class CreateWalletButtonGroup extends StatelessWidget {
const CreateWalletButtonGroup({
Key? key,
super.key,
required this.coin,
required this.isDesktop,
}) : super(key: key);
});
final Coin coin;
final CryptoCurrency coin;
final bool isDesktop;
@override
@ -34,7 +35,7 @@ class CreateWalletButtonGroup extends StatelessWidget {
crossAxisAlignment:
isDesktop ? CrossAxisAlignment.center : CrossAxisAlignment.stretch,
children: [
if (Platform.isAndroid || coin != Coin.wownero)
if (Platform.isAndroid || coin is! Wownero)
ConstrainedBox(
constraints: BoxConstraints(
minHeight: isDesktop ? 70 : 0,
@ -61,7 +62,7 @@ class CreateWalletButtonGroup extends StatelessWidget {
),
),
),
if (Platform.isAndroid || coin != Coin.wownero)
if (Platform.isAndroid || coin is! Wownero)
SizedBox(
height: isDesktop ? 16 : 12,
),

View file

@ -143,7 +143,7 @@ class _FrostCreateStep5State extends ConsumerState<FrostCreateStep5> {
final data = ref.read(pFrostScaffoldArgs)!;
final info = WalletInfo.createNew(
coin: data.info.frostCurrency.coin,
coin: data.info.frostCurrency,
name: data.info.walletName,
);

View file

@ -49,7 +49,7 @@ class _FrostReshareStep1cState extends ConsumerState<FrostReshareStep1c> {
final info = WalletInfo.createNew(
name: data.info.walletName,
coin: data.info.frostCurrency.coin,
coin: data.info.frostCurrency,
);
final wallet = IncompleteFrostWallet();

View file

@ -75,7 +75,7 @@ class _RestoreFrostMsWalletViewState
final myName = participants[myNameIndex];
final info = WalletInfo.createNew(
coin: widget.frostCurrency.coin,
coin: widget.frostCurrency,
name: widget.walletName,
);

View file

@ -26,12 +26,11 @@ import 'package:stackwallet/providers/ui/verify_recovery_phrase/mnemonic_word_co
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/add_wallet_type_enum.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/name_generator.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoin_frost.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/frost_currency.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -48,15 +47,15 @@ import 'package:tuple/tuple.dart';
class NameYourWalletView extends ConsumerStatefulWidget {
const NameYourWalletView({
Key? key,
super.key,
required this.addWalletType,
required this.coin,
}) : super(key: key);
});
static const routeName = "/nameYourWallet";
final AddWalletType addWalletType;
final Coin coin;
final CryptoCurrency coin;
@override
ConsumerState<NameYourWalletView> createState() => _NameYourWalletViewState();
@ -64,7 +63,7 @@ class NameYourWalletView extends ConsumerStatefulWidget {
class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
late final AddWalletType addWalletType;
late final Coin coin;
late final CryptoCurrency coin;
late TextEditingController textEditingController;
late FocusNode textFieldFocusNode;
@ -96,7 +95,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
if (mounted) {
ref.read(mnemonicWordCountStateProvider.state).state =
Constants.possibleLengthsForCoin(coin).last;
coin.possibleMnemonicLengths.last;
ref.read(pNewWalletOptions.notifier).state = null;
switch (widget.addWalletType) {
@ -244,7 +243,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
height: isDesktop ? 0 : 16,
),
Text(
"Name your ${coin.prettyName} ${coin.isFrost ? "multisig " : ""}wallet",
"Name your ${coin.prettyName} ${coin is FrostCurrency ? "multisig " : ""}wallet",
textAlign: TextAlign.center,
style: isDesktop
? STextStyles.desktopH2(context)
@ -254,7 +253,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
height: isDesktop ? 16 : 8,
),
Text(
"Enter a label for your wallet (e.g. ${coin.isFrost ? "Multisig" : "Savings"})",
"Enter a label for your wallet (e.g. ${coin is FrostCurrency ? "Multisig" : "Savings"})",
textAlign: TextAlign.center,
style: isDesktop
? STextStyles.desktopSubtitleH2(context)
@ -383,7 +382,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
const SizedBox(
height: 32,
),
if (widget.coin.isFrost)
if (widget.coin is FrostCurrency)
if (widget.addWalletType == AddWalletType.Restore)
PrimaryButton(
label: "Next",
@ -395,15 +394,13 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
RestoreFrostMsWalletView.routeName,
arguments: (
walletName: name,
// TODO: [prio=med] this will cause issues if frost is ever applied to other coins
frostCurrency: coin.isTestNet
? BitcoinFrost(CryptoCurrencyNetwork.test)
: BitcoinFrost(CryptoCurrencyNetwork.main),
frostCurrency: coin,
),
);
},
),
if (widget.coin.isFrost && widget.addWalletType == AddWalletType.New)
if (widget.coin is FrostCurrency &&
widget.addWalletType == AddWalletType.New)
Column(
children: [
PrimaryButton(
@ -416,10 +413,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
CreateNewFrostMsWalletView.routeName,
arguments: (
walletName: name,
// TODO: [prio=med] this will cause issues if frost is ever applied to other coins
frostCurrency: coin.isTestNet
? BitcoinFrost(CryptoCurrencyNetwork.test)
: BitcoinFrost(CryptoCurrencyNetwork.main),
frostCurrency: coin,
),
);
},
@ -437,10 +431,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
SelectNewFrostImportTypeView.routeName,
arguments: (
walletName: name,
// TODO: [prio=med] this will cause issues if frost is ever applied to other coins
frostCurrency: coin.isTestNet
? BitcoinFrost(CryptoCurrencyNetwork.test)
: BitcoinFrost(CryptoCurrencyNetwork.main),
frostCurrency: coin,
),
);
},
@ -480,7 +471,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
// ),
],
),
if (!widget.coin.isFrost)
if (widget.coin is! FrostCurrency)
ConstrainedBox(
constraints: BoxConstraints(
minWidth: isDesktop ? 480 : 0,

View file

@ -11,9 +11,9 @@ import 'package:stackwallet/providers/ui/verify_recovery_phrase/mnemonic_word_co
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/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -26,7 +26,8 @@ import 'package:tuple/tuple.dart';
final pNewWalletOptions =
StateProvider<({String mnemonicPassphrase, int mnemonicWordsCount})?>(
(ref) => null);
(ref) => null,
);
enum NewWalletOptions {
Default,
@ -35,15 +36,15 @@ enum NewWalletOptions {
class NewWalletOptionsView extends ConsumerStatefulWidget {
const NewWalletOptionsView({
Key? key,
super.key,
required this.walletName,
required this.coin,
}) : super(key: key);
});
static const routeName = "/newWalletOptionsView";
final String walletName;
final Coin coin;
final CryptoCurrency coin;
@override
ConsumerState<NewWalletOptionsView> createState() =>
@ -74,7 +75,7 @@ class _NewWalletOptionsViewState extends ConsumerState<NewWalletOptionsView> {
@override
Widget build(BuildContext context) {
final lengths = Constants.possibleLengthsForCoin(widget.coin).toList();
final lengths = widget.coin.possibleMnemonicLengths;
return ConditionalParent(
condition: Util.isDesktop,
builder: (child) => DesktopScaffold(
@ -339,7 +340,8 @@ class _NewWalletOptionsViewState extends ConsumerState<NewWalletOptionsView> {
),
GestureDetector(
key: const Key(
"mnemonicPassphraseFieldShowPasswordButtonKey"),
"mnemonicPassphraseFieldShowPasswordButtonKey",
),
onTap: () async {
setState(() {
hidePassword = !hidePassword;

View file

@ -25,13 +25,14 @@ import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/monero.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';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
@ -45,14 +46,14 @@ import 'package:tuple/tuple.dart';
class NewWalletRecoveryPhraseWarningView extends ConsumerStatefulWidget {
const NewWalletRecoveryPhraseWarningView({
Key? key,
super.key,
required this.coin,
required this.walletName,
}) : super(key: key);
});
static const routeName = "/newWalletRecoveryPhraseWarning";
final Coin coin;
final CryptoCurrency coin;
final String walletName;
@override
@ -62,7 +63,7 @@ class NewWalletRecoveryPhraseWarningView extends ConsumerStatefulWidget {
class _NewWalletRecoveryPhraseWarningViewState
extends ConsumerState<NewWalletRecoveryPhraseWarningView> {
late final Coin coin;
late final CryptoCurrency coin;
late final String walletName;
late final bool isDesktop;
@ -79,8 +80,8 @@ class _NewWalletRecoveryPhraseWarningViewState
debugPrint("BUILD: $runtimeType");
final options = ref.read(pNewWalletOptions.state).state;
final seedCount = options?.mnemonicWordsCount ??
Constants.defaultSeedPhraseLengthFor(coin: coin);
final seedCount =
options?.mnemonicWordsCount ?? coin.defaultSeedPhraseLength;
return MasterScaffold(
isDesktop: isDesktop,
@ -118,7 +119,7 @@ class _NewWalletRecoveryPhraseWarningViewState
);
},
),
)
),
],
),
body: SingleChildScrollView(
@ -180,7 +181,8 @@ class _NewWalletRecoveryPhraseWarningViewState
"access to your wallet.",
style: isDesktop
? STextStyles.desktopTextMediumRegular(
context)
context,
)
: STextStyles.subtitle(context).copyWith(
fontSize: 12,
),
@ -359,13 +361,14 @@ class _NewWalletRecoveryPhraseWarningViewState
child: Text(
"Do not show them to anyone.",
style: STextStyles.navBarTitle(
context),
context,
),
),
),
],
),
],
)
),
],
),
),
@ -410,12 +413,14 @@ class _NewWalletRecoveryPhraseWarningViewState
MaterialTapTargetSize.shrinkWrap,
value: ref
.watch(
checkBoxStateProvider.state)
checkBoxStateProvider.state,
)
.state,
onChanged: (newValue) {
ref
.read(
checkBoxStateProvider.state)
checkBoxStateProvider.state,
)
.state = newValue!;
},
),
@ -428,7 +433,8 @@ class _NewWalletRecoveryPhraseWarningViewState
"I understand that Stack Wallet does not keep and cannot restore my recovery phrase, and If I lose my recovery phrase, I will not be able to access my funds.",
style: isDesktop
? STextStyles.desktopTextMedium(
context)
context,
)
: STextStyles.baseXS(context)
.copyWith(
height: 1.3,
@ -452,21 +458,23 @@ class _NewWalletRecoveryPhraseWarningViewState
.state
? () async {
try {
unawaited(showDialog<dynamic>(
context: context,
barrierDismissible: false,
useSafeArea: true,
builder: (ctx) {
return const Center(
child: LoadingIndicator(
width: 50,
height: 50,
),
);
},
));
unawaited(
showDialog<dynamic>(
context: context,
barrierDismissible: false,
useSafeArea: true,
builder: (ctx) {
return const Center(
child: LoadingIndicator(
width: 50,
height: 50,
),
);
},
),
);
String? otherDataJsonString;
if (widget.coin == Coin.tezos) {
if (widget.coin is Tezos) {
otherDataJsonString = jsonEncode({
WalletInfoKeys
.tezosDerivationPath:
@ -474,7 +482,7 @@ class _NewWalletRecoveryPhraseWarningViewState
.value,
});
// }//todo: probably not needed (broken anyways)
// else if (widget.coin == Coin.epicCash) {
// else if (widget.coin is Epiccash) {
// final int secondsSinceEpoch =
// DateTime.now().millisecondsSinceEpoch ~/ 1000;
// const int epicCashFirstBlock = 1565370278;
@ -504,8 +512,7 @@ class _NewWalletRecoveryPhraseWarningViewState
// ),
// },
// );
} else if (widget.coin ==
Coin.firo) {
} else if (widget.coin is Firo) {
otherDataJsonString = jsonEncode(
{
WalletInfoKeys
@ -524,15 +531,18 @@ class _NewWalletRecoveryPhraseWarningViewState
var node = ref
.read(
nodeServiceChangeNotifierProvider)
.getPrimaryNodeFor(coin: coin);
nodeServiceChangeNotifierProvider,
)
.getPrimaryNodeFor(
currency: coin,
);
if (node == null) {
node =
DefaultNodes.getNodeFor(coin);
node = coin.defaultNode;
await ref
.read(
nodeServiceChangeNotifierProvider)
nodeServiceChangeNotifierProvider,
)
.setPrimaryNodeFor(
coin: coin,
node: node,
@ -549,34 +559,35 @@ class _NewWalletRecoveryPhraseWarningViewState
String? mnemonic;
String? privateKey;
wordCount = Constants
.defaultSeedPhraseLengthFor(
coin: info.coin,
);
wordCount = info
.coin.defaultSeedPhraseLength;
if (coin == Coin.monero ||
coin == Coin.wownero) {
if (coin is Monero ||
coin is Wownero) {
// currently a special case due to the
// xmr/wow libraries handling their
// own mnemonic generation
} else if (wordCount > 0) {
if (ref
.read(pNewWalletOptions
.state)
.read(
pNewWalletOptions.state,
)
.state !=
null) {
if (coin
.hasMnemonicPassphraseSupport) {
mnemonicPassphrase = ref
.read(pNewWalletOptions
.state)
.read(
pNewWalletOptions.state,
)
.state!
.mnemonicPassphrase;
} else {}
wordCount = ref
.read(
pNewWalletOptions.state)
pNewWalletOptions.state,
)
.state!
.mnemonicWordsCount;
} else {
@ -587,7 +598,8 @@ class _NewWalletRecoveryPhraseWarningViewState
24 < wordCount ||
wordCount % 3 != 0) {
throw Exception(
"Invalid word count");
"Invalid word count",
);
}
final strength =
@ -604,9 +616,11 @@ class _NewWalletRecoveryPhraseWarningViewState
secureStorageInterface:
ref.read(secureStoreProvider),
nodeService: ref.read(
nodeServiceChangeNotifierProvider),
nodeServiceChangeNotifierProvider,
),
prefs: ref.read(
prefsChangeNotifierProvider),
prefsChangeNotifierProvider,
),
mnemonicPassphrase:
mnemonicPassphrase,
mnemonic: mnemonic,
@ -616,31 +630,36 @@ class _NewWalletRecoveryPhraseWarningViewState
await wallet.init();
// pop progress dialog
if (mounted) {
if (context.mounted) {
Navigator.pop(context);
}
// set checkbox back to unchecked to annoy users to agree again :P
ref
.read(
checkBoxStateProvider.state)
checkBoxStateProvider.state,
)
.state = false;
if (mounted) {
unawaited(Navigator.of(context)
.pushNamed(
NewWalletRecoveryPhraseView
.routeName,
arguments: Tuple2(
wallet,
await (wallet
as MnemonicInterface)
.getMnemonicAsWords(),
if (context.mounted) {
final nav = Navigator.of(context);
unawaited(
nav.pushNamed(
NewWalletRecoveryPhraseView
.routeName,
arguments: Tuple2(
wallet,
await (wallet
as MnemonicInterface)
.getMnemonicAsWords(),
),
),
));
);
}
} catch (e, s) {
Logging.instance.log("$e\n$s",
level: LogLevel.Fatal);
Logging.instance.log(
"$e\n$s",
level: LogLevel.Fatal,
);
// TODO: handle gracefully
// any network/socket exception here will break new wallet creation
rethrow;
@ -656,18 +675,22 @@ class _NewWalletRecoveryPhraseWarningViewState
: Theme.of(context)
.extension<StackColors>()!
.getPrimaryDisabledButtonStyle(
context),
context,
),
child: Text(
"View recovery phrase",
style: isDesktop
? ref
.read(
checkBoxStateProvider.state)
checkBoxStateProvider.state,
)
.state
? STextStyles.desktopButtonEnabled(
context)
context,
)
: STextStyles.desktopButtonDisabled(
context)
context,
)
: STextStyles.button(context),
),
),

View file

@ -24,10 +24,13 @@ import 'package:stackwallet/providers/ui/verify_recovery_phrase/mnemonic_word_co
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/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/epiccash.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/monero.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/wownero.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/date_picker/date_picker.dart';
@ -48,7 +51,7 @@ class RestoreOptionsView extends ConsumerStatefulWidget {
static const routeName = "/restoreOptions";
final String walletName;
final Coin coin;
final CryptoCurrency coin;
@override
ConsumerState<RestoreOptionsView> createState() => _RestoreOptionsViewState();
@ -56,7 +59,7 @@ class RestoreOptionsView extends ConsumerStatefulWidget {
class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
late final String walletName;
late final Coin coin;
late final CryptoCurrency coin;
late final bool isDesktop;
late TextEditingController _dateController;
@ -69,8 +72,7 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
bool hidePassword = true;
bool _expandedAdavnced = false;
bool get supportsMnemonicPassphrase =>
!(coin == Coin.monero || coin == Coin.wownero || coin == Coin.epicCash);
bool get supportsMnemonicPassphrase => coin.hasMnemonicPassphraseSupport;
@override
void initState() {
@ -153,7 +155,7 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
),
builder: (_) {
return MnemonicWordCountSelectSheet(
lengthOptions: Constants.possibleLengthsForCoin(coin),
lengthOptions: coin.possibleMnemonicLengths,
);
},
);
@ -161,9 +163,9 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType with ${coin.name} $walletName");
debugPrint("BUILD: $runtimeType with ${coin.identifier} $walletName");
final lengths = Constants.possibleLengthsForCoin(coin).toList();
final lengths = coin.possibleMnemonicLengths;
return MasterScaffold(
isDesktop: isDesktop,
@ -217,9 +219,9 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
SizedBox(
height: isDesktop ? 40 : 24,
),
if (coin == Coin.monero ||
coin == Coin.epicCash ||
(coin == Coin.wownero &&
if (coin is Monero ||
coin is Epiccash ||
(coin is Wownero &&
ref.watch(mnemonicWordCountStateProvider.state).state ==
25))
Text(
@ -233,17 +235,17 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),
if (coin == Coin.monero ||
coin == Coin.epicCash ||
(coin == Coin.wownero &&
if (coin is Monero ||
coin is Epiccash ||
(coin is Wownero &&
ref.watch(mnemonicWordCountStateProvider.state).state ==
25))
SizedBox(
height: isDesktop ? 16 : 8,
),
if (coin == Coin.monero ||
coin == Coin.epicCash ||
(coin == Coin.wownero &&
if (coin is Monero ||
coin is Epiccash ||
(coin is Wownero &&
ref.watch(mnemonicWordCountStateProvider.state).state ==
25))
if (!isDesktop)
@ -251,9 +253,9 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
onTap: chooseDate,
controller: _dateController,
),
if (coin == Coin.monero ||
coin == Coin.epicCash ||
(coin == Coin.wownero &&
if (coin is Monero ||
coin is Epiccash ||
(coin is Wownero &&
ref.watch(mnemonicWordCountStateProvider.state).state ==
25))
if (isDesktop)
@ -262,17 +264,17 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
onTap: chooseDesktopDate,
controller: _dateController,
),
if (coin == Coin.monero ||
coin == Coin.epicCash ||
(coin == Coin.wownero &&
if (coin is Monero ||
coin is Epiccash ||
(coin is Wownero &&
ref.watch(mnemonicWordCountStateProvider.state).state ==
25))
const SizedBox(
height: 8,
),
if (coin == Coin.monero ||
coin == Coin.epicCash ||
(coin == Coin.wownero &&
if (coin is Monero ||
coin is Epiccash ||
(coin is Wownero &&
ref.watch(mnemonicWordCountStateProvider.state).state ==
25))
RoundedWhiteContainer(
@ -291,9 +293,9 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
),
),
),
if (coin == Coin.monero ||
coin == Coin.epicCash ||
(coin == Coin.wownero &&
if (coin is Monero ||
coin is Epiccash ||
(coin is Wownero &&
ref.watch(mnemonicWordCountStateProvider.state).state ==
25))
SizedBox(

View file

@ -18,8 +18,8 @@ import 'package:bip39/bip39.dart' as bip39;
import 'package:bip39/src/wordlists/english.dart' as bip39wordlist;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_libmonero/monero/monero.dart';
import 'package:flutter_libmonero/wownero/wownero.dart';
import 'package:flutter_libmonero/monero/monero.dart' as libxmr;
import 'package:flutter_libmonero/wownero/wownero.dart' as libwow;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
@ -44,12 +44,16 @@ import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/custom_text_selection_controls.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/form_input_status_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.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/monero.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/wownero.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
import 'package:stackwallet/wallets/wallet/impl/monero_wallet.dart';
@ -69,7 +73,7 @@ import 'package:wakelock/wakelock.dart';
class RestoreWalletView extends ConsumerStatefulWidget {
const RestoreWalletView({
Key? key,
super.key,
required this.walletName,
required this.coin,
required this.seedWordsLength,
@ -77,12 +81,12 @@ class RestoreWalletView extends ConsumerStatefulWidget {
required this.restoreFromDate,
this.barcodeScanner = const BarcodeScannerWrapper(),
this.clipboard = const ClipboardWrapper(),
}) : super(key: key);
});
static const routeName = "/restoreWallet";
final String walletName;
final Coin coin;
final CryptoCurrency coin;
final String mnemonicPassphrase;
final int seedWordsLength;
final DateTime restoreFromDate;
@ -166,7 +170,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
@override
void dispose() {
for (var element in _controllers) {
for (final element in _controllers) {
element.dispose();
}
@ -176,13 +180,15 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
// TODO: check for wownero wordlist?
bool _isValidMnemonicWord(String word) {
// TODO: get the actual language
if (widget.coin == Coin.monero) {
var moneroWordList = monero.getMoneroWordList("English");
if (widget.coin is Monero) {
final moneroWordList = libxmr.monero.getMoneroWordList("English");
return moneroWordList.contains(word);
}
if (widget.coin == Coin.wownero) {
var wowneroWordList = wownero.getWowneroWordList("English",
seedWordsLength: widget.seedWordsLength);
if (widget.coin is Wownero) {
final wowneroWordList = libwow.wownero.getWowneroWordList(
"English",
seedWordsLength: widget.seedWordsLength,
);
return wowneroWordList.contains(word);
}
return _wordListHashSet.contains(word);
@ -201,7 +207,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
Future<void> attemptRestore() async {
if (_formKey.currentState!.validate()) {
String mnemonic = "";
for (var element in _controllers) {
for (final element in _controllers) {
mnemonic += " ${element.text.trim().toLowerCase()}";
}
mnemonic = mnemonic.trim();
@ -209,24 +215,25 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
int height = 0;
String? otherDataJsonString;
if (widget.coin == Coin.monero) {
height = monero.getHeigthByDate(date: widget.restoreFromDate);
} else if (widget.coin == Coin.wownero) {
height = wownero.getHeightByDate(date: widget.restoreFromDate);
if (widget.coin is Monero) {
height = libxmr.monero.getHeigthByDate(date: widget.restoreFromDate);
} else if (widget.coin is Wownero) {
height = libwow.wownero.getHeightByDate(date: widget.restoreFromDate);
}
// todo: wait until this implemented
// else if (widget.coin == Coin.wownero) {
// else if (widget.coin is Wownero) {
// height = wownero.getHeightByDate(date: widget.restoreFromDate);
// }
// TODO: make more robust estimate of date maybe using https://explorer.epic.tech/api-index
if (widget.coin == Coin.epicCash) {
int secondsSinceEpoch =
if (widget.coin is Epiccash) {
final int secondsSinceEpoch =
widget.restoreFromDate.millisecondsSinceEpoch ~/ 1000;
const int epicCashFirstBlock = 1565370278;
const double overestimateSecondsPerBlock = 61;
int chosenSeconds = secondsSinceEpoch - epicCashFirstBlock;
int approximateHeight = chosenSeconds ~/ overestimateSecondsPerBlock;
final int chosenSeconds = secondsSinceEpoch - epicCashFirstBlock;
final int approximateHeight =
chosenSeconds ~/ overestimateSecondsPerBlock;
//todo: check if print needed
// debugPrint(
// "approximate height: $approximateHeight chosen_seconds: $chosenSeconds");
@ -250,7 +257,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
),
},
);
} else if (widget.coin == Coin.firo) {
} else if (widget.coin is Firo) {
otherDataJsonString = jsonEncode(
{
WalletInfoKeys.lelantusCoinIsarRescanRequired: false,
@ -260,12 +267,14 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
// TODO: do actual check to make sure it is a valid mnemonic for monero
if (bip39.validateMnemonic(mnemonic) == false &&
!(widget.coin == Coin.monero || widget.coin == Coin.wownero)) {
unawaited(showFloatingFlushBar(
type: FlushBarType.warning,
message: "Invalid seed phrase!",
context: context,
));
!(widget.coin is Monero || widget.coin is Wownero)) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Invalid seed phrase!",
context: context,
),
);
} else {
if (!Platform.isLinux) await Wakelock.enable();
@ -278,30 +287,35 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
bool isRestoring = true;
// show restoring in progress
unawaited(showDialog<dynamic>(
context: context,
useSafeArea: false,
barrierDismissible: false,
builder: (context) {
return RestoringDialog(
onCancel: () async {
isRestoring = false;
await ref.read(pWallets).deleteWallet(
info,
ref.read(secureStoreProvider),
);
if (mounted) {
unawaited(
showDialog<dynamic>(
context: context,
useSafeArea: false,
barrierDismissible: false,
builder: (context) {
return RestoringDialog(
onCancel: () async {
isRestoring = false;
await ref.read(pWallets).deleteWallet(
info,
ref.read(secureStoreProvider),
);
},
);
},
);
},
));
),
);
}
var node = ref
.read(nodeServiceChangeNotifierProvider)
.getPrimaryNodeFor(coin: widget.coin);
.getPrimaryNodeFor(currency: widget.coin);
if (node == null) {
node = DefaultNodes.getNodeFor(widget.coin);
node = widget.coin.defaultNode;
await ref.read(nodeServiceChangeNotifierProvider).setPrimaryNodeFor(
coin: widget.coin,
node: node,
@ -324,15 +338,15 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
// TODO: extract interface with isRestore param
switch (wallet.runtimeType) {
case EpiccashWallet:
case const (EpiccashWallet):
await (wallet as EpiccashWallet).init(isRestore: true);
break;
case MoneroWallet:
case const (MoneroWallet):
await (wallet as MoneroWallet).init(isRestore: true);
break;
case WowneroWallet:
case const (WowneroWallet):
await (wallet as WowneroWallet).init(isRestore: true);
break;
@ -355,12 +369,11 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
if (isCreateSpecialEthWallet) {
ref.read(createSpecialEthWalletRoutingFlag.notifier).state =
false;
ref
.read(newEthWalletTriggerTempUntilHiveCompletelyDeleted.state)
.state =
ref.read(newEthWalletTriggerTempUntilHiveCompletelyDeleted.state).state =
!ref
.read(newEthWalletTriggerTempUntilHiveCompletelyDeleted
.state)
.read(
newEthWalletTriggerTempUntilHiveCompletelyDeleted.state,
)
.state;
}
@ -385,7 +398,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
(route) => false,
),
);
if (info.coin == Coin.ethereum) {
if (info.coin is Ethereum) {
unawaited(
Navigator.of(context).pushNamed(
EditWalletTokensView.routeName,
@ -451,7 +464,9 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
}
InputDecoration _getInputDecorationFor(
FormInputStatus status, String prefix) {
FormInputStatus status,
String prefix,
) {
Color color;
Color prefixColor;
Color borderColor;
@ -656,9 +671,10 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(
const Duration(milliseconds: 50));
const Duration(milliseconds: 50),
);
}
if (mounted) {
if (context.mounted) {
Navigator.of(context).pop();
}
},
@ -788,8 +804,9 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
"Paste",
style: STextStyles
.desktopButtonSmallSecondaryEnabled(
context),
)
context,
),
),
],
),
),
@ -836,12 +853,14 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
textCapitalization:
TextCapitalization.none,
key: Key(
"restoreMnemonicFormField_$i"),
"restoreMnemonicFormField_$i",
),
decoration:
_getInputDecorationFor(
_inputStatuses[
i * 4 + j - 1],
"${i * 4 + j}"),
_inputStatuses[
i * 4 + j - 1],
"${i * 4 + j}",
),
autovalidateMode:
AutovalidateMode
.onUserInteraction,
@ -861,9 +880,10 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
formInputStatus =
FormInputStatus.empty;
} else if (_isValidMnemonicWord(
value
.trim()
.toLowerCase())) {
value
.trim()
.toLowerCase(),
)) {
formInputStatus =
FormInputStatus.valid;
} else {
@ -921,17 +941,18 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
TextAlign.left,
style:
STextStyles.label(
context)
.copyWith(
context,
).copyWith(
color: Theme.of(
context)
context,
)
.extension<
StackColors>()!
.textError,
),
),
),
)
),
],
),
),
@ -945,7 +966,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
for (int i = rows * cols;
i < _seedWordCount - remainder;
i++) ...[
TableViewCell(
const TableViewCell(
flex: 1,
child: Column(
// ... (existing code for input field)
@ -965,11 +986,13 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
textCapitalization:
TextCapitalization.none,
key: Key(
"restoreMnemonicFormField_$i"),
"restoreMnemonicFormField_$i",
),
decoration:
_getInputDecorationFor(
_inputStatuses[i],
"${i + 1}"),
_inputStatuses[i],
"${i + 1}",
),
autovalidateMode:
AutovalidateMode
.onUserInteraction,
@ -984,9 +1007,10 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
formInputStatus =
FormInputStatus.empty;
} else if (_isValidMnemonicWord(
value
.trim()
.toLowerCase())) {
value
.trim()
.toLowerCase(),
)) {
formInputStatus =
FormInputStatus.valid;
} else {
@ -1029,17 +1053,18 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
TextAlign.left,
style:
STextStyles.label(
context)
.copyWith(
context,
).copyWith(
color: Theme.of(
context)
context,
)
.extension<
StackColors>()!
.textError,
),
),
),
)
),
],
),
),
@ -1095,7 +1120,9 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
textCapitalization: TextCapitalization.none,
key: Key("restoreMnemonicFormField_$i"),
decoration: _getInputDecorationFor(
_inputStatuses[i - 1], "$i"),
_inputStatuses[i - 1],
"$i",
),
autovalidateMode:
AutovalidateMode.onUserInteraction,
selectionControls:
@ -1107,7 +1134,8 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
if (value.isEmpty) {
formInputStatus = FormInputStatus.empty;
} else if (_isValidMnemonicWord(
value.trim().toLowerCase())) {
value.trim().toLowerCase(),
)) {
formInputStatus = FormInputStatus.valid;
} else {
formInputStatus =
@ -1155,7 +1183,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
),
),
),
)
),
],
),
Padding(

View file

@ -70,7 +70,7 @@ class _SelectWalletForTokenViewState
ref.read(createSpecialEthWalletRoutingFlag.notifier).state = true;
Navigator.of(context).pushNamed(
CreateOrRestoreWalletView.routeName,
arguments: CoinEntity(widget.entity.coin),
arguments: CoinEntity(widget.entity.cryptoCurrency),
);
}
@ -78,7 +78,7 @@ class _SelectWalletForTokenViewState
Widget build(BuildContext context) {
final ethWalletInfos = ref
.watch(pAllWalletsInfo)
.where((e) => e.coin == widget.entity.coin)
.where((e) => e.coin == widget.entity.cryptoCurrency)
.toList();
final _hasEthWallets = ethWalletInfos.isNotEmpty;

View file

@ -30,9 +30,9 @@ 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/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/ethereum.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -44,10 +44,10 @@ final createSpecialEthWalletRoutingFlag = StateProvider((ref) => false);
class VerifyRecoveryPhraseView extends ConsumerStatefulWidget {
const VerifyRecoveryPhraseView({
Key? key,
super.key,
required this.wallet,
required this.mnemonic,
}) : super(key: key);
});
static const routeName = "/verifyRecoveryPhrase";
@ -154,7 +154,7 @@ class _VerifyRecoveryPhraseViewState
DesktopHomeView.routeName,
),
);
if (widget.wallet.info.coin == Coin.ethereum) {
if (widget.wallet.info.coin is Ethereum) {
unawaited(
Navigator.of(context).pushNamed(
EditWalletTokensView.routeName,
@ -177,7 +177,7 @@ class _VerifyRecoveryPhraseViewState
(route) => false,
),
);
if (widget.wallet.info.coin == Coin.ethereum) {
if (widget.wallet.info.coin is Ethereum) {
unawaited(
Navigator.of(context).pushNamed(
EditWalletTokensView.routeName,
@ -198,12 +198,14 @@ class _VerifyRecoveryPhraseViewState
);
}
} else {
unawaited(showFloatingFlushBar(
type: FlushBarType.warning,
message: "Incorrect. Please try again.",
iconAsset: Assets.svg.circleX,
context: context,
));
unawaited(
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Incorrect. Please try again.",
iconAsset: Assets.svg.circleX,
context: context,
),
);
final int next = Random().nextInt(_mnemonic.length);
ref
@ -221,7 +223,10 @@ class _VerifyRecoveryPhraseViewState
}
Tuple2<List<String>, String> randomize(
List<String> mnemonic, int chosenIndex, int wordsToShow) {
List<String> mnemonic,
int chosenIndex,
int wordsToShow,
) {
final List<String> remaining = [];
final String chosenWord = mnemonic[chosenIndex];
@ -354,7 +359,8 @@ class _VerifyRecoveryPhraseViewState
.extension<StackColors>()!
.textFieldDefaultBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius),
Constants.size.circularBorderRadius,
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
@ -391,11 +397,13 @@ class _VerifyRecoveryPhraseViewState
builder: (_, ref, __) {
final selectedWord = ref
.watch(
verifyMnemonicSelectedWordStateProvider.state)
verifyMnemonicSelectedWordStateProvider.state,
)
.state;
final correctWord = ref
.watch(
verifyMnemonicCorrectWordStateProvider.state)
verifyMnemonicCorrectWordStateProvider.state,
)
.state;
return ConstrainedBox(
@ -406,7 +414,8 @@ class _VerifyRecoveryPhraseViewState
onPressed: selectedWord.isNotEmpty
? () async {
await _continue(
correctWord == selectedWord);
correctWord == selectedWord,
);
}
: null,
style: selectedWord.isNotEmpty
@ -421,9 +430,11 @@ class _VerifyRecoveryPhraseViewState
"Verify",
style: selectedWord.isNotEmpty
? STextStyles.desktopButtonEnabled(
context)
context,
)
: STextStyles.desktopButtonDisabled(
context),
context,
),
)
: Text(
"Continue",

View file

@ -20,12 +20,14 @@ import 'package:stackwallet/providers/db/main_db_provider.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_book_filter_provider.dart';
import 'package:stackwallet/supported_coins.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/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
import 'package:stackwallet/widgets/address_book_card.dart';
import 'package:stackwallet/widgets/background.dart';
@ -45,7 +47,7 @@ class AddressBookView extends ConsumerStatefulWidget {
static const String routeName = "/addressBook";
final Coin? coin;
final CryptoCurrency? coin;
final String? filterTerm;
@override
@ -65,8 +67,10 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
ref.refresh(addressBookFilterProvider);
if (widget.coin == null) {
final List<Coin> coins = Coin.values.toList();
coins.remove(Coin.firoTestNet);
final coins = [...SupportedCoins.cryptocurrencies];
coins.removeWhere(
(e) => e is Firo && e.network == CryptoCurrencyNetwork.test,
);
final bool showTestNet =
ref.read(prefsChangeNotifierProvider).showTestNetCoins;
@ -74,9 +78,10 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
if (showTestNet) {
ref.read(addressBookFilterProvider).addAll(coins, false);
} else {
ref
.read(addressBookFilterProvider)
.addAll(coins.where((e) => !e.isTestNet), false);
ref.read(addressBookFilterProvider).addAll(
coins.where((e) => e.network != CryptoCurrencyNetwork.test),
false,
);
}
} else {
ref.read(addressBookFilterProvider).add(widget.coin!, false);
@ -101,7 +106,7 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
addresses.add(
ContactAddressEntry()
..coinName = wallet.info.coin.name
..coinName = wallet.info.coin.identifier
..address = addressString
..label = "Current Receiving"
..other = wallet.info.name,

View file

@ -12,10 +12,12 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_book_filter_provider.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -25,7 +27,7 @@ import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class AddressBookFilterView extends ConsumerStatefulWidget {
const AddressBookFilterView({Key? key}) : super(key: key);
const AddressBookFilterView({super.key});
static const String routeName = "/addressBookFilter";
@ -35,19 +37,23 @@ class AddressBookFilterView extends ConsumerStatefulWidget {
}
class _AddressBookFilterViewState extends ConsumerState<AddressBookFilterView> {
late final List<Coin> _coins;
late final List<CryptoCurrency> _coins;
@override
void initState() {
List<Coin> coins = [...Coin.values];
coins.remove(Coin.firoTestNet);
final coins = [...SupportedCoins.cryptocurrencies];
coins.removeWhere(
(e) => e is Firo && e.network == CryptoCurrencyNetwork.test,
);
bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;
final showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins;
if (showTestNet) {
_coins = coins.toList(growable: false);
} else {
_coins = coins.where((e) => !e.isTestNet).toList(growable: false);
_coins = coins
.where((e) => e.network != CryptoCurrencyNetwork.test)
.toList(growable: false);
}
super.initState();
}

View file

@ -14,20 +14,24 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/themes/coin_image_provider.dart';
import 'package:stackwallet/themes/stack_colors.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/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
class CoinSelectSheet extends StatelessWidget {
const CoinSelectSheet({Key? key}) : super(key: key);
const CoinSelectSheet({super.key});
@override
Widget build(BuildContext context) {
final maxHeight = MediaQuery.of(context).size.height * 0.60;
var coins_ = [...Coin.values];
coins_.remove(Coin.firoTestNet);
final coins_ = [...SupportedCoins.cryptocurrencies];
coins_.removeWhere(
(e) => e is Firo && e.network == CryptoCurrencyNetwork.test,
);
return Container(
decoration: BoxDecoration(
color: Theme.of(context).extension<StackColors>()!.popupBG,
@ -85,7 +89,11 @@ class CoinSelectSheet extends StatelessWidget {
shrinkWrap: true,
itemCount: showTestNet
? coins_.length
: coins_.where((e) => !e.isTestNet).length,
: coins_
.where(
(e) => e.network != CryptoCurrencyNetwork.test,
)
.length,
itemBuilder: (builderContext, index) {
final coin = coins_[index];
return Padding(

View file

@ -27,7 +27,6 @@ import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.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';
@ -41,10 +40,10 @@ import 'package:tuple/tuple.dart';
class ContactDetailsView extends ConsumerStatefulWidget {
const ContactDetailsView({
Key? key,
super.key,
required this.contactId,
this.clipboard = const ClipboardWrapper(),
}) : super(key: key);
});
static const String routeName = "/contactDetails";
@ -79,7 +78,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
.sortByTimestampDesc()
.findAll();
List<Tuple2<String, Transaction>> result = [];
final List<Tuple2<String, Transaction>> result = [];
for (final tx in transactions) {
result.add(Tuple2(tx.walletId, tx));
@ -151,7 +150,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
height: 20,
),
onPressed: () {
bool isFavorite = _contact.isFavorite;
final bool isFavorite = _contact.isFavorite;
ref.read(addressBookServiceProvider).editContact(
_contact.copyWith(isFavorite: !isFavorite));

View file

@ -27,7 +27,6 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
@ -56,8 +55,8 @@ class ContactPopUp extends ConsumerWidget {
final active = ref.read(currentWalletIdProvider);
bool hasActiveWallet = active != null;
bool isExchangeFlow =
final bool hasActiveWallet = active != null;
final bool isExchangeFlow =
ref.watch(exchangeFlowIsActiveStateProvider.state).state;
final addresses = contact.addressesSorted.where((e) {

View file

@ -19,6 +19,7 @@ import 'package:stackwallet/pages/address_book_views/subviews/coin_select_sheet.
import 'package:stackwallet/providers/providers.dart';
// import 'package:stackwallet/providers/global/should_show_lockscreen_on_resume_state_provider.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.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/address_utils.dart';
@ -26,10 +27,11 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
@ -62,7 +64,7 @@ class _NewContactAddressEntryFormState
late final FocusNode addressLabelFocusNode;
late final FocusNode addressFocusNode;
List<Coin> coins = [];
List<CryptoCurrency> coins = [];
@override
void initState() {
@ -72,7 +74,7 @@ class _NewContactAddressEntryFormState
..text = ref.read(addressEntryDataProvider(widget.id)).address ?? "";
addressLabelFocusNode = FocusNode();
addressFocusNode = FocusNode();
coins = [...Coin.values];
coins = [...SupportedCoins.cryptocurrencies];
super.initState();
}
@ -88,15 +90,20 @@ class _NewContactAddressEntryFormState
@override
Widget build(BuildContext context) {
final isDesktop = Util.isDesktop;
bool showTestNet = ref.watch(
prefsChangeNotifierProvider.select((value) => value.showTestNetCoins),
);
if (isDesktop) {
coins = [...Coin.values];
coins = [...SupportedCoins.cryptocurrencies];
coins.removeWhere(
(e) => e is Firo && e.network == CryptoCurrencyNetwork.test,
);
coins.remove(Coin.firoTestNet);
final showTestNet =
ref.read(prefsChangeNotifierProvider).showTestNetCoins;
if (showTestNet) {
coins = coins.where((e) => !e.isTestNet).toList();
coins = coins.toList();
} else {
coins = coins
.where((e) => e.network != CryptoCurrencyNetwork.test)
.toList();
}
}
@ -104,7 +111,7 @@ class _NewContactAddressEntryFormState
children: [
if (isDesktop)
DropdownButtonHideUnderline(
child: DropdownButton2<Coin>(
child: DropdownButton2<CryptoCurrency>(
hint: Text(
"Select cryptocurrency",
style: STextStyles.fieldLabel(context),
@ -128,10 +135,12 @@ class _NewContactAddressEntryFormState
),
),
isExpanded: true,
value: ref.watch(addressEntryDataProvider(widget.id)
.select((value) => value.coin)),
value: ref.watch(
addressEntryDataProvider(widget.id)
.select((value) => value.coin),
),
onChanged: (value) {
if (value is Coin) {
if (value is CryptoCurrency) {
ref.read(addressEntryDataProvider(widget.id)).coin = value;
}
},
@ -145,7 +154,7 @@ class _NewContactAddressEntryFormState
),
items: [
...coins.map(
(coin) => DropdownMenuItem<Coin>(
(coin) => DropdownMenuItem<CryptoCurrency>(
value: coin,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
@ -205,7 +214,7 @@ class _NewContactAddressEntryFormState
context: context,
builder: (_) => const CoinSelectSheet(),
).then((value) {
if (value is Coin) {
if (value is CryptoCurrency) {
ref.read(addressEntryDataProvider(widget.id)).coin =
value;
}
@ -214,8 +223,10 @@ class _NewContactAddressEntryFormState
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ref.watch(addressEntryDataProvider(widget.id)
.select((value) => value.coin)) ==
ref.watch(
addressEntryDataProvider(widget.id)
.select((value) => value.coin),
) ==
null
? Text(
"Select cryptocurrency",
@ -245,8 +256,9 @@ class _NewContactAddressEntryFormState
Text(
ref
.watch(
addressEntryDataProvider(widget.id)
.select((value) => value.coin))!
addressEntryDataProvider(widget.id)
.select((value) => value.coin),
)!
.prettyName,
style: STextStyles.itemSubtitle12(context),
),
@ -335,8 +347,10 @@ class _NewContactAddressEntryFormState
suffixIcon: UnconstrainedBox(
child: Row(
children: [
if (ref.watch(addressEntryDataProvider(widget.id)
.select((value) => value.address)) !=
if (ref.watch(
addressEntryDataProvider(widget.id)
.select((value) => value.address),
) !=
null)
TextFieldIconButton(
key: const Key("addAddressBookClearAddressButtonKey"),
@ -348,8 +362,10 @@ class _NewContactAddressEntryFormState
},
child: const XIcon(),
),
if (ref.watch(addressEntryDataProvider(widget.id)
.select((value) => value.address)) ==
if (ref.watch(
addressEntryDataProvider(widget.id)
.select((value) => value.address),
) ==
null)
TextFieldIconButton(
key: const Key("addAddressPasteAddressButtonKey"),
@ -372,8 +388,10 @@ class _NewContactAddressEntryFormState
child: const ClipboardIcon(),
),
if (!Util.isDesktop &&
ref.watch(addressEntryDataProvider(widget.id)
.select((value) => value.address)) ==
ref.watch(
addressEntryDataProvider(widget.id)
.select((value) => value.address),
) ==
null)
TextFieldIconButton(
key: const Key("addAddressBookEntryScanQrButtonKey"),
@ -419,11 +437,12 @@ class _NewContactAddressEntryFormState
.read(addressEntryDataProvider(widget.id))
.coin !=
null) {
if (AddressUtils.validateAddress(
qrResult.rawContent,
ref
.read(addressEntryDataProvider(widget.id))
.coin!)) {
if (ref
.read(addressEntryDataProvider(widget.id))
.coin!
.validateAddress(
qrResult.rawContent,
)) {
addressController.text = qrResult.rawContent;
ref
.read(addressEntryDataProvider(widget.id))
@ -436,8 +455,9 @@ class _NewContactAddressEntryFormState
// .state)
// .state = true;
Logging.instance.log(
"Failed to get camera permissions to scan address qr code: $e\n$s",
level: LogLevel.Warning);
"Failed to get camera permissions to scan address qr code: $e\n$s",
level: LogLevel.Warning,
);
}
},
child: const QrCodeIcon(),
@ -466,8 +486,10 @@ class _NewContactAddressEntryFormState
},
),
),
if (!ref.watch(addressEntryDataProvider(widget.id)
.select((value) => value.isValidAddress)) &&
if (!ref.watch(
addressEntryDataProvider(widget.id)
.select((value) => value.isValidAddress),
) &&
addressController.text.isNotEmpty)
Row(
children: [

View file

@ -30,16 +30,17 @@ import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/buy/buy_response.dart';
import 'package:stackwallet/services/buy/simplex/simplex_api.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
@ -58,14 +59,14 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart';
class BuyForm extends ConsumerStatefulWidget {
const BuyForm({
Key? key,
super.key,
this.coin,
this.tokenContract,
this.clipboard = const ClipboardWrapper(),
this.scanner = const BarcodeScannerWrapper(),
}) : super(key: key);
});
final Coin? coin;
final CryptoCurrency? coin;
final ClipboardInterface clipboard;
final BarcodeScannerInterface scanner;
@ -76,7 +77,7 @@ class BuyForm extends ConsumerStatefulWidget {
}
class _BuyFormState extends ConsumerState<BuyForm> {
late final Coin? coin;
late final CryptoCurrency? coin;
late final ClipboardInterface clipboard;
late final BarcodeScannerInterface scanner;
@ -249,7 +250,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
],
),
);
})
},
)
: await Navigator.of(context).push(
MaterialPageRoute<dynamic>(
builder: (_) => CryptoSelectionView(
@ -386,7 +388,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
],
),
);
})
},
)
: await Navigator.of(context).push(
MaterialPageRoute<dynamic>(
builder: (_) => FiatSelectionView(
@ -410,7 +413,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
if (ticker == null) return false;
try {
coinFromTickerCaseInsensitive(ticker);
SupportedCoins.getCryptoCurrencyForTicker(ticker);
return true;
} on ArgumentError catch (_) {
return false;
@ -501,7 +504,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
),
),
],
)
),
],
),
),
@ -517,9 +520,10 @@ class _BuyFormState extends ConsumerState<BuyForm> {
child: Text(
"Ok",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
onPressed: () {
Navigator.of(context).pop();
@ -589,7 +593,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
),
),
],
)
),
],
),
),
@ -606,9 +610,10 @@ class _BuyFormState extends ConsumerState<BuyForm> {
child: Text(
"Ok",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
onPressed: () {
Navigator.of(context).pop();
@ -701,7 +706,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
],
),
);
})
},
)
: await Navigator.of(context).push(
MaterialPageRoute<dynamic>(
builder: (_) => BuyQuotePreviewView(
@ -742,7 +748,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
Fiat.fromJson({'ticker': 'USD', 'name': 'United States Dollar'});
selectedCrypto = Crypto.fromJson({
'ticker': widget.coin?.ticker ?? 'BTC',
'name': widget.coin?.prettyName ?? 'Bitcoin'
'name': widget.coin?.prettyName ?? 'Bitcoin',
});
// THIS IS BAD. No way to be certain the simplex ticker points to the same
@ -907,7 +913,9 @@ class _BuyFormState extends ConsumerState<BuyForm> {
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(
vertical: 3, horizontal: 6),
vertical: 3,
horizontal: 6,
),
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
@ -916,12 +924,14 @@ class _BuyFormState extends ConsumerState<BuyForm> {
),
child: Text(
format.simpleCurrencySymbol(
selectedFiat?.ticker ?? "ERR".toUpperCase()),
selectedFiat?.ticker ?? "ERR".toUpperCase(),
),
textAlign: TextAlign.center,
style: STextStyles.smallMed12(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
),
const SizedBox(
@ -976,7 +986,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
});
validateAmount();
},
)
),
],
),
SizedBox(
@ -1026,47 +1036,53 @@ class _BuyFormState extends ConsumerState<BuyForm> {
fit: BoxFit.scaleDown,
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(children: [
const SizedBox(width: 2),
buyWithFiat
? Container(
padding: const EdgeInsets.symmetric(
vertical: 3, horizontal: 6),
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.currencyListItemBG,
borderRadius: BorderRadius.circular(4),
),
child: Text(
format.simpleCurrencySymbol(
selectedFiat?.ticker.toUpperCase() ??
"ERR"),
textAlign: TextAlign.center,
style: STextStyles.smallMed12(context).copyWith(
child: Row(
children: [
const SizedBox(width: 2),
buyWithFiat
? Container(
padding: const EdgeInsets.symmetric(
vertical: 3,
horizontal: 6,
),
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.currencyListItemBG,
borderRadius: BorderRadius.circular(4),
),
child: Text(
format.simpleCurrencySymbol(
selectedFiat?.ticker.toUpperCase() ?? "ERR",
),
textAlign: TextAlign.center,
style:
STextStyles.smallMed12(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
.accentColorDark,
),
),
)
: CoinIconForTicker(
ticker: selectedCrypto?.ticker ?? "BTC",
size: 20,
),
)
: CoinIconForTicker(
ticker: selectedCrypto?.ticker ?? "BTC",
size: 20,
),
SizedBox(
width: buyWithFiat
? 8
: 10), // maybe make isDesktop-aware?
Text(
buyWithFiat
? selectedFiat?.ticker ?? "ERR"
: selectedCrypto?.ticker ?? "ERR",
style: STextStyles.smallMed14(context).copyWith(
SizedBox(
width: buyWithFiat ? 8 : 10,
), // maybe make isDesktop-aware?
Text(
buyWithFiat
? selectedFiat?.ticker ?? "ERR"
: selectedCrypto?.ticker ?? "ERR",
style: STextStyles.smallMed14(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
]),
.accentColorDark,
),
),
],
),
),
),
suffixIcon: Padding(
@ -1078,7 +1094,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
_buyAmountController.text.isNotEmpty
? TextFieldIconButton(
key: const Key(
"buyViewClearAmountFieldButtonKey"),
"buyViewClearAmountFieldButtonKey",
),
onTap: () {
// if (_BuyFormState.buyWithFiat) {
// _buyAmountController.text = _BuyFormState
@ -1099,7 +1116,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
)
: TextFieldIconButton(
key: const Key(
"buyViewPasteAddressFieldButtonKey"),
"buyViewPasteAddressFieldButtonKey",
),
onTap: () async {
final ClipboardData? data = await clipboard
.getData(Clipboard.kTextPlain);
@ -1150,7 +1168,7 @@ class _BuyFormState extends ConsumerState<BuyForm> {
text: "Choose from Stack",
onTap: () {
try {
final coin = coinFromTickerCaseInsensitive(
final coin = SupportedCoins.getCryptoCurrencyForTicker(
selectedCrypto!.ticker,
);
Navigator.of(context)
@ -1236,7 +1254,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
_addressToggleFlag
? TextFieldIconButton(
key: const Key(
"buyViewClearAddressFieldButtonKey"),
"buyViewClearAddressFieldButtonKey",
),
onTap: () {
_receiveAddressController.text = "";
_address = "";
@ -1248,7 +1267,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
)
: TextFieldIconButton(
key: const Key(
"buyViewPasteAddressFieldButtonKey"),
"buyViewPasteAddressFieldButtonKey",
),
onTap: () async {
final ClipboardData? data = await clipboard
.getData(Clipboard.kTextPlain);
@ -1257,7 +1277,9 @@ class _BuyFormState extends ConsumerState<BuyForm> {
String content = data.text!.trim();
if (content.contains("\n")) {
content = content.substring(
0, content.indexOf("\n"));
0,
content.indexOf("\n"),
);
}
_receiveAddressController.text = content;
@ -1300,7 +1322,8 @@ class _BuyFormState extends ConsumerState<BuyForm> {
child: Text(
"Address book",
style: STextStyles.desktopH3(
context),
context,
),
),
),
const DesktopDialogCloseButton(),
@ -1308,9 +1331,15 @@ class _BuyFormState extends ConsumerState<BuyForm> {
),
Expanded(
child: AddressBookAddressChooser(
coin: coinFromTickerCaseInsensitive(
selectedCrypto!.ticker
.toString()),
coin: SupportedCoins
.cryptocurrencies
.firstWhere(
(e) =>
e.ticker.toLowerCase() ==
selectedCrypto!.ticker
.toString()
.toLowerCase(),
),
),
),
],
@ -1352,21 +1381,25 @@ class _BuyFormState extends ConsumerState<BuyForm> {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(
const Duration(milliseconds: 75));
const Duration(milliseconds: 75),
);
}
final qrResult = await scanner.scan();
Logging.instance.log(
"qrResult content: ${qrResult.rawContent}",
level: LogLevel.Info);
"qrResult content: ${qrResult.rawContent}",
level: LogLevel.Info,
);
final results = AddressUtils.parseUri(
qrResult.rawContent);
qrResult.rawContent,
);
Logging.instance.log(
"qrResult parsed: $results",
level: LogLevel.Info);
"qrResult parsed: $results",
level: LogLevel.Info,
);
if (results.isNotEmpty) {
// auto fill address

View file

@ -12,21 +12,21 @@ import 'package:flutter/material.dart';
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/pages/buy_view/buy_view.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
class BuyInWalletView extends StatefulWidget {
const BuyInWalletView({
Key? key,
super.key,
required this.coin,
this.contract,
}) : super(key: key);
});
static const String routeName = "/stackBuyInWalletView";
final Coin? coin;
final CryptoCurrency? coin;
final EthContract? contract;
@override
@ -34,7 +34,7 @@ class BuyInWalletView extends StatefulWidget {
}
class _BuyInWalletViewState extends State<BuyInWalletView> {
late final Coin? coin;
late final CryptoCurrency? coin;
@override
Widget build(BuildContext context) {

View file

@ -15,18 +15,18 @@ import 'package:stackwallet/pages/buy_view/buy_form.dart';
import 'package:stackwallet/services/event_bus/events/global/tor_connection_status_changed_event.dart';
import 'package:stackwallet/services/tor_service.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:stackwallet/widgets/tor_subscription.dart';
class BuyView extends ConsumerStatefulWidget {
const BuyView({
Key? key,
super.key,
this.coin,
this.tokenContract,
}) : super(key: key);
});
final Coin? coin;
final CryptoCurrency? coin;
final EthContract? tokenContract;
static const String routeName = "/stackBuyView";
@ -36,7 +36,7 @@ class BuyView extends ConsumerStatefulWidget {
}
class _BuyViewState extends ConsumerState<BuyView> {
Coin? coin;
CryptoCurrency? coin;
EthContract? tokenContract;
late bool torEnabled;

View file

@ -14,11 +14,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/buy/response_objects/crypto.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/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
@ -53,9 +53,11 @@ class _CryptoSelectionViewState extends ConsumerState<CryptoSelectionView> {
void filter(String text) {
setState(() {
_coins = [
...coins.where((e) =>
e.name.toLowerCase().contains(text.toLowerCase()) ||
e.ticker.toLowerCase().contains(text.toLowerCase()))
...coins.where(
(e) =>
e.name.toLowerCase().contains(text.toLowerCase()) ||
e.ticker.toLowerCase().contains(text.toLowerCase()),
),
];
});
}
@ -66,10 +68,12 @@ class _CryptoSelectionViewState extends ConsumerState<CryptoSelectionView> {
coins = [...widget.coins];
coins.sort(
(a, b) => a.ticker.toLowerCase().compareTo(b.ticker.toLowerCase()));
for (Coin coin in Coin.values.reversed) {
int index = coins.indexWhere((element) =>
element.ticker.toLowerCase() == coin.ticker.toLowerCase());
(a, b) => a.ticker.toLowerCase().compareTo(b.ticker.toLowerCase()),
);
for (final coin in SupportedCoins.cryptocurrencies.reversed) {
final index = coins.indexWhere(
(element) => element.ticker.toLowerCase() == coin.ticker.toLowerCase(),
);
if (index > 0) {
final currency = coins.removeAt(index);
coins.insert(0, currency);
@ -104,7 +108,8 @@ class _CryptoSelectionViewState extends ConsumerState<CryptoSelectionView> {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(
const Duration(milliseconds: 50));
const Duration(milliseconds: 50),
);
}
if (mounted) {
Navigator.of(context).pop();
@ -265,7 +270,7 @@ bool isStackCoin(String? ticker) {
if (ticker == null) return false;
try {
coinFromTickerCaseInsensitive(ticker);
SupportedCoins.getCryptoCurrencyForTicker(ticker);
return true;
} on ArgumentError catch (_) {
return false;
@ -289,10 +294,10 @@ bool isStackCoin(String? ticker) {
/// caller must ensure [Coin] for ticker exists
class CoinIconForTicker extends ConsumerWidget {
const CoinIconForTicker({
Key? key,
super.key,
required this.ticker,
required this.size,
}) : super(key: key);
});
final String ticker;
final double size;
@ -300,7 +305,7 @@ class CoinIconForTicker extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
try {
final coin = coinFromTickerCaseInsensitive(ticker);
final coin = SupportedCoins.getCryptoCurrencyForTicker(ticker);
return SvgPicture.file(
File(
ref.watch(coinIconProvider(coin)),
@ -321,7 +326,7 @@ class CoinIconForTicker extends ConsumerWidget {
// }) {
// String? iconAsset = /*isStackCoin(ticker)
// ?*/
// Assets.svg.iconFor(coin: coinFromTickerCaseInsensitive(ticker));
// Assets.svg.iconFor(coin: SupportedCoins.getCryptoCurrencyForTicker(ticker));
// // : Assets.svg.buyIconFor(ticker);
// return (iconAsset != null)
// ? SvgPicture.asset(iconAsset, height: size, width: size)

View file

@ -23,8 +23,8 @@ import 'package:stackwallet/providers/global/wallets_provider.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/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart';
import 'package:stackwallet/widgets/background.dart';
@ -56,7 +56,7 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
late final FocusNode portFocusNode;
late final TextEditingController fusionRoundController;
late final FocusNode fusionRoundFocusNode;
late final Coin coin;
late final CryptoCurrency coin;
bool _enableSSLCheckbox = false;
bool _enableStartButton = false;

View file

@ -17,10 +17,10 @@ import 'package:stackwallet/providers/cash_fusion/fusion_progress_ui_state_provi
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart';
import 'package:stackwallet/widgets/background.dart';
@ -44,7 +44,7 @@ class FusionProgressView extends ConsumerStatefulWidget {
}
class _FusionProgressViewState extends ConsumerState<FusionProgressView> {
late final Coin coin;
late final CryptoCurrency coin;
Future<bool> _requestAndProcessCancel() async {
final shouldCancel = await showDialog<bool?>(

View file

@ -24,7 +24,6 @@ import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.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/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart';
@ -49,12 +48,12 @@ enum CoinControlViewType {
class CoinControlView extends ConsumerStatefulWidget {
const CoinControlView({
Key? key,
super.key,
required this.walletId,
required this.type,
this.requestedTotal,
this.selectedUTXOs,
}) : super(key: key);
});
static const routeName = "/coinControl";
@ -128,7 +127,7 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
filter: CCFilter.all,
sort: _sort,
searchTerm: "",
coin: coin,
cryptoCurrency: coin,
);
} else {
_map = null;
@ -141,7 +140,7 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
: CCFilter.available,
sort: _sort,
searchTerm: _isSearching ? searchController.text : "",
coin: coin,
cryptoCurrency: coin,
);
}
@ -682,7 +681,7 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
);
final selectedSum =
selectedSumInt.toAmountAsRaw(
fractionDigits: coin.decimals,
fractionDigits: coin.fractionDigits,
);
return Text(
ref

View file

@ -17,7 +17,6 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.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/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
@ -26,14 +25,14 @@ import 'package:stackwallet/widgets/rounded_container.dart';
class UtxoCard extends ConsumerStatefulWidget {
const UtxoCard({
Key? key,
super.key,
required this.utxo,
required this.walletId,
required this.onSelectedChanged,
required this.initialSelectedState,
required this.canSelect,
this.onPressed,
}) : super(key: key);
});
final String walletId;
final UTXO utxo;
@ -138,7 +137,7 @@ class _UtxoCardState extends ConsumerState<UtxoCard> {
Text(
ref.watch(pAmountFormatter(coin)).format(
utxo.value.toAmountAsRaw(
fractionDigits: coin.decimals,
fractionDigits: coin.fractionDigits,
),
),
style: STextStyles.w600_14(context),

View file

@ -20,7 +20,6 @@ import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
@ -37,10 +36,10 @@ import 'package:stackwallet/widgets/rounded_container.dart';
class UtxoDetailsView extends ConsumerStatefulWidget {
const UtxoDetailsView({
Key? key,
super.key,
required this.utxoId,
required this.walletId,
}) : super(key: key);
});
static const routeName = "/utxoDetails";
@ -244,7 +243,7 @@ class _UtxoDetailsViewState extends ConsumerState<UtxoDetailsView> {
Text(
ref.watch(pAmountFormatter(coin)).format(
utxo!.value.toAmountAsRaw(
fractionDigits: coin.decimals,
fractionDigits: coin.fractionDigits,
),
),
style: STextStyles.pageTitleH2(context),

View file

@ -13,8 +13,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/stack_colors.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/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -24,11 +24,11 @@ import 'package:stackwallet/widgets/wallet_info_row/sub_widgets/wallet_info_row_
class ChooseFromStackView extends ConsumerStatefulWidget {
const ChooseFromStackView({
Key? key,
super.key,
required this.coin,
}) : super(key: key);
});
final Coin coin;
final CryptoCurrency coin;
static const String routeName = "/chooseFromStack";
@ -38,7 +38,7 @@ class ChooseFromStackView extends ConsumerStatefulWidget {
}
class _ChooseFromStackViewState extends ConsumerState<ChooseFromStackView> {
late final Coin coin;
late final CryptoCurrency coin;
@override
void initState() {

View file

@ -26,7 +26,6 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
@ -47,14 +46,14 @@ import 'package:uuid/uuid.dart';
class ConfirmChangeNowSendView extends ConsumerStatefulWidget {
const ConfirmChangeNowSendView({
Key? key,
super.key,
required this.txData,
required this.walletId,
this.routeOnSuccessName = WalletView.routeName,
required this.trade,
this.shouldSendPublicFiroFunds,
this.fromDesktopStep4 = false,
}) : super(key: key);
});
static const String routeName = "/confirmChangeNowSend";

View file

@ -22,10 +22,10 @@ import 'package:stackwallet/services/exchange/exchange.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
import 'package:stackwallet/services/exchange/trocador/trocador_exchange.dart';
import 'package:stackwallet/supported_coins.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/prefs.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
@ -143,7 +143,8 @@ class _ExchangeCurrencySelectionViewState
onPressed: () async {
Navigator.of(context, rootNavigator: isDesktop).pop();
_currencies = await _showUpdatingCurrencies(
whileFuture: _loadCurrencies());
whileFuture: _loadCurrencies(),
);
setState(() {});
},
),
@ -164,15 +165,17 @@ class _ExchangeCurrencySelectionViewState
.filter()
.isFiatEqualTo(false)
.and()
.group((q) => widget.isFixedRate
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated))
.group(
(q) => widget.isFixedRate
? q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.fixed)
: q
.rateTypeEqualTo(SupportedRateType.both)
.or()
.rateTypeEqualTo(SupportedRateType.estimated),
)
.sortByIsStackCoin()
.thenByName()
.findAll();
@ -180,9 +183,10 @@ class _ExchangeCurrencySelectionViewState
// If using Tor, filter exchanges which do not support Tor.
if (Prefs.instance.useTor) {
if (Exchange.exchangeNamesWithTorSupport.isNotEmpty) {
currencies.removeWhere((element) => !Exchange
.exchangeNamesWithTorSupport
.contains(element.exchangeName));
currencies.removeWhere(
(element) => !Exchange.exchangeNamesWithTorSupport
.contains(element.exchangeName),
);
}
}
@ -193,7 +197,8 @@ class _ExchangeCurrencySelectionViewState
final List<Currency> distinctCurrencies = [];
for (final currency in currencies) {
if (!distinctCurrencies.any(
(e) => e.ticker.toLowerCase() == currency.ticker.toLowerCase())) {
(e) => e.ticker.toLowerCase() == currency.ticker.toLowerCase(),
)) {
distinctCurrencies.add(currency);
}
}
@ -207,23 +212,29 @@ class _ExchangeCurrencySelectionViewState
}
return _currencies
.where((e) =>
e.name.toLowerCase().contains(text.toLowerCase()) ||
e.ticker.toLowerCase().contains(text.toLowerCase()))
.where(
(e) =>
e.name.toLowerCase().contains(text.toLowerCase()) ||
e.ticker.toLowerCase().contains(text.toLowerCase()),
)
.toList();
} else {
if (text.isEmpty) {
return _currencies
.where((e) =>
e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase())
.where(
(e) =>
e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase(),
)
.toList();
}
return _currencies
.where((e) =>
e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase() &&
(e.name.toLowerCase().contains(text.toLowerCase()) ||
e.ticker.toLowerCase().contains(text.toLowerCase())))
.where(
(e) =>
e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase() &&
(e.name.toLowerCase().contains(text.toLowerCase()) ||
e.ticker.toLowerCase().contains(text.toLowerCase())),
)
.toList();
}
}
@ -266,7 +277,8 @@ class _ExchangeCurrencySelectionViewState
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(
const Duration(milliseconds: 50));
const Duration(milliseconds: 50),
);
}
if (mounted) {
Navigator.of(context).pop();
@ -353,18 +365,24 @@ class _ExchangeCurrencySelectionViewState
Flexible(
child: Builder(
builder: (context) {
final coins = Coin.values.where((e) =>
e.ticker.toLowerCase() !=
widget.pairedTicker?.toLowerCase());
final coins = SupportedCoins.cryptocurrencies.where(
(e) =>
e.ticker.toLowerCase() !=
widget.pairedTicker?.toLowerCase(),
);
final items = filter(_searchString);
final walletCoins = items
.where((currency) => coins
.where((coin) =>
coin.ticker.toLowerCase() ==
currency.ticker.toLowerCase())
.isNotEmpty)
.where(
(currency) => coins
.where(
(coin) =>
coin.ticker.toLowerCase() ==
currency.ticker.toLowerCase(),
)
.isNotEmpty,
)
.toList();
// sort alphabetically by name
@ -402,7 +420,9 @@ class _ExchangeCurrencySelectionViewState
height: 24,
child: isStackCoin(items[index].ticker)
? CoinIconForTicker(
ticker: items[index].ticker, size: 24)
ticker: items[index].ticker,
size: 24,
)
// ? getIconForTicker(
// items[index].ticker,
// size: 24,

View file

@ -40,10 +40,11 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount_unit.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/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoin.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
@ -59,14 +60,14 @@ import 'package:uuid/uuid.dart';
class ExchangeForm extends ConsumerStatefulWidget {
const ExchangeForm({
Key? key,
super.key,
this.walletId,
this.coin,
this.contract,
}) : super(key: key);
});
final String? walletId;
final Coin? coin;
final CryptoCurrency? coin;
final EthContract? contract;
@override
@ -75,7 +76,7 @@ class ExchangeForm extends ConsumerStatefulWidget {
class _ExchangeFormState extends ConsumerState<ExchangeForm> {
late final String? walletId;
late final Coin? coin;
late final CryptoCurrency? coin;
late final bool walletInitiated;
List<Exchange> get usableExchanges {
@ -172,7 +173,8 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
.tryParse(
value,
locale: ref.read(localeServiceChangeNotifierProvider).locale,
coin: Coin.bitcoin, // dummy value (not used due to override)
coin: Bitcoin(CryptoCurrencyNetwork
.main), // dummy value (not used due to override)
overrideWithDecimalPlacesFromString: true,
)
?.decimal;
@ -607,12 +609,12 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
}
}
bool isWalletCoin(Coin? coin, bool isSend) {
bool isWalletCoin(CryptoCurrency? coin, bool isSend) {
if (coin == null) {
return false;
}
String? ticker = isSend
final String? ticker = isSend
? ref.read(efCurrencyPairProvider).send?.ticker
: ref.read(efCurrencyPairProvider).receive?.ticker;

View file

@ -19,12 +19,12 @@ import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_3_view.
import 'package:stackwallet/pages/exchange_view/sub_widgets/step_row.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/widgets/background.dart';
@ -72,7 +72,7 @@ class _Step2ViewState extends ConsumerState<Step2View> {
bool isStackCoin(String ticker) {
try {
coinFromTickerCaseInsensitive(ticker);
SupportedCoins.getCryptoCurrencyForTicker(ticker);
return true;
} on ArgumentError catch (_) {
return false;
@ -207,10 +207,13 @@ class _Step2ViewState extends ConsumerState<Step2View> {
text: "Choose from Stack",
onTap: () {
try {
final coin =
coinFromTickerCaseInsensitive(
model.receiveTicker,
);
final coin = SupportedCoins
.cryptocurrencies
.firstWhere((e) =>
e.ticker.toLowerCase() ==
model.receiveTicker
.toLowerCase());
Navigator.of(context)
.pushNamed(
ChooseFromStackView.routeName,
@ -480,10 +483,12 @@ class _Step2ViewState extends ConsumerState<Step2View> {
text: "Choose from Stack",
onTap: () {
try {
final coin =
coinFromTickerCaseInsensitive(
model.sendTicker,
);
final coin = SupportedCoins
.cryptocurrencies
.firstWhere((e) =>
e.ticker.toLowerCase() ==
model.sendTicker.toLowerCase());
Navigator.of(context)
.pushNamed(
ChooseFromStackView.routeName,

View file

@ -26,15 +26,18 @@ import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dia
import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/stellar.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.dart';
@ -72,7 +75,7 @@ class _Step4ViewState extends ConsumerState<Step4View> {
bool _isWalletCoinAndHasWallet(String ticker, WidgetRef ref) {
try {
final coin = coinFromTickerCaseInsensitive(ticker);
final coin = SupportedCoins.getCryptoCurrencyForTicker(ticker);
return ref
.read(pWallets)
.wallets
@ -194,9 +197,9 @@ class _Step4ViewState extends ConsumerState<Step4View> {
);
}
Future<void> _confirmSend(Tuple2<String, Coin> tuple) async {
Future<void> _confirmSend(Tuple2<String, CryptoCurrency> tuple) async {
final bool firoPublicSend;
if (tuple.item2 == Coin.firo) {
if (tuple.item2 is Firo) {
final result = await _showSendFromFiroBalanceSelectSheet(tuple.item1);
if (result == null) {
return;
@ -210,7 +213,7 @@ class _Step4ViewState extends ConsumerState<Step4View> {
final wallet = ref.read(pWallets).getWallet(tuple.item1);
final Amount amount = model.sendAmount.toAmount(
fractionDigits: wallet.info.coin.decimals,
fractionDigits: wallet.info.coin.fractionDigits,
);
final address = model.trade!.payInAddress;
@ -258,8 +261,7 @@ class _Step4ViewState extends ConsumerState<Step4View> {
),
);
} else {
final memo = wallet.info.coin == Coin.stellar ||
wallet.info.coin == Coin.stellarTestnet
final memo = wallet.info.coin is Stellar
? model.trade!.payInExtraId.isNotEmpty
? model.trade!.payInExtraId
: null
@ -851,16 +853,23 @@ class _Step4ViewState extends ConsumerState<Step4View> {
.useMaterialPageRoute,
builder:
(BuildContext context) {
final coin =
coinFromTickerCaseInsensitive(
model.trade!.payInCurrency,
final coin = SupportedCoins
.cryptocurrencies
.firstWhere(
(e) =>
e.ticker
.toLowerCase() ==
model.trade!
.payInCurrency
.toLowerCase(),
);
return SendFromView(
coin: coin,
amount: model.sendAmount
.toAmount(
fractionDigits:
coin.decimals,
coin.fractionDigits,
),
address: model
.trade!.payInAddress,

View file

@ -23,14 +23,17 @@ import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.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/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/stellar.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.dart';
@ -56,7 +59,7 @@ class SendFromView extends ConsumerStatefulWidget {
static const String routeName = "/sendFrom";
final Coin coin;
final CryptoCurrency coin;
final Amount amount;
final String address;
final Trade trade;
@ -68,7 +71,7 @@ class SendFromView extends ConsumerStatefulWidget {
}
class _SendFromViewState extends ConsumerState<SendFromView> {
late final Coin coin;
late final CryptoCurrency coin;
late final Amount amount;
late final String address;
late final Trade trade;
@ -279,7 +282,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
// if not firo then do normal send
if (shouldSendPublicFiroFunds == null) {
final memo = coin == Coin.stellar || coin == Coin.stellarTestnet
final memo = coin is Stellar
? trade.payInExtraId.isNotEmpty
? trade.payInExtraId
: null
@ -427,7 +430,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
final coin = ref.watch(pWalletCoin(walletId));
final isFiro = coin == Coin.firoTestNet || coin == Coin.firo;
final isFiro = coin is Firo;
return RoundedWhiteContainer(
padding: const EdgeInsets.all(0),
@ -602,10 +605,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
children: [
Container(
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.colorForCoin(coin)
.withOpacity(0.5),
color: ref.watch(pCoinColor(coin)).withOpacity(0.5),
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),

View file

@ -16,16 +16,18 @@ import 'package:stackwallet/models/exchange/response_objects/estimate.dart';
import 'package:stackwallet/providers/exchange/exchange_form_state_provider.dart';
import 'package:stackwallet/providers/global/locale_provider.dart';
import 'package:stackwallet/services/exchange/exchange.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/amount/amount_unit.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoin.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/animated_text.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/exchange/trocador/trocador_kyc_info_button.dart';
@ -33,11 +35,11 @@ import 'package:stackwallet/widgets/exchange/trocador/trocador_rating_type_enum.
class ExchangeOption extends ConsumerStatefulWidget {
const ExchangeOption({
Key? key,
super.key,
required this.exchange,
required this.fixedRate,
required this.reversed,
}) : super(key: key);
});
final Exchange exchange;
final bool fixedRate;
@ -92,9 +94,9 @@ class _ExchangeOptionState extends ConsumerState<ExchangeOption> {
int decimals;
try {
decimals = coinFromTickerCaseInsensitive(
receivingCurrency.ticker)
.decimals;
decimals = SupportedCoins.getCryptoCurrencyForTicker(
receivingCurrency.ticker,
).fractionDigits;
} catch (_) {
decimals = 8; // some reasonable alternative
}
@ -109,10 +111,11 @@ class _ExchangeOptionState extends ConsumerState<ExchangeOption> {
.toAmount(fractionDigits: decimals);
}
Coin? coin;
CryptoCurrency? coin;
try {
coin = coinFromTickerCaseInsensitive(
receivingCurrency.ticker);
coin = SupportedCoins.getCryptoCurrencyForTicker(
receivingCurrency.ticker,
);
} catch (_) {
coin = null;
}
@ -128,7 +131,8 @@ class _ExchangeOptionState extends ConsumerState<ExchangeOption> {
localeServiceChangeNotifierProvider
.select((value) => value.locale),
),
coin: Coin.bitcoin, // some sane default
coin: Bitcoin(CryptoCurrencyNetwork
.main), // some sane default
maxDecimals: 8, // some sane default
);
rateString = "1 ${sendCurrency.ticker.toUpperCase()} "

View file

@ -33,6 +33,7 @@ import 'package:stackwallet/services/exchange/exchange.dart';
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
import 'package:stackwallet/services/exchange/simpleswap/simpleswap_exchange.dart';
import 'package:stackwallet/services/exchange/trocador/trocador_exchange.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
@ -40,10 +41,10 @@ import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -58,13 +59,13 @@ import 'package:url_launcher/url_launcher.dart';
class TradeDetailsView extends ConsumerStatefulWidget {
const TradeDetailsView({
Key? key,
super.key,
required this.tradeId,
required this.transactionIfSentFromStack,
required this.walletId,
required this.walletName,
this.clipboard = const ClipboardWrapper(),
}) : super(key: key);
});
static const String routeName = "/tradeDetails";
@ -87,9 +88,9 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
bool isStackCoin(String ticker) {
try {
try {
coinFromTickerCaseInsensitive(ticker);
SupportedCoins.getCryptoCurrencyForTicker(ticker);
} catch (_) {}
coinFromPrettyName(ticker);
SupportedCoins.getCryptoCurrencyByPrettyName(ticker);
return true;
} on ArgumentError catch (_) {
return false;
@ -167,8 +168,11 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
final bool sentFromStack =
transactionIfSentFromStack != null && walletId != null;
final trade = ref.watch(tradesServiceProvider.select(
(value) => value.trades.firstWhere((e) => e.tradeId == tradeId)));
final trade = ref.watch(
tradesServiceProvider.select(
(value) => value.trades.firstWhere((e) => e.tradeId == tradeId),
),
);
final bool hasTx = sentFromStack ||
!(trade.status == "New" ||
@ -273,16 +277,19 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
label: "Send from Stack",
buttonHeight: ButtonHeight.l,
onPressed: () {
Coin coin;
CryptoCurrency coin;
try {
coin = coinFromTickerCaseInsensitive(
trade.payInCurrency);
coin = SupportedCoins.getCryptoCurrencyForTicker(
trade.payInCurrency,
);
} catch (_) {
coin = coinFromPrettyName(trade.payInCurrency);
coin = SupportedCoins.getCryptoCurrencyByPrettyName(
trade.payInCurrency,
);
}
final amount = Amount.fromDecimal(
sendAmount,
fractionDigits: coin.decimals,
fractionDigits: coin.fractionDigits,
);
final address = trade.payInAddress;
@ -368,28 +375,34 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
const SizedBox(
height: 4,
),
Builder(builder: (context) {
String text;
try {
final coin = coinFromTickerCaseInsensitive(
trade.payInCurrency);
final amount = sendAmount.toAmount(
fractionDigits: coin.decimals);
text = ref
.watch(pAmountFormatter(coin))
.format(amount);
} catch (_) {
text = sendAmount.toStringAsFixed(
Builder(
builder: (context) {
String text;
try {
final coin =
SupportedCoins.getCryptoCurrencyForTicker(
trade.payInCurrency,
);
final amount = sendAmount.toAmount(
fractionDigits: coin.fractionDigits,
);
text = ref
.watch(pAmountFormatter(coin))
.format(amount);
} catch (_) {
text = sendAmount.toStringAsFixed(
trade.payInCurrency.toLowerCase() == "xmr"
? 12
: 8);
}
: 8,
);
}
return SelectableText(
"-$text ${trade.payInCurrency.toUpperCase()}",
style: STextStyles.itemSubtitle(context),
);
}),
return SelectableText(
"-$text ${trade.payInCurrency.toUpperCase()}",
style: STextStyles.itemSubtitle(context),
);
},
),
],
),
if (!isDesktop)
@ -464,7 +477,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
),
),
],
)
),
],
),
const SizedBox(
@ -512,7 +525,8 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
Text(
"Amount",
style: STextStyles.desktopTextExtraExtraSmall(
context),
context,
),
),
const SizedBox(
height: 2,
@ -520,8 +534,8 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
Text(
"${trade.payInAmount} ${trade.payInCurrency.toUpperCase()}",
style: STextStyles.desktopTextExtraExtraSmall(
context)
.copyWith(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
@ -542,43 +556,44 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
),
child: RichText(
text: TextSpan(
text:
"You must send at least ${sendAmount.toStringAsFixed(
trade.payInCurrency.toLowerCase() == "xmr" ? 12 : 8,
)} ${trade.payInCurrency.toUpperCase()}. ",
style: isDesktop
? STextStyles.desktopTextExtraExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorRed)
: STextStyles.label(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.warningForeground,
),
children: [
TextSpan(
text:
"If you send less than ${sendAmount.toStringAsFixed(
trade.payInCurrency.toLowerCase() == "xmr"
? 12
: 8,
)} ${trade.payInCurrency.toUpperCase()}, your transaction may not be converted and it may not be refunded.",
style: isDesktop
? STextStyles.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorRed)
: STextStyles.label(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.warningForeground,
),
),
]),
text:
"You must send at least ${sendAmount.toStringAsFixed(
trade.payInCurrency.toLowerCase() == "xmr" ? 12 : 8,
)} ${trade.payInCurrency.toUpperCase()}. ",
style: isDesktop
? STextStyles.desktopTextExtraExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorRed,
)
: STextStyles.label(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.warningForeground,
),
children: [
TextSpan(
text:
"If you send less than ${sendAmount.toStringAsFixed(
trade.payInCurrency.toLowerCase() == "xmr" ? 12 : 8,
)} ${trade.payInCurrency.toUpperCase()}, your transaction may not be converted and it may not be refunded.",
style: isDesktop
? STextStyles.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorRed,
)
: STextStyles.label(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.warningForeground,
),
),
],
),
),
),
),
@ -613,8 +628,10 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
CustomTextButton(
text: "View transaction",
onTap: () {
final Coin coin =
coinFromTickerCaseInsensitive(trade.payInCurrency);
final CryptoCurrency coin =
SupportedCoins.getCryptoCurrencyForTicker(
trade.payInCurrency,
);
if (isDesktop) {
Navigator.of(context).push(
@ -638,7 +655,10 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
Navigator.of(context).pushNamed(
TransactionDetailsView.routeName,
arguments: Tuple3(
transactionIfSentFromStack!, coin, walletId!),
transactionIfSentFromStack!,
coin,
walletId!,
),
);
}
},
@ -787,14 +807,15 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
width: width + 20,
height: width + 20,
child: QrImageView(
data: trade.payInAddress,
size: width,
backgroundColor: Theme.of(context)
.extension<StackColors>()!
.popupBG,
foregroundColor: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
data: trade.payInAddress,
size: width,
backgroundColor: Theme.of(context)
.extension<StackColors>()!
.popupBG,
foregroundColor: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
),
),
@ -812,14 +833,16 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonStyle(
context),
context,
),
child: Text(
"Cancel",
style: STextStyles.button(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
),
),
@ -1005,8 +1028,10 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
height: 4,
),
SelectableText(
ref.watch(tradeNoteServiceProvider
.select((value) => value.getNote(tradeId: tradeId))),
ref.watch(
tradeNoteServiceProvider
.select((value) => value.getNote(tradeId: tradeId)),
),
style: STextStyles.itemSubtitle12(context),
),
],
@ -1132,7 +1157,8 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
if (isDesktop)
SelectableText(
Format.extractDateFrom(
trade.timestamp.millisecondsSinceEpoch ~/ 1000),
trade.timestamp.millisecondsSinceEpoch ~/ 1000,
),
style: STextStyles.desktopTextExtraExtraSmall(context)
.copyWith(
color: Theme.of(context)
@ -1145,13 +1171,15 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
if (!isDesktop)
SelectableText(
Format.extractDateFrom(
trade.timestamp.millisecondsSinceEpoch ~/ 1000),
trade.timestamp.millisecondsSinceEpoch ~/ 1000,
),
style: STextStyles.itemSubtitle12(context),
),
if (isDesktop)
IconCopyButton(
data: Format.extractDateFrom(
trade.timestamp.millisecondsSinceEpoch ~/ 1000),
trade.timestamp.millisecondsSinceEpoch ~/ 1000,
),
),
],
),
@ -1265,7 +1293,7 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
.infoItemIcons,
width: 12,
),
)
),
],
),
],
@ -1352,15 +1380,19 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
SecondaryButton(
label: "Send from Stack",
onPressed: () {
Coin coin;
CryptoCurrency coin;
try {
coin = coinFromTickerCaseInsensitive(trade.payInCurrency);
coin = SupportedCoins.getCryptoCurrencyForTicker(
trade.payInCurrency,
);
} catch (_) {
coin = coinFromPrettyName(trade.payInCurrency);
coin = SupportedCoins.getCryptoCurrencyByPrettyName(
trade.payInCurrency,
);
}
final amount = Amount.fromDecimal(
sendAmount,
fractionDigits: coin.decimals,
fractionDigits: coin.fractionDigits,
);
final address = trade.payInAddress;

View file

@ -19,8 +19,8 @@ import 'package:stackwallet/providers/exchange/exchange_form_state_provider.dart
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -28,16 +28,16 @@ import 'package:stackwallet/widgets/custom_loading_overlay.dart';
class WalletInitiatedExchangeView extends ConsumerStatefulWidget {
const WalletInitiatedExchangeView({
Key? key,
super.key,
required this.walletId,
required this.coin,
this.contract,
}) : super(key: key);
});
static const String routeName = "/walletInitiatedExchange";
final String walletId;
final Coin coin;
final CryptoCurrency coin;
final EthContract? contract;
@override
@ -48,7 +48,7 @@ class WalletInitiatedExchangeView extends ConsumerStatefulWidget {
class _WalletInitiatedExchangeViewState
extends ConsumerState<WalletInitiatedExchangeView> {
late final String walletId;
late final Coin coin;
late final CryptoCurrency coin;
bool _initialCachePopulationUnderway = false;

View file

@ -13,7 +13,7 @@
//
// import 'package:stackwallet/themes/stack_colors.dart';
// import 'package:stackwallet/utilities/assets.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';
@ -163,7 +163,7 @@
//
// @override
// Widget build(BuildContext context) {
// final Coin coin = ref.watch(managerProvider.select((value) => value.coin));
// final CryptoCurrency coin = ref.watch(managerProvider.select((value) => value.coin));
// final wallet = ref.watch(walletsChangeNotifierProvider
// .select((value) => value.getWallet(widget.walletId)));
//

View file

@ -19,7 +19,6 @@ import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.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/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
@ -30,10 +29,10 @@ import 'package:stackwallet/widgets/rounded_white_container.dart';
class OrdinalDetailsView extends ConsumerStatefulWidget {
const OrdinalDetailsView({
Key? key,
super.key,
required this.walletId,
required this.ordinal,
}) : super(key: key);
});
final String walletId;
final Ordinal ordinal;
@ -113,7 +112,7 @@ class _OrdinalDetailsViewState extends ConsumerState<OrdinalDetailsView> {
: ref.watch(pAmountFormatter(coin)).format(
Amount(
rawValue: BigInt.from(utxo!.value),
fractionDigits: coin.decimals,
fractionDigits: coin.fractionDigits,
),
),
),

View file

@ -15,9 +15,9 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
@ -26,19 +26,19 @@ import 'package:stackwallet/widgets/stack_dialog.dart';
class ConfirmPaynymConnectDialog extends ConsumerWidget {
const ConfirmPaynymConnectDialog({
Key? key,
super.key,
required this.nymName,
required this.locale,
required this.onConfirmPressed,
required this.amount,
required this.coin,
}) : super(key: key);
});
final String nymName;
final String locale;
final VoidCallback onConfirmPressed;
final Amount amount;
final Coin coin;
final CryptoCurrency coin;
String get title => "Connect to $nymName";

View file

@ -28,7 +28,6 @@ import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
@ -44,10 +43,10 @@ import 'package:tuple/tuple.dart';
class PaynymDetailsPopup extends ConsumerStatefulWidget {
const PaynymDetailsPopup({
Key? key,
super.key,
required this.walletId,
required this.accountLite,
}) : super(key: key);
});
final String walletId;
final PaynymAccountLite accountLite;

View file

@ -26,7 +26,7 @@ import 'package:stackwallet/providers/global/locale_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';

View file

@ -23,7 +23,7 @@ import 'package:stackwallet/themes/stack_colors.dart';
// import 'package:stackwallet/providers/global/should_show_lockscreen_on_resume_state_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/biometrics.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';

View file

@ -30,9 +30,9 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/custom_buttons/simple_edit_button.dart';
@ -53,7 +53,7 @@ class AddressCard extends ConsumerStatefulWidget {
final int addressId;
final String walletId;
final Coin coin;
final CryptoCurrency coin;
final ClipboardInterface clipboard;
final VoidCallback? onPressed;

View file

@ -23,7 +23,6 @@ import 'package:stackwallet/providers/db/main_db_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
@ -40,10 +39,10 @@ import 'package:stackwallet/widgets/transaction_card.dart';
class AddressDetailsView extends ConsumerStatefulWidget {
const AddressDetailsView({
Key? key,
super.key,
required this.addressId,
required this.walletId,
}) : super(key: key);
});
static const String routeName = "/addressDetailsView";
@ -398,7 +397,11 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
height: 12,
),
if (!isDesktop)
coin == Coin.bitcoincash || coin == Coin.bitcoincashTestnet
ref
.watch(pWallets)
.getWallet(widget.walletId)
.isarTransactionVersion ==
2
? _AddressDetailsTxV2List(
walletId: widget.walletId,
address: address,
@ -418,10 +421,10 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
class _AddressDetailsTxList extends StatelessWidget {
const _AddressDetailsTxList({
Key? key,
super.key,
required this.walletId,
required this.address,
}) : super(key: key);
});
final String walletId;
final Address address;

View file

@ -25,23 +25,23 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
class AddressQrPopup extends StatefulWidget {
const AddressQrPopup({
Key? key,
super.key,
required this.addressString,
required this.coin,
this.clipboard = const ClipboardWrapper(),
}) : super(key: key);
});
final String addressString;
final Coin coin;
final CryptoCurrency coin;
final ClipboardInterface clipboard;
@override
@ -54,12 +54,12 @@ class _AddressQrPopupState extends State<AddressQrPopup> {
Future<void> _capturePng(bool shouldSaveInsteadOfShare) async {
try {
RenderRepaintBoundary boundary =
final RenderRepaintBoundary boundary =
_qrKey.currentContext?.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage();
ByteData? byteData =
final ui.Image image = await boundary.toImage();
final ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData!.buffer.asUint8List();
final Uint8List pngBytes = byteData!.buffer.asUint8List();
if (shouldSaveInsteadOfShare) {
if (isDesktop) {

View file

@ -28,10 +28,12 @@ import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoincash.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/ecash.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -45,15 +47,15 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart';
class GenerateUriQrCodeView extends StatefulWidget {
const GenerateUriQrCodeView({
Key? key,
super.key,
required this.coin,
required this.receivingAddress,
this.clipboard = const ClipboardWrapper(),
}) : super(key: key);
});
static const String routeName = "/generateUriQrCodeView";
final Coin coin;
final CryptoCurrency coin;
final String receivingAddress;
final ClipboardInterface clipboard;
@ -76,12 +78,12 @@ class _GenerateUriQrCodeViewState extends State<GenerateUriQrCodeView> {
Future<void> _capturePng(bool shouldSaveInsteadOfShare) async {
try {
RenderRepaintBoundary boundary =
final RenderRepaintBoundary boundary =
_qrKey.currentContext?.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage();
ByteData? byteData =
final ui.Image image = await boundary.toImage();
final ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData!.buffer.asUint8List();
final Uint8List pngBytes = byteData!.buffer.asUint8List();
if (shouldSaveInsteadOfShare) {
if (Util.isDesktop) {
@ -149,7 +151,7 @@ class _GenerateUriQrCodeViewState extends State<GenerateUriQrCodeView> {
return null;
}
Map<String, String> queryParams = {};
final Map<String, String> queryParams = {};
if (amountString.isNotEmpty) {
queryParams["amount"] = amountString;
@ -159,9 +161,7 @@ class _GenerateUriQrCodeViewState extends State<GenerateUriQrCodeView> {
}
String receivingAddress = widget.receivingAddress;
if ((widget.coin == Coin.bitcoincash ||
widget.coin == Coin.eCash ||
widget.coin == Coin.bitcoincashTestnet) &&
if ((widget.coin is Bitcoincash || widget.coin is Ecash) &&
receivingAddress.contains(":")) {
// remove cash addr prefix
receivingAddress = receivingAddress.split(":").sublist(1).join();
@ -256,9 +256,7 @@ class _GenerateUriQrCodeViewState extends State<GenerateUriQrCodeView> {
isDesktop = Util.isDesktop;
String receivingAddress = widget.receivingAddress;
if ((widget.coin == Coin.bitcoincash ||
widget.coin == Coin.eCash ||
widget.coin == Coin.bitcoincashTestnet) &&
if ((widget.coin is Bitcoincash || widget.coin is Ecash) &&
receivingAddress.contains(":")) {
// remove cash addr prefix
receivingAddress = receivingAddress.split(":").sublist(1).join();

View file

@ -29,9 +29,9 @@ import 'package:stackwallet/utilities/address_utils.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/impl/bitcoin_wallet.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
@ -66,7 +66,7 @@ class ReceiveView extends ConsumerStatefulWidget {
}
class _ReceiveViewState extends ConsumerState<ReceiveView> {
late final Coin coin;
late final CryptoCurrency coin;
late final String walletId;
late final ClipboardInterface clipboard;
late final bool _supportsSpark;

View file

@ -32,9 +32,10 @@ import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.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/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/epiccash.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/nano_currency.dart';
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
@ -55,7 +56,7 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart';
class ConfirmTransactionView extends ConsumerStatefulWidget {
const ConfirmTransactionView({
Key? key,
super.key,
required this.txData,
required this.walletId,
required this.onSuccess,
@ -65,7 +66,7 @@ class ConfirmTransactionView extends ConsumerStatefulWidget {
this.isPaynymNotificationTransaction = false,
this.isTokenTx = false,
this.onSuccessInsteadOfRouteOnSuccess,
}) : super(key: key);
});
static const String routeName = "/confirmTransactionView";
@ -157,7 +158,7 @@ class _ConfirmTransactionViewState
break;
}
} else {
if (coin == Coin.epicCash) {
if (coin is Epiccash) {
txDataFuture = wallet.confirmSend(
txData: widget.txData.copyWith(
noteOnChain: onChainNoteController.text,
@ -276,7 +277,7 @@ class _ConfirmTransactionViewState
),
),
],
)
),
],
),
),
@ -292,9 +293,10 @@ class _ConfirmTransactionViewState
child: Text(
"Ok",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
onPressed: () {
Navigator.of(context).pop();
@ -340,7 +342,8 @@ class _ConfirmTransactionViewState
final String unit;
if (widget.isTokenTx) {
unit = ref.watch(
pCurrentTokenWallet.select((value) => value!.tokenContract.symbol));
pCurrentTokenWallet.select((value) => value!.tokenContract.symbol),
);
} else {
unit = coin.ticker;
}
@ -375,10 +378,12 @@ class _ConfirmTransactionViewState
fee = widget.txData.fee;
amountWithoutChange = (widget.txData.amountWithoutChange ??
Amount.zeroWith(
fractionDigits: wallet.cryptoCurrency.fractionDigits)) +
fractionDigits: wallet.cryptoCurrency.fractionDigits,
)) +
(widget.txData.amountSparkWithoutChange ??
Amount.zeroWith(
fractionDigits: wallet.cryptoCurrency.fractionDigits));
fractionDigits: wallet.cryptoCurrency.fractionDigits,
));
break;
}
} else {
@ -526,11 +531,11 @@ class _ConfirmTransactionViewState
],
),
),
if (coin != Coin.banano && coin != Coin.nano)
if (coin is! NanoCurrency)
const SizedBox(
height: 12,
),
if (coin != Coin.banano && coin != Coin.nano)
if (coin is! NanoCurrency)
RoundedWhiteContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -570,13 +575,11 @@ class _ConfirmTransactionViewState
],
),
),
if (coin == Coin.epicCash &&
widget.txData.noteOnChain!.isNotEmpty)
if (coin is Epiccash && widget.txData.noteOnChain!.isNotEmpty)
const SizedBox(
height: 12,
),
if (coin == Coin.epicCash &&
widget.txData.noteOnChain!.isNotEmpty)
if (coin is Epiccash && widget.txData.noteOnChain!.isNotEmpty)
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
@ -605,7 +608,7 @@ class _ConfirmTransactionViewState
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
(coin == Coin.epicCash) ? "Local Note" : "Note",
(coin is Epiccash) ? "Local Note" : "Note",
style: STextStyles.smallMed12(context),
),
const SizedBox(
@ -688,7 +691,8 @@ class _ConfirmTransactionViewState
Text(
"Amount",
style: STextStyles.desktopTextExtraExtraSmall(
context),
context,
),
),
const SizedBox(
height: 2,
@ -696,15 +700,18 @@ class _ConfirmTransactionViewState
Builder(
builder: (context) {
final externalCalls = ref.watch(
prefsChangeNotifierProvider.select(
(value) => value.externalCalls));
prefsChangeNotifierProvider.select(
(value) => value.externalCalls,
),
);
String fiatAmount = "N/A";
if (externalCalls) {
final price = widget.isTokenTx
? ref
.read(
priceAnd24hChangeNotifierProvider)
priceAnd24hChangeNotifierProvider,
)
.getTokenPrice(
ref
.read(pCurrentTokenWallet)!
@ -714,7 +721,8 @@ class _ConfirmTransactionViewState
.item1
: ref
.read(
priceAnd24hChangeNotifierProvider)
priceAnd24hChangeNotifierProvider,
)
.getPrice(coin)
.item1;
if (price > Decimal.zero) {
@ -724,7 +732,8 @@ class _ConfirmTransactionViewState
.fiatString(
locale: ref
.read(
localeServiceChangeNotifierProvider)
localeServiceChangeNotifierProvider,
)
.locale,
);
}
@ -734,14 +743,15 @@ class _ConfirmTransactionViewState
children: [
SelectableText(
ref.watch(pAmountFormatter(coin)).format(
amountWithoutChange,
ethContract: ref
.read(pCurrentTokenWallet)
?.tokenContract),
amountWithoutChange,
ethContract: ref
.read(pCurrentTokenWallet)
?.tokenContract,
),
style: STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
@ -752,16 +762,20 @@ class _ConfirmTransactionViewState
" | ",
style: STextStyles
.desktopTextExtraExtraSmall(
context),
context,
),
),
if (externalCalls)
SelectableText(
"~$fiatAmount ${ref.watch(prefsChangeNotifierProvider.select(
(value) => value.currency,
))}",
"~$fiatAmount ${ref.watch(
prefsChangeNotifierProvider.select(
(value) => value.currency,
),
)}",
style: STextStyles
.desktopTextExtraExtraSmall(
context),
context,
),
),
],
);
@ -787,7 +801,8 @@ class _ConfirmTransactionViewState
? "PayNym recipient"
: "Send to",
style: STextStyles.desktopTextExtraExtraSmall(
context),
context,
),
),
const SizedBox(
height: 2,
@ -800,13 +815,13 @@ class _ConfirmTransactionViewState
widget.txData.sparkRecipients!.first
.address,
style: STextStyles.desktopTextExtraExtraSmall(
context)
.copyWith(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
),
)
),
],
),
),
@ -827,7 +842,8 @@ class _ConfirmTransactionViewState
Text(
"Transaction fee",
style: STextStyles.desktopTextExtraExtraSmall(
context),
context,
),
),
const SizedBox(
height: 2,
@ -835,8 +851,8 @@ class _ConfirmTransactionViewState
SelectableText(
ref.watch(pAmountFormatter(coin)).format(fee!),
style: STextStyles.desktopTextExtraExtraSmall(
context)
.copyWith(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
@ -892,17 +908,17 @@ class _ConfirmTransactionViewState
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (coin == Coin.epicCash)
if (coin is Epiccash)
Text(
"On chain Note (optional)",
style: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),
if (coin == Coin.epicCash)
if (coin is Epiccash)
const SizedBox(
height: 8,
),
if (coin == Coin.epicCash)
if (coin is Epiccash)
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
@ -942,12 +958,12 @@ class _ConfirmTransactionViewState
),
),
),
if (coin == Coin.epicCash)
if (coin is Epiccash)
const SizedBox(
height: 12,
),
SelectableText(
(coin == Coin.epicCash)
(coin is Epiccash)
? "Local Note (optional)"
: "Note (optional)",
style:
@ -1016,7 +1032,7 @@ class _ConfirmTransactionViewState
),
const SizedBox(
height: 20,
)
),
],
),
),
@ -1221,11 +1237,12 @@ class _ConfirmTransactionViewState
} else {
unawaited(
showFloatingFlushBar(
type: FlushBarType.warning,
message: Util.isDesktop
? "Invalid passphrase"
: "Invalid PIN",
context: context),
type: FlushBarType.warning,
message: Util.isDesktop
? "Invalid passphrase"
: "Invalid PIN",
context: context,
),
);
}
}

View file

@ -25,10 +25,10 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
import 'package:stackwallet/wallets/wallet/impl/bitcoin_frost_wallet.dart';
@ -58,7 +58,7 @@ class FrostSendView extends ConsumerStatefulWidget {
static const String routeName = "/frostSendView";
final String walletId;
final Coin coin;
final CryptoCurrency coin;
@override
ConsumerState<FrostSendView> createState() => _FrostSendViewState();
@ -69,7 +69,7 @@ class _FrostSendViewState extends ConsumerState<FrostSendView> {
int _greatestWidgetIndex = 0;
late final String walletId;
late final Coin coin;
late final CryptoCurrency coin;
late TextEditingController noteController;
late TextEditingController onChainNoteController;

View file

@ -12,10 +12,10 @@ import 'package:stackwallet/utilities/amount/amount_unit.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart';
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
@ -55,7 +55,7 @@ class Recipient extends ConsumerStatefulWidget {
final int index;
final int displayNumber;
final Coin coin;
final CryptoCurrency coin;
final VoidCallback? remove;
final VoidCallback? onChanged;
@ -324,7 +324,8 @@ class _RecipientState extends ConsumerState<Recipient> {
final Amount amount =
Decimal.parse(results["amount"]!)
.toAmount(
fractionDigits: widget.coin.decimals,
fractionDigits:
widget.coin.fractionDigits,
);
amountController.text = ref
.read(pAmountFormatter(widget.coin))
@ -409,7 +410,7 @@ class _RecipientState extends ConsumerState<Recipient> {
textAlign: TextAlign.right,
inputFormatters: [
AmountInputFormatter(
decimals: widget.coin.decimals,
decimals: widget.coin.fractionDigits,
unit: ref.watch(pAmountUnit(widget.coin)),
locale: locale,
),

View file

@ -11,7 +11,6 @@ import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -93,7 +92,7 @@ class _FrostSendStep4State extends ConsumerState<FrostSendStep4> {
height: 12,
),
Text(
"Send ${cryptoCurrency.coin.ticker}",
"Send ${cryptoCurrency.ticker}",
style: STextStyles.w600_20(context),
),
const SizedBox(
@ -103,7 +102,7 @@ class _FrostSendStep4State extends ConsumerState<FrostSendStep4> {
? _Recipient(
address: recipients[0].address,
amount: ref
.watch(pAmountFormatter(cryptoCurrency.coin))
.watch(pAmountFormatter(cryptoCurrency))
.format(recipients[0].amount),
)
: Column(
@ -143,7 +142,7 @@ class _FrostSendStep4State extends ConsumerState<FrostSendStep4> {
body: _Recipient(
address: recipients[i].address,
amount: ref
.watch(pAmountFormatter(cryptoCurrency.coin))
.watch(pAmountFormatter(cryptoCurrency))
.format(recipients[i].amount),
),
),
@ -156,7 +155,7 @@ class _FrostSendStep4State extends ConsumerState<FrostSendStep4> {
DetailItem(
title: "Transaction fee",
detail: ref
.watch(pAmountFormatter(cryptoCurrency.coin))
.watch(pAmountFormatter(cryptoCurrency))
.format(ref.watch(pFrostTxData)!.fee!),
horizontal: true,
),
@ -165,7 +164,7 @@ class _FrostSendStep4State extends ConsumerState<FrostSendStep4> {
),
DetailItem(
title: "Total",
detail: ref.watch(pAmountFormatter(cryptoCurrency.coin)).format(
detail: ref.watch(pAmountFormatter(cryptoCurrency)).format(
ref.watch(pFrostTxData)!.fee! +
recipients.map((e) => e.amount).reduce((v, e) => v += e)),
horizontal: true,

View file

@ -43,13 +43,19 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.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/monero.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/crypto_currency.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/nano_currency.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.dart';
@ -73,19 +79,19 @@ import 'package:tuple/tuple.dart';
class SendView extends ConsumerStatefulWidget {
const SendView({
Key? key,
super.key,
required this.walletId,
required this.coin,
this.autoFillData,
this.clipboard = const ClipboardWrapper(),
this.barcodeScanner = const BarcodeScannerWrapper(),
this.accountLite,
}) : super(key: key);
});
static const String routeName = "/sendView";
final String walletId;
final Coin coin;
final CryptoCurrency coin;
final SendViewAutoFillData? autoFillData;
final ClipboardInterface clipboard;
final BarcodeScannerInterface barcodeScanner;
@ -97,7 +103,7 @@ class SendView extends ConsumerStatefulWidget {
class _SendViewState extends ConsumerState<SendView> {
late final String walletId;
late final Coin coin;
late final CryptoCurrency coin;
late final ClipboardInterface clipboard;
late final BarcodeScannerInterface scanner;
@ -178,7 +184,7 @@ class _SendViewState extends ConsumerState<SendView> {
// autofill amount field
if (results["amount"] != null) {
final Amount amount = Decimal.parse(results["amount"]!).toAmount(
fractionDigits: coin.decimals,
fractionDigits: coin.fractionDigits,
);
cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format(
amount,
@ -232,15 +238,15 @@ class _SendViewState extends ConsumerState<SendView> {
ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1;
if (_price == Decimal.zero) {
amount = 0.toAmountAsRaw(fractionDigits: coin.decimals);
amount = 0.toAmountAsRaw(fractionDigits: coin.fractionDigits);
} else {
amount = baseAmount <= Amount.zero
? 0.toAmountAsRaw(fractionDigits: coin.decimals)
? 0.toAmountAsRaw(fractionDigits: coin.fractionDigits)
: (baseAmount.decimal / _price)
.toDecimal(
scaleOnInfinitePrecision: coin.decimals,
scaleOnInfinitePrecision: coin.fractionDigits,
)
.toAmount(fractionDigits: coin.decimals);
.toAmount(fractionDigits: coin.fractionDigits);
}
if (_cachedAmountToSend != null && _cachedAmountToSend == amount) {
return;
@ -258,7 +264,7 @@ class _SendViewState extends ConsumerState<SendView> {
cryptoAmountController.text = amountString;
_cryptoAmountChangeLock = false;
} else {
amount = 0.toAmountAsRaw(fractionDigits: coin.decimals);
amount = 0.toAmountAsRaw(fractionDigits: coin.fractionDigits);
_cryptoAmountChangeLock = true;
cryptoAmountController.text = "";
_cryptoAmountChangeLock = false;
@ -309,11 +315,11 @@ class _SendViewState extends ConsumerState<SendView> {
_cryptoAmountChangedFeeUpdateTimer?.cancel();
_cryptoAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () {
if (coin != Coin.epicCash && !_baseFocus.hasFocus) {
if (coin is! Epiccash && !_baseFocus.hasFocus) {
setState(() {
_calculateFeesFuture = calculateFees(
amount == null
? 0.toAmountAsRaw(fractionDigits: coin.decimals)
? 0.toAmountAsRaw(fractionDigits: coin.fractionDigits)
: amount!,
);
});
@ -330,11 +336,11 @@ class _SendViewState extends ConsumerState<SendView> {
void _baseAmountChanged() {
_baseAmountChangedFeeUpdateTimer?.cancel();
_baseAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () {
if (coin != Coin.epicCash && !_cryptoFocus.hasFocus) {
if (coin is! Epiccash && !_cryptoFocus.hasFocus) {
setState(() {
_calculateFeesFuture = calculateFees(
ref.read(pSendAmount) == null
? 0.toAmountAsRaw(fractionDigits: coin.decimals)
? 0.toAmountAsRaw(fractionDigits: coin.fractionDigits)
: ref.read(pSendAmount)!,
);
});
@ -356,8 +362,8 @@ class _SendViewState extends ConsumerState<SendView> {
final value = fee.contains(",")
? Decimal.parse(fee.replaceFirst(",", "."))
.toAmount(fractionDigits: coin.decimals)
: Decimal.parse(fee).toAmount(fractionDigits: coin.decimals);
.toAmount(fractionDigits: coin.fractionDigits)
: Decimal.parse(fee).toAmount(fractionDigits: coin.fractionDigits);
if (shouldSetState) {
setState(() => _currentFee = value);
@ -455,7 +461,7 @@ class _SendViewState extends ConsumerState<SendView> {
}
Amount fee;
if (coin == Coin.monero) {
if (coin is Monero) {
MoneroTransactionPriority specialMoneroId;
switch (ref.read(feeRateTypeStateProvider.state).state) {
case FeeRateType.fast:
@ -552,7 +558,7 @@ class _SendViewState extends ConsumerState<SendView> {
final coinControlEnabled =
ref.read(prefsChangeNotifierProvider).enableCoinControl;
if (coin != Coin.ethereum &&
if (coin is! Ethereum &&
!(wallet is CoinControlInterface && coinControlEnabled) ||
(wallet is CoinControlInterface &&
coinControlEnabled &&
@ -751,9 +757,7 @@ class _SendViewState extends ConsumerState<SendView> {
break;
}
} else {
final memo = coin == Coin.stellar || coin == Coin.stellarTestnet
? memoController.text
: null;
final memo = coin is Stellar ? memoController.text : null;
txDataFuture = wallet.prepareSend(
txData: TxData(
recipients: [
@ -878,16 +882,16 @@ class _SendViewState extends ConsumerState<SendView> {
void initState() {
coin = widget.coin;
ref.refresh(feeSheetSessionCacheProvider);
_currentFee = 0.toAmountAsRaw(fractionDigits: coin.decimals);
_currentFee = 0.toAmountAsRaw(fractionDigits: coin.fractionDigits);
_calculateFeesFuture =
calculateFees(0.toAmountAsRaw(fractionDigits: coin.decimals));
calculateFees(0.toAmountAsRaw(fractionDigits: coin.fractionDigits));
_data = widget.autoFillData;
walletId = widget.walletId;
clipboard = widget.clipboard;
scanner = widget.barcodeScanner;
isStellar = coin == Coin.stellar || coin == Coin.stellarTestnet;
isFiro = coin == Coin.firo || coin == Coin.firoTestNet;
isStellar = coin is Stellar;
isFiro = coin is Firo;
sendToController = TextEditingController();
cryptoAmountController = TextEditingController();
@ -905,7 +909,7 @@ class _SendViewState extends ConsumerState<SendView> {
if (_data!.amount != null) {
final amount = Amount.fromDecimal(
_data!.amount!,
fractionDigits: coin.decimals,
fractionDigits: coin.fractionDigits,
);
cryptoAmountController.text = ref.read(pAmountFormatter(coin)).format(
@ -927,7 +931,7 @@ class _SendViewState extends ConsumerState<SendView> {
noteController.text = "PayNym send";
}
// if (coin != Coin.epicCash) {
// if (coin is! Epiccash) {
// _cryptoFocus.addListener(() {
// if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) {
// if (_amountToSend == null) {
@ -1005,8 +1009,8 @@ class _SendViewState extends ConsumerState<SendView> {
ref.listen(publicPrivateBalanceStateProvider, (previous, next) {
if (ref.read(pSendAmount) == null) {
setState(() {
_calculateFeesFuture =
calculateFees(0.toAmountAsRaw(fractionDigits: coin.decimals));
_calculateFeesFuture = calculateFees(
0.toAmountAsRaw(fractionDigits: coin.fractionDigits));
});
} else {
setState(() {
@ -1019,7 +1023,7 @@ class _SendViewState extends ConsumerState<SendView> {
}
// add listener for epic cash to strip http:// and https:// prefixes if the address also ocntains an @ symbol (indicating an epicbox address)
if (coin == Coin.epicCash) {
if (coin is Epiccash) {
sendToController.addListener(() {
_address = sendToController.text.trim();
@ -1119,8 +1123,7 @@ class _SendViewState extends ConsumerState<SendView> {
style: STextStyles.label(context)
.copyWith(fontSize: 10),
),
if (coin != Coin.firo &&
coin != Coin.firoTestNet)
if (coin is! Firo)
Text(
"Available balance",
style: STextStyles.label(context)
@ -1233,7 +1236,7 @@ class _SendViewState extends ConsumerState<SendView> {
style: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),
// if (coin == Coin.monero)
// if (coin is Monero)
// CustomTextButton(
// text: "Use OpenAlias",
// onTap: () async {
@ -1359,8 +1362,7 @@ class _SendViewState extends ConsumerState<SendView> {
);
}
if (coin ==
Coin.epicCash) {
if (coin is Epiccash) {
// strip http:// and https:// if content contains @
content = formatAddress(
content,
@ -1433,10 +1435,7 @@ class _SendViewState extends ConsumerState<SendView> {
),
child: TextField(
key: const Key("sendViewMemoFieldKey"),
maxLength: (coin == Coin.firo ||
coin == Coin.firoTestNet)
? 31
: null,
maxLength: (coin is Firo) ? 31 : null,
controller: memoController,
readOnly: false,
autocorrect: false,
@ -1527,7 +1526,8 @@ class _SendViewState extends ConsumerState<SendView> {
_data!.contactLabel == _address) {
error = SparkInterface.validateSparkAddress(
address: _data!.address,
isTestNet: coin.isTestNet,
isTestNet: coin.network ==
CryptoCurrencyNetwork.test,
)
? "Unsupported"
: null;
@ -1733,7 +1733,7 @@ class _SendViewState extends ConsumerState<SendView> {
style: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),
if (coin != Coin.ethereum && coin != Coin.tezos)
if (coin is! Ethereum && coin is! Tezos)
CustomTextButton(
text: "Send all ${coin.ticker}",
onTap: () async {
@ -1815,7 +1815,7 @@ class _SendViewState extends ConsumerState<SendView> {
textAlign: TextAlign.right,
inputFormatters: [
AmountInputFormatter(
decimals: coin.decimals,
decimals: coin.fractionDigits,
unit: ref.watch(pAmountUnit(coin)),
locale: locale,
),
@ -1825,7 +1825,7 @@ class _SendViewState extends ConsumerState<SendView> {
// newValue) =>
// // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$')
// // RegExp(r'^\d{1,3}([,\.]\d+)?|[,\.\d]+$')
// getAmountRegex(locale, coin.decimals)
// getAmountRegex(locale, coin.fractionDigits)
// .hasMatch(newValue.text)
// ? newValue
// : oldValue),
@ -2001,17 +2001,17 @@ class _SendViewState extends ConsumerState<SendView> {
const SizedBox(
height: 12,
),
if (coin == Coin.epicCash)
if (coin is Epiccash)
Text(
"On chain Note (optional)",
style: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),
if (coin == Coin.epicCash)
if (coin is Epiccash)
const SizedBox(
height: 8,
),
if (coin == Coin.epicCash)
if (coin is Epiccash)
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
@ -2055,12 +2055,12 @@ class _SendViewState extends ConsumerState<SendView> {
),
),
),
if (coin == Coin.epicCash)
if (coin is Epiccash)
const SizedBox(
height: 12,
),
Text(
(coin == Coin.epicCash)
(coin is Epiccash)
? "Local Note (optional)"
: "Note (optional)",
style: STextStyles.smallMed12(context),
@ -2111,26 +2111,23 @@ class _SendViewState extends ConsumerState<SendView> {
const SizedBox(
height: 12,
),
if (coin != Coin.epicCash &&
coin != Coin.nano &&
coin != Coin.banano &&
coin != Coin.tezos)
if (coin is! Epiccash &&
coin is! NanoCurrency &&
coin is! Tezos)
Text(
"Transaction fee (estimated)",
style: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),
if (coin != Coin.epicCash &&
coin != Coin.nano &&
coin != Coin.banano &&
coin != Coin.tezos)
if (coin is! Epiccash &&
coin is! NanoCurrency &&
coin is! Tezos)
const SizedBox(
height: 8,
),
if (coin != Coin.epicCash &&
coin != Coin.nano &&
coin != Coin.banano &&
coin != Coin.tezos)
if (coin is! Epiccash &&
coin is! NanoCurrency &&
coin is! Tezos)
Stack(
children: [
TextField(
@ -2187,7 +2184,8 @@ class _SendViewState extends ConsumerState<SendView> {
?.decimal ??
Decimal.zero)
.toAmount(
fractionDigits: coin.decimals,
fractionDigits:
coin.fractionDigits,
),
updateChosen: (String fee) {
if (fee == "custom") {

View file

@ -14,9 +14,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/themes/coin_image_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/animated_widgets/rotating_arrows.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
@ -30,7 +30,7 @@ class BuildingTransactionDialog extends ConsumerStatefulWidget {
});
final VoidCallback onCancel;
final Coin coin;
final CryptoCurrency coin;
final bool isSpark;
@override

View file

@ -13,23 +13,23 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lottie/lottie.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/coin_image_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
class SendingTransactionDialog extends ConsumerStatefulWidget {
const SendingTransactionDialog({
Key? key,
super.key,
required this.coin,
required this.controller,
}) : super(key: key);
});
final Coin coin;
final CryptoCurrency coin;
final ProgressAndSuccessController controller;
@override

View file

@ -19,10 +19,14 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.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/monero.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/wownero.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.dart';
@ -44,12 +48,12 @@ class FeeSheetSessionCache extends ChangeNotifier {
class TransactionFeeSelectionSheet extends ConsumerStatefulWidget {
const TransactionFeeSelectionSheet({
Key? key,
super.key,
required this.walletId,
required this.amount,
required this.updateChosen,
this.isToken = false,
}) : super(key: key);
});
final String walletId;
final Amount amount;
@ -79,7 +83,7 @@ class _TransactionFeeSelectionSheetState
required Amount amount,
required FeeRateType feeRateType,
required int feeRate,
required Coin coin,
required CryptoCurrency coin,
}) async {
switch (feeRateType) {
case FeeRateType.fast:
@ -87,11 +91,13 @@ class _TransactionFeeSelectionSheetState
if (widget.isToken == false) {
final wallet = ref.read(pWallets).getWallet(walletId);
if (coin == Coin.monero || coin == Coin.wownero) {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount, MoneroTransactionPriority.fast.raw!);
amount,
MoneroTransactionPriority.fast.raw!,
);
ref.read(feeSheetSessionCacheProvider).fast[amount] = fee;
} else if (coin == Coin.firo || coin == Coin.firoTestNet) {
} else if (coin is Firo) {
final Amount fee;
switch (ref.read(publicPrivateBalanceStateProvider.state).state) {
case FiroType.spark:
@ -122,11 +128,13 @@ class _TransactionFeeSelectionSheetState
if (ref.read(feeSheetSessionCacheProvider).average[amount] == null) {
if (widget.isToken == false) {
final wallet = ref.read(pWallets).getWallet(walletId);
if (coin == Coin.monero || coin == Coin.wownero) {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount, MoneroTransactionPriority.regular.raw!);
amount,
MoneroTransactionPriority.regular.raw!,
);
ref.read(feeSheetSessionCacheProvider).average[amount] = fee;
} else if (coin == Coin.firo || coin == Coin.firoTestNet) {
} else if (coin is Firo) {
final Amount fee;
switch (ref.read(publicPrivateBalanceStateProvider.state).state) {
case FiroType.spark:
@ -156,11 +164,13 @@ class _TransactionFeeSelectionSheetState
if (ref.read(feeSheetSessionCacheProvider).slow[amount] == null) {
if (widget.isToken == false) {
final wallet = ref.read(pWallets).getWallet(walletId);
if (coin == Coin.monero || coin == Coin.wownero) {
if (coin is Monero || coin is Wownero) {
final fee = await wallet.estimateFeeFor(
amount, MoneroTransactionPriority.slow.raw!);
amount,
MoneroTransactionPriority.slow.raw!,
);
ref.read(feeSheetSessionCacheProvider).slow[amount] = fee;
} else if (coin == Coin.firo || coin == Coin.firoTestNet) {
} else if (coin is Firo) {
final Amount fee;
switch (ref.read(publicPrivateBalanceStateProvider.state).state) {
case FiroType.spark:
@ -192,10 +202,12 @@ class _TransactionFeeSelectionSheetState
}
String estimatedTimeToBeIncludedInNextBlock(
int targetBlockTime, int estimatedNumberOfBlocks) {
int time = targetBlockTime * estimatedNumberOfBlocks;
int targetBlockTime,
int estimatedNumberOfBlocks,
) {
final int time = targetBlockTime * estimatedNumberOfBlocks;
int hours = (time / 3600).floor();
final int hours = (time / 3600).floor();
if (hours > 1) {
return "~$hours hours";
} else if (hours == 1) {
@ -295,7 +307,7 @@ class _TransactionFeeSelectionSheetState
ref.read(feeRateTypeStateProvider.state).state =
FeeRateType.fast;
}
String? fee =
final String? fee =
getAmount(FeeRateType.fast, wallet.info.coin);
if (fee != null) {
widget.updateChosen(fee);
@ -364,8 +376,10 @@ class _TransactionFeeSelectionSheetState
feeRate: feeObject!.fast,
amount: amount,
),
builder: (_,
AsyncSnapshot<Amount> snapshot) {
builder: (
_,
AsyncSnapshot<Amount> snapshot,
) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
@ -380,7 +394,8 @@ class _TransactionFeeSelectionSheetState
false,
)})",
style: STextStyles.itemSubtitle(
context),
context,
),
textAlign: TextAlign.left,
);
} else {
@ -388,7 +403,8 @@ class _TransactionFeeSelectionSheetState
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle(
context),
context,
),
);
}
},
@ -398,19 +414,16 @@ class _TransactionFeeSelectionSheetState
const SizedBox(
height: 2,
),
if (feeObject == null &&
coin != Coin.ethereum)
if (feeObject == null && coin is! Ethereum)
AnimatedText(
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle(context),
),
if (feeObject != null &&
coin != Coin.ethereum)
if (feeObject != null && coin is! Ethereum)
Text(
estimatedTimeToBeIncludedInNextBlock(
Constants.targetBlockTimeInSeconds(
coin),
coin.targetBlockTimeSeconds,
feeObject!.numberOfBlocksFast,
),
style: STextStyles.itemSubtitle(context),
@ -418,7 +431,7 @@ class _TransactionFeeSelectionSheetState
),
],
),
)
),
],
),
),
@ -434,7 +447,8 @@ class _TransactionFeeSelectionSheetState
ref.read(feeRateTypeStateProvider.state).state =
FeeRateType.average;
}
String? fee = getAmount(FeeRateType.average, coin);
final String? fee =
getAmount(FeeRateType.average, coin);
if (fee != null) {
widget.updateChosen(fee);
}
@ -500,8 +514,10 @@ class _TransactionFeeSelectionSheetState
feeRate: feeObject!.medium,
amount: amount,
),
builder: (_,
AsyncSnapshot<Amount> snapshot) {
builder: (
_,
AsyncSnapshot<Amount> snapshot,
) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
@ -516,7 +532,8 @@ class _TransactionFeeSelectionSheetState
false,
)})",
style: STextStyles.itemSubtitle(
context),
context,
),
textAlign: TextAlign.left,
);
} else {
@ -524,7 +541,8 @@ class _TransactionFeeSelectionSheetState
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle(
context),
context,
),
);
}
},
@ -534,19 +552,16 @@ class _TransactionFeeSelectionSheetState
const SizedBox(
height: 2,
),
if (feeObject == null &&
coin != Coin.ethereum)
if (feeObject == null && coin is! Ethereum)
AnimatedText(
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle(context),
),
if (feeObject != null &&
coin != Coin.ethereum)
if (feeObject != null && coin is! Ethereum)
Text(
estimatedTimeToBeIncludedInNextBlock(
Constants.targetBlockTimeInSeconds(
coin),
coin.targetBlockTimeSeconds,
feeObject!.numberOfBlocksAverage,
),
style: STextStyles.itemSubtitle(context),
@ -570,7 +585,7 @@ class _TransactionFeeSelectionSheetState
ref.read(feeRateTypeStateProvider.state).state =
FeeRateType.slow;
}
String? fee = getAmount(FeeRateType.slow, coin);
final String? fee = getAmount(FeeRateType.slow, coin);
if (fee != null) {
widget.updateChosen(fee);
}
@ -636,8 +651,10 @@ class _TransactionFeeSelectionSheetState
feeRate: feeObject!.slow,
amount: amount,
),
builder: (_,
AsyncSnapshot<Amount> snapshot) {
builder: (
_,
AsyncSnapshot<Amount> snapshot,
) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
@ -652,7 +669,8 @@ class _TransactionFeeSelectionSheetState
false,
)})",
style: STextStyles.itemSubtitle(
context),
context,
),
textAlign: TextAlign.left,
);
} else {
@ -660,7 +678,8 @@ class _TransactionFeeSelectionSheetState
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle(
context),
context,
),
);
}
},
@ -670,19 +689,16 @@ class _TransactionFeeSelectionSheetState
const SizedBox(
height: 2,
),
if (feeObject == null &&
coin != Coin.ethereum)
if (feeObject == null && coin is! Ethereum)
AnimatedText(
stringsToLoopThrough:
stringsToLoopThrough,
style: STextStyles.itemSubtitle(context),
),
if (feeObject != null &&
coin != Coin.ethereum)
if (feeObject != null && coin is! Ethereum)
Text(
estimatedTimeToBeIncludedInNextBlock(
Constants.targetBlockTimeInSeconds(
coin),
coin.targetBlockTimeSeconds,
feeObject!.numberOfBlocksSlow,
),
style: STextStyles.itemSubtitle(context),
@ -732,7 +748,8 @@ class _TransactionFeeSelectionSheetState
onChanged: (x) {
ref
.read(
feeRateTypeStateProvider.state)
feeRateTypeStateProvider.state,
)
.state = FeeRateType.custom;
Navigator.of(context).pop();
},
@ -781,7 +798,7 @@ class _TransactionFeeSelectionSheetState
);
}
String? getAmount(FeeRateType feeRateType, Coin coin) {
String? getAmount(FeeRateType feeRateType, CryptoCurrency coin) {
try {
switch (feeRateType) {
case FeeRateType.fast:

View file

@ -34,12 +34,13 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/epiccash.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
import 'package:stackwallet/wallets/isar/providers/eth/token_balance_provider.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
@ -70,7 +71,7 @@ class TokenSendView extends ConsumerStatefulWidget {
static const String routeName = "/tokenSendView";
final String walletId;
final Coin coin;
final CryptoCurrency coin;
final EthContract tokenContract;
final SendViewAutoFillData? autoFillData;
final ClipboardInterface clipboard;
@ -82,7 +83,7 @@ class TokenSendView extends ConsumerStatefulWidget {
class _TokenSendViewState extends ConsumerState<TokenSendView> {
late final String walletId;
late final Coin coin;
late final CryptoCurrency coin;
late final EthContract tokenContract;
late final ClipboardInterface clipboard;
late final BarcodeScannerInterface scanner;
@ -317,7 +318,7 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
_cryptoAmountChangedFeeUpdateTimer?.cancel();
_cryptoAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () {
if (coin != Coin.epicCash && !_baseFocus.hasFocus) {
if (coin is! Epiccash && !_baseFocus.hasFocus) {
setState(() {
_calculateFeesFuture = calculateFees();
});
@ -329,7 +330,7 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
void _baseAmountChanged() {
_baseAmountChangedFeeUpdateTimer?.cancel();
_baseAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () {
if (coin != Coin.epicCash && !_cryptoFocus.hasFocus) {
if (coin is! Epiccash && !_cryptoFocus.hasFocus) {
setState(() {
_calculateFeesFuture = calculateFees();
});
@ -1161,7 +1162,7 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
const SizedBox(
height: 12,
),
if (coin != Coin.epicCash)
if (coin is! Epiccash)
Text(
"Transaction fee (estimated)",
style: STextStyles.smallMed12(context),

View file

@ -4,16 +4,16 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/amount/amount_unit.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/wallets/crypto_currency/crypto_currency.dart';
class ChooseUnitSheet extends ConsumerStatefulWidget {
const ChooseUnitSheet({
Key? key,
super.key,
required this.coin,
}) : super(key: key);
});
final Coin coin;
final CryptoCurrency coin;
@override
ConsumerState<ChooseUnitSheet> createState() => _ChooseUnitSheetState();

View file

@ -9,9 +9,9 @@ import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/amount/amount_unit.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/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -25,11 +25,11 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart';
class EditCoinUnitsView extends ConsumerStatefulWidget {
const EditCoinUnitsView({
Key? key,
super.key,
required this.coin,
}) : super(key: key);
});
final Coin coin;
final CryptoCurrency coin;
static const String routeName = "/editCoinUnitsView";

View file

@ -5,12 +5,14 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/edit_coin_units_view.dart';
import 'package:stackwallet/providers/global/prefs_provider.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/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -19,11 +21,11 @@ import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class ManageCoinUnitsView extends ConsumerWidget {
const ManageCoinUnitsView({Key? key}) : super(key: key);
const ManageCoinUnitsView({super.key});
static const String routeName = "/manageCoinUnitsView";
void onEditPressed(Coin coin, BuildContext context) {
void onEditPressed(CryptoCurrency coin, BuildContext context) {
if (Util.isDesktop) {
showDialog<void>(
context: context,
@ -39,14 +41,17 @@ class ManageCoinUnitsView extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
bool showTestNet = ref.watch(
final showTestNet = ref.watch(
prefsChangeNotifierProvider.select((value) => value.showTestNetCoins),
);
final _coins = Coin.values.where((e) => e != Coin.firoTestNet).toList();
final _coins = SupportedCoins.cryptocurrencies
.where((e) => e is! Firo && e.network != CryptoCurrencyNetwork.test)
.toList();
List<Coin> coins =
showTestNet ? _coins : _coins.where((e) => !e.isTestNet).toList();
final coins = showTestNet
? _coins
: _coins.where((e) => e.network != CryptoCurrencyNetwork.test).toList();
return ConditionalParent(
condition: Util.isDesktop,

View file

@ -12,21 +12,21 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/block_explorers.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class ManageExplorerView extends ConsumerStatefulWidget {
const ManageExplorerView({
Key? key,
super.key,
required this.coin,
}) : super(key: key);
});
static const String routeName = "/manageExplorer";
final Coin coin;
final CryptoCurrency coin;
@override
ConsumerState<ManageExplorerView> createState() => _ManageExplorerViewState();

View file

@ -19,8 +19,9 @@ 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/wallets/crypto_currency/coins/stellar.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.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';
@ -74,42 +75,46 @@ class HiddenSettings extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Consumer(builder: (_, ref, __) {
return GestureDetector(
onTap: () async {
final notifs =
ref.read(notificationsProvider).notifications;
Consumer(
builder: (_, ref, __) {
return GestureDetector(
onTap: () async {
final notifs = ref
.read(notificationsProvider)
.notifications;
for (final n in notifs) {
for (final n in notifs) {
await ref
.read(notificationsProvider)
.delete(n, false);
}
await ref
.read(notificationsProvider)
.delete(n, false);
}
await ref
.read(notificationsProvider)
.delete(notifs[0], true);
.delete(notifs[0], true);
if (context.mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.success,
message: "Notification history deleted",
context: context,
),
);
}
},
child: RoundedWhiteContainer(
child: Text(
"Delete notifications",
style: STextStyles.button(context).copyWith(
if (context.mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.success,
message: "Notification history deleted",
context: context,
),
);
}
},
child: RoundedWhiteContainer(
child: Text(
"Delete notifications",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
.accentColorDark,
),
),
),
),
);
}),
);
},
),
// const SizedBox(
// height: 12,
// ),
@ -141,34 +146,37 @@ class HiddenSettings extends StatelessWidget {
const SizedBox(
height: 12,
),
Consumer(builder: (_, ref, __) {
return GestureDetector(
onTap: () async {
await ref
.read(debugServiceProvider)
.deleteAllLogs();
Consumer(
builder: (_, ref, __) {
return GestureDetector(
onTap: () async {
await ref
.read(debugServiceProvider)
.deleteAllLogs();
if (context.mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.success,
message: "Debug Logs deleted",
context: context,
),
);
}
},
child: RoundedWhiteContainer(
child: Text(
"Delete Debug Logs",
style: STextStyles.button(context).copyWith(
if (context.mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.success,
message: "Debug Logs deleted",
context: context,
),
);
}
},
child: RoundedWhiteContainer(
child: Text(
"Delete Debug Logs",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
.accentColorDark,
),
),
),
),
);
}),
);
},
),
const SizedBox(
height: 12,
),
@ -216,8 +224,10 @@ class HiddenSettings extends StatelessWidget {
// ),
Consumer(
builder: (_, ref, __) {
if (ref.watch(prefsChangeNotifierProvider
.select((value) => value.familiarity)) <
if (ref.watch(
prefsChangeNotifierProvider
.select((value) => value.familiarity),
) <
6) {
return GestureDetector(
onTap: () async {
@ -236,9 +246,10 @@ class HiddenSettings extends StatelessWidget {
child: Text(
"Enable exchange",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
),
);
@ -257,7 +268,7 @@ class HiddenSettings extends StatelessWidget {
await showDialog<bool>(
context: context,
builder: (_) => TorWarningDialog(
coin: Coin.stellar,
coin: Stellar(CryptoCurrencyNetwork.main),
),
);
},
@ -265,9 +276,10 @@ class HiddenSettings extends StatelessWidget {
child: Text(
"Show Tor warning popup",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
),
);
@ -286,9 +298,10 @@ class HiddenSettings extends StatelessWidget {
child: Text(
"Do nothing",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
),
),
);

View file

@ -14,26 +14,23 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:solana/solana.dart';
import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/providers/global/secure_store_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/tor_service.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/connection_check/electrum_connection_check.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/test_epic_box_connection.dart';
import 'package:stackwallet/utilities/test_eth_node_connection.dart';
import 'package:stackwallet/utilities/test_monero_node_connection.dart';
import 'package:stackwallet/utilities/test_stellar_node_connection.dart';
import 'package:stackwallet/utilities/test_node_connection.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/api/tezos/tezos_rpc_api.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/monero.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/wownero.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/cryptonote_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -51,17 +48,17 @@ enum AddEditNodeViewType { add, edit }
class AddEditNodeView extends ConsumerStatefulWidget {
const AddEditNodeView({
Key? key,
super.key,
required this.viewType,
required this.coin,
required this.nodeId,
required this.routeOnSuccessOrDelete,
}) : super(key: key);
});
static const String routeName = "/addEditNode";
final AddEditNodeViewType viewType;
final Coin coin;
final CryptoCurrency coin;
final String routeOnSuccessOrDelete;
final String? nodeId;
@ -71,192 +68,31 @@ class AddEditNodeView extends ConsumerStatefulWidget {
class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
late final AddEditNodeViewType viewType;
late final Coin coin;
late final CryptoCurrency coin;
late final String? nodeId;
late final bool isDesktop;
late bool saveEnabled;
late bool testConnectionEnabled;
Future<bool> _xmrHelper(String url, int? port) async {
final uri = Uri.parse(url);
final String path = uri.path.isEmpty ? "/json_rpc" : uri.path;
final uriString = "${uri.scheme}://${uri.host}:${port ?? 0}$path";
ref.read(nodeFormDataProvider).useSSL = true;
final response = await testMoneroNodeConnection(
Uri.parse(uriString),
false,
);
if (response.cert != null) {
if (mounted) {
final shouldAllowBadCert = await showBadX509CertificateDialog(
response.cert!,
response.url!,
response.port!,
context,
);
if (shouldAllowBadCert) {
final response =
await testMoneroNodeConnection(Uri.parse(uriString), true);
ref.read(nodeFormDataProvider).host = url;
return response.success;
}
}
} else {
ref.read(nodeFormDataProvider).host = url;
return response.success;
void _onTestSuccess(NodeFormData data) {
if (coin is Epiccash) {
ref.read(nodeFormDataProvider).host = data.host;
ref.read(nodeFormDataProvider).port = data.port;
ref.read(nodeFormDataProvider).useSSL = data.useSSL;
} else if (coin is CryptonoteCurrency) {
ref.read(nodeFormDataProvider).host = data.host;
}
return false;
}
Future<bool> _testConnection({bool showFlushBar = true}) async {
final formData = ref.read(nodeFormDataProvider);
bool testPassed = false;
switch (coin) {
case Coin.epicCash:
try {
final data = await testEpicNodeConnection(formData);
if (data != null) {
testPassed = true;
ref.read(nodeFormDataProvider).host = data.host;
ref.read(nodeFormDataProvider).port = data.port;
ref.read(nodeFormDataProvider).useSSL = data.useSSL;
}
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning);
}
break;
case Coin.monero:
case Coin.wownero:
try {
final url = formData.host!;
final uri = Uri.tryParse(url);
if (uri != null) {
if (!uri.hasScheme) {
// try https first
testPassed = await _xmrHelper("https://$url", formData.port);
if (testPassed == false) {
// try http
testPassed = await _xmrHelper("http://$url", formData.port);
}
} else {
testPassed = await _xmrHelper(url, formData.port);
}
}
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning);
}
break;
case Coin.bitcoin:
case Coin.bitcoincash:
case Coin.litecoin:
case Coin.dogecoin:
case Coin.eCash:
case Coin.firo:
case Coin.namecoin:
case Coin.particl:
case Coin.peercoin:
case Coin.peercoinTestNet:
case Coin.bitcoinFrost:
case Coin.bitcoinFrostTestNet:
case Coin.bitcoinTestNet:
case Coin.litecoinTestNet:
case Coin.bitcoincashTestnet:
case Coin.firoTestNet:
case Coin.dogecoinTestNet:
try {
testPassed = await checkElectrumServer(
host: formData.host!,
port: formData.port!,
useSSL: formData.useSSL!,
overridePrefs: ref.read(prefsChangeNotifierProvider),
overrideTorService: ref.read(pTorService),
);
} catch (_) {
testPassed = false;
}
break;
case Coin.ethereum:
try {
testPassed = await testEthNodeConnection(formData.host!);
} catch (_) {
testPassed = false;
}
break;
case Coin.stellar:
case Coin.stellarTestnet:
try {
testPassed =
await testStellarNodeConnection(formData.host!, formData.port!);
} catch (_) {}
break;
case Coin.nano:
case Coin.banano:
throw UnimplementedError();
//TODO: check network/node
case Coin.tezos:
try {
testPassed = await TezosRpcAPI.testNetworkConnection(
nodeInfo: (host: formData.host!, port: formData.port!),
);
} catch (_) {}
break;
case Coin.solana:
try {
RpcClient rpcClient;
if (formData.host!.startsWith("http") ||
formData.host!.startsWith("https")) {
rpcClient = RpcClient("${formData.host}:${formData.port}");
} else {
rpcClient = RpcClient("http://${formData.host}:${formData.port}");
}
await rpcClient.getEpochInfo().then((value) => testPassed = true);
} catch (_) {
testPassed = false;
}
break;
}
if (showFlushBar && mounted) {
if (testPassed) {
unawaited(showFloatingFlushBar(
type: FlushBarType.success,
message: "Server ping success",
context: context,
));
} else {
unawaited(showFloatingFlushBar(
type: FlushBarType.warning,
message: "Server unreachable",
context: context,
));
}
}
return testPassed;
}
Future<void> attemptSave() async {
final canConnect = await _testConnection(showFlushBar: false);
final canConnect = await testNodeConnection(
context: context,
onSuccess: _onTestSuccess,
cryptoCurrency: coin,
nodeFormData: ref.read(nodeFormDataProvider),
ref: ref,
);
bool? shouldSave;
@ -387,7 +223,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
// strip unused path
String address = formData.host!;
if (coin == Coin.monero || coin == Coin.wownero) {
if (coin is Monero || coin is Wownero) {
if (address.startsWith("http")) {
final uri = Uri.parse(address);
address = "${uri.scheme}://${uri.host}";
@ -404,7 +240,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
useSSL: formData.useSSL!,
loginName: formData.login,
enabled: true,
coinName: coin.name,
coinName: coin.identifier,
isFailover: formData.isFailover!,
trusted: formData.trusted!,
isDown: false,
@ -429,7 +265,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
useSSL: formData.useSSL!,
loginName: formData.login,
enabled: true,
coinName: coin.name,
coinName: coin.identifier,
isFailover: formData.isFailover!,
trusted: formData.trusted!,
isDown: false,
@ -652,7 +488,32 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
buttonHeight: isDesktop ? ButtonHeight.l : null,
onPressed: testConnectionEnabled
? () async {
await _testConnection();
final testPassed = await testNodeConnection(
context: context,
onSuccess: _onTestSuccess,
cryptoCurrency: coin,
nodeFormData: ref.read(nodeFormDataProvider),
ref: ref,
);
if (context.mounted) {
if (testPassed) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.success,
message: "Server ping success",
context: context,
),
);
} else {
unawaited(
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Server unreachable",
context: context,
),
);
}
}
}
: null,
),
@ -724,7 +585,7 @@ class NodeForm extends ConsumerStatefulWidget {
final NodeModel? node;
final SecureStorageInterface secureStore;
final bool readOnly;
final Coin coin;
final CryptoCurrency coin;
final void Function(bool canSave, bool canTestConnection)? onChanged;
@override
@ -754,39 +615,15 @@ class _NodeFormState extends ConsumerState<NodeForm> {
void Function(bool canSave, bool canTestConnection)? onChanged;
bool _checkShouldEnableAuthFields(Coin coin) {
bool _checkShouldEnableAuthFields(CryptoCurrency coin) {
// TODO: which coin servers can have username and password?
switch (coin) {
case Coin.bitcoin:
case Coin.litecoin:
case Coin.dogecoin:
case Coin.firo:
case Coin.namecoin:
case Coin.bitcoincash:
case Coin.particl:
case Coin.peercoin:
case Coin.peercoinTestNet:
case Coin.tezos:
case Coin.bitcoinTestNet:
case Coin.litecoinTestNet:
case Coin.bitcoincashTestnet:
case Coin.firoTestNet:
case Coin.dogecoinTestNet:
case Coin.epicCash:
case Coin.nano:
case Coin.banano:
case Coin.eCash:
case Coin.solana:
case Coin.stellar:
case Coin.stellarTestnet:
case Coin.bitcoinFrost:
case Coin.bitcoinFrostTestNet:
return false;
case Coin.ethereum:
case Coin.monero:
case Coin.wownero:
case Ethereum():
case CryptonoteCurrency():
return true;
default:
return false;
}
}
@ -862,7 +699,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
_useSSL = node.useSSL;
_isFailover = node.isFailover;
_trusted = node.trusted ?? false;
if (widget.coin == Coin.epicCash) {
if (widget.coin is Epiccash) {
enableSSLCheckbox = !node.host.startsWith("http");
} else {
enableSSLCheckbox = true;
@ -961,9 +798,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
focusNode: _hostFocusNode,
style: STextStyles.field(context),
decoration: standardInputDecoration(
(widget.coin != Coin.monero && widget.coin != Coin.wownero)
? "IP address"
: "Url",
(widget.coin is! CryptonoteCurrency) ? "IP address" : "Url",
_hostFocusNode,
context,
).copyWith(
@ -987,7 +822,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
: null,
),
onChanged: (newValue) {
if (widget.coin == Coin.epicCash) {
if (widget.coin is Epiccash) {
if (newValue.startsWith("https://")) {
_useSSL = true;
enableSSLCheckbox = false;
@ -1151,7 +986,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
const SizedBox(
height: 8,
),
if (widget.coin != Coin.monero && widget.coin != Coin.wownero)
if (widget.coin is! CryptonoteCurrency)
Row(
children: [
GestureDetector(
@ -1202,7 +1037,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
),
],
),
if (widget.coin == Coin.monero || widget.coin == Coin.wownero)
if (widget.coin is Monero || widget.coin is Wownero)
Row(
children: [
GestureDetector(
@ -1253,15 +1088,11 @@ class _NodeFormState extends ConsumerState<NodeForm> {
),
],
),
if (widget.coin != Coin.monero &&
widget.coin != Coin.wownero &&
widget.coin != Coin.epicCash)
if (widget.coin is! CryptonoteCurrency && widget.coin is! Epiccash)
const SizedBox(
height: 8,
),
if (widget.coin != Coin.monero &&
widget.coin != Coin.wownero &&
widget.coin != Coin.epicCash)
if (widget.coin is! CryptonoteCurrency && widget.coin is! Epiccash)
Row(
children: [
GestureDetector(

View file

@ -18,9 +18,9 @@ import 'package:stackwallet/pages/settings_views/sub_widgets/nodes_list.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
@ -30,14 +30,14 @@ import 'package:tuple/tuple.dart';
class CoinNodesView extends ConsumerStatefulWidget {
const CoinNodesView({
Key? key,
super.key,
required this.coin,
this.rootNavigator = false,
}) : super(key: key);
});
static const String routeName = "/coinNodes";
final Coin coin;
final CryptoCurrency coin;
final bool rootNavigator;
@override

View file

@ -15,19 +15,21 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.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/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class ManageNodesView extends ConsumerStatefulWidget {
const ManageNodesView({
Key? key,
}) : super(key: key);
super.key,
});
static const String routeName = "/manageNodes";
@ -36,12 +38,14 @@ class ManageNodesView extends ConsumerStatefulWidget {
}
class _ManageNodesViewState extends ConsumerState<ManageNodesView> {
List<Coin> _coins = [...Coin.values];
List<CryptoCurrency> _coins = [...SupportedCoins.cryptocurrencies];
@override
void initState() {
_coins = _coins.toList();
_coins.remove(Coin.firoTestNet);
_coins.removeWhere(
(e) => e is Firo && e.network == CryptoCurrencyNetwork.test,
);
super.initState();
}
@ -52,12 +56,13 @@ class _ManageNodesViewState extends ConsumerState<ManageNodesView> {
@override
Widget build(BuildContext context) {
bool showTestNet = ref.watch(
final showTestNet = ref.watch(
prefsChangeNotifierProvider.select((value) => value.showTestNetCoins),
);
List<Coin> coins =
showTestNet ? _coins : _coins.where((e) => !e.isTestNet).toList();
final coins = showTestNet
? _coins
: _coins.where((e) => e.network != CryptoCurrencyNetwork.test).toList();
return Background(
child: Scaffold(

View file

@ -13,25 +13,17 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:solana/solana.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart';
import 'package:stackwallet/providers/global/secure_store_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/tor_service.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/connection_check/electrum_connection_check.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/test_epic_box_connection.dart';
import 'package:stackwallet/utilities/test_eth_node_connection.dart';
import 'package:stackwallet/utilities/test_monero_node_connection.dart';
import 'package:stackwallet/utilities/test_stellar_node_connection.dart';
import 'package:stackwallet/utilities/test_node_connection.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/api/tezos/tezos_rpc_api.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -43,15 +35,15 @@ import 'package:tuple/tuple.dart';
class NodeDetailsView extends ConsumerStatefulWidget {
const NodeDetailsView({
Key? key,
super.key,
required this.coin,
required this.nodeId,
required this.popRouteName,
}) : super(key: key);
});
static const String routeName = "/nodeDetails";
final Coin coin;
final CryptoCurrency coin;
final String nodeId;
final String popRouteName;
@ -61,7 +53,7 @@ class NodeDetailsView extends ConsumerStatefulWidget {
class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
late final SecureStorageInterface secureStore;
late final Coin coin;
late final CryptoCurrency coin;
late final String nodeId;
late final String popRouteName;
@ -76,170 +68,19 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
super.initState();
}
Future<void> _testConnection(WidgetRef ref, BuildContext context) async {
final node =
ref.watch(nodeServiceChangeNotifierProvider).getNodeById(id: nodeId);
bool testPassed = false;
switch (coin) {
case Coin.epicCash:
try {
testPassed = await testEpicNodeConnection(
NodeFormData()
..host = node!.host
..useSSL = node.useSSL
..port = node.port,
) !=
null;
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning);
testPassed = false;
}
break;
case Coin.monero:
case Coin.wownero:
try {
final uri = Uri.parse(node!.host);
if (uri.scheme.startsWith("http")) {
final String path = uri.path.isEmpty ? "/json_rpc" : uri.path;
String uriString = "${uri.scheme}://${uri.host}:${node.port}$path";
final response = await testMoneroNodeConnection(
Uri.parse(uriString),
false,
);
if (response.cert != null) {
if (mounted) {
final shouldAllowBadCert = await showBadX509CertificateDialog(
response.cert!,
response.url!,
response.port!,
context,
);
if (shouldAllowBadCert) {
final response = await testMoneroNodeConnection(
Uri.parse(uriString), true);
testPassed = response.success;
}
}
} else {
testPassed = response.success;
}
}
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Warning);
}
break;
case Coin.bitcoin:
case Coin.litecoin:
case Coin.dogecoin:
case Coin.firo:
case Coin.particl:
case Coin.peercoin:
case Coin.peercoinTestNet:
case Coin.bitcoinTestNet:
case Coin.firoTestNet:
case Coin.dogecoinTestNet:
case Coin.bitcoincash:
case Coin.namecoin:
case Coin.litecoinTestNet:
case Coin.bitcoincashTestnet:
case Coin.eCash:
case Coin.bitcoinFrost:
case Coin.bitcoinFrostTestNet:
try {
testPassed = await checkElectrumServer(
host: node!.host,
port: node.port,
useSSL: node.useSSL,
overridePrefs: ref.read(prefsChangeNotifierProvider),
overrideTorService: ref.read(pTorService),
);
} catch (_) {
testPassed = false;
}
break;
case Coin.ethereum:
try {
testPassed = await testEthNodeConnection(node!.host);
} catch (_) {
testPassed = false;
}
break;
case Coin.nano:
case Coin.banano:
// TODO: fix this lacking code
throw UnimplementedError();
//TODO: check network/node
case Coin.tezos:
try {
testPassed = await TezosRpcAPI.testNetworkConnection(
nodeInfo: (host: node!.host, port: node!.port),
);
} catch (_) {}
break;
case Coin.stellar:
case Coin.stellarTestnet:
try {
testPassed = await testStellarNodeConnection(node!.host, node.port);
} catch (_) {
testPassed = false;
}
break;
case Coin.solana:
try {
RpcClient rpcClient;
if (node!.host.startsWith("http") || node.host.startsWith("https")) {
rpcClient = RpcClient("${node.host}:${node.port}");
} else {
rpcClient = RpcClient("http://${node.host}:${node.port}");
}
await rpcClient.getEpochInfo().then((value) => testPassed = true);
} catch (_) {
testPassed = false;
}
break;
}
if (testPassed) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.success,
message: "Server ping success",
context: context,
),
);
} else {
unawaited(
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Server unreachable",
context: context,
),
);
}
}
@override
Widget build(BuildContext context) {
final isDesktop = Util.isDesktop;
final node = ref.watch(nodeServiceChangeNotifierProvider
.select((value) => value.getNodeById(id: nodeId)));
final node = ref.watch(
nodeServiceChangeNotifierProvider
.select((value) => value.getNodeById(id: nodeId)),
);
final nodesForCoin = ref.watch(nodeServiceChangeNotifierProvider
.select((value) => value.getNodesFor(coin)));
final nodesForCoin = ref.watch(
nodeServiceChangeNotifierProvider
.select((value) => value.getNodesFor(coin)),
);
final canDelete = nodesForCoin.length > 1;
@ -256,7 +97,7 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
FocusScope.of(context).unfocus();
await Future<void>.delayed(const Duration(milliseconds: 75));
}
if (mounted) {
if (context.mounted) {
Navigator.of(context).pop();
}
},
@ -350,7 +191,7 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
Text(
"Node details",
style: STextStyles.desktopH3(context),
)
),
],
),
Padding(
@ -420,7 +261,52 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
label: "Test connection",
buttonHeight: isDesktop ? ButtonHeight.l : null,
onPressed: () async {
await _testConnection(ref, context);
final node = ref
.read(nodeServiceChangeNotifierProvider)
.getNodeById(id: nodeId)!;
final nodeFormData = NodeFormData()
..useSSL = node.useSSL
..trusted = node.trusted
..name = node.name
..host = node.host
..login = node.loginName
..port = node.port
..isFailover = node.isFailover;
nodeFormData.password = await node.getPassword(
ref.read(secureStoreProvider),
);
if (context.mounted) {
final testPassed = await testNodeConnection(
context: context,
nodeFormData: nodeFormData,
cryptoCurrency: coin,
ref: ref,
);
if (testPassed) {
if (context.mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.success,
message: "Server ping success",
context: context,
),
);
}
} else {
if (context.mounted) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Server unreachable",
context: context,
),
);
}
}
}
},
),
),

View file

@ -33,9 +33,8 @@ import 'package:stackwallet/services/trade_notes_service.dart';
import 'package:stackwallet/services/trade_sent_from_stack_service.dart';
import 'package:stackwallet/services/trade_service.dart';
import 'package:stackwallet/services/wallets.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/supported_coins.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/stack_restoring_status.dart';
import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
@ -43,6 +42,8 @@ import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/frost_currency.dart';
import 'package:stackwallet/wallets/isar/models/frost_wallet_info.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
import 'package:stackwallet/wallets/wallet/impl/bitcoin_frost_wallet.dart';
@ -80,7 +81,9 @@ String getErrorMessageFromSWBException(Exception e) {
String createAutoBackupFilename(String dirPath, DateTime date) {
// this filename structure is important. DO NOT CHANGE
return "$dirPath/stackautobackup_${date.year}_${date.month}_${date.day}_${date.hour}_${date.minute}_${date.second}.swb";
return "$dirPath/stackautobackup_"
"${date.year}_${date.month}_${date.day}_${date.hour}"
"_${date.minute}_${date.second}.swb";
}
abstract class SWB {
@ -95,8 +98,9 @@ abstract class SWB {
.log("SWB cancel restore requested", level: LogLevel.Info);
} else {
Logging.instance.log(
"SWB cancel restore requested while a cancellation request is currently in progress",
level: LogLevel.Warning);
"SWB cancel restore requested while a cancellation request is currently in progress",
level: LogLevel.Warning,
);
}
// return completer that will complete on SWBRestoreCancelEventType.completed event
@ -129,11 +133,11 @@ abstract class SWB {
String plaintext,
) async {
try {
File backupFile = File(fileToSave);
final File backupFile = File(fileToSave);
if (!backupFile.existsSync()) {
String jsonBackup = plaintext;
Uint8List content = Uint8List.fromList(utf8.encode(jsonBackup));
Uint8List encryptedContent =
final String jsonBackup = plaintext;
final Uint8List content = Uint8List.fromList(utf8.encode(jsonBackup));
final Uint8List encryptedContent =
await encryptWithPassphrase(passphrase, content);
backupFile
.writeAsStringSync(Format.uint8listToString(encryptedContent));
@ -153,13 +157,15 @@ abstract class SWB {
int adkVersion,
) async {
try {
File backupFile = File(fileToSave);
final File backupFile = File(fileToSave);
if (!backupFile.existsSync()) {
String jsonBackup = plaintext;
Uint8List content = Uint8List.fromList(utf8.encode(jsonBackup));
Uint8List encryptedContent = await encryptWithAdk(
Format.stringToUint8List(adk), content,
version: adkVersion);
final String jsonBackup = plaintext;
final Uint8List content = Uint8List.fromList(utf8.encode(jsonBackup));
final Uint8List encryptedContent = await encryptWithAdk(
Format.stringToUint8List(adk),
content,
version: adkVersion,
);
backupFile
.writeAsStringSync(Format.uint8listToString(encryptedContent));
}
@ -175,10 +181,10 @@ abstract class SWB {
Tuple2<String, String> data,
) async {
try {
String fileToRestore = data.item1;
String passphrase = data.item2;
File backupFile = File(fileToRestore);
String encryptedText = await backupFile.readAsString();
final String fileToRestore = data.item1;
final String passphrase = data.item2;
final File backupFile = File(fileToRestore);
final String encryptedText = await backupFile.readAsString();
return await decryptStackWalletStringWithPassphrase(
Tuple2(encryptedText, passphrase),
);
@ -192,15 +198,15 @@ abstract class SWB {
Tuple2<String, String> data,
) async {
try {
String encryptedText = data.item1;
String passphrase = data.item2;
final encryptedText = data.item1;
final passphrase = data.item2;
final Uint8List encryptedBytes = Format.stringToUint8List(encryptedText);
final encryptedBytes = Format.stringToUint8List(encryptedText);
Uint8List decryptedContent =
final decryptedContent =
await decryptWithPassphrase(passphrase, encryptedBytes);
final String jsonBackup = utf8.decode(decryptedContent);
final jsonBackup = utf8.decode(decryptedContent);
return jsonBackup;
} catch (e, s) {
Logging.instance.log("$e\n$s", level: LogLevel.Error);
@ -215,24 +221,27 @@ abstract class SWB {
Logging.instance
.log("Starting createStackWalletJSON...", level: LogLevel.Info);
final _wallets = Wallets.sharedInstance;
Map<String, dynamic> backupJson = {};
NodeService nodeService =
final Map<String, dynamic> backupJson = {};
final NodeService nodeService =
NodeService(secureStorageInterface: secureStorage);
final _secureStore = secureStorage;
Logging.instance.log("createStackWalletJSON awaiting DB.instance.mutex...",
level: LogLevel.Info);
Logging.instance.log(
"createStackWalletJSON awaiting DB.instance.mutex...",
level: LogLevel.Info,
);
// prevent modification of data
await DB.instance.mutex.protect(() async {
Logging.instance.log(
"...createStackWalletJSON DB.instance.mutex acquired",
level: LogLevel.Info);
"...createStackWalletJSON DB.instance.mutex acquired",
level: LogLevel.Info,
);
Logging.instance.log(
"SWB backing up nodes",
level: LogLevel.Warning,
);
try {
var primaryNodes = nodeService.primaryNodes.map((e) async {
final primaryNodes = nodeService.primaryNodes.map((e) async {
final map = e.toMap();
map["password"] = await e.getPassword(_secureStore);
return map;
@ -258,7 +267,7 @@ abstract class SWB {
level: LogLevel.Warning,
);
Map<String, dynamic> prefs = {};
final Map<String, dynamic> prefs = {};
final _prefs = Prefs.instance;
await _prefs.init();
prefs['currency'] = _prefs.currency;
@ -282,8 +291,8 @@ abstract class SWB {
level: LogLevel.Warning,
);
AddressBookService addressBookService = AddressBookService();
var addresses = addressBookService.contacts;
final AddressBookService addressBookService = AddressBookService();
final addresses = addressBookService.contacts;
backupJson['addressBookEntries'] =
addresses.map((e) => e.toMap()).toList();
@ -292,9 +301,9 @@ abstract class SWB {
level: LogLevel.Warning,
);
List<dynamic> backupWallets = [];
for (var wallet in _wallets.wallets) {
Map<String, dynamic> backupWallet = {};
final List<dynamic> backupWallets = [];
for (final wallet in _wallets.wallets) {
final Map<String, dynamic> backupWallet = {};
backupWallet['name'] = wallet.info.name;
backupWallet['id'] = wallet.walletId;
backupWallet['isFavorite'] = wallet.info.isFavourite;
@ -307,10 +316,11 @@ abstract class SWB {
} else if (wallet is PrivateKeyInterface) {
backupWallet['privateKey'] = await wallet.getPrivateKey();
} else if (wallet is BitcoinFrostWallet) {
String? keys = await wallet.getSerializedKeys();
String? config = await wallet.getMultisigConfig();
final String? keys = await wallet.getSerializedKeys();
final String? config = await wallet.getMultisigConfig();
if (keys == null || config == null) {
String err = "${wallet.info.coin.name} wallet ${wallet.info.name} "
final String err =
"${wallet.info.coin.identifier} wallet ${wallet.info.name} "
"has null keys or config";
Logging.instance.log(err, level: LogLevel.Fatal);
throw Exception(err);
@ -320,12 +330,12 @@ abstract class SWB {
// TODO [prio=low]: solve case in which either keys or config is null.
// Format keys & config as a JSON string and set otherDataJsonString.
Map<String, dynamic> frostData = {};
final Map<String, dynamic> frostData = {};
frostData["keys"] = keys;
frostData["config"] = config;
backupWallet['frostWalletData'] = jsonEncode(frostData);
}
backupWallet['coinName'] = wallet.info.coin.name;
backupWallet['coinName'] = wallet.info.coin.identifier;
backupWallet['storedChainHeight'] = wallet.info.cachedChainHeight;
// backupWallet['txidList'] = DB.instance.get<dynamic>(
@ -377,8 +387,10 @@ abstract class SWB {
final tradeNotes = tradeNotesService.all;
backupJson["tradeNotes"] = tradeNotes;
});
Logging.instance.log("createStackWalletJSON DB.instance.mutex released",
level: LogLevel.Info);
Logging.instance.log(
"createStackWalletJSON DB.instance.mutex released",
level: LogLevel.Info,
);
// // back up notifications data
// final notificationsService = NotificationsService();
@ -411,9 +423,10 @@ abstract class SWB {
}
} else {
if (walletbackup['mnemonic'] is List) {
List<String> mnemonicList = (walletbackup['mnemonic'] as List<dynamic>)
.map<String>((e) => e as String)
.toList();
final List<String> mnemonicList =
(walletbackup['mnemonic'] as List<dynamic>)
.map<String>((e) => e as String)
.toList();
mnemonic = mnemonicList.join(" ").trim();
} else {
mnemonic = walletbackup['mnemonic'] as String;
@ -432,7 +445,7 @@ abstract class SWB {
try {
String? serializedKeys;
String? multisigConfig;
if (info.coin.isFrost) {
if (info.coin is FrostCurrency) {
// Decode info.otherDataJsonString for Frost recovery info.
final frostData = jsonDecode(walletbackup["frostWalletData"] as String);
serializedKeys = frostData["keys"] as String;
@ -544,8 +557,9 @@ abstract class SWB {
await restoringFuture;
Logging.instance.log(
"SWB restored: ${info.walletId} ${info.name} ${info.coin.prettyName}",
level: LogLevel.Info);
"SWB restored: ${info.walletId} ${info.name} ${info.coin.prettyName}",
level: LogLevel.Info,
);
final currentAddress = await wallet.getCurrentReceivingAddress();
uiState?.update(
@ -576,15 +590,16 @@ abstract class SWB {
Map<String, String> oldToNewWalletIdMap,
SecureStorageInterface secureStorageInterface,
) async {
Map<String, dynamic> prefs = validJSON["prefs"] as Map<String, dynamic>;
List<dynamic>? addressBookEntries =
final Map<String, dynamic> prefs =
validJSON["prefs"] as Map<String, dynamic>;
final List<dynamic>? addressBookEntries =
validJSON["addressBookEntries"] as List?;
List<dynamic>? primaryNodes = validJSON["primaryNodes"] as List?;
List<dynamic>? nodes = validJSON["nodes"] as List?;
List<dynamic>? trades = validJSON["tradeHistory"] as List?;
List<dynamic>? tradeTxidLookupData =
final List<dynamic>? primaryNodes = validJSON["primaryNodes"] as List?;
final List<dynamic>? nodes = validJSON["nodes"] as List?;
final List<dynamic>? trades = validJSON["tradeHistory"] as List?;
final List<dynamic>? tradeTxidLookupData =
validJSON["tradeTxidLookupData"] as List?;
Map<String, dynamic>? tradeNotes =
final Map<String, dynamic>? tradeNotes =
validJSON["tradeNotes"] as Map<String, dynamic>?;
uiState?.preferences = StackRestoringStatus.restoring;
@ -689,7 +704,7 @@ abstract class SWB {
level: LogLevel.Warning,
);
List<String> _currentWalletIds = await MainDB.instance.isar.walletInfo
final List<String> _currentWalletIds = await MainDB.instance.isar.walletInfo
.where()
.walletIdProperty()
.findAll();
@ -697,12 +712,12 @@ abstract class SWB {
final preRestoreState =
PreRestoreState(_currentWalletIds.toSet(), preRestoreJSON);
Map<String, String> oldToNewWalletIdMap = {};
final Map<String, String> oldToNewWalletIdMap = {};
Map<String, dynamic> validJSON =
final Map<String, dynamic> validJSON =
json.decode(jsonBackup) as Map<String, dynamic>;
List<dynamic> wallets = validJSON["wallets"] as List;
final List<dynamic> wallets = validJSON["wallets"] as List;
// check for duplicate walletIds and assign new ones if required
for (final wallet in wallets) {
@ -748,9 +763,9 @@ abstract class SWB {
final List<Tuple2<dynamic, WalletInfo>> managers = [];
Map<String, WalletRestoreState> walletStates = {};
final Map<String, WalletRestoreState> walletStates = {};
for (var walletbackup in wallets) {
for (final walletbackup in wallets) {
// check if cancel was requested and restore previous state
if (_checkShouldCancel(
preRestoreState,
@ -759,8 +774,10 @@ abstract class SWB {
return false;
}
final coin = Coin.values
.firstWhere((element) => element.name == walletbackup['coinName']);
final coin = SupportedCoins.getCryptoCurrencyFor(
walletbackup['coinName'] as String,
);
final walletName = walletbackup['name'] as String;
final walletId = oldToNewWalletIdMap[walletbackup["id"] as String]!;
@ -781,7 +798,7 @@ abstract class SWB {
);
}
if (coin == Coin.firo) {
if (coin is Firo) {
otherData ??= {};
// swb will do a restore so this flag should be set to false so another
// rescan/restore isn't done when opening the wallet
@ -789,7 +806,7 @@ abstract class SWB {
}
final info = WalletInfo(
coinName: coin.name,
coinName: coin.identifier,
walletId: walletId,
name: walletName,
mainAddressType: coin.primaryAddressType,
@ -798,10 +815,10 @@ abstract class SWB {
cachedChainHeight: walletbackup['storedChainHeight'] as int? ?? 0,
);
var node = nodeService.getPrimaryNodeFor(coin: coin);
var node = nodeService.getPrimaryNodeFor(currency: coin);
if (node == null) {
node = DefaultNodes.getNodeFor(coin);
node = coin.defaultNode;
await nodeService.setPrimaryNodeFor(coin: coin, node: node);
}
@ -845,7 +862,7 @@ abstract class SWB {
// set the states so the ui can display each status as they update during restores
uiState?.walletStates = walletStates;
List<Future<bool>> restoreStatuses = [];
final List<Future<bool>> restoreStatuses = [];
// start restoring wallets
for (final tuple in managers) {
// check if cancel was requested and restore previous state
@ -873,7 +890,7 @@ abstract class SWB {
return false;
}
for (Future<bool> status in restoreStatuses) {
for (final Future<bool> status in restoreStatuses) {
// check if cancel was requested and restore previous state
if (_checkShouldCancel(
preRestoreState,
@ -905,17 +922,18 @@ abstract class SWB {
PreRestoreState revertToState,
SecureStorageInterface secureStorageInterface,
) async {
Map<String, dynamic> prefs =
final Map<String, dynamic> prefs =
revertToState.validJSON["prefs"] as Map<String, dynamic>;
List<dynamic>? addressBookEntries =
final List<dynamic>? addressBookEntries =
revertToState.validJSON["addressBookEntries"] as List?;
List<dynamic>? primaryNodes =
final List<dynamic>? primaryNodes =
revertToState.validJSON["primaryNodes"] as List?;
List<dynamic>? nodes = revertToState.validJSON["nodes"] as List?;
List<dynamic>? trades = revertToState.validJSON["tradeHistory"] as List?;
List<dynamic>? tradeTxidLookupData =
final List<dynamic>? nodes = revertToState.validJSON["nodes"] as List?;
final List<dynamic>? trades =
revertToState.validJSON["tradeHistory"] as List?;
final List<dynamic>? tradeTxidLookupData =
revertToState.validJSON["tradeTxidLookupData"] as List?;
Map<String, dynamic>? tradeNotes =
final Map<String, dynamic>? tradeNotes =
revertToState.validJSON["tradeNotes"] as Map<String, dynamic>?;
// prefs
@ -971,7 +989,7 @@ abstract class SWB {
}
// nodes
NodeService nodeService = NodeService(
final NodeService nodeService = NodeService(
secureStorageInterface: secureStorageInterface,
);
final currentNodes = nodeService.nodes;
@ -1015,10 +1033,12 @@ abstract class SWB {
// primary nodes
if (primaryNodes != null) {
for (var node in primaryNodes) {
for (final node in primaryNodes) {
try {
await nodeService.setPrimaryNodeFor(
coin: coinFromPrettyName(node['coinName'] as String),
coin: SupportedCoins.getCryptoCurrencyByPrettyName(
node['coinName'] as String,
),
node: nodeService.getNodeById(id: node['id'] as String)!,
);
} catch (e, s) {
@ -1050,12 +1070,15 @@ abstract class SWB {
// trade existed before attempted restore so we don't delete it, only
// revert data to pre restore state
await tradesService.edit(
trade: Trade.fromMap(tradeData as Map<String, dynamic>),
shouldNotifyListeners: true);
trade: Trade.fromMap(tradeData as Map<String, dynamic>),
shouldNotifyListeners: true,
);
} else {
// trade did not exist before so we delete it
await tradesService.delete(
trade: tradeTx, shouldNotifyListeners: true);
trade: tradeTx,
shouldNotifyListeners: true,
);
}
}
}
@ -1093,7 +1116,7 @@ abstract class SWB {
if (tradeTxidLookupData != null) {
for (int i = 0; i < tradeTxidLookupData.length; i++) {
final json = Map<String, dynamic>.from(tradeTxidLookupData[i] as Map);
TradeWalletLookup lookup = TradeWalletLookup.fromJson(json);
final TradeWalletLookup lookup = TradeWalletLookup.fromJson(json);
await tradeTxidLookupDataService.save(tradeWalletLookup: lookup);
}
}
@ -1137,8 +1160,9 @@ abstract class SWB {
_prefs.isAutoBackupEnabled = prefs['isAutoBackupEnabled'] as bool;
_prefs.autoBackupLocation = prefs['autoBackupLocation'] as String?;
_prefs.backupFrequencyType = BackupFrequencyType.values.firstWhere(
(e) => e.name == (prefs['backupFrequencyType'] as String?),
orElse: () => BackupFrequencyType.everyAppStart);
(e) => e.name == (prefs['backupFrequencyType'] as String?),
orElse: () => BackupFrequencyType.everyAppStart,
);
_prefs.lastAutoBackup =
DateTime.tryParse(prefs['lastAutoBackup'] as String? ?? "");
}
@ -1146,10 +1170,10 @@ abstract class SWB {
static Future<void> _restoreAddressBook(
List<dynamic> addressBookEntries,
) async {
AddressBookService addressBookService = AddressBookService();
for (var contact in addressBookEntries) {
List<ContactAddressEntry> addresses = [];
for (var address in (contact['addresses'] as List<dynamic>)) {
final AddressBookService addressBookService = AddressBookService();
for (final contact in addressBookEntries) {
final List<ContactAddressEntry> addresses = [];
for (final address in (contact['addresses'] as List<dynamic>)) {
addresses.add(
ContactAddressEntry()
..coinName = address['coin'] as String
@ -1175,11 +1199,11 @@ abstract class SWB {
List<dynamic>? primaryNodes,
SecureStorageInterface secureStorageInterface,
) async {
NodeService nodeService = NodeService(
final NodeService nodeService = NodeService(
secureStorageInterface: secureStorageInterface,
);
if (nodes != null) {
for (var node in nodes) {
for (final node in nodes) {
await nodeService.add(
NodeModel(
host: node['host'] as String,
@ -1199,10 +1223,12 @@ abstract class SWB {
}
}
if (primaryNodes != null) {
for (var node in primaryNodes) {
for (final node in primaryNodes) {
try {
await nodeService.setPrimaryNodeFor(
coin: coinFromPrettyName(node['coinName'] as String),
coin: SupportedCoins.getCryptoCurrencyByPrettyName(
node['coinName'] as String,
),
node: nodeService.getNodeById(id: node['id'] as String)!,
);
} catch (e, s) {
@ -1272,16 +1298,18 @@ abstract class SWB {
final json = Map<String, dynamic>.from(tradeTxidLookupData[i] as Map);
TradeWalletLookup lookup = TradeWalletLookup.fromJson(json);
// update walletIds
List<String> walletIds =
final List<String> walletIds =
lookup.walletIds.map((e) => oldToNewWalletIdMap[e]!).toList();
lookup = lookup.copyWith(walletIds: walletIds);
final oldLookup = DB.instance.get<TradeWalletLookup>(
boxName: DB.boxNameTradeLookup, key: lookup.uuid);
boxName: DB.boxNameTradeLookup,
key: lookup.uuid,
);
if (oldLookup != null) {
if (oldLookup.txid == lookup.txid &&
oldLookup.tradeId == lookup.tradeId) {
List<String> mergedList = oldLookup.walletIds;
final List<String> mergedList = oldLookup.walletIds;
for (final id in lookup.walletIds) {
if (!mergedList.contains(id)) {
mergedList.add(id);
@ -1308,7 +1336,9 @@ abstract class SWB {
final tradeNotesService = TradeNotesService();
for (final note in tradeNotes.entries) {
await tradeNotesService.set(
tradeId: note.key, note: note.value as String);
tradeId: note.key,
note: note.value as String,
);
}
}
}

View file

@ -20,8 +20,8 @@ import 'package:stackwallet/providers/stack_restore/stack_restoring_ui_state_pro
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/stack_restoring_status.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
@ -89,9 +89,7 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
height: 32,
child: RoundedContainer(
padding: const EdgeInsets.all(0),
color: Theme.of(context)
.extension<StackColors>()!
.colorForCoin(coin),
color: ref.watch(pCoinColor(coin)),
child: Center(
child: SvgPicture.file(
File(
@ -212,9 +210,7 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
height: 32,
child: RoundedContainer(
padding: const EdgeInsets.all(0),
color: Theme.of(context)
.extension<StackColors>()!
.colorForCoin(coin),
color: ref.watch(pCoinColor(coin)),
child: Center(
child: SvgPicture.file(
File(
@ -239,7 +235,7 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
try {
// final mnemonicList = await manager.mnemonic;
// int maxUnusedAddressGap = 20;
// if (coin == Coin.firo) {
// if (coin is Firo) {
// maxUnusedAddressGap = 50;
// }
// const maxNumberOfIndexesToCheck = 1000;

View file

@ -16,6 +16,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
@ -63,165 +64,181 @@ class _StartupWalletSelectionViewState
),
),
),
body: LayoutBuilder(builder: (context, constraints) {
return Padding(
padding: const EdgeInsets.only(
left: 12,
top: 12,
right: 12,
),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight - 24,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 4,
),
Text(
"Select a wallet to load into immediately on startup",
style: STextStyles.smallMed12(context),
),
const SizedBox(
height: 12,
),
RoundedWhiteContainer(
padding: const EdgeInsets.all(0),
child: Column(
children: [
...wallets.map(
(wallet) => Padding(
padding: const EdgeInsets.all(12),
child: Row(
key: Key(
"startupWalletSelectionGroupKey_${wallet.walletId}"),
children: [
Container(
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.colorForCoin(
ref.watch(pWalletCoin(
wallet.walletId)),
)
.withOpacity(0.5),
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
body: LayoutBuilder(
builder: (context, constraints) {
return Padding(
padding: const EdgeInsets.only(
left: 12,
top: 12,
right: 12,
),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight - 24,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 4,
),
Text(
"Select a wallet to load into immediately on startup",
style: STextStyles.smallMed12(context),
),
const SizedBox(
height: 12,
),
RoundedWhiteContainer(
padding: const EdgeInsets.all(0),
child: Column(
children: [
...wallets.map(
(wallet) => Padding(
padding: const EdgeInsets.all(12),
child: Row(
key: Key(
"startupWalletSelectionGroupKey_${wallet.walletId}",
),
children: [
Container(
decoration: BoxDecoration(
color: ref
.watch(
pCoinColor(
ref.watch(
pWalletCoin(
wallet.walletId,
),
),
),
)
.withOpacity(0.5),
borderRadius: BorderRadius.circular(
Constants
.size.circularBorderRadius,
),
),
),
child: Padding(
padding: const EdgeInsets.all(4),
child: SvgPicture.file(
File(
ref.watch(
coinIconProvider(
ref.watch(pWalletCoin(
wallet.walletId)),
child: Padding(
padding: const EdgeInsets.all(4),
child: SvgPicture.file(
File(
ref.watch(
coinIconProvider(
ref.watch(
pWalletCoin(
wallet.walletId,
),
),
),
),
),
width: 20,
height: 20,
),
width: 20,
height: 20,
),
),
),
const SizedBox(
width: 12,
),
Expanded(
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
ref.watch(
pWalletName(wallet.walletId)),
style: STextStyles.titleBold12(
context),
),
// const SizedBox(
// height: 2,
// ),
// FutureBuilder(
// future: manager.totalBalance,
// builder: (builderContext,
// AsyncSnapshot<Decimal> snapshot) {
// if (snapshot.connectionState ==
// ConnectionState.done &&
// snapshot.hasData) {
// return Text(
// "${Format.localizedStringAsFixed(
// value: snapshot.data!,
// locale: ref.watch(
// localeServiceChangeNotifierProvider
// .select((value) =>
// value.locale)),
// decimalPlaces: 8,
// )} ${manager.coin.ticker}",
// style: STextStyles.itemSubtitle(context),
// );
// } else {
// return AnimatedText(
// stringsToLoopThrough: const [
// "Loading balance",
// "Loading balance.",
// "Loading balance..",
// "Loading balance..."
// ],
// style: STextStyles.itemSubtitle(context),
// );
// }
// },
// ),
],
const SizedBox(
width: 12,
),
),
SizedBox(
height: 20,
width: 20,
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: wallet.walletId,
groupValue: ref.watch(
prefsChangeNotifierProvider.select(
Expanded(
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
ref.watch(
pWalletName(wallet.walletId),
),
style: STextStyles.titleBold12(
context,
),
),
// const SizedBox(
// height: 2,
// ),
// FutureBuilder(
// future: manager.totalBalance,
// builder: (builderContext,
// AsyncSnapshot<Decimal> snapshot) {
// if (snapshot.connectionState ==
// ConnectionState.done &&
// snapshot.hasData) {
// return Text(
// "${Format.localizedStringAsFixed(
// value: snapshot.data!,
// locale: ref.watch(
// localeServiceChangeNotifierProvider
// .select((value) =>
// value.locale)),
// decimalPlaces: 8,
// )} ${manager.coin.ticker}",
// style: STextStyles.itemSubtitle(context),
// );
// } else {
// return AnimatedText(
// stringsToLoopThrough: const [
// "Loading balance",
// "Loading balance.",
// "Loading balance..",
// "Loading balance..."
// ],
// style: STextStyles.itemSubtitle(context),
// );
// }
// },
// ),
],
),
),
SizedBox(
height: 20,
width: 20,
child: Radio(
activeColor: Theme.of(context)
.extension<StackColors>()!
.radioButtonIconEnabled,
value: wallet.walletId,
groupValue: ref.watch(
prefsChangeNotifierProvider
.select(
(value) =>
value.startupWalletId),
value.startupWalletId,
),
),
onChanged: (value) {
if (value is String) {
ref
.read(
prefsChangeNotifierProvider,
)
.startupWalletId = value;
}
},
),
onChanged: (value) {
if (value is String) {
ref
.read(
prefsChangeNotifierProvider)
.startupWalletId = value;
}
},
),
),
],
],
),
),
),
),
],
],
),
),
),
],
],
),
),
),
),
),
),
);
}),
);
},
),
),
);
}

View file

@ -16,6 +16,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/themes/theme_providers.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -117,9 +118,8 @@ class WalletSyncingOptionsView extends ConsumerWidget {
children: [
Container(
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.colorForCoin(info.coin)
color: ref
.watch(pCoinColor(info.coin))
.withOpacity(0.5),
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,

View file

@ -11,39 +11,39 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/global/node_service_provider.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/widgets/node_card.dart';
class NodesList extends ConsumerWidget {
const NodesList({
Key? key,
super.key,
required this.coin,
required this.popBackToRoute,
}) : super(key: key);
});
final Coin coin;
final CryptoCurrency coin;
final String popBackToRoute;
@override
Widget build(BuildContext context, WidgetRef ref) {
final nodes = ref.watch(nodeServiceChangeNotifierProvider
.select((value) => value.getNodesFor(coin)));
final nodes = ref.watch(
nodeServiceChangeNotifierProvider
.select((value) => value.getNodesFor(coin)),
);
return Column(
children: [
...nodes
.map(
(node) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: NodeCard(
key: Key("${node.id}_card_key"),
nodeId: node.id,
coin: coin,
popBackToRoute: popBackToRoute,
),
),
)
.toList(),
...nodes.map(
(node) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: NodeCard(
key: Key("${node.id}_card_key"),
nodeId: node.id,
coin: coin,
popBackToRoute: popBackToRoute,
),
),
),
],
);
}

View file

@ -32,9 +32,11 @@ import 'package:stackwallet/services/tor_service.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/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/epiccash.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/monero.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/wownero.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
import 'package:stackwallet/wallets/wallet/impl/monero_wallet.dart';
@ -57,12 +59,12 @@ import 'package:wakelock/wakelock.dart';
/// [eventBus] should only be set during testing
class WalletNetworkSettingsView extends ConsumerStatefulWidget {
const WalletNetworkSettingsView({
Key? key,
super.key,
required this.walletId,
required this.initialSyncStatus,
required this.initialNodeStatus,
this.eventBus,
}) : super(key: key);
});
final String walletId;
final WalletSyncStatus initialSyncStatus;
@ -260,7 +262,7 @@ class _WalletNetworkSettingsViewState
final coin = ref.read(pWalletCoin(widget.walletId));
if (coin == Coin.monero || coin == Coin.wownero || coin == Coin.epicCash) {
if (coin is Monero || coin is Wownero || coin is Epiccash) {
_blocksRemainingSubscription = eventBus.on<BlocksRemainingEvent>().listen(
(event) async {
if (event.walletId == widget.walletId) {
@ -319,22 +321,22 @@ class _WalletNetworkSettingsViewState
final coin = ref.watch(pWalletCoin(widget.walletId));
if (coin == Coin.monero) {
double highestPercent =
if (coin is Monero) {
final double highestPercent =
(ref.read(pWallets).getWallet(widget.walletId) as MoneroWallet)
.highestPercentCached;
if (_percent < highestPercent) {
_percent = highestPercent.clamp(0.0, 1.0);
}
} else if (coin == Coin.wownero) {
double highestPercent =
} else if (coin is Wownero) {
final double highestPercent =
(ref.watch(pWallets).getWallet(widget.walletId) as WowneroWallet)
.highestPercentCached;
if (_percent < highestPercent) {
_percent = highestPercent.clamp(0.0, 1.0);
}
} else if (coin == Coin.epicCash) {
double highestPercent =
} else if (coin is Epiccash) {
final double highestPercent =
(ref.watch(pWallets).getWallet(widget.walletId) as EpiccashWallet)
.highestPercent;
if (_percent < highestPercent) {
@ -360,7 +362,7 @@ class _WalletNetworkSettingsViewState
style: STextStyles.navBarTitle(context),
),
actions: [
if (ref.watch(pWalletCoin(widget.walletId)) != Coin.epicCash)
if (ref.watch(pWalletCoin(widget.walletId)) is! Epiccash)
Padding(
padding: const EdgeInsets.only(
top: 10,
@ -371,7 +373,8 @@ class _WalletNetworkSettingsViewState
aspectRatio: 1,
child: AppBarIconButton(
key: const Key(
"walletNetworkSettingsAddNewNodeViewButton"),
"walletNetworkSettingsAddNewNodeViewButton",
),
size: 36,
shadows: const [],
color: Theme.of(context)
@ -402,8 +405,8 @@ class _WalletNetworkSettingsViewState
.extension<StackColors>()!
.popupBG,
borderRadius: BorderRadius.circular(
Constants
.size.circularBorderRadius),
Constants.size.circularBorderRadius,
),
// boxShadow: [CFColors.standardBoxShadow],
boxShadow: const [],
),
@ -431,7 +434,8 @@ class _WalletNetworkSettingsViewState
child: Text(
"Rescan blockchain",
style: STextStyles.baseXS(
context),
context,
),
),
),
),
@ -620,9 +624,9 @@ class _WalletNetworkSettingsViewState
.accentColorYellow,
),
),
if (coin == Coin.monero ||
coin == Coin.wownero ||
coin == Coin.epicCash)
if (coin is Monero ||
coin is Wownero ||
coin is Epiccash)
Text(
" (Blocks to go: ${_blocksRemaining == -1 ? "?" : _blocksRemaining})",
style: STextStyles.syncPercent(context)
@ -633,7 +637,7 @@ class _WalletNetworkSettingsViewState
),
),
],
)
),
],
),
),
@ -768,8 +772,9 @@ class _WalletNetworkSettingsViewState
: STextStyles.smallMed12(context),
),
CustomTextButton(
text: ref.watch(prefsChangeNotifierProvider
.select((value) => value.useTor))
text: ref.watch(
prefsChangeNotifierProvider.select((value) => value.useTor),
)
? "Disconnect"
: "Connect",
onTap: onTorTapped,
@ -787,8 +792,9 @@ class _WalletNetworkSettingsViewState
isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12),
child: Row(
children: [
if (ref.watch(prefsChangeNotifierProvider
.select((value) => value.useTor)))
if (ref.watch(
prefsChangeNotifierProvider.select((value) => value.useTor),
))
Container(
width: _iconSize,
height: _iconSize,
@ -810,8 +816,9 @@ class _WalletNetworkSettingsViewState
),
),
),
if (!ref.watch(prefsChangeNotifierProvider
.select((value) => value.useTor)))
if (!ref.watch(
prefsChangeNotifierProvider.select((value) => value.useTor),
))
Container(
width: _iconSize,
height: _iconSize,
@ -916,13 +923,11 @@ class _WalletNetworkSettingsViewState
coin: ref.watch(pWalletCoin(widget.walletId)),
popBackToRoute: WalletNetworkSettingsView.routeName,
),
if (isDesktop &&
ref.watch(pWalletCoin(widget.walletId)) != Coin.epicCash)
if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash)
const SizedBox(
height: 32,
),
if (isDesktop &&
ref.watch(pWalletCoin(widget.walletId)) != Coin.epicCash)
if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash)
Padding(
padding: const EdgeInsets.only(
bottom: 12,
@ -938,8 +943,7 @@ class _WalletNetworkSettingsViewState
],
),
),
if (isDesktop &&
ref.watch(pWalletCoin(widget.walletId)) != Coin.epicCash)
if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash)
RoundedWhiteContainer(
borderColor: isDesktop
? Theme.of(context).extension<StackColors>()!.background
@ -987,8 +991,8 @@ class _WalletNetworkSettingsViewState
Text(
"Advanced",
style: STextStyles.desktopTextExtraExtraSmall(
context)
.copyWith(
context,
).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
@ -997,10 +1001,11 @@ class _WalletNetworkSettingsViewState
Text(
"Rescan blockchain",
style: STextStyles.desktopTextExtraExtraSmall(
context),
context,
),
),
],
)
),
],
),
SvgPicture.asset(

View file

@ -36,10 +36,13 @@ import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/frost_currency.dart';
import 'package:stackwallet/wallets/crypto_currency/intermediate/nano_currency.dart';
import 'package:stackwallet/wallets/wallet/impl/bitcoin_frost_wallet.dart';
import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
@ -64,7 +67,7 @@ class WalletSettingsView extends ConsumerStatefulWidget {
static const String routeName = "/walletSettings";
final String walletId;
final Coin coin;
final CryptoCurrency coin;
final WalletSyncStatus initialSyncStatus;
final NodeConnectionStatus initialNodeStatus;
final EventBus? eventBus;
@ -75,7 +78,7 @@ class WalletSettingsView extends ConsumerStatefulWidget {
class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
late final String walletId;
late final Coin coin;
late final CryptoCurrency coin;
late String xpub;
late final bool xPubEnabled;
@ -206,11 +209,11 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
);
},
),
if (coin.isFrost)
if (coin is FrostCurrency)
const SizedBox(
height: 8,
),
if (coin.isFrost)
if (coin is FrostCurrency)
SettingsListButton(
iconAssetName: Assets.svg.addressBook2,
iconSize: 16,
@ -376,11 +379,11 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
);
},
),
if (coin == Coin.firo)
if (coin is Firo)
const SizedBox(
height: 8,
),
if (coin == Coin.firo)
if (coin is Firo)
Consumer(
builder: (_, ref, __) {
return SettingsListButton(
@ -419,7 +422,7 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
),
DB.instance
.clearSharedTransactionCache(
coin: coin,
currency: coin,
),
],
),
@ -431,11 +434,11 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
);
},
),
if (coin == Coin.nano || coin == Coin.banano)
if (coin is NanoCurrency)
const SizedBox(
height: 8,
),
if (coin == Coin.nano || coin == Coin.banano)
if (coin is NanoCurrency)
Consumer(
builder: (_, ref, __) {
return SettingsListButton(

View file

@ -21,10 +21,11 @@ import 'package:stackwallet/services/ethereum/cached_eth_token_balance.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/ethereum.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
import 'package:stackwallet/wallets/isar/providers/eth/token_balance_provider.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
@ -178,7 +179,10 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
),
const Spacer(),
Text(
ref.watch(pAmountFormatter(Coin.ethereum)).format(
ref
.watch(pAmountFormatter(
Ethereum(CryptoCurrencyNetwork.main)))
.format(
ref
.watch(pTokenBalance(
(

Some files were not shown because too many files have changed in this diff Show more